‪TYPO3CMS  ‪main
ShortcutAndMountPointRedirect.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Http\Message\ResponseInterface;
21 use Psr\Http\Message\ServerRequestInterface;
22 use Psr\Http\Server\MiddlewareInterface;
23 use Psr\Http\Server\RequestHandlerInterface;
24 use Psr\Log\LoggerAwareInterface;
25 use Psr\Log\LoggerAwareTrait;
36 
43 class ‪ShortcutAndMountPointRedirect implements MiddlewareInterface, LoggerAwareInterface
44 {
45  use LoggerAwareTrait;
46 
47  public function ‪process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
48  {
49  $exposeInformation = ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['exposeRedirectInformation'] ?? false;
50 
51  // Check for shortcut page and mount point redirect
52  try {
53  $redirectToUri = $this->‪getRedirectUri($request);
54  } catch (‪ImmediateResponseException $e) {
55  return $e->‪getResponse();
56  }
57  if ($redirectToUri !== null && $redirectToUri !== (string)$request->getUri()) {
59  $pageArguments = $request->getAttribute('routing', null);
60  $message = 'TYPO3 Shortcut/Mountpoint' . ($exposeInformation ? ' at page with ID ' . $pageArguments->getPageId() : '');
61  return new ‪RedirectResponse(
62  $redirectToUri,
63  307,
64  ['X-Redirect-By' => $message]
65  );
66  }
67 
68  // See if the current page is of doktype "External URL", if so, do a redirect as well.
69  $pageInformation = $request->getAttribute('frontend.page.information');
70  $pageRecord = $pageInformation->getPageRecord();
71  if ((int)$pageRecord['doktype'] === ‪PageRepository::DOKTYPE_LINK) {
72  $externalUrl = $this->‪prefixExternalPageUrl($pageRecord['url'], $request->getAttribute('normalizedParams')->getSiteUrl());
73  $message = 'TYPO3 External URL' . ($exposeInformation ? ' at page with ID ' . $pageRecord['uid'] : '');
74  if (!empty($externalUrl)) {
75  return new ‪RedirectResponse(
76  $externalUrl,
77  303,
78  ['X-Redirect-By' => $message]
79  );
80  }
81  $this->logger->error(
82  'Page of type "External URL" could not be resolved properly',
83  [
84  'page' => $pageRecord,
85  ]
86  );
87  return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
88  $request,
89  'Page of type "External URL" could not be resolved properly',
91  );
92  }
93 
94  return $handler->handle($request);
95  }
96 
97  protected function ‪getRedirectUri(ServerRequestInterface $request): ?string
98  {
99  $redirectToUri = $this->‪getRedirectUriForShortcut($request);
100  if ($redirectToUri !== null) {
101  return $redirectToUri;
102  }
103  return $this->‪getRedirectUriForMountPoint($request);
104  }
105 
112  protected function ‪getRedirectUriForShortcut(ServerRequestInterface $request): ?string
113  {
114  $pageInformation = $request->getAttribute('frontend.page.information');
115  $originalShortcutPageRecord = $pageInformation->getOriginalShortcutPageRecord();
116  if (!empty($originalShortcutPageRecord)
117  && $originalShortcutPageRecord['doktype'] == ‪PageRepository::DOKTYPE_SHORTCUT
118  ) {
119  // Check if the shortcut page is actually on the current site, if not, this is a "page not found"
120  // because the request was www.mydomain.com/?id=23 where page ID 23 (which is a shortcut) is on another domain/site.
121  if ((int)($request->getQueryParams()['id'] ?? 0) > 0) {
122  try {
123  $siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
124  $targetSite = $siteFinder->getSiteByPageId($originalShortcutPageRecord['l10n_parent'] ?: $originalShortcutPageRecord['uid']);
125  } catch (‪SiteNotFoundException) {
126  $targetSite = null;
127  }
128  $site = $request->getAttribute('site');
129  if ($targetSite !== $site) {
130  $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
131  $request,
132  'ID was outside the domain',
134  );
135  throw new ‪ImmediateResponseException($response, 1638022483);
136  }
137  }
138  return $this->‪getUriToCurrentPageForRedirect($request);
139  }
140  return null;
141  }
142 
149  protected function ‪getRedirectUriForMountPoint(ServerRequestInterface $request): ?string
150  {
151  $pageInformation = $request->getAttribute('frontend.page.information');
152  $originalMountPointPageRecord = $pageInformation->getOriginalMountPointPageRecord();
153  if (!empty($originalMountPointPageRecord)
154  && (int)$originalMountPointPageRecord['doktype'] === ‪PageRepository::DOKTYPE_MOUNTPOINT
155  ) {
156  return $this->‪getUriToCurrentPageForRedirect($request);
157  }
158  return null;
159  }
160 
168  protected function ‪prefixExternalPageUrl(string $redirectTo, string $sitePrefix): string
169  {
170  $uI = parse_url($redirectTo);
171  // If relative path, prefix Site URL
172  // If it's a valid email without protocol, add "mailto:"
173  if (!($uI['scheme'] ?? false)) {
174  if (GeneralUtility::validEmail($redirectTo)) {
175  $redirectTo = 'mailto:' . $redirectTo;
176  } elseif (!str_starts_with($redirectTo, '/')) {
177  $redirectTo = $sitePrefix . $redirectTo;
178  }
179  }
180  return $redirectTo;
181  }
182 
183  protected function ‪getUriToCurrentPageForRedirect(ServerRequestInterface $request): string
184  {
185  $pageInformation = $request->getAttribute('frontend.page.information');
186  $pageRecord = $pageInformation->getPageRecord();
187  $parameter = $pageRecord['uid'];
189  $pageArguments = $request->getAttribute('routing');
190  $type = $pageArguments->getPageType();
191  if ($type) {
192  $parameter .= ',' . $type;
193  }
194  $tsfe = $request->getAttribute('frontend.controller');
195  return GeneralUtility::makeInstance(ContentObjectRenderer::class, $tsfe)->createUrl([
196  'parameter' => $parameter,
197  'addQueryString' => 'untrusted',
198  'addQueryString.' => ['exclude' => 'id,type'],
199  'forceAbsoluteUrl' => true,
200  ]);
201  }
202 }
‪TYPO3\CMS\Core\Routing\PageArguments
Definition: PageArguments.php:26
‪TYPO3\CMS\Frontend\Middleware\ShortcutAndMountPointRedirect\prefixExternalPageUrl
‪string prefixExternalPageUrl(string $redirectTo, string $sitePrefix)
Definition: ShortcutAndMountPointRedirect.php:168
‪TYPO3\CMS\Frontend\Middleware\ShortcutAndMountPointRedirect\getRedirectUri
‪getRedirectUri(ServerRequestInterface $request)
Definition: ShortcutAndMountPointRedirect.php:97
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SHORTCUT
‪const DOKTYPE_SHORTCUT
Definition: PageRepository.php:100
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_LINK
‪const DOKTYPE_LINK
Definition: PageRepository.php:99
‪TYPO3\CMS\Core\Exception\SiteNotFoundException
Definition: SiteNotFoundException.php:25
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\INVALID_EXTERNAL_URL
‪const INVALID_EXTERNAL_URL
Definition: PageAccessFailureReasons.php:30
‪TYPO3\CMS\Frontend\Controller\ErrorController
Definition: ErrorController.php:38
‪TYPO3\CMS\Frontend\Middleware\ShortcutAndMountPointRedirect\getUriToCurrentPageForRedirect
‪getUriToCurrentPageForRedirect(ServerRequestInterface $request)
Definition: ShortcutAndMountPointRedirect.php:183
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_MOUNTPOINT
‪const DOKTYPE_MOUNTPOINT
Definition: PageRepository.php:102
‪TYPO3\CMS\Frontend\Middleware\ShortcutAndMountPointRedirect\getRedirectUriForMountPoint
‪getRedirectUriForMountPoint(ServerRequestInterface $request)
Definition: ShortcutAndMountPointRedirect.php:149
‪TYPO3\CMS\Frontend\Middleware
Definition: BackendUserAuthenticator.php:18
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\ACCESS_DENIED_HOST_PAGE_MISMATCH
‪const ACCESS_DENIED_HOST_PAGE_MISMATCH
Definition: PageAccessFailureReasons.php:51
‪TYPO3\CMS\Core\Http\ImmediateResponseException\getResponse
‪Response getResponse()
Definition: ImmediateResponseException.php:49
‪TYPO3\CMS\Frontend\Middleware\ShortcutAndMountPointRedirect\process
‪process(ServerRequestInterface $request, RequestHandlerInterface $handler)
Definition: ShortcutAndMountPointRedirect.php:47
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:30
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:102
‪TYPO3\CMS\Core\Domain\Repository\PageRepository
Definition: PageRepository.php:69
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Frontend\Middleware\ShortcutAndMountPointRedirect
Definition: ShortcutAndMountPointRedirect.php:44
‪TYPO3\CMS\Core\Http\ImmediateResponseException
Definition: ImmediateResponseException.php:35
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons
Definition: PageAccessFailureReasons.php:25
‪TYPO3\CMS\Frontend\Middleware\ShortcutAndMountPointRedirect\getRedirectUriForShortcut
‪getRedirectUriForShortcut(ServerRequestInterface $request)
Definition: ShortcutAndMountPointRedirect.php:112