From 99e56e06fea564734e6b941c245a961ad3a50fb8 Mon Sep 17 00:00:00 2001 From: Mart Kop Date: Thu, 17 Apr 2025 10:54:04 +0200 Subject: [PATCH] Add redirect querystring check and utf8 requirement --- .../RedirectBundle/Router/RedirectRouter.php | 12 +++++++----- .../Tests/Router/RedirectRouterTest.php | 7 +++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Kunstmaan/RedirectBundle/Router/RedirectRouter.php b/src/Kunstmaan/RedirectBundle/Router/RedirectRouter.php index 56dfc03fec..2e597d324a 100644 --- a/src/Kunstmaan/RedirectBundle/Router/RedirectRouter.php +++ b/src/Kunstmaan/RedirectBundle/Router/RedirectRouter.php @@ -137,13 +137,15 @@ private function initRouteCollection(string $pathInfo): void } } - $queryString = $this->context->getQueryString(); - if ($queryString) { - $targetPath .= '?' . $queryString; + $isExternalHost = !\str_starts_with($targetPath, '/'); + $targetPathHasQueryString = \str_contains($targetPath, '?'); + if (($isExternalHost || $targetPathHasQueryString) && ($queryString = $this->context->getQueryString())) { + $targetPath .= ($targetPathHasQueryString ? '&' : '?') . $queryString; } $needsUtf8 = false; - foreach ([$routePath, $targetPath] as $item) { + $decodedPath = urldecode($routePath); + foreach ([$routePath, $decodedPath, $targetPath] as $item) { if (preg_match('/[\x80-\xFF]/', $item)) { $needsUtf8 = true; @@ -151,7 +153,7 @@ private function initRouteCollection(string $pathInfo): void } } - $route = new Route($routePath, [ + $route = new Route($decodedPath, [ '_controller' => 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction', 'path' => $targetPath, 'permanent' => $redirect->isPermanent(), diff --git a/src/Kunstmaan/RedirectBundle/Tests/Router/RedirectRouterTest.php b/src/Kunstmaan/RedirectBundle/Tests/Router/RedirectRouterTest.php index 1d3f59fb9f..1e786ccd65 100644 --- a/src/Kunstmaan/RedirectBundle/Tests/Router/RedirectRouterTest.php +++ b/src/Kunstmaan/RedirectBundle/Tests/Router/RedirectRouterTest.php @@ -76,6 +76,13 @@ public function urlProviderForImprovedRouter(): iterable yield 'Wildcard root origin to wildcard root target redirect with query params' => ['/test/abc/def?query=test', 'https://www.google.com/test/abc/def?query=test', $this->getRedirect(12, '/*', 'https://www.google.com/*')]; yield 'Wildcard root origin to wildcard root target with root path should not redirect' => ['/', null, $this->getRedirect(13, '/*', 'https://www.google.com/*')]; yield 'Redirect with query params' => ['/test?query=test', 'https://www.google.com/test?query=test', $this->getRedirect(14, '/test', 'https://www.google.com/test')]; + yield 'Wildcard root origin to wildcard root target redirect with spaces' => ['/test/abc/%20def?query=test', 'https://www.google.com/test/abc/%20def?query=test', $this->getRedirect(15, '/*', 'https://www.google.com/*')]; + yield 'Wildcard root origin to wildcard root target redirect with spaces unencoded' => ['/test/abc/ def?query=test', 'https://www.google.com/test/abc/ def?query=test', $this->getRedirect(16, '/*', 'https://www.google.com/*')]; + yield 'Wildcard root origin to wildcard root target redirect with spaces unencoded, required UTF8, query parameter' => ['/documenten/2025bestand 2011 - 2022 (versie vóór kunstmaan).pdf?include=true', 'https://www.google.com/documenten/2025bestand 2011 - 2022 (versie vóór kunstmaan).pdf?include=true', $this->getRedirect(17, '/*', 'https://www.google.com/*')]; + yield 'Redirect to external target redirect and query parameters' => ['/redirect?lorem=ipsum&var=ible', 'https://google.com?lorem=ipsum&var=ible', $this->getRedirect(18, '/redirect', 'https://google.com')]; + yield 'Redirect to target redirect and query parameters' => ['/redirect?lorem=ipsum&var=ible', '/target-path', $this->getRedirect(19, '/redirect', '/target-path')]; + yield 'Redirect with query parameter' => ['/redirect?lorem=ipsum&var=ible', '/target-path?foo=baz&lorem=ipsum&var=ible', $this->getRedirect(20, '/redirect', '/target-path?foo=baz')]; + yield 'Redirect with query parameter to external target' => ['/redirect?lorem=ipsum&var=ible', 'https://google.com/target-path?foo=baz&lorem=ipsum&var=ible', $this->getRedirect(21, '/redirect', 'https://google.com/target-path?foo=baz')]; } private function getRedirect(int $id, string $origin, string $target, bool $permanent = false, ?string $domain = null): Redirect