示例#1
0
文件: files.php 项目: rosarion/core
 /**
  * @param false|string $filename
  */
 private static function addSendfileHeader($filename)
 {
     if (isset($_SERVER['MOD_X_SENDFILE_ENABLED'])) {
         $filename = \OC\Files\Filesystem::getLocalFile($filename);
         header("X-Sendfile: " . $filename);
     }
     if (isset($_SERVER['MOD_X_SENDFILE2_ENABLED'])) {
         $filename = \OC\Files\Filesystem::getLocalFile($filename);
         if (isset($_SERVER['HTTP_RANGE']) && preg_match("/^bytes=([0-9]+)-([0-9]*)\$/", $_SERVER['HTTP_RANGE'], $range)) {
             $filelength = filesize($filename);
             if ($range[2] === "") {
                 $range[2] = $filelength - 1;
             }
             header("Content-Range: bytes {$range['1']}-{$range['2']}/" . $filelength);
             header("HTTP/1.1 206 Partial content");
             header("X-Sendfile2: " . str_replace(",", "%2c", rawurlencode($filename)) . " {$range['1']}-{$range['2']}");
         } else {
             header("X-Sendfile: " . $filename);
         }
     }
     if (isset($_SERVER['MOD_X_ACCEL_REDIRECT_ENABLED'])) {
         if (isset($_SERVER['MOD_X_ACCEL_REDIRECT_PREFIX'])) {
             $filename = $_SERVER['MOD_X_ACCEL_REDIRECT_PREFIX'] . \OC\Files\Filesystem::getLocalFile($filename);
         } else {
             $filename = \OC::$WEBROOT . '/data' . \OC\Files\Filesystem::getRoot() . $filename;
         }
         header("X-Accel-Redirect: " . $filename);
     }
 }
示例#2
0
 public function testEditNoCreateHook()
 {
     $storage1 = $this->getTestStorage();
     $storage2 = $this->getTestStorage();
     $defaultRoot = \OC\Files\Filesystem::getRoot();
     \OC\Files\Filesystem::mount($storage1, array(), '/');
     \OC\Files\Filesystem::mount($storage2, array(), $defaultRoot);
     \OC_Hook::connect('OC_Filesystem', 'post_create', $this, 'dummyHookCreate');
     \OC_Hook::connect('OC_Filesystem', 'post_update', $this, 'dummyHookUpdate');
     \OC_Hook::connect('OC_Filesystem', 'post_write', $this, 'dummyHookWrite');
     $view = new \OC\Files\View($defaultRoot);
     $this->hookWritePath = $this->hookUpdatePath = $this->hookCreatePath = null;
     $view->file_put_contents('/asd.txt', 'foo');
     $this->assertEquals('/asd.txt', $this->hookCreatePath);
     $this->assertNull($this->hookUpdatePath);
     $this->assertEquals('/asd.txt', $this->hookWritePath);
     $this->hookWritePath = $this->hookUpdatePath = $this->hookCreatePath = null;
     $view->file_put_contents('/asd.txt', 'foo');
     $this->assertNull($this->hookCreatePath);
     $this->assertEquals('/asd.txt', $this->hookUpdatePath);
     $this->assertEquals('/asd.txt', $this->hookWritePath);
     \OC_Hook::clear('OC_Filesystem', 'post_create');
     \OC_Hook::clear('OC_Filesystem', 'post_update');
     \OC_Hook::clear('OC_Filesystem', 'post_write');
 }
