Merge pull request #7323 from nextcloud/shared-jailed-source-root-12
[12]Use the correct root for shared jail when the source storage is also a jail
This commit is contained in:
commit
5dd15c4a7d
|
@ -29,6 +29,7 @@ namespace OCA\Files_Sharing;
|
|||
|
||||
use OC\Files\Cache\FailedCache;
|
||||
use OC\Files\Cache\Wrapper\CacheJail;
|
||||
use OC\Files\Storage\Wrapper\Jail;
|
||||
use OCP\Files\Cache\ICacheEntry;
|
||||
|
||||
/**
|
||||
|
@ -61,12 +62,30 @@ class Cache extends CacheJail {
|
|||
$this->storage = $storage;
|
||||
$this->sourceRootInfo = $sourceRootInfo;
|
||||
$this->numericId = $sourceRootInfo->getStorageId();
|
||||
|
||||
parent::__construct(
|
||||
null,
|
||||
$this->sourceRootInfo->getPath()
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
protected function getRoot() {
|
||||
if (is_null($this->root)) {
|
||||
$absoluteRoot = $this->sourceRootInfo->getPath();
|
||||
|
||||
// the sourceRootInfo path is the absolute path of the folder in the "real" storage
|
||||
// in the case where a folder is shared from a Jail we need to ensure that the share Jail
|
||||
// has it's root set relative to the source Jail
|
||||
$currentStorage = $this->storage->getSourceStorage();
|
||||
if ($currentStorage->instanceOfStorage(Jail::class)) {
|
||||
/** @var Jail $currentStorage */
|
||||
$absoluteRoot = $currentStorage->getJailedPath($absoluteRoot);
|
||||
}
|
||||
$this->root = $absoluteRoot;
|
||||
}
|
||||
return $this->root;
|
||||
}
|
||||
|
||||
public function getCache() {
|
||||
if (is_null($this->cache)) {
|
||||
$sourceStorage = $this->storage->getSourceStorage();
|
||||
|
@ -90,7 +109,7 @@ class Cache extends CacheJail {
|
|||
|
||||
public function get($file) {
|
||||
if ($this->rootUnchanged && ($file === '' || $file === $this->sourceRootInfo->getId())) {
|
||||
return $this->formatCacheEntry(clone $this->sourceRootInfo);
|
||||
return $this->formatCacheEntry(clone $this->sourceRootInfo, '');
|
||||
}
|
||||
return parent::get($file);
|
||||
}
|
||||
|
@ -115,16 +134,20 @@ class Cache extends CacheJail {
|
|||
return parent::moveFromCache($sourceCache, $sourcePath, $targetPath);
|
||||
}
|
||||
|
||||
protected function formatCacheEntry($entry) {
|
||||
$path = isset($entry['path']) ? $entry['path'] : '';
|
||||
$entry = parent::formatCacheEntry($entry);
|
||||
protected function formatCacheEntry($entry, $path = null) {
|
||||
if (is_null($path)) {
|
||||
$path = isset($entry['path']) ? $entry['path'] : '';
|
||||
$entry['path'] = $this->getJailedPath($path);
|
||||
} else {
|
||||
$entry['path'] = $path;
|
||||
}
|
||||
$sharePermissions = $this->storage->getPermissions($path);
|
||||
if (isset($entry['permissions'])) {
|
||||
$entry['permissions'] &= $sharePermissions;
|
||||
} else {
|
||||
$entry['permissions'] = $sharePermissions;
|
||||
}
|
||||
$entry['uid_owner'] = $this->storage->getOwner($path);
|
||||
$entry['uid_owner'] = $this->storage->getOwner('');
|
||||
$entry['displayname_owner'] = $this->getOwnerDisplayName();
|
||||
if ($path === '') {
|
||||
$entry['is_share_mount_point'] = true;
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
namespace OCA\Files_Sharing\Tests;
|
||||
|
||||
use OC\Files\Storage\Temporary;
|
||||
use OC\Files\Storage\Wrapper\Jail;
|
||||
use OCA\Files_Sharing\SharedStorage;
|
||||
|
||||
/**
|
||||
|
@ -552,4 +554,41 @@ class CacheTest extends TestCase {
|
|||
|
||||
$this->assertEquals($sourceStorage->getCache()->getNumericStorageId(), $sharedStorage->getCache()->getNumericStorageId());
|
||||
}
|
||||
|
||||
public function testShareJailedStorage() {
|
||||
$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(\OCP\Share::SHARE_TYPE_USER)
|
||||
->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
|
||||
->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
|
||||
->setPermissions(\OCP\Constants::PERMISSION_ALL);
|
||||
$this->shareManager->createShare($share);
|
||||
\OC_Util::tearDownFS();
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
$this->assertEquals('foo', \OC\Files\Filesystem::file_get_contents('/sub/foo.txt'));
|
||||
|
||||
\OC\Files\Filesystem::file_put_contents('/sub/bar.txt', 'bar');
|
||||
/** @var SharedStorage $sharedStorage */
|
||||
list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/sub');
|
||||
|
||||
$this->assertTrue($sharedStorage->getCache()->inCache('bar.txt'));
|
||||
|
||||
$this->assertTrue($sourceStorage->getCache()->inCache('jail/sub/bar.txt'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
*/
|
||||
|
||||
namespace OC\Files\Cache\Wrapper;
|
||||
|
||||
use OC\Files\Cache\Cache;
|
||||
use OCP\Files\Cache\ICacheEntry;
|
||||
use OCP\Files\Search\ISearchQuery;
|
||||
|
@ -48,11 +49,15 @@ class CacheJail extends CacheWrapper {
|
|||
$this->root = $root;
|
||||
}
|
||||
|
||||
protected function getRoot() {
|
||||
return $this->root;
|
||||
}
|
||||
|
||||
protected function getSourcePath($path) {
|
||||
if ($path === '') {
|
||||
return $this->root;
|
||||
return $this->getRoot();
|
||||
} else {
|
||||
return $this->root . '/' . ltrim($path, '/');
|
||||
return $this->getRoot() . '/' . ltrim($path, '/');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,13 +66,13 @@ class CacheJail extends CacheWrapper {
|
|||
* @return null|string the jailed path or null if the path is outside the jail
|
||||
*/
|
||||
protected function getJailedPath($path) {
|
||||
if ($this->root === '') {
|
||||
if ($this->getRoot() === '') {
|
||||
return $path;
|
||||
}
|
||||
$rootLength = strlen($this->root) + 1;
|
||||
if ($path === $this->root) {
|
||||
$rootLength = strlen($this->getRoot()) + 1;
|
||||
if ($path === $this->getRoot()) {
|
||||
return '';
|
||||
} else if (substr($path, 0, $rootLength) === $this->root . '/') {
|
||||
} else if (substr($path, 0, $rootLength) === $this->getRoot() . '/') {
|
||||
return substr($path, $rootLength);
|
||||
} else {
|
||||
return null;
|
||||
|
@ -86,8 +91,8 @@ class CacheJail extends CacheWrapper {
|
|||
}
|
||||
|
||||
protected function filterCacheEntry($entry) {
|
||||
$rootLength = strlen($this->root) + 1;
|
||||
return ($entry['path'] === $this->root) or (substr($entry['path'], 0, $rootLength) === $this->root . '/');
|
||||
$rootLength = strlen($this->getRoot()) + 1;
|
||||
return ($entry['path'] === $this->getRoot()) or (substr($entry['path'], 0, $rootLength) === $this->getRoot() . '/');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,7 +194,7 @@ class CacheJail extends CacheWrapper {
|
|||
* remove all entries for files that are stored on the storage from the cache
|
||||
*/
|
||||
public function clear() {
|
||||
$this->getCache()->remove($this->root);
|
||||
$this->getCache()->remove($this->getRoot());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -58,6 +58,17 @@ class Jail extends Wrapper {
|
|||
}
|
||||
}
|
||||
|
||||
public function getJailedPath($path) {
|
||||
$root = rtrim($this->rootPath, '/') . '/';
|
||||
|
||||
if (strpos($path, $root) !== 0) {
|
||||
return null;
|
||||
} else {
|
||||
$path = substr($path, strlen($this->rootPath));
|
||||
return trim($path, '/');
|
||||
}
|
||||
}
|
||||
|
||||
public function getId() {
|
||||
return parent::getId();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue