diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 552b279b88..a7a3e2e5eb 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -3610,6 +3610,11 @@ parameters: count: 1 path: src/Controllers/Table/ExportController.php + - + message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" + count: 1 + path: src/Controllers/Table/ExportRowsController.php + - message: """ #^Call to deprecated method getInstance\\(\\) of class PhpMyAdmin\\\\Config\\: @@ -7480,12 +7485,12 @@ parameters: path: src/Http/Middleware/TokenRequestParamChecking.php - - message: "#^Parameter \\#1 \\$page of static method PhpMyAdmin\\\\Core\\:\\:checkPageValidity\\(\\) expects string, mixed given\\.$#" - count: 2 + message: "#^Cannot access offset 'back' on array\\|object\\.$#" + count: 1 path: src/Http/Middleware/UrlParamsSetting.php - - message: "#^Static property PhpMyAdmin\\\\UrlParams\\:\\:\\$params \\(array\\\\) does not accept array\\\\.$#" + message: "#^Cannot access offset 'goto' on array\\|object\\.$#" count: 1 path: src/Http/Middleware/UrlParamsSetting.php diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 62f81534ad..c8aaf41782 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -3140,6 +3140,9 @@ + + + @@ -6153,19 +6156,6 @@ - - - - - - - - - - - - - diff --git a/src/Controllers/Table/ExportRowsController.php b/src/Controllers/Table/ExportRowsController.php index 6f3f7b6d77..9572633961 100644 --- a/src/Controllers/Table/ExportRowsController.php +++ b/src/Controllers/Table/ExportRowsController.php @@ -26,7 +26,7 @@ final class ExportRowsController implements InvocableController $GLOBALS['single_table'] ??= null; $GLOBALS['where_clause'] ??= null; - if (isset($_POST['goto']) && (! isset($_POST['rows_to_delete']) || ! is_array($_POST['rows_to_delete']))) { + if (! empty($GLOBALS['goto']) && (! isset($_POST['rows_to_delete']) || ! is_array($_POST['rows_to_delete']))) { $this->response->setRequestStatus(false); $this->response->addJSON('message', __('No row selected.')); diff --git a/src/Http/Middleware/UrlParamsSetting.php b/src/Http/Middleware/UrlParamsSetting.php index e6b04dc5c9..dc8e4d5c20 100644 --- a/src/Http/Middleware/UrlParamsSetting.php +++ b/src/Http/Middleware/UrlParamsSetting.php @@ -11,6 +11,7 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; +use Webmozart\Assert\Assert; final class UrlParamsSetting implements MiddlewareInterface { @@ -22,38 +23,42 @@ final class UrlParamsSetting implements MiddlewareInterface { UrlParams::$params = []; - $this->setGotoAndBackGlobals(); + $this->setGotoAndBackGlobals($request); return $handler->handle($request); } - private function setGotoAndBackGlobals(): void + private function setGotoAndBackGlobals(ServerRequestInterface $request): void { // Holds page that should be displayed. $GLOBALS['goto'] = ''; - if (isset($_REQUEST['goto']) && Core::checkPageValidity($_REQUEST['goto'])) { - $GLOBALS['goto'] = $_REQUEST['goto']; - UrlParams::$params['goto'] = $GLOBALS['goto']; + $goto = $request->getQueryParams()['goto'] ?? $request->getParsedBody()['goto'] ?? null; + Assert::nullOrString($goto); + + if ($goto !== null && Core::checkPageValidity($goto)) { + $GLOBALS['goto'] = $goto; + UrlParams::$params['goto'] = $goto; } else { if ($this->config->issetCookie('goto')) { $this->config->removeCookie('goto'); } - - unset($_REQUEST['goto'], $_GET['goto'], $_POST['goto']); } - if (isset($_REQUEST['back']) && Core::checkPageValidity($_REQUEST['back'])) { + $back = $request->getQueryParams()['back'] ?? $request->getParsedBody()['back'] ?? null; + Assert::nullOrString($back); + + if ($back !== null && Core::checkPageValidity($back)) { // Returning page. - $GLOBALS['back'] = $_REQUEST['back']; + $GLOBALS['back'] = $back; return; } - if ($this->config->issetCookie('back')) { - $this->config->removeCookie('back'); + if (! $this->config->issetCookie('back')) { + return; } - unset($_REQUEST['back'], $_GET['back'], $_POST['back']); + $this->config->removeCookie('back'); } } diff --git a/tests/unit/Controllers/Table/ExportRowsControllerTest.php b/tests/unit/Controllers/Table/ExportRowsControllerTest.php index 0ef519fdf2..96669bd240 100644 --- a/tests/unit/Controllers/Table/ExportRowsControllerTest.php +++ b/tests/unit/Controllers/Table/ExportRowsControllerTest.php @@ -49,7 +49,7 @@ class ExportRowsControllerTest extends AbstractTestCase public function testWithoutRowsToDelete(): void { - $_POST['goto'] = 'goto'; + $GLOBALS['goto'] = 'goto'; $controller = $this->createMock(ExportController::class); $controller->expects(self::never())->method('__invoke'); @@ -67,7 +67,7 @@ class ExportRowsControllerTest extends AbstractTestCase public function testWithRowsToDelete(): void { - $_POST['goto'] = 'goto'; + $GLOBALS['goto'] = 'goto'; $_POST['rows_to_delete'] = ['key1' => 'row1', 'key2' => 'row2']; $controller = $this->createMock(ExportController::class); diff --git a/tests/unit/Controllers/Table/ReplaceControllerTest.php b/tests/unit/Controllers/Table/ReplaceControllerTest.php index 239b6c4544..e082b91b23 100644 --- a/tests/unit/Controllers/Table/ReplaceControllerTest.php +++ b/tests/unit/Controllers/Table/ReplaceControllerTest.php @@ -77,7 +77,6 @@ class ReplaceControllerTest extends AbstractTestCase $_POST['table'] = Current::$table; $_POST['ajax_request'] = 'true'; $_POST['relational_display'] = 'K'; - $_POST['goto'] = 'index.php?route=/sql'; $request = self::createStub(ServerRequest::class); $request->method('getParsedBodyParam')->willReturnMap([ diff --git a/tests/unit/Http/Middleware/UrlParamsSettingTest.php b/tests/unit/Http/Middleware/UrlParamsSettingTest.php index b1298412b3..a3ca7a799a 100644 --- a/tests/unit/Http/Middleware/UrlParamsSettingTest.php +++ b/tests/unit/Http/Middleware/UrlParamsSettingTest.php @@ -5,12 +5,12 @@ declare(strict_types=1); namespace PhpMyAdmin\Tests\Http\Middleware; use PhpMyAdmin\Config; +use PhpMyAdmin\Http\Factory\ServerRequestFactory; use PhpMyAdmin\Http\Middleware\UrlParamsSetting; use PhpMyAdmin\Tests\AbstractTestCase; use PhpMyAdmin\UrlParams; use PHPUnit\Framework\Attributes\CoversClass; use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; #[CoversClass(UrlParamsSetting::class)] @@ -21,10 +21,10 @@ final class UrlParamsSettingTest extends AbstractTestCase UrlParams::$params = []; $GLOBALS['goto'] = null; $GLOBALS['back'] = null; - $_REQUEST['goto'] = 'index.php?route=/'; - $_REQUEST['back'] = 'index.php?route=/'; - $request = self::createStub(ServerRequestInterface::class); + $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') + ->withQueryParams(['goto' => 'index.php?route=/', 'back' => 'index.php?route=/']); + $response = self::createStub(ResponseInterface::class); $handler = self::createMock(RequestHandlerInterface::class); $handler->method('handle')->with($request)->willReturn($response); @@ -37,5 +37,8 @@ final class UrlParamsSettingTest extends AbstractTestCase self::assertSame('index.php?route=/', $GLOBALS['back']); /** @psalm-suppress TypeDoesNotContainType */ self::assertSame(['goto' => 'index.php?route=/'], UrlParams::$params); + + $GLOBALS['goto'] = null; + $GLOBALS['back'] = null; } } diff --git a/tests/unit/Table/SearchTest.php b/tests/unit/Table/SearchTest.php index 7d102646c6..60ebce5598 100644 --- a/tests/unit/Table/SearchTest.php +++ b/tests/unit/Table/SearchTest.php @@ -191,7 +191,6 @@ class SearchTest extends AbstractTestCase { $_POST['db'] = 'opengis'; $_POST['table'] = 'world_cities'; - $_POST['back'] = 'index.php?route=/table/search'; $_POST['geom_func'] = [2 => ' ']; $_POST['customWhereClause'] = ''; $_POST['session_max_rows'] = '25';