[BUGFIX] Replace __DIR__ with absolute path in class cache 40/24840/9
authorAlexander Stehlik <alexander.stehlik@googlemail.com>
Wed, 16 Oct 2013 19:59:31 +0000 (21:59 +0200)
committerThomas Maroschik <tmaroschik@dfau.de>
Mon, 21 Oct 2013 10:08:06 +0000 (12:08 +0200)
Since the directory constant __DIR__ is not always the same in all
environments (web, command line) we only allow absolute paths in the
class cache.

This requires the class cache to be cleared after the TYPO3 instance
was moved to another directory.

Resolves: #52885
Releases: 6.2
Change-Id: I0fc4c13d2977883e6881b5d7dda189813f97ae36
Reviewed-on: https://review.typo3.org/24840
Tested-by: Sebastian Fischer
Reviewed-by: Thorsten Kahler
Tested-by: Thorsten Kahler
Reviewed-by: Jigal van Hemert
Reviewed-by: Thomas Maroschik
Tested-by: Thomas Maroschik
typo3/sysext/core/Classes/Cache/Backend/ClassLoaderBackend.php
typo3/sysext/core/Classes/Core/ClassAliasMap.php

index fe18921..c95a6ea 100755 (executable)
@@ -27,7 +27,6 @@ namespace TYPO3\CMS\Core\Cache\Backend;
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
 
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\PathUtility;
 
 /**
@@ -39,6 +38,14 @@ use TYPO3\CMS\Core\Utility\PathUtility;
 class ClassLoaderBackend extends SimpleFileBackend {
 
        /**
+        * This string will be used for writing the require statement in the
+        * cache file and for getting the required path via regex.
+        *
+        * @var string
+        */
+       protected $requireFileTemplate = '<?php require \'%s\';';
+
+       /**
         * Set a class loader cache content
         *
         * @TODO: Rename method
@@ -51,24 +58,20 @@ class ClassLoaderBackend extends SimpleFileBackend {
                if ($entryIdentifier === '') {
                        throw new \InvalidArgumentException('The specified entry identifier must not be empty.', 1364205170);
                }
+               if (!PathUtility::isAbsolutePath($filePath)) {
+                       throw new \InvalidArgumentException('Only absolute paths are allowed for the class loader, given path was: ' . $filePath, 1381923089);
+               }
                if (!@file_exists($filePath)) {
                        throw new \InvalidArgumentException('The specified file path (' . $filePath . ') must exist.', 1364205235);
                }
-               if (strtolower(substr($filePath, -3)) !== 'php') {
+               if (strtolower(substr($filePath, -4)) !== '.php') {
                        throw new \InvalidArgumentException('The specified file (' . $filePath . ') must be a php file.', 1364205377);
                }
                if ($entryIdentifier !== basename($entryIdentifier)) {
                        throw new \InvalidArgumentException('The specified entry identifier (' . $entryIdentifier . ') must not contain a path segment.', 1364205166);
                }
-               if (\TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($filePath)) {
-                       // Make relative if absolute to prevent wrong entries if the whole installation is moved or copied
-                       $filePath = \TYPO3\CMS\Core\Utility\PathUtility::getRelativePath($this->cacheDirectory, dirname($filePath)) . basename($filePath);
-               }
-               if (PathUtility::isAbsolutePath($filePath)) {
-                       $this->set($entryIdentifier, '<?php require \'' . $filePath . '\';');
-               } else {
-                       $this->set($entryIdentifier, '<?php require __DIR__ . \'/' . $filePath . '\';');
-               }
+
+               $this->set($entryIdentifier, sprintf($this->requireFileTemplate, $filePath));
        }
 
        /**
@@ -104,31 +107,26 @@ class ClassLoaderBackend extends SimpleFileBackend {
        }
 
        /**
-        * Retrieves the target of the a linked cache entry
+        * Retrieves the path and filename that is passed to the require
+        * command in the cache entry with the given identifier.
         *
-        * @TODO: Rename method
         * @param string $entryIdentifier
-        * @return bool|string
+        * @return boolean|string FALSE if required path can not be retrieved or the required file path on success
         * @internal
         */
-       public function getTargetOfLinkedCacheEntry($entryIdentifier) {
-               $pathAndFilename = $this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension;
-               if (@file_exists($pathAndFilename)) {
-                       // If not a link
-                       $fileContent = file_get_contents($pathAndFilename);
-                       $pattern = "!^\<\?php require ((__DIR__) \. )?'([\/\.\_a-z0-9]+)';!i";
+       public function getPathOfRequiredFileInCacheEntry($entryIdentifier) {
+               $result = FALSE;
+
+               $fileContent = $this->get($entryIdentifier);
+               if ($fileContent !== FALSE) {
+                       $pattern = '!^' . sprintf(preg_quote($this->requireFileTemplate), '(.+)') . '!i';
                        $matches = array();
-                       if (preg_match($pattern, $fileContent, $matches) !== FALSE) {
-                               if (!empty($matches[3])) {
-                                       $targetPath = $matches[3];
-                                       if (!empty($matches[2]) && $matches[2] == '__DIR__') {
-                                               $targetPath = dirname($pathAndFilename) . $targetPath;
-                                       }
-                                       return \TYPO3\CMS\Core\Utility\PathUtility::getRelativePath($this->cacheDirectory, dirname($targetPath)) . basename($targetPath);
-                               }
+                       if (preg_match($pattern, $fileContent, $matches) === 1) {
+                               $requireString = $matches[1];
+                               $result = $requireString;
                        }
                }
-               return FALSE;
+               return $result;
        }
 
        /**
index 8ba8ec5..450ff7f 100644 (file)
@@ -192,9 +192,12 @@ class ClassAliasMap implements \TYPO3\CMS\Core\SingletonInterface {
                foreach ($classNameToAliasMapping as $originalClassName => $aliasClassNames) {
                        $originalClassNameCacheEntryIdentifier = str_replace('\\', '_', strtolower($originalClassName));
                        // Trigger autoloading for all aliased class names, so a cache entry is created
-                       if ($this->classLoader->loadClass($originalClassName, FALSE) && $originalClassTarget = $cacheBackend->getTargetOfLinkedCacheEntry($originalClassNameCacheEntryIdentifier)) {
+                       if (
+                               $this->classLoader->loadClass($originalClassName, FALSE)
+                               && ($requiredFile = $cacheBackend->getPathOfRequiredFileInCacheEntry($originalClassNameCacheEntryIdentifier))
+                       ) {
                                $proxyContent = array(
-                                       $this->buildRequireOnceCommand($originalClassTarget),
+                                       $this->buildRequireOnceCommand($requiredFile),
                                        $this->buildClassLoaderCommand(),
                                );
                                foreach ($aliasClassNames as $aliasClassName) {
@@ -262,13 +265,13 @@ class ClassAliasMap implements \TYPO3\CMS\Core\SingletonInterface {
        }
 
        /**
-        * String command to build class alias
+        * Creates a require_once command for the given file.
         *
-        * @param string $classFilePath
+        * @param string $requiredFile
         * @return string
         */
-       protected function buildRequireOnceCommand($classFilePath) {
-               return sprintf('require_once __DIR__ . \'/%s\';', $classFilePath);
+       protected function buildRequireOnceCommand($requiredFile) {
+               return sprintf('require_once \'%s\';', $requiredFile);
        }
 
        /**