[TASK] Introduce unified RequestHandling for all requests 09/37409/5
authorBenjamin Mack <benni@typo3.org>
Sun, 1 Mar 2015 13:47:15 +0000 (14:47 +0100)
committerHelmut Hummel <helmut.hummel@typo3.org>
Sun, 1 Mar 2015 21:05:20 +0000 (22:05 +0100)
The TYPO3 Bootstrap gets a new function run() to unify
existing entrypoints in FE, BE, CLI and Install Tool.

This way the "visible" part of the bootstrap is reduced
to solely using the new "run()" method, which resolves
to a proper RequestHandler depending on the following
constraints.

* Install Tool
* Frontend: eID
* Frontend: TSFE
* Backend: Regular request
* Backend: AJAX
* Command-Line (CLIkeys)

The interface behaves exactly like TYPO3 Flow.

Unlike Flow, the request handlers are currently hardcoded
inside the bootstrap, but can be extended later.

Each RequestHandler logic is currently put from the global
scope into the main "handleRequest()" method.

Further changes are the deprecation of init.php and
the streamlining of Backend requests, as well as diagram
of the bootstrap process.

Resolves: #65437
Releases: master
Change-Id: I3a2ffe60e59005955c5ef3d3c541b61de2b97526
Reviewed-on: http://review.typo3.org/37409
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Helmut Hummel <helmut.hummel@typo3.org>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
16 files changed:
index.php
typo3/ajax.php
typo3/cli_dispatch.phpsh
typo3/init.php
typo3/sysext/backend/Classes/AjaxRequestHandler.php [new file with mode: 0644]
typo3/sysext/backend/Classes/CliRequestHandler.php [new file with mode: 0644]
typo3/sysext/backend/Classes/RequestHandler.php [new file with mode: 0644]
typo3/sysext/core/Classes/Core/Bootstrap.php
typo3/sysext/core/Classes/Core/CliBootstrap.php
typo3/sysext/core/Classes/Core/RequestHandlerInterface.php [new file with mode: 0644]
typo3/sysext/frontend/Classes/EidRequestHandler.php [new file with mode: 0644]
typo3/sysext/frontend/Classes/FrontendRequestHandler.php [deleted file]
typo3/sysext/frontend/Classes/RequestHandler.php [new file with mode: 0644]
typo3/sysext/install/Classes/RequestHandler.php [new file with mode: 0644]
typo3/sysext/install/Resources/Private/PHP/Boot.php [deleted file]
typo3/sysext/install/Start/Install.php

index fcacf5d..e24c525 100644 (file)
--- a/index.php
+++ b/index.php
@@ -30,11 +30,4 @@ if (version_compare(PHP_VERSION, '5.5.0', '<')) {
 define('TYPO3_MODE', 'FE');
 
 require __DIR__ . '/typo3/sysext/core/Classes/Core/Bootstrap.php';
 define('TYPO3_MODE', 'FE');
 
 require __DIR__ . '/typo3/sysext/core/Classes/Core/Bootstrap.php';
-\TYPO3\CMS\Core\Core\Bootstrap::getInstance()
-       ->baseSetup('')
-       ->redirectToInstallerIfEssentialConfigurationDoesNotExist()
-       ->startOutputBuffering()
-       ->loadConfigurationAndInitialize();
-
-$frontendRequestHandler = new \TYPO3\CMS\Frontend\FrontendRequestHandler();
-$frontendRequestHandler->handleRequest();
+\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->run()->shutdown();
index 9850381..fbe1263 100644 (file)
 
 /**
  * AJAX dispatcher
 
 /**
  * AJAX dispatcher
- *
- * @author Benjamin Mack <mack@xnos.org>
+ * main entry point for AJAX calls in the TYPO3 Backend. Based on $TYPO3_AJAX the Bootstrap let's the request
+ * handled by TYPO3\CMS\Backend\AjaxRequestHandler and AjaxController.
+ * See $TYPO3_CONF_VARS['BE']['AJAX'] and the Core APIs on how to register an AJAX call in the TYPO3 Backend.
  */
  */
-
 $TYPO3_AJAX = TRUE;
 $TYPO3_AJAX = TRUE;
+define('TYPO3_MODE', 'BE');
 
 
-// This is a list of requests that don't necessarily need a valid BE user
-$noUserAjaxIDs = array(
-       'BackendLogin::login',
-       'BackendLogin::logout',
-       'BackendLogin::refreshLogin',
-       'BackendLogin::isTimedOut',
-       'BackendLogin::getChallenge',
-       'BackendLogin::getRsaPublicKey',
-);
-
-// First get the ajaxID
-$ajaxID = isset($_POST['ajaxID']) ? $_POST['ajaxID'] : $_GET['ajaxID'];
-if (isset($ajaxID)) {
-       $ajaxID = (string)stripslashes($ajaxID);
-}
-
-// If we're trying to do an ajax login, don't require a user.
-if (in_array($ajaxID, $noUserAjaxIDs)) {
-       define('TYPO3_PROCEED_IF_NO_USER', 2);
-}
-
-require __DIR__ . '/init.php';
-
-// Finding the script path from the registry
-$ajaxRegistryEntry = isset($GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'][$ajaxID]) ? $GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'][$ajaxID] : NULL;
-$ajaxScript = NULL;
-$csrfTokenCheck = FALSE;
-if ($ajaxRegistryEntry !== NULL) {
-       if (is_array($ajaxRegistryEntry)) {
-               if (isset($ajaxRegistryEntry['callbackMethod'])) {
-                       $ajaxScript = $ajaxRegistryEntry['callbackMethod'];
-                       $csrfTokenCheck = $ajaxRegistryEntry['csrfTokenCheck'];
-               }
-       } else {
-               // @Deprecated since 6.2 will be removed two versions later
-               $ajaxScript = $ajaxRegistryEntry;
-       }
-}
-
-// Instantiating the AJAX object
-$ajaxObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Http\AjaxRequestHandler::class, $ajaxID);
-$ajaxParams = array();
-
-// Evaluating the arguments and calling the AJAX method/function
-if (empty($ajaxID)) {
-       $ajaxObj->setError('No valid ajaxID parameter given.');
-} elseif (empty($ajaxScript)) {
-       $ajaxObj->setError('No backend function registered for ajaxID "' . $ajaxID . '".');
-} else {
-       $success = TRUE;
-       $tokenIsValid = TRUE;
-       if ($csrfTokenCheck) {
-               $tokenIsValid = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get()->validateToken(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('ajaxToken'), 'ajaxCall', $ajaxID);
-       }
-       if ($tokenIsValid) {
-               // Cleanup global variable space
-               unset($csrfTokenCheck, $ajaxRegistryEntry, $tokenIsValid, $success);
-               $success = \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($ajaxScript, $ajaxParams, $ajaxObj, FALSE, TRUE);
-       } else {
-               $ajaxObj->setError('Invalid CSRF token detected for ajaxID "' . $ajaxID . '"!');
-       }
-       if ($success === FALSE) {
-               $ajaxObj->setError('Registered backend function for ajaxID "' . $ajaxID . '" was not found.');
-       }
-}
-
-// Outputting the content (and setting the X-JSON-Header)
-$ajaxObj->render();
+require __DIR__ . '/sysext/core/Classes/Core/Bootstrap.php';
+\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->run('typo3/')->shutdown();
index 3eaf59e..1bc8ed2 100755 (executable)
@@ -30,29 +30,4 @@ require __DIR__ . '/sysext/core/Classes/Core/CliBootstrap.php';
 \TYPO3\CMS\Core\Core\CliBootstrap::checkEnvironmentOrDie();
 
 require __DIR__ . '/sysext/core/Classes/Core/Bootstrap.php';
 \TYPO3\CMS\Core\Core\CliBootstrap::checkEnvironmentOrDie();
 
 require __DIR__ . '/sysext/core/Classes/Core/Bootstrap.php';
