diff --git a/lib/private/encryption/keys/storage.php b/lib/private/encryption/keys/storage.php index e4e3fb084f31902dd6fcd5d47a3b35b94b704c37..7d0612ae30e1d49ae8978b44aa222df01a1e205a 100644 --- a/lib/private/encryption/keys/storage.php +++ b/lib/private/encryption/keys/storage.php @@ -283,7 +283,12 @@ class Storage implements \OCP\Encryption\Keys\IStorage { * @param string $owner * @param bool $systemWide */ - public function renameKeys($source, $target, $owner, $systemWide) { + public function renameKeys($source, $target) { + + list($owner, $source) = $this->util->getUidAndFilename($source); + list(, $target) = $this->util->getUidAndFilename($target); + $systemWide = $this->util->isSystemWideMountPoint($target); + if ($systemWide) { $sourcePath = $this->keys_base_dir . $source . '/'; $targetPath = $this->keys_base_dir . $target . '/'; @@ -298,6 +303,34 @@ class Storage implements \OCP\Encryption\Keys\IStorage { } } + /** + * copy keys if a file was renamed + * + * @param string $source + * @param string $target + * @param string $owner + * @param bool $systemWide + */ + public function copyKeys($source, $target) { + + list($owner, $source) = $this->util->getUidAndFilename($source); + list(, $target) = $this->util->getUidAndFilename($target); + $systemWide = $this->util->isSystemWideMountPoint($target); + + if ($systemWide) { + $sourcePath = $this->keys_base_dir . $source . '/'; + $targetPath = $this->keys_base_dir . $target . '/'; + } else { + $sourcePath = '/' . $owner . $this->keys_base_dir . $source . '/'; + $targetPath = '/' . $owner . $this->keys_base_dir . $target . '/'; + } + + if ($this->view->file_exists($sourcePath)) { + $this->keySetPreparation(dirname($targetPath)); + $this->view->copy($sourcePath, $targetPath); + } + } + /** * Make preparations to filesystem for saving a keyfile * diff --git a/lib/private/files/storage/wrapper/encryption.php b/lib/private/files/storage/wrapper/encryption.php index 3ea3b987d4c4ad79d1d60273c941d75adb018ec3..2e5bbfd97becc0394499b6a15e03015d78d23c64 100644 --- a/lib/private/files/storage/wrapper/encryption.php +++ b/lib/private/files/storage/wrapper/encryption.php @@ -173,17 +173,14 @@ class Encryption extends Wrapper { return $this->storage->rename($path1, $path2); } - $fullPath1 = $this->getFullPath($path1); - list($owner, $source) = $this->util->getUidAndFilename($fullPath1); + $source = $this->getFullPath($path1); $result = $this->storage->rename($path1, $path2); if ($result) { - $fullPath2 = $this->getFullPath($path2); - $systemWide = $this->util->isSystemWideMountPoint($this->mountPoint); - list(, $target) = $this->util->getUidAndFilename($fullPath2); + $target = $this->getFullPath($path2); $encryptionModule = $this->getEncryptionModule($path2); if ($encryptionModule) { $keyStorage = $this->getKeyStorage($encryptionModule->getId()); - $keyStorage->renameKeys($source, $target, $owner, $systemWide); + $keyStorage->renameKeys($source, $target); } } @@ -198,9 +195,22 @@ class Encryption extends Wrapper { * @return bool */ public function copy($path1, $path2) { - // todo copy encryption keys, get users with access to the file and reencrypt - // or is this to encryption module specific? Then we can hand this over - return $this->storage->copy($path1, $path2); + if ($this->util->isExcluded($path1)) { + return $this->storage->rename($path1, $path2); + } + + $source = $this->getFullPath($path1); + $result = $this->storage->copy($path1, $path2); + if ($result) { + $target = $this->getFullPath($path2); + $encryptionModule = $this->getEncryptionModule($path2); + if ($encryptionModule) { + $keyStorage = $this->getKeyStorage($encryptionModule->getId()); + $keyStorage->copyKeys($source, $target); + } + } + + return $result; } /** diff --git a/lib/public/encryption/keys/istorage.php b/lib/public/encryption/keys/istorage.php index 0a3ed44d378cb48b02959f1f0a3194e1364ec258..2d1672face5406eb3ba538412f75feceb2062d4e 100644 --- a/lib/public/encryption/keys/istorage.php +++ b/lib/public/encryption/keys/istorage.php @@ -122,14 +122,20 @@ interface IStorage { */ public function deleteSystemUserKey($keyId); + /** + * copy keys if a file was renamed + * + * @param string $source + * @param string $target + */ + public function renameKeys($source, $target); + /** * move keys if a file was renamed * * @param string $source * @param string $target - * @param string $owner - * @param bool $systemWide */ - public function renameKeys($source, $target, $owner, $systemWide); + public function copyKeys($source, $target); } diff --git a/tests/lib/encryption/keys/storage.php b/tests/lib/encryption/keys/storage.php index c2e5bdbd3d1eeea93973b1d2e6737ce0afdb45d2..be32f0e44a1337884750097542928e914b5d7fe7 100644 --- a/tests/lib/encryption/keys/storage.php +++ b/tests/lib/encryption/keys/storage.php @@ -277,4 +277,80 @@ class StorageTest extends TestCase { ); } + /** + * @dataProvider dataProviderCopyRename + */ + public function testRenameKeys($source, $target, $systemWideMount, $expectedSource, $expectedTarget) { + $this->view->expects($this->any()) + ->method('file_exists') + ->willReturn(true); + $this->view->expects($this->any()) + ->method('is_dir') + ->willReturn(true); + $this->view->expects($this->once()) + ->method('rename') + ->with( + $this->equalTo($expectedSource), + $this->equalTo($expectedTarget)) + ->willReturn(true); + $this->util->expects($this->any()) + ->method('getUidAndFilename') + ->will($this->returnCallback(array($this, 'getUidAndFilenameCallback'))); + $this->util->expects($this->any()) + ->method('isSystemWideMountPoint') + ->willReturn($systemWideMount); + + $storage = new Storage('encModule', $this->view, $this->util); + $storage->renameKeys($source, $target); + } + + /** + * @dataProvider dataProviderCopyRename + */ + public function testCopyKeys($source, $target, $systemWideMount, $expectedSource, $expectedTarget) { + $this->view->expects($this->any()) + ->method('file_exists') + ->willReturn(true); + $this->view->expects($this->any()) + ->method('is_dir') + ->willReturn(true); + $this->view->expects($this->once()) + ->method('copy') + ->with( + $this->equalTo($expectedSource), + $this->equalTo($expectedTarget)) + ->willReturn(true); + $this->util->expects($this->any()) + ->method('getUidAndFilename') + ->will($this->returnCallback(array($this, 'getUidAndFilenameCallback'))); + $this->util->expects($this->any()) + ->method('isSystemWideMountPoint') + ->willReturn($systemWideMount); + + $storage = new Storage('encModule', $this->view, $this->util); + $storage->copyKeys($source, $target); + } + + public function getUidAndFilenameCallback() { + $args = func_get_args(); + + $path = $args[0]; + $parts = explode('/', $path); + + return array($parts[1], '/' . implode('/', array_slice($parts, 2))); + } + + public function dataProviderCopyRename() { + return array( + array('/user1/files/foo.txt', '/user1/files/bar.txt', false, + '/user1/files_encryption/keys/files/foo.txt/', '/user1/files_encryption/keys/files/bar.txt/'), + array('/user1/files/foo/foo.txt', '/user1/files/bar.txt', false, + '/user1/files_encryption/keys/files/foo/foo.txt/', '/user1/files_encryption/keys/files/bar.txt/'), + array('/user1/files/foo.txt', '/user1/files/foo/bar.txt', false, + '/user1/files_encryption/keys/files/foo.txt/', '/user1/files_encryption/keys/files/foo/bar.txt/'), + array('/user1/files/foo.txt', '/user1/files/foo/bar.txt', true, + '/files_encryption/keys/files/foo.txt/', '/files_encryption/keys/files/foo/bar.txt/'), + ); + } + }