diff options
author | Björn Schießle <schiessle@owncloud.com> | 2014-04-24 18:45:45 +0200 |
---|---|---|
committer | Björn Schießle <schiessle@owncloud.com> | 2014-04-24 18:45:45 +0200 |
commit | f520305848be6994a0726d907a0182aa07da0be8 (patch) | |
tree | a5c05f26cf6f9a21dd1bc82abf517634199543e2 /lib | |
parent | 40257d9736ce0d7bad02bf4a1baa86d9b1fc8f7f (diff) | |
parent | b312d38d38c4e391765beb0aadb6bd2eafd9cb2c (diff) | |
download | nextcloud-server-f520305848be6994a0726d907a0182aa07da0be8.tar.gz nextcloud-server-f520305848be6994a0726d907a0182aa07da0be8.zip |
Merge pull request #8026 from owncloud/remove_shared_folder
remove the "Shared" folder
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/connector/sabre/directory.php | 12 | ||||
-rw-r--r-- | lib/private/connector/sabre/file.php | 11 | ||||
-rw-r--r-- | lib/private/connector/sabre/objecttree.php | 11 | ||||
-rw-r--r-- | lib/private/files/mount/manager.php | 7 | ||||
-rw-r--r-- | lib/private/files/mount/mount.php | 7 | ||||
-rw-r--r-- | lib/private/files/view.php | 37 | ||||
-rw-r--r-- | lib/private/share/constants.php | 8 | ||||
-rw-r--r-- | lib/private/share/share.php | 70 | ||||
-rw-r--r-- | lib/public/share.php | 16 |
9 files changed, 121 insertions, 58 deletions
diff --git a/lib/private/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php index 70f45aa1e7f..5d386a772a7 100644 --- a/lib/private/connector/sabre/directory.php +++ b/lib/private/connector/sabre/directory.php @@ -50,10 +50,6 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function createFile($name, $data = null) { - if (strtolower($name) === 'shared' && empty($this->path)) { - throw new \Sabre_DAV_Exception_Forbidden(); - } - // for chunked upload also updating a existing file is a "createFile" // because we create all the chunks before reasamble them to the existing file. if (isset($_SERVER['HTTP_OC_CHUNKED'])) { @@ -86,10 +82,6 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function createDirectory($name) { - if (strtolower($name) === 'shared' && empty($this->path)) { - throw new \Sabre_DAV_Exception_Forbidden(); - } - if (!\OC\Files\Filesystem::isCreatable($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } @@ -196,10 +188,6 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function delete() { - if ($this->path === 'Shared') { - throw new \Sabre_DAV_Exception_Forbidden(); - } - if (!\OC\Files\Filesystem::isDeletable($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php index 750d646a8f5..433b4d805c9 100644 --- a/lib/private/connector/sabre/file.php +++ b/lib/private/connector/sabre/file.php @@ -71,13 +71,6 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D // mark file as partial while uploading (ignored by the scanner) $partpath = $this->path . '.ocTransferId' . rand() . '.part'; - // if file is located in /Shared we write the part file to the users - // root folder because we can't create new files in /shared - // we extend the name with a random number to avoid overwriting a existing file - if (dirname($partpath) === 'Shared') { - $partpath = pathinfo($partpath, PATHINFO_FILENAME) . rand() . '.part'; - } - try { $putOkay = $fs->file_put_contents($partpath, $data); if ($putOkay === false) { @@ -149,10 +142,6 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D public function delete() { $fs = $this->getFS(); - if ($this->path === 'Shared') { - throw new \Sabre_DAV_Exception_Forbidden(); - } - if (!$fs->isDeletable($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } diff --git a/lib/private/connector/sabre/objecttree.php b/lib/private/connector/sabre/objecttree.php index accf020daa2..2956f608380 100644 --- a/lib/private/connector/sabre/objecttree.php +++ b/lib/private/connector/sabre/objecttree.php @@ -87,16 +87,19 @@ class ObjectTree extends \Sabre_DAV_ObjectTree { list($sourceDir,) = \Sabre_DAV_URLUtil::splitPath($sourcePath); list($destinationDir,) = \Sabre_DAV_URLUtil::splitPath($destinationPath); + $isShareMountPoint = false; + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath( '/' . \OCP\User::getUser() . '/files/' . $sourcePath); + if ($storage instanceof \OC\Files\Storage\Shared && !$internalPath) { + $isShareMountPoint = true; + } + // check update privileges $fs = $this->getFileView(); - if (!$fs->isUpdatable($sourcePath)) { + if (!$fs->isUpdatable($sourcePath) && !$isShareMountPoint) { throw new \Sabre_DAV_Exception_Forbidden(); } if ($sourceDir !== $destinationDir) { // for a full move we need update privileges on sourcePath and sourceDir as well as destinationDir - if (ltrim($destinationDir, '/') === '' && strtolower($sourceNode->getName()) === 'shared') { - throw new \Sabre_DAV_Exception_Forbidden(); - } if (!$fs->isUpdatable($sourceDir)) { throw new \Sabre_DAV_Exception_Forbidden(); } diff --git a/lib/private/files/mount/manager.php b/lib/private/files/mount/manager.php index ff4a336f347..91460b72730 100644 --- a/lib/private/files/mount/manager.php +++ b/lib/private/files/mount/manager.php @@ -24,6 +24,13 @@ class Manager { } /** + * @param string $mountPoint + */ + public function removeMount($mountPoint) { + unset($this->mounts[$mountPoint]); + } + + /** * Find the mount for $path * * @param $path diff --git a/lib/private/files/mount/mount.php b/lib/private/files/mount/mount.php index 0ce2f5975c7..08d5ddf348b 100644 --- a/lib/private/files/mount/mount.php +++ b/lib/private/files/mount/mount.php @@ -66,6 +66,13 @@ class Mount { } /** + * @param string $mountPoint new mount point + */ + public function setMountPoint($mountPoint) { + $this->mountPoint = $mountPoint; + } + + /** * create the storage that is mounted * * @return \OC\Files\Storage\Storage diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 519ed250b1f..58dfc73dcf3 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -348,7 +348,8 @@ class View { $postFix = (substr($path, -1, 1) === '/') ? '/' : ''; $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path)); list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix); - if (!$internalPath || $internalPath === '' || $internalPath === '/') { + if (!($storage instanceof \OC\Files\Storage\Shared) && + (!$internalPath || $internalPath === '' || $internalPath === '/')) { // do not allow deleting the storage's root / the mount point // because for some storages it might delete the whole contents // but isn't supposed to work that way @@ -404,11 +405,21 @@ class View { if ($run) { $mp1 = $this->getMountPoint($path1 . $postFix1); $mp2 = $this->getMountPoint($path2 . $postFix2); - if ($mp1 == $mp2) { - list($storage, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); - list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); - if ($storage) { - $result = $storage->rename($internalPath1, $internalPath2); + list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); + list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); + // if source and target are on the same storage we can call the rename operation from the + // storage. If it is a "Shared" file/folder we call always the rename operation of the + // shared storage to handle mount point renaming, etc correctly + if ($storage1 instanceof \OC\Files\Storage\Shared) { + if ($storage1) { + $result = $storage1->rename($absolutePath1, $absolutePath2); + \OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2); + } else { + $result = false; + } + } elseif ($mp1 == $mp2) { + if ($storage1) { + $result = $storage1->rename($internalPath1, $internalPath2); \OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2); } else { $result = false; @@ -417,7 +428,6 @@ class View { if ($this->is_dir($path1)) { $result = $this->copy($path1, $path2); if ($result === true) { - list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); $result = $storage1->unlink($internalPath1); } } else { @@ -431,7 +441,6 @@ class View { fclose($target); if ($result !== false) { - list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); $storage1->unlink($internalPath1); } } @@ -972,8 +981,13 @@ class View { $permissions = $subStorage->getPermissions($rootEntry['path']); $subPermissionsCache->set($rootEntry['fileid'], $user, $permissions); } - // do not allow renaming/deleting the mount point - $rootEntry['permissions'] = $permissions & (\OCP\PERMISSION_ALL - (\OCP\PERMISSION_UPDATE | \OCP\PERMISSION_DELETE)); + // do not allow renaming/deleting the mount point if they are not shared files/folders + // for shared files/folders we use the permissions given by the owner + if ($subStorage instanceof \OC\Files\Storage\Shared) { + $rootEntry['permissions'] = $permissions; + } else { + $rootEntry['permissions'] = $permissions & (\OCP\PERMISSION_ALL - (\OCP\PERMISSION_UPDATE | \OCP\PERMISSION_DELETE)); + } //remove any existing entry with the same name foreach ($files as $i => $file) { @@ -1154,7 +1168,8 @@ class View { * @var \OC\Files\Mount\Mount $mount */ $cache = $mount->getStorage()->getCache(); - if ($internalPath = $cache->getPathById($id)) { + $internalPath = $cache->getPathById($id); + if (is_string($internalPath)) { $fullPath = $mount->getMountPoint() . $internalPath; if (!is_null($path = $this->getRelativePath($fullPath))) { return $path; diff --git a/lib/private/share/constants.php b/lib/private/share/constants.php index 7e4223d10fa..4c398c43c2d 100644 --- a/lib/private/share/constants.php +++ b/lib/private/share/constants.php @@ -26,13 +26,13 @@ class Constants { const SHARE_TYPE_USER = 0; const SHARE_TYPE_GROUP = 1; const SHARE_TYPE_LINK = 3; - const SHARE_TYPE_EMAIL = 4; - const SHARE_TYPE_CONTACT = 5; - const SHARE_TYPE_REMOTE = 6; + const SHARE_TYPE_EMAIL = 4; // ToDo Check if it is still in use otherwise remove it + const SHARE_TYPE_CONTACT = 5; // ToDo Check if it is still in use otherwise remove it + const SHARE_TYPE_REMOTE = 6; // ToDo Check if it is still in use otherwise remove it const FORMAT_NONE = -1; const FORMAT_STATUSES = -2; - const FORMAT_SOURCES = -3; + const FORMAT_SOURCES = -3; // ToDo Check if it is still in use otherwise remove it const TOKEN_LENGTH = 32; // see db_structure.xml diff --git a/lib/private/share/share.php b/lib/private/share/share.php index 0f69a94453a..c0ce3a1d8af 100644 --- a/lib/private/share/share.php +++ b/lib/private/share/share.php @@ -223,7 +223,7 @@ class Share extends \OC\Share\Constants { } else { while ($row = $result->fetchRow()) { foreach ($fileTargets[$row['fileid']] as $uid => $shareData) { - $sharedPath = '/Shared' . $shareData['file_target']; + $sharedPath = $shareData['file_target']; $sharedPath .= substr($path, strlen($row['path']) -5); $sharePaths[$uid] = $sharedPath; } @@ -253,6 +253,22 @@ class Share extends \OC\Share\Constants { } /** + * Get the items of item type shared with a user + * @param string Item type + * @param sting user id for which user we want the shares + * @param int Format (optional) Format type must be defined by the backend + * @param mixed Parameters (optional) + * @param int Number of items to return (optional) Returns all by default + * @param bool include collections (optional) + * @return Return depends on format + */ + public static function getItemsSharedWithUser($itemType, $user, $format = self::FORMAT_NONE, + $parameters = null, $limit = -1, $includeCollections = false) { + return self::getItems($itemType, null, self::$shareTypeUserAndGroups, $user, null, $format, + $parameters, $limit, $includeCollections); + } + + /** * Get the item of item type shared with the current user * @param string $itemType * @param string $itemTarget @@ -473,6 +489,7 @@ class Share extends \OC\Share\Constants { $itemSourceName = $itemSource; } + // verify that the file exists before we try to share it if ($itemType === 'file' or $itemType === 'folder') { $path = \OC\Files\Filesystem::getPath($itemSource); @@ -484,6 +501,21 @@ class Share extends \OC\Share\Constants { } } + //verify that we don't share a folder which already contains a share mount point + if ($itemType === 'folder') { + $path = '/' . $uidOwner . '/files' . \OC\Files\Filesystem::getPath($itemSource) . '/'; + $mountManager = \OC\Files\Filesystem::getMountManager(); + $mounts = $mountManager->getAll(); + foreach ($mounts as $mountPoint => $mount) { + if ($mount->getStorage() instanceof \OC\Files\Storage\Shared && strpos($mountPoint, $path) === 0) { + $message = 'Sharing "' . $itemSourceName . '" failed, because it contains files shared with you!'; + \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); + throw new \Exception($message); + } + + } + } + // Verify share type and sharing conditions are met if ($shareType === self::SHARE_TYPE_USER) { if ($shareWith == $uidOwner) { @@ -876,6 +908,7 @@ class Share extends \OC\Share\Constants { $hookParams = array( 'itemType' => $item['item_type'], 'itemSource' => $item['item_source'], + 'fileSource' => $item['file_source'], 'shareType' => $item['share_type'], 'shareWith' => $item['share_with'], 'itemParent' => $item['parent'], @@ -1135,6 +1168,7 @@ class Share extends \OC\Share\Constants { // Filter out duplicate group shares for users with unique targets if ($row['share_type'] == self::$shareTypeGroupUserUnique && isset($items[$row['parent']])) { $row['share_type'] = self::SHARE_TYPE_GROUP; + $row['unique_name'] = true; // remember that we use a unique name for this user $row['share_with'] = $items[$row['parent']]['share_with']; // Remove the parent group share unset($items[$row['parent']]); @@ -1173,10 +1207,6 @@ class Share extends \OC\Share\Constants { // Remove root from file source paths if retrieving own shared items if (isset($uidOwner) && isset($row['path'])) { if (isset($row['parent'])) { - // FIXME: Doesn't always construct the correct path, example: - // Folder '/a/b', share '/a' and '/a/b' to user2 - // user2 reshares /Shared/b and ask for share status of /Shared/a/b - // expected result: path=/Shared/a/b; actual result /Shared/b because of the parent $query = \OC_DB::prepare('SELECT `file_target` FROM `*PREFIX*share` WHERE `id` = ?'); $parentResult = $query->execute(array($row['parent'])); if (\OC_DB::isError($result)) { @@ -1185,7 +1215,7 @@ class Share extends \OC\Share\Constants { \OC_Log::ERROR); } else { $parentRow = $parentResult->fetchRow(); - $tmpPath = '/Shared' . $parentRow['file_target']; + $tmpPath = $parentRow['file_target']; // find the right position where the row path continues from the target path $pos = strrpos($row['path'], $parentRow['file_target']); $subPath = substr($row['path'], $pos); @@ -1395,8 +1425,8 @@ class Share extends \OC\Share\Constants { } } $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`, `item_target`,' - .' `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,' - .' `file_target`, `token`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)'); + .' `share_type`, `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,' + .' `file_target`, `token`, `parent`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)'); // Share with a group if ($shareType == self::SHARE_TYPE_GROUP) { $groupItemTarget = Helper::generateTarget($itemType, $itemSource, $shareType, $shareWith['group'], @@ -1440,10 +1470,9 @@ class Share extends \OC\Share\Constants { } else { $groupFileTarget = null; } - $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, $shareType, - $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget, $token)); - // Save this id, any extra rows for this group share will need to reference it - $parent = \OC_DB::insertid('*PREFIX*share'); + $queriesToExecute = array(); + $queriesToExecute['groupShare'] = array($itemType, $itemSource, $groupItemTarget, $shareType, + $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget, $token, $parent); // Loop through all users of this group in case we need to add an extra row foreach ($shareWith['users'] as $uid) { $itemTarget = Helper::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $uid, @@ -1469,12 +1498,21 @@ class Share extends \OC\Share\Constants { } // Insert an extra row for the group share if the item or file target is unique for this user if ($itemTarget != $groupItemTarget || (isset($fileSource) && $fileTarget != $groupFileTarget)) { - $query->execute(array($itemType, $itemSource, $itemTarget, $parent, + $queriesToExecute[] = array($itemType, $itemSource, $itemTarget, self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(), - $fileSource, $fileTarget, $token)); + $fileSource, $fileTarget, $token); $id = \OC_DB::insertid('*PREFIX*share'); } } + $query->execute($queriesToExecute['groupShare']); + // Save this id, any extra rows for this group share will need to reference it + $parent = \OC_DB::insertid('*PREFIX*share'); + unset($queriesToExecute['groupShare']); + foreach ($queriesToExecute as $qe) { + $qe[] = $parent; + $query->execute($qe); + } + \OC_Hook::emit('OCP\Share', 'post_shared', array( 'itemType' => $itemType, 'itemSource' => $itemSource, @@ -1534,8 +1572,8 @@ class Share extends \OC\Share\Constants { } else { $fileTarget = null; } - $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner, - $permissions, time(), $fileSource, $fileTarget, $token)); + $query->execute(array($itemType, $itemSource, $itemTarget, $shareType, $shareWith, $uidOwner, + $permissions, time(), $fileSource, $fileTarget, $token, $parent)); $id = \OC_DB::insertid('*PREFIX*share'); \OC_Hook::emit('OCP\Share', 'post_shared', array( 'itemType' => $itemType, diff --git a/lib/public/share.php b/lib/public/share.php index c694314ad08..230a517b5ee 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -91,6 +91,22 @@ class Share extends \OC\Share\Constants { } /** + * Get the items of item type shared with a user + * @param string Item type + * @param sting user id for which user we want the shares + * @param int Format (optional) Format type must be defined by the backend + * @param mixed Parameters (optional) + * @param int Number of items to return (optional) Returns all by default + * @param bool include collections (optional) + * @return Return depends on format + */ + public static function getItemsSharedWithUser($itemType, $user, $format = self::FORMAT_NONE, + $parameters = null, $limit = -1, $includeCollections = false) { + + return \OC\Share\Share::getItemsSharedWithUser($itemType, $user, $format, $parameters, $limit, $includeCollections); + } + + /** * Get the item of item type shared with the current user * @param string $itemType * @param string $itemTarget |