Skip to content

Commit

Permalink
[TASK] Deprecate TSFE->makeCacheHash()
Browse files Browse the repository at this point in the history
The functionality is moved into a new PSR-15 middleware
to base the logic on the request object directly, and
to make the validation more flexible when validating
page parameters for site-based routing.

The previous deprecation to add the request object
to the method has been reverted.

Resolves: #86411
Releases: master
Change-Id: I294fae7e7c0f9eb1e128a88238dabdd8ed27619f
Reviewed-on: https://review.typo3.org/58420
Reviewed-by: Jan Helke <typo3@helke.de>
Tested-by: Jan Helke <typo3@helke.de>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
  • Loading branch information
bmack authored and NeoBlack committed Sep 28, 2018
1 parent ea2dfc1 commit 063417c
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 27 deletions.
Expand Up @@ -11,7 +11,6 @@ Description

The following public methods within :php:`TypoScriptFrontendController` now expect an argument:

* :php:`makeCacheHash(ServerRequestInterface $request)`
* :php:`calculateLinkVars(array $queryParams)`
* :php:`preparePageContentGeneration(ServerRequestInterface $request)`

Expand Down
@@ -0,0 +1,35 @@
.. include:: ../../Includes.txt

===========================================
Deprecation: #86411 - TSFE->makeCacheHash()
===========================================

See :issue:`86411`

Description
===========

The method :php:`TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->makeCacheHash()`
which acts for validating the `&cHash` GET parameter against other given GET parameters
has been marked as deprecated, as this functionality has been moved into a PSR-15 middleware.


Impact
======

Calling the method directly will trigger a deprecation message.


Affected Installations
======================

TYPO3 installations with extensions calling the PHP method directly.


Migration
=========

Ensure to use the PSR-15 middleware stack with the PageParameterValidator in use to verify a
given cHash signature against given query parameters.

.. index:: Frontend, FullyScanned
Expand Up @@ -428,7 +428,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
public $forceTemplateParsing = false;

/**
* The array which cHash_calc is based on, see ->makeCacheHash().
* The array which cHash_calc is based on, see PageParameterValidator class.
* @var array
*/
public $cHash_array = [];
Expand Down Expand Up @@ -2229,22 +2229,16 @@ protected function mergingWithGetVars($GET_VARS)
* This is used to cache pages with more parameters than just id and type.
*
* @see reqCHash()
* @param ServerRequestInterface $request
* @deprecated since TYPO3 v9.5, will be removed in TYPO3 v10.0. This validation is done in the PageParameterValidator PSR-15 middleware.
*/
public function makeCacheHash(ServerRequestInterface $request = null)
public function makeCacheHash()
{
if ($request === null) {
trigger_error('TSFE->makeCacheHash() requires a ServerRequestInterface as first argument, add this argument in order to avoid this deprecation error.', E_USER_DEPRECATED);
}
trigger_error('TSFE->makeCacheHash() will be removed in TYPO3 v10.0, as this is now handled in the PSR-15 middleware.', E_USER_DEPRECATED);
// No need to test anything if caching was already disabled.
if ($this->no_cache && !$GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFoundOnCHashError']) {
return;
}
if ($request === null) {
$GET = GeneralUtility::_GET();
} else {
$GET = $request->getQueryParams();
}
$GET = GeneralUtility::_GET();
if ($this->cHash && is_array($GET)) {
// Make sure we use the page uid and not the page alias
$GET['id'] = $this->id;
Expand Down Expand Up @@ -2272,9 +2266,9 @@ public function makeCacheHash(ServerRequestInterface $request = null)

/**
* Will disable caching if the cHash value was not set.
* This function should be called to check the _existence_ of "&cHash" whenever a plugin generating cacheable output is using extra GET variables. If there _is_ a cHash value the validation of it automatically takes place in makeCacheHash() (see above)
* This function should be called to check the _existence_ of "&cHash" whenever a plugin generating cacheable output is using extra GET variables. If there _is_ a cHash value the validation of it automatically takes place in \TYPO3\CMS\Frontend\Middleware\PageParameterValidator
*
* @see makeCacheHash(), \TYPO3\CMS\Frontend\Plugin\AbstractPlugin::pi_cHashCheck()
* @see \TYPO3\CMS\Frontend\Plugin\AbstractPlugin::pi_cHashCheck()
*/
public function reqCHash()
{
Expand Down
124 changes: 124 additions & 0 deletions typo3/sysext/frontend/Classes/Middleware/PageParameterValidator.php
@@ -0,0 +1,124 @@
<?php
declare(strict_types = 1);

namespace TYPO3\CMS\Frontend\Middleware;

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Core\TimeTracker\TimeTracker;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\Controller\ErrorController;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
use TYPO3\CMS\Frontend\Page\CacheHashCalculator;
use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons;

/**
* This middleware validates given request parameters.
*/
class PageParameterValidator implements MiddlewareInterface
{

/**
* The cHash Service class used for cHash related functionality
*
* @var CacheHashCalculator
*/
protected $cacheHashCalculator;

/**
* @var TypoScriptFrontendController
*/
protected $controller;

/**
* @param TypoScriptFrontendController|null $controller
*/
public function __construct(TypoScriptFrontendController $controller = null)
{
$this->controller = $controller ?? $GLOBALS['TSFE'];
$this->cacheHashCalculator = GeneralUtility::makeInstance(CacheHashCalculator::class);
}

/**
* Validates the &cHash parameter against the other $queryParameters / GET parameters
*
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$pageNotFoundOnValidationError = (bool)($GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFoundOnCHashError'] ?? true);
if ($this->controller->no_cache && !$pageNotFoundOnValidationError) {
// No need to test anything if caching was already disabled.
} else {
// Evaluate the cache hash parameter
$queryParams = $request->getQueryParams();
if (!empty($queryParams) && !$this->evaluateCacheHashParameter($queryParams, $pageNotFoundOnValidationError)) {
return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
$request,
'Request parameters could not be validated (&cHash comparison failed)',
['code' => PageAccessFailureReasons::CACHEHASH_COMPARISON_FAILED]
);
}
}
return $handler->handle($request);
}

/**
* Calculates a hash string based on additional parameters in the url.
*
* Calculated hash is stored in $this->controller->cHash_array.
* This is used to cache pages with more parameters than just id and type.
*
* @see TypoScriptFrontendController::reqCHash()
* @param array $queryParams GET parameters
* @param bool $pageNotFoundOnCacheHashError see $GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFoundOnCHashError']
* @return bool if false, then a PageNotFound response is triggered
*/
protected function evaluateCacheHashParameter(array $queryParams, bool $pageNotFoundOnCacheHashError): bool
{
if ($this->controller->cHash) {
// Make sure we use the page uid and not the page alias
$queryParams['id'] = $this->controller->id;
$this->controller->cHash_array = $this->cacheHashCalculator->getRelevantParameters(GeneralUtility::implodeArrayForUrl('', $queryParams));
$cHash_calc = $this->cacheHashCalculator->calculateCacheHash($this->controller->cHash_array);
if (!hash_equals($cHash_calc, $this->controller->cHash)) {
// Early return to trigger the error controller
if ($pageNotFoundOnCacheHashError) {
return false;
}
$this->controller->no_cache = true;
$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);
}
// No cHash is set, check if that is correct
} elseif ($this->cacheHashCalculator->doParametersRequireCacheHash(GeneralUtility::implodeArrayForUrl('', $queryParams))) {
// Will disable caching
$this->controller->reqCHash();
}
return true;
}

/**
* @return TimeTracker
*/
protected function getTimeTracker(): TimeTracker
{
return GeneralUtility::makeInstance(TimeTracker::class);
}
}
3 changes: 0 additions & 3 deletions typo3/sysext/frontend/Classes/Middleware/PageResolver.php
Expand Up @@ -140,9 +140,6 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
$this->controller->determineId();
}

// Evaluate the cache hash parameter
$this->controller->makeCacheHash($request);

return $handler->handle($request);
}

