From 132a02d6a827eb31438ab02cecdb2687ae8a5849 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 25 May 2015 01:48:07 +0200 Subject: [PATCH] exclude directories from beeing processed extended case: search at any place of the path given adding case insensitiveness added suggestions and improvements --- apps/files/ajax/newfile.php | 9 +++++++++ apps/files/ajax/newfolder.php | 9 +++++++++ config/config.sample.php | 13 ++++++++++++ .../sabre/custompropertiesbackend.php | 3 +++ lib/private/connector/sabre/directory.php | 6 ++++++ lib/private/connector/sabre/objecttree.php | 4 ++++ lib/private/files/cache/scanner.php | 4 +++- lib/private/files/filesystem.php | 20 +++++++++++++++++++ lib/private/files/view.php | 3 +++ 9 files changed, 70 insertions(+), 1 deletion(-) diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php index b4e1e508a3f3..69f1eb66f624 100644 --- a/apps/files/ajax/newfile.php +++ b/apps/files/ajax/newfile.php @@ -62,6 +62,15 @@ exit(); } +if (\OC\Files\Filesystem::isExcludedDir($fileName)) { + $result['data'] = array('message' => $l10n->t( + 'The name %s has been excluded by the admin for files and directories. Please choose a different name.', + $fileName) + ); + OCP\JSON::error($result); + exit(); +} + $target = $dir.'/'.$fileName; if (\OC\Files\Filesystem::file_exists($target)) { diff --git a/apps/files/ajax/newfolder.php b/apps/files/ajax/newfolder.php index 90bc9ecbb834..0dfade0e39ed 100644 --- a/apps/files/ajax/newfolder.php +++ b/apps/files/ajax/newfolder.php @@ -54,6 +54,15 @@ return; } +if (\OC\Files\Filesystem::isExcludedDir($folderName)) { + $result['data'] = array('message' => $l10n->t( + 'The name %s has been excluded by the admin for files and directories. Please choose a different name.', + $folderName) + ); + OCP\JSON::error($result); + exit(); +} + if (!\OC\Files\Filesystem::file_exists($dir . '/')) { $result['data'] = array('message' => (string)$l10n->t( 'The target folder has been moved or deleted.'), diff --git a/config/config.sample.php b/config/config.sample.php index 9a40f82252a8..ac9d5f6aa4bb 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -803,6 +803,19 @@ */ 'blacklisted_files' => array('.htaccess'), +/** + * Exclude specific directory names and disallow + * scanning, creating and renaming using these names. Case insensitive. + * Excluded directories will not show up. + * Use when the storage backend supports eg snapshot directories to be excluded. + * WARNING: USE THIS ONLY IF YOU KNOW WHAT YOU ARE DOING. + */ +'excluded_directories' => + array ( + '.snapshot', + '~snapshot', + ), + /** * Define a default folder for shared files and folders other than root. */ diff --git a/lib/private/connector/sabre/custompropertiesbackend.php b/lib/private/connector/sabre/custompropertiesbackend.php index 44092534d6d7..d83a2beee8ab 100644 --- a/lib/private/connector/sabre/custompropertiesbackend.php +++ b/lib/private/connector/sabre/custompropertiesbackend.php @@ -103,6 +103,9 @@ public function propFind($path, PropFind $propFind) { } catch (ServiceUnavailable $e) { // might happen for unavailable mount points, skip return; + } catch (Forbidden $e) { + // might happen for excluded mount points, skip + return; } catch (NotFound $e) { // in some rare (buggy) cases the node might not be found, // we catch the exception to prevent breaking the whole list with a 404 diff --git a/lib/private/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php index 67fdbb28dea1..0a1f07e78432 100644 --- a/lib/private/connector/sabre/directory.php +++ b/lib/private/connector/sabre/directory.php @@ -71,6 +71,12 @@ class Directory extends \OC\Connector\Sabre\Node */ public function createFile($name, $data = null) { + # the check here is necessary, because createFile uses put covered in sabre/file.php + # and not touch covered in files/view.php + if (\OC\Files\Filesystem::isExcludedDir($name)) { + throw new \Sabre\DAV\Exception\Forbidden(); + } + try { // for chunked upload also updating a existing file is a "createFile" // because we create all the chunks before re-assemble them to the existing file. diff --git a/lib/private/connector/sabre/objecttree.php b/lib/private/connector/sabre/objecttree.php index 8def14e8e9c1..a408a8236ef9 100644 --- a/lib/private/connector/sabre/objecttree.php +++ b/lib/private/connector/sabre/objecttree.php @@ -101,6 +101,10 @@ public function getNodeForPath($path) { if (!$this->fileView) { throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup'); } + // if the path has been entered manually and eg not via a file explorer + if (\OC\Files\Filesystem::isExcludedDir($path, true)) { + throw new \Sabre\DAV\Exception\Forbidden(); + } $path = trim($path, '/'); if (isset($this->cache[$path])) { diff --git a/lib/private/files/cache/scanner.php b/lib/private/files/cache/scanner.php index d253afbfa1d0..e034978cc04b 100644 --- a/lib/private/files/cache/scanner.php +++ b/lib/private/files/cache/scanner.php @@ -277,7 +277,9 @@ protected function getNewChildren($folder) { if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { if (!Filesystem::isIgnoredDir($file)) { - $children[] = $file; + if (!Filesystem::isExcludedDir($file)) { + $children[] = $file; + } } } } diff --git a/lib/private/files/filesystem.php b/lib/private/files/filesystem.php index 10c64e1301ae..e9a2754204c9 100644 --- a/lib/private/files/filesystem.php +++ b/lib/private/files/filesystem.php @@ -587,6 +587,26 @@ static public function isIgnoredDir($dir) { return false; } + /** + * check if the directory should be excluded + * A config.php parameter array can contain additional directory names to be excluded + * @param String $dir + * @return boolean + */ + static public function isExcludedDir($dir, $inDir = false) { + $excluded = array(); + $path_parts = array(); + $excluded = \OC::$server->getSystemConfig()->getValue('excluded_directories', array()); + $path_parts = explode('/', $dir); + $excluded = array_map('strtolower', $excluded); + $path_parts = array_map('strtolower', $path_parts); + $match = array_intersect($path_parts, $excluded); + if ($match) { + return true; + } + return false; + } + /** * following functions are equivalent to their php builtin equivalents for arguments/return values. */ diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 63af2b616cff..c82074a180e5 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -596,6 +596,7 @@ public function rename($path1, $path2) { Filesystem::isValidPath($path2) and Filesystem::isValidPath($path1) and !Filesystem::isFileBlacklisted($path2) + and !Filesystem::isExcludedDir($path2) ) { $path1 = $this->getRelativePath($absolutePath1); $path2 = $this->getRelativePath($absolutePath2); @@ -699,6 +700,7 @@ public function copy($path1, $path2, $preserveMtime = false) { Filesystem::isValidPath($path2) and Filesystem::isValidPath($path1) and !Filesystem::isFileBlacklisted($path2) + and !Filesystem::isExcludedDir($path2) ) { $path1 = $this->getRelativePath($absolutePath1); $path2 = $this->getRelativePath($absolutePath2); @@ -923,6 +925,7 @@ private function basicOperation($operation, $path, $hooks = array(), $extraParam $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path)); if (Filesystem::isValidPath($path) and !Filesystem::isFileBlacklisted($path) + and !Filesystem::isExcludedDir($path) ) { $path = $this->getRelativePath($absolutePath); if ($path == null) {