/** * read block to file */ protected function readCache() { // cache should always be empty string when this function is called // don't try to fill the cache when trying to write at the end of the unencrypted file when it coincides with new block if ($this->cache === '' && !($this->position === $this->unencryptedSize && ($this->position % $this->unencryptedBlockSize) === 0)) { // Get the data from the file handle $data = parent::stream_read($this->util->getBlockSize()); $this->cache = $this->encryptionModule->decrypt($data); } }
/** * read block to file */ protected function readCache() { // cache should always be empty string when this function is called // don't try to fill the cache when trying to write at the end of the unencrypted file when it coincides with new block if ($this->cache === '' && !($this->position === $this->unencryptedSize && $this->position % $this->unencryptedBlockSize === 0)) { // Get the data from the file handle $data = parent::stream_read($this->util->getBlockSize()); $position = (int) floor($this->position / $this->unencryptedBlockSize); $numberOfChunks = (int) ($this->unencryptedSize / $this->unencryptedBlockSize); if ($numberOfChunks === $position) { $position .= 'end'; } $this->cache = $this->encryptionModule->decrypt($data, $position); } }
/** * calculate the unencrypted size * * @param string $path internal path relative to the storage root * @param int $size size of the physical file * @param int $unencryptedSize size of the unencrypted file * * @return int calculated unencrypted size */ protected function fixUnencryptedSize($path, $size, $unencryptedSize) { $headerSize = $this->getHeaderSize($path); $header = $this->getHeader($path); $encryptionModule = $this->getEncryptionModule($path); $stream = $this->storage->fopen($path, 'r'); // if we couldn't open the file we return the old unencrypted size if (!is_resource($stream)) { $this->logger->error('Could not open ' . $path . '. Recalculation of unencrypted size aborted.'); return $unencryptedSize; } $newUnencryptedSize = 0; $size -= $headerSize; $blockSize = $this->util->getBlockSize(); // if a header exists we skip it if ($headerSize > 0) { fread($stream, $headerSize); } // fast path, else the calculation for $lastChunkNr is bogus if ($size === 0) { return 0; } $signed = (isset($header['signed']) && $header['signed'] === 'true') ? true : false; $unencryptedBlockSize = $encryptionModule->getUnencryptedBlockSize($signed); // calculate last chunk nr // next highest is end of chunks, one subtracted is last one // we have to read the last chunk, we can't just calculate it (because of padding etc) $lastChunkNr = ceil($size/ $blockSize)-1; // calculate last chunk position $lastChunkPos = ($lastChunkNr * $blockSize); // try to fseek to the last chunk, if it fails we have to read the whole file if (@fseek($stream, $lastChunkPos, SEEK_CUR) === 0) { $newUnencryptedSize += $lastChunkNr * $unencryptedBlockSize; } $lastChunkContentEncrypted=''; $count = $blockSize; while ($count > 0) { $data=fread($stream, $blockSize); $count=strlen($data); $lastChunkContentEncrypted .= $data; if(strlen($lastChunkContentEncrypted) > $blockSize) { $newUnencryptedSize += $unencryptedBlockSize; $lastChunkContentEncrypted=substr($lastChunkContentEncrypted, $blockSize); } } fclose($stream); // we have to decrypt the last chunk to get it actual size $encryptionModule->begin($this->getFullPath($path), $this->uid, 'r', $header, []); $decryptedLastChunk = $encryptionModule->decrypt($lastChunkContentEncrypted); $decryptedLastChunk .= $encryptionModule->end($this->getFullPath($path)); // calc the real file size with the size of the last chunk $newUnencryptedSize += strlen($decryptedLastChunk); $this->updateUnencryptedSize($this->getFullPath($path), $newUnencryptedSize); // write to cache if applicable $cache = $this->storage->getCache(); if ($cache) { $entry = $cache->get($path); $cache->update($entry['fileid'], ['size' => $newUnencryptedSize]); } return $newUnencryptedSize; }