From 4053edb9d51c8716eb981d0160982754ebdbabac Mon Sep 17 00:00:00 2001 From: Benni Mack <benni@typo3.org> Date: Thu, 24 Sep 2020 15:25:07 +0200 Subject: [PATCH] [BUGFIX] Do not use returnUrl and index.php for workspace logout links When a workspace preview is given, previously a URL to "index.php" was set, which is not needed anymore. Instead, the logout link for workspace preview links should link to the current URL but only with ADMCMD_prev=LOGOUT. The patch changes the implementation to use UriInterface instead of string magic. Resolves: #92398 Releases: master, 10.4 Change-Id: I3fffe5e43689b41c6f0423c53459e39e230e6278 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/65847 Tested-by: Daniel Goerz <daniel.goerz@posteo.de> Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Claus-Peter Eberwein <claus-peter.eberwein@b13.com> Tested-by: Benni Mack <benni@typo3.org> Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de> Reviewed-by: Claus-Peter Eberwein <claus-peter.eberwein@b13.com> Reviewed-by: Benni Mack <benni@typo3.org> --- .../Classes/Middleware/WorkspacePreview.php | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/typo3/sysext/workspaces/Classes/Middleware/WorkspacePreview.php b/typo3/sysext/workspaces/Classes/Middleware/WorkspacePreview.php index 9d6c3accf6e2..82b4298796d0 100644 --- a/typo3/sysext/workspaces/Classes/Middleware/WorkspacePreview.php +++ b/typo3/sysext/workspaces/Classes/Middleware/WorkspacePreview.php @@ -19,6 +19,7 @@ namespace TYPO3\CMS\Workspaces\Middleware; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Message\UriInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; use Symfony\Component\HttpFoundation\Cookie; @@ -83,7 +84,7 @@ class WorkspacePreview implements MiddlewareInterface // the cookie for the backend preview. if ($keyword === 'LOGOUT') { // "log out", and unset the cookie - $message = $this->getLogoutTemplateMessage($request->getQueryParams()['returnUrl'] ?? ''); + $message = $this->getLogoutTemplateMessage($request->getUri()); $response = new HtmlResponse($message); return $this->addCookie('', $normalizedParams, $response); } @@ -131,7 +132,7 @@ class WorkspacePreview implements MiddlewareInterface // Add an info box to the frontend content if ($GLOBALS['TSFE'] instanceof TypoScriptFrontendController && $context->getPropertyFromAspect('workspace', 'isOffline', false)) { - $previewInfo = $this->renderPreviewInfo($GLOBALS['TSFE'], $request->getAttribute('normalizedParams')); + $previewInfo = $this->renderPreviewInfo($GLOBALS['TSFE'], $request->getUri()); $body = $response->getBody(); $body->rewind(); $content = $body->getContents(); @@ -152,13 +153,12 @@ class WorkspacePreview implements MiddlewareInterface * Renders the logout template when the "logout" button was pressed. * Returns a string which can be put into a HttpResponse. * - * @param string $returnUrl + * @param UriInterface $currentUrl * @return string */ - protected function getLogoutTemplateMessage(string $returnUrl = ''): string + protected function getLogoutTemplateMessage(UriInterface $currentUrl): string { - $returnUrl = GeneralUtility::sanitizeLocalUrl($returnUrl); - $returnUrl = $this->removePreviewParameterFromUrl($returnUrl); + $currentUrl = $this->removePreviewParameterFromUrl($currentUrl); if ($GLOBALS['TYPO3_CONF_VARS']['FE']['workspacePreviewLogoutTemplate']) { $templateFile = GeneralUtility::getFileAbsFileName($GLOBALS['TYPO3_CONF_VARS']['FE']['workspacePreviewLogoutTemplate']); if (@is_file($templateFile)) { @@ -171,9 +171,9 @@ class WorkspacePreview implements MiddlewareInterface } else { $message = $this->getLanguageService()->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang_mod.xlf:previewLogoutSuccess'); $message = htmlspecialchars($message); - $message = sprintf($message, '<a href="' . htmlspecialchars($returnUrl) . '">', '</a>'); + $message = sprintf($message, '<a href="' . htmlspecialchars((string)$currentUrl) . '">', '</a>'); } - return sprintf($message, htmlspecialchars($returnUrl)); + return sprintf($message, htmlspecialchars((string)$currentUrl)); } /** @@ -311,10 +311,10 @@ class WorkspacePreview implements MiddlewareInterface * via TypoScript. * * @param TypoScriptFrontendController $tsfe - * @param NormalizedParams $normalizedParams + * @param UriInterface $currentUrl * @return string */ - protected function renderPreviewInfo(TypoScriptFrontendController $tsfe, NormalizedParams $normalizedParams): string + protected function renderPreviewInfo(TypoScriptFrontendController $tsfe, UriInterface $currentUrl): string { $content = ''; if (!isset($tsfe->config['config']['disablePreviewNotification']) || (int)$tsfe->config['config']['disablePreviewNotification'] !== 1) { @@ -335,8 +335,7 @@ class WorkspacePreview implements MiddlewareInterface $stopPreviewText = $this->getLanguageService()->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang_mod.xlf:stopPreview'); $stopPreviewText = htmlspecialchars($stopPreviewText); if ($GLOBALS['BE_USER'] instanceof PreviewUserAuthentication) { - $url = $this->removePreviewParameterFromUrl($normalizedParams->getRequestUri()); - $urlForStoppingPreview = $normalizedParams->getSiteUrl() . 'index.php?returnUrl=' . rawurlencode($url) . '&ADMCMD_prev=LOGOUT'; + $urlForStoppingPreview = (string)$this->removePreviewParameterFromUrl($currentUrl, 'LOGOUT'); $text .= '<br><a style="color: #000; pointer-events: visible;" href="' . htmlspecialchars($urlForStoppingPreview) . '">' . $stopPreviewText . '</a>'; } $styles = []; @@ -388,12 +387,24 @@ class WorkspacePreview implements MiddlewareInterface /** * Used for generating URLs (e.g. in logout page) without the existing ADMCMD_prev keyword as GET variable * - * @param string $url - * @return string + * @param UriInterface $url + * @param string $newAdminCommand + * @return UriInterface */ - protected function removePreviewParameterFromUrl(string $url): string + protected function removePreviewParameterFromUrl(UriInterface $url, string $newAdminCommand = ''): UriInterface { - return (string)preg_replace('/\\&?' . $this->previewKey . '=[[:alnum:]]+/', '', $url); + $queryString = $url->getQuery(); + if (!empty($queryString)) { + $queryStringParts = GeneralUtility::explodeUrl2Array($queryString); + unset($queryStringParts[$this->previewKey]); + } else { + $queryStringParts = []; + } + if ($newAdminCommand !== '') { + $queryStringParts[$this->previewKey] = $newAdminCommand; + } + $queryString = http_build_query($queryStringParts, '', '&', PHP_QUERY_RFC3986); + return $url->withQuery($queryString); } /** -- GitLab