/** * @brief Get the source file path for a shared file * @param string Shared target file path * @return string source file path or false if not found */ private function getSourcePath($target) { $source = $this->getFile($target); if ($source) { if (!isset($source['fullPath'])) { \OC\Files\Filesystem::initMountPoints($source['fileOwner']); $mount = \OC\Files\Mount::findByNumericId($source['storage']); if ($mount) { $this->files[$target]['fullPath'] = $mount->getMountPoint() . $source['path']; } else { $this->files[$target]['fullPath'] = false; } } return $this->files[$target]['fullPath']; } return false; }
/** * @brief Get the source cache of a shared file or folder * @param string $target Shared target file path * @return \OC\Files\Cache\Cache */ private function getSourceCache($target) { $source = \OC_Share_Backend_File::getSource($target); if (isset($source['path']) && isset($source['fileOwner'])) { \OC\Files\Filesystem::initMountPoints($source['fileOwner']); $mount = \OC\Files\Mount::findByNumericId($source['storage']); if ($mount) { $fullPath = $mount->getMountPoint() . $source['path']; list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($fullPath); if ($storage) { $this->files[$target] = $internalPath; $cache = $storage->getCache(); $this->storageId = $storage->getId(); $this->numericId = $cache->getNumericStorageId(); return $cache; } } } return false; }
/** * @brief Get shared items from the database * @param string Item type * @param string Item source or target (optional) * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, SHARE_TYPE_LINK, $shareTypeUserAndGroups, or $shareTypeGroupUserUnique * @param string User or group the item is being shared with * @param string User that is the owner of shared items (optional) * @param int Format to convert items to with formatItems() * @param mixed Parameters to pass to formatItems() * @param int Number of items to return, -1 to return all matches (optional) * @param bool Include collection item types (optional) * @return mixed * * See public functions getItem(s)... for parameter usage * */ private static function getItems($itemType, $item = null, $shareType = null, $shareWith = null, $uidOwner = null, $format = self::FORMAT_NONE, $parameters = null, $limit = -1, $includeCollections = false, $itemShareWithBySource = false) { if (!self::isEnabled()) { if ($limit == 1 || isset($uidOwner) && isset($item)) { return false; } else { return array(); } } $backend = self::getBackend($itemType); $collectionTypes = false; // Get filesystem root to add it to the file target and remove from the // file source, match file_source with the file cache if ($itemType == 'file' || $itemType == 'folder') { $root = \OC\Files\Filesystem::getRoot(); $where = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid`'; if (!isset($item)) { $where .= ' WHERE `file_target` IS NOT NULL'; } $fileDependent = true; $queryArgs = array(); } else { $fileDependent = false; $root = ''; if ($includeCollections && !isset($item) && ($collectionTypes = self::getCollectionItemTypes($itemType))) { // If includeCollections is true, find collections of this item type, e.g. a music album contains songs if (!in_array($itemType, $collectionTypes)) { $itemTypes = array_merge(array($itemType), $collectionTypes); } else { $itemTypes = $collectionTypes; } $placeholders = join(',', array_fill(0, count($itemTypes), '?')); $where = ' WHERE `item_type` IN (' . $placeholders . '))'; $queryArgs = $itemTypes; } else { $where = ' WHERE `item_type` = ?'; $queryArgs = array($itemType); } } if (isset($shareType)) { // Include all user and group items if ($shareType == self::$shareTypeUserAndGroups && isset($shareWith)) { $where .= ' AND `share_type` IN (?,?,?)'; $queryArgs[] = self::SHARE_TYPE_USER; $queryArgs[] = self::SHARE_TYPE_GROUP; $queryArgs[] = self::$shareTypeGroupUserUnique; $userAndGroups = array_merge(array($shareWith), \OC_Group::getUserGroups($shareWith)); $placeholders = join(',', array_fill(0, count($userAndGroups), '?')); $where .= ' AND `share_with` IN (' . $placeholders . ')'; $queryArgs = array_merge($queryArgs, $userAndGroups); // Don't include own group shares $where .= ' AND `uid_owner` != ?'; $queryArgs[] = $shareWith; } else { $where .= ' AND `share_type` = ?'; $queryArgs[] = $shareType; if (isset($shareWith)) { $where .= ' AND `share_with` = ?'; $queryArgs[] = $shareWith; } } } if (isset($uidOwner)) { $where .= ' AND `uid_owner` = ?'; $queryArgs[] = $uidOwner; if (!isset($shareType)) { // Prevent unique user targets for group shares from being selected $where .= ' AND `share_type` != ?'; $queryArgs[] = self::$shareTypeGroupUserUnique; } if ($itemType == 'file' || $itemType == 'folder') { $column = 'file_source'; } else { $column = 'item_source'; } } else { if ($itemType == 'file' || $itemType == 'folder') { $column = 'file_target'; } else { $column = 'item_target'; } } if (isset($item)) { if ($includeCollections && ($collectionTypes = self::getCollectionItemTypes($itemType))) { $where .= ' AND ('; } else { $where .= ' AND'; } // If looking for own shared items, check item_source else check item_target if (isset($uidOwner) || $itemShareWithBySource) { // If item type is a file, file source needs to be checked in case the item was converted if ($itemType == 'file' || $itemType == 'folder') { $where .= ' `file_source` = ?'; $column = 'file_source'; } else { $where .= ' `item_source` = ?'; $column = 'item_source'; } } else { if ($itemType == 'file' || $itemType == 'folder') { $where .= ' `file_target` = ?'; $item = \OC\Files\Filesystem::normalizePath($item); } else { $where .= ' `item_target` = ?'; } } $queryArgs[] = $item; if ($includeCollections && $collectionTypes) { $placeholders = join(',', array_fill(0, count($collectionTypes), '?')); $where .= ' OR `item_type` IN (' . $placeholders . '))'; $queryArgs = array_merge($queryArgs, $collectionTypes); } } if ($limit != -1 && !$includeCollections) { if ($shareType == self::$shareTypeUserAndGroups) { // Make sure the unique user target is returned if it exists, // unique targets should follow the group share in the database // If the limit is not 1, the filtering can be done later $where .= ' ORDER BY `*PREFIX*share`.`id` DESC'; } // The limit must be at least 3, because filtering needs to be done if ($limit < 3) { $queryLimit = 3; } else { $queryLimit = $limit; } } else { $queryLimit = null; } // TODO Optimize selects if ($format == self::FORMAT_STATUSES) { if ($itemType == 'file' || $itemType == 'folder') { $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`,' . ' `share_type`, `file_source`, `path`, `expiration`, `storage`'; } else { $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `expiration`'; } } else { if (isset($uidOwner)) { if ($itemType == 'file' || $itemType == 'folder') { $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`,' . ' `share_type`, `share_with`, `file_source`, `path`, `permissions`, `stime`,' . ' `expiration`, `token`, `storage`'; } else { $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `permissions`,' . ' `stime`, `file_source`, `expiration`, `token`'; } } else { if ($fileDependent) { if (($itemType == 'file' || $itemType == 'folder') && $format == \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS || $format == \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT) { $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`, `uid_owner`, ' . '`share_type`, `share_with`, `file_source`, `path`, `file_target`, ' . '`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, ' . '`name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`, `etag`'; } else { $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`, `*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`, `file_source`, `path`, `file_target`, `permissions`, `stime`, `expiration`, `token`, `storage`'; } } else { $select = '*'; } } } $root = strlen($root); $query = \OC_DB::prepare('SELECT ' . $select . ' FROM `*PREFIX*share` ' . $where, $queryLimit); $result = $query->execute($queryArgs); if (\OC_DB::isError($result)) { \OC_Log::write('OCP\\Share', \OC_DB::getErrorMessage($result) . ', select=' . $select . ' where=' . $where, \OC_Log::ERROR); } $items = array(); $targets = array(); $switchedItems = array(); $mounts = array(); while ($row = $result->fetchRow()) { if (isset($row['id'])) { $row['id'] = (int) $row['id']; } if (isset($row['share_type'])) { $row['share_type'] = (int) $row['share_type']; } if (isset($row['parent'])) { $row['parent'] = (int) $row['parent']; } if (isset($row['file_parent'])) { $row['file_parent'] = (int) $row['file_parent']; } if (isset($row['file_source'])) { $row['file_source'] = (int) $row['file_source']; } if (isset($row['permissions'])) { $row['permissions'] = (int) $row['permissions']; } if (isset($row['storage'])) { $row['storage'] = (int) $row['storage']; } if (isset($row['stime'])) { $row['stime'] = (int) $row['stime']; } // Filter out duplicate group shares for users with unique targets if ($row['share_type'] == self::$shareTypeGroupUserUnique && isset($items[$row['parent']])) { $row['share_type'] = self::SHARE_TYPE_GROUP; $row['share_with'] = $items[$row['parent']]['share_with']; // Remove the parent group share unset($items[$row['parent']]); if ($row['permissions'] == 0) { continue; } } else { if (!isset($uidOwner)) { // Check if the same target already exists if (isset($targets[$row[$column]])) { // Check if the same owner shared with the user twice // through a group and user share - this is allowed $id = $targets[$row[$column]]; if (isset($items[$id]) && $items[$id]['uid_owner'] == $row['uid_owner']) { // Switch to group share type to ensure resharing conditions aren't bypassed if ($items[$id]['share_type'] != self::SHARE_TYPE_GROUP) { $items[$id]['share_type'] = self::SHARE_TYPE_GROUP; $items[$id]['share_with'] = $row['share_with']; } // Switch ids if sharing permission is granted on only // one share to ensure correct parent is used if resharing if (~(int) $items[$id]['permissions'] & PERMISSION_SHARE && (int) $row['permissions'] & PERMISSION_SHARE) { $items[$row['id']] = $items[$id]; $switchedItems[$id] = $row['id']; unset($items[$id]); $id = $row['id']; } // Combine the permissions for the item $items[$id]['permissions'] |= (int) $row['permissions']; continue; } } else { $targets[$row[$column]] = $row['id']; } } } // Remove root from file source paths if retrieving own shared items if (isset($uidOwner) && isset($row['path'])) { if (isset($row['parent'])) { $row['path'] = '/Shared/' . basename($row['path']); } else { if (!isset($mounts[$row['storage']])) { $mounts[$row['storage']] = \OC\Files\Mount::findByNumericId($row['storage']); } if ($mounts[$row['storage']]) { $path = $mounts[$row['storage']]->getMountPoint() . $row['path']; $row['path'] = substr($path, $root); } } } if (isset($row['expiration'])) { $time = new \DateTime(); if ($row['expiration'] < date('Y-m-d H:i', $time->format('U') - $time->getOffset())) { self::delete($row['id']); continue; } } // Check if resharing is allowed, if not remove share permission if (isset($row['permissions']) && !self::isResharingAllowed()) { $row['permissions'] &= ~PERMISSION_SHARE; } // Add display names to result if (isset($row['share_with']) && $row['share_with'] != '') { $row['share_with_displayname'] = \OCP\User::getDisplayName($row['share_with']); } if (isset($row['uid_owner']) && $row['uid_owner'] != '') { $row['displayname_owner'] = \OCP\User::getDisplayName($row['uid_owner']); } $items[$row['id']] = $row; } if (!empty($items)) { $collectionItems = array(); foreach ($items as &$row) { // Return only the item instead of a 2-dimensional array if ($limit == 1 && $row[$column] == $item && ($row['item_type'] == $itemType || $itemType == 'file')) { if ($format == self::FORMAT_NONE) { return $row; } else { break; } } // Check if this is a collection of the requested item type if ($includeCollections && $collectionTypes && in_array($row['item_type'], $collectionTypes)) { if (($collectionBackend = self::getBackend($row['item_type'])) && $collectionBackend instanceof Share_Backend_Collection) { // Collections can be inside collections, check if the item is a collection if (isset($item) && $row['item_type'] == $itemType && $row[$column] == $item) { $collectionItems[] = $row; } else { $collection = array(); $collection['item_type'] = $row['item_type']; if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') { $collection['path'] = basename($row['path']); } $row['collection'] = $collection; // Fetch all of the children sources $children = $collectionBackend->getChildren($row[$column]); foreach ($children as $child) { $childItem = $row; $childItem['item_type'] = $itemType; if ($row['item_type'] != 'file' && $row['item_type'] != 'folder') { $childItem['item_source'] = $child['source']; $childItem['item_target'] = $child['target']; } if ($backend instanceof Share_Backend_File_Dependent) { if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') { $childItem['file_source'] = $child['source']; } else { $meta = \OC\Files\Filesystem::getFileInfo($child['file_path']); $childItem['file_source'] = $meta['fileid']; } $childItem['file_target'] = \OC\Files\Filesystem::normalizePath($child['file_path']); } if (isset($item)) { if ($childItem[$column] == $item) { // Return only the item instead of a 2-dimensional array if ($limit == 1) { if ($format == self::FORMAT_NONE) { return $childItem; } else { // Unset the items array and break out of both loops $items = array(); $items[] = $childItem; break 2; } } else { $collectionItems[] = $childItem; } } } else { $collectionItems[] = $childItem; } } } } // Remove collection item $toRemove = $row['id']; if (array_key_exists($toRemove, $switchedItems)) { $toRemove = $switchedItems[$toRemove]; } unset($items[$toRemove]); } } if (!empty($collectionItems)) { $items = array_merge($items, $collectionItems); } if (empty($items) && $limit == 1) { return false; } if ($format == self::FORMAT_NONE) { return $items; } else { if ($format == self::FORMAT_STATUSES) { $statuses = array(); foreach ($items as $item) { if ($item['share_type'] == self::SHARE_TYPE_LINK) { $statuses[$item[$column]]['link'] = true; } else { if (!isset($statuses[$item[$column]])) { $statuses[$item[$column]]['link'] = false; } } if ($itemType == 'file' || $itemType == 'folder') { $statuses[$item[$column]]['path'] = $item['path']; } } return $statuses; } else { return $backend->formatItems($items, $format, $parameters); } } } else { if ($limit == 1 || isset($uidOwner) && isset($item)) { return false; } } return array(); }