-\TYPO3\CMS\Core\Core\Bootstrap::getInstance()
-       ->baseSetup('typo3/')
-       ->loadConfigurationAndInitialize()
-       ->loadTypo3LoadedExtAndExtLocalconf(TRUE)
-       ->applyAdditionalConfigurationSettings()
-       ->initializeTypo3DbGlobal();
-
-\TYPO3\CMS\Core\Core\CliBootstrap::initializeCliKeyOrDie();
-
-\TYPO3\CMS\Core\Core\Bootstrap::getInstance()
-       ->loadExtensionTables(TRUE)
-       ->initializeBackendUser()
-       ->initializeBackendAuthentication()
-       ->initializeLanguageObject();
-
-       // Make sure output is not buffered, so command-line output and interaction can take place
-\TYPO3\CMS\Core\Utility\GeneralUtility::flushOutputBuffers();
-
-try {
-       include(TYPO3_cliInclude);
-} catch (\Exception $e) {
-       fwrite(STDERR, $e->getMessage() . LF);
-       exit(99);
-}
-
-\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->shutdown();
+\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->run('typo3/')->shutdown();
index 49d6ced..235b9c8 100644 (file)
  * For a detailed description of this script, the scope of constants and variables in it,
  * please refer to the document "Inside TYPO3"
  *
  * For a detailed description of this script, the scope of constants and variables in it,
  * please refer to the document "Inside TYPO3"
  *
+ * Please note that this file might be removed in the future in favor of adding these lines to all entry
+ * scripts as well.
+ *
  * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  */
 define('TYPO3_MODE', 'BE');
 
 require __DIR__ . '/sysext/core/Classes/Core/Bootstrap.php';
  * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  */
 define('TYPO3_MODE', 'BE');
 
 require __DIR__ . '/sysext/core/Classes/Core/Bootstrap.php';
