]> source.dussan.org Git - nextcloud-server.git/commitdiff
fix search in nested jails
authorRobin Appelman <robin@icewind.nl>
Mon, 25 Jan 2021 16:38:34 +0000 (17:38 +0100)
committerDaniel Kesselberg <mail@danielkesselberg.de>
Tue, 16 Mar 2021 14:22:22 +0000 (15:22 +0100)
Signed-off-by: Robin Appelman <robin@icewind.nl>
apps/files_sharing/lib/Cache.php
apps/files_sharing/tests/CacheTest.php
lib/private/Files/Cache/Wrapper/CacheJail.php
lib/private/Share20/Share.php
tests/lib/Files/Cache/Wrapper/CacheJailTest.php

index c3f31ac3e4feb4bc6aa6ae7e6885917a9eaa29e1..3a6ade5a2ac3653b02564f7e9d049c7e153a2efb 100644 (file)
@@ -89,6 +89,10 @@ class Cache extends CacheJail {
                return $this->root;
        }
 
+       protected function getGetUnjailedRoot() {
+               return $this->sourceRootInfo->getPath();
+       }
+
        public function getCache() {
                if (is_null($this->cache)) {
                        $sourceStorage = $this->storage->getSourceStorage();
index 7b80bfcaaae0ee6a8d3ad3c275dd90276c5116ca..5c4f26e05b6ce3947b7c63c8915ccafd1644c32b 100644 (file)
@@ -517,4 +517,40 @@ class CacheTest extends TestCase {
 
                $this->assertTrue($sourceStorage->getCache()->inCache('jail/sub/bar.txt'));
        }
+
+       public function testSearchShareJailedStorage() {
+               $sourceStorage = new Temporary();
+               $sourceStorage->mkdir('jail');
+               $sourceStorage->mkdir('jail/sub');
+               $sourceStorage->file_put_contents('jail/sub/foo.txt', 'foo');
+               $jailedSource = new Jail([
+                       'storage' => $sourceStorage,
+                       'root' => 'jail'
+               ]);
+               $sourceStorage->getScanner()->scan('');
+               $this->registerMount(self::TEST_FILES_SHARING_API_USER1, $jailedSource, '/' . self::TEST_FILES_SHARING_API_USER1 . '/files/foo');
+
+               self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
+
+               $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1);
+               $node = $rootFolder->get('foo/sub');
+               $share = $this->shareManager->newShare();
+               $share->setNode($node)
+                       ->setShareType(IShare::TYPE_USER)
+                       ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
+                       ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
+                       ->setPermissions(\OCP\Constants::PERMISSION_ALL);
+               $share = $this->shareManager->createShare($share);
+               $share->setStatus(IShare::STATUS_ACCEPTED);
+               $this->shareManager->updateShare($share);
+               \OC_Util::tearDownFS();
+
+               self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
+
+               /** @var SharedStorage $sharedStorage */
+               list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/sub');
+
+               $results = $sharedStorage->getCache()->search("foo.txt");
+               $this->assertCount(1, $results);
+       }
 }
