‪TYPO3CMS  10.4
SystemEnvironmentBuilder.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
16 namespace ‪TYPO3\CMS\Core\Core;
17 
21 
42 {
44  const ‪REQUESTTYPE_FE = 1;
46  const ‪REQUESTTYPE_BE = 2;
48  const ‪REQUESTTYPE_CLI = 4;
53 
62  public static function ‪run(int $entryPointLevel = 0, int $requestType = self::REQUESTTYPE_FE)
63  {
66  ‪self::setRequestType($requestType | ($requestType === self::REQUESTTYPE_BE && strpos($_REQUEST['route'] ?? '', '/ajax/') === 0 ? TYPO3_REQUESTTYPE_AJAX : 0));
67  ‪self::defineLegacyConstants($requestType === self::REQUESTTYPE_FE ? 'FE' : 'BE');
68  $scriptPath = ‪self::calculateScriptPath($entryPointLevel, $requestType);
69  $rootPath = ‪self::calculateRootPath($entryPointLevel, $requestType);
70 
73  ‪self::initializeEnvironment($requestType, $scriptPath, $rootPath);
74  }
75 
85  {
86  $applicationContext = getenv('TYPO3_CONTEXT') ?: (getenv('REDIRECT_TYPO3_CONTEXT') ?: (getenv('HTTP_TYPO3_CONTEXT') ?: 'Production'));
87  return new ‪ApplicationContext($applicationContext);
88  }
89 
93  protected static function ‪defineBaseConstants()
94  {
95  // Check one of the constants and return early if already defined,
96  // needed if multiple requests are handled in one process, for instance in functional testing.
97  // This check can be removed in TYPO3 v11.0.
98  if (defined('FILE_DENY_PATTERN_DEFAULT')) {
99  return;
100  }
101 
102  // A linefeed, a carriage return, a CR-LF combination
103  defined('LF') ?: define('LF', chr(10));
104  defined('CR') ?: define('CR', chr(13));
105  defined('CRLF') ?: define('CRLF', CR . LF);
106 
107  // A generic constant to state we are in TYPO3 scope. This is especially used in script files
108  // like ext_localconf.php that run in global scope without class encapsulation: "defined('TYPO3') or die();"
109  // This is a security measure to prevent script output if those files are located within document root and
110  // called directly without bootstrap and error handling setup.
111  defined('TYPO3') ?: define('TYPO3', true);
112 
113  // Relative path from document root to typo3/ directory, hardcoded to "typo3/"
114  if (!defined('TYPO3_mainDir')) {
115  define('TYPO3_mainDir', 'typo3/');
116  }
117 
121  define('FILE_DENY_PATTERN_DEFAULT', ‪FileNameValidator::DEFAULT_FILE_DENY_PATTERN);
125  define('PHP_EXTENSIONS_DEFAULT', 'php,php3,php4,php5,php6,php7,php8,phpsh,inc,phtml,pht,phar');
129  define('TYPO3_copyright_year', '1998-' . date('Y'));
133  define('TYPO3_URL_GENERAL', 'https://typo3.org/');
137  define('TYPO3_URL_LICENSE', 'https://typo3.org/project/licenses/');
141  define('TYPO3_URL_EXCEPTION', 'https://typo3.org/go/exception/CMS/');
145  define('TYPO3_URL_DONATE', 'https://typo3.org/community/contribute/donate/');
149  define('TYPO3_URL_WIKI_OPCODECACHE', 'https://docs.typo3.org/m/typo3/guide-installation/master/en-us/Troubleshooting/Index.html#opcode-cache-messages');
150  }
151 
161  protected static function ‪calculateScriptPath(int $entryPointLevel, int $requestType): string
162  {
163  $isCli = ‪self::isCliRequestType($requestType);
164  // Absolute path of the entry script that was called
165  $scriptPath = GeneralUtility::fixWindowsFilePath(self::getPathThisScript($isCli));
166  $rootPath = ‪self::getRootPathFromScriptPath($scriptPath, $entryPointLevel);
167  // Check if the root path has been set in the environment (e.g. by the composer installer)
168  if (getenv('TYPO3_PATH_ROOT')) {
169  if ($isCli && self::usesComposerClassLoading()) {
170  // $scriptPath is used for various path calculations based on the document root
171  // Therefore we assume it is always a subdirectory of the document root, which is not the case
172  // in composer mode on cli, as the binary is in the composer bin directory.
173  // Because of that, we enforce the document root path of this binary to be set
174  $scriptName = 'typo3/sysext/core/bin/typo3';
175  } else {
176  // Base the script path on the path taken from the environment
177  // to make relative path calculations work in case only one of both is symlinked
178  // or has the real path
179  $scriptName = ltrim(substr($scriptPath, strlen($rootPath)), '/');
180  }
181  $rootPath = rtrim(GeneralUtility::fixWindowsFilePath((string)getenv('TYPO3_PATH_ROOT')), '/');
182  $scriptPath = $rootPath . '/' . $scriptName;
183  }
184  return $scriptPath;
185  }
186 
201  protected static function ‪calculateRootPath(int $entryPointLevel, int $requestType): string
202  {
203  // Check if the root path has been set in the environment (e.g. by the composer installer)
204  if (getenv('TYPO3_PATH_ROOT')) {
205  return rtrim(GeneralUtility::fixWindowsFilePath((string)getenv('TYPO3_PATH_ROOT')), '/');
206  }
207  $isCli = ‪self::isCliRequestType($requestType);
208  // Absolute path of the entry script that was called
209  $scriptPath = GeneralUtility::fixWindowsFilePath(self::getPathThisScript($isCli));
210  return ‪self::getRootPathFromScriptPath($scriptPath, $entryPointLevel);
211  }
212 
216  protected static function ‪initializeGlobalVariables()
217  {
218  // Unset variable(s) in global scope (security issue #13959)
219  ‪$GLOBALS['T3_SERVICES'] = [];
220  }
221 
226  protected static function ‪initializeGlobalTimeTrackingVariables()
227  {
228  // EXEC_TIME is set so that the rest of the script has a common value for the script execution time
229  ‪$GLOBALS['EXEC_TIME'] = time();
230  // $ACCESS_TIME is a common time in minutes for access control
231  ‪$GLOBALS['ACCESS_TIME'] = ‪$GLOBALS['EXEC_TIME'] - ‪$GLOBALS['EXEC_TIME'] % 60;
232  // $SIM_EXEC_TIME is set to $EXEC_TIME but can be altered later in the script if we want to
233  // simulate another execution-time when selecting from eg. a database
234  ‪$GLOBALS['SIM_EXEC_TIME'] = ‪$GLOBALS['EXEC_TIME'];
235  // If $SIM_EXEC_TIME is changed this value must be set accordingly
236  ‪$GLOBALS['SIM_ACCESS_TIME'] = ‪$GLOBALS['ACCESS_TIME'];
237  }
238 
246  protected static function ‪initializeEnvironment(int $requestType, string $scriptPath, string $sitePath)
247  {
248  if (getenv('TYPO3_PATH_ROOT')) {
249  $rootPathFromEnvironment = rtrim(GeneralUtility::fixWindowsFilePath((string)getenv('TYPO3_PATH_ROOT')), '/');
250  if ($sitePath !== $rootPathFromEnvironment) {
251  // This means, that we re-initialized the environment during a single request
252  // This currently only happens in custom code or during functional testing
253  // Once the constants are removed, we might be able to remove this code here as well and directly pass an environment to the application
254  $scriptPath = $rootPathFromEnvironment . substr($scriptPath, strlen($sitePath));
255  $sitePath = $rootPathFromEnvironment;
256  }
257  }
258 
259  $projectRootPath = GeneralUtility::fixWindowsFilePath((string)getenv('TYPO3_PATH_APP'));
260  $isDifferentRootPath = ($projectRootPath && $projectRootPath !== $sitePath);
262  static::createApplicationContext(),
263  self::isCliRequestType($requestType),
264  self::usesComposerClassLoading(),
265  $isDifferentRootPath ? $projectRootPath : $sitePath,
266  $sitePath,
267  $isDifferentRootPath ? $projectRootPath . '/var' : $sitePath . '/typo3temp/var',
268  $isDifferentRootPath ? $projectRootPath . '/config' : $sitePath . '/typo3conf',
269  $scriptPath,
270  self::isRunningOnWindows() ? 'WINDOWS' : 'UNIX'
271  );
272  }
273 
277  protected static function ‪isRunningOnWindows(): bool
278  {
279  return stripos(PHP_OS, 'darwin') === false
280  && stripos(PHP_OS, 'cygwin') === false
281  && stripos(PHP_OS, 'win') !== false;
282  }
283 
299  protected static function ‪getPathThisScript(bool $isCli)
300  {
301  if ($isCli) {
303  }
305  }
306 
312  protected static function ‪getPathThisScriptNonCli()
313  {
315  throw new \Exception('TYPO3 does only support being used with cgi.fix_pathinfo=1 on CGI server APIs.', 1675108421);
316  }
317 
318  return $_SERVER['SCRIPT_FILENAME'];
319  }
320 
329  protected static function ‪getPathThisScriptCli()
330  {
331  // Possible relative path of the called script
332  $scriptPath = $_SERVER['argv'][0] ?? $_ENV['_'] ?? $_SERVER['_'];
333  // Find out if path is relative or not
334  $isRelativePath = false;
335  if (self::isRunningOnWindows()) {
336  if (!preg_match('/^([a-zA-Z]:)?\\\\/', $scriptPath)) {
337  $isRelativePath = true;
338  }
339  } elseif ($scriptPath[0] !== '/') {
340  $isRelativePath = true;
341  }
342  // Concatenate path to current working directory with relative path and remove "/./" constructs
343  if ($isRelativePath) {
344  $workingDirectory = $_SERVER['PWD'] ?? getcwd();
345  $scriptPath = $workingDirectory . '/' . preg_replace('/\\.\\//', '', $scriptPath);
346  }
347  return $scriptPath;
348  }
349 
365  protected static function ‪getRootPathFromScriptPath($scriptPath, $entryPointLevel)
366  {
367  $entryScriptDirectory = ‪PathUtility::dirnameDuringBootstrap($scriptPath);
368  if ($entryPointLevel > 0) {
369  [$rootPath] = ‪GeneralUtility::revExplode('/', $entryScriptDirectory, $entryPointLevel + 1);
370  } else {
371  $rootPath = $entryScriptDirectory;
372  }
373  return $rootPath;
374  }
375 
379  protected static function ‪usesComposerClassLoading(): bool
380  {
381  return defined('TYPO3_COMPOSER_MODE') && TYPO3_COMPOSER_MODE;
382  }
383 
388  protected static function ‪defineTypo3RequestTypes()
389  {
390  // Check one of the constants and return early if already defined,
391  // needed if multiple requests are handled in one process, for instance in functional testing.
392  if (defined('TYPO3_REQUESTTYPE_FE')) {
393  return;
394  }
395  define('TYPO3_REQUESTTYPE_FE', self::REQUESTTYPE_FE);
396  define('TYPO3_REQUESTTYPE_BE', self::REQUESTTYPE_BE);
397  define('TYPO3_REQUESTTYPE_CLI', self::REQUESTTYPE_CLI);
398  define('TYPO3_REQUESTTYPE_AJAX', self::REQUESTTYPE_AJAX);
399  define('TYPO3_REQUESTTYPE_INSTALL', self::REQUESTTYPE_INSTALL);
400  }
401 
407  protected static function ‪setRequestType(int $requestType)
408  {
409  // Return early if already defined,
410  // needed if multiple requests are handled in one process, for instance in functional testing.
411  if (defined('TYPO3_REQUESTTYPE')) {
412  return;
413  }
414  define('TYPO3_REQUESTTYPE', $requestType);
415  }
416 
422  protected static function ‪defineLegacyConstants(string $mode)
423  {
424  // Return early if already defined,
425  // needed if multiple requests are handled in one process, for instance in functional testing.
426  if (defined('TYPO3_MODE')) {
427  return;
428  }
429  define('TYPO3_MODE', $mode);
430  }
431 
439  protected static function ‪isCliRequestType(?int $requestType): bool
440  {
441  if ($requestType === null) {
442  $requestType = PHP_SAPI === 'cli' ? ‪self::REQUESTTYPE_CLI : ‪self::REQUESTTYPE_FE;
443  }
444 
445  return ($requestType & self::REQUESTTYPE_CLI) === ‪self::REQUESTTYPE_CLI;
446  }
447 }
‪TYPO3\CMS\Core\Resource\Security\FileNameValidator\DEFAULT_FILE_DENY_PATTERN
‪const DEFAULT_FILE_DENY_PATTERN
Definition: FileNameValidator.php:29
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\calculateRootPath
‪static string calculateRootPath(int $entryPointLevel, int $requestType)
Definition: SystemEnvironmentBuilder.php:201
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:24
‪TYPO3\CMS\Core\Core\Environment\isRunningOnCgiServer
‪static bool isRunningOnCgiServer()
Definition: Environment.php:312
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\isCliRequestType
‪static bool isCliRequestType(?int $requestType)
Definition: SystemEnvironmentBuilder.php:439
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\usesComposerClassLoading
‪static bool usesComposerClassLoading()
Definition: SystemEnvironmentBuilder.php:379
‪TYPO3\CMS\Core\Core\ApplicationContext
Definition: ApplicationContext.php:37
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\getRootPathFromScriptPath
‪static string getRootPathFromScriptPath($scriptPath, $entryPointLevel)
Definition: SystemEnvironmentBuilder.php:365
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\initializeGlobalTimeTrackingVariables
‪static initializeGlobalTimeTrackingVariables()
Definition: SystemEnvironmentBuilder.php:226
‪TYPO3\CMS\Core\Resource\Security\FileNameValidator
Definition: FileNameValidator.php:25
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder
Definition: SystemEnvironmentBuilder.php:42
‪TYPO3\CMS\Core\Utility\PathUtility\dirnameDuringBootstrap
‪static string dirnameDuringBootstrap($path)
Definition: PathUtility.php:276
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\REQUESTTYPE_BE
‪const REQUESTTYPE_BE
Definition: SystemEnvironmentBuilder.php:46
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\defineTypo3RequestTypes
‪static defineTypo3RequestTypes()
Definition: SystemEnvironmentBuilder.php:388
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\createApplicationContext
‪static ApplicationContext createApplicationContext()
Definition: SystemEnvironmentBuilder.php:84
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\setRequestType
‪static setRequestType(int $requestType)
Definition: SystemEnvironmentBuilder.php:407
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\calculateScriptPath
‪static string calculateScriptPath(int $entryPointLevel, int $requestType)
Definition: SystemEnvironmentBuilder.php:161
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\getPathThisScriptNonCli
‪static string getPathThisScriptNonCli()
Definition: SystemEnvironmentBuilder.php:312
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\defineBaseConstants
‪static defineBaseConstants()
Definition: SystemEnvironmentBuilder.php:93
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\REQUESTTYPE_CLI
‪const REQUESTTYPE_CLI
Definition: SystemEnvironmentBuilder.php:48
‪TYPO3\CMS\Core\Core\Environment\usesCgiFixPathInfo
‪static usesCgiFixPathInfo()
Definition: Environment.php:317
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\initializeGlobalVariables
‪static initializeGlobalVariables()
Definition: SystemEnvironmentBuilder.php:216
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\isRunningOnWindows
‪static isRunningOnWindows()
Definition: SystemEnvironmentBuilder.php:277
‪TYPO3\CMS\Core\Core\Environment\initialize
‪static initialize(ApplicationContext $context, bool $cli, bool $composerMode, string $projectPath, string $publicPath, string $varPath, string $configPath, string $currentScript, string $os)
Definition: Environment.php:104
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\run
‪static run(int $entryPointLevel=0, int $requestType=self::REQUESTTYPE_FE)
Definition: SystemEnvironmentBuilder.php:62
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\getPathThisScriptCli
‪static string getPathThisScriptCli()
Definition: SystemEnvironmentBuilder.php:329
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\getPathThisScript
‪static string getPathThisScript(bool $isCli)
Definition: SystemEnvironmentBuilder.php:299
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\REQUESTTYPE_AJAX
‪const REQUESTTYPE_AJAX
Definition: SystemEnvironmentBuilder.php:50
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Utility\GeneralUtility\revExplode
‪static string[] revExplode($delimiter, $string, $count=0)
Definition: GeneralUtility.php:1025
‪TYPO3\CMS\Core\Core
Definition: ApplicationContext.php:16
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\REQUESTTYPE_FE
‪const REQUESTTYPE_FE
Definition: SystemEnvironmentBuilder.php:44
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\defineLegacyConstants
‪static defineLegacyConstants(string $mode)
Definition: SystemEnvironmentBuilder.php:422
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\REQUESTTYPE_INSTALL
‪const REQUESTTYPE_INSTALL
Definition: SystemEnvironmentBuilder.php:52
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\initializeEnvironment
‪static initializeEnvironment(int $requestType, string $scriptPath, string $sitePath)
Definition: SystemEnvironmentBuilder.php:246