/** * Copies a file or directory. * * This method must work recursively and delete the destination * if it exists * * @param string $source * @param string $destination * @throws \Sabre\DAV\Exception\ServiceUnavailable * @return void */ public function copy($source, $destination) { if (!$this->fileView) { throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup'); } // this will trigger existence check $this->getNodeForPath($source); list($destinationDir, $destinationName) = \Sabre\HTTP\URLUtil::splitPath($destination); try { $this->fileView->verifyPath($destinationDir, $destinationName); } catch (\OCP\Files\InvalidPathException $ex) { throw new InvalidPath($ex->getMessage()); } // Webdav's copy will implicitly do a delete+create, so only create+delete permissions are required if (!$this->fileView->isCreatable($destinationDir)) { throw new \Sabre\DAV\Exception\Forbidden(); } try { $this->fileView->copy($source, $destination); } catch (StorageNotAvailableException $e) { throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); } catch (ForbiddenException $ex) { throw new Forbidden($ex->getMessage(), $ex->getRetry()); } catch (LockedException $e) { throw new FileLocked($e->getMessage(), $e->getCode(), $e); } list($destinationDir, ) = \Sabre\HTTP\URLUtil::splitPath($destination); $this->markDirty($destinationDir); }
/** * Moves a file from one location to another * * @param string $sourcePath The path to the file which should be moved * @param string $destinationPath The full destination path, so not just the destination parent node * @throws \Sabre\DAV\Exception\BadRequest * @throws \Sabre\DAV\Exception\ServiceUnavailable * @throws \Sabre\DAV\Exception\Forbidden * @return int */ public function move($sourcePath, $destinationPath) { if (!$this->fileView) { throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup'); } $targetNodeExists = $this->nodeExists($destinationPath); $sourceNode = $this->getNodeForPath($sourcePath); if ($sourceNode instanceof \Sabre\DAV\ICollection && $targetNodeExists) { throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode->getName() . ', target exists'); } list($sourceDir, ) = \Sabre\HTTP\URLUtil::splitPath($sourcePath); list($destinationDir, ) = \Sabre\HTTP\URLUtil::splitPath($destinationPath); $isMovableMount = false; $sourceMount = $this->mountManager->find($this->fileView->getAbsolutePath($sourcePath)); $internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath)); if ($sourceMount instanceof MoveableMount && $internalPath === '') { $isMovableMount = true; } try { $sameFolder = $sourceDir === $destinationDir; // if we're overwriting or same folder if ($targetNodeExists || $sameFolder) { // note that renaming a share mount point is always allowed if (!$this->fileView->isUpdatable($destinationDir) && !$isMovableMount) { throw new \Sabre\DAV\Exception\Forbidden(); } } else { if (!$this->fileView->isCreatable($destinationDir)) { throw new \Sabre\DAV\Exception\Forbidden(); } } if (!$sameFolder) { // moving to a different folder, source will be gone, like a deletion // note that moving a share mount point is always allowed if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) { throw new \Sabre\DAV\Exception\Forbidden(); } } $fileName = basename($destinationPath); try { $this->fileView->verifyPath($destinationDir, $fileName); } catch (\OCP\Files\InvalidPathException $ex) { throw new InvalidPath($ex->getMessage()); } $renameOkay = $this->fileView->rename($sourcePath, $destinationPath); if (!$renameOkay) { throw new \Sabre\DAV\Exception\Forbidden(''); } } catch (StorageNotAvailableException $e) { throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); } catch (ForbiddenException $ex) { throw new Forbidden($ex->getMessage(), $ex->getRetry()); } catch (LockedException $e) { throw new FileLocked($e->getMessage(), $e->getCode(), $e); } $this->markDirty($sourceDir); $this->markDirty($destinationDir); }
/** * Moves a file from one location to another * * @param string $sourcePath The path to the file which should be moved * @param string $destinationPath The full destination path, so not just the destination parent node * @throws \Sabre\DAV\Exception\BadRequest * @throws \Sabre\DAV\Exception\ServiceUnavailable * @throws \Sabre\DAV\Exception\Forbidden * @return int */ public function move($sourcePath, $destinationPath) { if (!$this->fileView) { throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup'); } $targetNodeExists = $this->nodeExists($destinationPath); $sourceNode = $this->getNodeForPath($sourcePath); if ($sourceNode instanceof \Sabre\DAV\ICollection && $targetNodeExists) { throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode . ', target exists'); } list($sourceDir, ) = \Sabre\DAV\URLUtil::splitPath($sourcePath); list($destinationDir, ) = \Sabre\DAV\URLUtil::splitPath($destinationPath); $isMovableMount = false; $sourceMount = $this->mountManager->find($this->fileView->getAbsolutePath($sourcePath)); $internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath)); if ($sourceMount instanceof MoveableMount && $internalPath === '') { $isMovableMount = true; } try { $sameFolder = $sourceDir === $destinationDir; // if we're overwriting or same folder if ($targetNodeExists || $sameFolder) { // note that renaming a share mount point is always allowed if (!$this->fileView->isUpdatable($destinationDir) && !$isMovableMount) { throw new \Sabre\DAV\Exception\Forbidden(); } } else { if (!$this->fileView->isCreatable($destinationDir)) { throw new \Sabre\DAV\Exception\Forbidden(); } } if (!$sameFolder) { // moving to a different folder, source will be gone, like a deletion // note that moving a share mount point is always allowed if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) { throw new \Sabre\DAV\Exception\Forbidden(); } } $fileName = basename($destinationPath); if (!\OCP\Util::isValidFileName($fileName)) { throw new \Sabre\DAV\Exception\BadRequest(); } $renameOkay = $this->fileView->rename($sourcePath, $destinationPath); if (!$renameOkay) { throw new \Sabre\DAV\Exception\Forbidden(''); } } catch (\OCP\Files\StorageNotAvailableException $e) { throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); } // update properties $query = \OC_DB::prepare('UPDATE `*PREFIX*properties` SET `propertypath` = ?' . ' WHERE `userid` = ? AND `propertypath` = ?'); $query->execute(array(\OC\Files\Filesystem::normalizePath($destinationPath), \OC_User::getUser(), \OC\Files\Filesystem::normalizePath($sourcePath))); $this->markDirty($sourceDir); $this->markDirty($destinationDir); }
/** * Moves a file from one location to another * * @param string $sourcePath The path to the file which should be moved * @param string $destinationPath The full destination path, so not just the destination parent node * @throws \Sabre\DAV\Exception\BadRequest * @throws \Sabre\DAV\Exception\ServiceUnavailable * @throws \Sabre\DAV\Exception\Forbidden * @return int */ public function move($sourcePath, $destinationPath) { if (!$this->fileView) { throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup'); } $sourceNode = $this->getNodeForPath($sourcePath); if ($sourceNode instanceof \Sabre\DAV\ICollection and $this->nodeExists($destinationPath)) { throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode . ', target exists'); } list($sourceDir, ) = \Sabre\DAV\URLUtil::splitPath($sourcePath); list($destinationDir, ) = \Sabre\DAV\URLUtil::splitPath($destinationPath); $isMovableMount = false; $sourceMount = $this->mountManager->find($this->fileView->getAbsolutePath($sourcePath)); $internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath)); if ($sourceMount instanceof MoveableMount && $internalPath === '') { $isMovableMount = true; } try { // check update privileges if (!$this->fileView->isUpdatable($sourcePath) && !$isMovableMount) { throw new \Sabre\DAV\Exception\Forbidden(); } if ($sourceDir !== $destinationDir) { if (!$this->fileView->isCreatable($destinationDir)) { throw new \Sabre\DAV\Exception\Forbidden(); } if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) { throw new \Sabre\DAV\Exception\Forbidden(); } } $fileName = basename($destinationPath); if (!\OCP\Util::isValidFileName($fileName)) { throw new \Sabre\DAV\Exception\BadRequest(); } $renameOkay = $this->fileView->rename($sourcePath, $destinationPath); if (!$renameOkay) { throw new \Sabre\DAV\Exception\Forbidden(''); } } catch (\OCP\Files\StorageNotAvailableException $e) { throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); } // update properties $query = \OC_DB::prepare('UPDATE `*PREFIX*properties` SET `propertypath` = ?' . ' WHERE `userid` = ? AND `propertypath` = ?'); $query->execute(array(\OC\Files\Filesystem::normalizePath($destinationPath), \OC_User::getUser(), \OC\Files\Filesystem::normalizePath($sourcePath))); $this->markDirty($sourceDir); $this->markDirty($destinationDir); }
/** * Restore a file or folder from trash bin * * @param string $file path to the deleted file/folder relative to "files_trashbin/files/", * including the timestamp suffix ".d12345678" * @param string $filename name of the file/folder * @param int $timestamp time when the file/folder was deleted * * @return bool true on success, false otherwise */ public static function restore($file, $filename, $timestamp) { $user = \OCP\User::getUser(); $view = new \OC\Files\View('/' . $user); $location = ''; if ($timestamp) { $location = self::getLocation($user, $filename, $timestamp); if ($location === false) { \OCP\Util::writeLog('files_trashbin', 'trash bin database inconsistent!', \OCP\Util::ERROR); } else { // if location no longer exists, restore file in the root directory if ($location !== '/' && (!$view->is_dir('files/' . $location) || !$view->isCreatable('files/' . $location))) { $location = ''; } } } // we need a extension in case a file/dir with the same name already exists $uniqueFilename = self::getUniqueFilename($location, $filename, $view); $source = \OC\Files\Filesystem::normalizePath('files_trashbin/files/' . $file); $target = \OC\Files\Filesystem::normalizePath('files/' . $location . '/' . $uniqueFilename); if (!$view->file_exists($source)) { return false; } $mtime = $view->filemtime($source); // restore file $restoreResult = $view->rename($source, $target); // handle the restore result if ($restoreResult) { $fakeRoot = $view->getRoot(); $view->chroot('/' . $user . '/files'); $view->touch('/' . $location . '/' . $uniqueFilename, $mtime); $view->chroot($fakeRoot); \OCP\Util::emitHook('\\OCA\\Files_Trashbin\\Trashbin', 'post_restore', array('filePath' => \OC\Files\Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename), 'trashPath' => \OC\Files\Filesystem::normalizePath($file))); self::restoreVersions($view, $file, $filename, $uniqueFilename, $location, $timestamp); if ($timestamp) { $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=? AND `id`=? AND `timestamp`=?'); $query->execute(array($user, $filename, $timestamp)); } return true; } return false; }
public static function isCreatable($path) { return self::$defaultInstance->isCreatable($path); }