‪TYPO3CMS  9.5
RouteDispatcher.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
17 use Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
30 
35 {
45  public function ‪dispatch(ServerRequestInterface $request, ResponseInterface $response = null): ResponseInterface
46  {
47  $router = GeneralUtility::makeInstance(Router::class);
48  $route = $router->matchRequest($request);
49  $request = $request->withAttribute('route', $route);
50  $request = $request->withAttribute('target', $route->getOption('target'));
51 
52  $enforceReferrerResponse = $this->‪enforceReferrer($request);
53  if ($enforceReferrerResponse instanceof ResponseInterface) {
54  return $enforceReferrerResponse;
55  }
56  if (!$this->‪isValidRequest($request)) {
57  throw new ‪InvalidRequestTokenException('Invalid request for route "' . $route->getPath() . '"', 1425389455);
58  }
59 
60  if ($route->getOption('module')) {
61  $this->‪addAndValidateModuleConfiguration($request, $route);
62  }
63  $targetIdentifier = $route->getOption('target');
64  $target = $this->‪getCallableFromTarget($targetIdentifier);
65  $arguments = [$request];
66 
67  // @deprecated Test if target accepts one (ok) or two (deprecated) arguments
68  $scanForResponse = !GeneralUtility::makeInstance(Features::class)
69  ->isFeatureEnabled('simplifiedControllerActionDispatching');
70  if ($scanForResponse) {
71  if (is_array($targetIdentifier)) {
72  $controllerActionName = implode('::', $targetIdentifier);
73  $targetReflection = new \ReflectionMethod($controllerActionName);
74  } elseif (is_string($targetIdentifier) && strpos($targetIdentifier, '::') !== false) {
75  $controllerActionName = $targetIdentifier;
76  $targetReflection = new \ReflectionMethod($controllerActionName);
77  } elseif (is_callable($targetIdentifier)) {
78  $controllerActionName = 'closure function';
79  $targetReflection = new \ReflectionFunction($targetIdentifier);
80  } else {
81  $controllerActionName = $targetIdentifier . '::__invoke';
82  $targetReflection = new \ReflectionMethod($controllerActionName);
83  }
84  if ($targetReflection->getNumberOfParameters() >= 2) {
85  trigger_error(
86  'Handing over second argument $response to controller action ' . $controllerActionName . '() is deprecated and will be removed in TYPO3 v10.0.',
87  E_USER_DEPRECATED
88  );
89  $arguments[] = $response;
90  }
91  }
92 
93  return call_user_func_array($target, $arguments);
94  }
95 
101  protected function ‪getFormProtection()
102  {
104  }
105 
114  protected function ‪enforceReferrer(ServerRequestInterface $request): ?ResponseInterface
115  {
117  $features = GeneralUtility::makeInstance(Features::class);
118  if (!$features->isFeatureEnabled('security.backend.enforceReferrer')) {
119  return null;
120  }
122  $route = $request->getAttribute('route');
123  $referrerFlags = GeneralUtility::trimExplode(',', $route->getOption('referrer') ?? '', true);
124  if (!in_array('required', $referrerFlags, true)) {
125  return null;
126  }
128  $referrerEnforcer = GeneralUtility::makeInstance(ReferrerEnforcer::class, $request);
129  return $referrerEnforcer->handle([
130  'flags' => $referrerFlags,
131  'subject' => $route->getPath(),
132  ]);
133  }
134 
144  protected function ‪isValidRequest($request)
145  {
146  $route = $request->getAttribute('route');
147  if ($route->getOption('access') === 'public') {
148  return true;
149  }
150  $token = (string)($request->getParsedBody()['token'] ?? $request->getQueryParams()['token']);
151  if ($token) {
152  return $this->‪getFormProtection()->validateToken($token, 'route', $route->getOption('_identifier'));
153  }
154  // backwards compatibility: check for M and module token params
155  // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
156  $token = (string)($request->getParsedBody()['moduleToken'] ?? $request->getQueryParams()['moduleToken']);
157  return $this->‪getFormProtection()->validateToken($token, 'moduleCall', $request->getParsedBody()['M'] ?? $request->getQueryParams()['M']);
158  }
159 
168  protected function ‪addAndValidateModuleConfiguration(ServerRequestInterface $request, ‪Route $route)
169  {
170  $moduleName = $route->‪getOption('moduleName');
171  $moduleConfiguration = $this->‪getModuleConfiguration($moduleName);
172  $route->‪setOption('moduleConfiguration', $moduleConfiguration);
173 
174  $backendUserAuthentication = ‪$GLOBALS['BE_USER'];
175 
176  // Check permissions and exit if the user has no permission for entry
177  $backendUserAuthentication->modAccess($moduleConfiguration);
178  $id = $request->getQueryParams()['id'] ?? $request->getParsedBody()['id'];
179  if (‪MathUtility::canBeInterpretedAsInteger($id) && $id > 0) {
180  $permClause = $backendUserAuthentication->getPagePermsClause(‪Permission::PAGE_SHOW);
181  // Check page access
182  if (!is_array(‪BackendUtility::readPageAccess($id, $permClause))) {
183  // Check if page has been deleted
184  $deleteField = ‪$GLOBALS['TCA']['pages']['ctrl']['delete'];
185  $pageInfo = ‪BackendUtility::getRecord('pages', $id, $deleteField, $permClause ? ' AND ' . $permClause : '', false);
186  if (!$pageInfo[$deleteField]) {
187  throw new \RuntimeException('You don\'t have access to this page', 1289917924);
188  }
189  }
190  }
191  }
192 
200  protected function ‪getModuleConfiguration($moduleName)
201  {
202  if (!isset(‪$GLOBALS['TBE_MODULES']['_configuration'][$moduleName])) {
203  throw new \RuntimeException('Module ' . $moduleName . ' is not configured.', 1289918325);
204  }
205  return ‪$GLOBALS['TBE_MODULES']['_configuration'][$moduleName];
206  }
207 }
‪TYPO3\CMS\Core\Http\Security\ReferrerEnforcer
Definition: ReferrerEnforcer.php:31
‪TYPO3\CMS\Core\Http\Dispatcher
Definition: Dispatcher.php:29
‪TYPO3\CMS\Backend\Http\RouteDispatcher
Definition: RouteDispatcher.php:35
‪TYPO3\CMS\Backend\Http\RouteDispatcher\enforceReferrer
‪ResponseInterface null enforceReferrer(ServerRequestInterface $request)
Definition: RouteDispatcher.php:114
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\get
‪static TYPO3 CMS Core FormProtection AbstractFormProtection get($classNameOrType='default',... $constructorArguments)
Definition: FormProtectionFactory.php:72
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Backend\Routing\Route\getOption
‪mixed getOption($name)
Definition: Route.php:114
‪TYPO3\CMS\Backend\Routing\Exception\InvalidRequestTokenException
Definition: InvalidRequestTokenException.php:21
‪TYPO3\CMS\Backend\Http\RouteDispatcher\isValidRequest
‪bool isValidRequest($request)
Definition: RouteDispatcher.php:144
‪TYPO3\CMS\Backend\Http
Definition: AjaxRequestHandler.php:3
‪TYPO3\CMS\Backend\Routing\Route
Definition: Route.php:23
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:23
‪TYPO3\CMS\Core\Http\Dispatcher\getCallableFromTarget
‪callable getCallableFromTarget($target)
Definition: Dispatcher.php:81
‪TYPO3\CMS\Backend\Http\RouteDispatcher\addAndValidateModuleConfiguration
‪addAndValidateModuleConfiguration(ServerRequestInterface $request, Route $route)
Definition: RouteDispatcher.php:168
‪TYPO3\CMS\Core\Configuration\Features
Definition: Features.php:54
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:32
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:130
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory
Definition: FormProtectionFactory.php:45
‪TYPO3\CMS\Backend\Http\RouteDispatcher\dispatch
‪ResponseInterface dispatch(ServerRequestInterface $request, ResponseInterface $response=null)
Definition: RouteDispatcher.php:45
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Http\RouteDispatcher\getFormProtection
‪TYPO3 CMS Core FormProtection AbstractFormProtection getFormProtection()
Definition: RouteDispatcher.php:101
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Backend\Routing\Route\setOption
‪Route setOption($name, $value)
Definition: Route.php:102
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Backend\Routing\Router
Definition: Router.php:32
‪TYPO3\CMS\Backend\Http\RouteDispatcher\getModuleConfiguration
‪array getModuleConfiguration($moduleName)
Definition: RouteDispatcher.php:200
‪TYPO3\CMS\Backend\Utility\BackendUtility\readPageAccess
‪static array bool readPageAccess($id, $perms_clause)
Definition: BackendUtility.php:635