Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix search in nested jails
Signed-off-by: Robin Appelman <[email protected]>
  • Loading branch information
icewind1991 committed Jan 26, 2021
commit 5ae0be08b47d423ad5e48d84368543852f6d42e0
4 changes: 4 additions & 0 deletions apps/files_sharing/lib/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ protected function getRoot() {
return $this->root;
}

protected function getGetUnjailedRoot() {
return $this->sourceRootInfo->getPath();
}

public function getCache() {
if (is_null($this->cache)) {
$sourceStorage = $this->storage->getSourceStorage();
Expand Down
36 changes: 36 additions & 0 deletions apps/files_sharing/tests/CacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -517,4 +517,40 @@ public function testShareJailedStorage() {

$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);
}
}
54 changes: 35 additions & 19 deletions lib/private/Files/Cache/Wrapper/CacheJail.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class CacheJail extends CacheWrapper {
* @var string
*/
protected $root;
protected $unjailedRoot;

/**
* @param \OCP\Files\Cache\ICache $cache
Expand All @@ -56,12 +57,27 @@ public function __construct($cache, $root) {
$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();
Expand All @@ -72,16 +88,20 @@ protected function getSourcePath($path) {

/**
* @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;
Expand All @@ -99,11 +119,6 @@ protected function formatCacheEntry($entry) {
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
*
Expand Down Expand Up @@ -216,9 +231,10 @@ public function getStatus($file) {
}

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);
}

/**
Expand All @@ -239,8 +255,8 @@ public function search($pattern) {
$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)));

Expand All @@ -267,8 +283,8 @@ public function searchByMime($mimetype) {
$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, '/')) {
Expand All @@ -291,12 +307,12 @@ public function searchQuery(ISearchQuery $query) {
$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,
Expand Down
5 changes: 3 additions & 2 deletions lib/private/Share20/Share.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

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;
Expand Down Expand Up @@ -233,8 +234,8 @@ public function setNodeType($type) {
*/
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;
Expand Down
18 changes: 18 additions & 0 deletions tests/lib/Files/Cache/Wrapper/CacheJailTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,22 @@ public function testMoveBetweenJail() {
$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']);
}
}