diff --git a/apps/dav/lib/Files/FileSearchBackend.php b/apps/dav/lib/Files/FileSearchBackend.php index fd45491da7e0e..1585db326cf3f 100644 --- a/apps/dav/lib/Files/FileSearchBackend.php +++ b/apps/dav/lib/Files/FileSearchBackend.php @@ -30,6 +30,7 @@ use OC\Files\Search\SearchComparison; use OC\Files\Search\SearchOrder; use OC\Files\Search\SearchQuery; +use OC\Files\Storage\Wrapper\Jail; use OC\Files\View; use OCA\DAV\Connector\Sabre\CachingTree; use OCA\DAV\Connector\Sabre\Directory; @@ -39,6 +40,8 @@ use OCP\Files\Folder; use OCP\Files\IRootFolder; use OCP\Files\Node; +use OCP\Files\Search\ISearchBinaryOperator; +use OCP\Files\Search\ISearchComparison; use OCP\Files\Search\ISearchOperator; use OCP\Files\Search\ISearchOrder; use OCP\Files\Search\ISearchQuery; @@ -157,23 +160,37 @@ public function preloadPropertyFor(array $nodes, array $requestProperties): void * @return SearchResult[] */ public function search(Query $search): array { - if (count($search->from) !== 1) { - throw new \InvalidArgumentException('Searching more than one folder is not supported'); - } - $query = $this->transformQuery($search); - $scope = $search->from[0]; - if ($scope->path === null) { - throw new \InvalidArgumentException('Using uri\'s as scope is not supported, please use a path relative to the search arbiter instead'); - } - $node = $this->tree->getNodeForPath($scope->path); - if (!$node instanceof Directory) { - throw new \InvalidArgumentException('Search is only supported on directories'); + $scopes = []; + foreach ($search->from as $scope) { + if ($scope->path === null) { + throw new \InvalidArgumentException('Using uri\'s as scope is not supported, please use a path relative to the search arbiter instead'); + } + $node = $this->tree->getNodeForPath($scope->path); + if (!$node instanceof Directory) { + throw new \InvalidArgumentException('Search is only supported on directories'); + } + $fileInfo = $node->getFileInfo(); + /** @var Folder $folder */ + $folder = $this->rootFolder->get($fileInfo->getPath()); + $folderStorage = $folder->getStorage(); + if ($folderStorage->instanceOfStorage(Jail::class)) { + /** @var Jail $folderStorage */ + $internalPath = $folderStorage->getUnjailedPath($folder->getInternalPath()); + } else { + $internalPath = $folder->getInternalPath(); + } + $scopes[] = new SearchComparison( + ISearchComparison::COMPARE_LIKE, + 'path', + $internalPath . '/%', + '' + ); } - $fileInfo = $node->getFileInfo(); - $folder = $this->rootFolder->get($fileInfo->getPath()); - /** @var Folder $folder $results */ - $results = $folder->search($query); + $scopeOperators = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $scopes); + $query = $this->transformQuery($search, $scopeOperators); + $userFolder = $this->rootFolder->getUserFolder($this->user->getUID()); + $results = $userFolder->search($query); /** @var SearchResult[] $nodes */ $nodes = array_map(function (Node $node) { @@ -288,7 +305,7 @@ private function getHrefForNode(Node $node) { * * @return ISearchQuery */ - private function transformQuery(Query $query): ISearchQuery { + private function transformQuery(Query $query, SearchBinaryOperator $scopeOperators): ISearchQuery { $orders = array_map(function (Order $order): ISearchOrder { $direction = $order->order === Order::ASC ? ISearchOrder::DIRECTION_ASCENDING : ISearchOrder::DIRECTION_DESCENDING; if (str_starts_with($order->property->name, FilesPlugin::FILE_METADATA_PREFIX)) { @@ -316,8 +333,12 @@ private function transformQuery(Query $query): ISearchQuery { throw new \InvalidArgumentException('Invalid search query, maximum operator limit of ' . self::OPERATOR_LIMIT . ' exceeded, got ' . $operatorCount . ' operators'); } + /** @var SearchBinaryOperator|SearchComparison */ + $queryOperators = $this->transformSearchOperation($query->where); + $operators = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [$queryOperators, $scopeOperators]); + return new SearchQuery( - $this->transformSearchOperation($query->where), + $operators, (int)$limit->maxResults, $offset, $orders,