From 52cdaa204f912bc58609555503ce6403fa995e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 19 Oct 2017 13:21:53 +0200 Subject: [PATCH] COPY does not delete the destination and by that allows to keep versions - related to #18307 but needs to be addressed for MOVE --- apps/dav/lib/Connector/Sabre/Node.php | 3 + apps/dav/lib/Connector/Sabre/Server.php | 3 + apps/dav/lib/DAV/CorePlugin.php | 88 +++++++++++++++++++++++++ apps/dav/lib/Files/ICopySource.php | 33 ++++++++++ 4 files changed, 127 insertions(+) create mode 100644 apps/dav/lib/DAV/CorePlugin.php create mode 100644 apps/dav/lib/Files/ICopySource.php diff --git a/apps/dav/lib/Connector/Sabre/Node.php b/apps/dav/lib/Connector/Sabre/Node.php index 79045907aef9..3d6d31e6ec53 100644 --- a/apps/dav/lib/Connector/Sabre/Node.php +++ b/apps/dav/lib/Connector/Sabre/Node.php @@ -384,6 +384,9 @@ public function changeLock($type) { $this->fileView->changeLock($this->path, $type); } + /** + * @return \OCP\Files\FileInfo + */ public function getFileInfo() { return $this->info; } diff --git a/apps/dav/lib/Connector/Sabre/Server.php b/apps/dav/lib/Connector/Sabre/Server.php index c01afff71c6b..4059f234f5f4 100644 --- a/apps/dav/lib/Connector/Sabre/Server.php +++ b/apps/dav/lib/Connector/Sabre/Server.php @@ -24,6 +24,8 @@ namespace OCA\DAV\Connector\Sabre; +use OCA\DAV\DAV\CorePlugin; + /** * Class \OCA\DAV\Connector\Sabre\Server * @@ -40,5 +42,6 @@ public function __construct($treeOrNode = null) { parent::__construct($treeOrNode); self::$exposeVersion = false; $this->enablePropfindDepthInfinity = true; + $this->addPlugin(new CorePlugin()); } } diff --git a/apps/dav/lib/DAV/CorePlugin.php b/apps/dav/lib/DAV/CorePlugin.php new file mode 100644 index 000000000000..364aa257162b --- /dev/null +++ b/apps/dav/lib/DAV/CorePlugin.php @@ -0,0 +1,88 @@ + + * + * @copyright Copyright (c) 2017, ownCloud GmbH + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + + +namespace OCA\DAV\DAV; + +use OCA\DAV\Connector\Sabre\File; +use OCA\DAV\Files\ICopySource; +use Sabre\DAV\IFile; +use Sabre\DAV\Server; +use Sabre\DAV\ServerPlugin; +use Sabre\HTTP\RequestInterface; +use Sabre\HTTP\ResponseInterface; + +class CorePlugin extends ServerPlugin { + + /** @var Server */ + private $server; + + /** + * @param Server $server + */ + function initialize(Server $server) { + $this->server = $server; + $server->on('method:COPY', [$this, 'httpCopy'], 90); + } + + /** + * WebDAV HTTP COPY method + * + * This method copies one uri to a different uri, and works much like the MOVE request + * A lot of the actual request processing is done in getCopyMoveInfo + * + * @param RequestInterface $request + * @param ResponseInterface $response + * @return bool + */ + function httpCopy(RequestInterface $request, ResponseInterface $response) { + + $path = $request->getPath(); + + $copyInfo = $this->server->getCopyAndMoveInfo($request); + $sourceNode = $this->server->tree->getNodeForPath($path); + $destinationNode = $copyInfo['destinationNode']; + if (!$copyInfo['destinationExists'] || !$destinationNode instanceof File || !$sourceNode instanceof IFile) { + return true; + } + + if (!$this->server->emit('beforeBind', [$copyInfo['destination']])) return false; + + $copySuccess = false; + if ($sourceNode instanceof ICopySource) { + $copySuccess = $sourceNode->copy($destinationNode->getFileInfo()->getPath()); + } + if (!$copySuccess) { + $destinationNode->put($sourceNode->get()); + } + + $this->server->emit('afterBind', [$copyInfo['destination']]); + + // If a resource was overwritten we should send a 204, otherwise a 201 + $response->setHeader('Content-Length', '0'); + $response->setStatus($copyInfo['destinationExists'] ? 204 : 201); + + // Sending back false will interrupt the event chain and tell the server + // we've handled this method. + return false; + } + +} diff --git a/apps/dav/lib/Files/ICopySource.php b/apps/dav/lib/Files/ICopySource.php new file mode 100644 index 000000000000..63dd96a4b705 --- /dev/null +++ b/apps/dav/lib/Files/ICopySource.php @@ -0,0 +1,33 @@ + + * + * @copyright Copyright (c) 2017, ownCloud GmbH + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + + +namespace OCA\DAV\Files; + + +interface ICopySource { + + /** + * @param string $destinationPath + * @return boolean + */ + public function copy($destinationPath); +}