diff options
Diffstat (limited to 'lib/private/Files/Storage/Common.php')
-rw-r--r-- | lib/private/Files/Storage/Common.php | 441 |
1 files changed, 155 insertions, 286 deletions
diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php index e613e435f03..2dc359169d7 100644 --- a/lib/private/Files/Storage/Common.php +++ b/lib/private/Files/Storage/Common.php @@ -13,21 +13,28 @@ use OC\Files\Cache\Propagator; use OC\Files\Cache\Scanner; use OC\Files\Cache\Updater; use OC\Files\Cache\Watcher; +use OC\Files\FilenameValidator; use OC\Files\Filesystem; +use OC\Files\ObjectStore\ObjectStoreStorage; +use OC\Files\Storage\Wrapper\Encryption; use OC\Files\Storage\Wrapper\Jail; use OC\Files\Storage\Wrapper\Wrapper; -use OCP\Files\EmptyFileNameException; -use OCP\Files\FileNameTooLongException; +use OCP\Files; +use OCP\Files\Cache\ICache; +use OCP\Files\Cache\IPropagator; +use OCP\Files\Cache\IScanner; +use OCP\Files\Cache\IUpdater; +use OCP\Files\Cache\IWatcher; use OCP\Files\ForbiddenException; use OCP\Files\GenericFileException; -use OCP\Files\InvalidCharacterInPathException; -use OCP\Files\InvalidDirectoryException; +use OCP\Files\IFilenameValidator; use OCP\Files\InvalidPathException; -use OCP\Files\ReservedWordException; +use OCP\Files\Storage\IConstructableStorage; use OCP\Files\Storage\ILockingStorage; use OCP\Files\Storage\IStorage; use OCP\Files\Storage\IWriteStreamStorage; use OCP\Files\StorageNotAvailableException; +use OCP\IConfig; use OCP\Lock\ILockingProvider; use OCP\Lock\LockedException; use OCP\Server; @@ -44,85 +51,75 @@ use Psr\Log\LoggerInterface; * Some \OC\Files\Storage\Common methods call functions which are first defined * in classes which extend it, e.g. $this->stat() . */ -abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { +abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage, IConstructableStorage { use LocalTempFileTrait; - protected $cache; - protected $scanner; - protected $watcher; - protected $propagator; + protected ?Cache $cache = null; + protected ?Scanner $scanner = null; + protected ?Watcher $watcher = null; + protected ?Propagator $propagator = null; protected $storageCache; - protected $updater; + protected ?Updater $updater = null; - protected $mountOptions = []; + protected array $mountOptions = []; protected $owner = null; - /** @var ?bool */ - private $shouldLogLocks = null; - /** @var ?LoggerInterface */ - private $logger; + private ?bool $shouldLogLocks = null; + private ?LoggerInterface $logger = null; + private ?IFilenameValidator $filenameValidator = null; - public function __construct($parameters) { + public function __construct(array $parameters) { } - /** - * Remove a file or folder - * - * @param string $path - * @return bool - */ - protected function remove($path) { - if ($this->is_dir($path)) { - return $this->rmdir($path); - } elseif ($this->is_file($path)) { - return $this->unlink($path); - } else { - return false; + protected function remove(string $path): bool { + if ($this->file_exists($path)) { + if ($this->is_dir($path)) { + return $this->rmdir($path); + } elseif ($this->is_file($path)) { + return $this->unlink($path); + } } + return false; } - public function is_dir($path) { + public function is_dir(string $path): bool { return $this->filetype($path) === 'dir'; } - public function is_file($path) { + public function is_file(string $path): bool { return $this->filetype($path) === 'file'; } - public function filesize($path): false|int|float { + public function filesize(string $path): int|float|false { if ($this->is_dir($path)) { return 0; //by definition } else { $stat = $this->stat($path); - if (isset($stat['size'])) { - return $stat['size']; - } else { - return 0; - } + return isset($stat['size']) ? $stat['size'] : 0; } } - public function isReadable($path) { + public function isReadable(string $path): bool { // at least check whether it exists // subclasses might want to implement this more thoroughly return $this->file_exists($path); } - public function isUpdatable($path) { + public function isUpdatable(string $path): bool { // at least check whether it exists // subclasses might want to implement this more thoroughly // a non-existing file/folder isn't updatable return $this->file_exists($path); } - public function isCreatable($path) { + public function isCreatable(string $path): bool { if ($this->is_dir($path) && $this->isUpdatable($path)) { return true; } return false; } - public function isDeletable($path) { + public function isDeletable(string $path): bool { if ($path === '' || $path === '/') { return $this->isUpdatable($path); } @@ -130,11 +127,11 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { return $this->isUpdatable($parent) && $this->isUpdatable($path); } - public function isSharable($path) { + public function isSharable(string $path): bool { return $this->isReadable($path); } - public function getPermissions($path) { + public function getPermissions(string $path): int { $permissions = 0; if ($this->isCreatable($path)) { $permissions |= \OCP\Constants::PERMISSION_CREATE; @@ -154,7 +151,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { return $permissions; } - public function filemtime($path) { + public function filemtime(string $path): int|false { $stat = $this->stat($path); if (isset($stat['mtime']) && $stat['mtime'] > 0) { return $stat['mtime']; @@ -163,8 +160,8 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { } } - public function file_get_contents($path) { - $handle = $this->fopen($path, "r"); + public function file_get_contents(string $path): string|false { + $handle = $this->fopen($path, 'r'); if (!$handle) { return false; } @@ -173,8 +170,8 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { return $data; } - public function file_put_contents($path, $data) { - $handle = $this->fopen($path, "w"); + public function file_put_contents(string $path, mixed $data): int|float|false { + $handle = $this->fopen($path, 'w'); if (!$handle) { return false; } @@ -184,19 +181,19 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { return $count; } - public function rename($source, $target) { + public function rename(string $source, string $target): bool { $this->remove($target); $this->removeCachedFile($source); return $this->copy($source, $target) and $this->remove($source); } - public function copy($source, $target) { + public function copy(string $source, string $target): bool { if ($this->is_dir($source)) { $this->remove($target); $dir = $this->opendir($source); $this->mkdir($target); - while ($file = readdir($dir)) { + while (($file = readdir($dir)) !== false) { if (!Filesystem::isIgnoredDir($file)) { if (!$this->copy($source . '/' . $file, $target . '/' . $file)) { closedir($dir); @@ -209,16 +206,16 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { } else { $sourceStream = $this->fopen($source, 'r'); $targetStream = $this->fopen($target, 'w'); - [, $result] = \OC_Helper::streamCopy($sourceStream, $targetStream); + [, $result] = Files::streamCopy($sourceStream, $targetStream, true); if (!$result) { - \OCP\Server::get(LoggerInterface::class)->warning("Failed to write data while copying $source to $target"); + Server::get(LoggerInterface::class)->warning("Failed to write data while copying $source to $target"); } $this->removeCachedFile($target); return $result; } } - public function getMimeType($path) { + public function getMimeType(string $path): string|false { if ($this->is_dir($path)) { return 'httpd/unix-directory'; } elseif ($this->file_exists($path)) { @@ -228,31 +225,26 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { } } - public function hash($type, $path, $raw = false) { + public function hash(string $type, string $path, bool $raw = false): string|false { $fh = $this->fopen($path, 'rb'); + if (!$fh) { + return false; + } $ctx = hash_init($type); hash_update_stream($ctx, $fh); fclose($fh); return hash_final($ctx, $raw); } - public function search($query) { - return $this->searchInDir($query); - } - - public function getLocalFile($path) { + public function getLocalFile(string $path): string|false { return $this->getCachedFile($path); } - /** - * @param string $path - * @param string $target - */ - private function addLocalFolder($path, $target) { + private function addLocalFolder(string $path, string $target): void { $dh = $this->opendir($path); if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { - if (!\OC\Files\Filesystem::isIgnoredDir($file)) { + if (!Filesystem::isIgnoredDir($file)) { if ($this->is_dir($path . '/' . $file)) { mkdir($target . '/' . $file); $this->addLocalFolder($path . '/' . $file, $target . '/' . $file); @@ -265,17 +257,12 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { } } - /** - * @param string $query - * @param string $dir - * @return array - */ - protected function searchInDir($query, $dir = '') { + protected function searchInDir(string $query, string $dir = ''): array { $files = []; $dh = $this->opendir($dir); if (is_resource($dh)) { while (($item = readdir($dh)) !== false) { - if (\OC\Files\Filesystem::isIgnoredDir($item)) { + if (Filesystem::isIgnoredDir($item)) { continue; } if (strstr(strtolower($item), strtolower($query)) !== false) { @@ -291,18 +278,15 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { } /** + * @inheritDoc * Check if a file or folder has been updated since $time * * The method is only used to check if the cache needs to be updated. Storage backends that don't support checking * the mtime should always return false here. As a result storage implementations that always return false expect * exclusive access to the backend and will not pick up files that have been added in a way that circumvents * Nextcloud filesystem. - * - * @param string $path - * @param int $time - * @return bool */ - public function hasUpdated($path, $time) { + public function hasUpdated(string $path, int $time): bool { return $this->filemtime($path) > $time; } @@ -314,76 +298,78 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { return $dependencies; } - public function getCache($path = '', $storage = null) { + public function getCache(string $path = '', ?IStorage $storage = null): ICache { if (!$storage) { $storage = $this; } + /** @var self $storage */ if (!isset($storage->cache)) { $storage->cache = new Cache($storage, $this->getCacheDependencies()); } return $storage->cache; } - public function getScanner($path = '', $storage = null) { + public function getScanner(string $path = '', ?IStorage $storage = null): IScanner { if (!$storage) { $storage = $this; } + if (!$storage->instanceOfStorage(self::class)) { + throw new \InvalidArgumentException('Storage is not of the correct class'); + } if (!isset($storage->scanner)) { $storage->scanner = new Scanner($storage); } return $storage->scanner; } - public function getWatcher($path = '', $storage = null) { + public function getWatcher(string $path = '', ?IStorage $storage = null): IWatcher { if (!$storage) { $storage = $this; } if (!isset($this->watcher)) { $this->watcher = new Watcher($storage); - $globalPolicy = \OC::$server->getConfig()->getSystemValue('filesystem_check_changes', Watcher::CHECK_NEVER); + $globalPolicy = Server::get(IConfig::class)->getSystemValueInt('filesystem_check_changes', Watcher::CHECK_NEVER); $this->watcher->setPolicy((int)$this->getMountOption('filesystem_check_changes', $globalPolicy)); } return $this->watcher; } - /** - * get a propagator instance for the cache - * - * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher - * @return \OC\Files\Cache\Propagator - */ - public function getPropagator($storage = null) { + public function getPropagator(?IStorage $storage = null): IPropagator { if (!$storage) { $storage = $this; } + if (!$storage->instanceOfStorage(self::class)) { + throw new \InvalidArgumentException('Storage is not of the correct class'); + } + /** @var self $storage */ if (!isset($storage->propagator)) { - $config = \OC::$server->getSystemConfig(); - $storage->propagator = new Propagator($storage, \OC::$server->getDatabaseConnection(), ['appdata_' . $config->getValue('instanceid')]); + $config = Server::get(IConfig::class); + $storage->propagator = new Propagator($storage, \OC::$server->getDatabaseConnection(), ['appdata_' . $config->getSystemValueString('instanceid')]); } return $storage->propagator; } - public function getUpdater($storage = null) { + public function getUpdater(?IStorage $storage = null): IUpdater { if (!$storage) { $storage = $this; } + if (!$storage->instanceOfStorage(self::class)) { + throw new \InvalidArgumentException('Storage is not of the correct class'); + } + /** @var self $storage */ if (!isset($storage->updater)) { $storage->updater = new Updater($storage); } return $storage->updater; } - public function getStorageCache($storage = null) { - return $this->getCache($storage)->getStorageCache(); + public function getStorageCache(?IStorage $storage = null): \OC\Files\Cache\Storage { + /** @var Cache $cache */ + $cache = $this->getCache(storage: $storage); + return $cache->getStorageCache(); } - /** - * get the owner of a path - * - * @param string $path The path to get the owner - * @return string|false uid or false - */ - public function getOwner($path) { + public function getOwner(string $path): string|false { if ($this->owner === null) { $this->owner = \OC_User::getUser(); } @@ -391,13 +377,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { return $this->owner; } - /** - * get the ETag for a file or folder - * - * @param string $path - * @return string - */ - public function getETag($path) { + public function getETag(string $path): string|false { return uniqid(); } @@ -408,8 +388,8 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { * @param string $path The path to clean * @return string cleaned path */ - public function cleanPath($path) { - if (strlen($path) == 0 or $path[0] != '/') { + public function cleanPath(string $path): string { + if (strlen($path) == 0 || $path[0] != '/') { $path = '/' . $path; } @@ -427,39 +407,28 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { /** * Test a storage for availability - * - * @return bool */ - public function test() { + public function test(): bool { try { if ($this->stat('')) { return true; } - \OC::$server->get(LoggerInterface::class)->info("External storage not available: stat() failed"); + Server::get(LoggerInterface::class)->info('External storage not available: stat() failed'); return false; } catch (\Exception $e) { - \OC::$server->get(LoggerInterface::class)->warning( - "External storage not available: " . $e->getMessage(), + Server::get(LoggerInterface::class)->warning( + 'External storage not available: ' . $e->getMessage(), ['exception' => $e] ); return false; } } - /** - * get the free space in the storage - * - * @param string $path - * @return int|float|false - */ - public function free_space($path) { + public function free_space(string $path): int|float|false { return \OCP\Files\FileInfo::SPACE_UNKNOWN; } - /** - * {@inheritdoc} - */ - public function isLocal() { + public function isLocal(): bool { // the common implementation returns a temporary file by // default, which is not local return false; @@ -467,11 +436,8 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { /** * Check if the storage is an instance of $class or is a wrapper for a storage that is an instance of $class - * - * @param string $class - * @return bool */ - public function instanceOfStorage($class) { + public function instanceOfStorage(string $class): bool { if (ltrim($class, '\\') === 'OC\Files\Storage\Shared') { // FIXME Temporary fix to keep existing checks working $class = '\OCA\Files_Sharing\SharedStorage'; @@ -483,107 +449,49 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { * A custom storage implementation can return an url for direct download of a give file. * * For now the returned array can hold the parameter url - in future more attributes might follow. - * - * @param string $path - * @return array|false */ - public function getDirectDownload($path) { + public function getDirectDownload(string $path): array|false { return []; } - /** - * @inheritdoc - * @throws InvalidPathException - */ - public function verifyPath($path, $fileName) { - // verify empty and dot files - $trimmed = trim($fileName); - if ($trimmed === '') { - throw new EmptyFileNameException(); - } - - if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) { - throw new InvalidDirectoryException(); - } + public function verifyPath(string $path, string $fileName): void { + $this->getFilenameValidator() + ->validateFilename($fileName); - if (!\OC::$server->getDatabaseConnection()->supports4ByteText()) { - // verify database - e.g. mysql only 3-byte chars - if (preg_match('%(?: - \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 - | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 - | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 -)%xs', $fileName)) { - throw new InvalidCharacterInPathException(); + // verify also the path is valid + if ($path && $path !== '/' && $path !== '.') { + try { + $this->verifyPath(dirname($path), basename($path)); + } catch (InvalidPathException $e) { + // Ignore invalid file type exceptions on directories + if ($e->getCode() !== FilenameValidator::INVALID_FILE_TYPE) { + $l = \OCP\Util::getL10N('lib'); + throw new InvalidPathException($l->t('Invalid parent path'), previous: $e); + } } } - - // 255 characters is the limit on common file systems (ext/xfs) - // oc_filecache has a 250 char length limit for the filename - if (isset($fileName[250])) { - throw new FileNameTooLongException(); - } - - // NOTE: $path will remain unverified for now - $this->verifyPosixPath($fileName); } /** - * @param string $fileName - * @throws InvalidPathException + * Get the filename validator + * (cached for performance) */ - protected function verifyPosixPath($fileName) { - $invalidChars = \OCP\Util::getForbiddenFileNameChars(); - $this->scanForInvalidCharacters($fileName, $invalidChars); - - $fileName = trim($fileName); - $reservedNames = ['*']; - if (in_array($fileName, $reservedNames)) { - throw new ReservedWordException(); + protected function getFilenameValidator(): IFilenameValidator { + if ($this->filenameValidator === null) { + $this->filenameValidator = Server::get(IFilenameValidator::class); } + return $this->filenameValidator; } - /** - * @param string $fileName - * @param string[] $invalidChars - * @throws InvalidPathException - */ - private function scanForInvalidCharacters(string $fileName, array $invalidChars) { - foreach ($invalidChars as $char) { - if (str_contains($fileName, $char)) { - throw new InvalidCharacterInPathException(); - } - } - - $sanitizedFileName = filter_var($fileName, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW); - if ($sanitizedFileName !== $fileName) { - throw new InvalidCharacterInPathException(); - } - } - - /** - * @param array $options - */ - public function setMountOptions(array $options) { + public function setMountOptions(array $options): void { $this->mountOptions = $options; } - /** - * @param string $name - * @param mixed $default - * @return mixed - */ - public function getMountOption($name, $default = null) { + public function getMountOption(string $name, mixed $default = null): mixed { return $this->mountOptions[$name] ?? $default; } - /** - * @param IStorage $sourceStorage - * @param string $sourceInternalPath - * @param string $targetInternalPath - * @param bool $preserveMtime - * @return bool - */ - public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime = false) { + public function copyFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath, bool $preserveMtime = false): bool { if ($sourceStorage === $this) { return $this->copy($sourceInternalPath, $targetInternalPath); } @@ -593,7 +501,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { $result = $this->mkdir($targetInternalPath); if (is_resource($dh)) { $result = true; - while ($result and ($file = readdir($dh)) !== false) { + while ($result && ($file = readdir($dh)) !== false) { if (!Filesystem::isIgnoredDir($file)) { $result &= $this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file); } @@ -607,7 +515,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { $this->writeStream($targetInternalPath, $source); $result = true; } catch (\Exception $e) { - \OC::$server->get(LoggerInterface::class)->warning('Failed to copy stream to storage', ['exception' => $e]); + Server::get(LoggerInterface::class)->warning('Failed to copy stream to storage', ['exception' => $e]); } } @@ -628,9 +536,6 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { /** * Check if a storage is the same as the current one, including wrapped storages - * - * @param IStorage $storage - * @return bool */ private function isSameStorage(IStorage $storage): bool { while ($storage->instanceOfStorage(Wrapper::class)) { @@ -643,14 +548,11 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { return $storage === $this; } - /** - * @param IStorage $sourceStorage - * @param string $sourceInternalPath - * @param string $targetInternalPath - * @return bool - */ - public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) { - if ($this->isSameStorage($sourceStorage)) { + public function moveFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath): bool { + if ( + !$sourceStorage->instanceOfStorage(Encryption::class) + && $this->isSameStorage($sourceStorage) + ) { // resolve any jailed paths while ($sourceStorage->instanceOfStorage(Jail::class)) { /** @@ -669,19 +571,27 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { $result = $this->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath, true); if ($result) { - if ($sourceStorage->is_dir($sourceInternalPath)) { - $result = $sourceStorage->rmdir($sourceInternalPath); - } else { - $result = $sourceStorage->unlink($sourceInternalPath); + if ($sourceStorage->instanceOfStorage(ObjectStoreStorage::class)) { + /** @var ObjectStoreStorage $sourceStorage */ + $sourceStorage->setPreserveCacheOnDelete(true); + } + try { + if ($sourceStorage->is_dir($sourceInternalPath)) { + $result = $sourceStorage->rmdir($sourceInternalPath); + } else { + $result = $sourceStorage->unlink($sourceInternalPath); + } + } finally { + if ($sourceStorage->instanceOfStorage(ObjectStoreStorage::class)) { + /** @var ObjectStoreStorage $sourceStorage */ + $sourceStorage->setPreserveCacheOnDelete(false); + } } } return $result; } - /** - * @inheritdoc - */ - public function getMetaData($path) { + public function getMetaData(string $path): ?array { if (Filesystem::isFileBlacklisted($path)) { throw new ForbiddenException('Invalid path: ' . $path, false); } @@ -711,13 +621,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { return $data; } - /** - * @param string $path - * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE - * @param \OCP\Lock\ILockingProvider $provider - * @throws \OCP\Lock\LockedException - */ - public function acquireLock($path, $type, ILockingProvider $provider) { + public function acquireLock(string $path, int $type, ILockingProvider $provider): void { $logger = $this->getLockLogger(); if ($logger) { $typeString = ($type === ILockingProvider::LOCK_SHARED) ? 'shared' : 'exclusive'; @@ -744,13 +648,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { } } - /** - * @param string $path - * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE - * @param \OCP\Lock\ILockingProvider $provider - * @throws \OCP\Lock\LockedException - */ - public function releaseLock($path, $type, ILockingProvider $provider) { + public function releaseLock(string $path, int $type, ILockingProvider $provider): void { $logger = $this->getLockLogger(); if ($logger) { $typeString = ($type === ILockingProvider::LOCK_SHARED) ? 'shared' : 'exclusive'; @@ -777,13 +675,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { } } - /** - * @param string $path - * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE - * @param \OCP\Lock\ILockingProvider $provider - * @throws \OCP\Lock\LockedException - */ - public function changeLock($path, $type, ILockingProvider $provider) { + public function changeLock(string $path, int $type, ILockingProvider $provider): void { $logger = $this->getLockLogger(); if ($logger) { $typeString = ($type === ILockingProvider::LOCK_SHARED) ? 'shared' : 'exclusive'; @@ -812,8 +704,8 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { private function getLockLogger(): ?LoggerInterface { if (is_null($this->shouldLogLocks)) { - $this->shouldLogLocks = \OC::$server->getConfig()->getSystemValueBool('filelocking.debug', false); - $this->logger = $this->shouldLogLocks ? \OC::$server->get(LoggerInterface::class) : null; + $this->shouldLogLocks = Server::get(IConfig::class)->getSystemValueBool('filelocking.debug', false); + $this->logger = $this->shouldLogLocks ? Server::get(LoggerInterface::class) : null; } return $this->logger; } @@ -821,54 +713,31 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { /** * @return array [ available, last_checked ] */ - public function getAvailability() { + public function getAvailability(): array { return $this->getStorageCache()->getAvailability(); } - /** - * @param bool $isAvailable - */ - public function setAvailability($isAvailable) { + public function setAvailability(bool $isAvailable): void { $this->getStorageCache()->setAvailability($isAvailable); } - /** - * Allow setting the storage owner - * - * This can be used for storages that do not have a dedicated owner, where we want to - * pass the user that we setup the mountpoint for along to the storage layer - * - * @param string|null $user - * @return void - */ public function setOwner(?string $user): void { $this->owner = $user; } - /** - * @return bool - */ - public function needsPartFile() { + public function needsPartFile(): bool { return true; } - /** - * fallback implementation - * - * @param string $path - * @param resource $stream - * @param int $size - * @return int - */ public function writeStream(string $path, $stream, ?int $size = null): int { $target = $this->fopen($path, 'w'); if (!$target) { throw new GenericFileException("Failed to open $path for writing"); } try { - [$count, $result] = \OC_Helper::streamCopy($stream, $target); + [$count, $result] = Files::streamCopy($stream, $target, true); if (!$result) { - throw new GenericFileException("Failed to copy stream"); + throw new GenericFileException('Failed to copy stream'); } } finally { fclose($target); @@ -877,7 +746,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { return $count; } - public function getDirectoryContent($directory): \Traversable { + public function getDirectoryContent(string $directory): \Traversable { $dh = $this->opendir($directory); if ($dh === false) { |