From 0cc7ae904d046501cc7335bdcdd49f24cf237192 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Fri, 15 Jun 2012 20:52:56 -0400 Subject: [PATCH 001/145] Initial work on a share API --- lib/public/share.php | 673 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 673 insertions(+) create mode 100644 lib/public/share.php diff --git a/lib/public/share.php b/lib/public/share.php new file mode 100644 index 0000000000..38a23b4385 --- /dev/null +++ b/lib/public/share.php @@ -0,0 +1,673 @@ +. +*/ + +namespace OCP; + +/** +* This class provides the ability for apps to share their content between users. +* Apps must create a backend class that extends OCP\Share_Backend and register it with this class. +*/ +class Share { + + const SHARETYPE_USER = 0; + const SHARETYPE_GROUP = 1; + const SHARETYPE_CONTACT = 2; + const SHARETYPE_PRIVATE_LINK = 3; + + const PERMISSION_READ = 0; + const PERMISSION_UPDATE = 1; + const PERMISSION_DELETE = 2; + const PERMISSION_SHARE = 3; + + private static $backendTypes = array(); + private static $backends = array(); + private static $sharedFolder = '/Shared/'; + + /** + * @brief Register a sharing backend class that extends OCP\Share_Backend for an item type + * @param string Class + * @param string Item type + * @param string (optional) Depends on item type + * @param array (optional) List of supported file extensions if this item type depends on files + * @return Returns true if backend is registered or false if error + */ + public static function registerBackend($class, $itemType, $dependsOn = null, $supportedFileExtensions = null) { + if (is_subclass_of($class, 'OCP\Share_Backend')) { + if (!isset(self::$backendTypes[$itemType])) { + self::$backendTypes[$itemType] = array('class' => $class, 'dependsOn' => $dependsOn, 'supportedFileExtensions' => $supportedFileExtensions); + return true; + } else { + \OC_Log::write('OCP\Share', 'Sharing backend '.$class.' not registered, '.self::$backendTypes[$itemType]['class'].' is already registered for '.$itemType, \OC_Log::WARN); + return false; + } + } + \OC_Log::write('OCP\Share', 'Sharing backend '.$class.' not registered, the class must extend abstract class OC_Share_Backend', \OC_Log::ERROR); + return false; + } + + /** + * @brief Get the items of item type shared with the current user + * @param string Item type + * @return + */ + public static function getItemsSharedWith($itemType) { + return self::getItems($itemType, null, \OC_User::getUser(), true, null, true); + } + + /** + * @brief Get the item of item type shared with the current user + * @param string Item type + * @return + */ + public static function getItemSharedWith($itemType, $item) { + return self::getItems($itemType, $item, \OC_User::getUser(), true, null, true, 1); + } + + /** + * @brief Get the shared items of item type owned by the current user + * @param string Item type + * @return The + */ + public static function getItemsOwned($itemType) { + return self::getItems($itemType, null, null, null, \OC_User::getUser(), true); + } + + /** + * @brief Get the shared item of item type owned by the current user + * @param string Item type + * @return The + */ + public static function getItemOwned($itemType, $item) { + return self::getItems($itemType, $item, null, null, \OC_User::getUser(), true, 1); + } + + /** + * @brief Share an item with a user, group, or via private link + * @param string Item type + * @param string Item + * @param int SHARETYPE_USER | SHARETYPE_GROUP | SHARETYPE_PRIVATE_LINK + * @param string User or group the item is being shared with + * @param string + * @return Returns true on success or false on failure + */ + public static function share($itemType, $item, $shareType, $shareWith, $permissions) { + $uidOwner = \OC_User::getUser(); + // Verify share type and sharing conditions are met + switch ($shareType) { + case self::SHARETYPE_USER: + if ($shareWith == $uidOwner) { + \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because the user '.$shareWith.' is the item owner', \OC_Log::ERROR); + return false; + } + if (!\OC_User::userExists($shareWith)) { + \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because the user '.$shareWith.' does not exist', \OC_Log::ERROR); + return false; + } else { + $inGroup = array_intersect(\OC_Group::getUserGroups($uidOwner), \OC_Group::getUserGroups($shareWith)); + if (empty($inGroup)) { + \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because the user '.$shareWith.' is not a member of any groups that '.$uidOwner.' is a member of', \OC_Log::ERROR); + return false; + } + } + if (self::getItems($itemType, $item, $shareWith, true, $uidOwner, false, 1)) { + \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because this item is already shared with the user '.$shareWith, \OC_Log::ERROR); + return false; + } + $uidSharedWith = array($shareWith); + $gidSharedWith = null; + break; + case self::SHARETYPE_GROUP: + if (!\OC_Group::groupExists($shareWith)) { + \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because the group '.$shareWith.' does not exist', \OC_Log::ERROR); + return false; + } else if (!\OC_Group::inGroup($uidOwner, $shareWith)) { + \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because '.$uidOwner.' is not a member of the group '.$shareWith, \OC_Log::ERROR); + return false; + } + if (self::getItems($itemType, $item, null, $shareWith, $uidOwner, false, 1)) { + \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because this item is already shared with the group '.$shareWith, \OC_Log::ERROR); + return false; + } + $uidSharedWith = array_diff(\OC_Group::usersInGroup($shareWith), array($uidOwner)); + $gidSharedWith = $shareWith; + break; + case self::SHARETYPE_PRIVATE_LINK: + // TODO don't loop through folder conversion + $uidSharedWith = ''; + $gidSharedWith = null; + default: + \OC_Log::write('OCP\Share', 'Share type '.$shareType.' is not valid for '.$item, \OC_Log::ERROR); + return false; + } + // If the item is a folder, scan through the folder looking for equivalent item types + if ($itemType == 'folder') { + $parentFolder = self::put('folder', $item, $uidSharedWith, $gidSharedWith, $uidOwner, $permissions, true); + if ($parentFolder && $files = \OC_Files::getDirectoryContent($item)) { + for ($i = 0; $i < count($files); $i++) { + $name = substr($files[$i]['name'], strpos($files[$i]['name'], $item) - strlen($item)); + if ($files[$i]['mimetype'] == 'httpd/unix-directory' && $children = OC_Files::getDirectoryContent($name, '/')) { + // Continue scanning into child folders + array_push($files, $children); + } else { + // Pass on to put() to check if this item should be converted, the item won't be inserted into the database unless it can be converted + self::put('file', $name, $uidSharedWith, $gidSharedWith, $uidOwner, $permissions, $parentFolder); + } + } + return $return; + } + return false; + } else { + // Put the item into the database + return self::put($itemType, $item, $uidSharedWith, $gidSharedWith, $uidOwner, $permissions); + } + } + + /** + * @brief Unshare an item from a user, group, or delete a private link + * @param string Item type + * @param string Item + * @param int SHARETYPE_USER | SHARETYPE_GROUP | SHARETYPE_PRIVATE_LINK + * @param string User or group the item is being shared with + * @return Returns true on success or false on failure + */ + public static function unshare($itemType, $item, $shareType, $shareWith) { + $uidOwner = \OC_User::getUser(); + switch ($shareType) { + case self::SHARETYPE_USER: + case self::SHARETYPE_PRIVATE_LINK: + $item = self::getItems($itemType, $item, $shareWith, null, $uidOwner, false, 1); + break; + case self::SHARETYPE_GROUP: + $item = self::getItems($itemType, $item, null, $shareWith, $uidOwner, false, 1); + break; + default: + \OC_Log::write('OCP\Share', 'Share type '.$shareType.' is not valid for item '.$item, \OC_Log::ERROR); + return false; + } + if ($item) { + self::delete($item['item_source'], $item['id']); + return true; + } + return false; + } + + /** + * @brief + * @param + * @param + * @return + */ + public static function unshareFromSelf($itemType, $itemTarget) { + $uidSharedWith = \OC_User::getUser(); + if ($item = self::getItems($itemType, $itemTarget, $uidSharedWith, true, null, false, 1)) { + // TODO Check if item is inside a shared folder and was converted + if ($item['parent']) { + $query = \OC_DB::prepare('SELECT item_type FROM *PREFIX*sharing WHERE id = ? LIMIT 1'); + $result = $query->execute(array($item['parent']))->fetchRow(); + // TODO Check other parents + if (isset($result['item_type']) && $result['item_type'] = 'folder') { + return false; + } + } + // Check if this is a group share, if it is a group share a new entry needs to be created marked as unshared from self + if ($item['uid_shared_with'] == null) { + $query = \OC_DB::prepare('INSERT INTO *PREFIX*sharing VALUES(?,?,?,?,?,?,?,?,?,?)'); + $result = $query->execute(array($item['item_type'], $item['item_source'], $item['item_target'], $uidSharedWith, $item['gid_shared_with'], $item['uid_owner'], self::UNSHARED_FROM_SELF, $item['stime'], $item['file_source'], $item['file_target'])); + if (\OC_DB::isError($result)) { +// \OC_Log::write('OCP\Share', 'Share type '.$shareType.' is not valid for item '.$item, \OC_Log::ERROR); + return false; + } + } + return self::delete($item['item_source'], $item['id'], true); + } + return false; + } + + /** + * @brief Set the target name of the item for the current user + * @param string Item type + * @param string Old item name + * @param string New item name + * @return Returns true on success or false on failure + */ + public static function setTarget($itemType, $oldTarget, $newTarget) { + if ($backend = self::getBackend($itemType)) { + $uidSharedWith = \OC_User::getUser(); + if ($item = self::getItems($itemType, $oldTarget, $uidSharedWith, true, null, false, 1)) { + // Check if this is a group share + if ($item['uid_shared_with'] == null) { + // A new entry needs to be created exclusively for the user + $query = \OC_DB::prepare('INSERT INTO *PREFIX*sharing VALUES(?,?,?,?,?,?,?,?,?,?)'); + if (isset($item['file_target'])) { + $fileTarget = $newTarget; + } else { + $fileTarget = null; + } + $query->execute(array($itemType, $item['item_source'], $newTarget, $uidSharedWith, $item['gid_shared_with'], $item['uid_owner'], $item['permissions'], $item['stime'], $item['file_source'], $fileTarget)); + return true; + } else { + // Check if this item is a file or folder, update the file_target as well if this is the case + if ($itemType == 'file' || $itemType == 'folder') { + $query = \OC_DB::prepare('UPDATE *PREFIX*sharing SET item_target = ?, file_target = REPLACE(file_target, ?, ?) WHERE uid_shared_with = ?'); + $query->execute(array($newTarget, $oldTarget, $newTarget, $uidSharedWith)); + } else { + $query = \OC_DB::prepare('UPDATE *PREFIX*sharing SET item_target = ? WHERE item_type = ? AND item_target = ? AND uid_shared_with = ?'); + $query->execute(array($newTarget, $itemType, $oldTarget, $uidSharedWith)); + } + return true; + } + } + } + return false; + } + + /** + * @brief Set the permissions of an item for a specific user or group + * @param string Item type + * @param string Item + * @param int SHARETYPE_USER | SHARETYPE_GROUP | SHARETYPE_PRIVATE_LINK + * @param string User or group the item is being shared with + * @param + * @return Returns true on success or false on failure + */ + public static function setPermissions($itemType, $item, $shareType, $shareWith, $permissions) { + $uidOwner = \OC_User::getUser(); + switch ($shareType) { + case self::SHARETYPE_USER: + case self::SHARETYPE_PRIVATE_LINK: + $item = self::getItems($itemType, $item, $shareWith, null, $uidOwner, false, 1); + break; + case self::SHARETYPE_GROUP: + $item = self::getItems($itemType, $item, null, $shareWith, $uidOwner, false, 1); + break; + default: + \OC_Log::write('OCP\Share', 'Share type '.$shareType.' is not valid for item '.$item, \OC_Log::ERROR); + return false; + } + if ($item) { + // Check if this item is a reshare and verify that the permissions granted don't exceed the parent shared item + if (isset($item['parent'])) { + $query = \OC_DB::prepare('SELECT permissions FROM *PREFIX*sharing WHERE id = ? LIMIT 1'); + $result = $query->execute(array($item['parent']))->fetchRow(); + if (!isset($result['permissions']) || $permissions > $result['permissions']) { + \OC_Log::write('OCP\Share', '', \OC_Log::ERROR); + return false; + } + } + $query = \OC_DB::prepare('UPDATE *PREFIX*sharing SET permissions = ? WHERE id = ?'); + $query->execute(array($permissions, $item['id'])); + // Check if permissions were reduced + if ($permissions < $item['permissions']) { + // Reduce the permissions for all reshares of this item + $ids = array($item['id']); + $query = \OC_DB::prepare('SELECT id, parent, permissions FROM *PREFIX*sharing WHERE item_source = ?'); + $result = $query->execute(array($item['item_source'])); + while ($item = $result->fetchRow()) { + if (in_array($item['parent'], $ids) && $item['permissions'] > $permissions) { + $ids[] = $item['id']; + } + } + // Remove parent item from array, this item's permissions already got updated + unset($ids[0]); + if (!empty($ids)) { + $query = \OC_DB::prepare('UPDATE *PREFIX*sharing SET permissions = ? WHERE id IN (?)'); + $query->execute(array($permissions, implode(',', $ids))); + } + } + return true; + } + return false; + } + + /** + * @brief Get the backend class for the specified item type + * @param string Item type + * @return Sharing backend object + */ + private static function getBackend($itemType) { + if (isset(self::$backends[$itemType])) { + return self::$backends[$itemType]; + } else if (isset(self::$backendTypes[$itemType]['class'])) { + $class = self::$backendTypes[$itemType]['class']; + if (class_exists($class)) { + self::$backends[$itemType] = new $class; + return self::$backends[$itemType]; + } else { + \OC_Log::write('OCP\Share', 'Sharing backend '.$class.' not found', \OC_Log::ERROR); + return false; + } + } + \OC_Log::write('OCP\Share', 'Sharing backend for '.$itemType.' not found', \OC_Log::ERROR); + return false; + } + + /** + * @brief Get a list of parent item types for the specified item type + * @param string Item type + * @return array + */ + private static function getParentItemTypes($itemType) { + $parents = array($itemType); + foreach (self::$backendTypes as $type => $backend) { + if (in_array($backend->dependsOn, $parents)) { + $parents[] = $type; + } + } + if (!empty($parents)) { + return $parents; + } + return false; + } + + /** + * @brief Get shared items from the database + * @param string Item type + * @param string Item (optional) + * @param string User the item(s) is(are) shared with + * @param string|bool Group the item(s) is(are) shared with + * @param string User that is the owner of shared items (optional) + * @param bool Translate the items back into their original source (optional) + * @param int Number of items to return, -1 to return all matches (optional) + * + * See public functions getItem(s)... for parameter usage + * + */ + private static function getItems($itemType, $item = null, $uidSharedWith = null, $gidSharedWith = null, $uidOwner = null, $translate = true, $limit = -1) { + if ($backend = self::getBackend($itemType)) { + // Check if there are any parent types that include this type of items, e.g. a music album contains songs + if (isset($itemType)) { + if ($parents = self::getParentItemTypes($itemType)) { + $where = "WHERE item_type IN ('".$itemType."'"; + foreach ($parents as $parent) { + $where .= ", '.$parent.'"; + } + $where .= ')'; + } else { + $where = "WHERE item_type = '".$itemType."'"; + } + // TODO exclude items that are inside of folders and got converted i.e. songs, pictures + if ($itemType == 'files') { + + } + } + if (isset($uidSharedWith)) { + if ($gidSharedWith === true) { + $where .= " AND (uid_shared_with = '".$uidSharedWith."'"; + // Include group shares + $groups = \OC_Group::getUserGroups($uidSharedWith); + if (!empty($groups)) { + $groups = "'".implode("','", $groups)."'"; + $where .= " OR gid_shared_with IN (".$groups.") AND (uid_shared_with IS NULL OR uid_shared_with = '".$uidSharedWith."'))"; + } + } else { + $where .= " AND uid_shared_with = '".$uidSharedWith."'"; + } + } else if (isset($gidSharedWith)) { + $where .= " AND gid_shared_with = '".$gidSharedWith."' AND uid_shared_with IS NULL"; + } + if (isset($uidOwner)) { + $where .= " AND uid_owner = '".$uidOwner."'"; + } + if (isset($item)) { + // If looking for own shared items, check item_source else check item_target + if (isset($uidOwner)) { + // Check if this item depends on a file and getSource() returned an array + $source = $backend->getSource($item, $uidOwner); + if (is_array($source)) { + $itemSource = $source['item']; + } else { + $itemSource = $source; + } + $where .= " AND item_source = '".$itemSource."'"; + } else { + $where .= " AND item_target = '".$item."'"; + } + } + if ($limit != -1) { + $where .= ' LIMIT '.$limit; + } + echo $where.'
'; + $query = \OC_DB::prepare('SELECT * FROM *PREFIX*sharing '.$where); + $result = $query->execute(); + $items = array(); + while ($item = $result->fetchRow()) { + // Check if this is part of a group share and the user has a different target from the group share + if ($gidSharedWith === true && isset($item['gid_shared_with']) && isset($item['uid_shared_with'])) { + // Remove the default group share item from the array + + } + if ($translate) { + if ($item['item_type'] != $itemType && $parentBackend = self::getBackend($item['item_type'])) { + if ($itemType == 'files') { + // TODO Don't get children, rather get file sources + } + // TODO add to array parent name + $children = $parentBackend->getChildren($item); + foreach ($children as $child) { + $items[] = $child; + } + } else { + $items[] = $backend->translateItem($item); + } + } + } + if (!empty($items)) { + return $items; + } + } + return false; + } + + /** + * @brief Put shared item into the database + * @param string Item type + * @param string Item + * @param array User(s) the item is being shared with + * @param string|null Group the item is being shared with + * @param string Owner of the item + * @param string + * @param int Parent folder target (optional) + * @return bool + */ + private static function put($itemType, $item, $uidSharedWith, $gidSharedWith, $uidOwner, $permissions, $parentFolder = null) { + // Check file extension for an equivalent item type to convert to + if ($itemType == 'file') { + $extension = strtolower(substr($item, strrpos($item, '.') + 1)); + foreach (self::$backendTypes as $type => $backend) { + if (isset($backend['dependsOn']) && $backend['dependsOn'] == 'file' && isset($backend['supportedFileExtensions']) && in_array($extension, $backend['supportedFileExtensions'])) { + $itemType = $type; + break; + } + } + // Exit if this is being called for a file inside a folder, and no equivalent item type is found + if (isset($parentFolder) && $itemType == 'file') { + return false; + } + } + if ($backend = self::getBackend($itemType)) { + // Check if this is a reshare + if ($checkReshare = self::getItemSharedWith($itemType, $item)) { + // TODO Check if resharing is allowed + $parent = $checkReshare['id']; + $itemSource = $checkReshare['item_source']; + $fileSource = $checkReshare['file_source']; + $fileTarget = $checkReshare['file_target']; + } else { + $parent = null; + $source = $backend->getSource($item, $uidOwner); + if (!$source) { + \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because the sharing backend for '.$itemType.' could not find its source', \OC_Log::ERROR); + return false; + } else if (is_array($source)) { + $itemSource = $source['item']; + $fileSource = \OC_FileCache::getId($source['file']); + } else { + $itemSource = $source; + $fileSource = null; + } + } + $query = \OC_DB::prepare('INSERT INTO *PREFIX*sharing (item_type, item_source, item_target, parent, uid_shared_with, gid_shared_with, uid_owner, permissions, stime, file_source, file_target) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); + // If the item is being shared with a group, add an entry for the group itself + if (isset($gidSharedWith)) { + if (isset($fileSource)) { + if (isset($parentFolder)) { + $groupFileTarget = self::getBackend('file')->generateTarget($source['file'], false); + } else { + $groupFileTarget = self::getBackend('file')->generateTarget($source['file'], false); + } + } else { + $groupFileTarget = null; + } + $groupItemTarget = $backend->generateTarget($item, false); + $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, null, $gidSharedWith, $uidOwner, $permissions, time(), $fileSource, $groupFileTarget)); + // Save this id, any extra rows for this group share will need to reference it + $parent = \OC_DB::insertid('*PREFIX*sharing'); + } + // Need to loop through the users in a group, just in case we need to change the item target or file target for a specific user + // A normal user share also goes through this loop + foreach ($uidSharedWith as $uid) { + $itemTarget = $backend->generateTarget($item, $uid); + if (isset($fileSource)) { + if (isset($parentFolder)) { + // TODO + } else { + $fileTarget = self::getBackend('file')->generateTarget($source['file'], $uid); + } + } else { + $fileTarget = null; + } + if (isset($gidSharedWith)) { + // 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, $uid, $gidSharedWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); + \OC_DB::insertid('*PREFIX*sharing'); + } + } else { + $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $uid, $gidSharedWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); + \OC_DB::insertid('*PREFIX*sharing'); + } + + } + return true; + } + return false; + } + + /** + * @brief Delete all reshares of an item + * @param string + * @param int Id of item to delete + * @param bool + */ + private static function delete($itemSource, $parent, $excludeParent = false) { + $query = \OC_DB::prepare('SELECT id, parent FROM *PREFIX*sharing WHERE item_source = ?'); + $result = $query->execute(array($itemSource)); + $ids = array($parent); + while ($item = $result->fetchRow()) { + if (in_array($item['parent'], $ids)) { + $ids[] = $item['id']; + } + } + if ($excludeParent) { + unset($ids[0]); + } + if (!empty($ids)) { + $query = \OC_DB::prepare('DELETE FROM *PREFIX*sharing WHERE id IN (?)'); + $query->execute(array(implode("','", $ids))); + } + } + + /** + * Hook Listeners + */ + + public static function post_writeFile($arguments) { + // TODO + } + + public static function post_deleteUser($arguments) { + // Delete any items shared with the deleted user + $query = \OC_DB::prepare('DELETE FROM *PREFIX*sharing WHERE uid_shared_with = ?'); + $result = $query->execute(array($arguments['uid'])); + // Delete any items the deleted user shared + $query = \OC_DB::prepare('SELECT id, item_source FROM *PREFIX*sharing WHERE uid_owner = ?'); + $result = $query->execute(array($arguments['uid'])); + while ($item = $result->fetchRow()) { + self::delete($item['item_source'], $item['id']); + } + } + + public static function post_addToGroup($arguments) { + // TODO + } + + public static function post_removeFromGroup($arguments) { + // TODO + } + +} + +/** +* Abstract backend class that apps must extend to share content. +*/ +abstract class Share_Backend { + + public static $dependsOn; + public static $supportedFileExtensions = array(); + + /** + * @brief Get the source of the item to be stored in the database + * @param string Item + * @param string Owner of the item + * @return mixed|array|false Source + * + * Return a + * Return an array if the item is file dependent, the array needs two keys: 'item' and 'file' + * Return false if the item does not exist for the user + * + * The translateItem() function will translate the source returned back into the item + */ + public abstract function getSource($item, $uid); + + /** + * @brief Get a unique name of the item for the specified user + * @param string Item + * @param string|false User the item is being shared with + * @param array|null List of similar item names already existing as shared items + * @return string Target name + * + * This function needs to verify that the user does not already have an item with this name. + * If it does generate a new name e.g. name_# + */ + public abstract function generateTarget($item, $uid, $exclude = null); + + public abstract function transteItem($source); + +} + +abstract class Share_Backend_Parent extends Share_Backend { + + public abstract function getChildren($item); + +} + +?> \ No newline at end of file From c7e0449a75ee2b19b46e40f6a0edcd1308c937e4 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Mon, 18 Jun 2012 15:18:30 -0400 Subject: [PATCH 002/145] Finish parent folder implementation, change recursive delete process --- lib/public/share.php | 119 +++++++++++++++++++++++++++++-------------- 1 file changed, 80 insertions(+), 39 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index 38a23b4385..8db58093ea 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -1,5 +1,4 @@ getId($source['file']); } else { $itemSource = $source; $fileSource = null; } } $query = \OC_DB::prepare('INSERT INTO *PREFIX*sharing (item_type, item_source, item_target, parent, uid_shared_with, gid_shared_with, uid_owner, permissions, stime, file_source, file_target) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); - // If the item is being shared with a group, add an entry for the group itself - if (isset($gidSharedWith)) { + // Share with a group + if (isset($gidSharedWith)) { if (isset($fileSource)) { - if (isset($parentFolder)) { - $groupFileTarget = self::getBackend('file')->generateTarget($source['file'], false); + if ($parentFolder) { + if ($parentFolder === true) { + $groupFileTarget = self::getBackend('file')->generateTarget($source['file'], false); + // Set group default file target for future use + $parentFolders[0]['folder'] = $groupFileTarget; + } else { + // Get group default file target + $groupFileTarget = $parentFolder[0]['folder'].$item; + $parent = $parentFolder[0]['id']; + unset($parentFolder[0]); + // Only loop through users we know have different file target paths + $uidSharedWith = array_keys($parentFolder); + } } else { $groupFileTarget = self::getBackend('file')->generateTarget($source['file'], false); } @@ -541,31 +552,64 @@ class Share { $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, null, $gidSharedWith, $uidOwner, $permissions, time(), $fileSource, $groupFileTarget)); // Save this id, any extra rows for this group share will need to reference it $parent = \OC_DB::insertid('*PREFIX*sharing'); - } - // Need to loop through the users in a group, just in case we need to change the item target or file target for a specific user - // A normal user share also goes through this loop - foreach ($uidSharedWith as $uid) { - $itemTarget = $backend->generateTarget($item, $uid); - if (isset($fileSource)) { - if (isset($parentFolder)) { - // TODO + // Loop through all users of this group in case we need to add an extra row + foreach ($uidSharedWith as $uid) { + $itemTarget = $backend->generateTarget($item, $uid); + if (isset($fileSource)) { + if ($parentFolder) { + if ($parentFolder === true) { + $fileTarget = self::getBackend('file')->generateTarget($source['file'], $uidSharedWith); + if ($fileTarget != $groupFileTarget) { + $parentFolders[$uid]['folder'] = $fileTarget; + } + } else if (isset($parentFolder[$uid])) { + $fileTarget = $parentFolder[$uid]['folder'].$item; + $parent = $parentFolder[$uid]['id']; + } + } else { + $fileTarget = self::getBackend('file')->generateTarget($source['file'], $uidSharedWith); + } } else { - $fileTarget = self::getBackend('file')->generateTarget($source['file'], $uid); + $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)) { + $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $uid, $gidSharedWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); + $id = \OC_DB::insertid('*PREFIX*sharing'); + } + if ($parentFolder === true) { + $parentFolders['id'] = $id; + } + } + if ($parentFolder === true) { + // Return parent folders to preserve file target paths for potential children + return $parentFolders; + } + } else { + // Share with a user + $itemTarget = $backend->generateTarget($item, $uidSharedWith); + if (isset($fileSource)) { + if ($parentFolder) { + if ($parentFolder === true) { + $fileTarget = self::getBackend('file')->generateTarget($source['file'], $uidSharedWith); + $parentFolders['folder'] = $fileTarget; + } else { + $fileTarget = $parentFolder['folder'].$item; + $parent = $parentFolder['id']; + } + } else { + $fileTarget = self::getBackend('file')->generateTarget($source['file'], $uidSharedWith); } } else { $fileTarget = null; } - if (isset($gidSharedWith)) { - // 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, $uid, $gidSharedWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); - \OC_DB::insertid('*PREFIX*sharing'); - } - } else { - $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $uid, $gidSharedWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); - \OC_DB::insertid('*PREFIX*sharing'); + $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $uidSharedWith, null, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); + $id = \OC_DB::insertid('*PREFIX*sharing'); + if ($parentFolder === true) { + $parentFolders['id'] = $id; + // Return parent folder to preserve file target paths for potential children + return $parentFolders; } - } return true; } @@ -578,14 +622,11 @@ class Share { * @param int Id of item to delete * @param bool */ - private static function delete($itemSource, $parent, $excludeParent = false) { - $query = \OC_DB::prepare('SELECT id, parent FROM *PREFIX*sharing WHERE item_source = ?'); - $result = $query->execute(array($itemSource)); + private static function delete($parent, $excludeParent = false) { + $query = \OC_DB::prepare('SELECT id FROM *PREFIX*sharing WHERE parent IN (?)'); $ids = array($parent); - while ($item = $result->fetchRow()) { - if (in_array($item['parent'], $ids)) { - $ids[] = $item['id']; - } + while ($item = $query->execute(array(implode("','", $ids)))->fetchRow()) { + $ids[] = $item['id']; } if ($excludeParent) { unset($ids[0]); @@ -612,7 +653,7 @@ class Share { $query = \OC_DB::prepare('SELECT id, item_source FROM *PREFIX*sharing WHERE uid_owner = ?'); $result = $query->execute(array($arguments['uid'])); while ($item = $result->fetchRow()) { - self::delete($item['item_source'], $item['id']); + self::delete($item['id']); } } From 945565f4206367be53a2c612a2d078a6b539a343 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Tue, 19 Jun 2012 14:19:30 -0400 Subject: [PATCH 003/145] Move ajax and js files to core --- core/ajax/share.php | 42 ++++++++++++++++++++++++ {apps/files_sharing => core}/js/share.js | 12 +++---- 2 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 core/ajax/share.php rename {apps/files_sharing => core}/js/share.js (94%) diff --git a/core/ajax/share.php b/core/ajax/share.php new file mode 100644 index 0000000000..f87c12dbb5 --- /dev/null +++ b/core/ajax/share.php @@ -0,0 +1,42 @@ +. +*/ + +OCP\JSON::checkLoggedIn(); +switch ($_POST['action']) { + case 'share': + $return = OCP\Share::share($_POST['itemType'], $_POST['item'], $_POST['shareType'], $_POST['shareWith'], $_POST['permissions']); + ($return) ? OCP\JSON::success() : OCP\JSON::error(); + break; + case 'unshare': + $return = OCP\Share::unshare($_POST['itemType'], $_POST['item'], $_POST['shareType'], $_POST['shareWith']); + ($return) ? OCP\JSON::success() : OCP\JSON::error(); + break; + case 'setTarget': + $return = OCP\Share::setTarget($_POST['itemType'], $_POST['item'], $_POST['newTarget']); + ($return) ? OCP\JSON::success() : OCP\JSON::error(); + break; + case 'setPermissions': + $return = OCP\Share::setPermissions($_POST['itemType'], $_POST['item'], $_POST['shareType'], $_POST['shareWith'], $_POST['permissions']); + ($return) ? OCP\JSON::success() : OCP\JSON::error(); + break; +} + +?> \ No newline at end of file diff --git a/apps/files_sharing/js/share.js b/core/js/share.js similarity index 94% rename from apps/files_sharing/js/share.js rename to core/js/share.js index 9194d2240a..5f695774ce 100644 --- a/apps/files_sharing/js/share.js +++ b/core/js/share.js @@ -6,7 +6,7 @@ OC.Share={ usersAndGroups:[], loadIcons:function() { // Cache all icons for shared files - $.getJSON(OC.filePath('files_sharing', 'ajax', 'getstatuses.php'), function(result) { + $.getJSON(OC.filePath('core', 'ajax', 'share.php'), function(result) { if (result && result.status === 'success') { $.each(result.data, function(item, hasPrivateLink) { if (hasPrivateLink) { @@ -19,7 +19,7 @@ OC.Share={ }); }, loadItem:function(item) { - $.ajax({type: 'GET', url: OC.filePath('files_sharing', 'ajax', 'getitem.php'), data: { item: item }, async: false, success: function(result) { + $.ajax({type: 'GET', url: OC.filePath('core', 'ajax', 'share.php'), data: { item: item }, async: false, success: function(result) { if (result && result.status === 'success') { var item = result.data; OC.Share.itemUsers = item.users; @@ -29,7 +29,7 @@ OC.Share={ }}); }, share:function(source, uid_shared_with, permissions, callback) { - $.post(OC.filePath('files_sharing', 'ajax', 'share.php'), { sources: source, uid_shared_with: uid_shared_with, permissions: permissions }, function(result) { + $.post(OC.filePath('core', 'ajax', 'share.php'), { sources: source, uid_shared_with: uid_shared_with, permissions: permissions }, function(result) { if (result && result.status === 'success') { if (callback) { callback(result.data); @@ -40,7 +40,7 @@ OC.Share={ }); }, unshare:function(source, uid_shared_with, callback) { - $.post(OC.filePath('files_sharing', 'ajax', 'unshare.php'), { source: source, uid_shared_with: uid_shared_with }, function(result) { + $.post(OC.filePath('core', 'ajax', 'share.php'), { source: source, uid_shared_with: uid_shared_with }, function(result) { if (result && result.status === 'success') { if (callback) { callback(); @@ -50,8 +50,8 @@ OC.Share={ } }); }, - changePermissions:function(source, uid_shared_with, permissions) { - $.post(OC.filePath('files_sharing','ajax','setpermissions.php'), { source: source, uid_shared_with: uid_shared_with, permissions: permissions }, function(result) { + setPermissions:function(source, uid_shared_with, permissions) { + $.post(OC.filePath('core', 'ajax', 'share.php'), { source: source, uid_shared_with: uid_shared_with, permissions: permissions }, function(result) { if (!result || result.status !== 'success') { OC.dialogs.alert('Error', 'Error while changing permissions'); } From bd8769a7c5178e1bb6704e3b2f03d0730b0cb4e5 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Tue, 19 Jun 2012 14:21:44 -0400 Subject: [PATCH 004/145] Fixes for registering and fetching backends --- lib/public/share.php | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index 8db58093ea..6fd3587c2b 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -43,19 +43,19 @@ class Share { /** * @brief Register a sharing backend class that extends OCP\Share_Backend for an item type - * @param string Class * @param string Item type + * @param object Backend class * @param string (optional) Depends on item type * @param array (optional) List of supported file extensions if this item type depends on files * @return Returns true if backend is registered or false if error */ - public static function registerBackend($class, $itemType, $dependsOn = null, $supportedFileExtensions = null) { + public static function registerBackend($itemType, $class, $dependsOn = null, $supportedFileExtensions = null) { if (is_subclass_of($class, 'OCP\Share_Backend')) { - if (!isset(self::$backendTypes[$itemType])) { - self::$backendTypes[$itemType] = array('class' => $class, 'dependsOn' => $dependsOn, 'supportedFileExtensions' => $supportedFileExtensions); + if (!isset(self::$backends[$itemType])) { + self::$backends[$itemType] = array('class' => $class, 'dependsOn' => $dependsOn, 'supportedFileExtensions' => $supportedFileExtensions); return true; } else { - \OC_Log::write('OCP\Share', 'Sharing backend '.$class.' not registered, '.self::$backendTypes[$itemType]['class'].' is already registered for '.$itemType, \OC_Log::WARN); + \OC_Log::write('OCP\Share', 'Sharing backend '.$class.' not registered, '.self::$backends[$itemType]['class'].' is already registered for '.$itemType, \OC_Log::WARN); return false; } } @@ -111,8 +111,10 @@ class Share { public static function share($itemType, $item, $shareType, $shareWith, $permissions) { $uidOwner = \OC_User::getUser(); // Verify share type and sharing conditions are met + // TODO Doesn't handle types switch ($shareType) { case self::SHARETYPE_USER: + \OC_Log::write('OCP\Share', 'share type '.$shareType, \OC_Log::ERROR); if ($shareWith == $uidOwner) { \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because the user '.$shareWith.' is the item owner', \OC_Log::ERROR); return false; @@ -153,6 +155,7 @@ class Share { // TODO don't loop through folder conversion $uidSharedWith = ''; $gidSharedWith = null; + break; default: \OC_Log::write('OCP\Share', 'Share type '.$shareType.' is not valid for '.$item, \OC_Log::ERROR); return false; @@ -218,11 +221,10 @@ class Share { public static function unshareFromSelf($itemType, $itemTarget) { $uidSharedWith = \OC_User::getUser(); if ($item = self::getItems($itemType, $itemTarget, $uidSharedWith, true, null, false, 1)) { - // TODO Check if item is inside a shared folder and was converted + // Check if item is inside a shared folder and was converted if ($item['parent']) { $query = \OC_DB::prepare('SELECT item_type FROM *PREFIX*sharing WHERE id = ? LIMIT 1'); $result = $query->execute(array($item['parent']))->fetchRow(); - // TODO Check other parents if (isset($result['item_type']) && $result['item_type'] = 'folder') { return false; } @@ -337,23 +339,14 @@ class Share { return false; } - /** + /** * @brief Get the backend class for the specified item type * @param string Item type * @return Sharing backend object */ private static function getBackend($itemType) { - if (isset(self::$backends[$itemType])) { - return self::$backends[$itemType]; - } else if (isset(self::$backendTypes[$itemType]['class'])) { - $class = self::$backendTypes[$itemType]['class']; - if (class_exists($class)) { - self::$backends[$itemType] = new $class; - return self::$backends[$itemType]; - } else { - \OC_Log::write('OCP\Share', 'Sharing backend '.$class.' not found', \OC_Log::ERROR); - return false; - } + if (isset(self::$backends[$itemType]['class'])) { + return self::$backends[$itemType]['class']; } \OC_Log::write('OCP\Share', 'Sharing backend for '.$itemType.' not found', \OC_Log::ERROR); return false; From 10986f00dc88dceeb5a052ff7651609d1e9b1465 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Thu, 21 Jun 2012 12:07:11 -0400 Subject: [PATCH 005/145] Use share type and share with in db instead of separate columns for user and group --- lib/public/share.php | 151 +++++++++++++++++++++++++------------------ 1 file changed, 88 insertions(+), 63 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index 6fd3587c2b..18388fec98 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -27,19 +27,20 @@ namespace OCP; */ class Share { - const SHARETYPE_USER = 0; - const SHARETYPE_GROUP = 1; + + const SHARE_TYPE_USER = 0; + const SHARE_TYPE_GROUP = 1; const SHARETYPE_CONTACT = 2; - const SHARETYPE_PRIVATE_LINK = 3; + const SHARETYPE_PRIVATE_LINK = 4; const PERMISSION_READ = 0; const PERMISSION_UPDATE = 1; const PERMISSION_DELETE = 2; const PERMISSION_SHARE = 3; - - private static $backendTypes = array(); + + private static $shareTypeUserAndGroups = -1; + private static $shareTypeGroupUserUnique = 3; private static $backends = array(); - private static $sharedFolder = '/Shared/'; /** * @brief Register a sharing backend class that extends OCP\Share_Backend for an item type @@ -113,7 +114,7 @@ class Share { // Verify share type and sharing conditions are met // TODO Doesn't handle types switch ($shareType) { - case self::SHARETYPE_USER: + case self::SHARE_TYPE_USER: \OC_Log::write('OCP\Share', 'share type '.$shareType, \OC_Log::ERROR); if ($shareWith == $uidOwner) { \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because the user '.$shareWith.' is the item owner', \OC_Log::ERROR); @@ -133,10 +134,8 @@ class Share { \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because this item is already shared with the user '.$shareWith, \OC_Log::ERROR); return false; } - $uidSharedWith = $shareWith; - $gidSharedWith = null; break; - case self::SHARETYPE_GROUP: + case self::SHARE_TYPE_GROUP: if (!\OC_Group::groupExists($shareWith)) { \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because the group '.$shareWith.' does not exist', \OC_Log::ERROR); return false; @@ -148,8 +147,11 @@ class Share { \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because this item is already shared with the group '.$shareWith, \OC_Log::ERROR); return false; } - $uidSharedWith = array_diff(\OC_Group::usersInGroup($shareWith), array($uidOwner)); - $gidSharedWith = $shareWith; + // Convert share with into an array with the keys group and users + $group = $shareWith; + $shareWith = array(); + $shareWith['group'] = $group; + $shareWith['users'] = array_diff(\OC_Group::usersInGroup($shareWith), array($uidOwner)); break; case self::SHARETYPE_PRIVATE_LINK: // TODO don't loop through folder conversion @@ -162,7 +164,7 @@ class Share { } // If the item is a folder, scan through the folder looking for equivalent item types if ($itemType == 'folder') { - $parentFolder = self::put('folder', $item, $uidSharedWith, $gidSharedWith, $uidOwner, $permissions, true); + $parentFolder = self::put('folder', $item, $shareType, $shareWith, $uidOwner, $permissions, true); if ($parentFolder && $files = \OC_Files::getDirectoryContent($item)) { for ($i = 0; $i < count($files); $i++) { $name = substr($files[$i]['name'], strpos($files[$i]['name'], $item) - strlen($item)); @@ -171,7 +173,7 @@ class Share { array_push($files, $children); } else { // Pass on to put() to check if this item should be converted, the item won't be inserted into the database unless it can be converted - self::put('file', $name, $uidSharedWith, $gidSharedWith, $uidOwner, $permissions, $parentFolder); + self::put('file', $name, $shareType, $shareWith, $uidOwner, $permissions, $parentFolder); } } return $return; @@ -179,7 +181,7 @@ class Share { return false; } else { // Put the item into the database - return self::put($itemType, $item, $uidSharedWith, $gidSharedWith, $uidOwner, $permissions); + return self::put($itemType, $item, $shareType, $shareWith, $uidOwner, $permissions); } } @@ -194,11 +196,11 @@ class Share { public static function unshare($itemType, $item, $shareType, $shareWith) { $uidOwner = \OC_User::getUser(); switch ($shareType) { - case self::SHARETYPE_USER: + case self::SHARE_TYPE_USER: case self::SHARETYPE_PRIVATE_LINK: $item = self::getItems($itemType, $item, $shareWith, null, $uidOwner, false, 1); break; - case self::SHARETYPE_GROUP: + case self::SHARE_TYPE_GROUP: $item = self::getItems($itemType, $item, null, $shareWith, $uidOwner, false, 1); break; default: @@ -225,7 +227,7 @@ class Share { if ($item['parent']) { $query = \OC_DB::prepare('SELECT item_type FROM *PREFIX*sharing WHERE id = ? LIMIT 1'); $result = $query->execute(array($item['parent']))->fetchRow(); - if (isset($result['item_type']) && $result['item_type'] = 'folder') { + if (isset($result['item_type']) && $result['item_type'] == 'folder') { return false; } } @@ -293,11 +295,11 @@ class Share { public static function setPermissions($itemType, $item, $shareType, $shareWith, $permissions) { $uidOwner = \OC_User::getUser(); switch ($shareType) { - case self::SHARETYPE_USER: + case self::SHARE_TYPE_USER: case self::SHARETYPE_PRIVATE_LINK: $item = self::getItems($itemType, $item, $shareWith, null, $uidOwner, false, 1); break; - case self::SHARETYPE_GROUP: + case self::SHARE_TYPE_GROUP: $item = self::getItems($itemType, $item, null, $shareWith, $uidOwner, false, 1); break; default: @@ -383,7 +385,7 @@ class Share { * See public functions getItem(s)... for parameter usage * */ - private static function getItems($itemType, $item = null, $uidSharedWith = null, $gidSharedWith = null, $uidOwner = null, $translate = true, $limit = -1) { + private static function getItems($itemType, $item = null, $shareType = null, $shareWith = null, $uidOwner = null, $format = true, $checkOnly = false, $limit = -1) { if ($backend = self::getBackend($itemType)) { // Check if there are any parent types that include this type of items, e.g. a music album contains songs if (isset($itemType)) { @@ -401,20 +403,17 @@ class Share { } } - if (isset($uidSharedWith)) { - if ($gidSharedWith === true) { - $where .= " AND (uid_shared_with = '".$uidSharedWith."'"; - // Include group shares - $groups = \OC_Group::getUserGroups($uidSharedWith); - if (!empty($groups)) { - $groups = "'".implode("','", $groups)."'"; - $where .= " OR gid_shared_with IN (".$groups.") AND (uid_shared_with IS NULL OR uid_shared_with = '".$uidSharedWith."'))"; - } + if (isset($shareType) && isset($shareWith)) { + // Include all user and group items + if ($shareType == self::$shareTypeUserAndGroups) { + $where .= " AND share_type IN ('".self::SHARE_TYPE_USER."','".self::SHARE_TYPE_GROUP."','".self::$shareTypeGroupUserUnique."')"; + $groups = \OC_Group::getUserGroups($shareWith); + $userAndGroups = array_merge(array($shareWith), $groups); + $where .= " AND share_with IN ('".implode("','", $userAndGroups)."')"; + } else { - $where .= " AND uid_shared_with = '".$uidSharedWith."'"; + $where .= " AND share_type = '".$shareType."' AND share_with = '".$shareWith."'"; } - } else if (isset($gidSharedWith)) { - $where .= " AND gid_shared_with = '".$gidSharedWith."' AND uid_shared_with IS NULL"; } if (isset($uidOwner)) { $where .= " AND uid_owner = '".$uidOwner."'"; @@ -431,39 +430,45 @@ class Share { } $where .= " AND item_source = '".$itemSource."'"; } else { - $where .= " AND item_target = '".$item."'"; + if ($itemType == 'file' && substr($item, -1) == '/') { + // Special case to select only the shared files inside the folder + $where .= " AND file_target LIKE '".$item."%/'"; + } else { + $where .= " AND item_target = '".$item."'"; + } } } if ($limit != -1) { $where .= ' LIMIT '.$limit; } - echo $where.'
'; $query = \OC_DB::prepare('SELECT * FROM *PREFIX*sharing '.$where); $result = $query->execute(); - $items = array(); - while ($item = $result->fetchRow()) { - // Check if this is part of a group share and the user has a different target from the group share - if ($gidSharedWith === true && isset($item['gid_shared_with']) && isset($item['uid_shared_with'])) { - // Remove the default group share item from the array + if (!$checkOnly) { + $items = array(); + while ($item = $result->fetchRow()) { + // Filter out duplicate group shares for users with unique targets + if ($item['share_type'] == self::$shareTypeGroupUserUnique) { - } - if ($translate) { - if ($item['item_type'] != $itemType && $parentBackend = self::getBackend($item['item_type'])) { - if ($itemType == 'files') { - // TODO Don't get children, rather get file sources - } - // TODO add to array parent name - $children = $parentBackend->getChildren($item); - foreach ($children as $child) { - $items[] = $child; - } + } + $sources[] = $item['item_source']; + if ($format) { + $shareInfo[$item['item_source']] = array('item_target' => $item['item_target'], 'permissions' => $item['permissions'], 'stime' => $item['stime']); } else { - $items[] = $backend->translateItem($item); + $shareInfo[$item['item_source']][$item['id']] = array('item_target' => $item['item_target'], 'permissions' => $item['permissions'], 'stime' => $item['stime']); } } - } - if (!empty($items)) { - return $items; + if ($format) { + return $backend->formatItems($sources, $shareInfo); + } else { + // TODO wrap items back into share type, share with, permissions + $items = $backend->getItems($sources); + + } + if (!empty($items)) { + return $items; + } + } else { + return $result->fetchAll(); } } return false; @@ -480,7 +485,7 @@ class Share { * @param bool|array Parent folder target (optional) * @return bool */ - private static function put($itemType, $item, $uidSharedWith, $gidSharedWith, $uidOwner, $permissions, $parentFolder = false) { + private static function put($itemType, $item, $shareType, $shareWith, $uidOwner, $permissions, $parentFolder = false) { // Check file extension for an equivalent item type to convert to if ($itemType == 'file') { $extension = strtolower(substr($item, strrpos($item, '.') + 1)); @@ -520,7 +525,7 @@ class Share { } $query = \OC_DB::prepare('INSERT INTO *PREFIX*sharing (item_type, item_source, item_target, parent, uid_shared_with, gid_shared_with, uid_owner, permissions, stime, file_source, file_target) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); // Share with a group - if (isset($gidSharedWith)) { + if ($shareType == self::SHARE_TYPE_GROUP) { if (isset($fileSource)) { if ($parentFolder) { if ($parentFolder === true) { @@ -542,11 +547,11 @@ class Share { $groupFileTarget = null; } $groupItemTarget = $backend->generateTarget($item, false); - $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, null, $gidSharedWith, $uidOwner, $permissions, time(), $fileSource, $groupFileTarget)); + $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, $shareType, $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget)); // Save this id, any extra rows for this group share will need to reference it $parent = \OC_DB::insertid('*PREFIX*sharing'); // Loop through all users of this group in case we need to add an extra row - foreach ($uidSharedWith as $uid) { + foreach ($shareWith['users'] as $uid) { $itemTarget = $backend->generateTarget($item, $uid); if (isset($fileSource)) { if ($parentFolder) { @@ -567,7 +572,7 @@ class Share { } // 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, $uid, $gidSharedWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); + $query->execute(array($itemType, $itemSource, $itemTarget, $parent, self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); $id = \OC_DB::insertid('*PREFIX*sharing'); } if ($parentFolder === true) { @@ -579,7 +584,6 @@ class Share { return $parentFolders; } } else { - // Share with a user $itemTarget = $backend->generateTarget($item, $uidSharedWith); if (isset($fileSource)) { if ($parentFolder) { @@ -596,7 +600,7 @@ class Share { } else { $fileTarget = null; } - $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $uidSharedWith, null, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); + $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); $id = \OC_DB::insertid('*PREFIX*sharing'); if ($parentFolder === true) { $parentFolders['id'] = $id; @@ -668,6 +672,8 @@ abstract class Share_Backend { public static $dependsOn; public static $supportedFileExtensions = array(); + + /** * @brief Get the source of the item to be stored in the database * @param string Item @@ -682,6 +688,8 @@ abstract class Share_Backend { */ public abstract function getSource($item, $uid); + + /** * @brief Get a unique name of the item for the specified user * @param string Item @@ -694,7 +702,24 @@ abstract class Share_Backend { */ public abstract function generateTarget($item, $uid, $exclude = null); - public abstract function transteItem($source); + + + /** + * @brief + * @param array + * @return + */ + public abstract function getItems($sources); + + + + /** + * @brief + * @param array + * @param array + * @return + */ + public abstract function formatItems($sources, $shareInfo); } From 71350bc61879ab2e532d5f55c058b4fba9341656 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Fri, 22 Jun 2012 17:43:04 -0400 Subject: [PATCH 006/145] I'm having trouble making up my mind... translateItem -> getItems() -> formatItems(). It may change again. Preparing shared storage for new api. --- apps/files_sharing/sharedstorage.php | 90 +++++++++++---------- lib/files.php | 5 ++ lib/public/share.php | 115 +++++++++++++-------------- 3 files changed, 108 insertions(+), 102 deletions(-) diff --git a/apps/files_sharing/sharedstorage.php b/apps/files_sharing/sharedstorage.php index fed1b834fa..21aa2f23b9 100644 --- a/apps/files_sharing/sharedstorage.php +++ b/apps/files_sharing/sharedstorage.php @@ -3,7 +3,7 @@ * ownCloud * * @author Michael Gapczynski - * @copyright 2011 Michael Gapczynski GapczynskiM@gmail.com + * @copyright 2011 Michael Gapczynski mtgap@owncloud.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -20,43 +20,50 @@ * */ -require_once( 'lib_share.php' ); - /** * Convert target path to source path and pass the function call to the correct storage provider */ class OC_Filestorage_Shared extends OC_Filestorage_Common { - private $datadir; + private $sharedFolder; private $sourcePaths = array(); public function __construct($arguments) { - $this->datadir = $arguments['datadir']; - $this->datadir .= "/"; + $this->sharedFolder = $arguments['sharedFolder']; } - - public function getInternalPath($path) { + + public function getSourcePath($target) { + $target = $this->sharedFolder.$target; + if (isset($this->sourcePaths[$target])) { + return $this->sourcePaths[$target]; + } else { + if (dirname($target) != $this->sharedFolder) { + $pos = strlen($this->sharedFolder); + // Get shared folder name + $itemTarget = substr($target, $pos, strpos($target, '/', $pos)); + } else { + $itemTarget = $target; + } + $sourcePath = OCP\Share::getItemSharedWith('file', $itemTarget, OC_Share_Backend_File::FORMAT_SOURCE_PATH); + if ($sourcePath) { + $this->sourcePaths[$target] = $sourcePath; + return $sourcePath; + } + return false; + } + } + + private function getInternalPath($path) { $mountPoint = OC_Filesystem::getMountPoint($path); $internalPath = substr($path, strlen($mountPoint)); return $internalPath; } - public function getSource($target) { - $target = $this->datadir.$target; - if (array_key_exists($target, $this->sourcePaths)) { - return $this->sourcePaths[$target]; - } else { - $source = OC_Share::getSource($target); - $this->sourcePaths[$target] = $source; - return $source; - } - } - public function mkdir($path) { if ($path == "" || $path == "/" || !$this->is_writable($path)) { return false; } else { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->mkdir($this->getInternalPath($source)); @@ -73,6 +80,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { public function opendir($path) { if ($path == "" || $path == "/") { $path = $this->datadir.$path; + // TODO $sharedItems = OC_Share::getItemsInFolder($path); $files = array(); foreach ($sharedItems as $item) { @@ -84,7 +92,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { OC_FakeDirStream::$dirs['shared']=$files; return opendir('fakedir://shared'); } else { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); $dh = $storage->opendir($this->getInternalPath($source)); @@ -143,7 +151,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($path == "" || $path == "/") { return true; } else { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->is_dir($this->getInternalPath($source)); @@ -152,7 +160,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } public function is_file($path) { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->is_file($this->getInternalPath($source)); @@ -167,7 +175,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { $stat["ctime"] = $this->filectime($path); return $stat; } else { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->stat($this->getInternalPath($source)); @@ -179,7 +187,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($path == "" || $path == "/") { return "dir"; } else { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->filetype($this->getInternalPath($source)); @@ -192,7 +200,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($path == "" || $path == "/" || $this->is_dir($path)) { return $this->getFolderSize($path); } else { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->filesize($this->getInternalPath($source)); @@ -267,7 +275,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($path == "" || $path == "/") { return true; } else { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->file_exists($this->getInternalPath($source)); @@ -288,7 +296,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } return $ctime; } else { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->filectime($this->getInternalPath($source)); @@ -309,7 +317,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } return $mtime; } else { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->filemtime($this->getInternalPath($source)); @@ -318,7 +326,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } public function file_get_contents($path) { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $info = array( 'target' => $this->datadir.$path, @@ -332,7 +340,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { public function file_put_contents($path, $data) { if ($this->is_writable($path)) { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $info = array( 'target' => $this->datadir.$path, @@ -381,7 +389,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { return false; // Check if both paths have write permission } else if ($this->is_writable($path1) && $this->is_writable($path2)) { - $oldSource = $this->getSource($path1); + $oldSource = $this->getSourcePath($path1); $newSource = $folders['source'].substr($newTarget, strlen($folders['target'])); if ($oldSource) { $storage = OC_Filesystem::getStorage($oldSource); @@ -424,7 +432,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } public function fopen($path, $mode) { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $info = array( 'target' => $this->datadir.$path, @@ -438,7 +446,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } public function toTmpFile($path) { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->toTmpFile($this->getInternalPath($source)); @@ -447,7 +455,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { public function fromTmpFile($tmpFile, $path) { if ($this->is_writable($path)) { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); $result = $storage->fromTmpFile($tmpFile, $this->getInternalPath($source)); @@ -465,7 +473,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($path == "" || $path == "/") { return 'httpd/unix-directory'; } - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->getMimeType($this->getInternalPath($source)); @@ -473,7 +481,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } public function hash($type, $path, $raw) { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->hash($type, $this->getInternalPath($source), $raw); @@ -481,7 +489,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } public function free_space($path) { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->free_space($this->getInternalPath($source)); @@ -510,14 +518,14 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } public function getLocalFile($path) { - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->getLocalFile($this->getInternalPath($source)); } } public function touch($path, $mtime=null){ - $source = $this->getSource($path); + $source = $this->getSourcePath($path); if ($source) { $storage = OC_Filesystem::getStorage($source); return $storage->touch($this->getInternalPath($source),$time); @@ -526,7 +534,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { public static function setup($options) { $user_dir = $options['user_dir']; - OC_Filesystem::mount('OC_Filestorage_Shared', array('datadir' => $user_dir.'/Shared'), $user_dir.'/Shared/'); + OC_Filesystem::mount('OC_Filestorage_Shared', array('sharedFolder' => $user_dir.'/Shared'), $user_dir.'/Shared/'); } /** diff --git a/lib/files.php b/lib/files.php index 469c3a15b8..2feae20afe 100644 --- a/lib/files.php +++ b/lib/files.php @@ -34,6 +34,11 @@ class OC_Files { */ public static function getDirectoryContent($directory, $mimetype_filter = ''){ $files=OC_FileCache::getFolderContent($directory, false, $mimetype_filter); + if ($directory == '') { + $files = array_merge($files, array()); + } else if (substr($directory, 7) == '/Shared') { + $files = array_merge($files, OCP\Share::getItemsSharedWith('file', $directory, OC_Share_Backend_File::FORMAT_FILE_APP)); + } foreach($files as &$file){ $file['directory']=$directory; $file['type']=($file['mimetype']=='httpd/unix-directory')?'dir':'file'; diff --git a/lib/public/share.php b/lib/public/share.php index 18388fec98..2ba3187dff 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -31,13 +31,15 @@ class Share { const SHARE_TYPE_USER = 0; const SHARE_TYPE_GROUP = 1; const SHARETYPE_CONTACT = 2; - const SHARETYPE_PRIVATE_LINK = 4; + const SHARETYPE_PRIVATE_LINK = 4; const PERMISSION_READ = 0; const PERMISSION_UPDATE = 1; const PERMISSION_DELETE = 2; const PERMISSION_SHARE = 3; + const FORMAT_NONE = -1; + private static $shareTypeUserAndGroups = -1; private static $shareTypeGroupUserUnique = 3; private static $backends = array(); @@ -67,37 +69,45 @@ class Share { /** * @brief Get the items of item type shared with the current user * @param string Item type - * @return + * @param int Format (optional) Format type must be defined by the backend + * @param int Number of items to return (optional) Returns all by default + * @return Return depends on format */ - public static function getItemsSharedWith($itemType) { - return self::getItems($itemType, null, \OC_User::getUser(), true, null, true); + public static function getItemsSharedWith($itemType, $format = self::FORMAT_NONE, $limit = -1) { + return self::getItems($itemType, null, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format, $limit); } /** * @brief Get the item of item type shared with the current user * @param string Item type - * @return + * @param string Item target + * @param int Format (optional) Format type must be defined by the backend + * @return Return depends on format */ - public static function getItemSharedWith($itemType, $item) { - return self::getItems($itemType, $item, \OC_User::getUser(), true, null, true, 1); + public static function getItemSharedWith($itemType, $itemTarget, $format = self::FORMAT_NONE) { + return self::getItems($itemType, $itemTarget, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format, 1); } /** * @brief Get the shared items of item type owned by the current user * @param string Item type - * @return The + * @param int Format (optional) Format type must be defined by the backend + * @param int Number of items to return (optional) Returns all by default + * @return Return depends on format */ - public static function getItemsOwned($itemType) { - return self::getItems($itemType, null, null, null, \OC_User::getUser(), true); + public static function getItemsOwned($itemType, $format = self::FORMAT_NONE, $limit = -1) { + return self::getItems($itemType, null, null, null, \OC_User::getUser(), $format, $limit); } /** * @brief Get the shared item of item type owned by the current user * @param string Item type - * @return The + * @param string Item + * @param int Format (optional) Format type must be defined by the backend + * @return Return depends on format */ - public static function getItemOwned($itemType, $item) { - return self::getItems($itemType, $item, null, null, \OC_User::getUser(), true, 1); + public static function getItemOwned($itemType, $item, $format = self::FORMAT_NONE) { + return self::getItems($itemType, $item, null, null, \OC_User::getUser(), $format, 1); } /** @@ -130,7 +140,7 @@ class Share { return false; } } - if (self::getItems($itemType, $item, $shareWith, true, $uidOwner, false, 1)) { + if (self::getItems($itemType, $item, self::SHARE_TYPE_USER, $shareWith, $uidOwner, self::FORMAT_NONE, 1)) { \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because this item is already shared with the user '.$shareWith, \OC_Log::ERROR); return false; } @@ -143,7 +153,7 @@ class Share { \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because '.$uidOwner.' is not a member of the group '.$shareWith, \OC_Log::ERROR); return false; } - if (self::getItems($itemType, $item, null, $shareWith, $uidOwner, false, 1)) { + if (self::getItems($itemType, $item, self::SHARE_TYPE_GROUP, $shareWith, $uidOwner, self::FORMAT_NONE, 1)) { \OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because this item is already shared with the group '.$shareWith, \OC_Log::ERROR); return false; } @@ -375,7 +385,7 @@ class Share { /** * @brief Get shared items from the database * @param string Item type - * @param string Item (optional) + * @param string Item or item target (optional) * @param string User the item(s) is(are) shared with * @param string|bool Group the item(s) is(are) shared with * @param string User that is the owner of shared items (optional) @@ -385,7 +395,7 @@ class Share { * See public functions getItem(s)... for parameter usage * */ - private static function getItems($itemType, $item = null, $shareType = null, $shareWith = null, $uidOwner = null, $format = true, $checkOnly = false, $limit = -1) { + private static function getItems($itemType, $item = null, $shareType = null, $shareWith = null, $uidOwner = null, $format = self::FORMAT_NONE, $limit = -1) { if ($backend = self::getBackend($itemType)) { // Check if there are any parent types that include this type of items, e.g. a music album contains songs if (isset($itemType)) { @@ -410,7 +420,6 @@ class Share { $groups = \OC_Group::getUserGroups($shareWith); $userAndGroups = array_merge(array($shareWith), $groups); $where .= " AND share_with IN ('".implode("','", $userAndGroups)."')"; - } else { $where .= " AND share_type = '".$shareType."' AND share_with = '".$shareWith."'"; } @@ -443,32 +452,24 @@ class Share { } $query = \OC_DB::prepare('SELECT * FROM *PREFIX*sharing '.$where); $result = $query->execute(); - if (!$checkOnly) { - $items = array(); - while ($item = $result->fetchRow()) { - // Filter out duplicate group shares for users with unique targets - if ($item['share_type'] == self::$shareTypeGroupUserUnique) { - - } - $sources[] = $item['item_source']; - if ($format) { - $shareInfo[$item['item_source']] = array('item_target' => $item['item_target'], 'permissions' => $item['permissions'], 'stime' => $item['stime']); - } else { - $shareInfo[$item['item_source']][$item['id']] = array('item_target' => $item['item_target'], 'permissions' => $item['permissions'], 'stime' => $item['stime']); - } - } - if ($format) { - return $backend->formatItems($sources, $shareInfo); - } else { - // TODO wrap items back into share type, share with, permissions - $items = $backend->getItems($sources); + $items = array(); + while ($item = $result->fetchRow()) { + // TODO Filter out duplicate group shares for users with unique targets + if ($item['share_type'] == self::$shareTypeGroupUserUnique) { + // Group shares should already be in items array } - if (!empty($items)) { - return $items; + // TODO Add in parent item types children? + if ($parents && in_array($item['item_type'], $parents)) { + $children[] = $item; } +// $items[] = array($item['item_source'] => $item['id']; + $items[$item['item']][$item['id']] = array('item_target' => $item['item_target'], 'permissions' => $item['permissions'], 'stime' => $item['stime']); + } + if ($format == self::FORMAT_NONE) { + return $items; } else { - return $result->fetchAll(); + return $backend->formatItems($items, $format); } } return false; @@ -523,7 +524,7 @@ class Share { $fileSource = null; } } - $query = \OC_DB::prepare('INSERT INTO *PREFIX*sharing (item_type, item_source, item_target, parent, uid_shared_with, gid_shared_with, uid_owner, permissions, stime, file_source, file_target) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); + $query = \OC_DB::prepare('INSERT INTO *PREFIX*sharing (item_type, item, item_source, item_target, parent, uid_shared_with, gid_shared_with, uid_owner, permissions, stime, file_source, file_target) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); // Share with a group if ($shareType == self::SHARE_TYPE_GROUP) { if (isset($fileSource)) { @@ -547,7 +548,7 @@ class Share { $groupFileTarget = null; } $groupItemTarget = $backend->generateTarget($item, false); - $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, $shareType, $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget)); + $query->execute(array($itemType, $item, $itemSource, $groupItemTarget, $parent, $shareType, $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget)); // Save this id, any extra rows for this group share will need to reference it $parent = \OC_DB::insertid('*PREFIX*sharing'); // Loop through all users of this group in case we need to add an extra row @@ -572,7 +573,7 @@ class Share { } // 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, self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); + $query->execute(array($itemType, $item, $itemSource, $itemTarget, $parent, self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); $id = \OC_DB::insertid('*PREFIX*sharing'); } if ($parentFolder === true) { @@ -600,7 +601,7 @@ class Share { } else { $fileTarget = null; } - $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); + $query->execute(array($itemType, $item, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); $id = \OC_DB::insertid('*PREFIX*sharing'); if ($parentFolder === true) { $parentFolders['id'] = $id; @@ -638,10 +639,6 @@ class Share { * Hook Listeners */ - public static function post_writeFile($arguments) { - // TODO - } - public static function post_deleteUser($arguments) { // Delete any items shared with the deleted user $query = \OC_DB::prepare('DELETE FROM *PREFIX*sharing WHERE uid_shared_with = ?'); @@ -705,22 +702,18 @@ abstract class Share_Backend { /** - * @brief - * @param array - * @return + * @brief Converts the shared item sources back into the item in the specified format + * @param array Sources of shared items + * @param int Format + * @return ? + * + * The items array is formatted with the sources as the keys to an array with the following keys: item_target, permissions, stime + * This function allows the backend to control the output of shared items with custom formats. + * It is only called through calls to the public getItem(s)SharedWith functions. */ - public abstract function getItems($sources); + public abstract function formatItems($items, $format); - - /** - * @brief - * @param array - * @param array - * @return - */ - public abstract function formatItems($sources, $shareInfo); - } abstract class Share_Backend_Parent extends Share_Backend { From 5f1aa1b92e7b8e18e38718b8da6c79eda0840ac1 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Fri, 22 Jun 2012 18:00:10 -0400 Subject: [PATCH 007/145] Fix additional getItems calls due to parameter change --- lib/public/share.php | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index 2ba3187dff..ec371ebf98 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -122,7 +122,6 @@ class Share { public static function share($itemType, $item, $shareType, $shareWith, $permissions) { $uidOwner = \OC_User::getUser(); // Verify share type and sharing conditions are met - // TODO Doesn't handle types switch ($shareType) { case self::SHARE_TYPE_USER: \OC_Log::write('OCP\Share', 'share type '.$shareType, \OC_Log::ERROR); @@ -168,6 +167,7 @@ class Share { $uidSharedWith = ''; $gidSharedWith = null; break; + // Future share types need to include their own conditions default: \OC_Log::write('OCP\Share', 'Share type '.$shareType.' is not valid for '.$item, \OC_Log::ERROR); return false; @@ -204,20 +204,7 @@ class Share { * @return Returns true on success or false on failure */ public static function unshare($itemType, $item, $shareType, $shareWith) { - $uidOwner = \OC_User::getUser(); - switch ($shareType) { - case self::SHARE_TYPE_USER: - case self::SHARETYPE_PRIVATE_LINK: - $item = self::getItems($itemType, $item, $shareWith, null, $uidOwner, false, 1); - break; - case self::SHARE_TYPE_GROUP: - $item = self::getItems($itemType, $item, null, $shareWith, $uidOwner, false, 1); - break; - default: - \OC_Log::write('OCP\Share', 'Share type '.$shareType.' is not valid for item '.$item, \OC_Log::ERROR); - return false; - } - if ($item) { + if ($item = self::getItems($itemType, $item, $shareType, $shareWith, \OC_User::getUser(), self::FORMAT_NONE, 1)) { self::delete($item['id']); return true; } @@ -265,7 +252,8 @@ class Share { public static function setTarget($itemType, $oldTarget, $newTarget) { if ($backend = self::getBackend($itemType)) { $uidSharedWith = \OC_User::getUser(); - if ($item = self::getItems($itemType, $oldTarget, $uidSharedWith, true, null, false, 1)) { + // TODO Check permissions for setting target? + if ($item = self::getItems($itemType, $oldTarget, self::SHARE_TYPE_USER, $uidSharedWith, null, self::FORMAT_NONE, 1)) { // Check if this is a group share if ($item['uid_shared_with'] == null) { // A new entry needs to be created exclusively for the user @@ -303,20 +291,7 @@ class Share { * @return Returns true on success or false on failure */ public static function setPermissions($itemType, $item, $shareType, $shareWith, $permissions) { - $uidOwner = \OC_User::getUser(); - switch ($shareType) { - case self::SHARE_TYPE_USER: - case self::SHARETYPE_PRIVATE_LINK: - $item = self::getItems($itemType, $item, $shareWith, null, $uidOwner, false, 1); - break; - case self::SHARE_TYPE_GROUP: - $item = self::getItems($itemType, $item, null, $shareWith, $uidOwner, false, 1); - break; - default: - \OC_Log::write('OCP\Share', 'Share type '.$shareType.' is not valid for item '.$item, \OC_Log::ERROR); - return false; - } - if ($item) { + if ($item = self::getItems($itemType, $item, $shareType, $shareWith, \OC_User::getUser(), self::FORMAT_NONE, 1)) { // Check if this item is a reshare and verify that the permissions granted don't exceed the parent shared item if (isset($item['parent'])) { $query = \OC_DB::prepare('SELECT permissions FROM *PREFIX*sharing WHERE id = ? LIMIT 1'); From 819811461535cceb8208651f6a131cbb97efd169 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 24 Jun 2012 16:42:51 -0400 Subject: [PATCH 008/145] Some more changes to getItems() and fixes in shared storage --- apps/files_sharing/sharedstorage.php | 15 +++++++++---- lib/public/share.php | 32 +++++++++++++++++++--------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/apps/files_sharing/sharedstorage.php b/apps/files_sharing/sharedstorage.php index 21aa2f23b9..11a5d39f01 100644 --- a/apps/files_sharing/sharedstorage.php +++ b/apps/files_sharing/sharedstorage.php @@ -38,16 +38,23 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { return $this->sourcePaths[$target]; } else { if (dirname($target) != $this->sharedFolder) { - $pos = strlen($this->sharedFolder); + $len = strlen($this->sharedFolder); + $pos = strpos($target, '/', $len); // Get shared folder name - $itemTarget = substr($target, $pos, strpos($target, '/', $pos)); + $itemTarget = substr($target, $len, $pos); + $insideFolder = true; } else { $itemTarget = $target; + $insideFolder = false; } $sourcePath = OCP\Share::getItemSharedWith('file', $itemTarget, OC_Share_Backend_File::FORMAT_SOURCE_PATH); if ($sourcePath) { - $this->sourcePaths[$target] = $sourcePath; - return $sourcePath; + if ($insideFolder) { + $this->sourcePaths[$target] = $sourcePath.substr($target, $pos); + } else { + $this->sourcePaths[$target] = $sourcePath; + } + return $this->sourcePaths[$target]; } return false; } diff --git a/lib/public/share.php b/lib/public/share.php index ec371ebf98..f4a11a170a 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -375,11 +375,11 @@ class Share { // Check if there are any parent types that include this type of items, e.g. a music album contains songs if (isset($itemType)) { if ($parents = self::getParentItemTypes($itemType)) { - $where = "WHERE item_type IN ('".$itemType."'"; - foreach ($parents as $parent) { - $where .= ", '.$parent.'"; - } - $where .= ')'; + $where = "WHERE item_type IN ('".$itemType."'"; + foreach ($parents as $parent) { + $where .= ", '.$parent.'"; + } + $where .= ')'; } else { $where = "WHERE item_type = '".$itemType."'"; } @@ -401,6 +401,10 @@ class Share { } if (isset($uidOwner)) { $where .= " AND uid_owner = '".$uidOwner."'"; + if (!isset($shareType)) { + // Prevent unique user targets for group shares from being selected + $where .= " AND share_type != '".self::$shareTypeGroupUserUnique."'"; + } } if (isset($item)) { // If looking for own shared items, check item_source else check item_target @@ -423,25 +427,33 @@ class Share { } } if ($limit != -1) { + if ($limit == 1 && $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 id DESC'; + } $where .= ' LIMIT '.$limit; } $query = \OC_DB::prepare('SELECT * FROM *PREFIX*sharing '.$where); $result = $query->execute(); $items = array(); while ($item = $result->fetchRow()) { - // TODO Filter out duplicate group shares for users with unique targets + // Filter out duplicate group shares for users with unique targets if ($item['share_type'] == self::$shareTypeGroupUserUnique) { - // Group shares should already be in items array - + // Group shares should already be in the items array + unset($items[$item['parent']]); } // TODO Add in parent item types children? if ($parents && in_array($item['item_type'], $parents)) { $children[] = $item; } -// $items[] = array($item['item_source'] => $item['id']; - $items[$item['item']][$item['id']] = array('item_target' => $item['item_target'], 'permissions' => $item['permissions'], 'stime' => $item['stime']); + $items[$item['id']] = $item; } if ($format == self::FORMAT_NONE) { + if ($limit == 1) { + // Return just the item instead of 2-dimensional array + return $items[key($items)]; + } return $items; } else { return $backend->formatItems($items, $format); From bc68f14c4baba0438bf019af144564eec6624760 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 24 Jun 2012 19:16:50 -0400 Subject: [PATCH 009/145] Prepare drop down UI for share API --- apps/files_sharing/appinfo/app.php | 2 +- core/ajax/share.php | 51 ++++++++---- core/js/share.js | 123 +++++++++++------------------ lib/public/share.php | 30 +++++-- 4 files changed, 107 insertions(+), 99 deletions(-) diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index bbb753d5e6..d51a4f5164 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -17,7 +17,7 @@ OCP\Util::connectHook('OC_User', 'post_removeFromGroup', 'OC_Share', 'removeFrom $dir = isset($_GET['dir']) ? $_GET['dir'] : '/'; if ($dir != '/Shared' || OCP\Config::getAppValue('files_sharing', 'resharing', 'yes') == 'yes') { - OCP\Util::addscript("files_sharing", "share"); + OCP\Util::addScript('core', 'share'); } OCP\Util::addscript("3rdparty", "chosen/chosen.jquery.min"); OCP\Util::addStyle( 'files_sharing', 'sharing' ); diff --git a/core/ajax/share.php b/core/ajax/share.php index f87c12dbb5..11fee4a000 100644 --- a/core/ajax/share.php +++ b/core/ajax/share.php @@ -20,23 +20,40 @@ */ OCP\JSON::checkLoggedIn(); -switch ($_POST['action']) { - case 'share': - $return = OCP\Share::share($_POST['itemType'], $_POST['item'], $_POST['shareType'], $_POST['shareWith'], $_POST['permissions']); - ($return) ? OCP\JSON::success() : OCP\JSON::error(); - break; - case 'unshare': - $return = OCP\Share::unshare($_POST['itemType'], $_POST['item'], $_POST['shareType'], $_POST['shareWith']); - ($return) ? OCP\JSON::success() : OCP\JSON::error(); - break; - case 'setTarget': - $return = OCP\Share::setTarget($_POST['itemType'], $_POST['item'], $_POST['newTarget']); - ($return) ? OCP\JSON::success() : OCP\JSON::error(); - break; - case 'setPermissions': - $return = OCP\Share::setPermissions($_POST['itemType'], $_POST['item'], $_POST['shareType'], $_POST['shareWith'], $_POST['permissions']); - ($return) ? OCP\JSON::success() : OCP\JSON::error(); - break; +if (isset($_POST['action'])) { + switch ($_POST['action']) { + case 'share': + $return = OCP\Share::share($_POST['itemType'], $_POST['item'], $_POST['shareType'], $_POST['shareWith'], $_POST['permissions']); + // TODO May need to return private link + ($return) ? OCP\JSON::success() : OCP\JSON::error(); + break; + case 'unshare': + $return = OCP\Share::unshare($_POST['itemType'], $_POST['item'], $_POST['shareType'], $_POST['shareWith']); + ($return) ? OCP\JSON::success() : OCP\JSON::error(); + break; + case 'setTarget': + $return = OCP\Share::setTarget($_POST['itemType'], $_POST['item'], $_POST['newTarget']); + ($return) ? OCP\JSON::success() : OCP\JSON::error(); + break; + case 'setPermissions': + $return = OCP\Share::setPermissions($_POST['itemType'], $_POST['item'], $_POST['shareType'], $_POST['shareWith'], $_POST['permissions']); + ($return) ? OCP\JSON::success() : OCP\JSON::error(); + break; + } +} else if (isset($_GET['fetch'])) { + switch ($_GET['fetch']) { + case 'getItemsSharedStatuses': + $return = OCP\Share::getItemsSharedStatuses($_POST['itemType']); + ($return) ? OCP\JSON::success(array('data' => $return)) : OCP\JSON::error(); + break; + case 'getItemShared': + $return = OCP\Share::getItemShared($_POST['itemType'], $_POST['item']); + ($return) ? OCP\JSON::success(array('data' => $return)) : OCP\JSON::error(); + break; + case 'getShareWith': + // TODO Autocomplete for all users, groups, etc. + break; + } } ?> \ No newline at end of file diff --git a/core/js/share.js b/core/js/share.js index 5f695774ce..9ba35616a4 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -1,35 +1,34 @@ OC.Share={ - icons:[], - itemUsers:[], - itemGroups:[], - itemPrivateLink:false, - usersAndGroups:[], - loadIcons:function() { - // Cache all icons for shared files - $.getJSON(OC.filePath('core', 'ajax', 'share.php'), function(result) { + item:[], + statuses:[], + loadIcons:function(itemType) { + // Load all share icons + $.get(OC.filePath('core', 'ajax', 'share.php'), { fetch: 'getItemsSharedStatuses', itemType: itemType }, function(result) { if (result && result.status === 'success') { $.each(result.data, function(item, hasPrivateLink) { - if (hasPrivateLink) { - OC.Share.icons[item] = OC.imagePath('core', 'actions/public'); + // Private links override shared in terms of icon display + if (itemType == 'file') { + OC.Share.statuses[item] = hasPrivateLink; } else { - OC.Share.icons[item] = OC.imagePath('core', 'actions/shared'); + if (hasPrivateLink) { + $('.share').find('[data-item="'+item+'"]').attr('src', OC.imagePath('core', 'actions/public')); + } else { + $('.share').find('[data-item="'+item+'"]').attr('src', OC.imagePath('core', 'actions/shared')); + } } }); } }); }, - loadItem:function(item) { - $.ajax({type: 'GET', url: OC.filePath('core', 'ajax', 'share.php'), data: { item: item }, async: false, success: function(result) { + loadItem:function(itemType, item) { + $.get(OC.filePath('core', 'ajax', 'share.php'), { fetch: 'getItemShared', itemType: itemType, item: item }, async: false, function(result) { if (result && result.status === 'success') { - var item = result.data; - OC.Share.itemUsers = item.users; - OC.Share.itemGroups = item.groups; - OC.Share.itemPrivateLink = item.privateLink; + OC.Share.item = result.data; } }}); }, - share:function(source, uid_shared_with, permissions, callback) { - $.post(OC.filePath('core', 'ajax', 'share.php'), { sources: source, uid_shared_with: uid_shared_with, permissions: permissions }, function(result) { + share:function(itemType, shareType, shareWith, permissions, callback) { + $.post(OC.filePath('core', 'ajax', 'share.php'), { action: 'share', itemType: itemType, shareType: shareType, shareWith: shareWith, permissions: permissions }, function(result) { if (result && result.status === 'success') { if (callback) { callback(result.data); @@ -39,8 +38,8 @@ OC.Share={ } }); }, - unshare:function(source, uid_shared_with, callback) { - $.post(OC.filePath('core', 'ajax', 'share.php'), { source: source, uid_shared_with: uid_shared_with }, function(result) { + unshare:function(itemType, shareType, shareWith, callback) { + $.post(OC.filePath('core', 'ajax', 'share.php'), { action: 'unshare', itemType: itemType, shareType: shareType, shareWith: shareWith }, function(result) { if (result && result.status === 'success') { if (callback) { callback(); @@ -50,16 +49,17 @@ OC.Share={ } }); }, - setPermissions:function(source, uid_shared_with, permissions) { - $.post(OC.filePath('core', 'ajax', 'share.php'), { source: source, uid_shared_with: uid_shared_with, permissions: permissions }, function(result) { + setPermissions:function(itemType, item, shareType, shareWith, permissions) { + $.post(OC.filePath('core', 'ajax', 'share.php'), { action: 'setPermissions', itemType: itemType, item: item, shareType: shareType, shareWith: shareWith, permissions: permissions }, function(result) { if (!result || result.status !== 'success') { OC.dialogs.alert('Error', 'Error while changing permissions'); } }); }, - showDropDown:function(item, appendTo) { + showDropDown:function(itemType, item, appendTo) { OC.Share.loadItem(item); var html = ''; $(html).appendTo(appendTo); - if (OC.Share.usersAndGroups.length < 1) { - $.ajax({type: 'GET', url: OC.filePath('files_sharing', 'ajax', 'userautocomplete.php'), async: false, success: function(users) { - if (users) { - OC.Share.usersAndGroups = users; - $.each(users, function(index, user) { - $(user).appendTo('#share_with'); - }); - $('#share_with').trigger('liszt:updated'); - } - }}); - } else { - $.each(OC.Share.usersAndGroups, function(index, user) { - $(user).appendTo('#share_with'); - }); - $('#share_with').trigger('liszt:updated'); - } - if (OC.Share.itemUsers) { - $.each(OC.Share.itemUsers, function(index, user) { - if (user.parentFolder) { - OC.Share.addSharedWith(user.uid, user.permissions, false, user.parentFolder); - } else { - OC.Share.addSharedWith(user.uid, user.permissions, false, false); - } - }); - } - if (OC.Share.itemGroups) { - $.each(OC.Share.itemGroups, function(index, group) { - if (group.parentFolder) { - OC.Share.addSharedWith(group.gid, group.permissions, group.users, group.parentFolder); - } else { - OC.Share.addSharedWith(group.gid, group.permissions, group.users, false); - } - }); - } - if (OC.Share.itemPrivateLink) { - OC.Share.showPrivateLink(item, OC.Share.itemPrivateLink); - } $('#dropdown').show('blind'); $('#share_with').chosen(); }, @@ -215,49 +178,57 @@ OC.Share={ $(document).ready(function() { + $('.share').live('click', function() { + if ($(this).data('itemType') !== undefined && $(this).data('item') !== undefined) { + OC.Share.showDropDown($(this).data('itemType'), $(this).data('item'), $(this)); + } + }); + if (typeof FileActions !== 'undefined') { - OC.Share.loadIcons(); + OC.Share.loadIcons('file'); FileActions.register('all', 'Share', function(filename) { // Return the correct sharing icon if (scanFiles.scanning) { return; } // workaround to prevent additional http request block scanning feedback var item = $('#dir').val() + '/' + filename; - // Check if icon is in cache - if (OC.Share.icons[item]) { - return OC.Share.icons[item]; + // Check if status is in cache + if (OC.Share.statuses[item] === true) { + return OC.imagePath('core', 'actions/public'); + } else if (OC.Share.statuses[item] === false) { + return OC.imagePath('core', 'actions/shared'); } else { var last = ''; var path = OC.Share.dirname(item); // Search for possible parent folders that are shared while (path != last) { - if (OC.Share.icons[path]) { - OC.Share.icons[item] = OC.Share.icons[path]; - return OC.Share.icons[item]; + if (OC.Share.statuses[path] === true) { + return OC.imagePath('core', 'actions/public'); + } else if (OC.Share.statuses[path] === false) { + return OC.imagePath('core', 'actions/shared'); } last = path; path = OC.Share.dirname(path); } - OC.Share.icons[item] = OC.imagePath('core', 'actions/share'); - return OC.Share.icons[item]; + return OC.imagePath('core', 'actions/share'); } }, function(filename) { - var file = $('#dir').val() + '/' + filename; + var item = $('#dir').val() + '/' + filename; var appendTo = $('tr').filterAttr('data-file',filename).find('td.filename'); // Check if drop down is already visible for a different file if (($('#dropdown').length > 0)) { - if (file != $('#dropdown').data('item')) { + if (item != $('#dropdown').data('item')) { OC.Share.hideDropDown(function () { $('tr').removeClass('mouseOver'); - $('tr').filterAttr('data-file',filename).addClass('mouseOver'); - OC.Share.showDropDown(file, appendTo); + $('tr').filterAttr('data-file', filename).addClass('mouseOver'); + OC.Share.showDropDown('file', item, appendTo); }); } } else { $('tr').filterAttr('data-file',filename).addClass('mouseOver'); - OC.Share.showDropDown(file, appendTo); + OC.Share.showDropDown('file', item, appendTo); } }); }; - + $(this).click(function(event) { if (!($(event.target).hasClass('drop')) && $(event.target).parents().index($('#dropdown')) == -1) { if ($('#dropdown').is(':visible')) { diff --git a/lib/public/share.php b/lib/public/share.php index f4a11a170a..b77a986f44 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -30,8 +30,7 @@ class Share { const SHARE_TYPE_USER = 0; const SHARE_TYPE_GROUP = 1; - const SHARETYPE_CONTACT = 2; - const SHARETYPE_PRIVATE_LINK = 4; + const SHARE_TYPE_PRIVATE_LINK = 3; const PERMISSION_READ = 0; const PERMISSION_UPDATE = 1; @@ -39,9 +38,10 @@ class Share { const PERMISSION_SHARE = 3; const FORMAT_NONE = -1; + const FORMAT_STATUSES = -2; private static $shareTypeUserAndGroups = -1; - private static $shareTypeGroupUserUnique = 3; + private static $shareTypeGroupUserUnique = 2; private static $backends = array(); /** @@ -95,7 +95,7 @@ class Share { * @param int Number of items to return (optional) Returns all by default * @return Return depends on format */ - public static function getItemsOwned($itemType, $format = self::FORMAT_NONE, $limit = -1) { + public static function getItemsShared($itemType, $format = self::FORMAT_NONE, $limit = -1) { return self::getItems($itemType, null, null, null, \OC_User::getUser(), $format, $limit); } @@ -106,10 +106,20 @@ class Share { * @param int Format (optional) Format type must be defined by the backend * @return Return depends on format */ - public static function getItemOwned($itemType, $item, $format = self::FORMAT_NONE) { + public static function getItemShared($itemType, $item, $format = self::FORMAT_NONE) { return self::getItems($itemType, $item, null, null, \OC_User::getUser(), $format, 1); } + /** + * @brief Get the status of each shared item of item type owned by the current user + * @param string Item type + * @param int Number of items to return (optional) Returns all by default + * @return array, item as key with a value of true if item has a private link or false + */ + public static function getItemsSharedStatuses($itemType, $limit = -1) { + return self::getItems($itemType, null, null, null, \OC_User::getUser(), self::FORMAT_STATUSES, $limit); + } + /** * @brief Share an item with a user, group, or via private link * @param string Item type @@ -455,6 +465,16 @@ class Share { return $items[key($items)]; } return $items; + } else if ($format == self::FORMAT_STATUSES) { + $statuses = array(); + foreach ($items as $item) { + if ($item['shareType'] == self::SHARE_TYPE_PRIVATE_LINK) { + $statuses[$item['item']] = true; + } else if (!isset($statuses[$item['item']])) { + $statuses[$items['item']] = false; + } + } + return $statuses; } else { return $backend->formatItems($items, $format); } From f21fdf14f9456b5a25c78f48d03063c383cdbdc2 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 24 Jun 2012 19:25:41 -0400 Subject: [PATCH 010/145] Forgot I got rid of the class field backendTypes, use the array keys of the backends field instead --- core/js/share.js | 2 +- lib/public/share.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/js/share.js b/core/js/share.js index 9ba35616a4..b7821ce14b 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -25,7 +25,7 @@ OC.Share={ if (result && result.status === 'success') { OC.Share.item = result.data; } - }}); + }); }, share:function(itemType, shareType, shareWith, permissions, callback) { $.post(OC.filePath('core', 'ajax', 'share.php'), { action: 'share', itemType: itemType, shareType: shareType, shareWith: shareWith, permissions: permissions }, function(result) { diff --git a/lib/public/share.php b/lib/public/share.php index b77a986f44..0ba4cefad9 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -355,8 +355,9 @@ class Share { * @return array */ private static function getParentItemTypes($itemType) { + $backendTypes = array_keys(self::$backends); $parents = array($itemType); - foreach (self::$backendTypes as $type => $backend) { + foreach ($backendTypes as $type => $backend) { if (in_array($backend->dependsOn, $parents)) { $parents[] = $type; } @@ -497,7 +498,8 @@ class Share { // Check file extension for an equivalent item type to convert to if ($itemType == 'file') { $extension = strtolower(substr($item, strrpos($item, '.') + 1)); - foreach (self::$backendTypes as $type => $backend) { + $backendTypes = array_keys(self::$backends); + foreach ($backendTypes as $type => $backend) { if (isset($backend['dependsOn']) && $backend['dependsOn'] == 'file' && isset($backend['supportedFileExtensions']) && in_array($extension, $backend['supportedFileExtensions'])) { $itemType = $type; break; From 28b7793d5bc3e89dd1fd85fe0461e9c7b2dd4133 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 24 Jun 2012 20:12:33 -0400 Subject: [PATCH 011/145] Fixes and change database table from sharing to share --- apps/files_sharing/appinfo/app.php | 2 + lib/public/share.php | 82 +++++++++++++++--------------- 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index d51a4f5164..281ab00d77 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -1,6 +1,7 @@ $class, 'dependsOn' => $dependsOn, 'supportedFileExtensions' => $supportedFileExtensions); return true; } else { - \OC_Log::write('OCP\Share', 'Sharing backend '.$class.' not registered, '.self::$backends[$itemType]['class'].' is already registered for '.$itemType, \OC_Log::WARN); + \OC_Log::write('OCP\Share', 'Sharing backend '.get_class($class).' not registered, '.get_class(self::$backends[$itemType]['class']).' is already registered for '.$itemType, \OC_Log::WARN); return false; } } - \OC_Log::write('OCP\Share', 'Sharing backend '.$class.' not registered, the class must extend abstract class OC_Share_Backend', \OC_Log::ERROR); + \OC_Log::write('OCP\Share', 'Sharing backend '.get_class($class).' not registered, the class must extend abstract class OC_Share_Backend', \OC_Log::ERROR); return false; } @@ -232,7 +232,7 @@ class Share { if ($item = self::getItems($itemType, $itemTarget, $uidSharedWith, true, null, false, 1)) { // Check if item is inside a shared folder and was converted if ($item['parent']) { - $query = \OC_DB::prepare('SELECT item_type FROM *PREFIX*sharing WHERE id = ? LIMIT 1'); + $query = \OC_DB::prepare('SELECT item_type FROM *PREFIX*share WHERE id = ? LIMIT 1'); $result = $query->execute(array($item['parent']))->fetchRow(); if (isset($result['item_type']) && $result['item_type'] == 'folder') { return false; @@ -240,7 +240,7 @@ class Share { } // Check if this is a group share, if it is a group share a new entry needs to be created marked as unshared from self if ($item['uid_shared_with'] == null) { - $query = \OC_DB::prepare('INSERT INTO *PREFIX*sharing VALUES(?,?,?,?,?,?,?,?,?,?)'); + $query = \OC_DB::prepare('INSERT INTO *PREFIX*share VALUES(?,?,?,?,?,?,?,?,?,?)'); $result = $query->execute(array($item['item_type'], $item['item_source'], $item['item_target'], $uidSharedWith, $item['gid_shared_with'], $item['uid_owner'], self::UNSHARED_FROM_SELF, $item['stime'], $item['file_source'], $item['file_target'])); if (\OC_DB::isError($result)) { // \OC_Log::write('OCP\Share', 'Share type '.$shareType.' is not valid for item '.$item, \OC_Log::ERROR); @@ -267,7 +267,7 @@ class Share { // Check if this is a group share if ($item['uid_shared_with'] == null) { // A new entry needs to be created exclusively for the user - $query = \OC_DB::prepare('INSERT INTO *PREFIX*sharing VALUES(?,?,?,?,?,?,?,?,?,?)'); + $query = \OC_DB::prepare('INSERT INTO *PREFIX*share VALUES(?,?,?,?,?,?,?,?,?,?)'); if (isset($item['file_target'])) { $fileTarget = $newTarget; } else { @@ -278,10 +278,10 @@ class Share { } else { // Check if this item is a file or folder, update the file_target as well if this is the case if ($itemType == 'file' || $itemType == 'folder') { - $query = \OC_DB::prepare('UPDATE *PREFIX*sharing SET item_target = ?, file_target = REPLACE(file_target, ?, ?) WHERE uid_shared_with = ?'); + $query = \OC_DB::prepare('UPDATE *PREFIX*share SET item_target = ?, file_target = REPLACE(file_target, ?, ?) WHERE uid_shared_with = ?'); $query->execute(array($newTarget, $oldTarget, $newTarget, $uidSharedWith)); } else { - $query = \OC_DB::prepare('UPDATE *PREFIX*sharing SET item_target = ? WHERE item_type = ? AND item_target = ? AND uid_shared_with = ?'); + $query = \OC_DB::prepare('UPDATE *PREFIX*share SET item_target = ? WHERE item_type = ? AND item_target = ? AND uid_shared_with = ?'); $query->execute(array($newTarget, $itemType, $oldTarget, $uidSharedWith)); } return true; @@ -304,20 +304,20 @@ class Share { if ($item = self::getItems($itemType, $item, $shareType, $shareWith, \OC_User::getUser(), self::FORMAT_NONE, 1)) { // Check if this item is a reshare and verify that the permissions granted don't exceed the parent shared item if (isset($item['parent'])) { - $query = \OC_DB::prepare('SELECT permissions FROM *PREFIX*sharing WHERE id = ? LIMIT 1'); + $query = \OC_DB::prepare('SELECT permissions FROM *PREFIX*share WHERE id = ? LIMIT 1'); $result = $query->execute(array($item['parent']))->fetchRow(); if (!isset($result['permissions']) || $permissions > $result['permissions']) { \OC_Log::write('OCP\Share', '', \OC_Log::ERROR); return false; } } - $query = \OC_DB::prepare('UPDATE *PREFIX*sharing SET permissions = ? WHERE id = ?'); + $query = \OC_DB::prepare('UPDATE *PREFIX*share SET permissions = ? WHERE id = ?'); $query->execute(array($permissions, $item['id'])); // Check if permissions were reduced if ($permissions < $item['permissions']) { // Reduce the permissions for all reshares of this item $ids = array($item['id']); - $query = \OC_DB::prepare('SELECT id, parent, permissions FROM *PREFIX*sharing WHERE item_source = ?'); + $query = \OC_DB::prepare('SELECT id, parent, permissions FROM *PREFIX*share WHERE item_source = ?'); $result = $query->execute(array($item['item_source'])); while ($item = $result->fetchRow()) { if (in_array($item['parent'], $ids) && $item['permissions'] > $permissions) { @@ -327,7 +327,7 @@ class Share { // Remove parent item from array, this item's permissions already got updated unset($ids[0]); if (!empty($ids)) { - $query = \OC_DB::prepare('UPDATE *PREFIX*sharing SET permissions = ? WHERE id IN (?)'); + $query = \OC_DB::prepare('UPDATE *PREFIX*share SET permissions = ? WHERE id IN (?)'); $query->execute(array($permissions, implode(',', $ids))); } } @@ -445,7 +445,7 @@ class Share { } $where .= ' LIMIT '.$limit; } - $query = \OC_DB::prepare('SELECT * FROM *PREFIX*sharing '.$where); + $query = \OC_DB::prepare('SELECT * FROM *PREFIX*share '.$where); $result = $query->execute(); $items = array(); while ($item = $result->fetchRow()) { @@ -460,24 +460,26 @@ class Share { } $items[$item['id']] = $item; } - if ($format == self::FORMAT_NONE) { - if ($limit == 1) { - // Return just the item instead of 2-dimensional array - return $items[key($items)]; - } - return $items; - } else if ($format == self::FORMAT_STATUSES) { - $statuses = array(); - foreach ($items as $item) { - if ($item['shareType'] == self::SHARE_TYPE_PRIVATE_LINK) { - $statuses[$item['item']] = true; - } else if (!isset($statuses[$item['item']])) { - $statuses[$items['item']] = false; + if (!empty($items)) { + if ($format == self::FORMAT_NONE) { + if ($limit == 1) { + // Return just the item instead of 2-dimensional array + return $items[key($items)]; } + return $items; + } else if ($format == self::FORMAT_STATUSES) { + $statuses = array(); + foreach ($items as $item) { + if ($item['shareType'] == self::SHARE_TYPE_PRIVATE_LINK) { + $statuses[$item['item']] = true; + } else if (!isset($statuses[$item['item']])) { + $statuses[$items['item']] = false; + } + } + return $statuses; + } else { + return $backend->formatItems($items, $format); } - return $statuses; - } else { - return $backend->formatItems($items, $format); } } return false; @@ -494,7 +496,7 @@ class Share { * @param bool|array Parent folder target (optional) * @return bool */ - private static function put($itemType, $item, $shareType, $shareWith, $uidOwner, $permissions, $parentFolder = false) { + private static function put($itemType, $item, $shareType, $shareWith, $uidOwner, $permissions, $parentFolder = null) { // Check file extension for an equivalent item type to convert to if ($itemType == 'file') { $extension = strtolower(substr($item, strrpos($item, '.') + 1)); @@ -533,7 +535,7 @@ class Share { $fileSource = null; } } - $query = \OC_DB::prepare('INSERT INTO *PREFIX*sharing (item_type, item, item_source, item_target, parent, uid_shared_with, gid_shared_with, uid_owner, permissions, stime, file_source, file_target) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); + $query = \OC_DB::prepare('INSERT INTO *PREFIX*share (item_type, item, item_source, item_target, parent, share_type, share_with, uid_owner, permissions, stime, file_source, file_target) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)'); // Share with a group if ($shareType == self::SHARE_TYPE_GROUP) { if (isset($fileSource)) { @@ -559,7 +561,7 @@ class Share { $groupItemTarget = $backend->generateTarget($item, false); $query->execute(array($itemType, $item, $itemSource, $groupItemTarget, $parent, $shareType, $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget)); // Save this id, any extra rows for this group share will need to reference it - $parent = \OC_DB::insertid('*PREFIX*sharing'); + $parent = \OC_DB::insertid('*PREFIX*share'); // Loop through all users of this group in case we need to add an extra row foreach ($shareWith['users'] as $uid) { $itemTarget = $backend->generateTarget($item, $uid); @@ -583,7 +585,7 @@ class Share { // 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, $item, $itemSource, $itemTarget, $parent, self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); - $id = \OC_DB::insertid('*PREFIX*sharing'); + $id = \OC_DB::insertid('*PREFIX*share'); } if ($parentFolder === true) { $parentFolders['id'] = $id; @@ -594,24 +596,24 @@ class Share { return $parentFolders; } } else { - $itemTarget = $backend->generateTarget($item, $uidSharedWith); + $itemTarget = $backend->generateTarget($item, $shareWith); if (isset($fileSource)) { if ($parentFolder) { if ($parentFolder === true) { - $fileTarget = self::getBackend('file')->generateTarget($source['file'], $uidSharedWith); + $fileTarget = self::getBackend('file')->generateTarget($source['file'], $shareWith); $parentFolders['folder'] = $fileTarget; } else { $fileTarget = $parentFolder['folder'].$item; $parent = $parentFolder['id']; } } else { - $fileTarget = self::getBackend('file')->generateTarget($source['file'], $uidSharedWith); + $fileTarget = self::getBackend('file')->generateTarget($source['file'], $shareWith); } } else { $fileTarget = null; } $query->execute(array($itemType, $item, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); - $id = \OC_DB::insertid('*PREFIX*sharing'); + $id = \OC_DB::insertid('*PREFIX*share'); if ($parentFolder === true) { $parentFolders['id'] = $id; // Return parent folder to preserve file target paths for potential children @@ -630,7 +632,7 @@ class Share { * @param bool */ private static function delete($parent, $excludeParent = false) { - $query = \OC_DB::prepare('SELECT id FROM *PREFIX*sharing WHERE parent IN (?)'); + $query = \OC_DB::prepare('SELECT id FROM *PREFIX*share WHERE parent IN (?)'); $ids = array($parent); while ($item = $query->execute(array(implode("','", $ids)))->fetchRow()) { $ids[] = $item['id']; @@ -639,7 +641,7 @@ class Share { unset($ids[0]); } if (!empty($ids)) { - $query = \OC_DB::prepare('DELETE FROM *PREFIX*sharing WHERE id IN (?)'); + $query = \OC_DB::prepare('DELETE FROM *PREFIX*share WHERE id IN (?)'); $query->execute(array(implode("','", $ids))); } } @@ -650,10 +652,10 @@ class Share { public static function post_deleteUser($arguments) { // Delete any items shared with the deleted user - $query = \OC_DB::prepare('DELETE FROM *PREFIX*sharing WHERE uid_shared_with = ?'); + $query = \OC_DB::prepare('DELETE FROM *PREFIX*share WHERE uid_shared_with = ?'); $result = $query->execute(array($arguments['uid'])); // Delete any items the deleted user shared - $query = \OC_DB::prepare('SELECT id, item_source FROM *PREFIX*sharing WHERE uid_owner = ?'); + $query = \OC_DB::prepare('SELECT id, item_source FROM *PREFIX*share WHERE uid_owner = ?'); $result = $query->execute(array($arguments['uid'])); while ($item = $result->fetchRow()) { self::delete($item['id']); From 32f9901bcd8b767b93520de346e092147dbb205b Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 24 Jun 2012 22:17:54 -0400 Subject: [PATCH 012/145] Fix retrieving supported file extensions from backend and remove the dependsOn and supportedFileExtensions parameters from registerBackend() --- apps/gallery/appinfo/app.php | 3 +++ lib/public/share.php | 21 +++++++++------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/gallery/appinfo/app.php b/apps/gallery/appinfo/app.php index df3b68ef73..9efb4346c3 100644 --- a/apps/gallery/appinfo/app.php +++ b/apps/gallery/appinfo/app.php @@ -28,6 +28,9 @@ OC::$CLASSPATH['OC_Gallery_Sharing'] = 'gallery/lib/sharing.php'; OC::$CLASSPATH['OC_Gallery_Hooks_Handlers'] = 'gallery/lib/hooks_handlers.php'; OC::$CLASSPATH['Pictures_Managers'] = 'gallery/lib/managers.php'; OC::$CLASSPATH['Pictures_Tiles'] = 'gallery/lib/tiles.php'; +OC::$CLASSPATH['OC_Share_Backend_Photo'] = 'gallery/lib/share.php'; + +OCP\Share::registerBackend('photo', new OC_Share_Backend_Photo()); $l = OC_L10N::get('gallery'); diff --git a/lib/public/share.php b/lib/public/share.php index 3ceb9f590c..1376eb4ded 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -52,13 +52,13 @@ class Share { * @param array (optional) List of supported file extensions if this item type depends on files * @return Returns true if backend is registered or false if error */ - public static function registerBackend($itemType, $class, $dependsOn = null, $supportedFileExtensions = null) { + public static function registerBackend($itemType, $class) { if (is_subclass_of($class, 'OCP\Share_Backend')) { if (!isset(self::$backends[$itemType])) { - self::$backends[$itemType] = array('class' => $class, 'dependsOn' => $dependsOn, 'supportedFileExtensions' => $supportedFileExtensions); + self::$backends[$itemType] = $class; return true; } else { - \OC_Log::write('OCP\Share', 'Sharing backend '.get_class($class).' not registered, '.get_class(self::$backends[$itemType]['class']).' is already registered for '.$itemType, \OC_Log::WARN); + \OC_Log::write('OCP\Share', 'Sharing backend '.get_class($class).' not registered, '.get_class(self::$backends[$itemType]).' is already registered for '.$itemType, \OC_Log::WARN); return false; } } @@ -342,8 +342,8 @@ class Share { * @return Sharing backend object */ private static function getBackend($itemType) { - if (isset(self::$backends[$itemType]['class'])) { - return self::$backends[$itemType]['class']; + if (isset(self::$backends[$itemType])) { + return self::$backends[$itemType]; } \OC_Log::write('OCP\Share', 'Sharing backend for '.$itemType.' not found', \OC_Log::ERROR); return false; @@ -500,9 +500,8 @@ class Share { // Check file extension for an equivalent item type to convert to if ($itemType == 'file') { $extension = strtolower(substr($item, strrpos($item, '.') + 1)); - $backendTypes = array_keys(self::$backends); - foreach ($backendTypes as $type => $backend) { - if (isset($backend['dependsOn']) && $backend['dependsOn'] == 'file' && isset($backend['supportedFileExtensions']) && in_array($extension, $backend['supportedFileExtensions'])) { + foreach (self::$backends as $type => $backend) { + if (isset($backend->dependsOn) && $backend->dependsOn == 'file' && isset($backend->supportedFileExtensions) && in_array($extension, $backend->supportedFileExtensions)) { $itemType = $type; break; } @@ -677,10 +676,8 @@ class Share { */ abstract class Share_Backend { - public static $dependsOn; - public static $supportedFileExtensions = array(); - - + public $dependsOn; + public $supportedFileExtensions = array(); /** * @brief Get the source of the item to be stored in the database From 243faf63349b184eadbeaa795f2aa54692cf9e51 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 24 Jun 2012 23:00:29 -0400 Subject: [PATCH 013/145] Fix searching for parent item types, search for file source instead of item source for the file item type in case the item was converted --- lib/public/share.php | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index 1376eb4ded..469b91b9f1 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -355,9 +355,8 @@ class Share { * @return array */ private static function getParentItemTypes($itemType) { - $backendTypes = array_keys(self::$backends); $parents = array($itemType); - foreach ($backendTypes as $type => $backend) { + foreach (self::$backends as $type => $backend) { if (in_array($backend->dependsOn, $parents)) { $parents[] = $type; } @@ -386,11 +385,7 @@ class Share { // Check if there are any parent types that include this type of items, e.g. a music album contains songs if (isset($itemType)) { if ($parents = self::getParentItemTypes($itemType)) { - $where = "WHERE item_type IN ('".$itemType."'"; - foreach ($parents as $parent) { - $where .= ", '.$parent.'"; - } - $where .= ')'; + $where = "WHERE item_type IN ('".implode("','", $parents)."')"; } else { $where = "WHERE item_type = '".$itemType."'"; } @@ -405,9 +400,9 @@ class Share { $where .= " AND share_type IN ('".self::SHARE_TYPE_USER."','".self::SHARE_TYPE_GROUP."','".self::$shareTypeGroupUserUnique."')"; $groups = \OC_Group::getUserGroups($shareWith); $userAndGroups = array_merge(array($shareWith), $groups); - $where .= " AND share_with IN ('".implode("','", $userAndGroups)."')"; + $where .= " AND share_with IN ('".implode(",", $userAndGroups).")"; } else { - $where .= " AND share_type = '".$shareType."' AND share_with = '".$shareWith."'"; + $where .= " AND share_type = ".$shareType." AND share_with = '".$shareWith."'"; } } if (isset($uidOwner)) { @@ -420,14 +415,19 @@ class Share { if (isset($item)) { // If looking for own shared items, check item_source else check item_target if (isset($uidOwner)) { - // Check if this item depends on a file and getSource() returned an array $source = $backend->getSource($item, $uidOwner); - if (is_array($source)) { - $itemSource = $source['item']; + // If item type is a file, file source needs to be checked in case the item was converted + if ($itemType == 'file') { + $where .= " AND file_source = ".\OC_FileCache::getId($source['file']); } else { - $itemSource = $source; + // Check if this item depends on a file and getSource() returned an array + if (is_array($source)) { + $itemSource = $source['item']; + } else { + $itemSource = $source; + } + $where .= " AND item_source = '".$itemSource."'"; } - $where .= " AND item_source = '".$itemSource."'"; } else { if ($itemType == 'file' && substr($item, -1) == '/') { // Special case to select only the shared files inside the folder @@ -528,7 +528,7 @@ class Share { return false; } else if (is_array($source)) { $itemSource = $source['item']; - $fileSource = self::getBackend('file')->getId($source['file']); + $fileSource = \OC_FileCache::getId($source['file']); } else { $itemSource = $source; $fileSource = null; From c41cb192c9e903ac6b4a911b851b848e71a97303 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 24 Jun 2012 23:12:20 -0400 Subject: [PATCH 014/145] Fix which line needs '' wrapped around the array values --- lib/public/share.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index 469b91b9f1..a00b35fef4 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -397,10 +397,10 @@ class Share { if (isset($shareType) && isset($shareWith)) { // Include all user and group items if ($shareType == self::$shareTypeUserAndGroups) { - $where .= " AND share_type IN ('".self::SHARE_TYPE_USER."','".self::SHARE_TYPE_GROUP."','".self::$shareTypeGroupUserUnique."')"; + $where .= " AND share_type IN (".self::SHARE_TYPE_USER.",".self::SHARE_TYPE_GROUP.",".self::$shareTypeGroupUserUnique.")"; $groups = \OC_Group::getUserGroups($shareWith); $userAndGroups = array_merge(array($shareWith), $groups); - $where .= " AND share_with IN ('".implode(",", $userAndGroups).")"; + $where .= " AND share_with IN ('".implode("','", $userAndGroups)."')"; } else { $where .= " AND share_type = ".$shareType." AND share_with = '".$shareWith."'"; } From d332e1e9c1b4289f8ecd927047e6d16234013908 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 25 Jun 2012 22:51:05 +0200 Subject: [PATCH 015/145] Documentation fix --- lib/public/share.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index a00b35fef4..0a76bf6520 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -685,11 +685,10 @@ abstract class Share_Backend { * @param string Owner of the item * @return mixed|array|false Source * - * Return a * Return an array if the item is file dependent, the array needs two keys: 'item' and 'file' * Return false if the item does not exist for the user * - * The translateItem() function will translate the source returned back into the item + * The formatItems() function will translate the source returned back into the item */ public abstract function getSource($item, $uid); @@ -730,4 +729,4 @@ abstract class Share_Backend_Parent extends Share_Backend { } -?> \ No newline at end of file +?> From b9e1033563b534faa75b0e0562f441b4eaf83a7d Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 25 Jun 2012 22:51:42 +0200 Subject: [PATCH 016/145] Basic framework for contacts sharing --- apps/contacts/appinfo/app.php | 2 ++ apps/contacts/lib/share.php | 54 +++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 apps/contacts/lib/share.php diff --git a/apps/contacts/appinfo/app.php b/apps/contacts/appinfo/app.php index 64fe00eef1..f27db13ca7 100644 --- a/apps/contacts/appinfo/app.php +++ b/apps/contacts/appinfo/app.php @@ -3,6 +3,7 @@ OC::$CLASSPATH['OC_Contacts_App'] = 'apps/contacts/lib/app.php'; OC::$CLASSPATH['OC_Contacts_Addressbook'] = 'apps/contacts/lib/addressbook.php'; OC::$CLASSPATH['OC_Contacts_VCard'] = 'apps/contacts/lib/vcard.php'; OC::$CLASSPATH['OC_Contacts_Hooks'] = 'apps/contacts/lib/hooks.php'; +OC::$CLASSPATH['OC_Contacts_Share'] = 'apps/contacts/lib/share.php'; OC::$CLASSPATH['OC_Connector_Sabre_CardDAV'] = 'apps/contacts/lib/connector_sabre.php'; OC::$CLASSPATH['OC_Search_Provider_Contacts'] = 'apps/contacts/lib/search.php'; OCP\Util::connectHook('OC_User', 'post_createUser', 'OC_Contacts_Hooks', 'createUser'); @@ -21,3 +22,4 @@ OCP\App::addNavigationEntry( array( OCP\App::registerPersonal('contacts','settings'); OCP\Util::addscript('contacts', 'loader'); OC_Search::registerProvider('OC_Search_Provider_Contacts'); +OCP\Share::registerBackend('addressbook', new OC_Contacts_Share()); diff --git a/apps/contacts/lib/share.php b/apps/contacts/lib/share.php new file mode 100644 index 0000000000..d304042edd --- /dev/null +++ b/apps/contacts/lib/share.php @@ -0,0 +1,54 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class OC_Contacts_Share extends OCP\Share_Backend { + /** + * @brief Get the source of the item to be stored in the database + * @param string Item + * @param string Owner of the item + * @return mixed|array|false Source + * + * Return an array if the item is file dependent, the array needs two keys: 'item' and 'file' + * Return false if the item does not exist for the user + * + * The formatItems() function will translate the source returned back into the item + */ + public function getSource($item, $uid) { + $addressbook = OC_Contacts_Addressbook::find( $item ); + if( $addressbook === false || $addressbook['userid'] != $uid) { + return false; + } + return $item; + } + + /** + * @brief Get a unique name of the item for the specified user + * @param string Item + * @param string|false User the item is being shared with + * @param array|null List of similar item names already existing as shared items + * @return string Target name + * + * This function needs to verify that the user does not already have an item with this name. + * If it does generate a new name e.g. name_# + */ + public function generateTarget($item, $uid, $exclude = null) { + } + + /** + * @brief Converts the shared item sources back into the item in the specified format + * @param array Sources of shared items + * @param int Format + * @return ? + * + * The items array is formatted with the sources as the keys to an array with the following keys: item_target, permissions, stime + * This function allows the backend to control the output of shared items with custom formats. + * It is only called through calls to the public getItem(s)SharedWith functions. + */ + public function formatItems($items, $format) { + } +} From 9fdfcc29febe4ae7d1f8f056878cd04f5596f1e0 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Mon, 25 Jun 2012 13:21:01 -0400 Subject: [PATCH 017/145] Fix group sharing --- lib/public/share.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index 0a76bf6520..7982f78e43 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -170,7 +170,7 @@ class Share { $group = $shareWith; $shareWith = array(); $shareWith['group'] = $group; - $shareWith['users'] = array_diff(\OC_Group::usersInGroup($shareWith), array($uidOwner)); + $shareWith['users'] = array_diff(\OC_Group::usersInGroup($group), array($uidOwner)); break; case self::SHARETYPE_PRIVATE_LINK: // TODO don't loop through folder conversion @@ -567,7 +567,7 @@ class Share { if (isset($fileSource)) { if ($parentFolder) { if ($parentFolder === true) { - $fileTarget = self::getBackend('file')->generateTarget($source['file'], $uidSharedWith); + $fileTarget = self::getBackend('file')->generateTarget($source['file'], $uid); if ($fileTarget != $groupFileTarget) { $parentFolders[$uid]['folder'] = $fileTarget; } @@ -576,7 +576,7 @@ class Share { $parent = $parentFolder[$uid]['id']; } } else { - $fileTarget = self::getBackend('file')->generateTarget($source['file'], $uidSharedWith); + $fileTarget = self::getBackend('file')->generateTarget($source['file'], $uid); } } else { $fileTarget = null; From b5961635eac898ee8a8c67aaa9f46fd91cbf53d0 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Mon, 25 Jun 2012 14:55:49 -0400 Subject: [PATCH 018/145] Fix ajax share file and replace 'User or Group' select form with a textbox --- core/ajax/share.php | 15 ++++++++------- core/js/share.js | 47 +++++++++------------------------------------ 2 files changed, 17 insertions(+), 45 deletions(-) diff --git a/core/ajax/share.php b/core/ajax/share.php index 11fee4a000..3582f8596b 100644 --- a/core/ajax/share.php +++ b/core/ajax/share.php @@ -18,37 +18,38 @@ * You should have received a copy of the GNU Affero General Public * License along with this library. If not, see . */ +require_once '../../lib/base.php'; -OCP\JSON::checkLoggedIn(); +OC_JSON::checkLoggedIn(); if (isset($_POST['action'])) { switch ($_POST['action']) { case 'share': $return = OCP\Share::share($_POST['itemType'], $_POST['item'], $_POST['shareType'], $_POST['shareWith'], $_POST['permissions']); // TODO May need to return private link - ($return) ? OCP\JSON::success() : OCP\JSON::error(); + ($return) ? OC_JSON::success() : OC_JSON::error(); break; case 'unshare': $return = OCP\Share::unshare($_POST['itemType'], $_POST['item'], $_POST['shareType'], $_POST['shareWith']); - ($return) ? OCP\JSON::success() : OCP\JSON::error(); + ($return) ? OC_JSON::success() : OC_JSON::error(); break; case 'setTarget': $return = OCP\Share::setTarget($_POST['itemType'], $_POST['item'], $_POST['newTarget']); - ($return) ? OCP\JSON::success() : OCP\JSON::error(); + ($return) ? OC_JSON::success() : OC_JSON::error(); break; case 'setPermissions': $return = OCP\Share::setPermissions($_POST['itemType'], $_POST['item'], $_POST['shareType'], $_POST['shareWith'], $_POST['permissions']); - ($return) ? OCP\JSON::success() : OCP\JSON::error(); + ($return) ? OC_JSON::success() : OC_JSON::error(); break; } } else if (isset($_GET['fetch'])) { switch ($_GET['fetch']) { case 'getItemsSharedStatuses': $return = OCP\Share::getItemsSharedStatuses($_POST['itemType']); - ($return) ? OCP\JSON::success(array('data' => $return)) : OCP\JSON::error(); + ($return) ? OC_JSON::success(array('data' => $return)) : OC_JSON::error(); break; case 'getItemShared': $return = OCP\Share::getItemShared($_POST['itemType'], $_POST['item']); - ($return) ? OCP\JSON::success(array('data' => $return)) : OCP\JSON::error(); + ($return) ? OC_JSON::success(array('data' => $return)) : OC_JSON::error(); break; case 'getShareWith': // TODO Autocomplete for all users, groups, etc. diff --git a/core/js/share.js b/core/js/share.js index b7821ce14b..73a7ff86c2 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -21,20 +21,20 @@ OC.Share={ }); }, loadItem:function(itemType, item) { - $.get(OC.filePath('core', 'ajax', 'share.php'), { fetch: 'getItemShared', itemType: itemType, item: item }, async: false, function(result) { + $.get(OC.filePath('core', 'ajax', 'share.php'), { fetch: 'getItemShared', itemType: itemType, item: item }, function(result) { if (result && result.status === 'success') { OC.Share.item = result.data; } }); }, - share:function(itemType, shareType, shareWith, permissions, callback) { - $.post(OC.filePath('core', 'ajax', 'share.php'), { action: 'share', itemType: itemType, shareType: shareType, shareWith: shareWith, permissions: permissions }, function(result) { + share:function(itemType, item, shareType, shareWith, permissions, callback) { + $.post(OC.filePath('core', 'ajax', 'share.php'), { action: 'share', itemType: itemType, item: item, shareType: shareType, shareWith: shareWith, permissions: permissions }, function(result) { if (result && result.status === 'success') { if (callback) { callback(result.data); } } else { - OC.dialogs.alert(result.data.message, 'Error while sharing'); + OC.dialogs.alert('Error', 'Error while sharing'); } }); }, @@ -58,11 +58,9 @@ OC.Share={ }, showDropDown:function(itemType, item, appendTo) { OC.Share.loadItem(item); - var html = '