[TASK] Rename PageParameterValidator middleware
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Middleware / PageArgumentValidator.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Frontend\Middleware;
5
6 /*
7 * This file is part of the TYPO3 CMS project.
8 *
9 * It is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License, either version 2
11 * of the License, or any later version.
12 *
13 * For the full copyright and license information, please read the
14 * LICENSE.txt file that was distributed with this source code.
15 *
16 * The TYPO3 project - inspiring people to share!
17 */
18
19 use Psr\Http\Message\ResponseInterface;
20 use Psr\Http\Message\ServerRequestInterface;
21 use Psr\Http\Server\MiddlewareInterface;
22 use Psr\Http\Server\RequestHandlerInterface;
23 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25 use TYPO3\CMS\Frontend\Controller\ErrorController;
26 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
27 use TYPO3\CMS\Frontend\Page\CacheHashCalculator;
28 use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons;
29
30 /**
31 * This middleware validates given request parameters against the common "cHash" functionality.
32 */
33 class PageArgumentValidator implements MiddlewareInterface
34 {
35
36 /**
37 * The cHash Service class used for cHash related functionality
38 *
39 * @var CacheHashCalculator
40 */
41 protected $cacheHashCalculator;
42
43 /**
44 * @var TypoScriptFrontendController
45 */
46 protected $controller;
47
48 /**
49 * @param TypoScriptFrontendController|null $controller
50 */
51 public function __construct(TypoScriptFrontendController $controller = null)
52 {
53 $this->controller = $controller ?? $GLOBALS['TSFE'];
54 $this->cacheHashCalculator = GeneralUtility::makeInstance(CacheHashCalculator::class);
55 }
56
57 /**
58 * Validates the &cHash parameter against the other $queryParameters / GET parameters
59 *
60 * @param ServerRequestInterface $request
61 * @param RequestHandlerInterface $handler
62 * @return ResponseInterface
63 */
64 public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
65 {
66 $pageNotFoundOnValidationError = (bool)($GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFoundOnCHashError'] ?? true);
67 if ($this->controller->no_cache && !$pageNotFoundOnValidationError) {
68 // No need to test anything if caching was already disabled.
69 } else {
70 // Evaluate the cache hash parameter
71 $queryParams = $request->getQueryParams();
72 if (!empty($queryParams) && !$this->evaluateCacheHashParameter($queryParams, $pageNotFoundOnValidationError)) {
73 return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
74 $request,
75 'Request parameters could not be validated (&cHash comparison failed)',
76 ['code' => PageAccessFailureReasons::CACHEHASH_COMPARISON_FAILED]
77 );
78 }
79 }
80 return $handler->handle($request);
81 }
82
83 /**
84 * Calculates a hash string based on additional parameters in the url.
85 *
86 * Calculated hash is stored in $this->controller->cHash_array.
87 * This is used to cache pages with more parameters than just id and type.
88 *
89 * @see TypoScriptFrontendController::reqCHash()
90 * @param array $queryParams GET parameters
91 * @param bool $pageNotFoundOnCacheHashError see $GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFoundOnCHashError']
92 * @return bool if false, then a PageNotFound response is triggered
93 */
94 protected function evaluateCacheHashParameter(array $queryParams, bool $pageNotFoundOnCacheHashError): bool
95 {
96 if ($this->controller->cHash) {
97 // Make sure we use the page uid and not the page alias
98 $queryParams['id'] = $this->controller->id;
99 $this->controller->cHash_array = $this->cacheHashCalculator->getRelevantParameters(GeneralUtility::implodeArrayForUrl('', $queryParams));
100 $cHash_calc = $this->cacheHashCalculator->calculateCacheHash($this->controller->cHash_array);
101 if (!hash_equals($cHash_calc, $this->controller->cHash)) {
102 // Early return to trigger the error controller
103 if ($pageNotFoundOnCacheHashError) {
104 return false;
105 }
106 $this->controller->no_cache = true;
107 $this->getTimeTracker()->setTSlogMessage('The incoming cHash "' . $this->controller->cHash . '" and calculated cHash "' . $cHash_calc . '" did not match, so caching was disabled. The fieldlist used was "' . implode(',', array_keys($this->controller->cHash_array)) . '"', 2);
108 }
109 // No cHash is set, check if that is correct
110 } elseif ($this->cacheHashCalculator->doParametersRequireCacheHash(GeneralUtility::implodeArrayForUrl('', $queryParams))) {
111 // Will disable caching
112 $this->controller->reqCHash();
113 }
114 return true;
115 }
116
117 /**
118 * @return TimeTracker
119 */
120 protected function getTimeTracker(): TimeTracker
121 {
122 return GeneralUtility::makeInstance(TimeTracker::class);
123 }
124 }