diff options
Diffstat (limited to 'lib/private/share/share.php')
-rw-r--r-- | lib/private/share/share.php | 601 |
1 files changed, 336 insertions, 265 deletions
diff --git a/lib/private/share/share.php b/lib/private/share/share.php index 22e354e515d..cfdc8aa9ffe 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`, `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))); @@ -339,11 +348,13 @@ class Share extends \OC\Share\Constants { * @param int $format (optional) Format type must be defined by the backend * @param mixed $parameters * @param boolean $includeCollections - * @return mixed Return depends on format + * @param string $shareWith (optional) define against which user should be checked, default: current user + * @return array */ public static function getItemSharedWithBySource($itemType, $itemSource, $format = self::FORMAT_NONE, - $parameters = null, $includeCollections = false) { - return self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format, + $parameters = null, $includeCollections = false, $shareWith = null) { + $shareWith = ($shareWith === null) ? \OC_User::getUser() : $shareWith; + return self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups, $shareWith, null, $format, $parameters, 1, $includeCollections, true); } @@ -676,9 +687,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'] === self::$shareTypeGroupUserUnique) { + $newParent = $item['parent']; + } else { + $newParent = $item['id']; + } + } + + if (!empty($toDelete)) { + self::unshareItem($toDelete, $newParent); return true; } return false; @@ -769,7 +802,7 @@ class Share extends \OC\Share\Constants { } } - if (!$itemUnshared && isset($groupShare)) { + if (!$itemUnshared && isset($groupShare) && !isset($uniqueGroupShare)) { $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`)' @@ -1050,9 +1083,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'], @@ -1069,7 +1103,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); @@ -1288,13 +1322,17 @@ class Share extends \OC\Share\Constants { $queryArgs = array_merge($queryArgs, $collectionTypes); } } + + if ($shareType == self::$shareTypeUserAndGroups && $limit === 1) { + // Make sure the unique user target is returned if it exists, + // unique targets should follow the group share in the database + // If the limit is not 1, the filtering can be done later + $where .= ' ORDER BY `*PREFIX*share`.`id` DESC'; + } else { + $where .= ' ORDER BY `*PREFIX*share`.`id` ASC'; + } + if ($limit != -1 && !$includeCollections) { - if ($shareType == self::$shareTypeUserAndGroups) { - // Make sure the unique user target is returned if it exists, - // unique targets should follow the group share in the database - // If the limit is not 1, the filtering can be done later - $where .= ' ORDER BY `*PREFIX*share`.`id` DESC'; - } // The limit must be at least 3, because filtering needs to be done if ($limit < 3) { $queryLimit = 3; @@ -1303,7 +1341,6 @@ class Share extends \OC\Share\Constants { } } else { $queryLimit = null; - $where .= ' ORDER BY `*PREFIX*share`.`id` ASC'; } $select = self::createSelectStatement($format, $fileDependent, $uidOwner); $root = strlen($root); @@ -1311,7 +1348,7 @@ class Share extends \OC\Share\Constants { $result = $query->execute($queryArgs); if (\OC_DB::isError($result)) { \OC_Log::write('OCP\Share', - \OC_DB::getErrorMessage($result) . ', select=' . $select . ' where=' . $where, + \OC_DB::getErrorMessage($result) . ', select=' . $select . ' where=', \OC_Log::ERROR); } $items = array(); @@ -1325,6 +1362,12 @@ class Share extends \OC\Share\Constants { $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']; + // if the group share was unshared from the user we keep the permission, otherwise + // we take the permission from the parent because this is always the up-to-date + // permission for the group share + if ($row['permissions'] > 0) { + $row['permissions'] = $items[$row['parent']]['permissions']; + } // Remove the parent group share unset($items[$row['parent']]); if ($row['permissions'] == 0) { @@ -1332,10 +1375,10 @@ class Share extends \OC\Share\Constants { } } else if (!isset($uidOwner)) { // Check if the same target already exists - if (isset($targets[$row[$column]])) { + if (isset($targets[$row['id']])) { // Check if the same owner shared with the user twice // through a group and user share - this is allowed - $id = $targets[$row[$column]]; + $id = $targets[$row['id']]; if (isset($items[$id]) && $items[$id]['uid_owner'] == $row['uid_owner']) { // Switch to group share type to ensure resharing conditions aren't bypassed if ($items[$id]['share_type'] != self::SHARE_TYPE_GROUP) { @@ -1351,12 +1394,12 @@ class Share extends \OC\Share\Constants { unset($items[$id]); $id = $row['id']; } - // Combine the permissions for the item $items[$id]['permissions'] |= (int)$row['permissions']; - continue; + } - } else { - $targets[$row[$column]] = $row['id']; + continue; + } elseif (!empty($row['parent'])) { + $targets[$row['parent']] = $row['id']; } } // Remove root from file source paths if retrieving own shared items @@ -1394,6 +1437,7 @@ class Share extends \OC\Share\Constants { } } } + if($checkExpireDate) { if (self::expireItem($row)) { continue; @@ -1411,8 +1455,17 @@ class Share extends \OC\Share\Constants { $row['displayname_owner'] = \OCP\User::getDisplayName($row['uid_owner']); } - $items[$row['id']] = $row; + if ($row['permissions'] > 0) { + $items[$row['id']] = $row; + } + + } + + // group items if we are looking for items shared with the current user + if (isset($shareWith) && $shareWith === \OCP\User::getUser()) { + $items = self::groupItems($items, $itemType); } + if (!empty($items)) { $collectionItems = array(); foreach ($items as &$row) { @@ -1498,6 +1551,47 @@ class Share extends \OC\Share\Constants { } /** + * group items with link to the same source + * + * @param array $items + * @param string $itemType + * @return array of grouped items + */ + protected static function groupItems($items, $itemType) { + + $fileSharing = ($itemType === 'file' || $itemType === 'folder') ? true : false; + + $result = array(); + + foreach ($items as $item) { + $grouped = false; + foreach ($result as $key => $r) { + // for file/folder shares we need to compare file_source, otherwise we compare item_source + // only group shares if they already point to the same target, otherwise the file where shared + // before grouping of shares was added. In this case we don't group them toi avoid confusions + if (( $fileSharing && $item['file_source'] === $r['file_source'] && $item['file_target'] === $r['file_target']) || + (!$fileSharing && $item['item_source'] === $r['item_source'] && $item['item_target'] === $r['item_target'])) { + // add the first item to the list of grouped shares + if (!isset($result[$key]['grouped'])) { + $result[$key]['grouped'][] = $result[$key]; + } + $result[$key]['permissions'] = (int) $item['permissions'] | (int) $r['permissions']; + $result[$key]['grouped'][] = $item; + $grouped = true; + break; + } + } + + if (!$grouped) { + $result[] = $item; + } + + } + + return $result; + } + +/** * Put shared item into the database * @param string $itemType Item type * @param string $itemSource Item source @@ -1514,121 +1608,34 @@ class Share extends \OC\Share\Constants { */ private static function put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, $parentFolder = null, $token = null, $itemSourceName = null, \DateTime $expirationDate = null) { - $backend = self::getBackend($itemType); - $l = \OC_L10N::get('lib'); - // Check if this is a reshare - if ($checkReshare = self::getItemSharedWithBySource($itemType, $itemSource, self::FORMAT_NONE, null, true)) { - // Check if attempting to share back to owner - if ($checkReshare['uid_owner'] == $shareWith && $shareType == self::SHARE_TYPE_USER) { - $message = 'Sharing %s failed, because the user %s is the original sharer'; - $message_t = $l->t('Sharing %s failed, because the user %s is the original sharer', array($itemSourceName, $shareWith)); + $queriesToExecute = array(); + $suggestedItemTarget = null; - \OC_Log::write('OCP\Share', sprintf($message, $itemSourceName, $shareWith), \OC_Log::ERROR); - throw new \Exception($message_t); - } - // Check if share permissions is granted - if (self::isResharingAllowed() && (int)$checkReshare['permissions'] & \OCP\PERMISSION_SHARE) { - if (~(int)$checkReshare['permissions'] & $permissions) { - $message = 'Sharing %s failed, because the permissions exceed permissions granted to %s'; - $message_t = $l->t('Sharing %s failed, because the permissions exceed permissions granted to %s', array($itemSourceName, $uidOwner)); - - \OC_Log::write('OCP\Share', sprintf($message, $itemSourceName, $uidOwner), \OC_Log::ERROR); - throw new \Exception($message_t); - } else { - // TODO Don't check if inside folder - $parent = $checkReshare['id']; - $itemSource = $checkReshare['item_source']; - $fileSource = $checkReshare['file_source']; - $suggestedItemTarget = $checkReshare['item_target']; - $suggestedFileTarget = $checkReshare['file_target']; - $filePath = $checkReshare['file_target']; - $expirationDate = min($expirationDate, $checkReshare['expiration']); - } - } else { - $message = 'Sharing %s failed, because resharing is not allowed'; - $message_t = $l->t('Sharing %s failed, because resharing is not allowed', array($itemSourceName)); - - \OC_Log::write('OCP\Share', sprintf($message, $itemSourceName), \OC_Log::ERROR); - throw new \Exception($message_t); - } - } else { - $parent = null; - $suggestedItemTarget = null; - $suggestedFileTarget = null; - if (!$backend->isValidSource($itemSource, $uidOwner)) { - $message = 'Sharing %s failed, because the sharing backend for ' - .'%s could not find its source'; - $message_t = $l->t('Sharing %s failed, because the sharing backend for %s could not find its source', array($itemSource, $itemType)); - \OC_Log::write('OCP\Share', sprintf($message, $itemSource, $itemType), \OC_Log::ERROR); - throw new \Exception($message_t); - } - if ($backend instanceof \OCP\Share_Backend_File_Dependent) { - $filePath = $backend->getFilePath($itemSource, $uidOwner); - if ($itemType == 'file' || $itemType == 'folder') { - $fileSource = $itemSource; - } else { - $meta = \OC\Files\Filesystem::getFileInfo($filePath); - $fileSource = $meta['fileid']; - } - if ($fileSource == -1) { - $message = 'Sharing %s failed, because the file could not be found in the file cache'; - $message_t = $l->t('Sharing %s failed, because the file could not be found in the file cache', array($itemSource)); - - \OC_Log::write('OCP\Share', sprintf($message, $itemSource), \OC_Log::ERROR); - throw new \Exception($message_t); - } - } else { - $filePath = null; - $fileSource = null; - } + $result = self::checkReshare($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, $itemSourceName, $expirationDate); + if(!empty($result)) { + $parent = $result['parent']; + $itemSource = $result['itemSource']; + $fileSource = $result['fileSource']; + $suggestedItemTarget = $result['suggestedItemTarget']; + $suggestedFileTarget = $result['suggestedFileTarget']; + $filePath = $result['filePath']; + $expirationDate = $result['expirationDate']; } - // Share with a group + $isGroupShare = false; if ($shareType == self::SHARE_TYPE_GROUP) { - $groupItemTarget = Helper::generateTarget($itemType, $itemSource, $shareType, $shareWith['group'], - $uidOwner, $suggestedItemTarget); - $run = true; - $error = ''; - \OC_Hook::emit('OCP\Share', 'pre_shared', array( - 'itemType' => $itemType, - 'itemSource' => $itemSource, - 'itemTarget' => $groupItemTarget, - 'shareType' => $shareType, - 'shareWith' => $shareWith['group'], - 'uidOwner' => $uidOwner, - 'permissions' => $permissions, - 'fileSource' => $fileSource, - 'expiration' => $expirationDate, - 'token' => $token, - 'run' => &$run, - 'error' => &$error - )); - - if ($run === false) { - throw new \Exception($error); - } - - if (isset($fileSource)) { - if ($parentFolder) { - if ($parentFolder === true) { - $groupFileTarget = Helper::generateTarget('file', $filePath, $shareType, - $shareWith['group'], $uidOwner, $suggestedFileTarget); - // Set group default file target for future use - $parentFolders[0]['folder'] = $groupFileTarget; - } else { - // Get group default file target - $groupFileTarget = $parentFolder[0]['folder'].$itemSource; - $parent = $parentFolder[0]['id']; - } - } else { - $groupFileTarget = Helper::generateTarget('file', $filePath, $shareType, $shareWith['group'], - $uidOwner, $suggestedFileTarget); - } - } else { - $groupFileTarget = null; + $isGroupShare = true; + $users = \OC_Group::usersInGroup($shareWith['group']); + // remove current user from list + if (in_array(\OCP\User::getUser(), $users)) { + unset($users[array_search(\OCP\User::getUser(), $users)]); } - $queriesToExecute = array(); + $groupItemTarget = Helper::generateTarget($itemType, $itemSource, $shareType, $shareWith['group'], + $uidOwner, $suggestedItemTarget); + $groupFileTarget = $filePath; + + // add group share to table and remember the id as parent $queriesToExecute['groupShare'] = array( 'itemType' => $itemType, 'itemSource' => $itemSource, @@ -1639,165 +1646,229 @@ class Share extends \OC\Share\Constants { 'permissions' => $permissions, 'shareTime' => time(), 'fileSource' => $fileSource, - 'fileTarget' => $groupFileTarget, + 'fileTarget' => $filePath, 'token' => $token, 'parent' => $parent, 'expiration' => $expirationDate, ); - // 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, + + } else { + $users = array($shareWith); + $itemTarget = Helper::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner, + $suggestedItemTarget); + } + + $run = true; + $error = ''; + $preHookData = array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'shareType' => $shareType, + 'uidOwner' => $uidOwner, + 'permissions' => $permissions, + 'fileSource' => $fileSource, + 'expiration' => $expirationDate, + 'token' => $token, + 'run' => &$run, + 'error' => &$error + ); + + $preHookData['itemTarget'] = ($isGroupShare) ? $groupItemTarget : $itemTarget; + $preHookData['shareWith'] = ($isGroupShare) ? $shareWith['group'] : $shareWith; + + \OC_Hook::emit('OCP\Share', 'pre_shared', $preHookData); + + if ($run === false) { + throw new \Exception($error); + } + + foreach ($users as $user) { + $sourceId = ($itemType === 'file' || $itemType === 'folder') ? $fileSource : $itemSource; + $sourceExists = self::getItemSharedWithBySource($itemType, $sourceId, self::FORMAT_NONE, null, true, $user); + + $shareType = ($isGroupShare) ? self::$shareTypeGroupUserUnique : $shareType; + + if ($sourceExists) { + $fileTarget = $sourceExists['file_target']; + $itemTarget = $sourceExists['item_target']; + + // for group shares we don't need a additional entry if the target is the same + if($isGroupShare && $groupItemTarget === $itemTarget) { + continue; + } + + } elseif(!$sourceExists && !$isGroupShare) { + + $itemTarget = Helper::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $user, $uidOwner, $suggestedItemTarget, $parent); if (isset($fileSource)) { if ($parentFolder) { if ($parentFolder === true) { - $fileTarget = Helper::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $uid, + $fileTarget = Helper::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $user, $uidOwner, $suggestedFileTarget, $parent); if ($fileTarget != $groupFileTarget) { - $parentFolders[$uid]['folder'] = $fileTarget; + $parentFolders[$user]['folder'] = $fileTarget; } - } else if (isset($parentFolder[$uid])) { - $fileTarget = $parentFolder[$uid]['folder'].$itemSource; - $parent = $parentFolder[$uid]['id']; + } else if (isset($parentFolder[$user])) { + $fileTarget = $parentFolder[$user]['folder'].$itemSource; + $parent = $parentFolder[$user]['id']; } } else { $fileTarget = Helper::generateTarget('file', $filePath, self::SHARE_TYPE_USER, - $uid, $uidOwner, $suggestedFileTarget, $parent); + $user, $uidOwner, $suggestedFileTarget, $parent); } } else { $fileTarget = null; } - // 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)) { - $queriesToExecute[] = array( - 'itemType' => $itemType, - 'itemSource' => $itemSource, - 'itemTarget' => $itemTarget, - 'shareType' => self::$shareTypeGroupUserUnique, - 'shareWith' => $uid, - 'uidOwner' => $uidOwner, - 'permissions' => $permissions, - 'shareTime' => time(), - 'fileSource' => $fileSource, - 'fileTarget' => $fileTarget, - 'token' => $token, - //'parent' => $parent, - 'expiration' => $expirationDate, - ); + + } else { + + // group share which doesn't exists until now, check if we need a unique target for this user + + $itemTarget = Helper::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $user, + $uidOwner, $suggestedItemTarget, $parent); + + // do we also need a file target + if (isset($fileSource)) { + $fileTarget = Helper::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $user, + $uidOwner, $suggestedFileTarget, $parent); + } else { + $fileTarget = null; + } + + if ($itemTarget === $groupItemTarget && (isset($fileSource) && $fileTarget === $groupItemTarget)) { + continue; } } + $queriesToExecute[] = array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'itemTarget' => $itemTarget, + 'shareType' => $shareType, + 'shareWith' => $user, + 'uidOwner' => $uidOwner, + 'permissions' => $permissions, + 'shareTime' => time(), + 'fileSource' => $fileSource, + 'fileTarget' => $fileTarget, + 'token' => $token, + 'parent' => $parent, + 'expiration' => $expirationDate, + ); + + } + + if ($isGroupShare) { self::insertShare($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 $shareQuery) { - $shareQuery['parent'] = $parent; - self::insertShare($shareQuery); - } + foreach ($queriesToExecute as $shareQuery) { + $shareQuery['parent'] = $parent; + self::insertShare($shareQuery); + } - \OC_Hook::emit('OCP\Share', 'post_shared', array( - 'itemType' => $itemType, - 'itemSource' => $itemSource, - 'itemTarget' => $groupItemTarget, - 'parent' => $parent, - 'shareType' => $shareType, - 'shareWith' => $shareWith['group'], - 'uidOwner' => $uidOwner, - 'permissions' => $permissions, - 'fileSource' => $fileSource, - 'fileTarget' => $groupFileTarget, - 'id' => $parent, - 'token' => $token, - 'expirationDate' => $expirationDate, - )); - - if ($parentFolder === true) { - // Return parent folders to preserve file target paths for potential children - return $parentFolders; + $postHookData = array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'parent' => $parent, + 'shareType' => $shareType, + 'uidOwner' => $uidOwner, + 'permissions' => $permissions, + 'fileSource' => $fileSource, + 'id' => $parent, + 'token' => $token, + 'expirationDate' => $expirationDate, + ); + + $postHookData['shareWith'] = ($isGroupShare) ? $shareWith['group'] : $shareWith; + $postHookData['itemTarget'] = ($isGroupShare) ? $groupItemTarget : $itemTarget; + $postHookData['fileTarget'] = ($isGroupShare) ? $groupFileTarget : $fileTarget; + + \OC_Hook::emit('OCP\Share', 'post_shared', $postHookData); + + + return true; + } + + private static function checkReshare($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, $itemSourceName, $expirationDate) { + $backend = self::getBackend($itemType); + $l = \OC_L10N::get('lib'); + + $checkReshare = self::getItemSharedWithBySource($itemType, $itemSource, self::FORMAT_NONE, null, true); + if ($checkReshare) { + // Check if attempting to share back to owner + if ($checkReshare['uid_owner'] == $shareWith && $shareType == self::SHARE_TYPE_USER) { + $message = 'Sharing %s failed, because the user %s is the original sharer'; + $message_t = $l->t('Sharing %s failed, because the user %s is the original sharer', array($itemSourceName, $shareWith)); + + \OC_Log::write('OCP\Share', sprintf($message, $itemSourceName, $shareWith), \OC_Log::ERROR); + throw new \Exception($message_t); } - } else { - $itemTarget = Helper::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner, - $suggestedItemTarget); - $run = true; - $error = ''; - \OC_Hook::emit('OCP\Share', 'pre_shared', array( - 'itemType' => $itemType, - 'itemSource' => $itemSource, - 'itemTarget' => $itemTarget, - 'shareType' => $shareType, - 'shareWith' => $shareWith, - 'uidOwner' => $uidOwner, - 'permissions' => $permissions, - 'fileSource' => $fileSource, - 'token' => $token, - 'expirationDate' => $expirationDate, - 'run' => &$run, - 'error' => &$error, - )); - - if ($run === false) { - throw new \Exception($error); - } - - if (isset($fileSource)) { - if ($parentFolder) { - if ($parentFolder === true) { - $fileTarget = Helper::generateTarget('file', $filePath, $shareType, $shareWith, - $uidOwner, $suggestedFileTarget); - $parentFolders['folder'] = $fileTarget; - } else { - $fileTarget = $parentFolder['folder'].$itemSource; - $parent = $parentFolder['id']; - } + + // Check if share permissions is granted + if (self::isResharingAllowed() && (int)$checkReshare['permissions'] & \OCP\PERMISSION_SHARE) { + if (~(int)$checkReshare['permissions'] & $permissions) { + $message = 'Sharing %s failed, because the permissions exceed permissions granted to %s'; + $message_t = $l->t('Sharing %s failed, because the permissions exceed permissions granted to %s', array($itemSourceName, $uidOwner)); + + \OC_Log::write('OCP\Share', sprintf($message, $itemSourceName, $uidOwner), \OC_Log::ERROR); + throw new \Exception($message_t); } else { - $fileTarget = Helper::generateTarget('file', $filePath, $shareType, $shareWith, $uidOwner, - $suggestedFileTarget); + // TODO Don't check if inside folder + $result['parent'] = $checkReshare['id']; + $result['itemSource'] = $checkReshare['item_source']; + $result['fileSource'] = $checkReshare['file_source']; + $result['suggestedItemTarget'] = $checkReshare['item_target']; + $result['suggestedFileTarget'] = $checkReshare['file_target']; + $result['filePath'] = $checkReshare['file_target']; + $result['expirationDate'] = min($expirationDate, $checkReshare['expiration']); } } else { - $fileTarget = null; - } + $message = 'Sharing %s failed, because resharing is not allowed'; + $message_t = $l->t('Sharing %s failed, because resharing is not allowed', array($itemSourceName)); - self::insertShare(array( - 'itemType' => $itemType, - 'itemSource' => $itemSource, - 'itemTarget' => $itemTarget, - 'shareType' => $shareType, - 'shareWith' => $shareWith, - 'uidOwner' => $uidOwner, - 'permissions' => $permissions, - 'shareTime' => time(), - 'fileSource' => $fileSource, - 'fileTarget' => $fileTarget, - 'token' => $token, - 'parent' => $parent, - 'expiration' => $expirationDate, - )); + \OC_Log::write('OCP\Share', sprintf($message, $itemSourceName), \OC_Log::ERROR); + throw new \Exception($message_t); + } + } else { + $result['parent'] = null; + $result['suggestedItemTarget'] = null; + $result['suggestedFileTarget'] = null; + $result['itemSource'] = $itemSource; + $result['expirationDate'] = $expirationDate; + if (!$backend->isValidSource($itemSource, $uidOwner)) { + $message = 'Sharing %s failed, because the sharing backend for ' + .'%s could not find its source'; + $message_t = $l->t('Sharing %s failed, because the sharing backend for %s could not find its source', array($itemSource, $itemType)); + \OC_Log::write('OCP\Share', sprintf($message, $itemSource, $itemType), \OC_Log::ERROR); + throw new \Exception($message_t); + } + if ($backend instanceof \OCP\Share_Backend_File_Dependent) { + $result['filePath'] = $backend->getFilePath($itemSource, $uidOwner); + if ($itemType == 'file' || $itemType == 'folder') { + $result['fileSource'] = $itemSource; + } else { + $meta = \OC\Files\Filesystem::getFileInfo($result['filePath']); + $result['fileSource'] = $meta['fileid']; + } + if ($result['fileSource'] == -1) { + $message = 'Sharing %s failed, because the file could not be found in the file cache'; + $message_t = $l->t('Sharing %s failed, because the file could not be found in the file cache', array($itemSource)); - $id = \OC_DB::insertid('*PREFIX*share'); - \OC_Hook::emit('OCP\Share', 'post_shared', array( - 'itemType' => $itemType, - 'itemSource' => $itemSource, - 'itemTarget' => $itemTarget, - 'parent' => $parent, - 'shareType' => $shareType, - 'shareWith' => $shareWith, - 'uidOwner' => $uidOwner, - 'permissions' => $permissions, - 'fileSource' => $fileSource, - 'fileTarget' => $fileTarget, - 'id' => $id, - 'token' => $token, - 'expirationDate' => $expirationDate, - )); - if ($parentFolder === true) { - $parentFolders['id'] = $id; - // Return parent folder to preserve file target paths for potential children - return $parentFolders; + \OC_Log::write('OCP\Share', sprintf($message, $itemSource), \OC_Log::ERROR); + throw new \Exception($message_t); + } + } else { + $result['filePath'] = null; + $result['fileSource'] = null; } } - return true; + + return $result; } private static function insertShare(array $shareData) @@ -1873,9 +1944,9 @@ class Share extends \OC\Share\Constants { $select = '*'; if ($format == self::FORMAT_STATUSES) { if ($fileDependent) { - $select = '`*PREFIX*share`.`id`, `*PREFIX*share`.`parent`, `share_type`, `path`, `storage`, `share_with`, `uid_owner` , `file_source`, `stime`'; + $select = '`*PREFIX*share`.`id`, `*PREFIX*share`.`parent`, `share_type`, `path`, `storage`, `share_with`, `uid_owner` , `file_source`, `stime`, `*PREFIX*share`.`permissions`'; } else { - $select = '`id`, `parent`, `share_type`, `share_with`, `uid_owner`, `item_source`, `stime`'; + $select = '`id`, `parent`, `share_type`, `share_with`, `uid_owner`, `item_source`, `stime`, `*PREFIX*share`.`permissions`'; } } else { if (isset($uidOwner)) { |