summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Petry <pvince81@owncloud.com>2014-01-08 13:17:36 +0100
committerVincent Petry <pvince81@owncloud.com>2014-01-08 13:17:36 +0100
commitf642ad39614970de67358d80517bc1d76a006e0e (patch)
tree3606c38d2a8404307a03cb494e89e55c8206c293
parentbb443ae937bdbc9f50c352d34abeaa0eaa3fa890 (diff)
downloadnextcloud-server-f642ad39614970de67358d80517bc1d76a006e0e.tar.gz
nextcloud-server-f642ad39614970de67358d80517bc1d76a006e0e.zip
Prevent deleting storage root
Storage mount points are not deletable, so make sure that the unlink operation and its hooks aren't run in such cases. Note that some storages might recursively delete their contents when calling unlink on their root. This fix prevents that as well.
-rw-r--r--lib/private/files/view.php13
-rw-r--r--tests/lib/files/view.php42
2 files changed, 55 insertions, 0 deletions
diff --git a/lib/private/files/view.php b/lib/private/files/view.php
index ac45a881331..8893911ed5d 100644
--- a/lib/private/files/view.php
+++ b/lib/private/files/view.php
@@ -336,6 +336,19 @@ class View {
}
public function unlink($path) {
+ if ($path === '' || $path === '/') {
+ // do not allow deleting the root
+ return false;
+ }
+ $postFix = (substr($path, -1, 1) === '/') ? '/' : '';
+ $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
+ list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
+ if (!$internalPath || $internalPath === '' || $internalPath === '/') {
+ // do not allow deleting the storage's root / the mount point
+ // because for some storages it might delete the whole contents
+ // but isn't supposed to work that way
+ return false;
+ }
return $this->basicOperation('unlink', $path, array('delete'));
}
diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php
index b59cef9f0da..76a7fd5f1ca 100644
--- a/tests/lib/files/view.php
+++ b/tests/lib/files/view.php
@@ -309,6 +309,48 @@ class View extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
+ function testUnlink() {
+ $storage1 = $this->getTestStorage();
+ $storage2 = $this->getTestStorage();
+ \OC\Files\Filesystem::mount($storage1, array(), '/');
+ \OC\Files\Filesystem::mount($storage2, array(), '/substorage');
+
+ $rootView = new \OC\Files\View('');
+ $rootView->file_put_contents('/foo.txt', 'asd');
+ $rootView->file_put_contents('/substorage/bar.txt', 'asd');
+
+ $this->assertTrue($rootView->file_exists('foo.txt'));
+ $this->assertTrue($rootView->file_exists('substorage/bar.txt'));
+
+ $this->assertTrue($rootView->unlink('foo.txt'));
+ $this->assertTrue($rootView->unlink('substorage/bar.txt'));
+
+ $this->assertFalse($rootView->file_exists('foo.txt'));
+ $this->assertFalse($rootView->file_exists('substorage/bar.txt'));
+ }
+
+ /**
+ * @medium
+ */
+ function testUnlinkRootMustFail() {
+ $storage1 = $this->getTestStorage();
+ $storage2 = $this->getTestStorage();
+ \OC\Files\Filesystem::mount($storage1, array(), '/');
+ \OC\Files\Filesystem::mount($storage2, array(), '/substorage');
+
+ $rootView = new \OC\Files\View('');
+ $rootView->file_put_contents('/foo.txt', 'asd');
+ $rootView->file_put_contents('/substorage/bar.txt', 'asd');
+
+ $this->assertFalse($rootView->unlink(''));
+ $this->assertFalse($rootView->unlink('/'));
+ $this->assertFalse($rootView->unlink('substorage'));
+ $this->assertFalse($rootView->unlink('/substorage'));
+ }
+
+ /**
+ * @medium
+ */
function testTouch() {
$storage = $this->getTestStorage(true, '\Test\Files\TemporaryNoTouch');