ac11642e187faf627de227a924f4de9ea14e5eeb
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Http / AjaxRequestHandler.php
1 <?php
2 namespace TYPO3\CMS\Backend\Http;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Core\Bootstrap;
18 use TYPO3\CMS\Core\Core\RequestHandlerInterface;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20
21 /**
22 * Base class for all AJAX-related calls for the TYPO3 Backend run through typo3/ajax.php.
23 * Before doing the basic BE-related set up of this request (see the additional calls on $this->bootstrap inside
24 * handleRequest()), some AJAX-calls can be made without a valid user, which is determined here.
25 *
26 * Due to legacy reasons, the actual logic is in EXT:core/Http/AjaxRequestHandler which will eventually
27 * be moved into this class.
28 * In the future, the logic for "TYPO3_PROCEED_IF_NO_USER" will be moved in here as well.
29 */
30 class AjaxRequestHandler implements RequestHandlerInterface {
31
32 /**
33 * Instance of the current TYPO3 bootstrap
34 * @var Bootstrap
35 */
36 protected $bootstrap;
37
38 /**
39 * List of requests that don't need a valid BE user
40 * @var array
41 */
42 protected $publicAjaxIds = array(
43 'BackendLogin::login',
44 'BackendLogin::logout',
45 'BackendLogin::refreshLogin',
46 'BackendLogin::isTimedOut',
47 'BackendLogin::getChallenge',
48 'BackendLogin::getRsaPublicKey'
49 );
50
51 /**
52 * Constructor handing over the bootstrap
53 *
54 * @param Bootstrap $bootstrap
55 */
56 public function __construct(Bootstrap $bootstrap) {
57 $this->bootstrap = $bootstrap;
58 }
59
60 /**
61 * Handles any AJAX request in the TYPO3 Backend
62 *
63 * @return void
64 */
65 public function handleRequest() {
66 // First get the ajaxID
67 $ajaxID = isset($_POST['ajaxID']) ? $_POST['ajaxID'] : $_GET['ajaxID'];
68 if (isset($ajaxID)) {
69 $ajaxID = (string)stripslashes($ajaxID);
70 }
71
72 $GLOBALS['ajaxID'] = $ajaxID;
73 $this->boot($ajaxID);
74
75 // Finding the script path from the registry
76 $ajaxRegistryEntry = isset($GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'][$ajaxID]) ? $GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'][$ajaxID] : NULL;
77 $ajaxScript = NULL;
78 $csrfTokenCheck = FALSE;
79 if ($ajaxRegistryEntry !== NULL && is_array($ajaxRegistryEntry) && isset($ajaxRegistryEntry['callbackMethod'])) {
80 $ajaxScript = $ajaxRegistryEntry['callbackMethod'];
81 $csrfTokenCheck = $ajaxRegistryEntry['csrfTokenCheck'];
82 }
83
84 // Instantiating the AJAX object
85 $ajaxObj = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Http\AjaxRequestHandler::class, $ajaxID);
86 $ajaxParams = array();
87
88 // Evaluating the arguments and calling the AJAX method/function
89 if (empty($ajaxID)) {
90 $ajaxObj->setError('No valid ajaxID parameter given.');
91 } elseif (empty($ajaxScript)) {
92 $ajaxObj->setError('No backend function registered for ajaxID "' . $ajaxID . '".');
93 } else {
94 $success = TRUE;
95 $tokenIsValid = TRUE;
96 if ($csrfTokenCheck) {
97 $tokenIsValid = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get()->validateToken(GeneralUtility::_GP('ajaxToken'), 'ajaxCall', $ajaxID);
98 }
99 if ($tokenIsValid) {
100 // Cleanup global variable space
101 unset($csrfTokenCheck, $ajaxRegistryEntry, $tokenIsValid, $success);
102 $success = GeneralUtility::callUserFunction($ajaxScript, $ajaxParams, $ajaxObj, FALSE, TRUE);
103 } else {
104 $ajaxObj->setError('Invalid CSRF token detected for ajaxID "' . $ajaxID . '"!');
105 }
106 if ($success === FALSE) {
107 $ajaxObj->setError('Registered backend function for ajaxID "' . $ajaxID . '" was not found.');
108 }
109 }
110
111 // Outputting the content (and setting the X-JSON-Header)
112 $ajaxObj->render();
113 }
114
115 /**
116 * This request handler can handle any backend request coming from ajax.php
117 *
118 * @return bool If the request is an AJAX backend request, TRUE otherwise FALSE
119 */
120 public function canHandleRequest() {
121 return TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX;
122 }
123
124 /**
125 * Returns the priority - how eager the handler is to actually handle the request.
126 *
127 * @return int The priority of the request handler.
128 */
129 public function getPriority() {
130 return 80;
131 }
132
133 /**
134 * Start the Backend bootstrap part
135 *
136 * @param string $ajaxId Contains the string of the ajaxId used
137 */
138 protected function boot($ajaxId) {
139 // If we're trying to do an ajax login, don't require a user
140 $proceedIfNoUserIsLoggedIn = in_array($ajaxId, $this->publicAjaxIds, TRUE);
141
142 $this->bootstrap
143 ->checkLockedBackendAndRedirectOrDie($proceedIfNoUserIsLoggedIn)
144 ->checkBackendIpOrDie()
145 ->checkSslBackendAndRedirectIfNeeded()
146 ->checkValidBrowserOrDie()
147 ->loadExtensionTables(TRUE)
148 ->initializeSpriteManager()
149 ->initializeBackendUser()
150 ->initializeBackendAuthentication($proceedIfNoUserIsLoggedIn)
151 ->initializeLanguageObject()
152 ->initializeBackendTemplate()
153 ->endOutputBufferingAndCleanPreviousOutput()
154 ->initializeOutputCompression()
155 ->sendHttpHeaders();
156 }
157 }