‪TYPO3CMS  ‪main
FilePathSanitizer.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
27 
39 {
47  protected ‪$allowedPaths = [];
48 
52  public function ‪__construct()
53  {
54  $this->allowedPaths = [
55  '_assets/',
56  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'],
57  'uploads/',
58  'typo3temp/',
61  ];
62  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['addAllowedPaths'])) {
63  $paths = ‪GeneralUtility::trimExplode(',', ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['addAllowedPaths'], true);
64  foreach ($paths as $path) {
65  if (is_string($path)) {
66  $this->allowedPaths[] = $path;
67  }
68  }
69  }
70  }
71 
77  public function ‪sanitize(string $originalFileName, ?bool $allowExtensionPath = null): string
78  {
79  if ($allowExtensionPath === false) {
80  throw new \BadMethodCallException('$allowAbsolutePaths must be either omitted or set to true', 1633671654);
81  }
82  $file = trim($originalFileName);
83  if (empty($file)) {
84  throw new ‪InvalidFileNameException('Empty file name given', 1530169746);
85  }
86  if (str_contains($file, '../')) {
87  throw new ‪InvalidPathException('File path "' . $file . '" contains illegal string "../"', 1530169814);
88  }
89  // if this is an URL, it can be returned directly
90  $urlScheme = parse_url($file, PHP_URL_SCHEME);
91  if ($urlScheme === 'https' || $urlScheme === 'http' || is_file(‪Environment::getPublicPath() . '/' . $file)) {
92  return $file;
93  }
94 
95  // this call also resolves EXT:myext/ files
96  $absolutePath = GeneralUtility::getFileAbsFileName($file);
97  if (!$absolutePath || is_dir($absolutePath)) {
98  throw new ‪FileDoesNotExistException('File "' . $file . '" was not found', 1530169845);
99  }
100 
101  $isExtensionPath = ‪PathUtility::isExtensionPath($file);
102  if ($allowExtensionPath && $isExtensionPath) {
103  return $file;
104  }
105  $relativePath = $this->‪makeRelative($absolutePath, $file, $isExtensionPath);
106 
107  // Check if the found file is in the allowed paths
108  foreach ($this->allowedPaths as $allowedPath) {
109  if (str_starts_with($relativePath, $allowedPath)) {
110  return $relativePath;
111  }
112  }
113  throw new ‪InvalidFileException('"' . $relativePath . '" is not located in the allowed paths', 1530169955);
114  }
115 
116  private function ‪makeRelative(string $absoluteFilePath, string $originalFilePath, bool $isExtensionPath): string
117  {
118  if ($isExtensionPath) {
119  return ‪PathUtility::getPublicResourceWebPath($originalFilePath, false);
120  }
121 
122  if (!str_starts_with($absoluteFilePath, ‪Environment::getPublicPath())) {
123  throw new ‪InvalidFileException('"' . $originalFilePath . '" is expected to be in public directory, but is not', 1633674049);
124  }
125 
126  return ‪PathUtility::stripPathSitePrefix($absoluteFilePath);
127  }
128 }
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static stripPathSitePrefix(string $path)
Definition: PathUtility.php:428
‪TYPO3\CMS\Core\Utility\PathUtility\isExtensionPath
‪static isExtensionPath(string $path)
Definition: PathUtility.php:117
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:27
‪TYPO3\CMS\Frontend\Resource
Definition: FileCollector.php:18
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static getPublicPath()
Definition: Environment.php:187
‪TYPO3\CMS\Frontend\Resource\FilePathSanitizer
Definition: FilePathSanitizer.php:39
‪TYPO3\CMS\Core\Core\Environment\getExtensionsPath
‪static getExtensionsPath()
Definition: Environment.php:253
‪TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException
Definition: FileDoesNotExistException.php:21
‪TYPO3\CMS\Frontend\Resource\FilePathSanitizer\$allowedPaths
‪array $allowedPaths
Definition: FilePathSanitizer.php:46
‪TYPO3\CMS\Core\Utility\PathUtility\getPublicResourceWebPath
‪static getPublicResourceWebPath(string $resourcePath, bool $prefixWithSitePath=true)
Definition: PathUtility.php:97
‪TYPO3\CMS\Frontend\Resource\FilePathSanitizer\__construct
‪__construct()
Definition: FilePathSanitizer.php:51
‪TYPO3\CMS\Core\Resource\Exception\InvalidFileException
Definition: InvalidFileException.php:23
‪TYPO3\CMS\Frontend\Resource\FilePathSanitizer\makeRelative
‪makeRelative(string $absoluteFilePath, string $originalFilePath, bool $isExtensionPath)
Definition: FilePathSanitizer.php:115
‪TYPO3\CMS\Core\Core\Environment\getFrameworkBasePath
‪static getFrameworkBasePath()
Definition: Environment.php:245
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Resource\Exception\InvalidPathException
Definition: InvalidPathException.php:23
‪TYPO3\CMS\Core\Resource\Exception\InvalidFileNameException
Definition: InvalidFileNameException.php:23
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode(string $delim, string $string, bool $removeEmptyValues=false, int $limit=0)
Definition: GeneralUtility.php:822
‪TYPO3\CMS\Frontend\Resource\FilePathSanitizer\sanitize
‪string sanitize(string $originalFileName, ?bool $allowExtensionPath=null)
Definition: FilePathSanitizer.php:76