diff options
author | Vincent Petry <pvince81@owncloud.com> | 2015-06-12 14:03:37 +0200 |
---|---|---|
committer | Vincent Petry <pvince81@owncloud.com> | 2015-06-12 14:03:37 +0200 |
commit | da96cbbcd4e3c81374ef51f52ab6a546db02c02d (patch) | |
tree | e96a9bd37496009b17b929c85af61deb90448092 | |
parent | abd70932c6d86d56d225c7762b9e9a0cfedf8640 (diff) | |
parent | 5586b2db096f64623b4df76da560c48198c573df (diff) | |
download | nextcloud-server-da96cbbcd4e3c81374ef51f52ab6a546db02c02d.tar.gz nextcloud-server-da96cbbcd4e3c81374ef51f52ab6a546db02c02d.zip |
Merge pull request #16884 from owncloud/issue-16843-stop-locking-encryption-key-storage
Do not lock the encryption key storage
-rw-r--r-- | lib/private/files/view.php | 74 | ||||
-rw-r--r-- | tests/lib/files/view.php | 78 |
2 files changed, 135 insertions, 17 deletions
diff --git a/lib/private/files/view.php b/lib/private/files/view.php index b98842f5eb7..a206eab54e4 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -1661,52 +1661,72 @@ class View { /** * @param string $path the path of the file to lock, relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @return bool False if the path is excluded from locking, true otherwise + * @throws \OCP\Lock\LockedException if the path is already locked */ private function lockPath($path, $type) { + $absolutePath = $this->getAbsolutePath($path); + if (!$this->shouldLockFile($absolutePath)) { + return false; + } + $mount = $this->getMount($path); if ($mount) { $mount->getStorage()->acquireLock( - $mount->getInternalPath( - $this->getAbsolutePath($path) - ), + $mount->getInternalPath($absolutePath), $type, $this->lockingProvider ); } + + return true; } /** * @param string $path the path of the file to lock, relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @return bool False if the path is excluded from locking, true otherwise + * @throws \OCP\Lock\LockedException if the path is already locked */ private function changeLock($path, $type) { + $absolutePath = $this->getAbsolutePath($path); + if (!$this->shouldLockFile($absolutePath)) { + return false; + } + $mount = $this->getMount($path); if ($mount) { $mount->getStorage()->changeLock( - $mount->getInternalPath( - $this->getAbsolutePath($path) - ), + $mount->getInternalPath($absolutePath), $type, $this->lockingProvider ); } + + return true; } /** * @param string $path the path of the file to unlock, relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @return bool False if the path is excluded from locking, true otherwise */ private function unlockPath($path, $type) { + $absolutePath = $this->getAbsolutePath($path); + if (!$this->shouldLockFile($absolutePath)) { + return false; + } + $mount = $this->getMount($path); if ($mount) { $mount->getStorage()->releaseLock( - $mount->getInternalPath( - $this->getAbsolutePath($path) - ), + $mount->getInternalPath($absolutePath), $type, $this->lockingProvider ); } + + return true; } /** @@ -1714,15 +1734,24 @@ class View { * * @param string $path the path of the file to lock relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @return bool False if the path is excluded from locking, true otherwise */ public function lockFile($path, $type) { $path = '/' . trim($path, '/'); + + $absolutePath = $this->getAbsolutePath($path); + if (!$this->shouldLockFile($absolutePath)) { + return false; + } + $this->lockPath($path, $type); $parents = $this->getParents($path); foreach ($parents as $parent) { $this->lockPath($parent, ILockingProvider::LOCK_SHARED); } + + return true; } /** @@ -1730,14 +1759,41 @@ class View { * * @param string $path the path of the file to lock relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @return bool False if the path is excluded from locking, true otherwise */ public function unlockFile($path, $type) { $path = rtrim($path, '/'); + + $absolutePath = $this->getAbsolutePath($path); + if (!$this->shouldLockFile($absolutePath)) { + return false; + } + $this->unlockPath($path, $type); $parents = $this->getParents($path); foreach ($parents as $parent) { $this->unlockPath($parent, ILockingProvider::LOCK_SHARED); } + + return true; + } + + /** + * Only lock files in data/user/files/ + * + * @param string $path Absolute path to the file/folder we try to (un)lock + * @return bool + */ + protected function shouldLockFile($path) { + $path = Filesystem::normalizePath($path); + + $pathSegments = explode('/', $path); + if (isset($pathSegments[2])) { + // E.g.: /username/files/path-to-file + return $pathSegments[2] === 'files'; + } + + return true; } } diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index 06a42d63431..1050c36d292 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -1086,25 +1086,87 @@ class View extends \Test\TestCase { * e.g. reading from a folder that's being renamed * * @expectedException \OCP\Lock\LockedException + * + * @dataProvider dataLockPaths + * + * @param string $rootPath + * @param string $pathPrefix */ - public function testReadFromWriteLockedPath() { - $view = new \OC\Files\View(); + public function testReadFromWriteLockedPath($rootPath, $pathPrefix) { + $rootPath = str_replace('{folder}', 'files', $rootPath); + $pathPrefix = str_replace('{folder}', 'files', $pathPrefix); + + $view = new \OC\Files\View($rootPath); $storage = new Temporary(array()); \OC\Files\Filesystem::mount($storage, [], '/'); - $view->lockFile('/foo/bar', ILockingProvider::LOCK_EXCLUSIVE); - $view->lockFile('/foo/bar/asd', ILockingProvider::LOCK_SHARED); + $this->assertTrue($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_EXCLUSIVE)); + $view->lockFile($pathPrefix . '/foo/bar/asd', ILockingProvider::LOCK_SHARED); + } + + /** + * Reading from a files_encryption folder that's being renamed + * + * @dataProvider dataLockPaths + * + * @param string $rootPath + * @param string $pathPrefix + */ + public function testReadFromWriteUnlockablePath($rootPath, $pathPrefix) { + $rootPath = str_replace('{folder}', 'files_encryption', $rootPath); + $pathPrefix = str_replace('{folder}', 'files_encryption', $pathPrefix); + + $view = new \OC\Files\View($rootPath); + $storage = new Temporary(array()); + \OC\Files\Filesystem::mount($storage, [], '/'); + $this->assertFalse($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_EXCLUSIVE)); + $this->assertFalse($view->lockFile($pathPrefix . '/foo/bar/asd', ILockingProvider::LOCK_SHARED)); } /** * e.g. writing a file that's being downloaded * * @expectedException \OCP\Lock\LockedException + * + * @dataProvider dataLockPaths + * + * @param string $rootPath + * @param string $pathPrefix */ - public function testWriteToReadLockedFile() { - $view = new \OC\Files\View(); + public function testWriteToReadLockedFile($rootPath, $pathPrefix) { + $rootPath = str_replace('{folder}', 'files', $rootPath); + $pathPrefix = str_replace('{folder}', 'files', $pathPrefix); + + $view = new \OC\Files\View($rootPath); $storage = new Temporary(array()); \OC\Files\Filesystem::mount($storage, [], '/'); - $view->lockFile('/foo/bar', ILockingProvider::LOCK_SHARED); - $view->lockFile('/foo/bar', ILockingProvider::LOCK_EXCLUSIVE); + $this->assertTrue($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_SHARED)); + $view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_EXCLUSIVE); + } + + /** + * Writing a file that's being downloaded + * + * @dataProvider dataLockPaths + * + * @param string $rootPath + * @param string $pathPrefix + */ + public function testWriteToReadUnlockableFile($rootPath, $pathPrefix) { + $rootPath = str_replace('{folder}', 'files_encryption', $rootPath); + $pathPrefix = str_replace('{folder}', 'files_encryption', $pathPrefix); + + $view = new \OC\Files\View($rootPath); + $storage = new Temporary(array()); + \OC\Files\Filesystem::mount($storage, [], '/'); + $this->assertFalse($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_SHARED)); + $this->assertFalse($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_EXCLUSIVE)); + } + + public function dataLockPaths() { + return [ + ['/testuser/{folder}', ''], + ['/testuser', '/{folder}'], + ['', '/testuser/{folder}'], + ]; } } |