summaryrefslogtreecommitdiffstats
path: root/apps/dav/lib/Upload
diff options
context:
space:
mode:
authorThomas Müller <thomas.mueller@tmit.eu>2017-07-31 22:46:19 +0200
committerDaniel Calviño Sánchez <danxuliu@gmail.com>2017-12-15 14:46:36 +0100
commit8c5d656f3b605a8cedbf412b7498b936e12866e6 (patch)
treef6d87ef4c5d7240ec03107856428e5c452be1a82 /apps/dav/lib/Upload
parentb19b1379699cf7790a13575f27a05b2f6db14f6a (diff)
downloadnextcloud-server-8c5d656f3b605a8cedbf412b7498b936e12866e6.tar.gz
nextcloud-server-8c5d656f3b605a8cedbf412b7498b936e12866e6.zip
Handle OC-Total-Length in new chunking
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Diffstat (limited to 'apps/dav/lib/Upload')
-rw-r--r--apps/dav/lib/Upload/ChunkingPlugin.php106
1 files changed, 106 insertions, 0 deletions
diff --git a/apps/dav/lib/Upload/ChunkingPlugin.php b/apps/dav/lib/Upload/ChunkingPlugin.php
new file mode 100644
index 00000000000..5768f53c2b4
--- /dev/null
+++ b/apps/dav/lib/Upload/ChunkingPlugin.php
@@ -0,0 +1,106 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+namespace OCA\DAV\Upload;
+
+
+use OCA\DAV\Connector\Sabre\File;
+use Sabre\DAV\Exception\BadRequest;
+use Sabre\DAV\Server;
+use Sabre\DAV\ServerPlugin;
+
+class ChunkingPlugin extends ServerPlugin {
+
+ /** @var Server */
+ private $server;
+ /** @var FutureFile */
+ private $sourceNode;
+
+ /**
+ * @inheritdoc
+ */
+ function initialize(Server $server) {
+ $server->on('beforeMove', [$this, 'beforeMove']);
+ $this->server = $server;
+ }
+
+ /**
+ * @param string $sourcePath source path
+ * @param string $destination destination path
+ */
+ function beforeMove($sourcePath, $destination) {
+ $this->sourceNode = $this->server->tree->getNodeForPath($sourcePath);
+ if (!$this->sourceNode instanceof FutureFile) {
+ // skip handling as the source is not a chunked FutureFile
+ return;
+ }
+
+ $this->verifySize();
+ return $this->performMove($sourcePath, $destination);
+ }
+
+ /**
+ * Move handler for future file.
+ *
+ * This overrides the default move behavior to prevent Sabre
+ * to delete the target file before moving. Because deleting would
+ * lose the file id and metadata.
+ *
+ * @param string $path source path
+ * @param string $destination destination path
+ * @return bool|void false to stop handling, void to skip this handler
+ */
+ public function performMove($path, $destination) {
+ if (!$this->server->tree->nodeExists($destination)) {
+ // skip and let the default handler do its work
+ return;
+ }
+
+ // do a move manually, skipping Sabre's default "delete" for existing nodes
+ $this->server->tree->move($path, $destination);
+
+ // trigger all default events (copied from CorePlugin::move)
+ $this->server->emit('afterMove', [$path, $destination]);
+ $this->server->emit('afterUnbind', [$path]);
+ $this->server->emit('afterBind', [$destination]);
+
+ $response = $this->server->httpResponse;
+ $response->setHeader('Content-Length', '0');
+ $response->setStatus(204);
+
+ return false;
+ }
+
+ /**
+ * @throws BadRequest
+ */
+ private function verifySize() {
+ $expectedSize = $this->server->httpRequest->getHeader('OC-Total-Length');
+ if ($expectedSize === null) {
+ return;
+ }
+ $actualSize = $this->sourceNode->getSize();
+ if ((int)$expectedSize !== $actualSize) {
+ throw new BadRequest("Chunks on server do not sum up to $expectedSize but to $actualSize bytes");
+ }
+ }
+}