diff --git a/misuzu.php b/misuzu.php index f7080a74..9dbbe30e 100644 --- a/misuzu.php +++ b/misuzu.php @@ -105,6 +105,8 @@ if(MSZ_CLI) { // Temporary backwards compatibility measure, remove this later return; } +$ctx = new MszContext; + // Everything below here should eventually be moved to index.php, probably only initialised when required. // Serving things like the css/js doesn't need to initialise sessions. diff --git a/public/index.php b/public/index.php index 8c55f089..212d2590 100644 --- a/public/index.php +++ b/public/index.php @@ -1,105 +1,9 @@ {$method}(...$args); - }; -} +$request = \Index\Http\HttpRequest::fromRequest(); -function msz_compat_redirect(string $target) { - return function($response) use ($target) { - $response->redirect($target, true); - }; -} - -$router = new HttpFx; -$router->use('/', function($response) { - $response->setPoweredBy('Misuzu'); -}); - -$router->addErrorHandler(400, function($response) { - $response->setContent(Template::renderRaw('errors.400')); -}); -$router->addErrorHandler(403, function($response) { - $response->setContent(Template::renderRaw('errors.403')); -}); -$router->addErrorHandler(404, function($response) { - $response->setContent(Template::renderRaw('errors.404')); -}); -$router->addErrorHandler(500, function($response) { - $response->setContent(file_get_contents(MSZ_TEMPLATES . '/500.html')); -}); -$router->addErrorHandler(503, function($response) { - $response->setContent(file_get_contents(MSZ_TEMPLATES . '/503.html')); -}); - -$request = HttpRequest::fromRequest(); - -if(strpos($request->getPath(), '.php') !== false) { - $router->get('/index.php', msz_compat_redirect(url('index'))); - $router->get('/info.php', msz_compat_redirect(url('info'))); - $router->get('/settings.php', msz_compat_redirect(url('settings-index'))); - $router->get('/changelog.php', msz_compat_handler('Changelog', 'legacy')); - $router->get('/info.php/:name', msz_compat_handler('Info', 'redir')); - $router->get('/auth.php', msz_compat_handler('Auth', 'legacy')); - $router->get('/news.php', msz_compat_handler('News', 'legacy')); - $router->get('/news.php/rss', msz_compat_handler('News', 'legacy')); - $router->get('/news.php/atom', msz_compat_handler('News', 'legacy')); - $router->get('/news/index.php', msz_compat_handler('News', 'legacy')); - $router->get('/news/category.php', msz_compat_handler('News', 'legacy')); - $router->get('/news/post.php', msz_compat_handler('News', 'legacy')); - $router->get('/news/feed.php', msz_compat_handler('News', 'legacy')); - $router->get('/news/feed.php/rss', msz_compat_handler('News', 'legacy')); - $router->get('/news/feed.php/atom', msz_compat_handler('News', 'legacy')); - $router->get('/user-assets.php', msz_compat_handler('Assets', 'serveLegacy')); - $router->get('/_sockchat.php', msz_compat_handler('SockChat', 'phpFile')); - $router->post('/_sockchat.php', msz_compat_handler('SockChat', 'phpFile')); -} else { - $router->get('/', msz_compat_handler('Home', 'index')); - - $router->get('/assets/:filename', msz_compat_handler('Assets', 'serveComponent')); - $router->get('/assets/avatar/:filename', msz_compat_handler('Assets', 'serveAvatar')); - $router->get('/assets/profile-background/:filename', msz_compat_handler('Assets', 'serveProfileBackground')); - - $router->get('/info', msz_compat_handler('Info', 'index')); - $router->get('/info/:name', msz_compat_handler('Info', 'page')); - $router->get('/info/:project/:name', msz_compat_handler('Info', 'page')); - - $router->get('/changelog', msz_compat_handler('Changelog', 'index')); - $router->get('/changelog.rss', msz_compat_handler('Changelog', 'feedRss')); - $router->get('/changelog.atom', msz_compat_handler('Changelog', 'feedAtom')); - $router->get('/changelog/change/:id', msz_compat_handler('Changelog', 'change')); - - $router->get('/news', msz_compat_handler('News', 'index')); - $router->get('/news.rss', msz_compat_handler('News', 'feedIndexRss')); - $router->get('/news.atom', msz_compat_handler('News', 'feedIndexAtom')); - $router->get('/news/:category', msz_compat_handler('News', 'viewCategory')); - $router->get('/news/post/:id', msz_compat_handler('News', 'viewPost')); - - $router->get('/forum/mark-as-read', msz_compat_handler('Forum', 'markAsReadGET')); - $router->post('/forum/mark-as-read', msz_compat_handler('Forum', 'markAsReadPOST')); - - $router->get('/_sockchat/emotes', msz_compat_handler('SockChat', 'emotes')); - $router->get('/_sockchat/login', msz_compat_handler('SockChat', 'login')); - $router->get('/_sockchat/resolve', msz_compat_handler('SockChat', 'resolve')); - $router->post('/_sockchat/bump', msz_compat_handler('SockChat', 'bump')); - $router->post('/_sockchat/verify', msz_compat_handler('SockChat', 'verify')); - $router->get('/_sockchat/token', msz_compat_handler('SockChat', 'token')); - $router->options('/_sockchat/token', msz_compat_handler('SockChat', 'token')); - $router->get('/_sockchat/profile-check', msz_compat_handler('SockChat', 'profileCheck')); - $router->options('/_sockchat/profile-check', msz_compat_handler('SockChat', 'profileCheck')); - $router->get('/_sockchat/bans', msz_compat_handler('SockChat', 'bans')); - $router->get('/_sockchat/bans/check', msz_compat_handler('SockChat', 'checkBan')); - $router->post('/_sockchat/bans/create', msz_compat_handler('SockChat', 'createBan')); - $router->delete('/_sockchat/bans/remove', msz_compat_handler('SockChat', 'removeBan')); -} - -$router->dispatch($request); +$ctx->setUpHttp(str_contains($request->getPath(), '.php')); +$ctx->dispatchHttp($request); diff --git a/src/Http/Handlers/SockChatHandler.php b/src/Http/Handlers/SockChatHandler.php index fa9e6a95..27c624a5 100644 --- a/src/Http/Handlers/SockChatHandler.php +++ b/src/Http/Handlers/SockChatHandler.php @@ -55,66 +55,6 @@ final class SockChatHandler extends Handler { parent::__construct(); } - public function phpFile($response, $request) { - if($request->hasParam('emotes')) - return $this->emotes($response, $request); - - $reqb = new HttpRequestBuilder; - $reqb->setMethod($request->getMethod()); - $reqb->setPath($request->getPath()); - $reqb->setCookies($request->getCookies()); - - foreach($request->getHeaders() as $header) { - $name = $header->getName(); - foreach($header->getLines() as $line) - $reqb->addHeader($name, $line); - } - - if($request->hasParam('bans')) { - $reqb->setHeader('X-SharpChat-Signature', $request->getParam('bans')); - return $this->bans($response, $reqb->toRequest()); - } - - $isForm = $request->isFormContent(); - - if($isForm) { - $content = $request->getContent(); - - if($content->hasParam('bump') && $content->hasParam('hash')) { - $reqb->setHeader('X-SharpChat-Signature', $content->getParam('hash')); - $reqb->setContent($content->getParam('bump')); - $this->bump($response, $reqb->toRequest()); - return; - } - - if($content->hasParam('user_id') && $content->hasParam('token') - && $content->hasParam('ip') && $content->hasParam('hash')) { - $reqb->setHeader('X-SharpChat-Signature', $content->getParam('hash')); - $reqb->setContent(json_encode([ - 'user_id' => $content->getParam('user_id'), - 'token' => $content->getParam('token'), - 'ip' => $content->getParam('ip'), - ])); - - return $this->verify($response, $reqb->toRequest()); - } - } else { - if($request->hasParam('user_id') && $request->hasParam('token') - && $request->hasParam('ip') && $request->hasParam('hash')) { - $reqb->setHeader('X-SharpChat-Signature', $request->getParam('hash')); - $reqb->setContent(json_encode([ - 'user_id' => $request->getParam('user_id'), - 'token' => $request->getParam('token'), - 'ip' => $request->getParam('ip'), - ])); - - return $this->verify($response, $reqb->toRequest()); - } - } - - return $this->login($response, $request); - } - public static function calculatePermissions(User $userInfo): int { $perms = self::PERMS_DEFAULT; diff --git a/src/MszContext.php b/src/MszContext.php new file mode 100644 index 00000000..002c7ab5 --- /dev/null +++ b/src/MszContext.php @@ -0,0 +1,208 @@ +router = new HttpFx; + $this->router->use('/', function($response) { + $response->setPoweredBy('Misuzu'); + }); + + $this->registerErrorPages(); + + if($legacy) + $this->registerLegacyRedirects(); + else + $this->registerHttpRoutes(); + } + + public function dispatchHttp(?HttpRequest $request = null): void { + $this->router->dispatch($request); + } + + private function registerErrorPages(): void { + $this->router->addErrorHandler(400, function($response) { + $response->setContent(Template::renderRaw('errors.400')); + }); + $this->router->addErrorHandler(403, function($response) { + $response->setContent(Template::renderRaw('errors.403')); + }); + $this->router->addErrorHandler(404, function($response) { + $response->setContent(Template::renderRaw('errors.404')); + }); + $this->router->addErrorHandler(500, function($response) { + $response->setContent(file_get_contents(MSZ_TEMPLATES . '/500.html')); + }); + $this->router->addErrorHandler(503, function($response) { + $response->setContent(file_get_contents(MSZ_TEMPLATES . '/503.html')); + }); + } + + private function registerHttpRoutes(): void { + function msz_compat_handler(string $className, string $method) { + return function(...$args) use ($className, $method) { + $className = "\\Misuzu\\Http\\Handlers\\{$className}Handler"; + return (new $className)->{$method}(...$args); + }; + } + + $this->router->get('/', msz_compat_handler('Home', 'index')); + + $this->router->get('/assets/:filename', msz_compat_handler('Assets', 'serveComponent')); + $this->router->get('/assets/avatar/:filename', msz_compat_handler('Assets', 'serveAvatar')); + $this->router->get('/assets/profile-background/:filename', msz_compat_handler('Assets', 'serveProfileBackground')); + + $this->router->get('/info', msz_compat_handler('Info', 'index')); + $this->router->get('/info/:name', msz_compat_handler('Info', 'page')); + $this->router->get('/info/:project/:name', msz_compat_handler('Info', 'page')); + + $this->router->get('/changelog', msz_compat_handler('Changelog', 'index')); + $this->router->get('/changelog.rss', msz_compat_handler('Changelog', 'feedRss')); + $this->router->get('/changelog.atom', msz_compat_handler('Changelog', 'feedAtom')); + $this->router->get('/changelog/change/:id', msz_compat_handler('Changelog', 'change')); + + $this->router->get('/news', msz_compat_handler('News', 'index')); + $this->router->get('/news.rss', msz_compat_handler('News', 'feedIndexRss')); + $this->router->get('/news.atom', msz_compat_handler('News', 'feedIndexAtom')); + $this->router->get('/news/:category', msz_compat_handler('News', 'viewCategory')); + $this->router->get('/news/post/:id', msz_compat_handler('News', 'viewPost')); + + $this->router->get('/forum/mark-as-read', msz_compat_handler('Forum', 'markAsReadGET')); + $this->router->post('/forum/mark-as-read', msz_compat_handler('Forum', 'markAsReadPOST')); + + $this->router->get('/_sockchat/emotes', msz_compat_handler('SockChat', 'emotes')); + $this->router->get('/_sockchat/login', msz_compat_handler('SockChat', 'login')); + $this->router->get('/_sockchat/resolve', msz_compat_handler('SockChat', 'resolve')); + $this->router->post('/_sockchat/bump', msz_compat_handler('SockChat', 'bump')); + $this->router->post('/_sockchat/verify', msz_compat_handler('SockChat', 'verify')); + $this->router->get('/_sockchat/token', msz_compat_handler('SockChat', 'token')); + $this->router->options('/_sockchat/token', msz_compat_handler('SockChat', 'token')); + $this->router->get('/_sockchat/profile-check', msz_compat_handler('SockChat', 'profileCheck')); + $this->router->options('/_sockchat/profile-check', msz_compat_handler('SockChat', 'profileCheck')); + $this->router->get('/_sockchat/bans', msz_compat_handler('SockChat', 'bans')); + $this->router->get('/_sockchat/bans/check', msz_compat_handler('SockChat', 'checkBan')); + $this->router->post('/_sockchat/bans/create', msz_compat_handler('SockChat', 'createBan')); + $this->router->delete('/_sockchat/bans/remove', msz_compat_handler('SockChat', 'removeBan')); + } + + private function registerLegacyRedirects(): void { + $this->router->get('/index.php', function($response) { + $response->redirect(url('index'), true); + }); + + $this->router->get('/info.php', function($response) { + $response->redirect(url('info'), true); + }); + + $this->router->get('/settings.php', function($response) { + $response->redirect(url('settings-index'), true); + }); + + $this->router->get('/changelog.php', function($response, $request) { + $changeId = $request->getParam('c', FILTER_SANITIZE_NUMBER_INT); + if($changeId) { + $response->redirect(url('changelog-change', ['change' => $changeId]), true); + return; + } + + $response->redirect(url('changelog-index', [ + 'date' => $request->getParam('d'), + 'user' => $request->getParam('u', FILTER_SANITIZE_NUMBER_INT), + ]), true); + }); + + $infoRedirect = function($response, $request, string ...$parts) { + $response->redirect(url('info', ['title' => implode('/', $parts)]), true); + }; + $this->router->get('/info.php/:name', $infoRedirect); + $this->router->get('/info.php/:project/:name', $infoRedirect); + + $this->router->get('/auth.php', function($response, $request) { + $response->redirect(url([ + 'logout' => 'auth-logout', + 'reset' => 'auth-reset', + 'forgot' => 'auth-forgot', + 'register' => 'auth-register', + ][$request->getParam('m')] ?? 'auth-login'), true); + }); + + $this->router->get('/news.php', function($response, $request) { + $postId = $request->getParam('n', FILTER_SANITIZE_NUMBER_INT) ?? $request->getParam('p', FILTER_SANITIZE_NUMBER_INT); + + if($postId > 0) + $location = url('news-post', ['post' => $postId]); + else { + $catId = $request->getParam('c', FILTER_SANITIZE_NUMBER_INT); + $pageId = $request->getParam('page', FILTER_SANITIZE_NUMBER_INT); + $location = url($catId > 0 ? 'news-category' : 'news-index', ['category' => $catId, 'page' => $pageId]); + } + + $response->redirect($location, true); + }); + + $this->router->get('/news.php/rss', function($response, $request) { + $catId = $request->getParam('c', FILTER_SANITIZE_NUMBER_INT); + $location = url($catId > 0 ? 'news-category-feed-rss' : 'news-feed-rss', ['category' => $catId]); + $response->redirect($location, true); + }); + + $this->router->get('/news.php/atom', function($response, $request) { + $catId = $request->getParam('c', FILTER_SANITIZE_NUMBER_INT); + $location = url($catId > 0 ? 'news-category-feed-atom' : 'news-feed-atom', ['category' => $catId]); + $response->redirect($location, true); + }); + + $this->router->get('/news/index.php', function($response) { + $response->redirect(url('news-index', [ + 'page' => $request->getParam('page', FILTER_SANITIZE_NUMBER_INT), + ]), true); + }); + + $this->router->get('/news/category.php', function($response, $request) { + $response->redirect(url('news-category', [ + 'category' => $request->getParam('c', FILTER_SANITIZE_NUMBER_INT), + 'page' => $request->getParam('p', FILTER_SANITIZE_NUMBER_INT), + ]), true); + }); + + $this->router->get('/news/post.php', function($response, $request) { + $response->redirect(url('news-post', [ + 'post' => $request->getParam('p', FILTER_SANITIZE_NUMBER_INT), + ]), true); + }); + + $this->router->get('/news/feed.php', function() { + return 400; + }); + + $this->router->get('/news/feed.php/rss', function($response, $request) { + $response->redirect(url( + $catId > 0 ? 'news-category-feed-rss' : 'news-feed-rss', + ['category' => $request->getParam('c', FILTER_SANITIZE_NUMBER_INT)] + ), true); + }); + + $this->router->get('/news/feed.php/atom', function($response, $request) { + $response->redirect(url( + $catId > 0 ? 'news-category-feed-atom' : 'news-feed-atom', + ['category' => $request->getParam('c', FILTER_SANITIZE_NUMBER_INT)] + ), true); + }); + + $this->router->get('/user-assets.php', function($response, $request) { + return (new \Misuzu\Http\Handlers\AssetsHandler)->serveLegacy($response, $request); + }); + } +}