diff --git a/composer.lock b/composer.lock index aeb7060..ecc7e7c 100644 --- a/composer.lock +++ b/composer.lock @@ -67,7 +67,7 @@ "source": { "type": "git", "url": "https://patchii.net/flash/index.git", - "reference": "73051dc71ee2d0045e5dbe5d846bb665a8b1c39c" + "reference": "9d5b050b8928435416a7efbebe2a19ae8e626224" }, "require": { "ext-mbstring": "*", @@ -105,7 +105,7 @@ ], "description": "Composer package for the common library for my projects.", "homepage": "https://railgun.sh/index", - "time": "2024-02-06T23:52:46+00:00" + "time": "2024-03-28T23:27:04+00:00" }, { "name": "flashwave/sasae", @@ -305,16 +305,16 @@ }, { "name": "jean85/pretty-package-versions", - "version": "2.0.5", + "version": "2.0.6", "source": { "type": "git", "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af" + "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/ae547e455a3d8babd07b96966b17d7fd21d9c6af", - "reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4", + "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4", "shasum": "" }, "require": { @@ -322,9 +322,9 @@ "php": "^7.1|^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.17", + "friendsofphp/php-cs-fixer": "^3.2", "jean85/composer-provided-replaced-stub-package": "^1.0", - "phpstan/phpstan": "^0.12.66", + "phpstan/phpstan": "^1.4", "phpunit/phpunit": "^7.5|^8.5|^9.4", "vimeo/psalm": "^4.3" }, @@ -358,9 +358,9 @@ ], "support": { "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.5" + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6" }, - "time": "2021-10-08T21:21:46+00:00" + "time": "2024-03-08T09:58:59+00:00" }, { "name": "psr/http-factory", @@ -802,16 +802,16 @@ }, { "name": "sentry/sentry", - "version": "4.6.0", + "version": "4.6.1", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php.git", - "reference": "30d98a460ab10f7b7032d76c62da5b1ce6c0765d" + "reference": "5a94184175e5830b589bf923da8c9c3af2c0f409" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/30d98a460ab10f7b7032d76c62da5b1ce6c0765d", - "reference": "30d98a460ab10f7b7032d76c62da5b1ce6c0765d", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/5a94184175e5830b589bf923da8c9c3af2c0f409", + "reference": "5a94184175e5830b589bf923da8c9c3af2c0f409", "shasum": "" }, "require": { @@ -875,7 +875,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-php/issues", - "source": "https://github.com/getsentry/sentry-php/tree/4.6.0" + "source": "https://github.com/getsentry/sentry-php/tree/4.6.1" }, "funding": [ { @@ -887,7 +887,7 @@ "type": "custom" } ], - "time": "2024-02-13T11:32:56+00:00" + "time": "2024-03-08T08:18:09+00:00" }, { "name": "symfony/deprecation-contracts", diff --git a/public/index.php b/public/index.php index 1047d00..561b287 100644 --- a/public/index.php +++ b/public/index.php @@ -1,7 +1,7 @@ prune(); $verifications = new Verifications($db); $verifications->prune(); -$router = new HttpFx; -$router->use('/', function($response, $request) { - $response->setPoweredBy('Mince'); -}); - -$router->setDefaultErrorHandler(function($response, $request, $code, $text) use ($templating) { - $response->setContent($templating->render('http-error', [ - 'error' => [ - 'code' => sprintf('%03d', $code), - 'text' => $text, - ], - ])); -}); +$router = new HttpRouter(errorHandler: new RouterErrorHandler($templating)); +$router->use('/', function($response, $request) { $response->setPoweredBy('Mince'); }); $router->register(new RpcRoutes($users, $accountLinks, $authorisations, $verifications, $cfg->getString('rpc:secret'), $cfg->getString('urls:clients'))); $router->register(new HomeRoutes($templating, new Servers($db), $authInfo, $cfg->getString('site:login'))); diff --git a/src/ClientsRoutes.php b/src/ClientsRoutes.php index 8559398..95b1a3c 100644 --- a/src/ClientsRoutes.php +++ b/src/ClientsRoutes.php @@ -3,7 +3,7 @@ namespace Mince; use InvalidArgumentException; use RuntimeException; -use Index\Routing\{Route,RouteHandler}; +use Index\Http\Routing\{RouteHandler,HttpGet,HttpMiddleware,HttpPost}; use Index\Security\CSRFP; use Ramsey\Uuid\Uuid; use Sasae\SasaeEnvironment; @@ -18,7 +18,7 @@ class ClientsRoutes extends RouteHandler { private object $authInfo ) {} - #[Route('/clients')] + #[HttpMiddleware('/clients')] public function verifyRequest($response, $request) { if(!$this->authInfo->success) return 403; @@ -41,7 +41,7 @@ class ClientsRoutes extends RouteHandler { ], ]; - #[Route('GET', '/clients')] + #[HttpGet('/clients')] public function getClients($response, $request) { $template = $this->templating->load('clients/index'); @@ -73,7 +73,7 @@ class ClientsRoutes extends RouteHandler { return $template; } - #[Route('POST', '/clients/link')] + #[HttpPost('/clients/link')] public function postLink($response, $request) { if($this->accountLinks->checkHasLink($this->authInfo->user_id)) { $response->redirect('/clients?error=link:already'); @@ -103,13 +103,13 @@ class ClientsRoutes extends RouteHandler { $response->redirect('/clients'); } - #[Route('POST', '/clients/unlink')] + #[HttpPost('/clients/unlink')] public function postUnlink($response) { $this->accountLinks->deleteLink(userInfo: $this->authInfo->user_id); $response->redirect('/clients'); } - #[Route('POST', '/clients/authorise')] + #[HttpPost('/clients/authorise')] public function postAuthorise($response, $request) { $body = $request->getContent(); $authId = (string)$body->getParam('auth'); @@ -138,7 +138,7 @@ class ClientsRoutes extends RouteHandler { $response->redirect('/clients'); } - #[Route('POST', '/clients/deauthorise')] + #[HttpPost('/clients/deauthorise')] public function postDeauthorise($response, $request) { $body = $request->getContent(); $authId = (string)$body->getParam('auth'); diff --git a/src/HomeRoutes.php b/src/HomeRoutes.php index 2aa4e07..dbbc809 100644 --- a/src/HomeRoutes.php +++ b/src/HomeRoutes.php @@ -1,7 +1,7 @@ templating->render('index', [ 'servers' => iterator_to_array($this->servers->getServers(deleted: false)), ]); } - #[Route('GET', '/login')] + #[HttpGet('/login')] public function getLogin($response) { $response->redirect($this->userInfo->success ? '/' : $this->loginUrl); } - #[Route('GET', '/downloads')] + #[HttpGet('/downloads')] public function getDownloads() { return $this->templating->render('downloads'); } - #[Route('GET', '/guide')] + #[HttpGet('/guide')] public function getGuide() { return $this->templating->render('guide'); } - #[Route('GET', '/index.php')] + #[HttpGet('/index.php')] public function getRedirect($response) { $response->redirect('/', true); } diff --git a/src/MojangInterop.php b/src/MojangInterop.php index 6234549..153551e 100644 --- a/src/MojangInterop.php +++ b/src/MojangInterop.php @@ -3,7 +3,7 @@ namespace Mince; use stdClass; use Index\Http\{HttpResponseBuilder,HttpRequest}; -use Index\Routing\IRouter; +use Index\Http\Routing\IRouter; use Ramsey\Uuid\{Uuid,UuidInterface}; final class MojangInterop { diff --git a/src/RouterErrorHandler.php b/src/RouterErrorHandler.php new file mode 100644 index 0000000..3ad0809 --- /dev/null +++ b/src/RouterErrorHandler.php @@ -0,0 +1,22 @@ +setTypeHTML(); + $response->setContent($this->templating->render('http-error', [ + 'error' => [ + 'code' => sprintf('%03d', $code), + 'text' => $message, + ], + ])); + } +} diff --git a/src/RpcRoutes.php b/src/RpcRoutes.php index 5390a42..0acc173 100644 --- a/src/RpcRoutes.php +++ b/src/RpcRoutes.php @@ -5,7 +5,7 @@ use stdClass; use InvalidArgumentException; use RuntimeException; use Stringable; -use Index\Routing\{Route,RouteHandler}; +use Index\Http\Routing\{HttpMiddleware,HttpPost,RouteHandler}; use Ramsey\Uuid\Uuid; class RpcRoutes extends RouteHandler { @@ -41,7 +41,7 @@ class RpcRoutes extends RouteHandler { return self::createPayload('error', $attrs); } - #[Route('/rpc')] + #[HttpMiddleware('/rpc')] public function verifyRequest($response, $request) { $userTime = (int)$request->getHeaderLine('X-Mince-Time'); $userHash = base64_decode((string)$request->getHeaderLine('X-Mince-Hash')); @@ -68,7 +68,7 @@ class RpcRoutes extends RouteHandler { return self::createErrorPayload('verification', 'Request verification failed.'); } - #[Route('POST', '/rpc/auth')] + #[HttpPost('/rpc/auth')] public function postAuth($response, $request) { $body = $request->getContent(); diff --git a/src/SkinsRoutes.php b/src/SkinsRoutes.php index bf7b988..d8b2bbc 100644 --- a/src/SkinsRoutes.php +++ b/src/SkinsRoutes.php @@ -7,7 +7,7 @@ use ImagickPixel; use InvalidArgumentException; use RuntimeException; use Index\XString; -use Index\Routing\{Route,RouteHandler}; +use Index\Http\Routing\{RouteHandler,HttpGet,HttpMiddleware,HttpPost}; use Index\Security\CSRFP; use Ramsey\Uuid\Uuid; use Sasae\SasaeEnvironment; @@ -52,7 +52,7 @@ class SkinsRoutes extends RouteHandler { unlink($path); } - #[Route('/skins')] + #[HttpMiddleware('/skins')] public function verifyRequest($response, $request) { if(!$this->authInfo->success) return 403; @@ -86,7 +86,7 @@ class SkinsRoutes extends RouteHandler { ], ]; - #[Route('GET', '/skins')] + #[HttpGet('/skins')] public function getSkins($response, $request) { $skinInfo = $this->skins->getSkin($this->linkInfo); $skinPath = $skinInfo === null ? null : $this->getRemotePath($skinInfo->getHash(), false); @@ -119,7 +119,7 @@ class SkinsRoutes extends RouteHandler { return $template; } - #[Route('POST', '/skins/upload-skin')] + #[HttpPost('/skins/upload-skin')] public function postUploadSkin($response, $request) { $body = $request->getContent(); if(!$body->hasUploadedFile('texture')) @@ -182,7 +182,7 @@ class SkinsRoutes extends RouteHandler { $response->redirect('/skins'); } - #[Route('POST', '/skins/delete-skin')] + #[HttpPost('/skins/delete-skin')] public function postDeleteSkin($response) { $skinInfo = $this->skins->getSkin($this->linkInfo); if($skinInfo !== null) { @@ -193,7 +193,7 @@ class SkinsRoutes extends RouteHandler { $response->redirect('/skins'); } - #[Route('POST', '/skins/upload-cape')] + #[HttpPost('/skins/upload-cape')] public function postUploadCape($response, $request) { $body = $request->getContent(); if(!$body->hasUploadedFile('texture')) @@ -245,7 +245,7 @@ class SkinsRoutes extends RouteHandler { $response->redirect('/skins'); } - #[Route('POST', '/skins/delete-cape')] + #[HttpPost('/skins/delete-cape')] public function postDeleteCape($response) { $capeInfo = $this->capes->getCape($this->linkInfo); if($capeInfo !== null) { @@ -256,7 +256,7 @@ class SkinsRoutes extends RouteHandler { $response->redirect('/skins'); } - #[Route('POST', '/skins/import')] + #[HttpPost('/skins/import')] public function postImport($response, $request) { $body = $request->getContent(); $userAgent = $request->getHeaderLine('User-Agent'); @@ -326,7 +326,7 @@ class SkinsRoutes extends RouteHandler { $response->redirect('/skins'); } - #[Route('GET', '/session/minecraft/profile/:id')] + #[HttpGet('/session/minecraft/profile/([a-fA-F0-9\-]+)')] public function getSessionMinecraftProfile($response, $request, string $id) { try { $uuid = Uuid::fromString($id); @@ -386,7 +386,7 @@ class SkinsRoutes extends RouteHandler { ]; } - #[Route('GET', '/users/profiles/minecraft/:name')] + #[HttpGet('/users/profiles/minecraft/([A-Za-z0-9_]+)')] public function getUsersMinecraftProfile($response, $request, string $name) { try { $linkInfo = $this->accountLinks->getLink(name: $name); @@ -405,15 +405,11 @@ class SkinsRoutes extends RouteHandler { } // quirky path and two of them to achieve equal string length with http://s3.amazonaws.com/MinecraftSkins/ for flashii.net and edgii.net - #[Route('GET', '/s3MinecraftSkins/:filename')] - #[Route('GET', '/s3s3MinecraftSkins/:filename')] + #[HttpGet('/s3MinecraftSkins/([A-Za-z0-9_]+).png')] + #[HttpGet('/s3s3MinecraftSkins/([A-Za-z0-9_]+).png')] public function getS3MinecraftSkin($response, $request, string $name) { - $path = pathinfo($name); - if(empty($path) || empty($path['filename']) || empty($path['extension']) || $path['extension'] !== 'png') - return 404; - try { - $linkInfo = $this->accountLinks->getLink(name: $path['filename']); + $linkInfo = $this->accountLinks->getLink(name: $name); } catch(RuntimeException $ex) { return 404; } @@ -424,6 +420,6 @@ class SkinsRoutes extends RouteHandler { $response->accelRedirect($this->getRemotePath($skinInfo->getHash(), false)); $response->setContentType('image/png'); - $response->setFileName("{$path['filename']}.{$path['extension']}", false); + $response->setFileName("{$name}.png", false); } }