diff options
Diffstat (limited to 'lib/private')
-rw-r--r-- | lib/private/Files/Cache/Scanner.php | 37 | ||||
-rw-r--r-- | lib/private/Files/ObjectStore/NoopScanner.php | 2 | ||||
-rw-r--r-- | lib/private/Files/Storage/Common.php | 18 | ||||
-rw-r--r-- | lib/private/Files/Storage/Local.php | 1 | ||||
-rw-r--r-- | lib/private/Files/Storage/Storage.php | 18 | ||||
-rw-r--r-- | lib/private/Files/Storage/Wrapper/Availability.php | 11 | ||||
-rw-r--r-- | lib/private/Files/Storage/Wrapper/Encoding.php | 4 | ||||
-rw-r--r-- | lib/private/Files/Storage/Wrapper/Encryption.php | 69 | ||||
-rw-r--r-- | lib/private/Files/Storage/Wrapper/Jail.php | 4 | ||||
-rw-r--r-- | lib/private/Files/Storage/Wrapper/PermissionsMask.php | 9 | ||||
-rw-r--r-- | lib/private/Files/Storage/Wrapper/Wrapper.php | 4 |
11 files changed, 118 insertions, 59 deletions
diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php index 2a5a6536697..f895948574b 100644 --- a/lib/private/Files/Cache/Scanner.php +++ b/lib/private/Files/Cache/Scanner.php @@ -126,11 +126,11 @@ class Scanner extends BasicEmitter implements IScanner { * @param int $parentId * @param array|null|false $cacheData existing data in the cache for the file to be scanned * @param bool $lock set to false to disable getting an additional read lock during scanning + * @param null $data the metadata for the file, as returned by the storage * @return array an array of metadata of the scanned file - * @throws \OC\ServerNotAvailableException * @throws \OCP\Lock\LockedException */ - public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true) { + public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true, $data = null) { if ($file !== '') { try { $this->storage->verifyPath(dirname($file), basename($file)); @@ -149,7 +149,7 @@ class Scanner extends BasicEmitter implements IScanner { } try { - $data = $this->getData($file); + $data = $data ?? $this->getData($file); } catch (ForbiddenException $e) { if ($lock) { if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) { @@ -367,26 +367,6 @@ class Scanner extends BasicEmitter implements IScanner { } /** - * Get the children from the storage - * - * @param string $folder - * @return string[] - */ - protected function getNewChildren($folder) { - $children = []; - if ($dh = $this->storage->opendir($folder)) { - if (is_resource($dh)) { - while (($file = readdir($dh)) !== false) { - if (!Filesystem::isIgnoredDir($file)) { - $children[] = trim(\OC\Files\Filesystem::normalizePath($file), '/'); - } - } - } - } - return $children; - } - - /** * scan all the files and folders in a folder * * @param string $path @@ -425,7 +405,7 @@ class Scanner extends BasicEmitter implements IScanner { private function handleChildren($path, $recursive, $reuse, $folderId, $lock, &$size) { // we put this in it's own function so it cleans up the memory before we start recursing $existingChildren = $this->getExistingChildren($folderId); - $newChildren = $this->getNewChildren($path); + $newChildren = iterator_to_array($this->storage->getDirectoryContent($path)); if ($this->useTransactions) { \OC::$server->getDatabaseConnection()->beginTransaction(); @@ -433,11 +413,14 @@ class Scanner extends BasicEmitter implements IScanner { $exceptionOccurred = false; $childQueue = []; - foreach ($newChildren as $file) { + $newChildNames = []; + foreach ($newChildren as $fileMeta) { + $file = $fileMeta['name']; + $newChildNames[] = $file; $child = $path ? $path . '/' . $file : $file; try { $existingData = isset($existingChildren[$file]) ? $existingChildren[$file] : false; - $data = $this->scanFile($child, $reuse, $folderId, $existingData, $lock); + $data = $this->scanFile($child, $reuse, $folderId, $existingData, $lock, $fileMeta); if ($data) { if ($data['mimetype'] === 'httpd/unix-directory' and $recursive === self::SCAN_RECURSIVE) { $childQueue[$child] = $data['fileid']; @@ -471,7 +454,7 @@ class Scanner extends BasicEmitter implements IScanner { throw $e; } } - $removedChildren = \array_diff(array_keys($existingChildren), $newChildren); + $removedChildren = \array_diff(array_keys($existingChildren), $newChildNames); foreach ($removedChildren as $childName) { $child = $path ? $path . '/' . $childName : $childName; $this->removeFromCache($child); diff --git a/lib/private/Files/ObjectStore/NoopScanner.php b/lib/private/Files/ObjectStore/NoopScanner.php index 57a94aba294..25b52416efd 100644 --- a/lib/private/Files/ObjectStore/NoopScanner.php +++ b/lib/private/Files/ObjectStore/NoopScanner.php @@ -44,7 +44,7 @@ class NoopScanner extends Scanner { * @param array|null $cacheData existing data in the cache for the file to be scanned * @return array an array of metadata of the scanned file */ - public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true) { + public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true, $data = null) { return []; } diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php index bb672f3a0ea..86252f5c3dd 100644 --- a/lib/private/Files/Storage/Common.php +++ b/lib/private/Files/Storage/Common.php @@ -234,7 +234,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { } else { $source = $this->fopen($path1, 'r'); $target = $this->fopen($path2, 'w'); - list(, $result) = \OC_Helper::streamCopy($source, $target); + [, $result] = \OC_Helper::streamCopy($source, $target); if (!$result) { \OC::$server->getLogger()->warning("Failed to write data while copying $path1 to $path2"); } @@ -626,7 +626,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { // are not the same as the original one.Once this is fixed we also // need to adjust the encryption wrapper. $target = $this->fopen($targetInternalPath, 'w'); - list(, $result) = \OC_Helper::streamCopy($source, $target); + [, $result] = \OC_Helper::streamCopy($source, $target); if ($result and $preserveMtime) { $this->touch($targetInternalPath, $sourceStorage->filemtime($sourceInternalPath)); } @@ -719,6 +719,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { $data['etag'] = $this->getETag($path); $data['storage_mtime'] = $data['mtime']; $data['permissions'] = $permissions; + $data['name'] = basename($path); return $data; } @@ -867,4 +868,17 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { } return $count; } + + public function getDirectoryContent($directory): \Traversable { + $dh = $this->opendir($directory); + if (is_resource($dh)) { + $basePath = rtrim($directory, '/'); + while (($file = readdir($dh)) !== false) { + if (!Filesystem::isIgnoredDir($file)) { + $childPath = $basePath . '/' . trim($file, '/'); + yield $this->getMetaData($childPath); + } + } + } + } } diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php index 89b318b4770..2019c67bede 100644 --- a/lib/private/Files/Storage/Local.php +++ b/lib/private/Files/Storage/Local.php @@ -196,6 +196,7 @@ class Local extends \OC\Files\Storage\Common { $data['etag'] = $this->calculateEtag($path, $stat); $data['storage_mtime'] = $data['mtime']; $data['permissions'] = $permissions; + $data['name'] = basename($path); return $data; } diff --git a/lib/private/Files/Storage/Storage.php b/lib/private/Files/Storage/Storage.php index 7e5a0cef4d7..76dab07b6a7 100644 --- a/lib/private/Files/Storage/Storage.php +++ b/lib/private/Files/Storage/Storage.php @@ -119,4 +119,22 @@ interface Storage extends \OCP\Files\Storage { * @throws \OCP\Lock\LockedException */ public function changeLock($path, $type, ILockingProvider $provider); + + /** + * Get the contents of a directory with metadata + * + * @param string $directory + * @return \Traversable an iterator, containing file metadata + * + * The metadata array will contain the following fields + * + * - name + * - mimetype + * - mtime + * - size + * - etag + * - storage_mtime + * - permissions + */ + public function getDirectoryContent($directory): \Traversable; } diff --git a/lib/private/Files/Storage/Wrapper/Availability.php b/lib/private/Files/Storage/Wrapper/Availability.php index 300ba7e7f7c..ea210128e8f 100644 --- a/lib/private/Files/Storage/Wrapper/Availability.php +++ b/lib/private/Files/Storage/Wrapper/Availability.php @@ -461,4 +461,15 @@ class Availability extends Wrapper { $this->getStorageCache()->setAvailability(false, $delay); throw $e; } + + + + public function getDirectoryContent($directory): \Traversable { + $this->checkAvailability(); + try { + return parent::getDirectoryContent($directory); + } catch (StorageNotAvailableException $e) { + $this->setUnavailable($e); + } + } } diff --git a/lib/private/Files/Storage/Wrapper/Encoding.php b/lib/private/Files/Storage/Wrapper/Encoding.php index d1e0622808b..4e81588de80 100644 --- a/lib/private/Files/Storage/Wrapper/Encoding.php +++ b/lib/private/Files/Storage/Wrapper/Encoding.php @@ -534,4 +534,8 @@ class Encoding extends Wrapper { public function getMetaData($path) { return $this->storage->getMetaData($this->findPathToUse($path)); } + + public function getDirectoryContent($directory): \Traversable { + return $this->storage->getDirectoryContent($this->findPathToUse($directory)); + } } diff --git a/lib/private/Files/Storage/Wrapper/Encryption.php b/lib/private/Files/Storage/Wrapper/Encryption.php index 1ea2664877b..897624ff6ae 100644 --- a/lib/private/Files/Storage/Wrapper/Encryption.php +++ b/lib/private/Files/Storage/Wrapper/Encryption.php @@ -105,17 +105,17 @@ class Encryption extends Wrapper { * @param ArrayCache $arrayCache */ public function __construct( - $parameters, - IManager $encryptionManager = null, - Util $util = null, - ILogger $logger = null, - IFile $fileHelper = null, - $uid = null, - IStorage $keyStorage = null, - Update $update = null, - Manager $mountManager = null, - ArrayCache $arrayCache = null - ) { + $parameters, + IManager $encryptionManager = null, + Util $util = null, + ILogger $logger = null, + IFile $fileHelper = null, + $uid = null, + IStorage $keyStorage = null, + Update $update = null, + Manager $mountManager = null, + ArrayCache $arrayCache = null + ) { $this->mountPoint = $parameters['mountPoint']; $this->mount = $parameters['mount']; $this->encryptionManager = $encryptionManager; @@ -169,15 +169,7 @@ class Encryption extends Wrapper { return $this->storage->filesize($path); } - /** - * @param string $path - * @return array - */ - public function getMetaData($path) { - $data = $this->storage->getMetaData($path); - if (is_null($data)) { - return null; - } + private function modifyMetaData(string $path, array $data): array { $fullPath = $this->getFullPath($path); $info = $this->getCache()->get($path); @@ -199,6 +191,25 @@ class Encryption extends Wrapper { } /** + * @param string $path + * @return array + */ + public function getMetaData($path) { + $data = $this->storage->getMetaData($path); + if (is_null($data)) { + return null; + } + return $this->modifyMetaData($path, $data); + } + + public function getDirectoryContent($directory): \Traversable { + $parent = rtrim($directory, '/'); + foreach ($this->getWrapperStorage()->getDirectoryContent($directory) as $data) { + yield $this->modifyMetaData($parent . '/' . $data['name'], $data); + } + } + + /** * see http://php.net/manual/en/function.file_get_contents.php * * @param string $path @@ -493,7 +504,7 @@ class Encryption extends Wrapper { try { $result = $this->fixUnencryptedSize($path, $size, $unencryptedSize); } catch (\Exception $e) { - $this->logger->error('Couldn\'t re-calculate unencrypted size for '. $path); + $this->logger->error('Couldn\'t re-calculate unencrypted size for ' . $path); $this->logger->logException($e); } unset($this->fixUnencryptedSizeOf[$this->getFullPath($path)]); @@ -546,7 +557,7 @@ class Encryption extends Wrapper { // 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; + $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 @@ -554,16 +565,16 @@ class Encryption extends Wrapper { $newUnencryptedSize += $lastChunkNr * $unencryptedBlockSize; } - $lastChunkContentEncrypted=''; + $lastChunkContentEncrypted = ''; $count = $blockSize; while ($count > 0) { - $data=fread($stream, $blockSize); - $count=strlen($data); + $data = fread($stream, $blockSize); + $count = strlen($data); $lastChunkContentEncrypted .= $data; if (strlen($lastChunkContentEncrypted) > $blockSize) { $newUnencryptedSize += $unencryptedBlockSize; - $lastChunkContentEncrypted=substr($lastChunkContentEncrypted, $blockSize); + $lastChunkContentEncrypted = substr($lastChunkContentEncrypted, $blockSize); } } @@ -743,7 +754,7 @@ class Encryption extends Wrapper { try { $source = $sourceStorage->fopen($sourceInternalPath, 'r'); $target = $this->fopen($targetInternalPath, 'w'); - list(, $result) = \OC_Helper::streamCopy($source, $target); + [, $result] = \OC_Helper::streamCopy($source, $target); fclose($source); fclose($target); } catch (\Exception $e) { @@ -889,7 +900,7 @@ class Encryption extends Wrapper { $header = substr($header, 0, $endAt + strlen(Util::HEADER_END)); // +1 to not start with an ':' which would result in empty element at the beginning - $exploded = explode(':', substr($header, strlen(Util::HEADER_START)+1)); + $exploded = explode(':', substr($header, strlen(Util::HEADER_START) + 1)); $element = array_shift($exploded); while ($element !== Util::HEADER_END) { @@ -1023,7 +1034,7 @@ class Encryption extends Wrapper { public function writeStream(string $path, $stream, int $size = null): int { // always fall back to fopen $target = $this->fopen($path, 'w'); - list($count, $result) = \OC_Helper::streamCopy($stream, $target); + [$count, $result] = \OC_Helper::streamCopy($stream, $target); fclose($target); return $count; } diff --git a/lib/private/Files/Storage/Wrapper/Jail.php b/lib/private/Files/Storage/Wrapper/Jail.php index 93380baac5e..929a4942562 100644 --- a/lib/private/Files/Storage/Wrapper/Jail.php +++ b/lib/private/Files/Storage/Wrapper/Jail.php @@ -539,4 +539,8 @@ class Jail extends Wrapper { return $count; } } + + public function getDirectoryContent($directory): \Traversable { + return $this->getWrapperStorage()->getDirectoryContent($this->getJailedPath($directory)); + } } diff --git a/lib/private/Files/Storage/Wrapper/PermissionsMask.php b/lib/private/Files/Storage/Wrapper/PermissionsMask.php index c2cea31bd5a..6b453b4380a 100644 --- a/lib/private/Files/Storage/Wrapper/PermissionsMask.php +++ b/lib/private/Files/Storage/Wrapper/PermissionsMask.php @@ -157,4 +157,13 @@ class PermissionsMask extends Wrapper { } return parent::getScanner($path, $storage); } + + public function getDirectoryContent($directory): \Traversable { + foreach ($this->getWrapperStorage()->getDirectoryContent($directory) as $data) { + $data['scan_permissions'] = isset($data['scan_permissions']) ? $data['scan_permissions'] : $data['permissions']; + $data['permissions'] &= $this->mask; + + yield $data; + } + } } diff --git a/lib/private/Files/Storage/Wrapper/Wrapper.php b/lib/private/Files/Storage/Wrapper/Wrapper.php index d67af5cb22e..4584bebe076 100644 --- a/lib/private/Files/Storage/Wrapper/Wrapper.php +++ b/lib/private/Files/Storage/Wrapper/Wrapper.php @@ -637,4 +637,8 @@ class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage, IWriteStrea return $count; } } + + public function getDirectoryContent($directory): \Traversable { + return $this->getWrapperStorage()->getDirectoryContent($directory); + } } |