Ported ObjectTree::move to IMoveTarget in new DAV endpoint

This commit is contained in:
Vincent Petry 2017-03-29 11:04:27 +02:00 committed by Joas Schilling
parent a761d4cce7
commit 0a9f7730d0
No known key found for this signature in database
GPG Key ID: E166FD8976B3BAC8
1 changed files with 110 additions and 4 deletions

View File

@ -34,12 +34,18 @@ use OCA\DAV\Connector\Sabre\Exception\Forbidden;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
use OCA\DAV\Connector\Sabre\Exception\FileLocked;
use OCP\Files\ForbiddenException;
use OCP\Files\InvalidPathException;
use OCP\Files\StorageNotAvailableException;
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
use Sabre\DAV\Exception\Locked;
use Sabre\DAV\Exception\ServiceUnavailable;
use Sabre\DAV\INode;
use Sabre\DAV\Exception\BadRequest;
use OC\Files\Mount\MoveableMount;
class Directory extends \OCA\DAV\Connector\Sabre\Node
implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota {
implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota, \Sabre\DAV\IMoveTarget {
/**
* Cached directory content
@ -137,7 +143,7 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node
return $node->put($data);
} catch (\OCP\Files\StorageNotAvailableException $e) {
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
} catch (\OCP\Files\InvalidPathException $ex) {
} catch (InvalidPathException $ex) {
throw new InvalidPath($ex->getMessage());
} catch (ForbiddenException $ex) {
throw new Forbidden($ex->getMessage(), $ex->getRetry());
@ -168,7 +174,7 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node
}
} catch (\OCP\Files\StorageNotAvailableException $e) {
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
} catch (\OCP\Files\InvalidPathException $ex) {
} catch (InvalidPathException $ex) {
throw new InvalidPath($ex->getMessage());
} catch (ForbiddenException $ex) {
throw new Forbidden($ex->getMessage(), $ex->getRetry());
@ -195,7 +201,7 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node
$info = $this->fileView->getFileInfo($path);
} catch (\OCP\Files\StorageNotAvailableException $e) {
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
} catch (\OCP\Files\InvalidPathException $ex) {
} catch (InvalidPathException $ex) {
throw new InvalidPath($ex->getMessage());
} catch (ForbiddenException $e) {
throw new \Sabre\DAV\Exception\Forbidden();
@ -311,4 +317,104 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node
}
}
/**
* Moves a node into this collection.
*
* It is up to the implementors to:
* 1. Create the new resource.
* 2. Remove the old resource.
* 3. Transfer any properties or other data.
*
* Generally you should make very sure that your collection can easily move
* the move.
*
* If you don't, just return false, which will trigger sabre/dav to handle
* the move itself. If you return true from this function, the assumption
* is that the move was successful.
*
* @param string $targetName New local file/collection name.
* @param string $fullSourcePath Full path to source node
* @param INode $sourceNode Source node itself
* @return bool
* @throws BadRequest
* @throws ServiceUnavailable
* @throws Forbidden
* @throws FileLocked
* @throws \Sabre\DAV\Exception\Forbidden
*/
public function moveInto($targetName, $fullSourcePath, INode $sourceNode) {
if (!$sourceNode instanceof Node) {
throw new BadRequest('Incompatible node types');
}
if (!$this->fileView) {
throw new ServiceUnavailable('filesystem not setup');
}
$destinationPath = $this->getPath() . '/' . $targetName;
$targetNodeExists = $this->childExists($targetName);
// at getNodeForPath we also check the path for isForbiddenFileOrDir
// with that we have covered both source and destination
if ($sourceNode instanceof Directory && $targetNodeExists) {
throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode->getName() . ', target exists');
}
list($sourceDir,) = \Sabre\HTTP\URLUtil::splitPath($sourceNode->getPath());
$destinationDir = $this->getPath();
$sourcePath = $sourceNode->getPath();
$isMovableMount = false;
$sourceMount = \OC::$server->getMountManager()->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 (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 ServiceUnavailable($e->getMessage());
} catch (ForbiddenException $ex) {
throw new Forbidden($ex->getMessage(), $ex->getRetry());
} catch (LockedException $e) {
throw new FileLocked($e->getMessage(), $e->getCode(), $e);
}
return true;
}
}