diff options
Diffstat (limited to 'lib/private/Share/Share.php')
-rw-r--r-- | lib/private/Share/Share.php | 291 |
1 files changed, 33 insertions, 258 deletions
diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php index aed233692ed..2d0d4f1cf87 100644 --- a/lib/private/Share/Share.php +++ b/lib/private/Share/Share.php @@ -5,18 +5,16 @@ * @author Arthur Schiwon <blizzz@arthur-schiwon.de> * @author Bart Visscher <bartv@thisnet.nl> * @author Bernhard Reiter <ockham@raz.or.at> - * @author Bjoern Schiessle <bjoern@schiessle.org> * @author Björn Schießle <bjoern@schiessle.org> * @author Christoph Wurst <christoph@winzerhof-wurst.at> * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <robin@icewind.nl> * @author Robin McCorkell <robin@mccorkell.me.uk> * @author Roeland Jago Douma <roeland@famdouma.nl> * @author Sebastian Döll <sebastian.doell@libasys.de> * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Vincent Petry <pvince81@owncloud.com> + * @author Vincent Petry <vincent@nextcloud.com> * @author Volkan Gezer <volkangezer@gmail.com> * * @license AGPL-3.0 @@ -104,8 +102,7 @@ class Share extends Constants { * \OC\Share\Share::getItemsSharedWith('folder'); (apps/files_sharing/tests/UpdaterTest.php) */ public static function getItemsSharedWith() { - return self::getItems('folder', null, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, self::FORMAT_NONE, - null, -1, false); + return self::getItems('folder', null, self::$shareTypeUserAndGroups, \OC_User::getUser()); } /** @@ -117,11 +114,12 @@ class Share extends Constants { * @param int $limit Number of items to return (optional) Returns all by default * @param boolean $includeCollections (optional) * @return mixed Return depends on format + * @deprecated TESTS ONLY - this methods is only used by tests + * called like this: + * \OC\Share\Share::getItemsSharedWithUser('test', $shareWith); (tests/lib/Share/Backend.php) */ - 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); + public static function getItemsSharedWithUser($itemType, $user) { + return self::getItems('test', null, self::$shareTypeUserAndGroups, $user); } /** @@ -194,6 +192,7 @@ class Share extends Constants { } $shares[] = $row; } + $result->closeCursor(); //if didn't found a result than let's look for a group share. if (empty($shares) && $user !== null) { @@ -233,23 +232,6 @@ class Share extends Constants { } /** - * Get the item of item type shared with the current user by source - * @param string $itemType - * @param string $itemSource - * @param int $format (optional) Format type must be defined by the backend - * @param mixed $parameters - * @param boolean $includeCollections - * @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, $shareWith = null) { - $shareWith = ($shareWith === null) ? \OC_User::getUser() : $shareWith; - return self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups, $shareWith, null, $format, - $parameters, 1, $includeCollections, true); - } - - /** * Get the shared item of item type owned by the current user * @param string $itemType * @param string $itemSource @@ -257,126 +239,14 @@ class Share extends Constants { * @param mixed $parameters * @param boolean $includeCollections * @return mixed Return depends on format + * + * Refactoring notes: + * * defacto $parameters and $format is always the default and therefore is removed in the subsequent call */ public static function getItemShared($itemType, $itemSource, $format = self::FORMAT_NONE, $parameters = null, $includeCollections = false) { - return self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), $format, - $parameters, -1, $includeCollections); - } - - /** - * Unshare an item from a user, group, or delete a private link - * @param string $itemType - * @param string $itemSource - * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK - * @param string $shareWith User or group the item is being shared with - * @param string $owner owner of the share, if null the current user is used - * @return boolean true on success or false on failure - */ - public static function unshare($itemType, $itemSource, $shareType, $shareWith, $owner = null) { - - // check if it is a valid itemType - self::getBackend($itemType); - - $items = self::getItemSharedWithUser($itemType, $itemSource, $shareWith, $owner, $shareType); - - $toDelete = []; - $newParent = null; - $currentUser = $owner ? $owner : \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 - } elseif ((int)$item['share_type'] === self::$shareTypeGroupUserUnique) { - $newParent = $item['parent']; - } else { - $newParent = $item['id']; - } - } - - if (!empty($toDelete)) { - self::unshareItem($toDelete, $newParent); - return true; - } - return false; - } - - /** - * Checks whether a share has expired, calls unshareItem() if yes. - * @param array $item Share data (usually database row) - * @return boolean True if item was expired, false otherwise. - */ - protected static function expireItem(array $item) { - $result = false; - - // only use default expiration date for link shares - if ((int) $item['share_type'] === IShare::TYPE_LINK) { - - // calculate expiration date - if (!empty($item['expiration'])) { - $userDefinedExpire = new \DateTime($item['expiration']); - $expires = $userDefinedExpire->getTimestamp(); - } else { - $expires = null; - } - - - // get default expiration settings - $defaultSettings = Helper::getDefaultExpireSetting(); - $expires = Helper::calculateExpireDate($defaultSettings, $item['stime'], $expires); - - - if (is_int($expires)) { - $now = time(); - if ($now > $expires) { - self::unshareItem($item); - $result = true; - } - } - } - return $result; - } - - /** - * Unshares a share given a share data array - * @param array $item Share data (usually database row) - * @param int $newParent parent ID - * @return null - */ - protected static function unshareItem(array $item, $newParent = null) { - $shareType = (int)$item['share_type']; - $shareWith = null; - if ($shareType !== IShare::TYPE_LINK) { - $shareWith = $item['share_with']; - } - - // Pass all the vars we have for now, they may be useful - $hookParams = [ - 'id' => $item['id'], - 'itemType' => $item['item_type'], - 'itemSource' => $item['item_source'], - 'shareType' => $shareType, - 'shareWith' => $shareWith, - 'itemParent' => $item['parent'], - 'uidOwner' => $item['uid_owner'], - ]; - if ($item['item_type'] === 'file' || $item['item_type'] === 'folder') { - $hookParams['fileSource'] = $item['file_source']; - $hookParams['fileTarget'] = $item['file_target']; - } - - \OC_Hook::emit(\OCP\Share::class, 'pre_unshare', $hookParams); - $deletedShares = Helper::delete($item['id'], false, null, $newParent); - $deletedShares[] = $hookParams; - $hookParams['deletedShares'] = $deletedShares; - \OC_Hook::emit(\OCP\Share::class, 'post_unshare', $hookParams); - if ((int)$item['share_type'] === IShare::TYPE_REMOTE && \OC::$server->getUserSession()->getUser()) { - list(, $remote) = Helper::splitUserRemote($item['share_with']); - self::sendRemoteUnshare($remote, $item['id'], $item['token']); - } + return self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), self::FORMAT_NONE, + null, -1, $includeCollections); } /** @@ -471,10 +341,12 @@ class Share extends Constants { * * See public functions getItem(s)... for parameter usage * + * Refactoring notes: + * * defacto $limit, $itemsShareWithBySource, $checkExpireDate, $parameters and $format is always the default and therefore is removed in the subsequent call */ public static function getItems($itemType, $item = null, $shareType = null, $shareWith = null, $uidOwner = null, $format = self::FORMAT_NONE, $parameters = null, $limit = -1, - $includeCollections = false, $itemShareWithBySource = false, $checkExpireDate = true) { + $includeCollections = false, $itemShareWithBySource = false, $checkExpireDate = true) { if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_enabled', 'yes') != 'yes') { return []; } @@ -578,7 +450,7 @@ class Share extends Constants { $where .= ' AND'; } // If looking for own shared items, check item_source else check item_target - if (isset($uidOwner) || $itemShareWithBySource) { + if (isset($uidOwner)) { // If item type is a file, file source needs to be checked in case the item was converted if ($fileDependent) { $where .= ' `file_source` = ?'; @@ -603,26 +475,10 @@ class Share extends Constants { } } - 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'; - } + $where .= ' ORDER BY `*PREFIX*share`.`id` ASC'; - if ($limit != -1 && !$includeCollections) { - // The limit must be at least 3, because filtering needs to be done - if ($limit < 3) { - $queryLimit = 3; - } else { - $queryLimit = $limit; - } - } else { - $queryLimit = null; - } - $select = self::createSelectStatement($format, $fileDependent, $uidOwner); + $queryLimit = null; + $select = self::createSelectStatement(self::FORMAT_NONE, $fileDependent, $uidOwner); $root = strlen($root); $query = \OC_DB::prepare('SELECT '.$select.' FROM `*PREFIX*share` '.$where, $queryLimit); $result = $query->execute($queryArgs); @@ -687,14 +543,20 @@ class Share extends Constants { // Remove root from file source paths if retrieving own shared items if (isset($uidOwner) && isset($row['path'])) { if (isset($row['parent'])) { - $query = \OC_DB::prepare('SELECT `file_target` FROM `*PREFIX*share` WHERE `id` = ?'); - $parentResult = $query->execute([$row['parent']]); - if ($result === false) { + $query = \OC::$server->getDatabaseConnection()->getQueryBuilder(); + $query->select('file_target') + ->from('share') + ->where($query->expr()->eq('id', $query->createNamedParameter($row['parent']))); + + $parentResult = $query->execute(); + $parentRow = $parentResult->fetch(); + $parentResult->closeCursor(); + + if ($parentRow === false) { \OCP\Util::writeLog('OCP\Share', 'Can\'t select parent: ' . \OC_DB::getErrorMessage() . ', select=' . $select . ' where=' . $where, ILogger::ERROR); } else { - $parentRow = $parentResult->fetchRow(); $tmpPath = $parentRow['file_target']; // find the right position where the row path continues from the target path $pos = strrpos($row['path'], $parentRow['file_target']); @@ -720,11 +582,6 @@ class Share extends Constants { } } - if ($checkExpireDate) { - if (self::expireItem($row)) { - continue; - } - } // Check if resharing is allowed, if not remove share permission if (isset($row['permissions']) && (!self::isResharingAllowed() | \OCP\Util::isSharingDisabledForUser())) { $row['permissions'] &= ~\OCP\Constants::PERMISSION_SHARE; @@ -764,14 +621,6 @@ class Share extends Constants { if (!empty($items)) { $collectionItems = []; foreach ($items as &$row) { - // Return only the item instead of a 2-dimensional array - if ($limit == 1 && $row[$column] == $item && ($row['item_type'] == $itemType || $itemType == 'file')) { - if ($format == self::FORMAT_NONE) { - return $row; - } else { - break; - } - } // Check if this is a collection of the requested item type if ($includeCollections && $collectionTypes && $row['item_type'] !== 'folder' && in_array($row['item_type'], $collectionTypes)) { if (($collectionBackend = self::getBackend($row['item_type'])) @@ -807,19 +656,7 @@ class Share extends Constants { } if (isset($item)) { if ($childItem[$column] == $item) { - // Return only the item instead of a 2-dimensional array - if ($limit == 1) { - if ($format == self::FORMAT_NONE) { - return $childItem; - } else { - // Unset the items array and break out of both loops - $items = []; - $items[] = $childItem; - break 2; - } - } else { - $collectionItems[] = $childItem; - } + $collectionItems[] = $childItem; } } else { $collectionItems[] = $childItem; @@ -855,7 +692,7 @@ class Share extends Constants { return $item['share_type'] !== self::$shareTypeGroupUserUnique; }); - return self::formatResult($items, $column, $backend, $format, $parameters); + return self::formatResult($items, $column, $backend); } elseif ($includeCollections && $collectionTypes && in_array('folder', $collectionTypes)) { // FIXME: Thats a dirty hack to improve file sharing performance, // see github issue #10588 for more details @@ -866,10 +703,7 @@ class Share extends Constants { foreach ($sharedParents as $parent) { $collectionItems[] = $parent; } - if ($limit === 1) { - return reset($collectionItems); - } - return self::formatResult($collectionItems, $column, $backend, $format, $parameters); + return self::formatResult($collectionItems, $column, $backend); } return []; @@ -1049,65 +883,6 @@ class Share extends Constants { return $url; } - /** - * try http post first with https and then with http as a fallback - * - * @param string $remoteDomain - * @param string $urlSuffix - * @param array $fields post parameters - * @return array - */ - private static function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields) { - $protocol = 'https://'; - $result = [ - 'success' => false, - 'result' => '', - ]; - $try = 0; - $discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class); - while ($result['success'] === false && $try < 2) { - $federationEndpoints = $discoveryService->discover($protocol . $remoteDomain, 'FEDERATED_SHARING'); - $endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares'; - $client = \OC::$server->getHTTPClientService()->newClient(); - - try { - $response = $client->post( - $protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, - [ - 'body' => $fields, - 'connect_timeout' => 10, - ] - ); - - $result = ['success' => true, 'result' => $response->getBody()]; - } catch (\Exception $e) { - $result = ['success' => false, 'result' => $e->getMessage()]; - } - - $try++; - $protocol = 'http://'; - } - - return $result; - } - - /** - * send server-to-server unshare to remote server - * - * @param string $remote url - * @param int $id share id - * @param string $token - * @return bool - */ - private static function sendRemoteUnshare($remote, $id, $token) { - $url = rtrim($remote, '/'); - $fields = ['token' => $token, 'format' => 'json']; - $url = self::removeProtocolFromUrl($url); - $result = self::tryHttpPostToShareEndpoint($url, '/'.$id.'/unshare', $fields); - $status = json_decode($result['result'], true); - - return ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200)); - } /** * @return int |