diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index ae5bbe011c9d6..67156893c3fd2 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -1166,6 +1166,9 @@ public function copyFromCache(ICache $sourceCache, ICacheEntry $sourceEntry, str // when moving from an encrypted storage to a non-encrypted storage remove the `encrypted` mark if ($sourceCache instanceof Cache && $sourceCache->hasEncryptionWrapper() && !$this->hasEncryptionWrapper()) { $data['encrypted'] = 0; + // normalizeData() prefers 'encryptedVersion' over 'encrypted' when both are + // set, so it has to be cleared too or the mark above gets ignored + unset($data['encryptedVersion']); } $fileId = $this->put($targetPath, $data); @@ -1199,6 +1202,11 @@ private function cacheEntryToArray(ICacheEntry $entry): array { if ($entry instanceof CacheEntry && isset($entry['scan_permissions'])) { $data['permissions'] = $entry['scan_permissions']; } + + if ($entry->isEncrypted() && isset($entry['encryptedVersion'])) { + $data['encryptedVersion'] = $entry['encryptedVersion']; + } + return $data; } diff --git a/tests/lib/Files/Cache/CacheTest.php b/tests/lib/Files/Cache/CacheTest.php index 821b371294af7..6c9f67f07a0f4 100644 --- a/tests/lib/Files/Cache/CacheTest.php +++ b/tests/lib/Files/Cache/CacheTest.php @@ -500,6 +500,49 @@ public function testMoveFromCache() { $this->assertTrue($this->cache->inCache('targetfolder/sub')); } + public function testCopyFromCachePreservesEncryptedVersion(): void { + $data = [ + 'size' => 100, 'mtime' => 50, 'mimetype' => 'foo/bar', + 'encrypted' => true, 'encryptedVersion' => 3, + ]; + $this->cache->put('source', $data); + $sourceEntry = $this->cache->get('source'); + $this->assertSame(3, $sourceEntry['encryptedVersion']); + + $this->cache->copyFromCache($this->cache, $sourceEntry, 'target'); + + $targetEntry = $this->cache->get('target'); + $this->assertTrue($targetEntry->isEncrypted()); + $this->assertSame(3, $targetEntry['encryptedVersion']); + } + + public function testCopyFromCacheClearsEncryptedVersionWhenCopyingToNonEncryptedStorage(): void { + $data = [ + 'size' => 100, 'mtime' => 50, 'mimetype' => 'foo/bar', + 'encrypted' => true, 'encryptedVersion' => 3, + ]; + $this->cache2->put('source', $data); + $sourceEntry = $this->cache2->get('source'); + + $sourceCache = $this->getMockBuilder(Cache::class) + ->setConstructorArgs([$this->storage2]) + ->onlyMethods(['hasEncryptionWrapper']) + ->getMock(); + $sourceCache->method('hasEncryptionWrapper')->willReturn(true); + + $targetCache = $this->getMockBuilder(Cache::class) + ->setConstructorArgs([$this->storage]) + ->onlyMethods(['hasEncryptionWrapper']) + ->getMock(); + $targetCache->method('hasEncryptionWrapper')->willReturn(false); + + $targetCache->copyFromCache($sourceCache, $sourceEntry, 'target'); + + $targetEntry = $targetCache->get('target'); + $this->assertFalse($targetEntry['encrypted']); + $this->assertSame(0, $targetEntry['encryptedVersion']); + } + public function testGetIncomplete() { $file1 = 'folder1'; $file2 = 'folder2';