Commit ea85ef39 authored by Kevin Ditscheid's avatar Kevin Ditscheid

[BUGFIX] Fix the request redirect via the new middleware

parent aacf6289
<?php
namespace SGalinski\SgRoutes\Middleware;
/**
*
* Copyright notice
......@@ -25,21 +27,20 @@
* This copyright notice MUST APPEAR in all copies of the script!
*/
namespace SGalinski\SgRoutes\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use SGalinski\SgRoutes\Service\LicensingService;
use SGalinski\SgRoutes\Service\RoutingService;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Http\RedirectResponse;
use TYPO3\CMS\Core\Http\Uri;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\Controller\ErrorController;
use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons;
use TYPO3\CMS\Frontend\Page\PageRepository;
/**
* Middleware resolver class for the sg_routes
......@@ -68,13 +69,11 @@ class RedirectResolver implements MiddlewareInterface {
$uri = $request->getUri();
$requestParameters = $request->getQueryParams();
$requestPath = $uri->getPath();
$requestParameterPageId = NULL;
$filteredRequestParameters = [];
foreach ($requestParameters as $key => $splittedParameter) {
if ($key === 'id') {
$requestParameterPageId = $splittedParameter;
continue;
}
......@@ -83,14 +82,8 @@ class RedirectResolver implements MiddlewareInterface {
$requestParameters = $filteredRequestParameters;
$routingService = GeneralUtility::makeInstance(RoutingService::class);
if ($requestParameterPageId !== NULL) {
$uri = $uri->withQuery('id=' . $requestParameterPageId);
$rootUid = $routingService->getRootUid($requestParameterPageId);
} else {
$uri = $uri->withQuery('');
$rootUid = $routingService->getRootUidByDomain($uri->getHost(), $requestPath);
}
$uri = $uri->withQuery('');
$rootUid = $request->getAttribute('site')->getRootPageId();
if ($rootUid) {
if ($GLOBALS['TYPO3_CONF_VARS']['FE']['tx_routes_executed'][$rootUid]) {
......@@ -124,12 +117,6 @@ class RedirectResolver implements MiddlewareInterface {
continue;
}
if (\substr($redirect['source_url'], -1) === '/') {
$trimmedSourceUrl = \substr($redirect['source_url'], 0, -1);
} else {
$trimmedSourceUrl = $redirect['source_url'];
}
if ($redirect['use_regular_expression'] && LicensingService::checkKey()) {
$pattern = '/' . \str_replace('/', '\\/', $redirect['source_url']) . '/is';
if ($redirect['redirect_url_parameters']) {
......@@ -147,41 +134,49 @@ class RedirectResolver implements MiddlewareInterface {
);
return new RedirectResponse($redirectUri, $redirect['redirect_code']);
}
} elseif (
(
(bool)$redirect['source_url_case_sensitive'] &&
\rawurldecode($uri) === $trimmedSourceUrl
) ||
(
!(bool)$redirect['source_url_case_sensitive'] &&
\mb_strtolower(\rawurldecode($uri)) === \mb_strtolower($trimmedSourceUrl)
)
) {
$destinationUrl = $redirect['destination_url'];
if (\strpos($destinationUrl, self::URL_WIZARD_ID) === 0) {
$destinationUrl = (int) \substr($destinationUrl, 14);
} else {
$sourceUrl = new Uri($redirect['source_url']);
$uri = $uri->withPath(\trim($uri->getPath(), '/'));
$sourceUrl = $sourceUrl->withPath(\trim($sourceUrl->getPath()));
if ($sourceUrl->getHost() === '') {
$uri = $uri->withHost('')->withScheme(NULL);
}
if (
(
(bool)$redirect['source_url_case_sensitive'] &&
(string) $uri === (string) $sourceUrl
) ||
(
!(bool)$redirect['source_url_case_sensitive'] &&
\mb_strtolower($uri) === \mb_strtolower($sourceUrl)
)
) {
$destinationUrl = $redirect['destination_url'];
if (\strpos($destinationUrl, self::URL_WIZARD_ID) === 0) {
$destinationUrl = (int) \substr($destinationUrl, 14);
}
if (\is_numeric($destinationUrl)) {
$contentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class, $GLOBALS['TSFE']);
$redirectUri = $contentObjectRenderer->typoLink_URL([
'parameter' => $destinationUrl,
'additionalParams' => '&' . \implode('&', $requestParameters)
]);
if ($redirectUri === '') {
// the page either does not exist or isn't accessible, drop out
return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
$request,
'The page with id #' . $destinationUrl . ' could not be found!',
['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
);
if (\is_numeric($destinationUrl)) {
$GLOBALS['TSFE']->sys_page = GeneralUtility::makeInstance(PageRepository::class);
$contentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class, $GLOBALS['TSFE']);
$redirectUri = $contentObjectRenderer->typoLink_URL([
'parameter' => $destinationUrl,
'additionalParams' => '&' . \implode('&', $requestParameters)
]);
if ($redirectUri === '') {
// the page either does not exist or isn't accessible, drop out
return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
$request,
'The page with id #' . $destinationUrl . ' could not be found!',
['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
);
} else {
$this->logRedirect(
$redirect, \rawurldecode($uri), $redirectUri, $start, \microtime(TRUE)
);
return new RedirectResponse($redirectUri, $redirect['redirect_code']);
}
}
} else {
$redirectUri = $destinationUrl . '&' . \implode('&', $requestParameters);
$this->logRedirect(
$redirect, \rawurldecode($uri), $redirectUri, $start, \microtime(TRUE)
);
return new RedirectResponse($redirectUri, $redirect['redirect_code']);
}
}
}
......
......@@ -35,12 +35,13 @@ use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Error\Http\PageNotFoundException;
use TYPO3\CMS\Core\Http\MiddlewareDispatcher;
use TYPO3\CMS\Core\Http\MiddlewareStackResolver;
use TYPO3\CMS\Core\Http\Request;
use TYPO3\CMS\Core\Http\ServerRequestFactory;
use TYPO3\CMS\Core\Http\Uri;
use TYPO3\CMS\Core\Package\PackageManager;
use TYPO3\CMS\Core\Service\DependencyOrderingService;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\RootlineUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Frontend\Controller\ErrorController;
use TYPO3\CMS\Frontend\Http\RequestHandler;
......@@ -72,10 +73,11 @@ class RoutingService {
*
* @param array $parameters
* @param ErrorController $errorController
* @return void
* @return string
* @throws \InvalidArgumentException
* @throws UserFuncException
*/
public function pageErrorHandler(array $parameters, ErrorController $errorController) {
public function pageErrorHandler(array $parameters, ErrorController $errorController): string {
try {
$key = 'pageAccessFailureReasons';
$pageAccessFailureReasons = [];
......@@ -83,7 +85,9 @@ class RoutingService {
$pageAccessFailureReasons = $parameters[$key];
}
$loginUrl = $this->getLoginPageUrl();
$request = $GLOBALS['TYPO3_REQUEST'];
$loginUrl = $this->getLoginPageUrl($request);
$isPageAccessFailureFrontendGroup = \array_key_exists('fe_group', $pageAccessFailureReasons);
$isSgAccountLoaded = ExtensionManagementUtility::isLoaded('sg_account');
$isKeyNumeric = isset($pageAccessFailureReasons['fe_group']) ?
......@@ -97,13 +101,7 @@ class RoutingService {
exit;
}
$request = $GLOBALS['TYPO3_REQUEST'];
$queryParams = $request->getQueryParams();
if ($queryParams['id'] !== NULL) {
$rootUid = $this->getRootUid($queryParams['id']);
} else {
$rootUid = $this->getRootUidByDomain($request->getUri()->getHost(), $request->getUri()->getPath());
}
$rootUid = $request->getAttribute('site')->getRootPageId();
$configurationFound = FALSE;
if ($rootUid) {
......@@ -149,7 +147,7 @@ class RoutingService {
}
try {
$errorController->pageNotFoundAction($GLOBALS['TYPO3_REQUEST'], 'Page Not Found');
$response = $errorController->pageNotFoundAction($GLOBALS['TYPO3_REQUEST'], 'Page Not Found');
} catch (PageNotFoundException $exception) {
// this can happen if e.g. the wanted error page can't be fetched.
......@@ -168,6 +166,8 @@ class RoutingService {
);
die();
}
return (string) $response->getBody();
}
/**
......@@ -266,84 +266,40 @@ class RoutingService {
return $out;
}
/**
* Find the root uid of the given pageId
*
* @param int $pageId
* @return int
*/
public function getRootUid(int $pageId): int {
$rootlineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $pageId);
$rootline = $rootlineUtility->get();
return $rootline[0]['uid'];
}
/**
* Fint the root uid of the given domain name
*
* @param string $domain
* @param string $path
* @return int
*/
public function getRootUidByDomain(string $domain, string $path = ''): int {
$domain = \explode(':', $domain)[0];
$domain = \strtolower(\preg_replace('/\\.$/', '', $domain));
// Removing extra trailing slashes
$path = \trim(\preg_replace('/\\/[^\\/]*$/', '', $path));
// Appending to domain string
$domain .= $path;
$domain = \preg_replace('/\\/*$/', '', $domain);
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
$row = $queryBuilder
->select(
'sys_domain.pid'
)
->from('sys_domain')
->from('pages')
->where(
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq('pages.uid', 'sys_domain.pid'),
$queryBuilder->expr()->orX(
$queryBuilder->expr()->eq(
'sys_domain.domainName',
$queryBuilder->createNamedParameter($domain)
),
$queryBuilder->expr()->eq(
'sys_domain.domainName',
$queryBuilder->createNamedParameter($domain . '/')
)
)
)
)
->setMaxResults(1)
->execute()
->fetch();
return $row['sys_domain.pid'] ?? 0;
}
/**
* You can define a url for the login page redirect. Here we parse the given url and take care of the correct
* url. So it is possible that the users enter just a path or a whole url.
*
* @param Request $request
* @return string
* @throws \UnexpectedValueException
*/
private function getLoginPageUrl(): string {
private function getLoginPageUrl(Request $request): string {
$sgAccountConfiguration = \SGalinski\SgAccount\Utility\ExtensionUtility::getExtensionConfiguration();
$loginRedirectUrl = \trim($sgAccountConfiguration['loginRedirectUrl']);
if ($loginRedirectUrl === '') {
return '';
}
$uri = $GLOBALS['TYPO3_REQUEST']->getUri();
if ($loginRedirectUrl === '/' || $loginRedirectUrl === $uri) {
$uri = $request->getUri();
if ($loginRedirectUrl === '/' || $loginRedirectUrl === $uri->getPath()) {
return $loginRedirectUrl;
}
$path = $uri->getPath() ?? '';
$query = $uri->getQuery() ? '?' . $uri->getQuery() : '';
$fragment = $uri->getFragment() ? '#' . $uri->getFragment() : '';
$loginRedirect = new Uri($loginRedirectUrl);
if ($loginRedirect->getHost() === '') {
$loginRedirect = $loginRedirect->withHost($uri->getHost());
}
if ($loginRedirect->getScheme() === NULL) {
$loginRedirect = $loginRedirect->withScheme($uri->getScheme());
}
if ($loginRedirect->getQuery() === '') {
$loginRedirect = $loginRedirect->withQuery($uri->getQuery());
}
if ($loginRedirect->getFragment() === NULL) {
$loginRedirect = $loginRedirect->withFragment($uri->getFragment());
}
return $path . $query . $fragment;
return (string) $loginRedirect;
}
}
......@@ -24,11 +24,10 @@
* This copyright notice MUST APPEAR in all copies of the script!
*/
return [
'frontend' => [
'sgalinski/sg-routes/redirect-resolver' => [
'target' => '',
'target' => \SGalinski\SgRoutes\Middleware\RedirectResolver::class,
'before' => [
'typo3/cms-frontend/page-resolver'
]
......
Markdown is supported
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