‪TYPO3CMS  10.4
SimpleFileBackend.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 
17 
27 
33 {
34  const ‪SEPARATOR = '^';
35  const ‪EXPIRYTIME_FORMAT = 'YmdHis';
37  const ‪DATASIZE_DIGITS = 10;
43  protected ‪$cacheDirectory = '';
44 
53  protected ‪$temporaryCacheDirectory = '';
54 
60  protected ‪$cacheEntryFileExtension = '';
61 
65  protected ‪$cacheEntryIdentifiers = [];
66 
70  protected ‪$frozen = false;
71 
80  {
81  parent::setCache(‪$cache);
82  if (empty($this->temporaryCacheDirectory)) {
83  // If no cache directory was given with cacheDirectory
84  // configuration option, set it to a path below var/ folder
86  } else {
88  }
89  $codeOrData = ‪$cache instanceof ‪PhpFrontend ? 'code' : 'data';
90  $finalCacheDirectory = ‪$temporaryCacheDirectory . 'cache/' . $codeOrData . '/' . $this->cacheIdentifier . '/';
91  if (!is_dir($finalCacheDirectory)) {
92  $this->‪createFinalCacheDirectory($finalCacheDirectory);
93  }
94  unset($this->temporaryCacheDirectory);
95  $this->cacheDirectory = $finalCacheDirectory;
96  $this->cacheEntryFileExtension = ‪$cache instanceof ‪PhpFrontend ? '.php' : '';
97  if (strlen($this->cacheDirectory) + 23 > PHP_MAXPATHLEN) {
98  throw new ‪Exception('The length of the temporary cache file path "' . $this->cacheDirectory . '" exceeds the maximum path length of ' . (PHP_MAXPATHLEN - 23) . '. Please consider setting the temporaryDirectoryBase option to a shorter path.', 1248710426);
99  }
100  }
101 
116  {
117  // Skip handling if directory is a stream resource
118  // This is used by unit tests with vfs:// directories
119  if (strpos(‪$cacheDirectory, '://')) {
120  $this->temporaryCacheDirectory = ‪$cacheDirectory;
121  return;
122  }
123  $documentRoot = ‪Environment::getProjectPath() . '/';
124  if ($open_basedir = ini_get('open_basedir')) {
126  $delimiter = ';';
127  ‪$cacheDirectory = str_replace('\\', '/', ‪$cacheDirectory);
128  if (!preg_match('/[A-Z]:/', substr(‪$cacheDirectory, 0, 2))) {
130  }
131  } else {
132  $delimiter = ':';
133  if (‪$cacheDirectory[0] !== '/') {
134  // relative path to cache directory.
136  }
137  }
138  $basedirs = explode($delimiter, $open_basedir);
139  $cacheDirectoryInBaseDir = false;
140  foreach ($basedirs as $basedir) {
142  $basedir = str_replace('\\', '/', $basedir);
143  }
144  if ($basedir[strlen($basedir) - 1] !== '/') {
145  $basedir .= '/';
146  }
147  if (GeneralUtility::isFirstPartOfStr(‪$cacheDirectory, $basedir)) {
148  $documentRoot = $basedir;
149  ‪$cacheDirectory = str_replace($basedir, '', ‪$cacheDirectory);
150  $cacheDirectoryInBaseDir = true;
151  break;
152  }
153  }
154  if (!$cacheDirectoryInBaseDir) {
155  throw new Exception(
156  'Open_basedir restriction in effect. The directory "' . ‪$cacheDirectory . '" is not in an allowed path.',
157  1476045417
158  );
159  }
160  } else {
161  if (‪$cacheDirectory[0] === '/') {
162  // Absolute path to cache directory.
163  $documentRoot = '';
164  }
166  if (!empty($documentRoot) && strpos(‪$cacheDirectory, $documentRoot) === 0) {
167  $documentRoot = '';
168  }
169  }
170  }
171  // After this point all paths have '/' as directory separator
172  if (‪$cacheDirectory[strlen(‪$cacheDirectory) - 1] !== '/') {
173  ‪$cacheDirectory .= '/';
174  }
175  $this->temporaryCacheDirectory = $documentRoot . ‪$cacheDirectory;
176  }
177 
184  protected function ‪createFinalCacheDirectory($finalCacheDirectory)
185  {
186  try {
187  ‪GeneralUtility::mkdir_deep($finalCacheDirectory);
188  } catch (\RuntimeException $e) {
189  throw new Exception('The directory "' . $finalCacheDirectory . '" can not be created.', 1303669848, $e);
190  }
191  if (!is_writable($finalCacheDirectory)) {
192  throw new Exception('The directory "' . $finalCacheDirectory . '" is not writable.', 1203965200);
193  }
194  }
195 
201  public function ‪getCacheDirectory()
202  {
204  }
205 
217  public function set($entryIdentifier, $data, array $tags = [], $lifetime = null)
218  {
219  if (!is_string($data)) {
220  throw new InvalidDataException('The specified data is of type "' . gettype($data) . '" but a string is expected.', 1334756734);
221  }
222  if ($entryIdentifier !== ‪PathUtility::basename($entryIdentifier)) {
223  throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1334756735);
224  }
225  if ($entryIdentifier === '') {
226  throw new \InvalidArgumentException('The specified entry identifier must not be empty.', 1334756736);
227  }
228  $temporaryCacheEntryPathAndFilename = $this->cacheDirectory . ‪StringUtility::getUniqueId() . '.temp';
229  $result = file_put_contents($temporaryCacheEntryPathAndFilename, $data);
230  ‪GeneralUtility::fixPermissions($temporaryCacheEntryPathAndFilename);
231  if ($result === false) {
232  throw new Exception('The temporary cache file "' . $temporaryCacheEntryPathAndFilename . '" could not be written.', 1334756737);
233  }
234  $cacheEntryPathAndFilename = $this->cacheDirectory . $entryIdentifier . ‪$this->cacheEntryFileExtension;
235  rename($temporaryCacheEntryPathAndFilename, $cacheEntryPathAndFilename);
236  if ($this->cacheEntryFileExtension === '.php') {
237  GeneralUtility::makeInstance(OpcodeCacheService::class)->clearAllActive($cacheEntryPathAndFilename);
238  }
239  }
240 
248  public function get($entryIdentifier)
249  {
250  if ($entryIdentifier !== ‪PathUtility::basename($entryIdentifier)) {
251  throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1334756877);
252  }
253  $pathAndFilename = $this->cacheDirectory . $entryIdentifier . ‪$this->cacheEntryFileExtension;
254  if (!file_exists($pathAndFilename)) {
255  return false;
256  }
257  return file_get_contents($pathAndFilename);
258  }
259 
267  public function ‪has($entryIdentifier)
268  {
269  if ($entryIdentifier !== ‪PathUtility::basename($entryIdentifier)) {
270  throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1334756878);
271  }
272  return file_exists($this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension);
273  }
274 
283  public function remove($entryIdentifier)
284  {
285  if ($entryIdentifier !== ‪PathUtility::basename($entryIdentifier)) {
286  throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1334756960);
287  }
288  if ($entryIdentifier === '') {
289  throw new \InvalidArgumentException('The specified entry identifier must not be empty.', 1334756961);
290  }
291  return @unlink($this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension);
292  }
293 
300  public function ‪flush()
301  {
302  $directory = ‪$this->cacheDirectory;
303  if (is_link($directory)) {
304  // Avoid attempting to rename the symlink see #87367
305  $directory = (string)realpath($directory);
306  }
307 
308  if (is_dir($directory)) {
309  $temporaryDirectory = rtrim($directory, '/') . '.' . ‪StringUtility::getUniqueId('remove');
310  if (rename($directory, $temporaryDirectory)) {
311  ‪GeneralUtility::mkdir($directory);
312  clearstatcache();
313  ‪GeneralUtility::rmdir($temporaryDirectory, true);
314  }
315  }
316  }
317 
325  protected function ‪isCacheFileExpired($cacheEntryPathAndFilename)
326  {
327  return file_exists($cacheEntryPathAndFilename) === false;
328  }
329 
333  public function ‪collectGarbage()
334  {
335  }
336 
343  protected function ‪findCacheFilesByIdentifier($entryIdentifier)
344  {
345  $pathAndFilename = $this->cacheDirectory . $entryIdentifier . ‪$this->cacheEntryFileExtension;
346  return file_exists($pathAndFilename) ? [$pathAndFilename] : false;
347  }
348 
356  public function ‪requireOnce($entryIdentifier)
357  {
358  $pathAndFilename = $this->cacheDirectory . $entryIdentifier . ‪$this->cacheEntryFileExtension;
359  if ($entryIdentifier !== ‪PathUtility::basename($entryIdentifier)) {
360  throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1282073037);
361  }
362  return file_exists($pathAndFilename) ? require_once $pathAndFilename : false;
363  }
364 
372  public function require(string $entryIdentifier)
373  {
374  $pathAndFilename = $this->cacheDirectory . $entryIdentifier . ‪$this->cacheEntryFileExtension;
375  if ($entryIdentifier !== ‪PathUtility::basename($entryIdentifier)) {
376  throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1532528267);
377  }
378  return file_exists($pathAndFilename) ? require $pathAndFilename : false;
379  }
380 }
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\flush
‪flush()
Definition: SimpleFileBackend.php:295
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:24
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\$cacheEntryFileExtension
‪string $cacheEntryFileExtension
Definition: SimpleFileBackend.php:57
‪TYPO3\CMS\Core\Cache\Frontend\PhpFrontend
Definition: PhpFrontend.php:25
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\$cacheDirectory
‪string $cacheDirectory
Definition: SimpleFileBackend.php:42
‪TYPO3\CMS\Core\Core\Environment\isWindows
‪static bool isWindows()
Definition: Environment.php:292
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\has
‪bool has($entryIdentifier)
Definition: SimpleFileBackend.php:262
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\createFinalCacheDirectory
‪createFinalCacheDirectory($finalCacheDirectory)
Definition: SimpleFileBackend.php:179
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\findCacheFilesByIdentifier
‪mixed findCacheFilesByIdentifier($entryIdentifier)
Definition: SimpleFileBackend.php:338
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\$cacheEntryIdentifiers
‪array $cacheEntryIdentifiers
Definition: SimpleFileBackend.php:61
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\collectGarbage
‪collectGarbage()
Definition: SimpleFileBackend.php:328
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\setCacheDirectory
‪setCacheDirectory($cacheDirectory)
Definition: SimpleFileBackend.php:110
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\$temporaryCacheDirectory
‪string $temporaryCacheDirectory
Definition: SimpleFileBackend.php:51
‪TYPO3\CMS\Core\Utility\PathUtility\basename
‪static string basename($path)
Definition: PathUtility.php:165
‪TYPO3\CMS\Core\Cache\Backend\PhpCapableBackendInterface
Definition: PhpCapableBackendInterface.php:23
‪TYPO3\CMS\Core\Core\Environment\getProjectPath
‪static string getProjectPath()
Definition: Environment.php:169
‪TYPO3\CMS\Core\Utility\GeneralUtility\fixPermissions
‪static mixed fixPermissions($path, $recursive=false)
Definition: GeneralUtility.php:1863
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\setCache
‪setCache(FrontendInterface $cache)
Definition: SimpleFileBackend.php:74
‪TYPO3\CMS\Core\Utility\GeneralUtility\mkdir_deep
‪static mkdir_deep($directory)
Definition: GeneralUtility.php:2022
‪TYPO3\CMS\Core\Cache\Exception
Definition: DuplicateIdentifierException.php:16
‪TYPO3\CMS\Core\Cache\Exception\InvalidDataException
Definition: InvalidDataException.php:24
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend
Definition: SimpleFileBackend.php:33
‪TYPO3\CMS\Core\Cache\Backend\AbstractBackend\$cache
‪TYPO3 CMS Core Cache Frontend FrontendInterface $cache
Definition: AbstractBackend.php:37
‪TYPO3\CMS\Core\Service\OpcodeCacheService
Definition: OpcodeCacheService.php:25
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\requireOnce
‪mixed requireOnce($entryIdentifier)
Definition: SimpleFileBackend.php:351
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\EXPIRYTIME_FORMAT
‪const EXPIRYTIME_FORMAT
Definition: SimpleFileBackend.php:35
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\DATASIZE_DIGITS
‪const DATASIZE_DIGITS
Definition: SimpleFileBackend.php:37
‪TYPO3\CMS\Core\Utility\StringUtility\getUniqueId
‪static string getUniqueId($prefix='')
Definition: StringUtility.php:92
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\EXPIRYTIME_LENGTH
‪const EXPIRYTIME_LENGTH
Definition: SimpleFileBackend.php:36
‪TYPO3\CMS\Core\Cache\Backend\AbstractBackend
Definition: AbstractBackend.php:28
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\getCacheDirectory
‪string getCacheDirectory()
Definition: SimpleFileBackend.php:196
‪TYPO3\CMS\Core\Utility\GeneralUtility\rmdir
‪static bool rmdir($path, $removeNonEmpty=false)
Definition: GeneralUtility.php:2075
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\SEPARATOR
‪const SEPARATOR
Definition: SimpleFileBackend.php:34
‪TYPO3\CMS\Core\Cache\Backend
Definition: AbstractBackend.php:16
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\isCacheFileExpired
‪bool isCacheFileExpired($cacheEntryPathAndFilename)
Definition: SimpleFileBackend.php:320
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:22
‪TYPO3\CMS\Core\Utility\GeneralUtility\mkdir
‪static bool mkdir($newFolder)
Definition: GeneralUtility.php:2005
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\$frozen
‪bool $frozen
Definition: SimpleFileBackend.php:65
‪TYPO3\CMS\Core\Cache\Exception
Definition: Exception.php:22
‪TYPO3\CMS\Core\Core\Environment\getVarPath
‪static string getVarPath()
Definition: Environment.php:192