-
-\TYPO3\CMS\Core\Core\Bootstrap::getInstance()
-       ->baseSetup('typo3/')
-       ->redirectToInstallerIfEssentialConfigurationDoesNotExist('../')
-       ->startOutputBuffering()
-       ->loadConfigurationAndInitialize()
-       ->loadTypo3LoadedExtAndExtLocalconf(TRUE)
-       ->applyAdditionalConfigurationSettings()
-       ->initializeTypo3DbGlobal()
-       ->checkLockedBackendAndRedirectOrDie()
-       ->checkBackendIpOrDie()
-       ->checkSslBackendAndRedirectIfNeeded()
-       ->checkValidBrowserOrDie()
-       ->loadExtensionTables(TRUE)
-       ->initializeSpriteManager()
-       ->initializeBackendUser()
-       ->initializeBackendAuthentication()
-       ->initializeLanguageObject()
-       ->initializeBackendTemplate()
-       ->endOutputBufferingAndCleanPreviousOutput()
-       ->initializeOutputCompression()
-       ->sendHttpHeaders();
+\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->run('typo3/');
diff --git a/typo3/sysext/backend/Classes/AjaxRequestHandler.php b/typo3/sysext/backend/Classes/AjaxRequestHandler.php
new file mode 100644 (file)
index 0000000..fb96fd3
--- /dev/null
@@ -0,0 +1,154 @@
+<?php
+namespace TYPO3\CMS\Backend;
+
+/*
+ * 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 TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Core\RequestHandlerInterface;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Base class for all AJAX-related calls for the TYPO3 Backend run through typo3/ajax.php.
+ * Before doing the basic BE-related set up of this request (see the additional calls on $this->bootstrap inside
+ * handleRequest()), some AJAX-calls can be made without a valid user, which is determined here.
+ *
+ * Due to legacy reasons, the actual logic is in EXT:core/Http/AjaxRequestHandler which will eventually
+ * be moved into this class.
+ * In the future, the logic for "TYPO3_PROCEED_IF_NO_USER" will be moved in here as well.
+ */
+class AjaxRequestHandler implements RequestHandlerInterface {
+
+       /**
+        * Instance of the current TYPO3 bootstrap
+        * @var Bootstrap
+        */
+       protected $bootstrap;
+
+       /**
+        * Constructor handing over the bootstrap
+        *
+        * @param Bootstrap $bootstrap
+        */
+       public function __construct(Bootstrap $bootstrap) {
+               $this->bootstrap = $bootstrap;
+       }
+
+       /**
+        * Handles any AJAX request in the TYPO3 Backend
+        *
+        * @return void
+        */
+       public function handleRequest() {
+
+               // This is a list of requests that don't necessarily need a valid BE user
+               $noUserAjaxIDs = array(
+                       'BackendLogin::login',
+                       'BackendLogin::logout',
+                       'BackendLogin::refreshLogin',
+                       'BackendLogin::isTimedOut',
+                       'BackendLogin::getChallenge',
+                       'BackendLogin::getRsaPublicKey',
+               );
+
+               // First get the ajaxID
+               $ajaxID = isset($_POST['ajaxID']) ? $_POST['ajaxID'] : $_GET['ajaxID'];
+               if (isset($ajaxID)) {
+                       $ajaxID = (string)stripslashes($ajaxID);
+               }
+
+               // If we're trying to do an ajax login, don't require a user.
+               if (in_array($ajaxID, $noUserAjaxIDs)) {
+                       define('TYPO3_PROCEED_IF_NO_USER', 2);
+               }
+
+               $this->bootstrap
+                       ->checkLockedBackendAndRedirectOrDie()
+                       ->checkBackendIpOrDie()
+                       ->checkSslBackendAndRedirectIfNeeded()
+                       ->checkValidBrowserOrDie()
+                       ->loadExtensionTables(TRUE)
+                       ->initializeSpriteManager()
+                       ->initializeBackendUser()
+                       ->initializeBackendAuthentication()
+                       ->initializeLanguageObject()
+                       ->initializeBackendTemplate()
+                       ->endOutputBufferingAndCleanPreviousOutput()
+                       ->initializeOutputCompression()
+                       ->sendHttpHeaders();
+
+               // Finding the script path from the registry
+               $ajaxRegistryEntry = isset($GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'][$ajaxID]) ? $GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'][$ajaxID] : NULL;
+               $ajaxScript = NULL;
+               $csrfTokenCheck = FALSE;
+               if ($ajaxRegistryEntry !== NULL) {
+                       if (is_array($ajaxRegistryEntry)) {
+                               if (isset($ajaxRegistryEntry['callbackMethod'])) {
+                                       $ajaxScript = $ajaxRegistryEntry['callbackMethod'];
+                                       $csrfTokenCheck = $ajaxRegistryEntry['csrfTokenCheck'];
+                               }
+                       } else {
+                               // @deprecated since 6.2 will be removed two versions later
+                               $ajaxScript = $ajaxRegistryEntry;
+                       }
+               }
+
+               // Instantiating the AJAX object
+               $ajaxObj = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Http\AjaxRequestHandler::class, $ajaxID);
+               $ajaxParams = array();
+
+               // Evaluating the arguments and calling the AJAX method/function
+               if (empty($ajaxID)) {
+                       $ajaxObj->setError('No valid ajaxID parameter given.');
+               } elseif (empty($ajaxScript)) {
+                       $ajaxObj->setError('No backend function registered for ajaxID "' . $ajaxID . '".');
+               } else {
+                       $success = TRUE;
+                       $tokenIsValid = TRUE;
+                       if ($csrfTokenCheck) {
+                               $tokenIsValid = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get()->validateToken(GeneralUtility::_GP('ajaxToken'), 'ajaxCall', $ajaxID);
+                       }
+                       if ($tokenIsValid) {
+                               // Cleanup global variable space
+                               unset($csrfTokenCheck, $ajaxRegistryEntry, $tokenIsValid, $success);
+                               $success = GeneralUtility::callUserFunction($ajaxScript, $ajaxParams, $ajaxObj, FALSE, TRUE);
+                       } else {
+                               $ajaxObj->setError('Invalid CSRF token detected for ajaxID "' . $ajaxID . '"!');
+                       }
+                       if ($success === FALSE) {
+                               $ajaxObj->setError('Registered backend function for ajaxID "' . $ajaxID . '" was not found.');
+                       }
+               }
+
+               // Outputting the content (and setting the X-JSON-Header)
+               $ajaxObj->render();
+       }
+
+       /**
+        * This request handler can handle any backend request coming from ajax.php
+        *
+        * @return bool If the request is an AJAX backend request, TRUE otherwise FALSE
+        */
+       public function canHandleRequest() {
+               return TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX;
+       }
+
+       /**
+        * Returns the priority - how eager the handler is to actually handle the request.
+        *
+        * @return int The priority of the request handler.
+        */
+       public function getPriority() {
+               return 80;
+       }
+}
diff --git a/typo3/sysext/backend/Classes/CliRequestHandler.php b/typo3/sysext/backend/Classes/CliRequestHandler.php
new file mode 100644 (file)
index 0000000..fe6f883
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+namespace TYPO3\CMS\Backend;
+
+/*
+ * 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 TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Core\RequestHandlerInterface;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Command Line Interface Request Handler dealing with "cliKey"-based Commands from the cli_dispatch.phpsh script.
+ * Picks up requests only when coming from the CLI mode.
+ * Resolves the "cliKey" which is registered inside $TYPO3_CONF_VARS[SC_OPTIONS][GLOBAL][cliKeys]
+ * and includes the CLI-based script or exits if no valid "cliKey" is found.
+ */
+class CliRequestHandler implements RequestHandlerInterface {
+
+       /**
+        * Instance of the current TYPO3 bootstrap
+        * @var Bootstrap
+        */
+       protected $bootstrap;
+
+       /**
+        * Constructor handing over the bootstrap
+        *
+        * @param Bootstrap $bootstrap
+        */
+       public function __construct(Bootstrap $bootstrap) {
+               $this->bootstrap = $bootstrap;
+       }
+
+       /**
+        * Handles any commandline request
+        *
+        * @return void
+        */
+       public function handleRequest() {
+               $commandLineKey = $this->getCommandLineKeyOrDie();
+               $commandLineScript = $this->getIncludeScriptByCommandLineKey($commandLineKey);
+
+               $this->bootstrap
+                       ->loadExtensionTables(TRUE)
+                       ->initializeBackendUser()
+                       ->initializeBackendAuthentication()
+                       ->initializeLanguageObject();
+
+               // Make sure output is not buffered, so command-line output and interaction can take place
+               GeneralUtility::flushOutputBuffers();
+
+               try {
+                       include($commandLineScript);
+               } catch (\Exception $e) {
+                       fwrite(STDERR, $e->getMessage() . LF);
+                       exit(99);
+               }
+       }
+
+       /**
+        * Check CLI parameters.
+        * First argument is a key that points to the script configuration.
+        * If it is not set or not valid, the script exits with an error message.
+        *
+        * @return string the CLI key in use
+        */
+       protected function getCommandLineKeyOrDie() {
+               $cliKey = $_SERVER['argv'][1];
+               $errorMessage = '';
+               if (empty($cliKey)) {
+                       $errorMessage = 'This script must have a \'cliKey\' as first argument.';
+               } elseif (!is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['cliKeys'][$cliKey])) {
+                       $errorMessage = 'The supplied \'cliKey\' is not valid.';
+               }
+
+               // exit with an error message
+               if (!empty($errorMessage)) {
+                       $errorMessage .= ' Valid keys are:
+
+';
+                       $cliKeys = array_keys($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['cliKeys']);
+                       asort($cliKeys);
+                       foreach ($cliKeys as $key => $value) {
+                               $errorMessage .= '  ' . $value . LF;
+                       }
+                       fwrite(STDERR, $errorMessage . LF);
+                       die(1);
+               }
+
+               return $cliKey;
+       }
+
+       /**
+        * Define cli-related parameters and return the include script.
+        *
+        * @param string $cliKey the CLI key
+        * @return string the absolute path to the include script
+        */
+       protected function getIncludeScriptByCommandLineKey($cliKey) {
+               list($commandLineScript, $commandLineName) = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['cliKeys'][$cliKey];
+               $commandLineScript = GeneralUtility::getFileAbsFileName($commandLineScript);
+               // Note: These constants are not in use anymore
+               define('TYPO3_cliKey', $cliKey);
+               define('TYPO3_cliInclude', $commandLineScript);
+               $GLOBALS['MCONF']['name'] = $commandLineName;
+               // This is a compatibility layer: Some cli scripts rely on this, like ext:phpunit cli
+               $GLOBALS['temp_cliScriptPath'] = array_shift($_SERVER['argv']);
+               $GLOBALS['temp_cliKey'] = array_shift($_SERVER['argv']);
+               array_unshift($_SERVER['argv'], $GLOBALS['temp_cliScriptPath']);
+               return $commandLineScript;
+       }
+
+       /**
+        * This request handler can handle any CLI request .
+        *
+        * @return bool If the request is a CLI request, TRUE otherwise FALSE
+        */
+       public function canHandleRequest() {
+               return defined('TYPO3_cliMode') && (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_BE) && (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI);
+       }
+
+       /**
+        * Returns the priority - how eager the handler is to actually handle the request.
+        *
+        * @return int The priority of the request handler.
+        */
+       public function getPriority() {
+               return 50;
+       }
+}
diff --git a/typo3/sysext/backend/Classes/RequestHandler.php b/typo3/sysext/backend/Classes/RequestHandler.php
new file mode 100644 (file)
index 0000000..23be5e2
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+namespace TYPO3\CMS\Backend;
+
+/*
+ * 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 TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Core\RequestHandlerInterface;
+
+/**
+ * General RequestHandler for the TYPO3 Backend. This is used for all Backend requests except for CLI
+ * or AJAX calls. Unlike all other RequestHandlers in the TYPO3 CMS Core, the actual logic for choosing
+ * the controller is still done inside places like mod.php and each single file.
+ * This RequestHandler here serves solely to check and set up all requirements needed for a TYPO3 Backend.
+ * This class might be changed in the future.
+ */
+class RequestHandler implements RequestHandlerInterface {
+
+       /**
+        * Instance of the current TYPO3 bootstrap
+        * @var Bootstrap
+        */
+       protected $bootstrap;
+
+       /**
+        * Constructor handing over the bootstrap
+        *
+        * @param Bootstrap $bootstrap
+        */
+       public function __construct(Bootstrap $bootstrap) {
+               $this->bootstrap = $bootstrap;
+       }
+
+       /**
+        * Handles any backend request
+        *
+        * @return void
+        */
+       public function handleRequest() {
+               $this->bootstrap
+                       ->checkLockedBackendAndRedirectOrDie()
+                       ->checkBackendIpOrDie()
+                       ->checkSslBackendAndRedirectIfNeeded()
+                       ->checkValidBrowserOrDie()
+                       ->loadExtensionTables(TRUE)
+                       ->initializeSpriteManager()
+                       ->initializeBackendUser()
+                       ->initializeBackendAuthentication()
+                       ->initializeLanguageObject()
+                       ->initializeBackendTemplate()
+                       ->endOutputBufferingAndCleanPreviousOutput()
+                       ->initializeOutputCompression()
+                       ->sendHttpHeaders();
+       }
+
+       /**
+        * This request handler can handle any backend request (but not CLI).
+        *
+        * @return bool If the request is not a CLI script, TRUE otherwise FALSE
+        */
+       public function canHandleRequest() {
+               return (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_BE && !(TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI));
+       }
+
+       /**
+        * Returns the priority - how eager the handler is to actually handle the
+        * request.
+        *
+        * @return int The priority of the request handler.
+        */
+       public function getPriority() {
+               return 50;
+       }
+}
index b6f35f5..2af7556 100644 (file)
@@ -71,6 +71,12 @@ class Bootstrap {
        protected $activeErrorHandlerClassName;
 
        /**
        protected $activeErrorHandlerClassName;
 
        /**
+        * registered request handlers
+        * @var RequestHandlerInterface[]
+        */
+       protected $availableRequestHandlers = array();
+
+       /**
         * @var bool
         */
        static protected $usesComposerClassLoading = FALSE;
         * @var bool
         */
        static protected $usesComposerClassLoading = FALSE;
@@ -152,6 +158,45 @@ class Bootstrap {
        }
 
        /**
        }
 
        /**
+        * Main entry point called at every request usually from Global scope. Checks if everthing is correct,
+        * and sets up the base request information for a regular request, then
+        * resolves the RequestHandler which handles the request.
+        *
+        * @param string $relativePathPart Relative path of entry script back to document root
+        * @return Bootstrap
+        */
+       public function run($relativePathPart = '') {
+               $this->baseSetup($relativePathPart);
+
+               // Failsafe minimal setup mode for the install tool
+               if (defined('TYPO3_enterInstallScript')) {
+                       $this->startOutputBuffering()
+                               ->loadConfigurationAndInitialize(FALSE, \TYPO3\CMS\Core\Package\FailsafePackageManager::class);
+               } elseif (!$this->checkIfEssentialConfigurationExists() && !defined('TYPO3_cliMode')) {
+                       // Redirect to install tool if base configuration is not found
+                       $backPathToSiteRoot = '';
+                       $pathParts = explode('/', $relativePathPart);
+                       for ($i = 1; $i <= count($pathParts); $i++) {
+                               $backPathToSiteRoot .= '../';
+                       }
+                       $this->redirectToInstallTool($backPathToSiteRoot);
+               } else {
+                       // Regular request (Frontend, AJAX, Backend, CLI)
+                       $this->startOutputBuffering()
+                               ->loadConfigurationAndInitialize()
+                               ->loadTypo3LoadedExtAndExtLocalconf(TRUE)
+                               ->applyAdditionalConfigurationSettings()
+                               ->initializeTypo3DbGlobal();
+               }
+
+               // Resolve request handler that were registered based on TYPO3_MODE
+               $this->registerRequestHandlers();
+               $requestHandler = $this->resolveRequestHandler();
+               $requestHandler->handleRequest();
+               return $this;
+       }
+
+       /**
         * Run the base setup that checks server environment, determines pathes,
         * populates base files and sets common configuration.
         *
         * Run the base setup that checks server environment, determines pathes,
         * populates base files and sets common configuration.
         *
@@ -209,25 +254,86 @@ class Bootstrap {
        }
 
        /**
        }
 
        /**
+        * checks if LocalConfiguration.php or PackageStates.php is missing,
+        * used to see if a redirect to the install tool is needed
+        *
+        * @return bool TRUE when the essential configuration is available, otherwise FALSE
+        */
+       protected function checkIfEssentialConfigurationExists() {
+               $configurationManager = new \TYPO3\CMS\Core\Configuration\ConfigurationManager;
+               $this->setEarlyInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, $configurationManager);
+               return (!file_exists($configurationManager->getLocalConfigurationFileLocation()) || !file_exists(PATH_typo3conf . 'PackageStates.php')) ? FALSE : TRUE;
+       }
+
+       /**
         * Redirect to install tool if LocalConfiguration.php is missing.
         *
         * @param string $pathUpToDocumentRoot Can contain '../' if called from a sub directory
         * Redirect to install tool if LocalConfiguration.php is missing.
         *
         * @param string $pathUpToDocumentRoot Can contain '../' if called from a sub directory
+        * @internal This is not a public API method, do not use in own extensions
+        */
+       public function redirectToInstallTool($pathUpToDocumentRoot = '') {
+               define('TYPO3_enterInstallScript', '1');
+               $this->defineTypo3RequestTypes();
+               Utility\HttpUtility::redirect($pathUpToDocumentRoot . 'typo3/sysext/install/Start/Install.php');
+       }
+
+       /**
+        * Adds available request handlers, which currently hard-coded here based on the TYPO3_MODE. The extensability
+        * of adding own request handlers would be too complex for now, but can be added later.
+        *
         * @return Bootstrap
         * @internal This is not a public API method, do not use in own extensions
         */
         * @return Bootstrap
         * @internal This is not a public API method, do not use in own extensions
         */
