[BUGFIX] Fix ambiguous identifier for imagesizes cache 79/39979/5
authorChristian Reiter <cr@cxd.de>
Fri, 5 Jun 2015 12:00:14 +0000 (14:00 +0200)
committerWouter Wolters <typo3@wouterwolters.nl>
Sat, 6 Jun 2015 13:25:53 +0000 (15:25 +0200)
Use sha1 of filepath instead of filemtime and filesize as identifier for
cached image dimensions to enable invalidation of stale cached entries
when an image is altered.
This also fixes cache collisions when dimensions are cached for a large
number of images with equal mtimes, some of which may also have equal
filesize, but different dimensions.

Releases: master
Resolves: #67289
Related: #28484
Change-Id: I520a8292dfbf3beb8efae996d286471e641ffd07
Reviewed-on: http://review.typo3.org/39979
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
typo3/sysext/core/Classes/Imaging/GraphicalFunctions.php

index a7dac44..2a427bc 100644 (file)
@@ -2284,7 +2284,8 @@ class GraphicalFunctions {
         */
        public function cacheImageDimensions(array $identifyResult) {
                $filePath = $identifyResult[3];
-               $statusHash = $this->generateCacheKeyForImageFile($filePath);
+               $statusHash = $this->generateStatusHashForImageFile($filePath);
+               $identifier = $this->generateCacheKeyForImageFile($filePath);
 
                /** @var \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend $cache */
                $cache = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_imagesizes');
@@ -2293,7 +2294,7 @@ class GraphicalFunctions {
                        'imagewidth'  => $identifyResult[0],
                        'imageheight' => $identifyResult[1],
                );
-               $cache->set($statusHash, $imageDimensions);
+               $cache->set($identifier, $imageDimensions);
 
                return TRUE;
        }
@@ -2301,23 +2302,24 @@ class GraphicalFunctions {
        /**
         * Fetches the cached image dimensions from the cache. Does not check if the image file exists.
         *
-        * @param string $filePath the image file path
+        * @param string $filePath Image file path, relative to PATH_site
         *
         * @return array|bool an array where [0]/[1] is w/h, [2] is extension and [3] is the file name,
         *                    or FALSE for a cache miss
         */
        public function getCachedImageDimensions($filePath) {
-               $statusHash = $this->generateCacheKeyForImageFile($filePath);
+               $statusHash = $this->generateStatusHashForImageFile($filePath);
+               $identifier = $this->generateCacheKeyForImageFile($filePath);
                /** @var \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend $cache */
                $cache = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_imagesizes');
-               $cachedImageDimensions = $cache->get($statusHash);
+               $cachedImageDimensions = $cache->get($identifier);
                if (!isset($cachedImageDimensions['hash'])) {
                        return FALSE;
                }
 
                if ($cachedImageDimensions['hash'] !== $statusHash) {
                        // The file has changed. Delete the cache entry.
-                       $cache->remove($filePath);
+                       $cache->remove($identifier);
                        $result = FALSE;
                } else {
                        preg_match('/([^\\.]*)$/', $filePath, $imageExtension);
@@ -2337,11 +2339,22 @@ class GraphicalFunctions {
         *
         * This method does not check if the image file actually exists.
         *
-        * @param string $filePath
+        * @param string $filePath Image file path, relative to PATH_site
         *
         * @return string the hash key (an SHA1 hash), will not be empty
         */
        protected function generateCacheKeyForImageFile($filePath) {
+               return sha1($filePath);
+       }
+
+       /**
+        * Creates the status hash to check whether a file has been changed.
+        *
+        * @param string $filePath Image file path, relative to PATH_site
+        *
+        * @return string the status hash (an SHA1 hash)
+        */
+       protected function generateStatusHashForImageFile($filePath) {
                $fileStatus = stat($filePath);
 
                return sha1($fileStatus['mtime'] . $fileStatus['size']);