first commit

This commit is contained in:
salam committed 2026-10-19 08:18:39 +02:00
commit 1218dd1517
12716 files changed
+989233

No files matched your search

@@ -0,0 +1,46 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Backend\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;
/**
* Sets up click-jacking prevention for HTTP requests by adding HTTP headers for the response
*
* @internal
*/
class AdditionalResponseHeaders implements MiddlewareInterface
{
/**
* Adds HTTP headers defined in $GLOBALS['TYPO3_CONF_VARS']['BE']['HTTP']['Response']['Headers']
*
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$response = $handler->handle($request);
foreach ($GLOBALS['TYPO3_CONF_VARS']['BE']['HTTP']['Response']['Headers'] ?? [] as $header) {
[$headerName, $value] = explode(':', $header, 2);
$response = $response->withAddedHeader($headerName, trim($value));
}
return $response;
}
}
@@ -0,0 +1,75 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Backend\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\Backend\Routing\Router;
use TYPO3\CMS\Core\Core\Bootstrap;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Initializes the Backend Router and also loads ext_tables.php from all extensions, as this is the place
* where all modules register their routes to the router afterwards.
*
* The route path is added to the request as attribute "routePath".
*
* @internal
*/
class BackendRouteInitialization implements MiddlewareInterface
{
/**
* Resolve the &route (or &M) GET/POST parameter, and also the Router object.
*
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// Check if a module URL is requested and deprecate this call
$moduleName = $request->getQueryParams()['M'] ?? $request->getParsedBody()['M'] ?? null;
// Allow the login page to be displayed if routing is not used and on index.php
// (consolidate RouteDispatcher::evaluateReferrer() when changing 'login' to something different)
$pathToRoute = $request->getQueryParams()['route'] ?? $request->getParsedBody()['route'] ?? $moduleName ?? '/login';
if ($moduleName !== null) {
// backwards compatibility for old module names
// @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
$router = GeneralUtility::makeInstance(Router::class);
foreach ($router->getRoutes() as $routeIdentifier => $route) {
if ($routeIdentifier === $moduleName) {
$pathToRoute = $route->getPath();
break;
}
}
trigger_error('Calling the TYPO3 Backend with "M" GET parameter will be removed in TYPO3 v10.0,'
. ' the calling code calls this script with "&M=' . $moduleName . '" and needs to be adapted'
. ' to use the TYPO3 API.', E_USER_DEPRECATED);
}
Bootstrap::initializeBackendRouter();
Bootstrap::loadExtTables();
// Add the route path to the request
$request = $request->withAttribute('routePath', $pathToRoute);
return $handler->handle($request);
}
}
@@ -0,0 +1,97 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Backend\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\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Context\UserAspect;
use TYPO3\CMS\Core\Context\WorkspaceAspect;
use TYPO3\CMS\Core\Core\Bootstrap;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Initializes the backend user authentication object (BE_USER) and the global LANG object.
*
* @internal
*/
class BackendUserAuthenticator implements MiddlewareInterface
{
/**
* List of requests that don't need a valid BE user
*
* @var array
*/
protected $publicRoutes = [
'/login',
'/login/frame',
'/ajax/login',
'/ajax/logout',
'/ajax/login/preflight',
'/ajax/login/refresh',
'/ajax/login/timedout',
'/ajax/rsa/publickey',
'/ajax/core/requirejs',
];
/**
* Calls the bootstrap process to set up $GLOBALS['BE_USER'] AND $GLOBALS['LANG']
*
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$pathToRoute = $request->getAttribute('routePath', '/login');
Bootstrap::initializeBackendUser();
// @todo: once this logic is in this method, the redirect URL should be handled as response here
Bootstrap::initializeBackendAuthentication($this->isLoggedInBackendUserRequired($pathToRoute));
Bootstrap::initializeLanguageObject();
// Register the backend user as aspect
$this->setBackendUserAspect(GeneralUtility::makeInstance(Context::class), $GLOBALS['BE_USER']);
return $handler->handle($request);
}
/**
* Check if the user is required for the request
* If we're trying to do a login or an ajax login, don't require a user
*
* @param string $routePath the Route path to check against, something like '
* @return bool whether the request can proceed without a login required
*/
protected function isLoggedInBackendUserRequired(string $routePath): bool
{
return in_array($routePath, $this->publicRoutes, true);
}
/**
* Register the backend user as aspect
*
* @param Context $context
* @param BackendUserAuthentication $user
*/
protected function setBackendUserAspect(Context $context, BackendUserAuthentication $user)
{
$context->setAspect('backend.user', GeneralUtility::makeInstance(UserAspect::class, $user));
$context->setAspect('workspace', GeneralUtility::makeInstance(WorkspaceAspect::class, $user->workspace));
}
}
@@ -0,0 +1,55 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Backend\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\Http\RedirectResponse;
/**
* Check lockSSL configuration variable and redirect
* to https version of the backend if needed
*
* Depends on the NormalizedParams middleware to identify the
* Site URL and if the page is not running via HTTPS yet.
*
* @internal
*/
class ForcedHttpsBackendRedirector implements MiddlewareInterface
{
/**
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if ((bool)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL'] && !$request->getAttribute('normalizedParams')->isHttps()) {
if ((int)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSLPort']) {
$sslPortSuffix = ':' . (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSLPort'];
} else {
$sslPortSuffix = '';
}
list(, $url) = explode('://', $request->getAttribute('normalizedParams')->getSiteUrl() . TYPO3_mainDir, 2);
list($server, $address) = explode('/', $url, 2);
return new RedirectResponse('https://' . $server . $sslPortSuffix . '/' . $address);
}
return $handler->handle($request);
}
}
@@ -0,0 +1,44 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Backend\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\Backend\Template\DocumentTemplate;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Initializes the global object $GLOBALS['TBE_TEMPLATE'] for legacy reasons
*
* @internal
*/
class LegacyBackendTemplateInitialization implements MiddlewareInterface
{
/**
* $GLOBALS['TBE_TEMPLATE'] is available then
*
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$GLOBALS['TBE_TEMPLATE'] = GeneralUtility::makeInstance(DocumentTemplate::class);
return $handler->handle($request);
}
}
@@ -0,0 +1,107 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Backend\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\Backend\Exception\BackendLockedException;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Http\JsonResponse;
use TYPO3\CMS\Core\Http\RedirectResponse;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Checks various security options for accessing the TYPO3 backend before proceeding
*
* Depends on the NormalizedParams middleware to identify the
* Site URL and if the page is not running via HTTPS yet.
*
* @internal
*/
class LockedBackendGuard implements MiddlewareInterface
{
/**
* Checks the client's IP address and if typo3conf/LOCK_BACKEND is available
*
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
try {
$redirectToUri = $this->checkLockedBackend();
if (!empty($redirectToUri)) {
return new RedirectResponse($redirectToUri, 302);
}
} catch (BackendLockedException $e) {
// Looks like an AJAX request that can handle JSON, (usually from the timeout functionality)
// So, let's form a request that fits
if (strpos($request->getHeaderLine('Accept'), 'application/json') !== false) {
$session = [
'timed_out' => false,
'will_time_out' => false,
'locked' => true,
'message' => $e->getMessage()
];
return new JsonResponse(['login' => $session]);
}
throw $e;
}
$this->validateVisitorsIpAgainstIpMaskList(
$request->getAttribute('normalizedParams')->getRemoteAddress(),
trim((string)$GLOBALS['TYPO3_CONF_VARS']['BE']['IPmaskList'])
);
return $handler->handle($request);
}
/**
* Check adminOnly configuration variable and redirects to an URL in file typo3conf/LOCK_BACKEND
*
* @return string|null
* @throws BackendLockedException
*/
protected function checkLockedBackend()
{
if ($GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'] < 0) {
throw new BackendLockedException('TYPO3 Backend locked: Backend and Install Tool are locked for maintenance. [BE][adminOnly] is set to "' . (int)$GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'] . '".', 1517949794);
}
if (@is_file(Environment::getLegacyConfigPath() . '/LOCK_BACKEND')) {
$fileContent = file_get_contents(Environment::getLegacyConfigPath() . '/LOCK_BACKEND');
if ($fileContent) {
return $fileContent;
}
throw new BackendLockedException('TYPO3 Backend locked: Browser backend is locked for maintenance. Remove lock by removing the file "typo3conf/LOCK_BACKEND" or use CLI-scripts.', 1517949793);
}
}
/**
* Compare client IP with IPmaskList and throw an exception
*
* @param string $ipAddress
* @param string $ipMaskList
* @throws \RuntimeException
*/
protected function validateVisitorsIpAgainstIpMaskList(string $ipAddress, string $ipMaskList = '')
{
if ($ipMaskList !== '' && !GeneralUtility::cmpIP($ipAddress, $ipMaskList)) {
throw new \RuntimeException('TYPO3 Backend access denied: The IP address of your client does not match the list of allowed IP addresses.', 1517949792);
}
}
}
@@ -0,0 +1,60 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Backend\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\Utility\MathUtility;
/**
* Sets up output compression
*
* @internal
*/
class OutputCompression implements MiddlewareInterface
{
/**
* Clears all output and checks if a compression level is set
*
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// Throw away all output that may have happened during bootstrapping by weird extensions
ob_clean();
// Initialize output compression if configured
$this->initializeOutputCompression();
return $handler->handle($request);
}
/**
* Initialize output compression if configured
*/
protected function initializeOutputCompression()
{
if (extension_loaded('zlib') && $GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel']) {
if (MathUtility::canBeInterpretedAsInteger($GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel'])) {
@ini_set('zlib.output_compression_level', (string)$GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel']);
}
ob_start('ob_gzhandler');
}
}
}
@@ -0,0 +1,61 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Backend\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\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Routing\SiteMatcher;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
/**
* Usually called after the route object is resolved, however, this is not possible yet as this happens
* within the RequestHandler/RouteDispatcher right now and should go away.
*
* This middleware checks for a "id" parameter. If present, it adds a site information to this page ID.
*
* Very useful for all "Web" related modules to resolve all available languages for a site.
*/
class SiteResolver implements MiddlewareInterface
{
/**
* Resolve the site information by checking the page ID ("id" parameter) which is typically used in BE modules
* of type "web".
*
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$pageId = ($request->getQueryParams()['id'] ?? $request->getParsedBody()['id'] ?? 0);
// Check if we have a numeric _GET/_POST parameter for "id", then a site information can be resolved based.
if (MathUtility::canBeInterpretedAsInteger($pageId)) {
$pageId = (int)$pageId;
$rootLine = null;
if ($pageId > 0) {
$rootLine = BackendUtility::BEgetRootLine($pageId);
}
$site = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId($pageId, $rootLine);
$request = $request->withAttribute('site', $site);
$GLOBALS['TYPO3_REQUEST'] = $request;
}
return $handler->handle($request);
}
}