示例#3
0
文件: share.php 项目: evanjt/core
 /**
  * Get shared items from the database
  * @param string $itemType
  * @param string $item Item source or target (optional)
  * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, SHARE_TYPE_LINK, $shareTypeUserAndGroups, or $shareTypeGroupUserUnique
  * @param string $shareWith User or group the item is being shared with
  * @param string $uidOwner User that is the owner of shared items (optional)
  * @param int $format Format to convert items to with formatItems() (optional)
  * @param mixed $parameters to pass to formatItems() (optional)
  * @param int $limit Number of items to return, -1 to return all matches (optional)
  * @param boolean $includeCollections Include collection item types (optional)
  * @param boolean $itemShareWithBySource (optional)
  * @param boolean $checkExpireDate
  * @return array
  *
  * See public functions getItem(s)... for parameter usage
  *
  */
 public static function getItems($itemType, $item = null, $shareType = null, $shareWith = null, $uidOwner = null, $format = self::FORMAT_NONE, $parameters = null, $limit = -1, $includeCollections = false, $itemShareWithBySource = false, $checkExpireDate = true)
 {
     if (!self::isEnabled()) {
         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') {
         if (!is_null($uidOwner)) {
             $root = \OC\Files\Filesystem::getRoot();
         } else {
             $root = '';
         }
         $where = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid` ';
         if (!isset($item)) {
             $where .= ' AND `file_target` IS NOT NULL ';
         }
         $where .= 'INNER JOIN `*PREFIX*storages` ON `numeric_id` = `*PREFIX*filecache`.`storage` ';
         $fileDependent = true;
         $queryArgs = array();
     } else {
         $fileDependent = false;
         $root = '';
         $collectionTypes = self::getCollectionItemTypes($itemType);
         if ($includeCollections && !isset($item) && $collectionTypes) {
             // 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 (\OC::$server->getAppConfig()->getValue('core', 'shareapi_allow_links', 'yes') !== 'yes') {
         $where .= ' AND `share_type` != ?';
         $queryArgs[] = self::SHARE_TYPE_LINK;
     }
     if (isset($shareType)) {
         // Include all user and group items
         if ($shareType == self::$shareTypeUserAndGroups && isset($shareWith)) {
             $where .= ' AND ((`share_type` in (?, ?) AND `share_with` = ?) ';
             $queryArgs[] = self::SHARE_TYPE_USER;
             $queryArgs[] = self::$shareTypeGroupUserUnique;
             $queryArgs[] = $shareWith;
             $groups = \OC_Group::getUserGroups($shareWith);
             if (!empty($groups)) {
                 $placeholders = join(',', array_fill(0, count($groups), '?'));
                 $where .= ' OR (`share_type` = ? AND `share_with` IN (' . $placeholders . ')) ';
                 $queryArgs[] = self::SHARE_TYPE_GROUP;
                 $queryArgs = array_merge($queryArgs, $groups);
             }
             $where .= ')';
             // 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 ($fileDependent) {
             $column = 'file_source';
         } else {
             $column = 'item_source';
         }
     } else {
         if ($fileDependent) {
             $column = 'file_target';
         } else {
             $column = 'item_target';
         }
     }
     if (isset($item)) {
         $collectionTypes = self::getCollectionItemTypes($itemType);
         if ($includeCollections && $collectionTypes && !in_array('folder', $collectionTypes)) {
             $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 ($fileDependent) {
                 $where .= ' `file_source` = ?';
                 $column = 'file_source';
             } else {
                 $where .= ' `item_source` = ?';
                 $column = 'item_source';
             }
         } else {
             if ($fileDependent) {
                 $where .= ' `file_target` = ?';
                 $item = \OC\Files\Filesystem::normalizePath($item);
             } else {
                 $where .= ' `item_target` = ?';
             }
         }
         $queryArgs[] = $item;
         if ($includeCollections && $collectionTypes && !in_array('folder', $collectionTypes)) {
             $placeholders = join(',', array_fill(0, count($collectionTypes), '?'));
             $where .= ' OR `item_type` IN (' . $placeholders . '))';
             $queryArgs = array_merge($queryArgs, $collectionTypes);
         }
     }
     if ($shareType == self::$shareTypeUserAndGroups && $limit === 1) {
         // Make sure the unique user target is returned if it exists,
         // unique targets should follow the group share in the database
         // If the limit is not 1, the filtering can be done later
         $where .= ' ORDER BY `*PREFIX*share`.`id` DESC';
     } else {
         $where .= ' ORDER BY `*PREFIX*share`.`id` ASC';
     }
     if ($limit != -1 && !$includeCollections) {
         // The limit must be at least 3, because filtering needs to be done
         if ($limit < 3) {
             $queryLimit = 3;
         } else {
             $queryLimit = $limit;
         }
     } else {
         $queryLimit = null;
     }
     $select = self::createSelectStatement($format, $fileDependent, $uidOwner);
     $root = strlen($root);
     $query = \OC_DB::prepare('SELECT ' . $select . ' FROM `*PREFIX*share` ' . $where, $queryLimit);
     $result = $query->execute($queryArgs);
     if (\OC_DB::isError($result)) {
         \OCP\Util::writeLog('OCP\\Share', \OC_DB::getErrorMessage() . ', select=' . $select . ' where=', \OCP\Util::ERROR);
     }
     $items = array();
     $targets = array();
     $switchedItems = array();
     $mounts = array();
     while ($row = $result->fetchRow()) {
         self::transformDBResults($row);
         // Filter out duplicate group shares for users with unique targets
         if ($fileDependent && !self::isFileReachable($row['path'], $row['storage_id'])) {
             continue;
         }
         if ($row['share_type'] == self::$shareTypeGroupUserUnique && isset($items[$row['parent']])) {
             $row['share_type'] = self::SHARE_TYPE_GROUP;
             $row['unique_name'] = true;
             // remember that we use a unique name for this user
             $row['share_with'] = $items[$row['parent']]['share_with'];
             // if the group share was unshared from the user we keep the permission, otherwise
             // we take the permission from the parent because this is always the up-to-date
             // permission for the group share
             if ($row['permissions'] > 0) {
                 $row['permissions'] = $items[$row['parent']]['permissions'];
             }
             // Remove the parent group share
             unset($items[$row['parent']]);
             if ($row['permissions'] == 0) {
                 continue;
             }
         } else {
             if (!isset($uidOwner)) {
                 // Check if the same target already exists
                 if (isset($targets[$row['id']])) {
                     // Check if the same owner shared with the user twice
                     // through a group and user share - this is allowed
                     $id = $targets[$row['id']];
                     if (isset($items[$id]) && $items[$id]['uid_owner'] == $row['uid_owner']) {
                         // Switch to group share type to ensure resharing conditions aren't bypassed
                         if ($items[$id]['share_type'] != self::SHARE_TYPE_GROUP) {
                             $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'] & \OCP\Constants::PERMISSION_SHARE && (int) $row['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
                             $items[$row['id']] = $items[$id];
                             $switchedItems[$id] = $row['id'];
                             unset($items[$id]);
                             $id = $row['id'];
                         }
                         $items[$id]['permissions'] |= (int) $row['permissions'];
                     }
                     continue;
                 } elseif (!empty($row['parent'])) {
                     $targets[$row['parent']] = $row['id'];
                 }
             }
         }
         // Remove root from file source paths if retrieving own shared items
         if (isset($uidOwner) && isset($row['path'])) {
             if (isset($row['parent'])) {
                 $query = \OC_DB::prepare('SELECT `file_target` FROM `*PREFIX*share` WHERE `id` = ?');
                 $parentResult = $query->execute(array($row['parent']));
                 if (\OC_DB::isError($result)) {
                     \OCP\Util::writeLog('OCP\\Share', 'Can\'t select parent: ' . \OC_DB::getErrorMessage() . ', select=' . $select . ' where=' . $where, \OCP\Util::ERROR);
                 } else {
                     $parentRow = $parentResult->fetchRow();
                     $tmpPath = $parentRow['file_target'];
                     // find the right position where the row path continues from the target path
                     $pos = strrpos($row['path'], $parentRow['file_target']);
                     $subPath = substr($row['path'], $pos);
                     $splitPath = explode('/', $subPath);
                     foreach (array_slice($splitPath, 2) as $pathPart) {
                         $tmpPath = $tmpPath . '/' . $pathPart;
                     }
                     $row['path'] = $tmpPath;
                 }
             } else {
                 if (!isset($mounts[$row['storage']])) {
                     $mountPoints = \OC\Files\Filesystem::getMountByNumericId($row['storage']);
                     if (is_array($mountPoints) && !empty($mountPoints)) {
                         $mounts[$row['storage']] = current($mountPoints);
                     }
                 }
                 if (!empty($mounts[$row['storage']])) {
                     $path = $mounts[$row['storage']]->getMountPoint() . $row['path'];
                     $relPath = substr($path, $root);
                     // path relative to data/user
                     $row['path'] = rtrim($relPath, '/');
                 }
             }
         }
         if ($checkExpireDate) {
             if (self::expireItem($row)) {
                 continue;
             }
         }
         // Check if resharing is allowed, if not remove share permission
         if (isset($row['permissions']) && !self::isResharingAllowed() | \OCP\Util::isSharingDisabledForUser()) {
             $row['permissions'] &= ~\OCP\Constants::PERMISSION_SHARE;
         }
         // Add display names to result
         $row['share_with_displayname'] = $row['share_with'];
         if (isset($row['share_with']) && $row['share_with'] != '' && $row['share_type'] === self::SHARE_TYPE_USER) {
             $row['share_with_displayname'] = \OCP\User::getDisplayName($row['share_with']);
         } else {
             if (isset($row['share_with']) && $row['share_with'] != '' && $row['share_type'] === self::SHARE_TYPE_REMOTE) {
                 $addressBookEntries = \OC::$server->getContactsManager()->search($row['share_with'], ['CLOUD']);
                 foreach ($addressBookEntries as $entry) {
                     foreach ($entry['CLOUD'] as $cloudID) {
                         if ($cloudID === $row['share_with']) {
                             $row['share_with_displayname'] = $entry['FN'];
                         }
                     }
                 }
             }
         }
         if (isset($row['uid_owner']) && $row['uid_owner'] != '') {
             $row['displayname_owner'] = \OCP\User::getDisplayName($row['uid_owner']);
         }
         if ($row['permissions'] > 0) {
             $items[$row['id']] = $row;
         }
     }
     // group items if we are looking for items shared with the current user
     if (isset($shareWith) && $shareWith === \OCP\User::getUser()) {
         $items = self::groupItems($items, $itemType);
     }
     if (!empty($items)) {
         $collectionItems = array();
         foreach ($items as &$row) {
             // Return only the item instead of a 2-dimensional array
             if ($limit == 1 && $row[$column] == $item && ($row['item_type'] == $itemType || $itemType == 'file')) {
                 if ($format == self::FORMAT_NONE) {
                     return $row;
                 } else {
                     break;
                 }
             }
             // Check if this is a collection of the requested item type
             if ($includeCollections && $collectionTypes && $row['item_type'] !== 'folder' && in_array($row['item_type'], $collectionTypes)) {
                 if (($collectionBackend = self::getBackend($row['item_type'])) && $collectionBackend instanceof \OCP\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 \OCP\Share_Backend_File_Dependent) {
                                 if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
                                     $childItem['file_source'] = $child['source'];
                                 } else {
                                     // TODO is this really needed if we already know that we use the file backend?
                                     $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]);
             } elseif ($includeCollections && $collectionTypes && in_array($row['item_type'], $collectionTypes)) {
                 // FIXME: Thats a dirty hack to improve file sharing performance,
                 // see github issue #10588 for more details
                 // Need to find a solution which works for all back-ends
                 $collectionBackend = self::getBackend($row['item_type']);
                 $sharedParents = $collectionBackend->getParents($row['item_source']);
                 foreach ($sharedParents as $parent) {
                     $collectionItems[] = $parent;
                 }
             }
         }
         if (!empty($collectionItems)) {
             $collectionItems = array_unique($collectionItems, SORT_REGULAR);
             $items = array_merge($items, $collectionItems);
         }
         // filter out invalid items, these can appear when subshare entries exist
         // for a group in which the requested user isn't a member any more
         $items = array_filter($items, function ($item) {
             return $item['share_type'] !== self::$shareTypeGroupUserUnique;
         });
         return self::formatResult($items, $column, $backend, $format, $parameters);
     } elseif ($includeCollections && $collectionTypes && in_array('folder', $collectionTypes)) {
         // FIXME: Thats a dirty hack to improve file sharing performance,
         // see github issue #10588 for more details
         // Need to find a solution which works for all back-ends
         $collectionItems = array();
         $collectionBackend = self::getBackend('folder');
         $sharedParents = $collectionBackend->getParents($item, $shareWith, $uidOwner);
         foreach ($sharedParents as $parent) {
             $collectionItems[] = $parent;
         }
         if ($limit === 1) {
             return reset($collectionItems);
         }
         return self::formatResult($collectionItems, $column, $backend, $format, $parameters);
     }
     return array();
 }
示例#4
0
 private function shouldEmitHooks($path = '')
 {
     if ($path && Cache\Scanner::isPartialFile($path)) {
         return false;
     }
     if (!Filesystem::$loaded) {
         return false;
     }
     $defaultRoot = Filesystem::getRoot();
     if ($defaultRoot === null) {
         return false;
     }
     if ($this->fakeRoot === $defaultRoot) {
         return true;
     }
     return strlen($this->fakeRoot) > strlen($defaultRoot) && substr($this->fakeRoot, 0, strlen($defaultRoot) + 1) === $defaultRoot . '/';
 }
示例#5
0
 /**
  * move file to the trash bin
  *
  * @param string $file_path path to the deleted file/directory relative to the files root directory
  */
 public static function move2trash($file_path)
 {
     // get the user for which the filesystem is setup
     $root = Filesystem::getRoot();
     list(, $user) = explode('/', $root);
     $size = 0;
     list($owner, $ownerPath) = self::getUidAndFilename($file_path);
     $view = new \OC\Files\View('/' . $user);
     // file has been deleted in between
     if (!$view->file_exists('/files/' . $file_path)) {
         return true;
     }
     self::setUpTrash($user);
     if ($owner !== $user) {
         // also setup for owner
         self::setUpTrash($owner);
     }
     $path_parts = pathinfo($file_path);
     $filename = $path_parts['basename'];
     $location = $path_parts['dirname'];
     $timestamp = time();
     $userTrashSize = self::getTrashbinSize($user);
     // disable proxy to prevent recursive calls
     $trashPath = '/files_trashbin/files/' . $filename . '.d' . $timestamp;
     /** @var \OC\Files\Storage\Storage $trashStorage */
     list($trashStorage, $trashInternalPath) = $view->resolvePath($trashPath);
     /** @var \OC\Files\Storage\Storage $sourceStorage */
     list($sourceStorage, $sourceInternalPath) = $view->resolvePath('/files/' . $file_path);
     try {
         $sizeOfAddedFiles = $sourceStorage->filesize($sourceInternalPath);
         if ($trashStorage->file_exists($trashInternalPath)) {
             $trashStorage->unlink($trashInternalPath);
         }
         $trashStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $trashInternalPath);
     } catch (\OCA\Files_Trashbin\Exceptions\CopyRecursiveException $e) {
         $sizeOfAddedFiles = false;
         if ($trashStorage->file_exists($trashInternalPath)) {
             $trashStorage->unlink($trashInternalPath);
         }
         \OCP\Util::writeLog('files_trashbin', 'Couldn\'t move ' . $file_path . ' to the trash bin', \OC_log::ERROR);
     }
     if ($sourceStorage->file_exists($sourceInternalPath)) {
         // failed to delete the original file, abort
         $sourceStorage->unlink($sourceInternalPath);
         return false;
     }
     $view->getUpdater()->rename('/files/' . $file_path, $trashPath);
     if ($sizeOfAddedFiles !== false) {
         $size = $sizeOfAddedFiles;
         $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)");
         $result = $query->execute(array($filename, $timestamp, $location, $user));
         if (!$result) {
             \OCP\Util::writeLog('files_trashbin', 'trash bin database couldn\'t be updated', \OC_log::ERROR);
         }
         \OCP\Util::emitHook('\\OCA\\Files_Trashbin\\Trashbin', 'post_moveToTrash', array('filePath' => \OC\Files\Filesystem::normalizePath($file_path), 'trashPath' => \OC\Files\Filesystem::normalizePath($filename . '.d' . $timestamp)));
         $size += self::retainVersions($file_path, $filename, $owner, $ownerPath, $timestamp);
         // if owner !== user we need to also add a copy to the owners trash
         if ($user !== $owner) {
             self::copyFilesToOwner($file_path, $owner, $ownerPath, $timestamp);
         }
     }
     $userTrashSize += $size;
     self::scheduleExpire($userTrashSize, $user);
     // if owner !== user we also need to update the owners trash size
     if ($owner !== $user) {
         $ownerTrashSize = self::getTrashbinSize($owner);
         $ownerTrashSize += $size;
         self::scheduleExpire($ownerTrashSize, $owner);
     }
     return $sizeOfAddedFiles === false ? false : true;
 }
示例#6
0
    /**
     * 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)
     * @param bool TODO (optional)
     * @prams bool check expire date
     * @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, $checkExpireDate = true)
    {
        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') {
            if (!is_null($uidOwner)) {
                $root = \OC\Files\Filesystem::getRoot();
            } else {
                $root = '';
            }
            $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 (\OC_Appconfig::getValue('core', 'shareapi_allow_links', 'yes') !== 'yes') {
            $where .= ' AND `share_type` != ?';
            $queryArgs[] = self::SHARE_TYPE_LINK;
        }
        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`, `item_source`, `*PREFIX*share`.`parent`,' . ' `share_type`, `file_source`, `path`, `expiration`, `storage`, `share_with`, `mail_send`, `uid_owner`';
            } else {
                $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `expiration`, `mail_send`, `uid_owner`';
            }
        } else {
            if (isset($uidOwner)) {
                if ($itemType == 'file' || $itemType == 'folder') {
                    $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`,' . ' `share_type`, `share_with`, `file_source`, `path`, `permissions`, `stime`,' . ' `expiration`, `token`, `storage`, `mail_send`, `uid_owner`';
                } else {
                    $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `permissions`,' . ' `stime`, `file_source`, `expiration`, `token`, `mail_send`, `uid_owner`';
                }
            } 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`, `item_source`, `*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`, `unencrypted_size`, `encrypted`, `etag`, `mail_send`';
                    } 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`, `mail_send`';
                    }
                } 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'])) {
                    // FIXME: Doesn't always construct the correct path, example:
                    // Folder '/a/b', share '/a' and '/a/b' to user2
                    // user2 reshares /Shared/b and ask for share status of /Shared/a/b
                    // expected result: path=/Shared/a/b; actual result /Shared/b because of the parent
                    $query = \OC_DB::prepare('SELECT `file_target` FROM `*PREFIX*share` WHERE `id` = ?');
                    $parentResult = $query->execute(array($row['parent']));
                    if (\OC_DB::isError($result)) {
                        \OC_Log::write('OCP\\Share', 'Can\'t select parent: ' . \OC_DB::getErrorMessage($result) . ', select=' . $select . ' where=' . $where, \OC_Log::ERROR);
                    } else {
                        $parentRow = $parentResult->fetchRow();
                        $tmpPath = '/Shared' . $parentRow['file_target'];
                        // find the right position where the row path continues from the target path
                        $pos = strrpos($row['path'], $parentRow['file_target']);
                        $subPath = substr($row['path'], $pos);
                        $splitPath = explode('/', $subPath);
                        foreach (array_slice($splitPath, 2) as $pathPart) {
                            $tmpPath = $tmpPath . '/' . $pathPart;
                        }
                        $row['path'] = $tmpPath;
                    }
                } else {
                    if (!isset($mounts[$row['storage']])) {
                        $mountPoints = \OC\Files\Filesystem::getMountByNumericId($row['storage']);
                        if (is_array($mountPoints)) {
                            $mounts[$row['storage']] = current($mountPoints);
                        }
                    }
                    if ($mounts[$row['storage']]) {
                        $path = $mounts[$row['storage']]->getMountPoint() . $row['path'];
                        $row['path'] = substr($path, $root);
                    }
                }
            }
            if ($checkExpireDate) {
                if (self::expireItem($row)) {
                    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();
    }
示例#7
0
 /**
  * move file to the trash bin
  *
  * @param string $file_path path to the deleted file/directory relative to the files root directory
  */
 public static function move2trash($file_path)
 {
     // get the user for which the filesystem is setup
     $root = Filesystem::getRoot();
     list(, $user) = explode('/', $root);
     $size = 0;
     list($owner, $ownerPath) = self::getUidAndFilename($file_path);
     // file has been deleted in between
     if (empty($ownerPath)) {
         return false;
     }
     self::setUpTrash($user);
     $view = new \OC\Files\View('/' . $user);
     $path_parts = pathinfo($file_path);
     $filename = $path_parts['basename'];
     $location = $path_parts['dirname'];
     $timestamp = time();
     $userTrashSize = self::getTrashbinSize($user);
     // disable proxy to prevent recursive calls
     $proxyStatus = \OC_FileProxy::$enabled;
     \OC_FileProxy::$enabled = false;
     $trashPath = '/files_trashbin/files/' . $filename . '.d' . $timestamp;
     try {
         $sizeOfAddedFiles = self::copy_recursive('/files/' . $file_path, $trashPath, $view);
     } catch (\OCA\Files_Trashbin\Exceptions\CopyRecursiveException $e) {
         $sizeOfAddedFiles = false;
         if ($view->file_exists($trashPath)) {
             $view->deleteAll($trashPath);
         }
         \OC_Log::write('files_trashbin', 'Couldn\'t move ' . $file_path . ' to the trash bin', \OC_log::ERROR);
     }
     \OC_FileProxy::$enabled = $proxyStatus;
     if ($sizeOfAddedFiles !== false) {
         $size = $sizeOfAddedFiles;
         $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)");
         $result = $query->execute(array($filename, $timestamp, $location, $user));
         if (!$result) {
             \OC_Log::write('files_trashbin', 'trash bin database couldn\'t be updated', \OC_log::ERROR);
         }
         \OCP\Util::emitHook('\\OCA\\Files_Trashbin\\Trashbin', 'post_moveToTrash', array('filePath' => \OC\Files\Filesystem::normalizePath($file_path), 'trashPath' => \OC\Files\Filesystem::normalizePath($filename . '.d' . $timestamp)));
         $size += self::retainVersions($file_path, $filename, $timestamp);
         $size += self::retainEncryptionKeys($file_path, $filename, $timestamp);
         // if owner !== user we need to also add a copy to the owners trash
         if ($user !== $owner) {
             self::copyFilesToOwner($file_path, $owner, $ownerPath, $timestamp);
         }
     }
     $userTrashSize += $size;
     $userTrashSize -= self::expire($userTrashSize, $user);
     // if owner !== user we also need to update the owners trash size
     if ($owner !== $user) {
         $ownerTrashSize = self::getTrashbinSize($owner);
         $ownerTrashSize += $size;
         $ownerTrashSize -= self::expire($ownerTrashSize, $owner);
     }
 }
示例#8
0
	private function shouldEmitHooks($path = '') {
		if ($path && Cache\Scanner::isPartialFile($path)) {
			return false;
		}
		if (!Filesystem::$loaded) {
			return false;
		}
		$defaultRoot = Filesystem::getRoot();
		if ($defaultRoot === null) {
			return false;
		}
		if ($this->fakeRoot === $defaultRoot) {
			return true;
		}
		$fullPath = $this->getAbsolutePath($path);
		return (strlen($fullPath) > strlen($defaultRoot)) && (substr($fullPath, 0, strlen($defaultRoot) + 1) === $defaultRoot . '/');
	}
示例#9
0
 /**
  * @brief get the relative path of the root data directory for the current user
  * @return string
  *
  * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem
  * Returns path like /admin/files
  */
 public static function getRoot()
 {
     return \OC\Files\Filesystem::getRoot();
 }