diff options
Diffstat (limited to 'lib/private')
-rw-r--r-- | lib/private/connector/sabre/objecttree.php | 4 | ||||
-rw-r--r-- | lib/private/files/cache/updater.php | 4 | ||||
-rw-r--r-- | lib/private/files/fileinfo.php | 2 | ||||
-rw-r--r-- | lib/private/files/mount/manager.php | 9 | ||||
-rw-r--r-- | lib/private/files/mount/mount.php | 13 | ||||
-rw-r--r-- | lib/private/files/mount/moveablemount.php | 30 | ||||
-rw-r--r-- | lib/private/files/view.php | 66 | ||||
-rw-r--r-- | lib/private/hook.php | 6 | ||||
-rw-r--r-- | lib/private/share/helper.php | 21 | ||||
-rw-r--r-- | lib/private/share/share.php | 72 |
10 files changed, 145 insertions, 82 deletions
diff --git a/lib/private/connector/sabre/objecttree.php b/lib/private/connector/sabre/objecttree.php index a3de2efaa50..c55a392bca0 100644 --- a/lib/private/connector/sabre/objecttree.php +++ b/lib/private/connector/sabre/objecttree.php @@ -126,10 +126,6 @@ class ObjectTree extends \Sabre\DAV\ObjectTree { 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, '/') === '') { - throw new \Sabre\DAV\Exception\Forbidden(); - } if (!$this->fileView->isUpdatable($sourceDir)) { throw new \Sabre\DAV\Exception\Forbidden(); } diff --git a/lib/private/files/cache/updater.php b/lib/private/files/cache/updater.php index f6feb6624b2..f15c203cd58 100644 --- a/lib/private/files/cache/updater.php +++ b/lib/private/files/cache/updater.php @@ -83,6 +83,10 @@ class Updater { * @var string $internalTo */ list($storageFrom, $internalFrom) = self::resolvePath($from); + // if it's a moved mountpoint we dont need to do anything + if ($internalFrom === '') { + return; + } list($storageTo, $internalTo) = self::resolvePath($to); if ($storageFrom && $storageTo) { if ($storageFrom === $storageTo) { diff --git a/lib/private/files/fileinfo.php b/lib/private/files/fileinfo.php index e7afeb4ccce..d012c0c5a63 100644 --- a/lib/private/files/fileinfo.php +++ b/lib/private/files/fileinfo.php @@ -108,7 +108,7 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess { * @return string */ public function getName() { - return $this->data['name']; + return basename($this->getPath()); } /** diff --git a/lib/private/files/mount/manager.php b/lib/private/files/mount/manager.php index db1f4600c74..45a9f339fba 100644 --- a/lib/private/files/mount/manager.php +++ b/lib/private/files/mount/manager.php @@ -31,6 +31,15 @@ class Manager { } /** + * @param string $mountPoint + * @param string $target + */ + public function moveMount($mountPoint, $target){ + $this->mounts[$target] = $this->mounts[$mountPoint]; + unset($this->mounts[$mountPoint]); + } + + /** * Find the mount for $path * * @param string $path diff --git a/lib/private/files/mount/mount.php b/lib/private/files/mount/mount.php index 7c40853ac95..04bccbcab87 100644 --- a/lib/private/files/mount/mount.php +++ b/lib/private/files/mount/mount.php @@ -16,11 +16,11 @@ class Mount { /** * @var \OC\Files\Storage\Storage $storage */ - private $storage = null; - private $class; - private $storageId; - private $arguments = array(); - private $mountPoint; + protected $storage = null; + protected $class; + protected $storageId; + protected $arguments = array(); + protected $mountPoint; /** * @var \OC\Files\Storage\Loader $loader @@ -142,7 +142,8 @@ class Mount { } else { $internalPath = substr($path, strlen($this->mountPoint)); } - return $internalPath; + // substr returns false instead of an empty string, we always want a string + return (string)$internalPath; } /** diff --git a/lib/private/files/mount/moveablemount.php b/lib/private/files/mount/moveablemount.php new file mode 100644 index 00000000000..117649339e9 --- /dev/null +++ b/lib/private/files/mount/moveablemount.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Mount; + +/** + * Defines the mount point to be (re)moved by the user + */ +interface MoveableMount { + /** + * Move the mount point to $target + * + * @param string $target the target mount point + * @return bool + */ + public function moveMount($target); + + /** + * Remove the mount points + * + * @return mixed + * @return bool + */ + public function removeMount(); +} diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 1dc6c405bcf..d42f6cbf9fe 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -26,6 +26,7 @@ namespace OC\Files; use OC\Files\Cache\Updater; +use OC\Files\Mount\MoveableMount; class View { private $fakeRoot = ''; @@ -357,14 +358,27 @@ class View { } $postFix = (substr($path, -1, 1) === '/') ? '/' : ''; $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path)); - list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix); - 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 - return false; + $mount = Filesystem::getMountManager()->find($absolutePath . $postFix); + if ($mount->getInternalPath($absolutePath) === '') { + if ($mount instanceof MoveableMount) { + \OC_Hook::emit( + Filesystem::CLASSNAME, "umount", + array(Filesystem::signal_param_path => $path) + ); + $result = $mount->removeMount(); + if ($result) { + \OC_Hook::emit( + Filesystem::CLASSNAME, "post_umount", + array(Filesystem::signal_param_path => $path) + ); + } + return $result; + } else { + // 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 + return false; + } } return $this->basicOperation('unlink', $path, array('delete')); } @@ -411,18 +425,19 @@ class View { if ($run) { $mp1 = $this->getMountPoint($path1 . $postFix1); $mp2 = $this->getMountPoint($path2 . $postFix2); - list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); + $manager = Filesystem::getMountManager(); + $mount = $manager->find($absolutePath1 . $postFix1); + $storage1 = $mount->getStorage(); + $internalPath1 = $mount->getInternalPath($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; - } + if ($internalPath1 === '' and $mount instanceof MoveableMount) { + /** + * @var \OC\Files\Mount\Mount | \OC\Files\Mount\MoveableMount $mount + */ + $sourceMountPoint = $mount->getMountPoint(); + $result = $mount->moveMount($absolutePath2); + $manager->moveMount($sourceMountPoint, $mount->getMountPoint()); + \OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2); } elseif ($mp1 == $mp2) { if ($storage1) { $result = $storage1->rename($internalPath1, $internalPath2); @@ -888,10 +903,6 @@ class View { return $result; } $path = Filesystem::normalizePath($this->fakeRoot . '/' . $directory); - /** - * @var \OC\Files\Storage\Storage $storage - * @var string $internalPath - */ list($storage, $internalPath) = Filesystem::resolvePath($path); if ($storage) { $cache = $storage->getCache($internalPath); @@ -924,9 +935,10 @@ class View { } //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders - $mountPoints = Filesystem::getMountPoints($path); + $mounts = Filesystem::getMountManager()->findIn($path); $dirLength = strlen($path); - foreach ($mountPoints as $mountPoint) { + foreach ($mounts as $mount) { + $mountPoint = $mount->getMountPoint(); $subStorage = Filesystem::getStorage($mountPoint); if ($subStorage) { $subCache = $subStorage->getCache(''); @@ -953,8 +965,8 @@ class View { $permissions = $rootEntry['permissions']; // 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; + if ($mount instanceof MoveableMount) { + $rootEntry['permissions'] = $permissions | \OCP\PERMISSION_UPDATE | \OCP\PERMISSION_DELETE; } else { $rootEntry['permissions'] = $permissions & (\OCP\PERMISSION_ALL - (\OCP\PERMISSION_UPDATE | \OCP\PERMISSION_DELETE)); } diff --git a/lib/private/hook.php b/lib/private/hook.php index 30e22847c7f..c9ca58f779e 100644 --- a/lib/private/hook.php +++ b/lib/private/hook.php @@ -31,6 +31,12 @@ class OC_Hook{ self::$registered[$signalclass][$signalname] = array(); } + // dont connect hooks twice + foreach (self::$registered[$signalclass][$signalname] as $hook) { + if ($hook['class'] === $slotclass and $hook['name'] === $slotname) { + return false; + } + } // Connect the hook handler to the requested emitter self::$registered[$signalclass][$signalname][] = array( "class" => $slotclass, diff --git a/lib/private/share/helper.php b/lib/private/share/helper.php index ab9e0ca4926..c92aa15b4bf 100644 --- a/lib/private/share/helper.php +++ b/lib/private/share/helper.php @@ -166,27 +166,6 @@ class Helper extends \OC\Share\Constants { // Reset parents array, only go through loop again if items are found $parents = array(); while ($item = $result->fetchRow()) { - // Search for a duplicate parent share, this occurs when an - // item is shared to the same user through a group and user or the - // same item is shared by different users - $userAndGroups = array_merge(array($item['uid_owner']), \OC_Group::getUserGroups($item['uid_owner'])); - $query = \OC_DB::prepare('SELECT `id`, `permissions` FROM `*PREFIX*share`' - .' WHERE `item_type` = ?' - .' AND `item_target` = ?' - .' AND `share_type` IN (?,?,?)' - .' AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')' - .' AND `uid_owner` != ? AND `id` != ?'); - $duplicateParent = $query->execute(array($item['item_type'], $item['item_target'], - self::SHARE_TYPE_USER, self::SHARE_TYPE_GROUP, self::$shareTypeGroupUserUnique, - $item['uid_owner'], $item['parent']))->fetchRow(); - if ($duplicateParent) { - // Change the parent to the other item id if share permission is granted - if ($duplicateParent['permissions'] & \OCP\PERMISSION_SHARE) { - $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `parent` = ? WHERE `id` = ?'); - $query->execute(array($duplicateParent['id'], $item['id'])); - continue; - } - } $ids[] = $item['id']; $parents[] = $item['id']; } diff --git a/lib/private/share/share.php b/lib/private/share/share.php index 2126a1d2dd4..f02eacfed74 100644 --- a/lib/private/share/share.php +++ b/lib/private/share/share.php @@ -519,6 +519,11 @@ class Share extends \OC\Share\Constants { } } + // single file shares should never have delete permissions + if ($itemType === 'file') { + $permissions = (int)$permissions & ~\OCP\PERMISSION_DELETE; + } + // Verify share type and sharing conditions are met if ($shareType === self::SHARE_TYPE_USER) { if ($shareWith == $uidOwner) { @@ -712,33 +717,54 @@ class Share extends \OC\Share\Constants { * Unsharing from self is not allowed for items inside collections */ public static function unshareFromSelf($itemType, $itemTarget) { - $item = self::getItemSharedWith($itemType, $itemTarget); - if (!empty($item)) { - if ((int)$item['share_type'] === self::SHARE_TYPE_GROUP) { - // Insert an extra row for the group share and set permission - // to 0 to prevent it from showing up for the user - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share`' + + $uid = \OCP\User::getUser(); + + if ($itemType === 'file' || $itemType === 'folder') { + $statement = 'SELECT * FROM `*PREFIX*share` WHERE `item_type` = ? and `file_target` = ?'; + } else { + $statement = 'SELECT * FROM `*PREFIX*share` WHERE `item_type` = ? and `item_target` = ?'; + } + + $query = \OCP\DB::prepare($statement); + $result = $query->execute(array($itemType, $itemTarget)); + + $shares = $result->fetchAll(); + + $itemUnshared = false; + foreach ($shares as $share) { + if ((int)$share['share_type'] === \OCP\Share::SHARE_TYPE_USER && + $share['share_with'] === $uid) { + Helper::delete($share['id']); + $itemUnshared = true; + break; + } elseif ((int)$share['share_type'] === \OCP\Share::SHARE_TYPE_GROUP) { + if (\OC_Group::inGroup($uid, $share['share_with'])) { + $groupShare = $share; + } + } elseif ((int)$share['share_type'] === self::$shareTypeGroupUserUnique && + $share['share_with'] === $uid) { + $uniqueGroupShare = $share; + } + } + + if (!$itemUnshared && isset($groupShare)) { + $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`)' .' VALUES (?,?,?,?,?,?,?,?,?,?,?)'); - $query->execute(array($item['item_type'], $item['item_source'], $item['item_target'], - $item['id'], self::$shareTypeGroupUserUnique, - \OC_User::getUser(), $item['uid_owner'], 0, $item['stime'], $item['file_source'], - $item['file_target'])); - \OC_DB::insertid('*PREFIX*share'); - // Delete all reshares by this user of the group share - Helper::delete($item['id'], true, \OC_User::getUser()); - } else if ((int)$item['share_type'] === self::$shareTypeGroupUserUnique) { - // Set permission to 0 to prevent it from showing up for the user - $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = ? WHERE `id` = ?'); - $query->execute(array(0, $item['id'])); - Helper::delete($item['id'], true); - } else { - Helper::delete($item['id']); - } - return true; + $query->execute(array($groupShare['item_type'], $groupShare['item_source'], $groupShare['item_target'], + $groupShare['id'], self::$shareTypeGroupUserUnique, + \OC_User::getUser(), $groupShare['uid_owner'], 0, $groupShare['stime'], $groupShare['file_source'], + $groupShare['file_target'])); + $itemUnshared = true; + } elseif (!$itemUnshared && isset($uniqueGroupShare)) { + $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = ? WHERE `id` = ?'); + $query->execute(array(0, $uniqueGroupShare['id'])); + $itemUnshared = true; } - return false; + + return $itemUnshared; } /** |