Expand Down
2 changes: 1 addition & 1 deletion typo3/sysext/frontend/Classes/Page/CacheHashCalculator.php
Expand Up @@ -108,7 +108,7 @@ public function doParametersRequireCacheHash($queryString)
* @param string $queryString Query-parameters: "&xxx=yyy&zzz=uuu
* @return array Array with key/value pairs of query-parameters WITHOUT a certain list of
* @throws \RuntimeException
* @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::makeCacheHash(), \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::typoLink()
* @see \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::typoLink()
*/
public function getRelevantParameters($queryString)
{
Expand Down
11 changes: 10 additions & 1 deletion typo3/sysext/frontend/Configuration/RequestMiddlewares.php
Expand Up @@ -106,11 +106,20 @@
'typo3/cms-frontend/site',
]
],
'typo3/cms-frontend/page-parameter-validator' => [
'target' => \TYPO3\CMS\Frontend\Middleware\PageParameterValidator::class,
'after' => [
'typo3/cms-frontend/page-resolver',
],
'before' => [
'typo3/cms-frontend/prepare-tsfe-rendering',
]
],
/** internal: do not use or reference this middleware in your own code, as this will be possibly be removed */
'typo3/cms-frontend/prepare-tsfe-rendering' => [
'target' => \TYPO3\CMS\Frontend\Middleware\PrepareTypoScriptFrontendRendering::class,
'after' => [
'typo3/cms-frontend/page-resolver',
'typo3/cms-frontend/page-parameter-validator',
]
],
/** internal: do not use or reference this middleware in your own code, as this will be possibly be removed */
Expand Down
Expand Up @@ -55,7 +55,7 @@ class PageResolverTest extends UnitTestCase

protected function setUp(): void
{
$this->controller = $this->getAccessibleMock(TypoScriptFrontendController::class, ['getSiteScript', 'makeCacheHash', 'determineId', 'isBackendUserLoggedIn'], [], '', false);
$this->controller = $this->getAccessibleMock(TypoScriptFrontendController::class, ['getSiteScript', 'determineId', 'isBackendUserLoggedIn'], [], '', false);

// A request handler which expects a site with some more details are found.
$this->responseOutputHandler = new class implements RequestHandlerInterface {
Expand Down
Expand Up @@ -21,13 +21,6 @@
'Deprecation-86046-AdditionalArgumentsInSeveralTypoScriptFrontendControllerMethods.rst'
],
],
'TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->makeCacheHash' => [
'numberOfMandatoryArguments' => 1,
'maximumNumberOfArguments' => 1,
'restFiles' => [
'Deprecation-86046-AdditionalArgumentsInSeveralTypoScriptFrontendControllerMethods.rst'
],
],
'TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->preparePageContentGeneration' => [
'numberOfMandatoryArguments' => 1,
'maximumNumberOfArguments' => 1,
Expand Down
Expand Up @@ -3572,4 +3572,11 @@
'Deprecation-86406-TCATypeGroupInternal_typeFileAndFile_reference.rst',
],
],
'TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->makeCacheHash' => [
'numberOfMandatoryArguments' => 0,
'maximumNumberOfArguments' => 0,
'restFiles' => [
'Deprecation-86411-TSFE-makeCacheHash.rst'
],
],
];

0 comments on commit 063417c

Please sign in to comment.