index 2f873a65cfeee78b2d4212d739349de15f7bb647..d8e2efb2daad9675c3fb197ec296b3330ac77e45 100644 (file)
@@ -46,6 +46,7 @@ class CacheJail extends CacheWrapper {
         * @var string
         */
        protected $root;
+       protected $unjailedRoot;
 
        /**
         * @param \OCP\Files\Cache\ICache $cache
@@ -56,12 +57,27 @@ class CacheJail extends CacheWrapper {
                $this->root = $root;
                $this->connection = \OC::$server->getDatabaseConnection();
                $this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
+
+               if ($cache instanceof CacheJail) {
+                       $this->unjailedRoot = $cache->getSourcePath($root);
+               } else {
+                       $this->unjailedRoot = $root;
+               }
        }
 
        protected function getRoot() {
                return $this->root;
        }
 
+       /**
+        * Get the root path with any nested jails resolved
+        *
+        * @return string
+        */
+       protected function getGetUnjailedRoot() {
+               return $this->unjailedRoot;
+       }
+
        protected function getSourcePath($path) {
                if ($path === '') {
                        return $this->getRoot();
@@ -72,16 +88,20 @@ class CacheJail extends CacheWrapper {
 
        /**
         * @param string $path
+        * @param null|string $root
         * @return null|string the jailed path or null if the path is outside the jail
         */
-       protected function getJailedPath($path) {
-               if ($this->getRoot() === '') {
+       protected function getJailedPath(string $path, string $root = null) {
+               if ($root === null) {
+                       $root = $this->getRoot();
+               }
+               if ($root === '') {
                        return $path;
                }
-               $rootLength = strlen($this->getRoot()) + 1;
-               if ($path === $this->getRoot()) {
+               $rootLength = strlen($root) + 1;
+               if ($path === $root) {
                        return '';
-               } elseif (substr($path, 0, $rootLength) === $this->getRoot() . '/') {
+               } elseif (substr($path, 0, $rootLength) === $root . '/') {
                        return substr($path, $rootLength);
                } else {
                        return null;
@@ -99,11 +119,6 @@ class CacheJail extends CacheWrapper {
                return $entry;
        }
 
-       protected function filterCacheEntry($entry) {
-               $rootLength = strlen($this->getRoot()) + 1;
-               return $rootLength === 1 || ($entry['path'] === $this->getRoot()) || (substr($entry['path'], 0, $rootLength) === $this->getRoot() . '/');
-       }
-
        /**
         * get the stored metadata of a file or folder
         *
@@ -216,9 +231,10 @@ class CacheJail extends CacheWrapper {
        }
 
        private function formatSearchResults($results) {
-               $results = array_filter($results, [$this, 'filterCacheEntry']);
-               $results = array_values($results);
-               return array_map([$this, 'formatCacheEntry'], $results);
+               return array_map(function($entry) {
+                       $entry['path'] = $this->getJailedPath($entry['path'], $this->getGetUnjailedRoot());
+                       return $entry;
+               }, $results);
        }
 
        /**
@@ -239,8 +255,8 @@ class CacheJail extends CacheWrapper {
                $query->selectFileCache()
                        ->whereStorageId()
                        ->andWhere($query->expr()->orX(
-                               $query->expr()->like('path', $query->createNamedParameter($this->getRoot() . '/%')),
-                               $query->expr()->eq('path_hash', $query->createNamedParameter(md5($this->getRoot()))),
+                               $query->expr()->like('path', $query->createNamedParameter($this->getGetUnjailedRoot() . '/%')),
+                               $query->expr()->eq('path_hash', $query->createNamedParameter(md5($this->getGetUnjailedRoot())))
                        ))
                        ->andWhere($query->expr()->iLike('name', $query->createNamedParameter($pattern)));
 
@@ -267,8 +283,8 @@ class CacheJail extends CacheWrapper {
                $query->selectFileCache()
                        ->whereStorageId()
                        ->andWhere($query->expr()->orX(
-                               $query->expr()->like('path', $query->createNamedParameter($this->getRoot() . '/%')),
-                               $query->expr()->eq('path_hash', $query->createNamedParameter(md5($this->getRoot()))),
+                               $query->expr()->like('path', $query->createNamedParameter($this->getGetUnjailedRoot() . '/%')),
+                               $query->expr()->eq('path_hash', $query->createNamedParameter(md5($this->getGetUnjailedRoot())))
                        ));
 
                if (strpos($mimetype, '/')) {
@@ -291,12 +307,12 @@ class CacheJail extends CacheWrapper {
                $prefixFilter = new SearchComparison(
                        ISearchComparison::COMPARE_LIKE,
                        'path',
-                       $this->getRoot() . '/%'
+                       $this->getGetUnjailedRoot() . '/%'
                );
                $rootFilter = new SearchComparison(
                        ISearchComparison::COMPARE_EQUAL,
                        'path',
-                       $this->getRoot()
+                       $this->getGetUnjailedRoot()
                );
                $operation = new SearchBinaryOperator(
                        ISearchBinaryOperator::OPERATOR_AND,
index 69f36edf4f3c858d31ea4efc3ca5122f7405bc8f..9b782d5a446e3b760c70d454b88f603790583e07 100644 (file)
@@ -32,6 +32,7 @@ namespace OC\Share20;
 
 use OCP\Files\Cache\ICacheEntry;
 use OCP\Files\File;
+use OCP\Files\FileInfo;
 use OCP\Files\IRootFolder;
 use OCP\Files\Node;
 use OCP\Files\NotFoundException;
@@ -233,8 +234,8 @@ class Share implements \OCP\Share\IShare {
         */
        public function getNodeType() {
                if ($this->nodeType === null) {
-                       $node = $this->getNode();
-                       $this->nodeType = $node instanceof File ? 'file' : 'folder';
+                       $info = $this->getNodeCacheEntry();
+                       $this->nodeType = $info->getMimeType() === FileInfo::MIMETYPE_FOLDER ? 'folder' : 'file';
                }
 
                return $this->nodeType;
index de54333312b44d9062d1b16ceec73e094eb07977..d9f7af1f034356461b0ecc29af80a1523371f87e 100644 (file)
@@ -182,4 +182,22 @@ class CacheJailTest extends CacheTest {
                $this->assertTrue($this->sourceCache->inCache('target/foo'));
                $this->assertTrue($this->sourceCache->inCache('target/foo/bar'));
        }
+
+       public function testSearchNested() {
+               $this->storage->getScanner()->scan('');
+               $file1 = 'foo';
+               $file2 = 'foo/bar';
+               $file3 = 'foo/bar/asd';
+               $data1 = ['size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'];
+
+               $this->sourceCache->put($file1, $data1);
+               $this->sourceCache->put($file2, $data1);
+               $this->sourceCache->put($file3, $data1);
+
+               $nested = new \OC\Files\Cache\Wrapper\CacheJail($this->cache, 'bar');
+
+               $result = $nested->search('%asd%');
+               $this->assertCount(1, $result);
+               $this->assertEquals('asd', $result[0]['path']);
+       }
 }