diff --git a/apps/files_sharing/lib/sharedmount.php b/apps/files_sharing/lib/sharedmount.php index 8eaf54696463..f1d1d036f583 100644 --- a/apps/files_sharing/lib/sharedmount.php +++ b/apps/files_sharing/lib/sharedmount.php @@ -49,6 +49,9 @@ class SharedMount extends MountPoint implements MoveableMount { */ private $user; + /** @var array */ + private $share; + /** * @param string $storage * @param SharedMount[] $mountpoints @@ -56,11 +59,18 @@ class SharedMount extends MountPoint implements MoveableMount { * @param \OCP\Files\Storage\IStorageFactory $loader */ public function __construct($storage, array $mountpoints, $arguments = null, $loader = null) { + if (!isset($arguments['user'])) { + throw new \InvalidArgumentException('Missing "user" key in arguments'); + } + if (!isset($arguments['share'])) { + throw new \InvalidArgumentException('Missing "share" key in arguments'); + } $this->user = $arguments['user']; $this->recipientView = new View('/' . $this->user . '/files'); - $newMountPoint = $this->verifyMountPoint($arguments['share'], $mountpoints); + $this->share = $arguments['share']; + $newMountPoint = $this->verifyMountPoint($this->share, $mountpoints); $absMountPoint = '/' . $this->user . '/files' . $newMountPoint; - $arguments['ownerView'] = new View('/' . $arguments['share']['uid_owner'] . '/files'); + $arguments['ownerView'] = new View('/' . $this->share['uid_owner'] . '/files'); parent::__construct($storage, $absMountPoint, $arguments, $loader); } @@ -238,8 +248,24 @@ public function removeMount() { * @return array */ public function getShare() { - /** @var $storage \OC\Files\Storage\Shared */ - $storage = $this->getStorage(); - return $storage->getShare(); + return $this->share; + } + + /** + * Get the file id of the root of the storage + * + * @return int + */ + public function getStorageRootId() { + return $this->share['file_source']; + } + + public function getStorageNumericId() { + $query = \OC::$server->getDatabaseConnection()->getQueryBuilder(); + $query->select('storage') + ->from('filecache') + ->where($query->expr()->eq('fileid', $query->createNamedParameter($this->getStorageRootId()))); + + return $query->execute()->fetchColumn(); } } diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 7a6873a504e5..1df8b72b7bca 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -87,7 +87,7 @@ private function init() { $this->initialized = true; try { Filesystem::initMountPoints($this->share['uid_owner']); - $sourcePath = $this->ownerView->getPath($this->share['file_source']); + $sourcePath = $this->ownerView->getPath($this->share['file_source'], false); list($this->sourceStorage, $sourceInternalPath) = $this->ownerView->resolvePath($sourcePath); $this->sourceRootInfo = $this->sourceStorage->getCache()->get($sourceInternalPath); } catch (\Exception $e) { diff --git a/lib/private/files/config/cachedmountinfo.php b/lib/private/files/config/cachedmountinfo.php index 2993c979a7f4..ce75cb668960 100644 --- a/lib/private/files/config/cachedmountinfo.php +++ b/lib/private/files/config/cachedmountinfo.php @@ -30,22 +30,22 @@ class CachedMountInfo implements ICachedMountInfo { /** * @var IUser */ - private $user; + protected $user; /** * @var int */ - private $storageId; + protected $storageId; /** * @var int */ - private $rootId; + protected $rootId; /** * @var string */ - private $mountPoint; + protected $mountPoint; /** * CachedMountInfo constructor. @@ -88,9 +88,9 @@ public function getRootId() { */ public function getMountPointNode() { // TODO injection etc - Filesystem::initMountPoints($this->user->getUID()); - $userNode = \OC::$server->getUserFolder($this->user->getUID()); - $nodes = $userNode->getById($this->rootId); + Filesystem::initMountPoints($this->getUser()->getUID()); + $userNode = \OC::$server->getUserFolder($this->getUser()->getUID()); + $nodes = $userNode->getById($this->getRootId()); if (count($nodes) > 0) { return $nodes[0]; } else { diff --git a/lib/private/files/config/lazystoragemountinfo.php b/lib/private/files/config/lazystoragemountinfo.php new file mode 100644 index 000000000000..900b89d0a061 --- /dev/null +++ b/lib/private/files/config/lazystoragemountinfo.php @@ -0,0 +1,82 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Files\Config; + +use OC\Files\Filesystem; +use OCP\Files\Config\ICachedMountInfo; +use OCP\Files\Mount\IMountPoint; +use OCP\Files\Node; +use OCP\IUser; + +class LazyStorageMountInfo extends CachedMountInfo { + /** @var IMountPoint */ + private $mount; + + /** + * CachedMountInfo constructor. + * + * @param IUser $user + * @param IMountPoint $mount + */ + public function __construct(IUser $user, IMountPoint $mount) { + $this->user = $user; + $this->mount = $mount; + } + + /** + * @return int the numeric storage id of the mount + */ + public function getStorageId() { + if (!$this->storageId) { + if (method_exists($this->mount, 'getStorageNumericId')) { + $this->storageId = $this->mount->getStorageNumericId(); + } else { + $storage = $this->mount->getStorage(); + if (!$storage) { + return -1; + } + $this->storageId = $storage->getStorageCache()->getNumericId(); + } + } + return parent::getStorageId(); + } + + /** + * @return int the fileid of the root of the mount + */ + public function getRootId() { + if (!$this->rootId) { + $this->rootId = $this->mount->getStorageRootId(); + } + return parent::getRootId(); + } + + /** + * @return string the mount point of the mount for the user + */ + public function getMountPoint() { + if (!$this->mountPoint) { + $this->mountPoint = $this->mount->getMountPoint(); + } + return parent::getMountPoint(); + } +} diff --git a/lib/private/files/config/usermountcache.php b/lib/private/files/config/usermountcache.php index 76281ef62e15..ed2b63bd75b5 100644 --- a/lib/private/files/config/usermountcache.php +++ b/lib/private/files/config/usermountcache.php @@ -91,18 +91,18 @@ public function registerMounts(IUser $user, array $mounts) { }); /** @var ICachedMountInfo[] $newMounts */ $newMounts = array_map(function (IMountPoint $mount) use ($user) { - $storage = $mount->getStorage(); - if ($storage->instanceOfStorage('\OC\Files\Storage\Shared')) { - $rootId = (int)$storage->getShare()['file_source']; + // note: SharedMount goes there + if (method_exists($mount, 'getStorageRootId')) { + $rootId = $mount->getStorageRootId(); } else { + $storage = $mount->getStorage(); $rootId = (int)$storage->getCache()->getId(''); } - $storageId = (int)$storage->getStorageCache()->getNumericId(); // filter out any storages which aren't scanned yet since we aren't interested in files from those storages (yet) if ($rootId === -1) { return null; } else { - return new CachedMountInfo($user, $storageId, $rootId, $mount->getMountPoint()); + return new LazyStorageMountInfo($user, $mount); } }, $mounts); $newMounts = array_values(array_filter($newMounts)); diff --git a/lib/private/files/mount/mountpoint.php b/lib/private/files/mount/mountpoint.php index 58d8288c7b49..04effca7084c 100644 --- a/lib/private/files/mount/mountpoint.php +++ b/lib/private/files/mount/mountpoint.php @@ -240,4 +240,13 @@ public function getOption($name, $default) { public function getOptions() { return $this->mountOptions; } + + /** + * Get the file id of the root of the storage + * + * @return int + */ + public function getStorageRootId() { + return (int)$this->getStorage()->getCache()->getId(''); + } } diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 0bc9ad211a85..572dbf3daa72 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -58,6 +58,7 @@ use OCP\IUser; use OCP\Lock\ILockingProvider; use OCP\Lock\LockedException; +use OCA\Files_Sharing\SharedMount; /** * Class to provide access to ownCloud filesystem via a "view", and methods for @@ -1648,10 +1649,11 @@ public function getETag($path) { * Note that the resulting path is not guarantied to be unique for the id, multiple paths can point to the same file * * @param int $id + * @param bool $includeShares whether to recurse into shared mounts * @throws NotFoundException * @return string */ - public function getPath($id) { + public function getPath($id, $includeShares = true) { $id = (int)$id; $manager = Filesystem::getMountManager(); $mounts = $manager->findIn($this->fakeRoot); @@ -1663,6 +1665,11 @@ public function getPath($id) { /** * @var \OC\Files\Mount\MountPoint $mount */ + if (!$includeShares && $mount instanceof SharedMount) { + // prevent potential infinite loop when instantiating shared storages + // recursively + continue; + } if ($mount->getStorage()) { $cache = $mount->getStorage()->getCache(); $internalPath = $cache->getPathById($id);