-       public function redirectToInstallerIfEssentialConfigurationDoesNotExist($pathUpToDocumentRoot = '') {
-               $configurationManager = new \TYPO3\CMS\Core\Configuration\ConfigurationManager;
-               $this->setEarlyInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, $configurationManager);
-               if (!file_exists($configurationManager->getLocalConfigurationFileLocation()) || !file_exists(PATH_typo3conf . 'PackageStates.php')) {
-                       define('TYPO3_enterInstallScript', '1');
-                       $this->defineTypo3RequestTypes();
-                       require_once __DIR__ . '/../Utility/HttpUtility.php';
-                       Utility\HttpUtility::redirect($pathUpToDocumentRoot . 'typo3/sysext/install/Start/Install.php');
+       protected function registerRequestHandlers() {
+               // Use the install tool handler if in install tool mode
+               if (!$this->checkIfEssentialConfigurationExists() || (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_INSTALL)) {
+                       $this->availableRequestHandlers = array(
+                               \TYPO3\CMS\Install\RequestHandler::class
+                       );
+               } elseif (TYPO3_MODE == 'BE') {
+                       $this->availableRequestHandlers = array(
+                               \TYPO3\CMS\Backend\RequestHandler::class,
+                               \TYPO3\CMS\Backend\AjaxRequestHandler::class,
+                               \TYPO3\CMS\Backend\CliRequestHandler::class
+                       );
+               } elseif (TYPO3_MODE == 'FE') {
+                       $this->availableRequestHandlers = array(
+                               \TYPO3\CMS\Frontend\RequestHandler::class,
+                               \TYPO3\CMS\Frontend\EidRequestHandler::class
+                       );
                }
                return $this;
        }
 
        /**
                }
                return $this;
        }
 
        /**
+        * Fetches the request handler that suits the best based on the priority and the interface
+        * Be sure to always have the constants that are defined in $this->defineTypo3RequestTypes() are set,
+        * so most RequestHandlers can check if they can handle the request.
+        *
+        * @return RequestHandlerInterface
+        * @throws \TYPO3\CMS\Core\Exception
+        * @internal This is not a public API method, do not use in own extensions
+        */
+       public function resolveRequestHandler() {
+               $suitableRequestHandlers = array();
+               foreach ($this->availableRequestHandlers as $requestHandlerClassName) {
+                       $requestHandler = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($requestHandlerClassName, $this);
+                       if ($requestHandler->canHandleRequest()) {
+                               $priority = $requestHandler->getPriority();
+                               if (isset($suitableRequestHandlers[$priority])) {
+                                       throw new \TYPO3\CMS\Core\Exception('More than one request handler with the same priority can handle the request, but only one handler may be active at a time!', 1176471352);
+                               }
+                               $suitableRequestHandlers[$priority] = $requestHandler;
+                       }
+               }
+               if (count($suitableRequestHandlers) === 0) {
+                       throw new \TYPO3\CMS\Core\Exception('No suitable request handler found.', 1225418233);
+               }
+               ksort($suitableRequestHandlers);
+               return array_pop($suitableRequestHandlers);
+       }
+
+       /**
         * Registers the instance of the specified object for an early boot stage.
         * On finalizing the Object Manager initialization, all those instances will
         * be transferred to the Object Manager's registry.
         * Registers the instance of the specified object for an early boot stage.
         * On finalizing the Object Manager initialization, all those instances will
         * be transferred to the Object Manager's registry.
index 5f3ced9..daedab4 100644 (file)
@@ -40,41 +40,6 @@ class CliBootstrap {
        }
 
        /**
        }
 
        /**
-        * Check and define cli parameters.
-        * First argument is a key that points to the script configuration.
-        * If it is not set or not valid, the script exits with an error message.
-        *
-        * @return void
-        * @internal This is not a public API method, do not use in own extensions
-        */
-       static public function initializeCliKeyOrDie() {
-               if (!isset($_SERVER['argv'][1]) || !is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['cliKeys'][$_SERVER['argv'][1]])) {
-                       if (!isset($_SERVER['argv'][1])) {
-                               $message = 'This script must have a \'cliKey\' as first argument.';
-                       } else {
-                               $message = 'The supplied \'cliKey\' is not valid.';
-                       }
-                       $message .= ' Valid keys are:
-
-';
-                       $cliKeys = array_keys($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['cliKeys']);
-                       asort($cliKeys);
-                       foreach ($cliKeys as $key => $value) {
-                               $message .= '  ' . $value . LF;
-                       }
-                       fwrite(STDERR, $message . LF);
-                       die(1);
-               }
-               define('TYPO3_cliKey', $_SERVER['argv'][1]);
-               define('TYPO3_cliInclude', \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['cliKeys'][TYPO3_cliKey][0]));
-               $GLOBALS['MCONF']['name'] = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['cliKeys'][TYPO3_cliKey][1];
-               // This is a compatibility layer: Some cli scripts rely on this, like ext:phpunit cli
-               $GLOBALS['temp_cliScriptPath'] = array_shift($_SERVER['argv']);
-               $GLOBALS['temp_cliKey'] = array_shift($_SERVER['argv']);
-               array_unshift($_SERVER['argv'], $GLOBALS['temp_cliScriptPath']);
-       }
-
-       /**
         * Set up cgi sapi as de facto cli, but check no HTTP
         * environment variables are set.
         *
         * Set up cgi sapi as de facto cli, but check no HTTP
         * environment variables are set.
         *
diff --git a/typo3/sysext/core/Classes/Core/RequestHandlerInterface.php b/typo3/sysext/core/Classes/Core/RequestHandlerInterface.php
new file mode 100644 (file)
index 0000000..cdddae3
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+namespace TYPO3\CMS\Core\Core;
+
+/*
+ * 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!
+ */
+
+/**
+ * The interface for a request handler
+ * see FrontendRequestHandler
+ *
+ * @api
+ */
+interface RequestHandlerInterface {
+
+       /**
+        * Handles a raw request
+        *
+        * @return void
+        * @api
+        */
+       public function handleRequest();
+
+       /**
+        * Checks if the request handler can handle the current request.
+        *
+        * @return bool TRUE if it can handle the request, otherwise FALSE
+        * @api
+        */
+       public function canHandleRequest();
+
+       /**
+        * Returns the priority - how eager the handler is to actually handle the
+        * request. An integer > 0 means "I want to handle this request" where
+        * "100" is default. "0" means "I am a fallback solution".
+        *
+        * @return int The priority of the request handler
+        * @api
+        */
+       public function getPriority();
+}
diff --git a/typo3/sysext/frontend/Classes/EidRequestHandler.php b/typo3/sysext/frontend/Classes/EidRequestHandler.php
new file mode 100644 (file)
index 0000000..804d768
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+namespace TYPO3\CMS\Frontend;
+
+/*
+ * 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 TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Frontend\Utility\EidUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Core\RequestHandlerInterface;
+
+/**
+ * Lightweight alternative to the regular RequestHandler used when $_GET[eID] is set.
+ * In the future, logic from the EidUtility will be moved to this class.
+ */
+class EidRequestHandler implements RequestHandlerInterface {
+
+       /**
+        * Instance of the current TYPO3 bootstrap
+        * @var Bootstrap
+        */
+       protected $bootstrap;
+
+       /**
+        * Constructor handing over the bootstrap
+        *
+        * @param Bootstrap $bootstrap
+        */
+       public function __construct(Bootstrap $bootstrap) {
+               $this->bootstrap = $bootstrap;
+       }
+
+       /**
+        * Handles a frontend request based on the _GP "eID" variable.
+        *
+        * @return void
+        */
+       public function handleRequest() {
+               // Hook to preprocess the current request
+               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['preprocessRequest'])) {
+                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['preprocessRequest'] as $hookFunction) {
+                               $hookParameters = array();
+                               GeneralUtility::callUserFunction($hookFunction, $hookParameters, $hookParameters);
+                       }
+                       unset($hookFunction);
+                       unset($hookParameters);
+               }
+
+               // Remove any output produced until now
+               $this->bootstrap->endOutputBufferingAndCleanPreviousOutput();
+               require EidUtility::getEidScriptPath();
+               $this->bootstrap->shutdown();
+               exit;
+       }
+
+       /**
+        * This request handler can handle any frontend request.
+        *
+        * @return bool If the request is not an eID request, TRUE otherwise FALSE
+        */
+       public function canHandleRequest() {
+               return GeneralUtility::_GP('eID') ? TRUE : FALSE;
+       }
+
+       /**
+        * Returns the priority - how eager the handler is to actually handle the
+        * request.
+        *
+        * @return int The priority of the request handler.
+        */
+       public function getPriority() {
+               return 80;
+       }
+}
diff --git a/typo3/sysext/frontend/Classes/FrontendRequestHandler.php b/typo3/sysext/frontend/Classes/FrontendRequestHandler.php
deleted file mode 100644 (file)
index dd4bcf5..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-<?php
-namespace TYPO3\CMS\Frontend;
-
-/*
- * 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 TYPO3\CMS\Frontend\Utility\EidUtility;
-
-/**
- * This is the MAIN DOCUMENT of the TypoScript driven standard front-end
- *
- * Basically put this is the script which all requests for TYPO3
- * delivered pages goes to in the frontend (the website). The script configures
- * constants, includes libraries and does a little logic here and there in order
- * to instantiate the right classes to create the webpage.
- */
-class FrontendRequestHandler {
-
-       /**
-        * Handles a frontend request
-        *
-        * @return void
-        */
-       public function handleRequest() {
-               \TYPO3\CMS\Core\Core\Bootstrap::getInstance()
-                       ->loadTypo3LoadedExtAndExtLocalconf(TRUE)
-                       ->applyAdditionalConfigurationSettings();
-
-               // Timetracking started
-               $configuredCookieName = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['cookieName']);
-               if (empty($configuredCookieName)) {
-                       $configuredCookieName = 'be_typo_user';
-               }
-               if ($_COOKIE[$configuredCookieName]) {
-                       $GLOBALS['TT'] = new \TYPO3\CMS\Core\TimeTracker\TimeTracker();
-               } else {
-                       $GLOBALS['TT'] = new \TYPO3\CMS\Core\TimeTracker\NullTimeTracker();
-               }
-
-               $GLOBALS['TT']->start();
-
-               \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->initializeTypo3DbGlobal();
-               // Hook to preprocess the current request:
-               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['preprocessRequest'])) {
-                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['preprocessRequest'] as $hookFunction) {
-                               $hookParameters = array();
-                               \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($hookFunction, $hookParameters, $hookParameters);
-                       }
-                       unset($hookFunction);
-                       unset($hookParameters);
-               }
-               // Look for extension ID which will launch alternative output engine
-               if (EidUtility::isEidRequest()) {
-                       // Remove any output produced until now
-                       ob_clean();
-                       require EidUtility::getEidScriptPath();
-                       \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->shutdown();
-                       exit;
-               }
-
-               /** @var $GLOBALS['TSFE'] \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController */
-               $GLOBALS['TSFE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
-                       \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::class,
-                       $GLOBALS['TYPO3_CONF_VARS'],
-                       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('id'),
-                       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('type'),
-                       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('no_cache'),
-                       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('cHash'),
-                       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('jumpurl'),
-                       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('MP'),
-                       \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('RDCT')
-               );
-
-               if ($GLOBALS['TYPO3_CONF_VARS']['FE']['pageUnavailable_force']
-                       && !\TYPO3\CMS\Core\Utility\GeneralUtility::cmpIP(
-                               \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR'),
-                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'])
-               ) {
-                       $GLOBALS['TSFE']->pageUnavailableAndExit('This page is temporarily unavailable.');
-               }
-
-               $GLOBALS['TSFE']->connectToDB();
-               $GLOBALS['TSFE']->sendRedirect();
-
-               // Output compression
-               // Remove any output produced until now
-               ob_clean();
-               if ($GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel'] && extension_loaded('zlib')) {
-                       if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel'])) {
-                               // Prevent errors if ini_set() is unavailable (safe mode)
-                               @ini_set('zlib.output_compression_level', $GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel']);
-                       }
-                       ob_start(array(\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\Utility\CompressionUtility::class), 'compressionOutputHandler'));
-               }
-
-               // FE_USER
-               $GLOBALS['TT']->push('Front End user initialized', '');
-               /** @var $GLOBALS['TSFE'] \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController */
-               $GLOBALS['TSFE']->initFEuser();
-               $GLOBALS['TT']->pull();
-
-               // BE_USER
-               /** @var $GLOBALS['BE_USER'] \TYPO3\CMS\Backend\FrontendBackendUserAuthentication */
-               $GLOBALS['BE_USER'] = $GLOBALS['TSFE']->initializeBackendUser();
-
-               // Process the ID, type and other parameters.
-               // After this point we have an array, $page in TSFE, which is the page-record
-               // of the current page, $id.
-               $GLOBALS['TT']->push('Process ID', '');
-               // Initialize admin panel since simulation settings are required here:
-               if ($GLOBALS['TSFE']->isBackendUserLoggedIn()) {
-                       $GLOBALS['BE_USER']->initializeAdminPanel();
-                       \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->loadExtensionTables(TRUE);
-               } else {
-                       \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->loadCachedTca();
-               }
-               $GLOBALS['TSFE']->checkAlternativeIdMethods();
-               $GLOBALS['TSFE']->clear_preview();
-               $GLOBALS['TSFE']->determineId();
-
-               // Now, if there is a backend user logged in and he has NO access to this page,
-               // then re-evaluate the id shown! _GP('ADMCMD_noBeUser') is placed here because
-               // \TYPO3\CMS\Version\Hook\PreviewHook might need to know if a backend user is logged in.
-               if (
-                       $GLOBALS['TSFE']->isBackendUserLoggedIn()
-                       && (!$GLOBALS['BE_USER']->extPageReadAccess($GLOBALS['TSFE']->page) || \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('ADMCMD_noBeUser'))
-               ) {
-                       // Remove user
-                       unset($GLOBALS['BE_USER']);
-                       $GLOBALS['TSFE']->beUserLogin = FALSE;
-                       // Re-evaluate the page-id.
-                       $GLOBALS['TSFE']->checkAlternativeIdMethods();
-                       $GLOBALS['TSFE']->clear_preview();
-                       $GLOBALS['TSFE']->determineId();
-               }
-
-               $GLOBALS['TSFE']->makeCacheHash();
-               $GLOBALS['TT']->pull();
-
-               // Admin Panel & Frontend editing
-               if ($GLOBALS['TSFE']->isBackendUserLoggedIn()) {
-                       $GLOBALS['BE_USER']->initializeFrontendEdit();
-                       if ($GLOBALS['BE_USER']->adminPanel instanceof \TYPO3\CMS\Frontend\View\AdminPanelView) {
-                               \TYPO3\CMS\Core\Core\Bootstrap::getInstance()
-                                       ->initializeLanguageObject()
-                                       ->initializeSpriteManager();
-                       }
-                       if ($GLOBALS['BE_USER']->frontendEdit instanceof \TYPO3\CMS\Core\FrontendEditing\FrontendEditingController) {
-                               $GLOBALS['BE_USER']->frontendEdit->initConfigOptions();
-                       }
-               }
-
-               // Starts the template
-               $GLOBALS['TT']->push('Start Template', '');
-               $GLOBALS['TSFE']->initTemplate();
-               $GLOBALS['TT']->pull();
-               // Get from cache
-               $GLOBALS['TT']->push('Get Page from cache', '');
-               $GLOBALS['TSFE']->getFromCache();
-               $GLOBALS['TT']->pull();
-               // Get config if not already gotten
-               // After this, we should have a valid config-array ready
-               $GLOBALS['TSFE']->getConfigArray();
-               // Setting language and locale
-               $GLOBALS['TT']->push('Setting language and locale', '');
-               $GLOBALS['TSFE']->settingLanguage();
-               $GLOBALS['TSFE']->settingLocale();
-               $GLOBALS['TT']->pull();
-
-               // Convert POST data to internal "renderCharset" if different from the metaCharset
-               $GLOBALS['TSFE']->convPOSTCharset();
-
-               // Check JumpUrl
-               $GLOBALS['TSFE']->setExternalJumpUrl();
-               $GLOBALS['TSFE']->checkJumpUrlReferer();
-
-               $GLOBALS['TSFE']->handleDataSubmission();
-
-               // Check for shortcut page and redirect
-               $GLOBALS['TSFE']->checkPageForShortcutRedirect();
-               $GLOBALS['TSFE']->checkPageForMountpointRedirect();
-
-               // Generate page
-               $GLOBALS['TSFE']->setUrlIdToken();
-               $GLOBALS['TT']->push('Page generation', '');
-               if ($GLOBALS['TSFE']->isGeneratePage()) {
-                       $GLOBALS['TSFE']->generatePage_preProcessing();
-                       $temp_theScript = $GLOBALS['TSFE']->generatePage_whichScript();
-                       if ($temp_theScript) {
-                               include $temp_theScript;
-                       } else {
-                               \TYPO3\CMS\Frontend\Page\PageGenerator::pagegenInit();
-                               // Global content object
-                               $GLOBALS['TSFE']->newCObj();
-                               // LIBRARY INCLUSION, TypoScript
-                               $temp_incFiles = \TYPO3\CMS\Frontend\Page\PageGenerator::getIncFiles();
-                               foreach ($temp_incFiles as $temp_file) {
-                                       include_once './' . $temp_file;
-                               }
-                               // Content generation
-                               if (!$GLOBALS['TSFE']->isINTincScript()) {
-                                       \TYPO3\CMS\Frontend\Page\PageGenerator::renderContent();
-                                       $GLOBALS['TSFE']->setAbsRefPrefix();
-                               }
-                       }
-                       $GLOBALS['TSFE']->generatePage_postProcessing();
-               } elseif ($GLOBALS['TSFE']->isINTincScript()) {
-                       \TYPO3\CMS\Frontend\Page\PageGenerator::pagegenInit();
-                       // Global content object
-                       $GLOBALS['TSFE']->newCObj();
-                       // LIBRARY INCLUSION, TypoScript
-                       $temp_incFiles = \TYPO3\CMS\Frontend\Page\PageGenerator::getIncFiles();
-                       foreach ($temp_incFiles as $temp_file) {
-                               include_once './' . $temp_file;
-                       }
-               }
-               $GLOBALS['TT']->pull();
-
-               // $GLOBALS['TSFE']->config['INTincScript']
-               if ($GLOBALS['TSFE']->isINTincScript()) {
-                       $GLOBALS['TT']->push('Non-cached objects', '');
-                       $GLOBALS['TSFE']->INTincScript();
-                       $GLOBALS['TT']->pull();
-               }
-               // Output content
-               $sendTSFEContent = FALSE;
-               if ($GLOBALS['TSFE']->isOutputting()) {
-                       $GLOBALS['TT']->push('Print Content', '');
-                       $GLOBALS['TSFE']->processOutput();
-                       $sendTSFEContent = TRUE;
-                       $GLOBALS['TT']->pull();
-               }
-               // Store session data for fe_users
-               $GLOBALS['TSFE']->storeSessionData();
-               // Statistics
-               $GLOBALS['TYPO3_MISC']['microtime_end'] = microtime(TRUE);
-               $GLOBALS['TSFE']->setParseTime();
-               if (isset($GLOBALS['TSFE']->config['config']['debug'])) {
-                       $debugParseTime = (bool)$GLOBALS['TSFE']->config['config']['debug'];
-               } else {
-                       $debugParseTime = !empty($GLOBALS['TSFE']->TYPO3_CONF_VARS['FE']['debug']);
-               }
-               if ($GLOBALS['TSFE']->isOutputting() && $debugParseTime) {
-                       $GLOBALS['TSFE']->content .= LF . '<!-- Parsetime: ' . $GLOBALS['TSFE']->scriptParseTime . 'ms -->';
-               }
-               // Check JumpUrl
-               $GLOBALS['TSFE']->jumpurl();
-               // Preview info
-               $GLOBALS['TSFE']->previewInfo();
-               // Hook for end-of-frontend
-               $GLOBALS['TSFE']->hook_eofe();
-               // Finish timetracking
-               $GLOBALS['TT']->pull();
-               // Check memory usage
-               \TYPO3\CMS\Core\Utility\MonitorUtility::peakMemoryUsage();
-               // beLoginLinkIPList
-               echo $GLOBALS['TSFE']->beLoginLinkIPList();
-
-               // Admin panel
-               if (
-                       $GLOBALS['TSFE']->isBackendUserLoggedIn()
-                       && $GLOBALS['BE_USER'] instanceof \TYPO3\CMS\Backend\FrontendBackendUserAuthentication
-                       && $GLOBALS['BE_USER']->isAdminPanelVisible()
-               ) {
-                       $GLOBALS['TSFE']->content = str_ireplace('</head>', $GLOBALS['BE_USER']->adminPanel->getAdminPanelHeaderData() . '</head>', $GLOBALS['TSFE']->content);
-                       $GLOBALS['TSFE']->content = str_ireplace('</body>', $GLOBALS['BE_USER']->displayAdminPanel() . '</body>', $GLOBALS['TSFE']->content);
-               }
-
-               if ($sendTSFEContent) {
-                       echo $GLOBALS['TSFE']->content;
-               }
-               // Debugging Output
-               if (isset($GLOBALS['error']) && is_object($GLOBALS['error']) && @is_callable(array($GLOBALS['error'], 'debugOutput'))) {
-                       $GLOBALS['error']->debugOutput();
-               }
-               if (TYPO3_DLOG) {
-                       \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('END of FRONTEND session', 'cms', 0, array('_FLUSH' => TRUE));
-               }
-               \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->shutdown();
-       }
-
-}
diff --git a/typo3/sysext/frontend/Classes/RequestHandler.php b/typo3/sysext/frontend/Classes/RequestHandler.php
new file mode 100644 (file)
index 0000000..85d2ea1
--- /dev/null
@@ -0,0 +1,314 @@
+<?php
+namespace TYPO3\CMS\Frontend;
+
+/*
+ * 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 TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Core\RequestHandlerInterface;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * This is the main entry point of the TypoScript driven standard front-end
+ *
+ * Basically put, this is the script which all requests for TYPO3 delivered pages goes to in the
+ * frontend (the website). The script instantiates a $TSFE object, includes libraries and does a little logic here
+ * and there in order to instantiate the right classes to create the webpage.
+ * Previously, this was called index_ts.php and also included the logic for the lightweight "eID" concept,
+ * which is now handled in a separate request handler (EidRequestHandler).
+ */
+class RequestHandler implements RequestHandlerInterface {
+
+       /**
+        * Instance of the current TYPO3 bootstrap
+        * @var Bootstrap
+        */
+       protected $bootstrap;
+
+       /**
+        * Constructor handing over the bootstrap
+        *
+        * @param Bootstrap $bootstrap
+        */
+       public function __construct(Bootstrap $bootstrap) {
+               $this->bootstrap = $bootstrap;
+       }
+
+       /**
+        * Handles a frontend request
+        *
+        * @return void
+        */
+       public function handleRequest() {
+               // Hook to preprocess the current request:
+               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['preprocessRequest'])) {
+                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['preprocessRequest'] as $hookFunction) {
+                               $hookParameters = array();
+                               GeneralUtility::callUserFunction($hookFunction, $hookParameters, $hookParameters);
+                       }
+                       unset($hookFunction);
+                       unset($hookParameters);
+               }
+
+               // Timetracking started
+               $configuredCookieName = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['cookieName']);
+               if (empty($configuredCookieName)) {
+                       $configuredCookieName = 'be_typo_user';
+               }
+               if ($_COOKIE[$configuredCookieName]) {
+                       $GLOBALS['TT'] = new \TYPO3\CMS\Core\TimeTracker\TimeTracker();
+               } else {
+                       $GLOBALS['TT'] = new \TYPO3\CMS\Core\TimeTracker\NullTimeTracker();
+               }
+
+               $GLOBALS['TT']->start();
+
+               /** @var $GLOBALS['TSFE'] \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController */
+               $GLOBALS['TSFE'] = GeneralUtility::makeInstance(
+                       \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::class,
+                       $GLOBALS['TYPO3_CONF_VARS'],
+                       GeneralUtility::_GP('id'),
+                       GeneralUtility::_GP('type'),
+                       GeneralUtility::_GP('no_cache'),
+                       GeneralUtility::_GP('cHash'),
+                       GeneralUtility::_GP('jumpurl'),
+                       GeneralUtility::_GP('MP'),
+                       GeneralUtility::_GP('RDCT')
+               );
+
+               if ($GLOBALS['TYPO3_CONF_VARS']['FE']['pageUnavailable_force']
+                       && !GeneralUtility::cmpIP(
+                               GeneralUtility::getIndpEnv('REMOTE_ADDR'),
+                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'])
+               ) {
+                       $GLOBALS['TSFE']->pageUnavailableAndExit('This page is temporarily unavailable.');
+               }
+
+               $GLOBALS['TSFE']->connectToDB();
+               $GLOBALS['TSFE']->sendRedirect();
+
+               // Output compression
+               // Remove any output produced until now
+               ob_clean();
+               if ($GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel'] && extension_loaded('zlib')) {
+                       if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel'])) {
+                               // Prevent errors if ini_set() is unavailable (safe mode)
+                               @ini_set('zlib.output_compression_level', $GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel']);
+                       }
+                       ob_start(array(GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\Utility\CompressionUtility::class), 'compressionOutputHandler'));
+               }
+
+               // FE_USER
+               $GLOBALS['TT']->push('Front End user initialized', '');
+               /** @var $GLOBALS['TSFE'] \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController */
+               $GLOBALS['TSFE']->initFEuser();
+               $GLOBALS['TT']->pull();
+
+               // BE_USER
+               /** @var $GLOBALS['BE_USER'] \TYPO3\CMS\Backend\FrontendBackendUserAuthentication */
+               $GLOBALS['BE_USER'] = $GLOBALS['TSFE']->initializeBackendUser();
+
+               // Process the ID, type and other parameters.
+               // After this point we have an array, $page in TSFE, which is the page-record
+               // of the current page, $id.
+               $GLOBALS['TT']->push('Process ID', '');
+               // Initialize admin panel since simulation settings are required here:
+               if ($GLOBALS['TSFE']->isBackendUserLoggedIn()) {
+                       $GLOBALS['BE_USER']->initializeAdminPanel();
+                       $this->bootstrap->loadExtensionTables(TRUE);
+               } else {
+                       $this->bootstrap->loadCachedTca();
+               }
+               $GLOBALS['TSFE']->checkAlternativeIdMethods();
+               $GLOBALS['TSFE']->clear_preview();
+               $GLOBALS['TSFE']->determineId();
+
+               // Now, if there is a backend user logged in and he has NO access to this page,
+               // then re-evaluate the id shown! _GP('ADMCMD_noBeUser') is placed here because
+               // \TYPO3\CMS\Version\Hook\PreviewHook might need to know if a backend user is logged in.
+               if (
+                       $GLOBALS['TSFE']->isBackendUserLoggedIn()
+                       && (!$GLOBALS['BE_USER']->extPageReadAccess($GLOBALS['TSFE']->page) || GeneralUtility::_GP('ADMCMD_noBeUser'))
+               ) {
+                       // Remove user
+                       unset($GLOBALS['BE_USER']);
+                       $GLOBALS['TSFE']->beUserLogin = FALSE;
+                       // Re-evaluate the page-id.
+                       $GLOBALS['TSFE']->checkAlternativeIdMethods();
+                       $GLOBALS['TSFE']->clear_preview();
+                       $GLOBALS['TSFE']->determineId();
+               }
+
+               $GLOBALS['TSFE']->makeCacheHash();
+               $GLOBALS['TT']->pull();
+
+               // Admin Panel & Frontend editing
+               if ($GLOBALS['TSFE']->isBackendUserLoggedIn()) {
+                       $GLOBALS['BE_USER']->initializeFrontendEdit();
+                       if ($GLOBALS['BE_USER']->adminPanel instanceof \TYPO3\CMS\Frontend\View\AdminPanelView) {
+                               $this->bootstrap
+                                       ->initializeLanguageObject()
+                                       ->initializeSpriteManager();
+                       }
+                       if ($GLOBALS['BE_USER']->frontendEdit instanceof \TYPO3\CMS\Core\FrontendEditing\FrontendEditingController) {
+                               $GLOBALS['BE_USER']->frontendEdit->initConfigOptions();
+                       }
+               }
+
+               // Starts the template
+               $GLOBALS['TT']->push('Start Template', '');
+               $GLOBALS['TSFE']->initTemplate();
+               $GLOBALS['TT']->pull();
+               // Get from cache
+               $GLOBALS['TT']->push('Get Page from cache', '');
+               $GLOBALS['TSFE']->getFromCache();
+               $GLOBALS['TT']->pull();
+               // Get config if not already gotten
+               // After this, we should have a valid config-array ready
+               $GLOBALS['TSFE']->getConfigArray();
+               // Setting language and locale
+               $GLOBALS['TT']->push('Setting language and locale', '');
+               $GLOBALS['TSFE']->settingLanguage();
+               $GLOBALS['TSFE']->settingLocale();
+               $GLOBALS['TT']->pull();
+
+               // Convert POST data to internal "renderCharset" if different from the metaCharset
+               $GLOBALS['TSFE']->convPOSTCharset();
+
+               // Check JumpUrl
+               $GLOBALS['TSFE']->setExternalJumpUrl();
+               $GLOBALS['TSFE']->checkJumpUrlReferer();
+
+               $GLOBALS['TSFE']->handleDataSubmission();
+
+               // Check for shortcut page and redirect
+               $GLOBALS['TSFE']->checkPageForShortcutRedirect();
+               $GLOBALS['TSFE']->checkPageForMountpointRedirect();
+
+               // Generate page
+               $GLOBALS['TSFE']->setUrlIdToken();
+               $GLOBALS['TT']->push('Page generation', '');
+               if ($GLOBALS['TSFE']->isGeneratePage()) {
+                       $GLOBALS['TSFE']->generatePage_preProcessing();
+                       $temp_theScript = $GLOBALS['TSFE']->generatePage_whichScript();
+                       if ($temp_theScript) {
+                               include $temp_theScript;
+                       } else {
+                               \TYPO3\CMS\Frontend\Page\PageGenerator::pagegenInit();
+                               // Global content object
+                               $GLOBALS['TSFE']->newCObj();
+                               // LIBRARY INCLUSION, TypoScript
+                               $temp_incFiles = \TYPO3\CMS\Frontend\Page\PageGenerator::getIncFiles();
+                               foreach ($temp_incFiles as $temp_file) {
+                                       include_once './' . $temp_file;
+                               }
+                               // Content generation
+                               if (!$GLOBALS['TSFE']->isINTincScript()) {
+                                       \TYPO3\CMS\Frontend\Page\PageGenerator::renderContent();
+                                       $GLOBALS['TSFE']->setAbsRefPrefix();
+                               }
+                       }
+                       $GLOBALS['TSFE']->generatePage_postProcessing();
+               } elseif ($GLOBALS['TSFE']->isINTincScript()) {
+                       \TYPO3\CMS\Frontend\Page\PageGenerator::pagegenInit();
+                       // Global content object
+                       $GLOBALS['TSFE']->newCObj();
+                       // LIBRARY INCLUSION, TypoScript
+                       $temp_incFiles = \TYPO3\CMS\Frontend\Page\PageGenerator::getIncFiles();
+                       foreach ($temp_incFiles as $temp_file) {
+                               include_once './' . $temp_file;
+                       }
+               }
+               $GLOBALS['TT']->pull();
+
+               // $GLOBALS['TSFE']->config['INTincScript']
+               if ($GLOBALS['TSFE']->isINTincScript()) {
+                       $GLOBALS['TT']->push('Non-cached objects', '');
+                       $GLOBALS['TSFE']->INTincScript();
+                       $GLOBALS['TT']->pull();
+               }
+               // Output content
+               $sendTSFEContent = FALSE;
+               if ($GLOBALS['TSFE']->isOutputting()) {
+                       $GLOBALS['TT']->push('Print Content', '');
+                       $GLOBALS['TSFE']->processOutput();
+                       $sendTSFEContent = TRUE;
+                       $GLOBALS['TT']->pull();
+               }
+               // Store session data for fe_users
+               $GLOBALS['TSFE']->storeSessionData();
+               // Statistics
+               $GLOBALS['TYPO3_MISC']['microtime_end'] = microtime(TRUE);
+               $GLOBALS['TSFE']->setParseTime();
+               if (isset($GLOBALS['TSFE']->config['config']['debug'])) {
+                       $debugParseTime = (bool)$GLOBALS['TSFE']->config['config']['debug'];
+               } else {
+                       $debugParseTime = !empty($GLOBALS['TSFE']->TYPO3_CONF_VARS['FE']['debug']);
+               }
+               if ($GLOBALS['TSFE']->isOutputting() && $debugParseTime) {
+                       $GLOBALS['TSFE']->content .= LF . '<!-- Parsetime: ' . $GLOBALS['TSFE']->scriptParseTime . 'ms -->';
+               }
+               // Check JumpUrl
+               $GLOBALS['TSFE']->jumpurl();
+               // Preview info
+               $GLOBALS['TSFE']->previewInfo();
+               // Hook for end-of-frontend
+               $GLOBALS['TSFE']->hook_eofe();
+               // Finish timetracking
+               $GLOBALS['TT']->pull();
+               // Check memory usage
+               \TYPO3\CMS\Core\Utility\MonitorUtility::peakMemoryUsage();
+               // beLoginLinkIPList
+               echo $GLOBALS['TSFE']->beLoginLinkIPList();
+
+               // Admin panel
+               if (
+                       $GLOBALS['TSFE']->isBackendUserLoggedIn()
+                       && $GLOBALS['BE_USER'] instanceof \TYPO3\CMS\Backend\FrontendBackendUserAuthentication
+                       && $GLOBALS['BE_USER']->isAdminPanelVisible()
+               ) {
+                       $GLOBALS['TSFE']->content = str_ireplace('</head>', $GLOBALS['BE_USER']->adminPanel->getAdminPanelHeaderData() . '</head>', $GLOBALS['TSFE']->content);
+                       $GLOBALS['TSFE']->content = str_ireplace('</body>', $GLOBALS['BE_USER']->displayAdminPanel() . '</body>', $GLOBALS['TSFE']->content);
+               }
+
+               if ($sendTSFEContent) {
+                       echo $GLOBALS['TSFE']->content;
+               }
+               // Debugging Output
+               if (isset($GLOBALS['error']) && is_object($GLOBALS['error']) && @is_callable(array($GLOBALS['error'], 'debugOutput'))) {
+                       $GLOBALS['error']->debugOutput();
+               }
+               if (TYPO3_DLOG) {
+                       GeneralUtility::devLog('END of FRONTEND session', 'cms', 0, array('_FLUSH' => TRUE));
+               }
+       }
+
+       /**
+        * This request handler can handle any frontend request.
+        *
+        * @return bool If the request is not an eID request, TRUE otherwise FALSE
+        */
+       public function canHandleRequest() {
+               return GeneralUtility::_GP('eID') ? FALSE : TRUE;
+       }
+
+       /**
+        * Returns the priority - how eager the handler is to actually handle the
+        * request.
+        *
+        * @return int The priority of the request handler.
+        */
+       public function getPriority() {
+               return 50;
+       }
+}
diff --git a/typo3/sysext/install/Classes/RequestHandler.php b/typo3/sysext/install/Classes/RequestHandler.php
new file mode 100644 (file)
index 0000000..007d511
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+namespace TYPO3\CMS\Install;
+
+/*
+ * 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 TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Core\RequestHandlerInterface;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Default request handler for all requests inside the TYPO3 Install Tool, which does a simple hardcoded
+ * dispatching to a controller based on the get/post variable.
+ *
+ * @package TYPO3\CMS\Install
+ */
+class RequestHandler implements RequestHandlerInterface {
+
+       /**
+        * Instance of the current TYPO3 bootstrap
+        * @var Bootstrap
+        */
+       protected $bootstrap;
+
+       /**
+        * Constructor handing over the bootstrap
+        *
+        * @param Bootstrap $bootstrap
+        */
+       public function __construct(Bootstrap $bootstrap) {
+               $this->bootstrap = $bootstrap;
+       }
+
+       /**
+        * Handles an install tool request
+        * Execute 'tool' or 'step' controller depending on install[controller] GET/POST parameter
+        *
+        * @return void
+        */
+       public function handleRequest() {
+               $getPost = GeneralUtility::_GP('install');
+               switch ($getPost['controller']) {
+                       case 'tool':
+                               $controllerClassName = Controller\ToolController::class;
+                               break;
+                       case 'ajax':
+                               $controllerClassName = Controller\AjaxController::class;
+                               break;
+                       default:
+                               $controllerClassName = Controller\StepController::class;
+               }
+               GeneralUtility::makeInstance($controllerClassName)->execute();
+       }
+
+       /**
+        * This request handler can handle any request when not in CLI mode and the install tool flag is set
+        * please note that both checks are needed, as when in "failsafe" mode, the TYPO3_REQUESTTYPE is not
+        * necessarily set at this point.
+        *
+        * @return bool Returns TRUE if the request is in Install Tool mode, otherwise FALSE
+        */
+       public function canHandleRequest() {
+               return defined('TYPO3_enterInstallScript') || (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_INSTALL);
+       }
+
+       /**
+        * Returns the priority - how eager the handler is to actually handle the request.
+        *
+        * @return int The priority of the request handler.
+        */
+       public function getPriority() {
+               return 20;
+       }
+}
diff --git a/typo3/sysext/install/Resources/Private/PHP/Boot.php b/typo3/sysext/install/Resources/Private/PHP/Boot.php
deleted file mode 100644 (file)
index 4029796..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-namespace TYPO3\CMS\Install;
-
-/*
- * 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!
- */
-
-defined('TYPO3_MODE') or die();
-
-// Bootstrap bare minimum: class loader, LocalConfiguration, but no extensions and such
-require __DIR__ . '/../../../../core/Classes/Core/Bootstrap.php';
-\TYPO3\CMS\Core\Core\Bootstrap::getInstance()
-       ->baseSetup('typo3/sysext/install/Start/')
-       ->startOutputBuffering()
-       ->loadConfigurationAndInitialize(FALSE, \TYPO3\CMS\Core\Package\FailsafePackageManager::class);
-
-// Execute 'tool' or 'step' controller depending on install[controller] GET/POST parameter
-$getPost = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('install');
-$controllerClassName = \TYPO3\CMS\Install\Controller\StepController::class;
-if (isset($getPost['controller'])) {
-       switch ($getPost['controller']) {
-               case 'tool':
-                       $controllerClassName = \TYPO3\CMS\Install\Controller\ToolController::class;
-                       break;
-               case 'ajax':
-                       $controllerClassName = \TYPO3\CMS\Install\Controller\AjaxController::class;
-                       break;
-       }
-}
-\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($controllerClassName)->execute();
\ No newline at end of file
index a014cfe..32eb05d 100644 (file)
@@ -105,9 +105,6 @@ if (version_compare(PHP_VERSION, '5.5.0', '<')) {
 define('TYPO3_MODE', 'BE');
 define('TYPO3_enterInstallScript', '1');
 
 define('TYPO3_MODE', 'BE');
 define('TYPO3_enterInstallScript', '1');
 
-/*
- * The following functionality must be required from another file, otherwise a parse error
- * "unexpected 'class'" will be shown on PHP 5.4 instead of the die() from version_compare above.
- */
-require __DIR__ . '/../Resources/Private/PHP/Boot.php';
-
+// Bootstrap bare minimum: class loader, LocalConfiguration, but no extensions and such
+require __DIR__ . '/../../core/Classes/Core/Bootstrap.php';
+\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->run('typo3/sysext/install/Start/')->shutdown();