diff options
-rw-r--r-- | lib/private/Files/Cache/Scanner.php | 5 | ||||
-rw-r--r-- | lib/private/Files/Filesystem.php | 10 | ||||
-rw-r--r-- | lib/private/Files/Storage/Common.php | 7 | ||||
-rw-r--r-- | lib/private/Files/Storage/Local.php | 18 |
4 files changed, 30 insertions, 10 deletions
diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php index bd8db2c8a12..af412dd129b 100644 --- a/lib/private/Files/Cache/Scanner.php +++ b/lib/private/Files/Cache/Scanner.php @@ -36,7 +36,6 @@ namespace OC\Files\Cache; use Doctrine\DBAL\Exception; -use OC\Files\Filesystem; use OC\Files\Storage\Wrapper\Jail; use OC\Files\Storage\Wrapper\Encoding; use OC\Hooks\BasicEmitter; @@ -140,8 +139,8 @@ class Scanner extends BasicEmitter implements IScanner { return null; } } - // only proceed if $file is not a partial file nor a blacklisted file - if (!self::isPartialFile($file) and !Filesystem::isFileBlacklisted($file)) { + // only proceed if $file is not a partial file, blacklist is handled by the storage + if (!self::isPartialFile($file)) { //acquire a lock if ($lock) { diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php index 1aedad93aa1..9db9252037f 100644 --- a/lib/private/Files/Filesystem.php +++ b/lib/private/Files/Filesystem.php @@ -66,6 +66,9 @@ class Filesystem { private static $listeningForProviders = false; + /** @var string[]|null */ + private static $blacklist = null; + /** * classname which used for hooks handling * used as signalclass in OC_Hooks::emit() @@ -492,9 +495,12 @@ class Filesystem { public static function isFileBlacklisted($filename) { $filename = self::normalizePath($filename); - $blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', ['.htaccess']); + if (self::$blacklist === null) { + self::$blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', ['.htaccess']); + } + $filename = strtolower(basename($filename)); - return in_array($filename, $blacklist); + return in_array($filename, self::$blacklist); } /** diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php index 7239c58a8a1..8e7e56e6ca2 100644 --- a/lib/private/Files/Storage/Common.php +++ b/lib/private/Files/Storage/Common.php @@ -52,6 +52,7 @@ use OC\Files\Storage\Wrapper\Jail; use OC\Files\Storage\Wrapper\Wrapper; use OCP\Files\EmptyFileNameException; use OCP\Files\FileNameTooLongException; +use OCP\Files\ForbiddenException; use OCP\Files\GenericFileException; use OCP\Files\InvalidCharacterInPathException; use OCP\Files\InvalidDirectoryException; @@ -702,6 +703,10 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { * @inheritdoc */ public function getMetaData($path) { + if (Filesystem::isFileBlacklisted($path)) { + throw new ForbiddenException('Invalid path: ' . $path, false); + } + $permissions = $this->getPermissions($path); if (!$permissions & \OCP\Constants::PERMISSION_READ) { //can't read, nothing we can do @@ -880,7 +885,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage { if (is_resource($dh)) { $basePath = rtrim($directory, '/'); while (($file = readdir($dh)) !== false) { - if (!Filesystem::isIgnoredDir($file) && !Filesystem::isFileBlacklisted($file)) { + if (!Filesystem::isIgnoredDir($file)) { $childPath = $basePath . '/' . trim($file, '/'); $metadata = $this->getMetaData($childPath); if ($metadata !== null) { diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php index 6406beaeebc..34ab9a5fc97 100644 --- a/lib/private/Files/Storage/Local.php +++ b/lib/private/Files/Storage/Local.php @@ -47,7 +47,9 @@ use OC\Files\Storage\Wrapper\Jail; use OCP\Constants; use OCP\Files\ForbiddenException; use OCP\Files\GenericFileException; +use OCP\Files\IMimeTypeDetector; use OCP\Files\Storage\IStorage; +use OCP\IConfig; use OCP\ILogger; /** @@ -60,6 +62,10 @@ class Local extends \OC\Files\Storage\Common { protected $realDataDir; + private IConfig $config; + + private IMimeTypeDetector $mimeTypeDetector; + public function __construct($arguments) { if (!isset($arguments['datadir']) || !is_string($arguments['datadir'])) { throw new \InvalidArgumentException('No data directory set for local storage'); @@ -76,6 +82,8 @@ class Local extends \OC\Files\Storage\Common { $this->datadir .= '/'; } $this->dataDirLength = strlen($this->realDataDir); + $this->config = \OC::$server->get(IConfig::class); + $this->mimeTypeDetector = \OC::$server->get(IMimeTypeDetector::class); } public function __destruct() { @@ -155,6 +163,9 @@ class Local extends \OC\Files\Storage\Common { $statResult['size'] = $filesize; $statResult[7] = $filesize; } + if (is_array($statResult)) { + $statResult['full_path'] = $fullPath; + } return $statResult; } @@ -181,15 +192,14 @@ class Local extends \OC\Files\Storage\Common { } if (!($path === '' || $path === '/')) { // deletable depends on the parents unix permissions - $fullPath = $this->getSourcePath($path); - $parent = dirname($fullPath); + $parent = dirname($stat['full_path']); if (is_writable($parent)) { $permissions += Constants::PERMISSION_DELETE; } } $data = []; - $data['mimetype'] = $isDir ? 'httpd/unix-directory' : \OC::$server->getMimeTypeDetector()->detectPath($path); + $data['mimetype'] = $isDir ? 'httpd/unix-directory' : $this->mimeTypeDetector->detectPath($path); $data['mtime'] = $stat['mtime']; if ($data['mtime'] === false) { $data['mtime'] = time(); @@ -450,7 +460,7 @@ class Local extends \OC\Files\Storage\Common { $fullPath = $this->datadir . $path; $currentPath = $path; - $allowSymlinks = \OC::$server->getConfig()->getSystemValue('localstorage.allowsymlinks', false); + $allowSymlinks = $this->config->getSystemValue('localstorage.allowsymlinks', false); if ($allowSymlinks || $currentPath === '') { return $fullPath; } |