Completed
Push — master ( ee0653...876238 )
by Morris
52:35 queued 21:55
created

ChunkingPlugin::performMove()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 2
nop 2
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Thomas Müller <[email protected]>
4
 *
5
 * @copyright Copyright (c) 2017, ownCloud GmbH
6
 * @license AGPL-3.0
7
 *
8
 * This code is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License, version 3,
10
 * as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License, version 3,
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
19
 *
20
 */
21
22
23
namespace OCA\DAV\Upload;
24
25
26
use OCA\DAV\Connector\Sabre\File;
27
use Sabre\DAV\Exception\BadRequest;
28
use Sabre\DAV\Server;
29
use Sabre\DAV\ServerPlugin;
30
31
class ChunkingPlugin extends ServerPlugin {
32
33
	/** @var Server */
34
	private $server;
35
	/** @var FutureFile */
36
	private $sourceNode;
37
38
	/**
39
	 * @inheritdoc
40
	 */
41
	function initialize(Server $server) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
42
		$server->on('beforeMove', [$this, 'beforeMove']);
43
		$this->server = $server;
44
	}
45
46
	/**
47
	 * @param string $sourcePath source path
48
	 * @param string $destination destination path
49
	 */
50
	function beforeMove($sourcePath, $destination) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
51
		$this->sourceNode = $this->server->tree->getNodeForPath($sourcePath);
52
		if (!$this->sourceNode instanceof FutureFile) {
53
			// skip handling as the source is not a chunked FutureFile
54
			return;
55
		}
56
57
		$this->verifySize();
58
		return $this->performMove($sourcePath, $destination);
59
	}
60
61
	/**
62
	 * Move handler for future file.
63
	 *
64
	 * This overrides the default move behavior to prevent Sabre
65
	 * to delete the target file before moving. Because deleting would
66
	 * lose the file id and metadata.
67
	 *
68
	 * @param string $path source path
69
	 * @param string $destination destination path
70
	 * @return bool|void false to stop handling, void to skip this handler
71
	 */
72
	public function performMove($path, $destination) {
73
		if (!$this->server->tree->nodeExists($destination)) {
74
			// skip and let the default handler do its work
75
			return;
76
		}
77
78
		// do a move manually, skipping Sabre's default "delete" for existing nodes
79
		$this->server->tree->move($path, $destination);
80
81
		// trigger all default events (copied from CorePlugin::move)
82
		$this->server->emit('afterMove', [$path, $destination]);
83
		$this->server->emit('afterUnbind', [$path]);
84
		$this->server->emit('afterBind', [$destination]);
85
86
		$response = $this->server->httpResponse;
87
		$response->setHeader('Content-Length', '0');
88
		$response->setStatus(204);
89
90
		return false;
91
	}
92
93
	/**
94
	 * @throws BadRequest
95
	 */
96
	private function verifySize() {
97
		$expectedSize = $this->server->httpRequest->getHeader('OC-Total-Length');
98
		if ($expectedSize === null) {
99
			return;
100
		}
101
		$actualSize = $this->sourceNode->getSize();
102
		if ((int)$expectedSize !== $actualSize) {
103
			throw new BadRequest("Chunks on server do not sum up to $expectedSize but to $actualSize bytes");
104
		}
105
	}
106
}
107