From 7e9b2d40c336fb5ce1d85b9d8e437888cb6ddd01 Mon Sep 17 00:00:00 2001 From: Benni Mack <benni@typo3.org> Date: Wed, 23 Dec 2015 19:53:14 +0100 Subject: [PATCH] [!!!][TASK] Remove old locking API Resolves: #72417 Releases: master Change-Id: I2f3349ca4dfeb1a3c3e1747db6ac42d492fa979a Reviewed-on: https://review.typo3.org/45424 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/Locking/Locker.php | 509 ------------------ .../Configuration/DefaultConfiguration.php | 1 - .../Breaking-72417-RemovedOldLockingAPI.rst | 16 + .../core/Tests/Unit/Locking/LockerTest.php | 234 -------- .../SilentConfigurationUpgradeService.php | 2 + 5 files changed, 18 insertions(+), 744 deletions(-) delete mode 100644 typo3/sysext/core/Classes/Locking/Locker.php create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Breaking-72417-RemovedOldLockingAPI.rst delete mode 100644 typo3/sysext/core/Tests/Unit/Locking/LockerTest.php diff --git a/typo3/sysext/core/Classes/Locking/Locker.php b/typo3/sysext/core/Classes/Locking/Locker.php deleted file mode 100644 index 316ac0b4929d..000000000000 --- a/typo3/sysext/core/Classes/Locking/Locker.php +++ /dev/null @@ -1,509 +0,0 @@ -<?php -namespace TYPO3\CMS\Core\Locking; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\GeneralUtility; - -/** - * TYPO3 locking class - * This class provides an abstract layer to various locking features for TYPO3 - * - * It is intended to blocks requests until some data has been generated. - * This is especially useful if two clients are requesting the same website short after each other. While the request of client 1 triggers building and caching of the website, client 2 will be waiting at this lock. - */ -class Locker -{ - const LOCKING_METHOD_SIMPLE = 'simple'; - const LOCKING_METHOD_FLOCK = 'flock'; - const LOCKING_METHOD_SEMAPHORE = 'semaphore'; - const LOCKING_METHOD_DISABLED = 'disable'; - - const FILE_LOCK_FOLDER = 'typo3temp/locks/'; - - /** - * @var string Locking method: One of the constants above - */ - protected $method = ''; - - /** - * @var mixed Identifier used for this lock - */ - protected $id; - - /** - * @var mixed Resource used for this lock (can be a file or a semaphore resource) - */ - protected $resource; - - /** - * @var resource File pointer if using flock method - */ - protected $filePointer; - - /** - * @var bool True if lock is acquired - */ - protected $isAcquired = false; - - /** - * @var int Number of times a locked resource is tried to be acquired. Only used in manual locks method "simple". - */ - protected $loops = 150; - - /** - * @var int Milliseconds after lock acquire is retried. $loops * $step results in the maximum delay of a lock. Only used in manual lock method "simple". - */ - protected $step = 200; - - /** - * @var string Logging facility - */ - protected $syslogFacility = 'cms'; - - /** - * @var bool True if locking should be logged - */ - protected $isLoggingEnabled = true; - - /** - * Constructor: - * initializes locking, check input parameters and set variables accordingly. - * - * Parameters $loops and $step only apply to the locking method LOCKING_METHOD_SIMPLE. - * - * @param string $id ID to identify this lock in the system - * @param string $method Define which locking method to use. Use one of the LOCKING_METHOD_* constants. Defaults to LOCKING_METHOD_SIMPLE. Use '' to use setting from Install Tool. - * @param int $loops Number of times a locked resource is tried to be acquired. - * @param int $step Milliseconds after lock acquire is retried. $loops * $step results in the maximum delay of a lock. - * @throws \RuntimeException - * @throws \InvalidArgumentException - * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8 - */ - public function __construct($id, $method = self::LOCKING_METHOD_SIMPLE, $loops = 0, $step = 0) - { - GeneralUtility::logDeprecatedFunction(); - // Force ID to be string - $id = (string)$id; - if ((int)$loops) { - $this->loops = (int)$loops; - } - if ((int)$step) { - $this->step = (int)$step; - } - if ($method === '' && isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['lockingMode'])) { - $method = (string)$GLOBALS['TYPO3_CONF_VARS']['SYS']['lockingMode']; - } - - switch ($method) { - case self::LOCKING_METHOD_SIMPLE: - // intended fall through - case self::LOCKING_METHOD_FLOCK: - $this->id = md5($id); - $this->createPathIfNeeded(); - break; - case self::LOCKING_METHOD_SEMAPHORE: - $this->id = abs(crc32($id)); - break; - case self::LOCKING_METHOD_DISABLED: - break; - default: - throw new \InvalidArgumentException('No such locking method "' . $method . '"', 1294586097); - } - $this->method = $method; - } - - /** - * Destructor: - * Releases lock automatically when instance is destroyed and release resources - */ - public function __destruct() - { - $this->release(); - switch ($this->method) { - case self::LOCKING_METHOD_FLOCK: - if ( - GeneralUtility::isAllowedAbsPath($this->resource) - && GeneralUtility::isFirstPartOfStr($this->resource, PATH_site . self::FILE_LOCK_FOLDER) - ) { - @unlink($this->resource); - } - break; - case self::LOCKING_METHOD_SEMAPHORE: - @sem_remove($this->resource); - break; - default: - // do nothing - } - } - - /** - * Tries to allocate the semaphore - * - * @return void - * @throws \RuntimeException - */ - protected function getSemaphore() - { - $this->resource = sem_get($this->id, 1); - if ($this->resource === false) { - throw new \RuntimeException('Unable to get semaphore with id ' . $this->id, 1313828196); - } - } - - /** - * Acquire a lock and return when successful. - * - * It is important to know that the lock will be acquired in any case, even if the request was blocked first. - * Therefore, the lock needs to be released in every situation. - * - * @return bool Returns TRUE if lock could be acquired without waiting, FALSE otherwise. - * @throws \RuntimeException - * @deprecated since 6.2 - will be removed two versions later; use new API instead - */ - public function acquire() - { - // @todo refactor locking in TSFE to use the new API, then this call can be logged - // GeneralUtility::logDeprecatedFunction(); - - // Default is TRUE, which means continue without caring for other clients. - // In the case of TYPO3s cache management, this has no negative effect except some resource overhead. - $noWait = false; - $isAcquired = false; - switch ($this->method) { - case self::LOCKING_METHOD_SIMPLE: - if (file_exists($this->resource)) { - $this->sysLog('Waiting for a different process to release the lock'); - $maxExecutionTime = (int)ini_get('max_execution_time'); - $maxAge = time() - ($maxExecutionTime ?: 120); - if (@filectime($this->resource) < $maxAge) { - @unlink($this->resource); - $this->sysLog('Unlinking stale lockfile', GeneralUtility::SYSLOG_SEVERITY_WARNING); - } - } - for ($i = 0; $i < $this->loops; $i++) { - $filePointer = @fopen($this->resource, 'x'); - if ($filePointer !== false) { - fclose($filePointer); - GeneralUtility::fixPermissions($this->resource); - $this->sysLog('Lock acquired'); - $noWait = $i === 0; - $isAcquired = true; - break; - } - usleep($this->step * 1000); - } - if (!$isAcquired) { - throw new \RuntimeException('Lock file could not be created', 1294586098); - } - break; - case self::LOCKING_METHOD_FLOCK: - $this->filePointer = fopen($this->resource, 'c'); - if ($this->filePointer === false) { - throw new \RuntimeException('Lock file could not be opened', 1294586099); - } - // Lock without blocking - if (flock($this->filePointer, LOCK_EX | LOCK_NB)) { - $noWait = true; - } elseif (flock($this->filePointer, LOCK_EX)) { - // Lock with blocking (waiting for similar locks to become released) - $noWait = false; - } else { - throw new \RuntimeException('Could not lock file "' . $this->resource . '"', 1294586100); - } - $isAcquired = true; - break; - case self::LOCKING_METHOD_SEMAPHORE: - $this->getSemaphore(); - while (!$isAcquired) { - if (@sem_acquire($this->resource)) { - // Unfortunately it is not possible to find out if the request has blocked, - // as sem_acquire will block until we get the resource. - // So we do not set $noWait here at all - $isAcquired = true; - } - } - break; - case self::LOCKING_METHOD_DISABLED: - break; - default: - // will never be reached - } - $this->isAcquired = $isAcquired; - return $noWait; - } - - /** - * Try to acquire an exclusive lock - * - * @throws \RuntimeException - * @return bool Returns TRUE if the lock was acquired successfully - */ - public function acquireExclusiveLock() - { - if ($this->isAcquired) { - return true; - } - $this->isAcquired = false; - switch ($this->method) { - case self::LOCKING_METHOD_SIMPLE: - if (file_exists($this->resource)) { - $this->sysLog('Waiting for a different process to release the lock'); - $maxExecutionTime = (int)ini_get('max_execution_time'); - $maxAge = time() - ($maxExecutionTime ?: 120); - if (@filectime($this->resource) < $maxAge) { - @unlink($this->resource); - $this->sysLog('Unlinking stale lockfile', GeneralUtility::SYSLOG_SEVERITY_WARNING); - } - } - for ($i = 0; $i < $this->loops; $i++) { - $filePointer = @fopen($this->resource, 'x'); - if ($filePointer !== false) { - fclose($filePointer); - GeneralUtility::fixPermissions($this->resource); - $this->sysLog('Lock acquired'); - $this->isAcquired = true; - break; - } - usleep($this->step * 1000); - } - break; - case self::LOCKING_METHOD_FLOCK: - $this->filePointer = fopen($this->resource, 'c'); - if ($this->filePointer === false) { - throw new \RuntimeException('Lock file could not be opened', 1294586099); - } - if (flock($this->filePointer, LOCK_EX)) { - $this->isAcquired = true; - } - break; - case self::LOCKING_METHOD_SEMAPHORE: - $this->getSemaphore(); - if (@sem_acquire($this->resource)) { - $this->isAcquired = true; - } - break; - case self::LOCKING_METHOD_DISABLED: - break; - default: - // will never be reached - } - return $this->isAcquired; - } - - /** - * Try to acquire a shared lock - * - * (Only works for the flock() locking method currently) - * - * @return bool Returns TRUE if the lock was acquired successfully - * @throws \RuntimeException - */ - public function acquireSharedLock() - { - if ($this->isAcquired) { - return true; - } - if ($this->method === self::LOCKING_METHOD_FLOCK) { - $this->filePointer = fopen($this->resource, 'c'); - if ($this->filePointer === false) { - throw new \RuntimeException('Lock file could not be opened', 1294586099); - } - if (flock($this->filePointer, LOCK_SH)) { - $this->isAcquired = true; - } - } - return $this->isAcquired; - } - - /** - * Release the lock - * - * @return bool Returns TRUE on success or FALSE on failure - */ - public function release() - { - if (!$this->isAcquired) { - return true; - } - $success = true; - switch ($this->method) { - case self::LOCKING_METHOD_SIMPLE: - if ( - GeneralUtility::isAllowedAbsPath($this->resource) - && GeneralUtility::isFirstPartOfStr($this->resource, PATH_site . self::FILE_LOCK_FOLDER) - ) { - if (@unlink($this->resource) === false) { - $success = false; - } - } - break; - case self::LOCKING_METHOD_FLOCK: - if (is_resource($this->filePointer)) { - if (flock($this->filePointer, LOCK_UN) === false) { - $success = false; - } - fclose($this->filePointer); - } - break; - case self::LOCKING_METHOD_SEMAPHORE: - if (!@sem_release($this->resource)) { - $success = false; - } - break; - case self::LOCKING_METHOD_DISABLED: - break; - default: - // will never be reached - } - $this->isAcquired = false; - return $success; - } - - /** - * Return the locking method which is currently used - * - * @return string Locking method - */ - public function getMethod() - { - return $this->method; - } - - /** - * Return the ID which is currently used - * - * @return string Locking ID - */ - public function getId() - { - return $this->id; - } - - /** - * Return the resource which is currently used. - * Depending on the locking method this can be a filename or a semaphore resource. - * - * @return mixed Locking resource (filename as string or semaphore as resource) - */ - public function getResource() - { - return $this->resource; - } - - /** - * Return the local status of a lock - * - * @return bool Returns TRUE if lock is acquired by this process, FALSE otherwise - */ - public function getLockStatus() - { - return $this->isAcquired; - } - - /** - * Return the global status of the lock - * - * @return bool Returns TRUE if the lock is locked by either this or another process, FALSE otherwise - */ - public function isLocked() - { - $result = false; - switch ($this->method) { - case self::LOCKING_METHOD_SIMPLE: - if (file_exists($this->resource)) { - $maxExecutionTime = (int)ini_get('max_execution_time'); - $maxAge = time() - ($maxExecutionTime ?: 120); - if (@filectime($this->resource) < $maxAge) { - @unlink($this->resource); - $this->sysLog('Unlinking stale lockfile', GeneralUtility::SYSLOG_SEVERITY_WARNING); - } else { - $result = true; - } - } - break; - case self::LOCKING_METHOD_FLOCK: - // we can't detect this reliably here, since the third parameter of flock() does not work on windows - break; - case self::LOCKING_METHOD_SEMAPHORE: - // no way to detect this at all, no PHP API for that - break; - case self::LOCKING_METHOD_DISABLED: - break; - default: - // will never be reached - } - return $result; - } - - /** - * Sets the facility (extension name) for the syslog entry. - * - * @param string $syslogFacility - */ - public function setSyslogFacility($syslogFacility) - { - $this->syslogFacility = $syslogFacility; - } - - /** - * Enable/ disable logging - * - * @param bool $isLoggingEnabled - */ - public function setEnableLogging($isLoggingEnabled) - { - $this->isLoggingEnabled = $isLoggingEnabled; - } - - /** - * Adds a common log entry for this locking API using \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog(). - * Example: 25-02-08 17:58 - cms: Locking [simple::0aeafd2a67a6bb8b9543fb9ea25ecbe2]: Acquired - * - * @param string $message The message to be logged - * @param int $severity Severity - 0 is info (default), 1 is notice, 2 is warning, 3 is error, 4 is fatal error - * @return void - */ - public function sysLog($message, $severity = 0) - { - if ($this->isLoggingEnabled) { - GeneralUtility::sysLog('Locking [' . $this->method . '::' . $this->id . ']: ' . trim($message), $this->syslogFacility, $severity); - } - } - - /** - * Tests if the directory for simple locks is available. - * If not, the directory will be created. The lock path is usually - * below typo3temp, typo3temp itself should exist already - * - * @return void - * @throws \RuntimeException If path couldn't be created. - */ - protected function createPathIfNeeded() - { - $path = PATH_site . self::FILE_LOCK_FOLDER; - if (!is_dir($path)) { - // Not using mkdir_deep on purpose here, if typo3temp itself - // does not exist, this issue should be solved on a different - // level of the application. - if (!GeneralUtility::mkdir($path)) { - throw new \RuntimeException('Cannot create directory ' . $path, 1395140007); - } - } - if (!is_writable($path)) { - throw new \RuntimeException('Cannot write to directory ' . $path, 1396278700); - } - $this->resource = $path . $this->id; - } -} diff --git a/typo3/sysext/core/Configuration/DefaultConfiguration.php b/typo3/sysext/core/Configuration/DefaultConfiguration.php index f5ba25b3b4a7..8992ae2b047d 100644 --- a/typo3/sysext/core/Configuration/DefaultConfiguration.php +++ b/typo3/sysext/core/Configuration/DefaultConfiguration.php @@ -105,7 +105,6 @@ return array( 'maxFileNameLength' => 60, // Integer: This is the maximum file name length. The value will be taken into account by basic file operations like renaming or creation of files and folders. 'UTF8filesystem' => false, // Boolean: If TRUE then TYPO3 uses utf-8 to store file names. This allows for accented Latin letters as well as any other non-latin characters like Cyrillic and Chinese. 'systemLocale' => '', // String: locale used for certain system related functions, e.g. escaping shell commands. If problems with filenames containing special characters occur, the value of this option is probably wrong. See <a href="http://php.net/manual/en/function.setlocale.php" target="_blank">setlocale()</a>. - 'lockingMode' => 'simple', // String: *deprecated* Define which locking mode is used to control requests to pages being generated. Can be one of either "disable" (no locking), "simple" (checks for file existence), "flock" (using PHPs <a href="http://php.net/flock" target="_blank">flock()</a> function), "semaphore" (using PHPs <a href="http://php.net/sem-acquire" target="_blank">sem_acquire()</a> function). Default is "simple". (This option is deprecated since TYPO3 CMS 7 and will be removed in TYPO3 CMS 8. The option is only used by extensions using the old Locker.) 'reverseProxyIP' => '', // String: list of IP addresses. If TYPO3 is behind one or more (intransparent) reverse proxies the IP addresses must be added here. 'reverseProxyHeaderMultiValue' => 'none', // String: "none","first","last": defines which values of a proxy header (eg HTTP_X_FORWARDED_FOR) to use, if more than one is found. "none" discards the value, "first" and "last" use the first/last of the values in the list. 'reverseProxyPrefix' => '', // String: optional prefix to be added to the internal URL (SCRIPT_NAME and REQUEST_URI). diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-72417-RemovedOldLockingAPI.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-72417-RemovedOldLockingAPI.rst new file mode 100644 index 000000000000..8f5e5b801d7d --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Breaking-72417-RemovedOldLockingAPI.rst @@ -0,0 +1,16 @@ +========================================== +Breaking: #72417 - Removed old locking API +========================================== + +Description +=========== + +The old locking mechanism was replaced by a more sophisticated a robust LockFactory, +and is now completely removed from the TYPO3 Core. + + +Impact +====== + +Using the ``Locker`` class will result in a fatal error. The option ``$TYPO3_CONF_VARS[SYS][lockingMode]`` has +no effect anymore. \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Unit/Locking/LockerTest.php b/typo3/sysext/core/Tests/Unit/Locking/LockerTest.php deleted file mode 100644 index 0b6081c43f6f..000000000000 --- a/typo3/sysext/core/Tests/Unit/Locking/LockerTest.php +++ /dev/null @@ -1,234 +0,0 @@ -<?php -namespace TYPO3\CMS\Core\Tests\Unit\Locking; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Locking\Locker; - -/** - * Testcase for \TYPO3\CMS\Core\Locking\Locker - */ -class LockerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /////////////////////////////// - // tests concerning __construct - /////////////////////////////// - /** - * @test - */ - public function constructorUsesDefaultLockingMethodSimple() - { - $instance = new Locker('999999999'); - $this->assertSame(Locker::LOCKING_METHOD_SIMPLE, $instance->getMethod()); - } - - /** - * @test - */ - public function constructorSetsMethodToGivenParameter() - { - $instance = new Locker('999999999', Locker::LOCKING_METHOD_FLOCK); - $this->assertSame(Locker::LOCKING_METHOD_FLOCK, $instance->getMethod()); - } - - /** - * @test - * @expectedException \InvalidArgumentException - */ - public function constructorThrowsExceptionForNotExistingLockingMethod() - { - new Locker('999999999', 'foo'); - } - - /** - * @test - */ - public function constructorFetchesInstallToolConfigurationIfEmptyMethod() - { - $GLOBALS['TYPO3_CONF_VARS']['SYS']['lockingMode'] = Locker::LOCKING_METHOD_SIMPLE; - $instance = new Locker('999999999', ''); - $this->assertSame(Locker::LOCKING_METHOD_SIMPLE, $instance->getMethod()); - } - - /** - * @test - */ - public function constructorUsesDefaultValueForLoops() - { - $instance = $this->getAccessibleMock(\TYPO3\CMS\Core\Locking\Locker::class, array('dummy'), array('999999999', Locker::LOCKING_METHOD_DISABLED)); - $this->assertSame(150, $instance->_get('loops')); - } - - /** - * @test - */ - public function constructorSetsLoopsToGivenNumberOfLoops() - { - $instance = $this->getAccessibleMock(\TYPO3\CMS\Core\Locking\Locker::class, array('dummy'), array('999999999', Locker::LOCKING_METHOD_DISABLED, 10)); - $this->assertSame(10, $instance->_get('loops')); - } - - /** - * @test - */ - public function constructorUsesDefaultValueForSteps() - { - $instance = $this->getAccessibleMock(\TYPO3\CMS\Core\Locking\Locker::class, array('dummy'), array('999999999', Locker::LOCKING_METHOD_DISABLED)); - $this->assertSame(200, $instance->_get('step')); - } - - /** - * @test - */ - public function constructorSetsStepToGivenNumberOfStep() - { - $instance = $this->getAccessibleMock(\TYPO3\CMS\Core\Locking\Locker::class, array('dummy'), array('999999999', Locker::LOCKING_METHOD_DISABLED, 0, 10)); - $this->assertSame(10, $instance->_get('step')); - } - - /** - * @test - */ - public function constructorCreatesLockDirectoryIfNotExisting() - { - \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir(PATH_site . Locker::FILE_LOCK_FOLDER, true); - new Locker('999999999', Locker::LOCKING_METHOD_SIMPLE); - $this->assertTrue(is_dir(PATH_site . Locker::FILE_LOCK_FOLDER)); - } - - /** - * @test - */ - public function constructorSetsIdToMd5OfStringIfUsingSimpleLocking() - { - $instance = new Locker('999999999', Locker::LOCKING_METHOD_SIMPLE); - $this->assertSame(md5('999999999'), $instance->getId()); - } - - /** - * @test - */ - public function constructorSetsResourceToPathWithIdIfUsingSimpleLocking() - { - $instance = new Locker('999999999', Locker::LOCKING_METHOD_SIMPLE); - $this->assertSame(PATH_site . Locker::FILE_LOCK_FOLDER . md5('999999999'), $instance->getResource()); - } - - /** - * @test - */ - public function constructorSetsIdToAbsCrc32OfIdStringIfUsingSemaphoreLocking() - { - if (!function_exists('sem_get')) { - $this->markTestSkipped('The system does not support semaphore base locking.'); - } - $instance = new Locker('999999999', Locker::LOCKING_METHOD_SEMAPHORE); - $this->assertSame(abs(crc32('999999999')), $instance->getId()); - } - - /////////////////////////////// - // tests concerning acquire - /////////////////////////////// - /** - * @test - */ - public function acquireFixesPermissionsOnLockFileIfUsingSimpleLogging() - { - if (TYPO3_OS == 'WIN') { - $this->markTestSkipped('acquireFixesPermissionsOnLockFileIfUsingSimpleLogging() test not available on Windows.'); - } - // Use a very high id to be unique - $instance = new Locker(999999999, Locker::LOCKING_METHOD_SIMPLE); - $instance->setEnableLogging(false); - $pathOfLockFile = $instance->getResource(); - $GLOBALS['TYPO3_CONF_VARS']['SYS']['fileCreateMask'] = '0777'; - // Acquire lock, get actual file permissions and clean up - $instance->acquireExclusiveLock(); - clearstatcache(); - $resultFilePermissions = substr(decoct(fileperms($pathOfLockFile)), 2); - $instance->release(); - $this->assertEquals($resultFilePermissions, '0777'); - } - - /////////////////////////////// - // tests concerning release - /////////////////////////////// - - /** - * @test - */ - public function releaseRemovesLockfileInTypo3TempLocks() - { - // Use a very high id to be unique - $instance = new Locker(999999999, Locker::LOCKING_METHOD_SIMPLE); - // Disable logging - $instance->setEnableLogging(false); - // File pointer to current lock file - $lockFile = $instance->getResource(); - $instance->acquireExclusiveLock(); - $instance->release(); - $this->assertFalse(is_file($lockFile)); - } - - /** - * Dataprovider for releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory - */ - public function invalidFileReferences() - { - return array( - 'simple not within PATH_site' => array('simple', '/tmp/TYPO3-Lock-Test'), - 'flock not withing PATH_site' => array('flock', '/tmp/TYPO3-Lock-Test'), - 'simple directory traversal' => array('simple', PATH_site . 'typo3temp/../typo3temp/locks/foo'), - 'flock directory traversal' => array('flock', PATH_site . 'typo3temp/../typo3temp/locks/foo'), - 'simple directory traversal 2' => array('simple', PATH_site . 'typo3temp/locks/../locks/foo'), - 'flock directory traversal 2' => array('flock', PATH_site . 'typo3temp/locks/../locks/foo'), - 'simple within uploads' => array('simple', PATH_site . 'uploads/TYPO3-Lock-Test'), - 'flock within uploads' => array('flock', PATH_site . 'uploads/TYPO3-Lock-Test') - ); - } - - /** - * @test - * @dataProvider invalidFileReferences - */ - public function releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory($lockMethod, $file) - { - if (TYPO3_OS === 'WIN') { - $this->markTestSkipped('releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory() test not available on Windows.'); - } - // Create test file - touch($file); - if (!is_file($file)) { - $this->markTestSkipped('releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory() skipped: Test file could not be created'); - } - // Create instance, set lockfile to invalid path - $instance = new Locker(999999999, $lockMethod); - $instance->setEnableLogging(false); - $t3libLockReflection = new \ReflectionClass(\TYPO3\CMS\Core\Locking\Locker::class); - $t3libLockReflectionResourceProperty = $t3libLockReflection->getProperty('resource'); - $t3libLockReflectionResourceProperty->setAccessible(true); - $t3libLockReflectionResourceProperty->setValue($instance, $file); - $t3libLockReflectionAcquiredProperty = $t3libLockReflection->getProperty('isAcquired'); - $t3libLockReflectionAcquiredProperty->setAccessible(true); - $t3libLockReflectionAcquiredProperty->setValue($instance, true); - // Call release method - $instance->release(); - // Check if file is still there and clean up - $fileExists = is_file($file); - if (is_file($file)) { - unlink($file); - } - $this->assertTrue($fileExists); - } -} diff --git a/typo3/sysext/install/Classes/Service/SilentConfigurationUpgradeService.php b/typo3/sysext/install/Classes/Service/SilentConfigurationUpgradeService.php index e214893a5405..09deb6a48a63 100755 --- a/typo3/sysext/install/Classes/Service/SilentConfigurationUpgradeService.php +++ b/typo3/sysext/install/Classes/Service/SilentConfigurationUpgradeService.php @@ -70,6 +70,8 @@ class SilentConfigurationUpgradeService 'INSTALL/wizardDone/TYPO3\\CMS\\Rtehtmlarea\\Hook\\Install\\RteAcronymButtonRenamedToAbbreviation', // #72400 'BE/spriteIconGenerator_handler', + // #72417 + 'SYS/lockingMode', ); /** -- GitLab