Skip to content
Snippets Groups Projects
Commit 5f6f2abe authored by Guido Schmechel's avatar Guido Schmechel Committed by Susanne Moog
Browse files

[BUGFIX] Replace regexp capture groups for redirects

The capture group in the redirect target are now replaced,
so redirects with regular expressions are working
referencing the original URL.

Resolves: #89799
Releases: master, 9.5
Change-Id: Ib624e6c7b40dd09ec090e72339ad9aae1211cc4e
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/62781


Tested-by: default avatarBenni Mack <benni@typo3.org>
Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: default avatarSusanne Moog <look@susi.dev>
Reviewed-by: default avatarBenni Mack <benni@typo3.org>
Reviewed-by: default avatarSusanne Moog <look@susi.dev>
parent a4809174
Branches
Tags
No related merge requests found
......@@ -66,7 +66,7 @@ class RedirectHandler implements MiddlewareInterface, LoggerAwareInterface
// If the matched redirect is found, resolve it, and check further
if (is_array($matchedRedirect)) {
$url = $this->redirectService->getTargetUrl($matchedRedirect, $request->getQueryParams(), $request->getAttribute('frontend.user'), $request->getAttribute('site'));
$url = $this->redirectService->getTargetUrl($matchedRedirect, $request->getQueryParams(), $request->getAttribute('frontend.user'), $request->getUri(), $request->getAttribute('site'));
if ($url instanceof UriInterface) {
$this->logger->debug('Redirecting', ['record' => $matchedRedirect, 'uri' => $url]);
$response = $this->buildRedirectResponse($url, $matchedRedirect);
......
......@@ -193,10 +193,11 @@ class RedirectService implements LoggerAwareInterface
* @param array $matchedRedirect
* @param array $queryParams
* @param FrontendUserAuthentication $frontendUserAuthentication
* @param UriInterface $uri
* @param SiteInterface|null $site
* @return UriInterface|null
*/
public function getTargetUrl(array $matchedRedirect, array $queryParams, FrontendUserAuthentication $frontendUserAuthentication, ?SiteInterface $site = null): ?UriInterface
public function getTargetUrl(array $matchedRedirect, array $queryParams, FrontendUserAuthentication $frontendUserAuthentication, UriInterface $uri, ?SiteInterface $site = null): ?UriInterface
{
$this->logger->debug('Found a redirect to process', $matchedRedirect);
$linkParameterParts = GeneralUtility::makeInstance(TypoLinkCodecService::class)->decode((string)$matchedRedirect['target']);
......@@ -211,6 +212,10 @@ class RedirectService implements LoggerAwareInterface
}
// Do this for files, folders, external URLs
if (!empty($linkDetails['url'])) {
if ($matchedRedirect['is_regexp']) {
$linkDetails = $this->replaceRegExpCaptureGroup($matchedRedirect, $uri, $linkDetails);
}
$url = new Uri($linkDetails['url']);
if ($matchedRedirect['force_https']) {
$url = $url->withScheme('https');
......@@ -337,4 +342,21 @@ class RedirectService implements LoggerAwareInterface
}
return $controller;
}
/**
* @param array $matchedRedirect
* @param UriInterface $uri
* @param array $linkDetails
* @return array
*/
protected function replaceRegExpCaptureGroup(array $matchedRedirect, UriInterface $uri, array $linkDetails): array
{
$matchResult = @preg_match($matchedRedirect['source_path'], $uri->getPath(), $matches);
if ($matchResult > 0) {
foreach ($matches as $key => $val) {
$linkDetails['url'] = str_replace('$' . $key, $val, $linkDetails['url']);
}
}
return $linkDetails;
}
}
......@@ -442,7 +442,7 @@ class RedirectServiceTest extends UnitTestCase
{
$this->linkServiceProphecy->resolve(Argument::any())->willThrow(new InvalidPathException('', 1516531195));
$result = $this->redirectService->getTargetUrl(['target' => 'invalid'], [], new FrontendUserAuthentication(), new Site('dummy', 13, []));
$result = $this->redirectService->getTargetUrl(['target' => 'invalid'], [], new FrontendUserAuthentication(), new Uri(), new Site('dummy', 13, []));
self::assertNull($result);
}
......@@ -463,7 +463,8 @@ class RedirectServiceTest extends UnitTestCase
];
$this->linkServiceProphecy->resolve($redirectTargetMatch['target'])->willReturn($linkDetails);
$result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new FrontendUserAuthentication(), new Site('dummy', 13, []));
$source = new Uri('https://example.com');
$result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new FrontendUserAuthentication(), $source, new Site('dummy', 13, []));
$uri = new Uri('https://example.com/');
self::assertEquals($uri, $result);
......@@ -487,7 +488,8 @@ class RedirectServiceTest extends UnitTestCase
];
$this->linkServiceProphecy->resolve($redirectTargetMatch['target'])->willReturn($linkDetails);
$result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new FrontendUserAuthentication(), new Site('dummy', 13, []));
$source = new Uri('https://example.com');
$result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new FrontendUserAuthentication(), $source, new Site('dummy', 13, []));
$uri = new Uri('https://example.com/file.txt');
self::assertEquals($uri, $result);
......@@ -512,7 +514,8 @@ class RedirectServiceTest extends UnitTestCase
];
$this->linkServiceProphecy->resolve($redirectTargetMatch['target'])->willReturn($linkDetails);
$result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new FrontendUserAuthentication(), new Site('dummy', 13, []));
$source = new Uri('https://example.com/');
$result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new FrontendUserAuthentication(), $source, new Site('dummy', 13, []));
$uri = new Uri('https://example.com/folder/');
self::assertEquals($uri, $result);
......@@ -534,7 +537,8 @@ class RedirectServiceTest extends UnitTestCase
];
$this->linkServiceProphecy->resolve($redirectTargetMatch['target'])->willReturn($linkDetails);
$result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new FrontendUserAuthentication(), new Site('dummy', 13, []));
$source = new Uri('https://example.com');
$result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new FrontendUserAuthentication(), $source, new Site('dummy', 13, []));
$uri = new Uri('https://example.com');
self::assertEquals($uri, $result);
......@@ -556,7 +560,8 @@ class RedirectServiceTest extends UnitTestCase
];
$this->linkServiceProphecy->resolve($redirectTargetMatch['target'])->willReturn($linkDetails);
$result = $this->redirectService->getTargetUrl($redirectTargetMatch, ['bar' => 3, 'baz' => 4], new FrontendUserAuthentication(), new Site('dummy', 13, []));
$source = new Uri('https://example.com/?bar=2&baz=4&foo=1');
$result = $this->redirectService->getTargetUrl($redirectTargetMatch, ['bar' => 3, 'baz' => 4], new FrontendUserAuthentication(), $source, new Site('dummy', 13, []));
$uri = new Uri('https://example.com/?bar=2&baz=4&foo=1');
self::assertEquals($uri, $result);
......@@ -601,8 +606,33 @@ class RedirectServiceTest extends UnitTestCase
$redirectService->expects(self::once())->method('getUriFromCustomLinkDetails')
->with($redirectTargetMatch, $frontendUserAuthentication, $site, $linkDetails, $queryParams)
->willReturn($uri);
$result = $redirectService->getTargetUrl($redirectTargetMatch, [], $frontendUserAuthentication, $site);
$result = $redirectService->getTargetUrl($redirectTargetMatch, [], $frontendUserAuthentication, $uri, $site);
self::assertEquals($uri, $result);
}
/**
* @test
*/
public function getTargetUrlReplaceRegExpCaptureGroup()
{
$redirectTargetMatch = [
'source_path' => '#^/foo/(.*)#',
'target' => 'https://anotherdomain.com/$1',
'force_https' => '0',
'keep_query_parameters' => '1',
'is_regexp' => 1
];
$linkDetails = [
'type' => LinkService::TYPE_URL,
'url' => 'https://anotherdomain.com/$1'
];
$this->linkServiceProphecy->resolve($redirectTargetMatch['target'])->willReturn($linkDetails);
$source = new Uri('https://example.com/foo/bar');
$result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new FrontendUserAuthentication(), $source, new Site('dummy', 13, []));
$uri = new Uri('https://anotherdomain.com/bar');
self::assertEquals($uri, $result);
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment