diff --git a/lib/private/Files/Cache/CacheEntry.php b/lib/private/Files/Cache/CacheEntry.php index 74af7d0a59800..5f20bfdd3e613 100644 --- a/lib/private/Files/Cache/CacheEntry.php +++ b/lib/private/Files/Cache/CacheEntry.php @@ -140,7 +140,7 @@ public function __clone() { #[\Override] public function getUnencryptedSize(): int { - if ($this->data['encrypted'] && isset($this->data['unencrypted_size']) && $this->data['unencrypted_size'] > 0) { + if ($this->data['encrypted'] && isset($this->data['unencrypted_size'])) { return $this->data['unencrypted_size']; } else { return $this->data['size'] ?? 0; diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php index 36c8c02a8bfca..df73ccd79d94d 100644 --- a/lib/private/Files/Cache/Scanner.php +++ b/lib/private/Files/Cache/Scanner.php @@ -183,8 +183,12 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = } } - // we only updated unencrypted_size if it's already set - if (isset($cacheData['unencrypted_size']) && $cacheData['unencrypted_size'] === 0) { + // Only skip updating unencrypted_size if both cached and new values are 0 + // This allows updating from incorrect cached 0 to correct non-zero value + // while avoiding unnecessary updates when both are legitimately 0 + if (isset($cacheData['unencrypted_size']) + && $cacheData['unencrypted_size'] === 0 + && (!isset($data['unencrypted_size']) || $data['unencrypted_size'] === 0)) { unset($data['unencrypted_size']); } @@ -202,7 +206,12 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = $data['etag_changed'] = true; } } else { - unset($data['unencrypted_size']); + // For new files, preserve unencrypted_size only when the file is encrypted + // and the key is present; otherwise clear it so it won't be written stale. + if (!isset($data['encrypted']) || !$data['encrypted'] + || !isset($data['unencrypted_size'])) { + unset($data['unencrypted_size']); + } $newData = $data; $fileId = -1; } diff --git a/lib/private/Files/FileInfo.php b/lib/private/Files/FileInfo.php index 65280b0f31580..37d96ba27ff2b 100644 --- a/lib/private/Files/FileInfo.php +++ b/lib/private/Files/FileInfo.php @@ -173,7 +173,7 @@ public function getSize($includeMounts = true) { if ($includeMounts) { $this->updateEntryFromSubMounts(); - if ($this->isEncrypted() && isset($this->data['unencrypted_size']) && $this->data['unencrypted_size'] > 0) { + if ($this->isEncrypted() && isset($this->data['unencrypted_size'])) { return $this->data['unencrypted_size']; } else { return isset($this->data['size']) ? 0 + $this->data['size'] : 0; diff --git a/lib/private/Files/Storage/Wrapper/Encryption.php b/lib/private/Files/Storage/Wrapper/Encryption.php index 8edf25e9a5111..a256dfaa63d1d 100644 --- a/lib/private/Files/Storage/Wrapper/Encryption.php +++ b/lib/private/Files/Storage/Wrapper/Encryption.php @@ -400,6 +400,7 @@ protected function verifyUnencryptedSize(string $path, int $unencryptedSize): in if ($unencryptedSize < 0 || ($size > 0 && $unencryptedSize === $size) || $unencryptedSize > $size + || ($unencryptedSize === 0 && $size > $this->util->getHeaderSize()) ) { // check if we already calculate the unencrypted size for the // given path to avoid recursions diff --git a/lib/private/Files/Stream/Encryption.php b/lib/private/Files/Stream/Encryption.php index 1c662aa023c6c..7b83ce0592a80 100644 --- a/lib/private/Files/Stream/Encryption.php +++ b/lib/private/Files/Stream/Encryption.php @@ -28,7 +28,7 @@ class Encryption extends Wrapper { protected string $cache; protected ?int $size = null; protected int $position; - protected ?int $unencryptedSize = null; + protected int|float|null $unencryptedSize = null; protected int $headerSize; protected int $unencryptedBlockSize; protected array $header;