From 2a4da7fe09825a2b94d63edec8985590ad7226e1 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Fri, 26 Sep 2014 16:58:47 +0200 Subject: [PATCH] on unshare only unshare childrens if there is no other parent available --- lib/private/share/helper.php | 24 +++++++++++++--- lib/private/share/share.php | 54 ++++++++++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/lib/private/share/helper.php b/lib/private/share/helper.php index 7e1cbb273b..90dd12e984 100644 --- a/lib/private/share/helper.php +++ b/lib/private/share/helper.php @@ -85,10 +85,12 @@ class Helper extends \OC\Share\Constants { * @param int $parent Id of item to delete * @param bool $excludeParent If true, exclude the parent from the delete (optional) * @param string $uidOwner The user that the parent was shared with (optional) + * @param int $newParent new parent for the childrens */ - public static function delete($parent, $excludeParent = false, $uidOwner = null) { + public static function delete($parent, $excludeParent = false, $uidOwner = null, $newParent = null) { $ids = array($parent); $deletedItems = array(); + $changeParent = array(); $parents = array($parent); while (!empty($parents)) { $parents = "'".implode("','", $parents)."'"; @@ -106,8 +108,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()) { - $ids[] = $item['id']; - $parents[] = $item['id']; $tmpItem = array( 'id' => $item['id'], 'shareWith' => $item['share_with'], @@ -118,12 +118,28 @@ class Helper extends \OC\Share\Constants { if (isset($item['file_target'])) { $tmpItem['fileTarget'] = $item['file_target']; } - $deletedItems[] = $tmpItem; + // if we have a new parent for the child we remember the child + // to update the parent, if not we add it to the list of items + // which should be deleted + if ($newParent !== null) { + $changeParent[] = $item['id']; + } else { + $deletedItems[] = $tmpItem; + $ids[] = $item['id']; + $parents[] = $item['id']; + } } } if ($excludeParent) { unset($ids[0]); } + + if (!empty($changeParent)) { + $idList = "'".implode("','", $changeParent)."'"; + $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `parent` = ? WHERE `id` IN ('.$idList.')'); + $query->execute(array($newParent)); + } + if (!empty($ids)) { $idList = "'".implode("','", $ids)."'"; $query = \OC_DB::prepare('DELETE FROM `*PREFIX*share` WHERE `id` IN ('.$idList.')'); diff --git a/lib/private/share/share.php b/lib/private/share/share.php index 706c51e4bd..b34b134ee8 100644 --- a/lib/private/share/share.php +++ b/lib/private/share/share.php @@ -294,23 +294,32 @@ class Share extends \OC\Share\Constants { $shares = array(); + $column = ($itemType === 'file' || $itemType === 'folder') ? 'file_source' : 'item_source'; + + $where = ' `' . $column . '` = ? AND `item_type` = ? '; + $arguments = array($itemSource, $itemType); + // for link shares $user === null + if ($user !== null) { + $where .= ' AND `share_with` = ? '; + $arguments[] = $user; + } + // first check if there is a db entry for the specific user $query = \OC_DB::prepare( - 'SELECT `file_target`, `item_target`, `permissions`, `expiration` + 'SELECT * FROM `*PREFIX*share` - WHERE - `item_source` = ? AND `item_type` = ? AND `share_with` = ?' + WHERE' . $where ); - $result = \OC_DB::executeAudited($query, array($itemSource, $itemType, $user)); + $result = \OC_DB::executeAudited($query, $arguments); while ($row = $result->fetchRow()) { $shares[] = $row; } //if didn't found a result than let's look for a group share. - if(empty($shares)) { + if(empty($shares) && $user !== null) { $groups = \OC_Group::getUserGroups($user); $query = \OC_DB::prepare( @@ -318,7 +327,7 @@ class Share extends \OC\Share\Constants { FROM `*PREFIX*share` WHERE - `item_source` = ? AND `item_type` = ? AND `share_with` in (?)' + `' . $column . '` = ? AND `item_type` = ? AND `share_with` in (?)' ); $result = \OC_DB::executeAudited($query, array($itemSource, $itemType, implode(',', $groups))); @@ -681,9 +690,31 @@ class Share extends \OC\Share\Constants { * @return boolean true on success or false on failure */ public static function unshare($itemType, $itemSource, $shareType, $shareWith) { - $item = self::getItems($itemType, $itemSource, $shareType, $shareWith, \OC_User::getUser(),self::FORMAT_NONE, null, 1); - if (!empty($item)) { - self::unshareItem($item); + + // check if it is a valid itemType + self::getBackend($itemType); + + $items = self::getItemSharedWithUser($itemType, $itemSource, $shareWith); + + $toDelete = array(); + $newParent = null; + $currentUser = \OC_User::getUser(); + foreach ($items as $item) { + // delete the item with the expected share_type and owner + if ((int)$item['share_type'] === (int)$shareType && $item['uid_owner'] === $currentUser) { + $toDelete = $item; + // if there is more then one result we don't have to delete the children + // but update their parent. For group shares the new parent should always be + // the original group share and not the db entry with the unique name + } else if ((int)$item['share_type'] === \OCP\Share::$shareTypeGroupUserUnique) { + $newParent = $item['parent']; + } else { + $newParent = $item['id']; + } + } + + if (!empty($toDelete)) { + self::unshareItem($toDelete, $newParent); return true; } return false; @@ -1056,9 +1087,10 @@ class Share extends \OC\Share\Constants { /** * Unshares a share given a share data array * @param array $item Share data (usually database row) + * @param int new parent ID * @return null */ - protected static function unshareItem(array $item) { + protected static function unshareItem(array $item, $newParent = null) { // Pass all the vars we have for now, they may be useful $hookParams = array( 'id' => $item['id'], @@ -1075,7 +1107,7 @@ class Share extends \OC\Share\Constants { } \OC_Hook::emit('OCP\Share', 'pre_unshare', $hookParams); - $deletedShares = Helper::delete($item['id']); + $deletedShares = Helper::delete($item['id'], false, null, $newParent); $deletedShares[] = $hookParams; $hookParams['deletedShares'] = $deletedShares; \OC_Hook::emit('OCP\Share', 'post_unshare', $hookParams);