fix search in nested jails
Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
parent
27f9df2e87
commit
5ae0be08b4
|
@ -89,6 +89,10 @@ class Cache extends CacheJail {
|
||||||
return $this->root;
|
return $this->root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getGetUnjailedRoot() {
|
||||||
|
return $this->sourceRootInfo->getPath();
|
||||||
|
}
|
||||||
|
|
||||||
public function getCache() {
|
public function getCache() {
|
||||||
if (is_null($this->cache)) {
|
if (is_null($this->cache)) {
|
||||||
$sourceStorage = $this->storage->getSourceStorage();
|
$sourceStorage = $this->storage->getSourceStorage();
|
||||||
|
|
|
@ -517,4 +517,40 @@ class CacheTest extends TestCase {
|
||||||
|
|
||||||
$this->assertTrue($sourceStorage->getCache()->inCache('jail/sub/bar.txt'));
|
$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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ class CacheJail extends CacheWrapper {
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $root;
|
protected $root;
|
||||||
|
protected $unjailedRoot;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \OCP\Files\Cache\ICache $cache
|
* @param \OCP\Files\Cache\ICache $cache
|
||||||
|
@ -56,12 +57,27 @@ class CacheJail extends CacheWrapper {
|
||||||
$this->root = $root;
|
$this->root = $root;
|
||||||
$this->connection = \OC::$server->getDatabaseConnection();
|
$this->connection = \OC::$server->getDatabaseConnection();
|
||||||
$this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
|
$this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
|
||||||
|
|
||||||
|
if ($cache instanceof CacheJail) {
|
||||||
|
$this->unjailedRoot = $cache->getSourcePath($root);
|
||||||
|
} else {
|
||||||
|
$this->unjailedRoot = $root;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getRoot() {
|
protected function getRoot() {
|
||||||
return $this->root;
|
return $this->root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the root path with any nested jails resolved
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getGetUnjailedRoot() {
|
||||||
|
return $this->unjailedRoot;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getSourcePath($path) {
|
protected function getSourcePath($path) {
|
||||||
if ($path === '') {
|
if ($path === '') {
|
||||||
return $this->getRoot();
|
return $this->getRoot();
|
||||||
|
@ -72,16 +88,20 @@ class CacheJail extends CacheWrapper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $path
|
* @param string $path
|
||||||
|
* @param null|string $root
|
||||||
* @return null|string the jailed path or null if the path is outside the jail
|
* @return null|string the jailed path or null if the path is outside the jail
|
||||||
*/
|
*/
|
||||||
protected function getJailedPath($path) {
|
protected function getJailedPath(string $path, string $root = null) {
|
||||||
if ($this->getRoot() === '') {
|
if ($root === null) {
|
||||||
|
$root = $this->getRoot();
|
||||||
|
}
|
||||||
|
if ($root === '') {
|
||||||
return $path;
|
return $path;
|
||||||
}
|
}
|
||||||
$rootLength = strlen($this->getRoot()) + 1;
|
$rootLength = strlen($root) + 1;
|
||||||
if ($path === $this->getRoot()) {
|
if ($path === $root) {
|
||||||
return '';
|
return '';
|
||||||
} elseif (substr($path, 0, $rootLength) === $this->getRoot() . '/') {
|
} elseif (substr($path, 0, $rootLength) === $root . '/') {
|
||||||
return substr($path, $rootLength);
|
return substr($path, $rootLength);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
@ -99,11 +119,6 @@ class CacheJail extends CacheWrapper {
|
||||||
return $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
|
* get the stored metadata of a file or folder
|
||||||
*
|
*
|
||||||
|
@ -216,9 +231,10 @@ class CacheJail extends CacheWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function formatSearchResults($results) {
|
private function formatSearchResults($results) {
|
||||||
$results = array_filter($results, [$this, 'filterCacheEntry']);
|
return array_map(function($entry) {
|
||||||
$results = array_values($results);
|
$entry['path'] = $this->getJailedPath($entry['path'], $this->getGetUnjailedRoot());
|
||||||
return array_map([$this, 'formatCacheEntry'], $results);
|
return $entry;
|
||||||
|
}, $results);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -239,8 +255,8 @@ class CacheJail extends CacheWrapper {
|
||||||
$query->selectFileCache()
|
$query->selectFileCache()
|
||||||
->whereStorageId()
|
->whereStorageId()
|
||||||
->andWhere($query->expr()->orX(
|
->andWhere($query->expr()->orX(
|
||||||
$query->expr()->like('path', $query->createNamedParameter($this->getRoot() . '/%')),
|
$query->expr()->like('path', $query->createNamedParameter($this->getGetUnjailedRoot() . '/%')),
|
||||||
$query->expr()->eq('path_hash', $query->createNamedParameter(md5($this->getRoot()))),
|
$query->expr()->eq('path_hash', $query->createNamedParameter(md5($this->getGetUnjailedRoot()))),
|
||||||
))
|
))
|
||||||
->andWhere($query->expr()->iLike('name', $query->createNamedParameter($pattern)));
|
->andWhere($query->expr()->iLike('name', $query->createNamedParameter($pattern)));
|
||||||
|
|
||||||
|
@ -267,8 +283,8 @@ class CacheJail extends CacheWrapper {
|
||||||
$query->selectFileCache()
|
$query->selectFileCache()
|
||||||
->whereStorageId()
|
->whereStorageId()
|
||||||
->andWhere($query->expr()->orX(
|
->andWhere($query->expr()->orX(
|
||||||
$query->expr()->like('path', $query->createNamedParameter($this->getRoot() . '/%')),
|
$query->expr()->like('path', $query->createNamedParameter($this->getGetUnjailedRoot() . '/%')),
|
||||||
$query->expr()->eq('path_hash', $query->createNamedParameter(md5($this->getRoot()))),
|
$query->expr()->eq('path_hash', $query->createNamedParameter(md5($this->getGetUnjailedRoot()))),
|
||||||
));
|
));
|
||||||
|
|
||||||
if (strpos($mimetype, '/')) {
|
if (strpos($mimetype, '/')) {
|
||||||
|
@ -291,12 +307,12 @@ class CacheJail extends CacheWrapper {
|
||||||
$prefixFilter = new SearchComparison(
|
$prefixFilter = new SearchComparison(
|
||||||
ISearchComparison::COMPARE_LIKE,
|
ISearchComparison::COMPARE_LIKE,
|
||||||
'path',
|
'path',
|
||||||
$this->getRoot() . '/%'
|
$this->getGetUnjailedRoot() . '/%'
|
||||||
);
|
);
|
||||||
$rootFilter = new SearchComparison(
|
$rootFilter = new SearchComparison(
|
||||||
ISearchComparison::COMPARE_EQUAL,
|
ISearchComparison::COMPARE_EQUAL,
|
||||||
'path',
|
'path',
|
||||||
$this->getRoot()
|
$this->getGetUnjailedRoot()
|
||||||
);
|
);
|
||||||
$operation = new SearchBinaryOperator(
|
$operation = new SearchBinaryOperator(
|
||||||
ISearchBinaryOperator::OPERATOR_AND,
|
ISearchBinaryOperator::OPERATOR_AND,
|
||||||
|
|
|
@ -32,6 +32,7 @@ namespace OC\Share20;
|
||||||
|
|
||||||
use OCP\Files\Cache\ICacheEntry;
|
use OCP\Files\Cache\ICacheEntry;
|
||||||
use OCP\Files\File;
|
use OCP\Files\File;
|
||||||
|
use OCP\Files\FileInfo;
|
||||||
use OCP\Files\IRootFolder;
|
use OCP\Files\IRootFolder;
|
||||||
use OCP\Files\Node;
|
use OCP\Files\Node;
|
||||||
use OCP\Files\NotFoundException;
|
use OCP\Files\NotFoundException;
|
||||||
|
@ -233,8 +234,8 @@ class Share implements \OCP\Share\IShare {
|
||||||
*/
|
*/
|
||||||
public function getNodeType() {
|
public function getNodeType() {
|
||||||
if ($this->nodeType === null) {
|
if ($this->nodeType === null) {
|
||||||
$node = $this->getNode();
|
$info = $this->getNodeCacheEntry();
|
||||||
$this->nodeType = $node instanceof File ? 'file' : 'folder';
|
$this->nodeType = $info->getMimeType() === FileInfo::MIMETYPE_FOLDER ? 'folder' : 'file';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->nodeType;
|
return $this->nodeType;
|
||||||
|
|
|
@ -182,4 +182,22 @@ class CacheJailTest extends CacheTest {
|
||||||
$this->assertTrue($this->sourceCache->inCache('target/foo'));
|
$this->assertTrue($this->sourceCache->inCache('target/foo'));
|
||||||
$this->assertTrue($this->sourceCache->inCache('target/foo/bar'));
|
$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']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue