Passed
Push — master ( 93e703...13ef47 )
by
unknown
14:27 queued 12s
created
apps/dav/lib/Connector/Sabre/QuotaPlugin.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -92,7 +92,7 @@  discard block
 block discarded – undo
92 92
 			return;
93 93
 		}
94 94
 
95
-		return $this->checkQuota($parent->getPath() . '/' . basename($uri));
95
+		return $this->checkQuota($parent->getPath().'/'.basename($uri));
96 96
 	}
97 97
 
98 98
 	/**
@@ -163,7 +163,7 @@  discard block
 block discarded – undo
163 163
 				// there is still enough space for the remaining chunks
164 164
 				$length -= $chunkHandler->getCurrentSize();
165 165
 				// use target file name for free space check in case of shared files
166
-				$path = rtrim($parentPath, '/') . '/' . $info['name'];
166
+				$path = rtrim($parentPath, '/').'/'.$info['name'];
167 167
 			}
168 168
 			$freeSpace = $this->getFreeSpace($path);
169 169
 			if ($freeSpace >= 0 && $length > $freeSpace) {
Please login to merge, or discard this patch.
Indentation   +203 added lines, -203 removed lines patch added patch discarded remove patch
@@ -44,207 +44,207 @@
 block discarded – undo
44 44
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
45 45
  */
46 46
 class QuotaPlugin extends \Sabre\DAV\ServerPlugin {
47
-	/** @var \OC\Files\View */
48
-	private $view;
49
-
50
-	/**
51
-	 * Reference to main server object
52
-	 *
53
-	 * @var \Sabre\DAV\Server
54
-	 */
55
-	private $server;
56
-
57
-	/**
58
-	 * @param \OC\Files\View $view
59
-	 */
60
-	public function __construct($view) {
61
-		$this->view = $view;
62
-	}
63
-
64
-	/**
65
-	 * This initializes the plugin.
66
-	 *
67
-	 * This function is called by \Sabre\DAV\Server, after
68
-	 * addPlugin is called.
69
-	 *
70
-	 * This method should set up the requires event subscriptions.
71
-	 *
72
-	 * @param \Sabre\DAV\Server $server
73
-	 * @return void
74
-	 */
75
-	public function initialize(\Sabre\DAV\Server $server) {
76
-		$this->server = $server;
77
-
78
-		$server->on('beforeWriteContent', [$this, 'beforeWriteContent'], 10);
79
-		$server->on('beforeCreateFile', [$this, 'beforeCreateFile'], 10);
80
-		$server->on('beforeMove', [$this, 'beforeMove'], 10);
81
-		$server->on('beforeCopy', [$this, 'beforeCopy'], 10);
82
-	}
83
-
84
-	/**
85
-	 * Check quota before creating file
86
-	 *
87
-	 * @param string $uri target file URI
88
-	 * @param resource $data data
89
-	 * @param INode $parent Sabre Node
90
-	 * @param bool $modified modified
91
-	 */
92
-	public function beforeCreateFile($uri, $data, INode $parent, $modified) {
93
-		if (!$parent instanceof Node) {
94
-			return;
95
-		}
96
-
97
-		return $this->checkQuota($parent->getPath() . '/' . basename($uri));
98
-	}
99
-
100
-	/**
101
-	 * Check quota before writing content
102
-	 *
103
-	 * @param string $uri target file URI
104
-	 * @param INode $node Sabre Node
105
-	 * @param resource $data data
106
-	 * @param bool $modified modified
107
-	 */
108
-	public function beforeWriteContent($uri, INode $node, $data, $modified) {
109
-		if (!$node instanceof Node) {
110
-			return;
111
-		}
112
-
113
-		return $this->checkQuota($node->getPath());
114
-	}
115
-
116
-	/**
117
-	 * Check if we're moving a Futurefile in which case we need to check
118
-	 * the quota on the target destination.
119
-	 *
120
-	 * @param string $source source path
121
-	 * @param string $destination destination path
122
-	 */
123
-	public function beforeMove($source, $destination) {
124
-		$sourceNode = $this->server->tree->getNodeForPath($source);
125
-		if (!$sourceNode instanceof FutureFile) {
126
-			return;
127
-		}
128
-
129
-		// get target node for proper path conversion
130
-		if ($this->server->tree->nodeExists($destination)) {
131
-			$destinationNode = $this->server->tree->getNodeForPath($destination);
132
-			$path = $destinationNode->getPath();
133
-		} else {
134
-			$parent = dirname($destination);
135
-			if ($parent === '.') {
136
-				$parent = '';
137
-			}
138
-			$parentNode = $this->server->tree->getNodeForPath($parent);
139
-			$path = $parentNode->getPath();
140
-		}
141
-
142
-		return $this->checkQuota($path, $sourceNode->getSize());
143
-	}
144
-
145
-	/**
146
-	 * Check quota on the target destination before a copy.
147
-	 */
148
-	public function beforeCopy(string $sourcePath, string $destinationPath): bool {
149
-		$sourceNode = $this->server->tree->getNodeForPath($sourcePath);
150
-		if (!$sourceNode instanceof Node) {
151
-			return true;
152
-		}
153
-
154
-		// get target node for proper path conversion
155
-		if ($this->server->tree->nodeExists($destinationPath)) {
156
-			$destinationNode = $this->server->tree->getNodeForPath($destinationPath);
157
-			if (!$destinationNode instanceof Node) {
158
-				return true;
159
-			}
160
-			$path = $destinationNode->getPath();
161
-		} else {
162
-			$parent = dirname($destinationPath);
163
-			if ($parent === '.') {
164
-				$parent = '';
165
-			}
166
-			$parentNode = $this->server->tree->getNodeForPath($parent);
167
-			if (!$parentNode instanceof Node) {
168
-				return true;
169
-			}
170
-			$path = $parentNode->getPath();
171
-		}
172
-
173
-		return $this->checkQuota($path, $sourceNode->getSize());
174
-	}
175
-
176
-
177
-	/**
178
-	 * This method is called before any HTTP method and validates there is enough free space to store the file
179
-	 *
180
-	 * @param string $path relative to the users home
181
-	 * @param int|float|null $length
182
-	 * @throws InsufficientStorage
183
-	 * @return bool
184
-	 */
185
-	public function checkQuota($path, $length = null) {
186
-		if ($length === null) {
187
-			$length = $this->getLength();
188
-		}
189
-
190
-		if ($length) {
191
-			[$parentPath, $newName] = \Sabre\Uri\split($path);
192
-			if (is_null($parentPath)) {
193
-				$parentPath = '';
194
-			}
195
-			$req = $this->server->httpRequest;
196
-			if ($req->getHeader('OC-Chunked')) {
197
-				$info = \OC_FileChunking::decodeName($newName);
198
-				$chunkHandler = $this->getFileChunking($info);
199
-				// subtract the already uploaded size to see whether
200
-				// there is still enough space for the remaining chunks
201
-				$length -= $chunkHandler->getCurrentSize();
202
-				// use target file name for free space check in case of shared files
203
-				$path = rtrim($parentPath, '/') . '/' . $info['name'];
204
-			}
205
-			$freeSpace = $this->getFreeSpace($path);
206
-			if ($freeSpace >= 0 && $length > $freeSpace) {
207
-				if (isset($chunkHandler)) {
208
-					$chunkHandler->cleanup();
209
-				}
210
-				throw new InsufficientStorage("Insufficient space in $path, $length required, $freeSpace available");
211
-			}
212
-		}
213
-		return true;
214
-	}
215
-
216
-	public function getFileChunking($info) {
217
-		// FIXME: need a factory for better mocking support
218
-		return new \OC_FileChunking($info);
219
-	}
220
-
221
-	public function getLength() {
222
-		$req = $this->server->httpRequest;
223
-		$length = $req->getHeader('X-Expected-Entity-Length');
224
-		if (!is_numeric($length)) {
225
-			$length = $req->getHeader('Content-Length');
226
-			$length = is_numeric($length) ? $length : null;
227
-		}
228
-
229
-		$ocLength = $req->getHeader('OC-Total-Length');
230
-		if (is_numeric($length) && is_numeric($ocLength)) {
231
-			return max($length, $ocLength);
232
-		}
233
-
234
-		return $length;
235
-	}
236
-
237
-	/**
238
-	 * @param string $uri
239
-	 * @return mixed
240
-	 * @throws ServiceUnavailable
241
-	 */
242
-	public function getFreeSpace($uri) {
243
-		try {
244
-			$freeSpace = $this->view->free_space(ltrim($uri, '/'));
245
-			return $freeSpace;
246
-		} catch (StorageNotAvailableException $e) {
247
-			throw new ServiceUnavailable($e->getMessage());
248
-		}
249
-	}
47
+    /** @var \OC\Files\View */
48
+    private $view;
49
+
50
+    /**
51
+     * Reference to main server object
52
+     *
53
+     * @var \Sabre\DAV\Server
54
+     */
55
+    private $server;
56
+
57
+    /**
58
+     * @param \OC\Files\View $view
59
+     */
60
+    public function __construct($view) {
61
+        $this->view = $view;
62
+    }
63
+
64
+    /**
65
+     * This initializes the plugin.
66
+     *
67
+     * This function is called by \Sabre\DAV\Server, after
68
+     * addPlugin is called.
69
+     *
70
+     * This method should set up the requires event subscriptions.
71
+     *
72
+     * @param \Sabre\DAV\Server $server
73
+     * @return void
74
+     */
75
+    public function initialize(\Sabre\DAV\Server $server) {
76
+        $this->server = $server;
77
+
78
+        $server->on('beforeWriteContent', [$this, 'beforeWriteContent'], 10);
79
+        $server->on('beforeCreateFile', [$this, 'beforeCreateFile'], 10);
80
+        $server->on('beforeMove', [$this, 'beforeMove'], 10);
81
+        $server->on('beforeCopy', [$this, 'beforeCopy'], 10);
82
+    }
83
+
84
+    /**
85
+     * Check quota before creating file
86
+     *
87
+     * @param string $uri target file URI
88
+     * @param resource $data data
89
+     * @param INode $parent Sabre Node
90
+     * @param bool $modified modified
91
+     */
92
+    public function beforeCreateFile($uri, $data, INode $parent, $modified) {
93
+        if (!$parent instanceof Node) {
94
+            return;
95
+        }
96
+
97
+        return $this->checkQuota($parent->getPath() . '/' . basename($uri));
98
+    }
99
+
100
+    /**
101
+     * Check quota before writing content
102
+     *
103
+     * @param string $uri target file URI
104
+     * @param INode $node Sabre Node
105
+     * @param resource $data data
106
+     * @param bool $modified modified
107
+     */
108
+    public function beforeWriteContent($uri, INode $node, $data, $modified) {
109
+        if (!$node instanceof Node) {
110
+            return;
111
+        }
112
+
113
+        return $this->checkQuota($node->getPath());
114
+    }
115
+
116
+    /**
117
+     * Check if we're moving a Futurefile in which case we need to check
118
+     * the quota on the target destination.
119
+     *
120
+     * @param string $source source path
121
+     * @param string $destination destination path
122
+     */
123
+    public function beforeMove($source, $destination) {
124
+        $sourceNode = $this->server->tree->getNodeForPath($source);
125
+        if (!$sourceNode instanceof FutureFile) {
126
+            return;
127
+        }
128
+
129
+        // get target node for proper path conversion
130
+        if ($this->server->tree->nodeExists($destination)) {
131
+            $destinationNode = $this->server->tree->getNodeForPath($destination);
132
+            $path = $destinationNode->getPath();
133
+        } else {
134
+            $parent = dirname($destination);
135
+            if ($parent === '.') {
136
+                $parent = '';
137
+            }
138
+            $parentNode = $this->server->tree->getNodeForPath($parent);
139
+            $path = $parentNode->getPath();
140
+        }
141
+
142
+        return $this->checkQuota($path, $sourceNode->getSize());
143
+    }
144
+
145
+    /**
146
+     * Check quota on the target destination before a copy.
147
+     */
148
+    public function beforeCopy(string $sourcePath, string $destinationPath): bool {
149
+        $sourceNode = $this->server->tree->getNodeForPath($sourcePath);
150
+        if (!$sourceNode instanceof Node) {
151
+            return true;
152
+        }
153
+
154
+        // get target node for proper path conversion
155
+        if ($this->server->tree->nodeExists($destinationPath)) {
156
+            $destinationNode = $this->server->tree->getNodeForPath($destinationPath);
157
+            if (!$destinationNode instanceof Node) {
158
+                return true;
159
+            }
160
+            $path = $destinationNode->getPath();
161
+        } else {
162
+            $parent = dirname($destinationPath);
163
+            if ($parent === '.') {
164
+                $parent = '';
165
+            }
166
+            $parentNode = $this->server->tree->getNodeForPath($parent);
167
+            if (!$parentNode instanceof Node) {
168
+                return true;
169
+            }
170
+            $path = $parentNode->getPath();
171
+        }
172
+
173
+        return $this->checkQuota($path, $sourceNode->getSize());
174
+    }
175
+
176
+
177
+    /**
178
+     * This method is called before any HTTP method and validates there is enough free space to store the file
179
+     *
180
+     * @param string $path relative to the users home
181
+     * @param int|float|null $length
182
+     * @throws InsufficientStorage
183
+     * @return bool
184
+     */
185
+    public function checkQuota($path, $length = null) {
186
+        if ($length === null) {
187
+            $length = $this->getLength();
188
+        }
189
+
190
+        if ($length) {
191
+            [$parentPath, $newName] = \Sabre\Uri\split($path);
192
+            if (is_null($parentPath)) {
193
+                $parentPath = '';
194
+            }
195
+            $req = $this->server->httpRequest;
196
+            if ($req->getHeader('OC-Chunked')) {
197
+                $info = \OC_FileChunking::decodeName($newName);
198
+                $chunkHandler = $this->getFileChunking($info);
199
+                // subtract the already uploaded size to see whether
200
+                // there is still enough space for the remaining chunks
201
+                $length -= $chunkHandler->getCurrentSize();
202
+                // use target file name for free space check in case of shared files
203
+                $path = rtrim($parentPath, '/') . '/' . $info['name'];
204
+            }
205
+            $freeSpace = $this->getFreeSpace($path);
206
+            if ($freeSpace >= 0 && $length > $freeSpace) {
207
+                if (isset($chunkHandler)) {
208
+                    $chunkHandler->cleanup();
209
+                }
210
+                throw new InsufficientStorage("Insufficient space in $path, $length required, $freeSpace available");
211
+            }
212
+        }
213
+        return true;
214
+    }
215
+
216
+    public function getFileChunking($info) {
217
+        // FIXME: need a factory for better mocking support
218
+        return new \OC_FileChunking($info);
219
+    }
220
+
221
+    public function getLength() {
222
+        $req = $this->server->httpRequest;
223
+        $length = $req->getHeader('X-Expected-Entity-Length');
224
+        if (!is_numeric($length)) {
225
+            $length = $req->getHeader('Content-Length');
226
+            $length = is_numeric($length) ? $length : null;
227
+        }
228
+
229
+        $ocLength = $req->getHeader('OC-Total-Length');
230
+        if (is_numeric($length) && is_numeric($ocLength)) {
231
+            return max($length, $ocLength);
232
+        }
233
+
234
+        return $length;
235
+    }
236
+
237
+    /**
238
+     * @param string $uri
239
+     * @return mixed
240
+     * @throws ServiceUnavailable
241
+     */
242
+    public function getFreeSpace($uri) {
243
+        try {
244
+            $freeSpace = $this->view->free_space(ltrim($uri, '/'));
245
+            return $freeSpace;
246
+        } catch (StorageNotAvailableException $e) {
247
+            throw new ServiceUnavailable($e->getMessage());
248
+        }
249
+    }
250 250
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/LockPlugin.php 1 patch
Indentation   +59 added lines, -59 removed lines patch added patch discarded remove patch
@@ -34,67 +34,67 @@
 block discarded – undo
34 34
 use Sabre\HTTP\RequestInterface;
35 35
 
36 36
 class LockPlugin extends ServerPlugin {
37
-	/**
38
-	 * Reference to main server object
39
-	 *
40
-	 * @var \Sabre\DAV\Server
41
-	 */
42
-	private $server;
37
+    /**
38
+     * Reference to main server object
39
+     *
40
+     * @var \Sabre\DAV\Server
41
+     */
42
+    private $server;
43 43
 
44
-	/**
45
-	 * State of the lock
46
-	 *
47
-	 * @var bool
48
-	 */
49
-	private $isLocked;
44
+    /**
45
+     * State of the lock
46
+     *
47
+     * @var bool
48
+     */
49
+    private $isLocked;
50 50
 
51
-	/**
52
-	 * {@inheritdoc}
53
-	 */
54
-	public function initialize(\Sabre\DAV\Server $server) {
55
-		$this->server = $server;
56
-		$this->server->on('beforeMethod:*', [$this, 'getLock'], 50);
57
-		$this->server->on('afterMethod:*', [$this, 'releaseLock'], 50);
58
-		$this->isLocked = false;
59
-	}
51
+    /**
52
+     * {@inheritdoc}
53
+     */
54
+    public function initialize(\Sabre\DAV\Server $server) {
55
+        $this->server = $server;
56
+        $this->server->on('beforeMethod:*', [$this, 'getLock'], 50);
57
+        $this->server->on('afterMethod:*', [$this, 'releaseLock'], 50);
58
+        $this->isLocked = false;
59
+    }
60 60
 
61
-	public function getLock(RequestInterface $request) {
62
-		// we can't listen on 'beforeMethod:PUT' due to order of operations with setting up the tree
63
-		// so instead we limit ourselves to the PUT method manually
64
-		if ($request->getMethod() !== 'PUT' || isset($_SERVER['HTTP_OC_CHUNKED'])) {
65
-			return;
66
-		}
67
-		try {
68
-			$node = $this->server->tree->getNodeForPath($request->getPath());
69
-		} catch (NotFound $e) {
70
-			return;
71
-		}
72
-		if ($node instanceof Node) {
73
-			try {
74
-				$node->acquireLock(ILockingProvider::LOCK_SHARED);
75
-			} catch (LockedException $e) {
76
-				throw new FileLocked($e->getMessage(), $e->getCode(), $e);
77
-			}
78
-			$this->isLocked = true;
79
-		}
80
-	}
61
+    public function getLock(RequestInterface $request) {
62
+        // we can't listen on 'beforeMethod:PUT' due to order of operations with setting up the tree
63
+        // so instead we limit ourselves to the PUT method manually
64
+        if ($request->getMethod() !== 'PUT' || isset($_SERVER['HTTP_OC_CHUNKED'])) {
65
+            return;
66
+        }
67
+        try {
68
+            $node = $this->server->tree->getNodeForPath($request->getPath());
69
+        } catch (NotFound $e) {
70
+            return;
71
+        }
72
+        if ($node instanceof Node) {
73
+            try {
74
+                $node->acquireLock(ILockingProvider::LOCK_SHARED);
75
+            } catch (LockedException $e) {
76
+                throw new FileLocked($e->getMessage(), $e->getCode(), $e);
77
+            }
78
+            $this->isLocked = true;
79
+        }
80
+    }
81 81
 
82
-	public function releaseLock(RequestInterface $request) {
83
-		// don't try to release the lock if we never locked one
84
-		if ($this->isLocked === false) {
85
-			return;
86
-		}
87
-		if ($request->getMethod() !== 'PUT' || isset($_SERVER['HTTP_OC_CHUNKED'])) {
88
-			return;
89
-		}
90
-		try {
91
-			$node = $this->server->tree->getNodeForPath($request->getPath());
92
-		} catch (NotFound $e) {
93
-			return;
94
-		}
95
-		if ($node instanceof Node) {
96
-			$node->releaseLock(ILockingProvider::LOCK_SHARED);
97
-			$this->isLocked = false;
98
-		}
99
-	}
82
+    public function releaseLock(RequestInterface $request) {
83
+        // don't try to release the lock if we never locked one
84
+        if ($this->isLocked === false) {
85
+            return;
86
+        }
87
+        if ($request->getMethod() !== 'PUT' || isset($_SERVER['HTTP_OC_CHUNKED'])) {
88
+            return;
89
+        }
90
+        try {
91
+            $node = $this->server->tree->getNodeForPath($request->getPath());
92
+        } catch (NotFound $e) {
93
+            return;
94
+        }
95
+        if ($node instanceof Node) {
96
+            $node->releaseLock(ILockingProvider::LOCK_SHARED);
97
+            $this->isLocked = false;
98
+        }
99
+    }
100 100
 }
Please login to merge, or discard this patch.
lib/private/legacy/OC_FileChunking.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -85,7 +85,7 @@
 block discarded – undo
85 85
 	public function isComplete() {
86 86
 		$prefix = $this->getPrefix();
87 87
 		$cache = $this->getCache();
88
-		$chunkcount = (int)$this->info['chunkcount'];
88
+		$chunkcount = (int) $this->info['chunkcount'];
89 89
 
90 90
 		for ($i = ($chunkcount - 1); $i >= 0; $i--) {
91 91
 			if (!$cache->hasKey($prefix.$i)) {
Please login to merge, or discard this patch.
Indentation   +152 added lines, -152 removed lines patch added patch discarded remove patch
@@ -29,156 +29,156 @@
 block discarded – undo
29 29
  *
30 30
  */
31 31
 class OC_FileChunking {
32
-	protected $info;
33
-	protected $cache;
34
-
35
-	/**
36
-	 * TTL of chunks
37
-	 *
38
-	 * @var int
39
-	 */
40
-	protected $ttl;
41
-
42
-	public static function decodeName($name) {
43
-		preg_match('/(?P<name>.*)-chunking-(?P<transferid>\d+)-(?P<chunkcount>\d+)-(?P<index>\d+)/', $name, $matches);
44
-		return $matches;
45
-	}
46
-
47
-	/**
48
-	 * @param string[] $info
49
-	 */
50
-	public function __construct($info) {
51
-		$this->info = $info;
52
-		$this->ttl = \OC::$server->getConfig()->getSystemValue('cache_chunk_gc_ttl', 86400);
53
-	}
54
-
55
-	public function getPrefix() {
56
-		$name = $this->info['name'];
57
-		$transferid = $this->info['transferid'];
58
-
59
-		return $name.'-chunking-'.$transferid.'-';
60
-	}
61
-
62
-	protected function getCache() {
63
-		if (!isset($this->cache)) {
64
-			$this->cache = new \OC\Cache\File();
65
-		}
66
-		return $this->cache;
67
-	}
68
-
69
-	/**
70
-	 * Stores the given $data under the given $key - the number of stored bytes is returned
71
-	 *
72
-	 * @param string $index
73
-	 * @param resource $data
74
-	 * @return int
75
-	 */
76
-	public function store($index, $data) {
77
-		$cache = $this->getCache();
78
-		$name = $this->getPrefix().$index;
79
-		$cache->set($name, $data, $this->ttl);
80
-
81
-		return $cache->size($name);
82
-	}
83
-
84
-	public function isComplete() {
85
-		$prefix = $this->getPrefix();
86
-		$cache = $this->getCache();
87
-		$chunkcount = (int)$this->info['chunkcount'];
88
-
89
-		for ($i = ($chunkcount - 1); $i >= 0; $i--) {
90
-			if (!$cache->hasKey($prefix.$i)) {
91
-				return false;
92
-			}
93
-		}
94
-
95
-		return true;
96
-	}
97
-
98
-	/**
99
-	 * Assembles the chunks into the file specified by the path.
100
-	 * Chunks are deleted afterwards.
101
-	 *
102
-	 * @param resource $f target path
103
-	 *
104
-	 * @return integer assembled file size
105
-	 *
106
-	 * @throws \OC\InsufficientStorageException when file could not be fully
107
-	 * assembled due to lack of free space
108
-	 */
109
-	public function assemble($f) {
110
-		$cache = $this->getCache();
111
-		$prefix = $this->getPrefix();
112
-		$count = 0;
113
-		for ($i = 0; $i < $this->info['chunkcount']; $i++) {
114
-			$chunk = $cache->get($prefix.$i);
115
-			// remove after reading to directly save space
116
-			$cache->remove($prefix.$i);
117
-			$count += fwrite($f, $chunk);
118
-			// let php release the memory to work around memory exhausted error with php 5.6
119
-			$chunk = null;
120
-		}
121
-
122
-		return $count;
123
-	}
124
-
125
-	/**
126
-	 * Returns the size of the chunks already present
127
-	 * @return integer size in bytes
128
-	 */
129
-	public function getCurrentSize() {
130
-		$cache = $this->getCache();
131
-		$prefix = $this->getPrefix();
132
-		$total = 0;
133
-		for ($i = 0; $i < $this->info['chunkcount']; $i++) {
134
-			$total += $cache->size($prefix.$i);
135
-		}
136
-		return $total;
137
-	}
138
-
139
-	/**
140
-	 * Removes all chunks which belong to this transmission
141
-	 */
142
-	public function cleanup() {
143
-		$cache = $this->getCache();
144
-		$prefix = $this->getPrefix();
145
-		for ($i = 0; $i < $this->info['chunkcount']; $i++) {
146
-			$cache->remove($prefix.$i);
147
-		}
148
-	}
149
-
150
-	/**
151
-	 * Removes one specific chunk
152
-	 * @param string $index
153
-	 */
154
-	public function remove($index) {
155
-		$cache = $this->getCache();
156
-		$prefix = $this->getPrefix();
157
-		$cache->remove($prefix.$index);
158
-	}
159
-
160
-	/**
161
-	 * Assembles the chunks into the file specified by the path.
162
-	 * Also triggers the relevant hooks and proxies.
163
-	 *
164
-	 * @param \OC\Files\Storage\Storage $storage storage
165
-	 * @param string $path target path relative to the storage
166
-	 * @return bool true on success or false if file could not be created
167
-	 *
168
-	 * @throws \OC\ServerNotAvailableException
169
-	 */
170
-	public function file_assemble($storage, $path) {
171
-		// use file_put_contents as method because that best matches what this function does
172
-		if (\OC\Files\Filesystem::isValidPath($path)) {
173
-			$target = $storage->fopen($path, 'w');
174
-			if ($target) {
175
-				$count = $this->assemble($target);
176
-				fclose($target);
177
-				return $count > 0;
178
-			} else {
179
-				return false;
180
-			}
181
-		}
182
-		return false;
183
-	}
32
+    protected $info;
33
+    protected $cache;
34
+
35
+    /**
36
+     * TTL of chunks
37
+     *
38
+     * @var int
39
+     */
40
+    protected $ttl;
41
+
42
+    public static function decodeName($name) {
43
+        preg_match('/(?P<name>.*)-chunking-(?P<transferid>\d+)-(?P<chunkcount>\d+)-(?P<index>\d+)/', $name, $matches);
44
+        return $matches;
45
+    }
46
+
47
+    /**
48
+     * @param string[] $info
49
+     */
50
+    public function __construct($info) {
51
+        $this->info = $info;
52
+        $this->ttl = \OC::$server->getConfig()->getSystemValue('cache_chunk_gc_ttl', 86400);
53
+    }
54
+
55
+    public function getPrefix() {
56
+        $name = $this->info['name'];
57
+        $transferid = $this->info['transferid'];
58
+
59
+        return $name.'-chunking-'.$transferid.'-';
60
+    }
61
+
62
+    protected function getCache() {
63
+        if (!isset($this->cache)) {
64
+            $this->cache = new \OC\Cache\File();
65
+        }
66
+        return $this->cache;
67
+    }
68
+
69
+    /**
70
+     * Stores the given $data under the given $key - the number of stored bytes is returned
71
+     *
72
+     * @param string $index
73
+     * @param resource $data
74
+     * @return int
75
+     */
76
+    public function store($index, $data) {
77
+        $cache = $this->getCache();
78
+        $name = $this->getPrefix().$index;
79
+        $cache->set($name, $data, $this->ttl);
80
+
81
+        return $cache->size($name);
82
+    }
83
+
84
+    public function isComplete() {
85
+        $prefix = $this->getPrefix();
86
+        $cache = $this->getCache();
87
+        $chunkcount = (int)$this->info['chunkcount'];
88
+
89
+        for ($i = ($chunkcount - 1); $i >= 0; $i--) {
90
+            if (!$cache->hasKey($prefix.$i)) {
91
+                return false;
92
+            }
93
+        }
94
+
95
+        return true;
96
+    }
97
+
98
+    /**
99
+     * Assembles the chunks into the file specified by the path.
100
+     * Chunks are deleted afterwards.
101
+     *
102
+     * @param resource $f target path
103
+     *
104
+     * @return integer assembled file size
105
+     *
106
+     * @throws \OC\InsufficientStorageException when file could not be fully
107
+     * assembled due to lack of free space
108
+     */
109
+    public function assemble($f) {
110
+        $cache = $this->getCache();
111
+        $prefix = $this->getPrefix();
112
+        $count = 0;
113
+        for ($i = 0; $i < $this->info['chunkcount']; $i++) {
114
+            $chunk = $cache->get($prefix.$i);
115
+            // remove after reading to directly save space
116
+            $cache->remove($prefix.$i);
117
+            $count += fwrite($f, $chunk);
118
+            // let php release the memory to work around memory exhausted error with php 5.6
119
+            $chunk = null;
120
+        }
121
+
122
+        return $count;
123
+    }
124
+
125
+    /**
126
+     * Returns the size of the chunks already present
127
+     * @return integer size in bytes
128
+     */
129
+    public function getCurrentSize() {
130
+        $cache = $this->getCache();
131
+        $prefix = $this->getPrefix();
132
+        $total = 0;
133
+        for ($i = 0; $i < $this->info['chunkcount']; $i++) {
134
+            $total += $cache->size($prefix.$i);
135
+        }
136
+        return $total;
137
+    }
138
+
139
+    /**
140
+     * Removes all chunks which belong to this transmission
141
+     */
142
+    public function cleanup() {
143
+        $cache = $this->getCache();
144
+        $prefix = $this->getPrefix();
145
+        for ($i = 0; $i < $this->info['chunkcount']; $i++) {
146
+            $cache->remove($prefix.$i);
147
+        }
148
+    }
149
+
150
+    /**
151
+     * Removes one specific chunk
152
+     * @param string $index
153
+     */
154
+    public function remove($index) {
155
+        $cache = $this->getCache();
156
+        $prefix = $this->getPrefix();
157
+        $cache->remove($prefix.$index);
158
+    }
159
+
160
+    /**
161
+     * Assembles the chunks into the file specified by the path.
162
+     * Also triggers the relevant hooks and proxies.
163
+     *
164
+     * @param \OC\Files\Storage\Storage $storage storage
165
+     * @param string $path target path relative to the storage
166
+     * @return bool true on success or false if file could not be created
167
+     *
168
+     * @throws \OC\ServerNotAvailableException
169
+     */
170
+    public function file_assemble($storage, $path) {
171
+        // use file_put_contents as method because that best matches what this function does
172
+        if (\OC\Files\Filesystem::isValidPath($path)) {
173
+            $target = $storage->fopen($path, 'w');
174
+            if ($target) {
175
+                $count = $this->assemble($target);
176
+                fclose($target);
177
+                return $count > 0;
178
+            } else {
179
+                return false;
180
+            }
181
+        }
182
+        return false;
183
+    }
184 184
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/ObjectTree.php 2 patches
Indentation   +199 added lines, -199 removed lines patch added patch discarded remove patch
@@ -41,203 +41,203 @@
 block discarded – undo
41 41
 
42 42
 class ObjectTree extends CachingTree {
43 43
 
44
-	/**
45
-	 * @var \OC\Files\View
46
-	 */
47
-	protected $fileView;
48
-
49
-	/**
50
-	 * @var  \OCP\Files\Mount\IMountManager
51
-	 */
52
-	protected $mountManager;
53
-
54
-	/**
55
-	 * Creates the object
56
-	 */
57
-	public function __construct() {
58
-	}
59
-
60
-	/**
61
-	 * @param \Sabre\DAV\INode $rootNode
62
-	 * @param \OC\Files\View $view
63
-	 * @param  \OCP\Files\Mount\IMountManager $mountManager
64
-	 */
65
-	public function init(\Sabre\DAV\INode $rootNode, \OC\Files\View $view, \OCP\Files\Mount\IMountManager $mountManager) {
66
-		$this->rootNode = $rootNode;
67
-		$this->fileView = $view;
68
-		$this->mountManager = $mountManager;
69
-	}
70
-
71
-	/**
72
-	 * If the given path is a chunked file name, converts it
73
-	 * to the real file name. Only applies if the OC-CHUNKED header
74
-	 * is present.
75
-	 *
76
-	 * @param string $path chunk file path to convert
77
-	 *
78
-	 * @return string path to real file
79
-	 */
80
-	private function resolveChunkFile($path) {
81
-		if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
82
-			// resolve to real file name to find the proper node
83
-			[$dir, $name] = \Sabre\Uri\split($path);
84
-			if ($dir === '/' || $dir === '.') {
85
-				$dir = '';
86
-			}
87
-
88
-			$info = \OC_FileChunking::decodeName($name);
89
-			// only replace path if it was really the chunked file
90
-			if (isset($info['transferid'])) {
91
-				// getNodePath is called for multiple nodes within a chunk
92
-				// upload call
93
-				$path = $dir . '/' . $info['name'];
94
-				$path = ltrim($path, '/');
95
-			}
96
-		}
97
-		return $path;
98
-	}
99
-
100
-	/**
101
-	 * Returns the INode object for the requested path
102
-	 *
103
-	 * @param string $path
104
-	 * @return \Sabre\DAV\INode
105
-	 * @throws InvalidPath
106
-	 * @throws \Sabre\DAV\Exception\Locked
107
-	 * @throws \Sabre\DAV\Exception\NotFound
108
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
109
-	 */
110
-	public function getNodeForPath($path) {
111
-		if (!$this->fileView) {
112
-			throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
113
-		}
114
-
115
-		$path = trim($path, '/');
116
-
117
-		if (isset($this->cache[$path])) {
118
-			return $this->cache[$path];
119
-		}
120
-
121
-		if ($path) {
122
-			try {
123
-				$this->fileView->verifyPath($path, basename($path));
124
-			} catch (\OCP\Files\InvalidPathException $ex) {
125
-				throw new InvalidPath($ex->getMessage());
126
-			}
127
-		}
128
-
129
-		// Is it the root node?
130
-		if (!strlen($path)) {
131
-			return $this->rootNode;
132
-		}
133
-
134
-		if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
135
-			// read from storage
136
-			$absPath = $this->fileView->getAbsolutePath($path);
137
-			$mount = $this->fileView->getMount($path);
138
-			$storage = $mount->getStorage();
139
-			$internalPath = $mount->getInternalPath($absPath);
140
-			if ($storage && $storage->file_exists($internalPath)) {
141
-				/**
142
-				 * @var \OC\Files\Storage\Storage $storage
143
-				 */
144
-				// get data directly
145
-				$data = $storage->getMetaData($internalPath);
146
-				$info = new FileInfo($absPath, $storage, $internalPath, $data, $mount);
147
-			} else {
148
-				$info = null;
149
-			}
150
-		} else {
151
-			// resolve chunk file name to real name, if applicable
152
-			$path = $this->resolveChunkFile($path);
153
-
154
-			// read from cache
155
-			try {
156
-				$info = $this->fileView->getFileInfo($path);
157
-
158
-				if ($info instanceof \OCP\Files\FileInfo && $info->getStorage()->instanceOfStorage(FailedStorage::class)) {
159
-					throw new StorageNotAvailableException();
160
-				}
161
-			} catch (StorageNotAvailableException $e) {
162
-				throw new \Sabre\DAV\Exception\ServiceUnavailable('Storage is temporarily not available', 0, $e);
163
-			} catch (StorageInvalidException $e) {
164
-				throw new \Sabre\DAV\Exception\NotFound('Storage ' . $path . ' is invalid');
165
-			} catch (LockedException $e) {
166
-				throw new \Sabre\DAV\Exception\Locked();
167
-			} catch (ForbiddenException $e) {
168
-				throw new \Sabre\DAV\Exception\Forbidden();
169
-			}
170
-		}
171
-
172
-		if (!$info) {
173
-			throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
174
-		}
175
-
176
-		if ($info->getType() === 'dir') {
177
-			$node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this);
178
-		} else {
179
-			$node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
180
-		}
181
-
182
-		$this->cache[$path] = $node;
183
-		return $node;
184
-	}
185
-
186
-	/**
187
-	 * Copies a file or directory.
188
-	 *
189
-	 * This method must work recursively and delete the destination
190
-	 * if it exists
191
-	 *
192
-	 * @param string $sourcePath
193
-	 * @param string $destinationPath
194
-	 * @throws FileLocked
195
-	 * @throws Forbidden
196
-	 * @throws InvalidPath
197
-	 * @throws \Exception
198
-	 * @throws \Sabre\DAV\Exception\Forbidden
199
-	 * @throws \Sabre\DAV\Exception\Locked
200
-	 * @throws \Sabre\DAV\Exception\NotFound
201
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
202
-	 * @return void
203
-	 */
204
-	public function copy($sourcePath, $destinationPath) {
205
-		if (!$this->fileView) {
206
-			throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
207
-		}
208
-
209
-
210
-		$info = $this->fileView->getFileInfo(dirname($destinationPath));
211
-		if ($this->fileView->file_exists($destinationPath)) {
212
-			$destinationPermission = $info && $info->isUpdateable();
213
-		} else {
214
-			$destinationPermission = $info && $info->isCreatable();
215
-		}
216
-		if (!$destinationPermission) {
217
-			throw new Forbidden('No permissions to copy object.');
218
-		}
219
-
220
-		// this will trigger existence check
221
-		$this->getNodeForPath($sourcePath);
222
-
223
-		[$destinationDir, $destinationName] = \Sabre\Uri\split($destinationPath);
224
-		try {
225
-			$this->fileView->verifyPath($destinationDir, $destinationName);
226
-		} catch (\OCP\Files\InvalidPathException $ex) {
227
-			throw new InvalidPath($ex->getMessage());
228
-		}
229
-
230
-		try {
231
-			$this->fileView->copy($sourcePath, $destinationPath);
232
-		} catch (StorageNotAvailableException $e) {
233
-			throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
234
-		} catch (ForbiddenException $ex) {
235
-			throw new Forbidden($ex->getMessage(), $ex->getRetry());
236
-		} catch (LockedException $e) {
237
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
238
-		}
239
-
240
-		[$destinationDir,] = \Sabre\Uri\split($destinationPath);
241
-		$this->markDirty($destinationDir);
242
-	}
44
+    /**
45
+     * @var \OC\Files\View
46
+     */
47
+    protected $fileView;
48
+
49
+    /**
50
+     * @var  \OCP\Files\Mount\IMountManager
51
+     */
52
+    protected $mountManager;
53
+
54
+    /**
55
+     * Creates the object
56
+     */
57
+    public function __construct() {
58
+    }
59
+
60
+    /**
61
+     * @param \Sabre\DAV\INode $rootNode
62
+     * @param \OC\Files\View $view
63
+     * @param  \OCP\Files\Mount\IMountManager $mountManager
64
+     */
65
+    public function init(\Sabre\DAV\INode $rootNode, \OC\Files\View $view, \OCP\Files\Mount\IMountManager $mountManager) {
66
+        $this->rootNode = $rootNode;
67
+        $this->fileView = $view;
68
+        $this->mountManager = $mountManager;
69
+    }
70
+
71
+    /**
72
+     * If the given path is a chunked file name, converts it
73
+     * to the real file name. Only applies if the OC-CHUNKED header
74
+     * is present.
75
+     *
76
+     * @param string $path chunk file path to convert
77
+     *
78
+     * @return string path to real file
79
+     */
80
+    private function resolveChunkFile($path) {
81
+        if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
82
+            // resolve to real file name to find the proper node
83
+            [$dir, $name] = \Sabre\Uri\split($path);
84
+            if ($dir === '/' || $dir === '.') {
85
+                $dir = '';
86
+            }
87
+
88
+            $info = \OC_FileChunking::decodeName($name);
89
+            // only replace path if it was really the chunked file
90
+            if (isset($info['transferid'])) {
91
+                // getNodePath is called for multiple nodes within a chunk
92
+                // upload call
93
+                $path = $dir . '/' . $info['name'];
94
+                $path = ltrim($path, '/');
95
+            }
96
+        }
97
+        return $path;
98
+    }
99
+
100
+    /**
101
+     * Returns the INode object for the requested path
102
+     *
103
+     * @param string $path
104
+     * @return \Sabre\DAV\INode
105
+     * @throws InvalidPath
106
+     * @throws \Sabre\DAV\Exception\Locked
107
+     * @throws \Sabre\DAV\Exception\NotFound
108
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
109
+     */
110
+    public function getNodeForPath($path) {
111
+        if (!$this->fileView) {
112
+            throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
113
+        }
114
+
115
+        $path = trim($path, '/');
116
+
117
+        if (isset($this->cache[$path])) {
118
+            return $this->cache[$path];
119
+        }
120
+
121
+        if ($path) {
122
+            try {
123
+                $this->fileView->verifyPath($path, basename($path));
124
+            } catch (\OCP\Files\InvalidPathException $ex) {
125
+                throw new InvalidPath($ex->getMessage());
126
+            }
127
+        }
128
+
129
+        // Is it the root node?
130
+        if (!strlen($path)) {
131
+            return $this->rootNode;
132
+        }
133
+
134
+        if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
135
+            // read from storage
136
+            $absPath = $this->fileView->getAbsolutePath($path);
137
+            $mount = $this->fileView->getMount($path);
138
+            $storage = $mount->getStorage();
139
+            $internalPath = $mount->getInternalPath($absPath);
140
+            if ($storage && $storage->file_exists($internalPath)) {
141
+                /**
142
+                 * @var \OC\Files\Storage\Storage $storage
143
+                 */
144
+                // get data directly
145
+                $data = $storage->getMetaData($internalPath);
146
+                $info = new FileInfo($absPath, $storage, $internalPath, $data, $mount);
147
+            } else {
148
+                $info = null;
149
+            }
150
+        } else {
151
+            // resolve chunk file name to real name, if applicable
152
+            $path = $this->resolveChunkFile($path);
153
+
154
+            // read from cache
155
+            try {
156
+                $info = $this->fileView->getFileInfo($path);
157
+
158
+                if ($info instanceof \OCP\Files\FileInfo && $info->getStorage()->instanceOfStorage(FailedStorage::class)) {
159
+                    throw new StorageNotAvailableException();
160
+                }
161
+            } catch (StorageNotAvailableException $e) {
162
+                throw new \Sabre\DAV\Exception\ServiceUnavailable('Storage is temporarily not available', 0, $e);
163
+            } catch (StorageInvalidException $e) {
164
+                throw new \Sabre\DAV\Exception\NotFound('Storage ' . $path . ' is invalid');
165
+            } catch (LockedException $e) {
166
+                throw new \Sabre\DAV\Exception\Locked();
167
+            } catch (ForbiddenException $e) {
168
+                throw new \Sabre\DAV\Exception\Forbidden();
169
+            }
170
+        }
171
+
172
+        if (!$info) {
173
+            throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
174
+        }
175
+
176
+        if ($info->getType() === 'dir') {
177
+            $node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this);
178
+        } else {
179
+            $node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
180
+        }
181
+
182
+        $this->cache[$path] = $node;
183
+        return $node;
184
+    }
185
+
186
+    /**
187
+     * Copies a file or directory.
188
+     *
189
+     * This method must work recursively and delete the destination
190
+     * if it exists
191
+     *
192
+     * @param string $sourcePath
193
+     * @param string $destinationPath
194
+     * @throws FileLocked
195
+     * @throws Forbidden
196
+     * @throws InvalidPath
197
+     * @throws \Exception
198
+     * @throws \Sabre\DAV\Exception\Forbidden
199
+     * @throws \Sabre\DAV\Exception\Locked
200
+     * @throws \Sabre\DAV\Exception\NotFound
201
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
202
+     * @return void
203
+     */
204
+    public function copy($sourcePath, $destinationPath) {
205
+        if (!$this->fileView) {
206
+            throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
207
+        }
208
+
209
+
210
+        $info = $this->fileView->getFileInfo(dirname($destinationPath));
211
+        if ($this->fileView->file_exists($destinationPath)) {
212
+            $destinationPermission = $info && $info->isUpdateable();
213
+        } else {
214
+            $destinationPermission = $info && $info->isCreatable();
215
+        }
216
+        if (!$destinationPermission) {
217
+            throw new Forbidden('No permissions to copy object.');
218
+        }
219
+
220
+        // this will trigger existence check
221
+        $this->getNodeForPath($sourcePath);
222
+
223
+        [$destinationDir, $destinationName] = \Sabre\Uri\split($destinationPath);
224
+        try {
225
+            $this->fileView->verifyPath($destinationDir, $destinationName);
226
+        } catch (\OCP\Files\InvalidPathException $ex) {
227
+            throw new InvalidPath($ex->getMessage());
228
+        }
229
+
230
+        try {
231
+            $this->fileView->copy($sourcePath, $destinationPath);
232
+        } catch (StorageNotAvailableException $e) {
233
+            throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
234
+        } catch (ForbiddenException $ex) {
235
+            throw new Forbidden($ex->getMessage(), $ex->getRetry());
236
+        } catch (LockedException $e) {
237
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
238
+        }
239
+
240
+        [$destinationDir,] = \Sabre\Uri\split($destinationPath);
241
+        $this->markDirty($destinationDir);
242
+    }
243 243
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -90,7 +90,7 @@  discard block
 block discarded – undo
90 90
 			if (isset($info['transferid'])) {
91 91
 				// getNodePath is called for multiple nodes within a chunk
92 92
 				// upload call
93
-				$path = $dir . '/' . $info['name'];
93
+				$path = $dir.'/'.$info['name'];
94 94
 				$path = ltrim($path, '/');
95 95
 			}
96 96
 		}
@@ -161,7 +161,7 @@  discard block
 block discarded – undo
161 161
 			} catch (StorageNotAvailableException $e) {
162 162
 				throw new \Sabre\DAV\Exception\ServiceUnavailable('Storage is temporarily not available', 0, $e);
163 163
 			} catch (StorageInvalidException $e) {
164
-				throw new \Sabre\DAV\Exception\NotFound('Storage ' . $path . ' is invalid');
164
+				throw new \Sabre\DAV\Exception\NotFound('Storage '.$path.' is invalid');
165 165
 			} catch (LockedException $e) {
166 166
 				throw new \Sabre\DAV\Exception\Locked();
167 167
 			} catch (ForbiddenException $e) {
@@ -170,7 +170,7 @@  discard block
 block discarded – undo
170 170
 		}
171 171
 
172 172
 		if (!$info) {
173
-			throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
173
+			throw new \Sabre\DAV\Exception\NotFound('File with name '.$path.' could not be located');
174 174
 		}
175 175
 
176 176
 		if ($info->getType() === 'dir') {
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
 			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
238 238
 		}
239 239
 
240
-		[$destinationDir,] = \Sabre\Uri\split($destinationPath);
240
+		[$destinationDir, ] = \Sabre\Uri\split($destinationPath);
241 241
 		$this->markDirty($destinationDir);
242 242
 	}
243 243
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/Directory.php 2 patches
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -127,7 +127,7 @@  discard block
 block discarded – undo
127 127
 				// exit if we can't create a new file and we don't updatable existing file
128 128
 				$chunkInfo = \OC_FileChunking::decodeName($name);
129 129
 				if (!$this->fileView->isCreatable($this->path) &&
130
-					!$this->fileView->isUpdatable($this->path . '/' . $chunkInfo['name'])
130
+					!$this->fileView->isUpdatable($this->path.'/'.$chunkInfo['name'])
131 131
 				) {
132 132
 					throw new \Sabre\DAV\Exception\Forbidden();
133 133
 				}
@@ -140,9 +140,9 @@  discard block
 block discarded – undo
140 140
 
141 141
 			$this->fileView->verifyPath($this->path, $name);
142 142
 
143
-			$path = $this->fileView->getAbsolutePath($this->path) . '/' . $name;
143
+			$path = $this->fileView->getAbsolutePath($this->path).'/'.$name;
144 144
 			// in case the file already exists/overwriting
145
-			$info = $this->fileView->getFileInfo($this->path . '/' . $name);
145
+			$info = $this->fileView->getFileInfo($this->path.'/'.$name);
146 146
 			if (!$info) {
147 147
 				// use a dummy FileInfo which is acceptable here since it will be refreshed after the put is complete
148 148
 				$info = new \OC\Files\FileInfo($path, null, null, [
@@ -153,11 +153,11 @@  discard block
 block discarded – undo
153 153
 
154 154
 			// only allow 1 process to upload a file at once but still allow reading the file while writing the part file
155 155
 			$node->acquireLock(ILockingProvider::LOCK_SHARED);
156
-			$this->fileView->lockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
156
+			$this->fileView->lockFile($path.'.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
157 157
 
158 158
 			$result = $node->put($data);
159 159
 
160
-			$this->fileView->unlockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
160
+			$this->fileView->unlockFile($path.'.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
161 161
 			$node->releaseLock(ILockingProvider::LOCK_SHARED);
162 162
 			return $result;
163 163
 		} catch (\OCP\Files\StorageNotAvailableException $e) {
@@ -187,9 +187,9 @@  discard block
 block discarded – undo
187 187
 			}
188 188
 
189 189
 			$this->fileView->verifyPath($this->path, $name);
190
-			$newPath = $this->path . '/' . $name;
190
+			$newPath = $this->path.'/'.$name;
191 191
 			if (!$this->fileView->mkdir($newPath)) {
192
-				throw new \Sabre\DAV\Exception\Forbidden('Could not create directory ' . $newPath);
192
+				throw new \Sabre\DAV\Exception\Forbidden('Could not create directory '.$newPath);
193 193
 			}
194 194
 		} catch (\OCP\Files\StorageNotAvailableException $e) {
195 195
 			throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
@@ -218,7 +218,7 @@  discard block
 block discarded – undo
218 218
 			throw new NotFound();
219 219
 		}
220 220
 
221
-		$path = $this->path . '/' . $name;
221
+		$path = $this->path.'/'.$name;
222 222
 		if (is_null($info)) {
223 223
 			try {
224 224
 				$this->fileView->verifyPath($this->path, $name);
@@ -233,7 +233,7 @@  discard block
 block discarded – undo
233 233
 		}
234 234
 
235 235
 		if (!$info) {
236
-			throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
236
+			throw new \Sabre\DAV\Exception\NotFound('File with name '.$path.' could not be located');
237 237
 		}
238 238
 
239 239
 		if ($info->getMimeType() === FileInfo::MIMETYPE_FOLDER) {
@@ -292,7 +292,7 @@  discard block
 block discarded – undo
292 292
 		// (required old code) instead of "updateFile".
293 293
 		//
294 294
 		// TODO: resolve chunk file name here and implement "updateFile"
295
-		$path = $this->path . '/' . $name;
295
+		$path = $this->path.'/'.$name;
296 296
 		return $this->fileView->file_exists($path);
297 297
 	}
298 298
 
@@ -389,7 +389,7 @@  discard block
 block discarded – undo
389 389
 			throw new ServiceUnavailable('filesystem not setup');
390 390
 		}
391 391
 
392
-		$destinationPath = $this->getPath() . '/' . $targetName;
392
+		$destinationPath = $this->getPath().'/'.$targetName;
393 393
 
394 394
 
395 395
 		$targetNodeExists = $this->childExists($targetName);
@@ -397,10 +397,10 @@  discard block
 block discarded – undo
397 397
 		// at getNodeForPath we also check the path for isForbiddenFileOrDir
398 398
 		// with that we have covered both source and destination
399 399
 		if ($sourceNode instanceof Directory && $targetNodeExists) {
400
-			throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode->getName() . ', target exists');
400
+			throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory '.$sourceNode->getName().', target exists');
401 401
 		}
402 402
 
403
-		[$sourceDir,] = \Sabre\Uri\split($sourceNode->getPath());
403
+		[$sourceDir, ] = \Sabre\Uri\split($sourceNode->getPath());
404 404
 		$destinationDir = $this->getPath();
405 405
 
406 406
 		$sourcePath = $sourceNode->getPath();
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
 
460 460
 	public function copyInto($targetName, $sourcePath, INode $sourceNode) {
461 461
 		if ($sourceNode instanceof File || $sourceNode instanceof Directory) {
462
-			$destinationPath = $this->getPath() . '/' . $targetName;
462
+			$destinationPath = $this->getPath().'/'.$targetName;
463 463
 			$sourcePath = $sourceNode->getPath();
464 464
 
465 465
 			if (!$this->fileView->isCreatable($this->getPath())) {
Please login to merge, or discard this patch.
Indentation   +425 added lines, -425 removed lines patch added patch discarded remove patch
@@ -58,429 +58,429 @@
 block discarded – undo
58 58
 
59 59
 class Directory extends \OCA\DAV\Connector\Sabre\Node implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota, \Sabre\DAV\IMoveTarget, \Sabre\DAV\ICopyTarget {
60 60
 
61
-	/**
62
-	 * Cached directory content
63
-	 * @var \OCP\Files\FileInfo[]
64
-	 */
65
-	private ?array $dirContent = null;
66
-
67
-	/** Cached quota info */
68
-	private ?array $quotaInfo = null;
69
-	private ?CachingTree $tree = null;
70
-
71
-	/** @var array<string, array<int, FileMetadata>> */
72
-	private array $metadata = [];
73
-
74
-	/**
75
-	 * Sets up the node, expects a full path name
76
-	 */
77
-	public function __construct(View $view, FileInfo $info, ?CachingTree $tree = null, IShareManager $shareManager = null) {
78
-		parent::__construct($view, $info, $shareManager);
79
-		$this->tree = $tree;
80
-	}
81
-
82
-	/**
83
-	 * Creates a new file in the directory
84
-	 *
85
-	 * Data will either be supplied as a stream resource, or in certain cases
86
-	 * as a string. Keep in mind that you may have to support either.
87
-	 *
88
-	 * After successful creation of the file, you may choose to return the ETag
89
-	 * of the new file here.
90
-	 *
91
-	 * The returned ETag must be surrounded by double-quotes (The quotes should
92
-	 * be part of the actual string).
93
-	 *
94
-	 * If you cannot accurately determine the ETag, you should not return it.
95
-	 * If you don't store the file exactly as-is (you're transforming it
96
-	 * somehow) you should also not return an ETag.
97
-	 *
98
-	 * This means that if a subsequent GET to this new file does not exactly
99
-	 * return the same contents of what was submitted here, you are strongly
100
-	 * recommended to omit the ETag.
101
-	 *
102
-	 * @param string $name Name of the file
103
-	 * @param resource|string $data Initial payload
104
-	 * @return null|string
105
-	 * @throws Exception\EntityTooLarge
106
-	 * @throws Exception\UnsupportedMediaType
107
-	 * @throws FileLocked
108
-	 * @throws InvalidPath
109
-	 * @throws \Sabre\DAV\Exception
110
-	 * @throws \Sabre\DAV\Exception\BadRequest
111
-	 * @throws \Sabre\DAV\Exception\Forbidden
112
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
113
-	 */
114
-	public function createFile($name, $data = null) {
115
-		try {
116
-			// for chunked upload also updating a existing file is a "createFile"
117
-			// because we create all the chunks before re-assemble them to the existing file.
118
-			if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
119
-
120
-				// exit if we can't create a new file and we don't updatable existing file
121
-				$chunkInfo = \OC_FileChunking::decodeName($name);
122
-				if (!$this->fileView->isCreatable($this->path) &&
123
-					!$this->fileView->isUpdatable($this->path . '/' . $chunkInfo['name'])
124
-				) {
125
-					throw new \Sabre\DAV\Exception\Forbidden();
126
-				}
127
-			} else {
128
-				// For non-chunked upload it is enough to check if we can create a new file
129
-				if (!$this->fileView->isCreatable($this->path)) {
130
-					throw new \Sabre\DAV\Exception\Forbidden();
131
-				}
132
-			}
133
-
134
-			$this->fileView->verifyPath($this->path, $name);
135
-
136
-			$path = $this->fileView->getAbsolutePath($this->path) . '/' . $name;
137
-			// in case the file already exists/overwriting
138
-			$info = $this->fileView->getFileInfo($this->path . '/' . $name);
139
-			if (!$info) {
140
-				// use a dummy FileInfo which is acceptable here since it will be refreshed after the put is complete
141
-				$info = new \OC\Files\FileInfo($path, null, null, [
142
-					'type' => FileInfo::TYPE_FILE
143
-				], null);
144
-			}
145
-			$node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
146
-
147
-			// only allow 1 process to upload a file at once but still allow reading the file while writing the part file
148
-			$node->acquireLock(ILockingProvider::LOCK_SHARED);
149
-			$this->fileView->lockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
150
-
151
-			$result = $node->put($data);
152
-
153
-			$this->fileView->unlockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
154
-			$node->releaseLock(ILockingProvider::LOCK_SHARED);
155
-			return $result;
156
-		} catch (\OCP\Files\StorageNotAvailableException $e) {
157
-			throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage(), $e->getCode(), $e);
158
-		} catch (InvalidPathException $ex) {
159
-			throw new InvalidPath($ex->getMessage(), false, $ex);
160
-		} catch (ForbiddenException $ex) {
161
-			throw new Forbidden($ex->getMessage(), $ex->getRetry(), $ex);
162
-		} catch (LockedException $e) {
163
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
164
-		}
165
-	}
166
-
167
-	/**
168
-	 * Creates a new subdirectory
169
-	 *
170
-	 * @param string $name
171
-	 * @throws FileLocked
172
-	 * @throws InvalidPath
173
-	 * @throws \Sabre\DAV\Exception\Forbidden
174
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
175
-	 */
176
-	public function createDirectory($name) {
177
-		try {
178
-			if (!$this->info->isCreatable()) {
179
-				throw new \Sabre\DAV\Exception\Forbidden();
180
-			}
181
-
182
-			$this->fileView->verifyPath($this->path, $name);
183
-			$newPath = $this->path . '/' . $name;
184
-			if (!$this->fileView->mkdir($newPath)) {
185
-				throw new \Sabre\DAV\Exception\Forbidden('Could not create directory ' . $newPath);
186
-			}
187
-		} catch (\OCP\Files\StorageNotAvailableException $e) {
188
-			throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
189
-		} catch (InvalidPathException $ex) {
190
-			throw new InvalidPath($ex->getMessage());
191
-		} catch (ForbiddenException $ex) {
192
-			throw new Forbidden($ex->getMessage(), $ex->getRetry());
193
-		} catch (LockedException $e) {
194
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
195
-		}
196
-	}
197
-
198
-	/**
199
-	 * Returns a specific child node, referenced by its name
200
-	 *
201
-	 * @param string $name
202
-	 * @param \OCP\Files\FileInfo $info
203
-	 * @return \Sabre\DAV\INode
204
-	 * @throws InvalidPath
205
-	 * @throws \Sabre\DAV\Exception\NotFound
206
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
207
-	 */
208
-	public function getChild($name, $info = null) {
209
-		if (!$this->info->isReadable()) {
210
-			// avoid detecting files through this way
211
-			throw new NotFound();
212
-		}
213
-
214
-		$path = $this->path . '/' . $name;
215
-		if (is_null($info)) {
216
-			try {
217
-				$this->fileView->verifyPath($this->path, $name);
218
-				$info = $this->fileView->getFileInfo($path);
219
-			} catch (\OCP\Files\StorageNotAvailableException $e) {
220
-				throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
221
-			} catch (InvalidPathException $ex) {
222
-				throw new InvalidPath($ex->getMessage());
223
-			} catch (ForbiddenException $e) {
224
-				throw new \Sabre\DAV\Exception\Forbidden();
225
-			}
226
-		}
227
-
228
-		if (!$info) {
229
-			throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
230
-		}
231
-
232
-		if ($info->getMimeType() === FileInfo::MIMETYPE_FOLDER) {
233
-			$node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this->tree, $this->shareManager);
234
-		} else {
235
-			$node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info, $this->shareManager);
236
-		}
237
-		if ($this->tree) {
238
-			$this->tree->cacheNode($node);
239
-		}
240
-		return $node;
241
-	}
242
-
243
-	/**
244
-	 * Returns an array with all the child nodes
245
-	 *
246
-	 * @return \Sabre\DAV\INode[]
247
-	 * @throws \Sabre\DAV\Exception\Locked
248
-	 * @throws \OCA\DAV\Connector\Sabre\Exception\Forbidden
249
-	 */
250
-	public function getChildren() {
251
-		if (!is_null($this->dirContent)) {
252
-			return $this->dirContent;
253
-		}
254
-		try {
255
-			if (!$this->info->isReadable()) {
256
-				// return 403 instead of 404 because a 404 would make
257
-				// the caller believe that the collection itself does not exist
258
-				if (\OCP\Server::get(\OCP\App\IAppManager::class)->isInstalled('files_accesscontrol')) {
259
-					throw new Forbidden('No read permissions. This might be caused by files_accesscontrol, check your configured rules');
260
-				} else {
261
-					throw new Forbidden('No read permissions');
262
-				}
263
-			}
264
-			$folderContent = $this->getNode()->getDirectoryListing();
265
-		} catch (LockedException $e) {
266
-			throw new Locked();
267
-		}
268
-
269
-		$nodes = [];
270
-		foreach ($folderContent as $info) {
271
-			$node = $this->getChild($info->getName(), $info);
272
-			$nodes[] = $node;
273
-		}
274
-		$this->dirContent = $nodes;
275
-		return $this->dirContent;
276
-	}
277
-
278
-	/**
279
-	 * Checks if a child exists.
280
-	 *
281
-	 * @param string $name
282
-	 * @return bool
283
-	 */
284
-	public function childExists($name) {
285
-		// note: here we do NOT resolve the chunk file name to the real file name
286
-		// to make sure we return false when checking for file existence with a chunk
287
-		// file name.
288
-		// This is to make sure that "createFile" is still triggered
289
-		// (required old code) instead of "updateFile".
290
-		//
291
-		// TODO: resolve chunk file name here and implement "updateFile"
292
-		$path = $this->path . '/' . $name;
293
-		return $this->fileView->file_exists($path);
294
-	}
295
-
296
-	/**
297
-	 * Deletes all files in this directory, and then itself
298
-	 *
299
-	 * @return void
300
-	 * @throws FileLocked
301
-	 * @throws \Sabre\DAV\Exception\Forbidden
302
-	 */
303
-	public function delete() {
304
-		if ($this->path === '' || $this->path === '/' || !$this->info->isDeletable()) {
305
-			throw new \Sabre\DAV\Exception\Forbidden();
306
-		}
307
-
308
-		try {
309
-			if (!$this->fileView->rmdir($this->path)) {
310
-				// assume it wasn't possible to remove due to permission issue
311
-				throw new \Sabre\DAV\Exception\Forbidden();
312
-			}
313
-		} catch (ForbiddenException $ex) {
314
-			throw new Forbidden($ex->getMessage(), $ex->getRetry());
315
-		} catch (LockedException $e) {
316
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
317
-		}
318
-	}
319
-
320
-	/**
321
-	 * Returns available diskspace information
322
-	 *
323
-	 * @return array
324
-	 */
325
-	public function getQuotaInfo() {
326
-		/** @var LoggerInterface $logger */
327
-		$logger = \OC::$server->get(LoggerInterface::class);
328
-		if ($this->quotaInfo) {
329
-			return $this->quotaInfo;
330
-		}
331
-		try {
332
-			$storageInfo = \OC_Helper::getStorageInfo($this->info->getPath(), $this->info, false);
333
-			if ($storageInfo['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED) {
334
-				$free = \OCP\Files\FileInfo::SPACE_UNLIMITED;
335
-			} else {
336
-				$free = $storageInfo['free'];
337
-			}
338
-			$this->quotaInfo = [
339
-				$storageInfo['used'],
340
-				$free
341
-			];
342
-			return $this->quotaInfo;
343
-		} catch (\OCP\Files\NotFoundException $e) {
344
-			$logger->warning("error while getting quota into", ['exception' => $e]);
345
-			return [0, 0];
346
-		} catch (\OCP\Files\StorageNotAvailableException $e) {
347
-			$logger->warning("error while getting quota into", ['exception' => $e]);
348
-			return [0, 0];
349
-		} catch (NotPermittedException $e) {
350
-			$logger->warning("error while getting quota into", ['exception' => $e]);
351
-			return [0, 0];
352
-		}
353
-	}
354
-
355
-	/**
356
-	 * Moves a node into this collection.
357
-	 *
358
-	 * It is up to the implementors to:
359
-	 *   1. Create the new resource.
360
-	 *   2. Remove the old resource.
361
-	 *   3. Transfer any properties or other data.
362
-	 *
363
-	 * Generally you should make very sure that your collection can easily move
364
-	 * the move.
365
-	 *
366
-	 * If you don't, just return false, which will trigger sabre/dav to handle
367
-	 * the move itself. If you return true from this function, the assumption
368
-	 * is that the move was successful.
369
-	 *
370
-	 * @param string $targetName New local file/collection name.
371
-	 * @param string $fullSourcePath Full path to source node
372
-	 * @param INode $sourceNode Source node itself
373
-	 * @return bool
374
-	 * @throws BadRequest
375
-	 * @throws ServiceUnavailable
376
-	 * @throws Forbidden
377
-	 * @throws FileLocked
378
-	 * @throws \Sabre\DAV\Exception\Forbidden
379
-	 */
380
-	public function moveInto($targetName, $fullSourcePath, INode $sourceNode) {
381
-		if (!$sourceNode instanceof Node) {
382
-			// it's a file of another kind, like FutureFile
383
-			if ($sourceNode instanceof IFile) {
384
-				// fallback to default copy+delete handling
385
-				return false;
386
-			}
387
-			throw new BadRequest('Incompatible node types');
388
-		}
389
-
390
-		if (!$this->fileView) {
391
-			throw new ServiceUnavailable('filesystem not setup');
392
-		}
393
-
394
-		$destinationPath = $this->getPath() . '/' . $targetName;
395
-
396
-
397
-		$targetNodeExists = $this->childExists($targetName);
398
-
399
-		// at getNodeForPath we also check the path for isForbiddenFileOrDir
400
-		// with that we have covered both source and destination
401
-		if ($sourceNode instanceof Directory && $targetNodeExists) {
402
-			throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode->getName() . ', target exists');
403
-		}
404
-
405
-		[$sourceDir,] = \Sabre\Uri\split($sourceNode->getPath());
406
-		$destinationDir = $this->getPath();
407
-
408
-		$sourcePath = $sourceNode->getPath();
409
-
410
-		$isMovableMount = false;
411
-		$sourceMount = \OC::$server->getMountManager()->find($this->fileView->getAbsolutePath($sourcePath));
412
-		$internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath));
413
-		if ($sourceMount instanceof MoveableMount && $internalPath === '') {
414
-			$isMovableMount = true;
415
-		}
416
-
417
-		try {
418
-			$sameFolder = ($sourceDir === $destinationDir);
419
-			// if we're overwriting or same folder
420
-			if ($targetNodeExists || $sameFolder) {
421
-				// note that renaming a share mount point is always allowed
422
-				if (!$this->fileView->isUpdatable($destinationDir) && !$isMovableMount) {
423
-					throw new \Sabre\DAV\Exception\Forbidden();
424
-				}
425
-			} else {
426
-				if (!$this->fileView->isCreatable($destinationDir)) {
427
-					throw new \Sabre\DAV\Exception\Forbidden();
428
-				}
429
-			}
430
-
431
-			if (!$sameFolder) {
432
-				// moving to a different folder, source will be gone, like a deletion
433
-				// note that moving a share mount point is always allowed
434
-				if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) {
435
-					throw new \Sabre\DAV\Exception\Forbidden();
436
-				}
437
-			}
438
-
439
-			$fileName = basename($destinationPath);
440
-			try {
441
-				$this->fileView->verifyPath($destinationDir, $fileName);
442
-			} catch (InvalidPathException $ex) {
443
-				throw new InvalidPath($ex->getMessage());
444
-			}
445
-
446
-			$renameOkay = $this->fileView->rename($sourcePath, $destinationPath);
447
-			if (!$renameOkay) {
448
-				throw new \Sabre\DAV\Exception\Forbidden('');
449
-			}
450
-		} catch (StorageNotAvailableException $e) {
451
-			throw new ServiceUnavailable($e->getMessage());
452
-		} catch (ForbiddenException $ex) {
453
-			throw new Forbidden($ex->getMessage(), $ex->getRetry());
454
-		} catch (LockedException $e) {
455
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
456
-		}
457
-
458
-		return true;
459
-	}
460
-
461
-
462
-	public function copyInto($targetName, $sourcePath, INode $sourceNode) {
463
-		if ($sourceNode instanceof File || $sourceNode instanceof Directory) {
464
-			$destinationPath = $this->getPath() . '/' . $targetName;
465
-			$sourcePath = $sourceNode->getPath();
466
-
467
-			if (!$this->fileView->isCreatable($this->getPath())) {
468
-				throw new \Sabre\DAV\Exception\Forbidden();
469
-			}
470
-
471
-			try {
472
-				$this->fileView->verifyPath($this->getPath(), $targetName);
473
-			} catch (InvalidPathException $ex) {
474
-				throw new InvalidPath($ex->getMessage());
475
-			}
476
-
477
-			return $this->fileView->copy($sourcePath, $destinationPath);
478
-		}
479
-
480
-		return false;
481
-	}
482
-
483
-	public function getNode(): Folder {
484
-		return $this->node;
485
-	}
61
+    /**
62
+     * Cached directory content
63
+     * @var \OCP\Files\FileInfo[]
64
+     */
65
+    private ?array $dirContent = null;
66
+
67
+    /** Cached quota info */
68
+    private ?array $quotaInfo = null;
69
+    private ?CachingTree $tree = null;
70
+
71
+    /** @var array<string, array<int, FileMetadata>> */
72
+    private array $metadata = [];
73
+
74
+    /**
75
+     * Sets up the node, expects a full path name
76
+     */
77
+    public function __construct(View $view, FileInfo $info, ?CachingTree $tree = null, IShareManager $shareManager = null) {
78
+        parent::__construct($view, $info, $shareManager);
79
+        $this->tree = $tree;
80
+    }
81
+
82
+    /**
83
+     * Creates a new file in the directory
84
+     *
85
+     * Data will either be supplied as a stream resource, or in certain cases
86
+     * as a string. Keep in mind that you may have to support either.
87
+     *
88
+     * After successful creation of the file, you may choose to return the ETag
89
+     * of the new file here.
90
+     *
91
+     * The returned ETag must be surrounded by double-quotes (The quotes should
92
+     * be part of the actual string).
93
+     *
94
+     * If you cannot accurately determine the ETag, you should not return it.
95
+     * If you don't store the file exactly as-is (you're transforming it
96
+     * somehow) you should also not return an ETag.
97
+     *
98
+     * This means that if a subsequent GET to this new file does not exactly
99
+     * return the same contents of what was submitted here, you are strongly
100
+     * recommended to omit the ETag.
101
+     *
102
+     * @param string $name Name of the file
103
+     * @param resource|string $data Initial payload
104
+     * @return null|string
105
+     * @throws Exception\EntityTooLarge
106
+     * @throws Exception\UnsupportedMediaType
107
+     * @throws FileLocked
108
+     * @throws InvalidPath
109
+     * @throws \Sabre\DAV\Exception
110
+     * @throws \Sabre\DAV\Exception\BadRequest
111
+     * @throws \Sabre\DAV\Exception\Forbidden
112
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
113
+     */
114
+    public function createFile($name, $data = null) {
115
+        try {
116
+            // for chunked upload also updating a existing file is a "createFile"
117
+            // because we create all the chunks before re-assemble them to the existing file.
118
+            if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
119
+
120
+                // exit if we can't create a new file and we don't updatable existing file
121
+                $chunkInfo = \OC_FileChunking::decodeName($name);
122
+                if (!$this->fileView->isCreatable($this->path) &&
123
+                    !$this->fileView->isUpdatable($this->path . '/' . $chunkInfo['name'])
124
+                ) {
125
+                    throw new \Sabre\DAV\Exception\Forbidden();
126
+                }
127
+            } else {
128
+                // For non-chunked upload it is enough to check if we can create a new file
129
+                if (!$this->fileView->isCreatable($this->path)) {
130
+                    throw new \Sabre\DAV\Exception\Forbidden();
131
+                }
132
+            }
133
+
134
+            $this->fileView->verifyPath($this->path, $name);
135
+
136
+            $path = $this->fileView->getAbsolutePath($this->path) . '/' . $name;
137
+            // in case the file already exists/overwriting
138
+            $info = $this->fileView->getFileInfo($this->path . '/' . $name);
139
+            if (!$info) {
140
+                // use a dummy FileInfo which is acceptable here since it will be refreshed after the put is complete
141
+                $info = new \OC\Files\FileInfo($path, null, null, [
142
+                    'type' => FileInfo::TYPE_FILE
143
+                ], null);
144
+            }
145
+            $node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
146
+
147
+            // only allow 1 process to upload a file at once but still allow reading the file while writing the part file
148
+            $node->acquireLock(ILockingProvider::LOCK_SHARED);
149
+            $this->fileView->lockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
150
+
151
+            $result = $node->put($data);
152
+
153
+            $this->fileView->unlockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
154
+            $node->releaseLock(ILockingProvider::LOCK_SHARED);
155
+            return $result;
156
+        } catch (\OCP\Files\StorageNotAvailableException $e) {
157
+            throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage(), $e->getCode(), $e);
158
+        } catch (InvalidPathException $ex) {
159
+            throw new InvalidPath($ex->getMessage(), false, $ex);
160
+        } catch (ForbiddenException $ex) {
161
+            throw new Forbidden($ex->getMessage(), $ex->getRetry(), $ex);
162
+        } catch (LockedException $e) {
163
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
164
+        }
165
+    }
166
+
167
+    /**
168
+     * Creates a new subdirectory
169
+     *
170
+     * @param string $name
171
+     * @throws FileLocked
172
+     * @throws InvalidPath
173
+     * @throws \Sabre\DAV\Exception\Forbidden
174
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
175
+     */
176
+    public function createDirectory($name) {
177
+        try {
178
+            if (!$this->info->isCreatable()) {
179
+                throw new \Sabre\DAV\Exception\Forbidden();
180
+            }
181
+
182
+            $this->fileView->verifyPath($this->path, $name);
183
+            $newPath = $this->path . '/' . $name;
184
+            if (!$this->fileView->mkdir($newPath)) {
185
+                throw new \Sabre\DAV\Exception\Forbidden('Could not create directory ' . $newPath);
186
+            }
187
+        } catch (\OCP\Files\StorageNotAvailableException $e) {
188
+            throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
189
+        } catch (InvalidPathException $ex) {
190
+            throw new InvalidPath($ex->getMessage());
191
+        } catch (ForbiddenException $ex) {
192
+            throw new Forbidden($ex->getMessage(), $ex->getRetry());
193
+        } catch (LockedException $e) {
194
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
195
+        }
196
+    }
197
+
198
+    /**
199
+     * Returns a specific child node, referenced by its name
200
+     *
201
+     * @param string $name
202
+     * @param \OCP\Files\FileInfo $info
203
+     * @return \Sabre\DAV\INode
204
+     * @throws InvalidPath
205
+     * @throws \Sabre\DAV\Exception\NotFound
206
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
207
+     */
208
+    public function getChild($name, $info = null) {
209
+        if (!$this->info->isReadable()) {
210
+            // avoid detecting files through this way
211
+            throw new NotFound();
212
+        }
213
+
214
+        $path = $this->path . '/' . $name;
215
+        if (is_null($info)) {
216
+            try {
217
+                $this->fileView->verifyPath($this->path, $name);
218
+                $info = $this->fileView->getFileInfo($path);
219
+            } catch (\OCP\Files\StorageNotAvailableException $e) {
220
+                throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
221
+            } catch (InvalidPathException $ex) {
222
+                throw new InvalidPath($ex->getMessage());
223
+            } catch (ForbiddenException $e) {
224
+                throw new \Sabre\DAV\Exception\Forbidden();
225
+            }
226
+        }
227
+
228
+        if (!$info) {
229
+            throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
230
+        }
231
+
232
+        if ($info->getMimeType() === FileInfo::MIMETYPE_FOLDER) {
233
+            $node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this->tree, $this->shareManager);
234
+        } else {
235
+            $node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info, $this->shareManager);
236
+        }
237
+        if ($this->tree) {
238
+            $this->tree->cacheNode($node);
239
+        }
240
+        return $node;
241
+    }
242
+
243
+    /**
244
+     * Returns an array with all the child nodes
245
+     *
246
+     * @return \Sabre\DAV\INode[]
247
+     * @throws \Sabre\DAV\Exception\Locked
248
+     * @throws \OCA\DAV\Connector\Sabre\Exception\Forbidden
249
+     */
250
+    public function getChildren() {
251
+        if (!is_null($this->dirContent)) {
252
+            return $this->dirContent;
253
+        }
254
+        try {
255
+            if (!$this->info->isReadable()) {
256
+                // return 403 instead of 404 because a 404 would make
257
+                // the caller believe that the collection itself does not exist
258
+                if (\OCP\Server::get(\OCP\App\IAppManager::class)->isInstalled('files_accesscontrol')) {
259
+                    throw new Forbidden('No read permissions. This might be caused by files_accesscontrol, check your configured rules');
260
+                } else {
261
+                    throw new Forbidden('No read permissions');
262
+                }
263
+            }
264
+            $folderContent = $this->getNode()->getDirectoryListing();
265
+        } catch (LockedException $e) {
266
+            throw new Locked();
267
+        }
268
+
269
+        $nodes = [];
270
+        foreach ($folderContent as $info) {
271
+            $node = $this->getChild($info->getName(), $info);
272
+            $nodes[] = $node;
273
+        }
274
+        $this->dirContent = $nodes;
275
+        return $this->dirContent;
276
+    }
277
+
278
+    /**
279
+     * Checks if a child exists.
280
+     *
281
+     * @param string $name
282
+     * @return bool
283
+     */
284
+    public function childExists($name) {
285
+        // note: here we do NOT resolve the chunk file name to the real file name
286
+        // to make sure we return false when checking for file existence with a chunk
287
+        // file name.
288
+        // This is to make sure that "createFile" is still triggered
289
+        // (required old code) instead of "updateFile".
290
+        //
291
+        // TODO: resolve chunk file name here and implement "updateFile"
292
+        $path = $this->path . '/' . $name;
293
+        return $this->fileView->file_exists($path);
294
+    }
295
+
296
+    /**
297
+     * Deletes all files in this directory, and then itself
298
+     *
299
+     * @return void
300
+     * @throws FileLocked
301
+     * @throws \Sabre\DAV\Exception\Forbidden
302
+     */
303
+    public function delete() {
304
+        if ($this->path === '' || $this->path === '/' || !$this->info->isDeletable()) {
305
+            throw new \Sabre\DAV\Exception\Forbidden();
306
+        }
307
+
308
+        try {
309
+            if (!$this->fileView->rmdir($this->path)) {
310
+                // assume it wasn't possible to remove due to permission issue
311
+                throw new \Sabre\DAV\Exception\Forbidden();
312
+            }
313
+        } catch (ForbiddenException $ex) {
314
+            throw new Forbidden($ex->getMessage(), $ex->getRetry());
315
+        } catch (LockedException $e) {
316
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
317
+        }
318
+    }
319
+
320
+    /**
321
+     * Returns available diskspace information
322
+     *
323
+     * @return array
324
+     */
325
+    public function getQuotaInfo() {
326
+        /** @var LoggerInterface $logger */
327
+        $logger = \OC::$server->get(LoggerInterface::class);
328
+        if ($this->quotaInfo) {
329
+            return $this->quotaInfo;
330
+        }
331
+        try {
332
+            $storageInfo = \OC_Helper::getStorageInfo($this->info->getPath(), $this->info, false);
333
+            if ($storageInfo['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED) {
334
+                $free = \OCP\Files\FileInfo::SPACE_UNLIMITED;
335
+            } else {
336
+                $free = $storageInfo['free'];
337
+            }
338
+            $this->quotaInfo = [
339
+                $storageInfo['used'],
340
+                $free
341
+            ];
342
+            return $this->quotaInfo;
343
+        } catch (\OCP\Files\NotFoundException $e) {
344
+            $logger->warning("error while getting quota into", ['exception' => $e]);
345
+            return [0, 0];
346
+        } catch (\OCP\Files\StorageNotAvailableException $e) {
347
+            $logger->warning("error while getting quota into", ['exception' => $e]);
348
+            return [0, 0];
349
+        } catch (NotPermittedException $e) {
350
+            $logger->warning("error while getting quota into", ['exception' => $e]);
351
+            return [0, 0];
352
+        }
353
+    }
354
+
355
+    /**
356
+     * Moves a node into this collection.
357
+     *
358
+     * It is up to the implementors to:
359
+     *   1. Create the new resource.
360
+     *   2. Remove the old resource.
361
+     *   3. Transfer any properties or other data.
362
+     *
363
+     * Generally you should make very sure that your collection can easily move
364
+     * the move.
365
+     *
366
+     * If you don't, just return false, which will trigger sabre/dav to handle
367
+     * the move itself. If you return true from this function, the assumption
368
+     * is that the move was successful.
369
+     *
370
+     * @param string $targetName New local file/collection name.
371
+     * @param string $fullSourcePath Full path to source node
372
+     * @param INode $sourceNode Source node itself
373
+     * @return bool
374
+     * @throws BadRequest
375
+     * @throws ServiceUnavailable
376
+     * @throws Forbidden
377
+     * @throws FileLocked
378
+     * @throws \Sabre\DAV\Exception\Forbidden
379
+     */
380
+    public function moveInto($targetName, $fullSourcePath, INode $sourceNode) {
381
+        if (!$sourceNode instanceof Node) {
382
+            // it's a file of another kind, like FutureFile
383
+            if ($sourceNode instanceof IFile) {
384
+                // fallback to default copy+delete handling
385
+                return false;
386
+            }
387
+            throw new BadRequest('Incompatible node types');
388
+        }
389
+
390
+        if (!$this->fileView) {
391
+            throw new ServiceUnavailable('filesystem not setup');
392
+        }
393
+
394
+        $destinationPath = $this->getPath() . '/' . $targetName;
395
+
396
+
397
+        $targetNodeExists = $this->childExists($targetName);
398
+
399
+        // at getNodeForPath we also check the path for isForbiddenFileOrDir
400
+        // with that we have covered both source and destination
401
+        if ($sourceNode instanceof Directory && $targetNodeExists) {
402
+            throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode->getName() . ', target exists');
403
+        }
404
+
405
+        [$sourceDir,] = \Sabre\Uri\split($sourceNode->getPath());
406
+        $destinationDir = $this->getPath();
407
+
408
+        $sourcePath = $sourceNode->getPath();
409
+
410
+        $isMovableMount = false;
411
+        $sourceMount = \OC::$server->getMountManager()->find($this->fileView->getAbsolutePath($sourcePath));
412
+        $internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath));
413
+        if ($sourceMount instanceof MoveableMount && $internalPath === '') {
414
+            $isMovableMount = true;
415
+        }
416
+
417
+        try {
418
+            $sameFolder = ($sourceDir === $destinationDir);
419
+            // if we're overwriting or same folder
420
+            if ($targetNodeExists || $sameFolder) {
421
+                // note that renaming a share mount point is always allowed
422
+                if (!$this->fileView->isUpdatable($destinationDir) && !$isMovableMount) {
423
+                    throw new \Sabre\DAV\Exception\Forbidden();
424
+                }
425
+            } else {
426
+                if (!$this->fileView->isCreatable($destinationDir)) {
427
+                    throw new \Sabre\DAV\Exception\Forbidden();
428
+                }
429
+            }
430
+
431
+            if (!$sameFolder) {
432
+                // moving to a different folder, source will be gone, like a deletion
433
+                // note that moving a share mount point is always allowed
434
+                if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) {
435
+                    throw new \Sabre\DAV\Exception\Forbidden();
436
+                }
437
+            }
438
+
439
+            $fileName = basename($destinationPath);
440
+            try {
441
+                $this->fileView->verifyPath($destinationDir, $fileName);
442
+            } catch (InvalidPathException $ex) {
443
+                throw new InvalidPath($ex->getMessage());
444
+            }
445
+
446
+            $renameOkay = $this->fileView->rename($sourcePath, $destinationPath);
447
+            if (!$renameOkay) {
448
+                throw new \Sabre\DAV\Exception\Forbidden('');
449
+            }
450
+        } catch (StorageNotAvailableException $e) {
451
+            throw new ServiceUnavailable($e->getMessage());
452
+        } catch (ForbiddenException $ex) {
453
+            throw new Forbidden($ex->getMessage(), $ex->getRetry());
454
+        } catch (LockedException $e) {
455
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
456
+        }
457
+
458
+        return true;
459
+    }
460
+
461
+
462
+    public function copyInto($targetName, $sourcePath, INode $sourceNode) {
463
+        if ($sourceNode instanceof File || $sourceNode instanceof Directory) {
464
+            $destinationPath = $this->getPath() . '/' . $targetName;
465
+            $sourcePath = $sourceNode->getPath();
466
+
467
+            if (!$this->fileView->isCreatable($this->getPath())) {
468
+                throw new \Sabre\DAV\Exception\Forbidden();
469
+            }
470
+
471
+            try {
472
+                $this->fileView->verifyPath($this->getPath(), $targetName);
473
+            } catch (InvalidPathException $ex) {
474
+                throw new InvalidPath($ex->getMessage());
475
+            }
476
+
477
+            return $this->fileView->copy($sourcePath, $destinationPath);
478
+        }
479
+
480
+        return false;
481
+    }
482
+
483
+    public function getNode(): Folder {
484
+        return $this->node;
485
+    }
486 486
 }
Please login to merge, or discard this patch.
lib/private/Cache/File.php 2 patches
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -55,10 +55,10 @@  discard block
 block discarded – undo
55 55
 			$rootView = new View();
56 56
 			$user = \OC::$server->getUserSession()->getUser();
57 57
 			Filesystem::initMountPoints($user->getUID());
58
-			if (!$rootView->file_exists('/' . $user->getUID() . '/cache')) {
59
-				$rootView->mkdir('/' . $user->getUID() . '/cache');
58
+			if (!$rootView->file_exists('/'.$user->getUID().'/cache')) {
59
+				$rootView->mkdir('/'.$user->getUID().'/cache');
60 60
 			}
61
-			$this->storage = new View('/' . $user->getUID() . '/cache');
61
+			$this->storage = new View('/'.$user->getUID().'/cache');
62 62
 			return $this->storage;
63 63
 		} else {
64 64
 			\OC::$server->get(LoggerInterface::class)->error('Can\'t get cache storage, user not logged in', ['app' => 'core']);
@@ -113,7 +113,7 @@  discard block
 block discarded – undo
113 113
 
114 114
 		// use part file to prevent hasKey() to find the key
115 115
 		// while it is being written
116
-		$keyPart = $key . '.' . $uniqueId . '.part';
116
+		$keyPart = $key.'.'.$uniqueId.'.part';
117 117
 		if ($storage and $storage->file_put_contents($keyPart, $value)) {
118 118
 			if ($ttl === 0) {
119 119
 				$ttl = 86400; // 60*60*24
@@ -162,7 +162,7 @@  discard block
 block discarded – undo
162 162
 			if (is_resource($dh)) {
163 163
 				while (($file = readdir($dh)) !== false) {
164 164
 					if ($file != '.' and $file != '..' and ($prefix === '' || strpos($file, $prefix) === 0)) {
165
-						$storage->unlink('/' . $file);
165
+						$storage->unlink('/'.$file);
166 166
 					}
167 167
 				}
168 168
 			}
@@ -187,17 +187,17 @@  discard block
 block discarded – undo
187 187
 			while (($file = readdir($dh)) !== false) {
188 188
 				if ($file != '.' and $file != '..') {
189 189
 					try {
190
-						$mtime = $storage->filemtime('/' . $file);
190
+						$mtime = $storage->filemtime('/'.$file);
191 191
 						if ($mtime < $now) {
192
-							$storage->unlink('/' . $file);
192
+							$storage->unlink('/'.$file);
193 193
 						}
194 194
 					} catch (\OCP\Lock\LockedException $e) {
195 195
 						// ignore locked chunks
196
-						\OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
196
+						\OC::$server->getLogger()->debug('Could not cleanup locked chunk "'.$file.'"', ['app' => 'core']);
197 197
 					} catch (\OCP\Files\ForbiddenException $e) {
198
-						\OC::$server->getLogger()->debug('Could not cleanup forbidden chunk "' . $file . '"', ['app' => 'core']);
198
+						\OC::$server->getLogger()->debug('Could not cleanup forbidden chunk "'.$file.'"', ['app' => 'core']);
199 199
 					} catch (\OCP\Files\LockNotAcquiredException $e) {
200
-						\OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
200
+						\OC::$server->getLogger()->debug('Could not cleanup locked chunk "'.$file.'"', ['app' => 'core']);
201 201
 					}
202 202
 				}
203 203
 			}
Please login to merge, or discard this patch.
Indentation   +160 added lines, -160 removed lines patch added patch discarded remove patch
@@ -36,174 +36,174 @@
 block discarded – undo
36 36
 use Psr\Log\LoggerInterface;
37 37
 
38 38
 class File implements ICache {
39
-	/** @var View */
40
-	protected $storage;
39
+    /** @var View */
40
+    protected $storage;
41 41
 
42
-	/**
43
-	 * Returns the cache storage for the logged in user
44
-	 *
45
-	 * @return \OC\Files\View cache storage
46
-	 * @throws \OC\ForbiddenException
47
-	 * @throws \OC\User\NoUserException
48
-	 */
49
-	protected function getStorage() {
50
-		if ($this->storage !== null) {
51
-			return $this->storage;
52
-		}
53
-		if (\OC::$server->getUserSession()->isLoggedIn()) {
54
-			$rootView = new View();
55
-			$user = \OC::$server->getUserSession()->getUser();
56
-			Filesystem::initMountPoints($user->getUID());
57
-			if (!$rootView->file_exists('/' . $user->getUID() . '/cache')) {
58
-				$rootView->mkdir('/' . $user->getUID() . '/cache');
59
-			}
60
-			$this->storage = new View('/' . $user->getUID() . '/cache');
61
-			return $this->storage;
62
-		} else {
63
-			\OC::$server->get(LoggerInterface::class)->error('Can\'t get cache storage, user not logged in', ['app' => 'core']);
64
-			throw new \OC\ForbiddenException('Can\t get cache storage, user not logged in');
65
-		}
66
-	}
42
+    /**
43
+     * Returns the cache storage for the logged in user
44
+     *
45
+     * @return \OC\Files\View cache storage
46
+     * @throws \OC\ForbiddenException
47
+     * @throws \OC\User\NoUserException
48
+     */
49
+    protected function getStorage() {
50
+        if ($this->storage !== null) {
51
+            return $this->storage;
52
+        }
53
+        if (\OC::$server->getUserSession()->isLoggedIn()) {
54
+            $rootView = new View();
55
+            $user = \OC::$server->getUserSession()->getUser();
56
+            Filesystem::initMountPoints($user->getUID());
57
+            if (!$rootView->file_exists('/' . $user->getUID() . '/cache')) {
58
+                $rootView->mkdir('/' . $user->getUID() . '/cache');
59
+            }
60
+            $this->storage = new View('/' . $user->getUID() . '/cache');
61
+            return $this->storage;
62
+        } else {
63
+            \OC::$server->get(LoggerInterface::class)->error('Can\'t get cache storage, user not logged in', ['app' => 'core']);
64
+            throw new \OC\ForbiddenException('Can\t get cache storage, user not logged in');
65
+        }
66
+    }
67 67
 
68
-	/**
69
-	 * @param string $key
70
-	 * @return mixed|null
71
-	 * @throws \OC\ForbiddenException
72
-	 */
73
-	public function get($key) {
74
-		$result = null;
75
-		if ($this->hasKey($key)) {
76
-			$storage = $this->getStorage();
77
-			$result = $storage->file_get_contents($key);
78
-		}
79
-		return $result;
80
-	}
68
+    /**
69
+     * @param string $key
70
+     * @return mixed|null
71
+     * @throws \OC\ForbiddenException
72
+     */
73
+    public function get($key) {
74
+        $result = null;
75
+        if ($this->hasKey($key)) {
76
+            $storage = $this->getStorage();
77
+            $result = $storage->file_get_contents($key);
78
+        }
79
+        return $result;
80
+    }
81 81
 
82
-	/**
83
-	 * Returns the size of the stored/cached data
84
-	 *
85
-	 * @param string $key
86
-	 * @return int
87
-	 */
88
-	public function size($key) {
89
-		$result = 0;
90
-		if ($this->hasKey($key)) {
91
-			$storage = $this->getStorage();
92
-			$result = $storage->filesize($key);
93
-		}
94
-		return $result;
95
-	}
82
+    /**
83
+     * Returns the size of the stored/cached data
84
+     *
85
+     * @param string $key
86
+     * @return int
87
+     */
88
+    public function size($key) {
89
+        $result = 0;
90
+        if ($this->hasKey($key)) {
91
+            $storage = $this->getStorage();
92
+            $result = $storage->filesize($key);
93
+        }
94
+        return $result;
95
+    }
96 96
 
97
-	/**
98
-	 * @param string $key
99
-	 * @param mixed $value
100
-	 * @param int $ttl
101
-	 * @return bool|mixed
102
-	 * @throws \OC\ForbiddenException
103
-	 */
104
-	public function set($key, $value, $ttl = 0) {
105
-		$storage = $this->getStorage();
106
-		$result = false;
107
-		// unique id to avoid chunk collision, just in case
108
-		$uniqueId = \OC::$server->getSecureRandom()->generate(
109
-			16,
110
-			ISecureRandom::CHAR_ALPHANUMERIC
111
-		);
97
+    /**
98
+     * @param string $key
99
+     * @param mixed $value
100
+     * @param int $ttl
101
+     * @return bool|mixed
102
+     * @throws \OC\ForbiddenException
103
+     */
104
+    public function set($key, $value, $ttl = 0) {
105
+        $storage = $this->getStorage();
106
+        $result = false;
107
+        // unique id to avoid chunk collision, just in case
108
+        $uniqueId = \OC::$server->getSecureRandom()->generate(
109
+            16,
110
+            ISecureRandom::CHAR_ALPHANUMERIC
111
+        );
112 112
 
113
-		// use part file to prevent hasKey() to find the key
114
-		// while it is being written
115
-		$keyPart = $key . '.' . $uniqueId . '.part';
116
-		if ($storage and $storage->file_put_contents($keyPart, $value)) {
117
-			if ($ttl === 0) {
118
-				$ttl = 86400; // 60*60*24
119
-			}
120
-			$result = $storage->touch($keyPart, time() + $ttl);
121
-			$result &= $storage->rename($keyPart, $key);
122
-		}
123
-		return $result;
124
-	}
113
+        // use part file to prevent hasKey() to find the key
114
+        // while it is being written
115
+        $keyPart = $key . '.' . $uniqueId . '.part';
116
+        if ($storage and $storage->file_put_contents($keyPart, $value)) {
117
+            if ($ttl === 0) {
118
+                $ttl = 86400; // 60*60*24
119
+            }
120
+            $result = $storage->touch($keyPart, time() + $ttl);
121
+            $result &= $storage->rename($keyPart, $key);
122
+        }
123
+        return $result;
124
+    }
125 125
 
126
-	/**
127
-	 * @param string $key
128
-	 * @return bool
129
-	 * @throws \OC\ForbiddenException
130
-	 */
131
-	public function hasKey($key) {
132
-		$storage = $this->getStorage();
133
-		if ($storage && $storage->is_file($key) && $storage->isReadable($key)) {
134
-			return true;
135
-		}
136
-		return false;
137
-	}
126
+    /**
127
+     * @param string $key
128
+     * @return bool
129
+     * @throws \OC\ForbiddenException
130
+     */
131
+    public function hasKey($key) {
132
+        $storage = $this->getStorage();
133
+        if ($storage && $storage->is_file($key) && $storage->isReadable($key)) {
134
+            return true;
135
+        }
136
+        return false;
137
+    }
138 138
 
139
-	/**
140
-	 * @param string $key
141
-	 * @return bool|mixed
142
-	 * @throws \OC\ForbiddenException
143
-	 */
144
-	public function remove($key) {
145
-		$storage = $this->getStorage();
146
-		if (!$storage) {
147
-			return false;
148
-		}
149
-		return $storage->unlink($key);
150
-	}
139
+    /**
140
+     * @param string $key
141
+     * @return bool|mixed
142
+     * @throws \OC\ForbiddenException
143
+     */
144
+    public function remove($key) {
145
+        $storage = $this->getStorage();
146
+        if (!$storage) {
147
+            return false;
148
+        }
149
+        return $storage->unlink($key);
150
+    }
151 151
 
152
-	/**
153
-	 * @param string $prefix
154
-	 * @return bool
155
-	 * @throws \OC\ForbiddenException
156
-	 */
157
-	public function clear($prefix = '') {
158
-		$storage = $this->getStorage();
159
-		if ($storage and $storage->is_dir('/')) {
160
-			$dh = $storage->opendir('/');
161
-			if (is_resource($dh)) {
162
-				while (($file = readdir($dh)) !== false) {
163
-					if ($file != '.' and $file != '..' and ($prefix === '' || strpos($file, $prefix) === 0)) {
164
-						$storage->unlink('/' . $file);
165
-					}
166
-				}
167
-			}
168
-		}
169
-		return true;
170
-	}
152
+    /**
153
+     * @param string $prefix
154
+     * @return bool
155
+     * @throws \OC\ForbiddenException
156
+     */
157
+    public function clear($prefix = '') {
158
+        $storage = $this->getStorage();
159
+        if ($storage and $storage->is_dir('/')) {
160
+            $dh = $storage->opendir('/');
161
+            if (is_resource($dh)) {
162
+                while (($file = readdir($dh)) !== false) {
163
+                    if ($file != '.' and $file != '..' and ($prefix === '' || strpos($file, $prefix) === 0)) {
164
+                        $storage->unlink('/' . $file);
165
+                    }
166
+                }
167
+            }
168
+        }
169
+        return true;
170
+    }
171 171
 
172
-	/**
173
-	 * Runs GC
174
-	 * @throws \OC\ForbiddenException
175
-	 */
176
-	public function gc() {
177
-		$storage = $this->getStorage();
178
-		if ($storage) {
179
-			// extra hour safety, in case of stray part chunks that take longer to write,
180
-			// because touch() is only called after the chunk was finished
181
-			$now = time() - 3600;
182
-			$dh = $storage->opendir('/');
183
-			if (!is_resource($dh)) {
184
-				return null;
185
-			}
186
-			while (($file = readdir($dh)) !== false) {
187
-				if ($file != '.' and $file != '..') {
188
-					try {
189
-						$mtime = $storage->filemtime('/' . $file);
190
-						if ($mtime < $now) {
191
-							$storage->unlink('/' . $file);
192
-						}
193
-					} catch (\OCP\Lock\LockedException $e) {
194
-						// ignore locked chunks
195
-						\OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
196
-					} catch (\OCP\Files\ForbiddenException $e) {
197
-						\OC::$server->getLogger()->debug('Could not cleanup forbidden chunk "' . $file . '"', ['app' => 'core']);
198
-					} catch (\OCP\Files\LockNotAcquiredException $e) {
199
-						\OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
200
-					}
201
-				}
202
-			}
203
-		}
204
-	}
172
+    /**
173
+     * Runs GC
174
+     * @throws \OC\ForbiddenException
175
+     */
176
+    public function gc() {
177
+        $storage = $this->getStorage();
178
+        if ($storage) {
179
+            // extra hour safety, in case of stray part chunks that take longer to write,
180
+            // because touch() is only called after the chunk was finished
181
+            $now = time() - 3600;
182
+            $dh = $storage->opendir('/');
183
+            if (!is_resource($dh)) {
184
+                return null;
185
+            }
186
+            while (($file = readdir($dh)) !== false) {
187
+                if ($file != '.' and $file != '..') {
188
+                    try {
189
+                        $mtime = $storage->filemtime('/' . $file);
190
+                        if ($mtime < $now) {
191
+                            $storage->unlink('/' . $file);
192
+                        }
193
+                    } catch (\OCP\Lock\LockedException $e) {
194
+                        // ignore locked chunks
195
+                        \OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
196
+                    } catch (\OCP\Files\ForbiddenException $e) {
197
+                        \OC::$server->getLogger()->debug('Could not cleanup forbidden chunk "' . $file . '"', ['app' => 'core']);
198
+                    } catch (\OCP\Files\LockNotAcquiredException $e) {
199
+                        \OC::$server->getLogger()->debug('Could not cleanup locked chunk "' . $file . '"', ['app' => 'core']);
200
+                    }
201
+                }
202
+            }
203
+        }
204
+    }
205 205
 
206
-	public static function isAvailable(): bool {
207
-		return true;
208
-	}
206
+    public static function isAvailable(): bool {
207
+        return true;
208
+    }
209 209
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/File.php 2 patches
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -165,7 +165,7 @@  discard block
 block discarded – undo
165 165
 
166 166
 		if ($needsPartFile) {
167 167
 			// mark file as partial while uploading (ignored by the scanner)
168
-			$partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part';
168
+			$partFilePath = $this->getPartFileBasePath($this->path).'.ocTransferId'.rand().'.part';
169 169
 
170 170
 			if (!$view->isCreatable($partFilePath) && $view->isUpdatable($this->path)) {
171 171
 				$needsPartFile = false;
@@ -218,27 +218,27 @@  discard block
 block discarded – undo
218 218
 			if ($this->request->getHeader('X-HASH') !== '') {
219 219
 				$hash = $this->request->getHeader('X-HASH');
220 220
 				if ($hash === 'all' || $hash === 'md5') {
221
-					$data = HashWrapper::wrap($data, 'md5', function ($hash) {
222
-						$this->header('X-Hash-MD5: ' . $hash);
221
+					$data = HashWrapper::wrap($data, 'md5', function($hash) {
222
+						$this->header('X-Hash-MD5: '.$hash);
223 223
 					});
224 224
 				}
225 225
 
226 226
 				if ($hash === 'all' || $hash === 'sha1') {
227
-					$data = HashWrapper::wrap($data, 'sha1', function ($hash) {
228
-						$this->header('X-Hash-SHA1: ' . $hash);
227
+					$data = HashWrapper::wrap($data, 'sha1', function($hash) {
228
+						$this->header('X-Hash-SHA1: '.$hash);
229 229
 					});
230 230
 				}
231 231
 
232 232
 				if ($hash === 'all' || $hash === 'sha256') {
233
-					$data = HashWrapper::wrap($data, 'sha256', function ($hash) {
234
-						$this->header('X-Hash-SHA256: ' . $hash);
233
+					$data = HashWrapper::wrap($data, 'sha256', function($hash) {
234
+						$this->header('X-Hash-SHA256: '.$hash);
235 235
 					});
236 236
 				}
237 237
 			}
238 238
 
239 239
 			if ($partStorage->instanceOfStorage(Storage\IWriteStreamStorage::class)) {
240 240
 				$isEOF = false;
241
-				$wrappedData = CallbackWrapper::wrap($data, null, null, null, null, function ($stream) use (&$isEOF) {
241
+				$wrappedData = CallbackWrapper::wrap($data, null, null, null, null, function($stream) use (&$isEOF) {
242 242
 					$isEOF = feof($stream);
243 243
 				});
244 244
 
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
 			if ($result === false) {
274 274
 				$expected = -1;
275 275
 				if (isset($_SERVER['CONTENT_LENGTH'])) {
276
-					$expected = (int)$_SERVER['CONTENT_LENGTH'];
276
+					$expected = (int) $_SERVER['CONTENT_LENGTH'];
277 277
 				}
278 278
 				if ($expected !== 0) {
279 279
 					throw new Exception(
@@ -292,7 +292,7 @@  discard block
 block discarded – undo
292 292
 			// double check if the file was fully received
293 293
 			// compare expected and actual size
294 294
 			if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
295
-				$expected = (int)$_SERVER['CONTENT_LENGTH'];
295
+				$expected = (int) $_SERVER['CONTENT_LENGTH'];
296 296
 				if ($count !== $expected) {
297 297
 					throw new BadRequest(
298 298
 						$this->l10n->t(
@@ -350,7 +350,7 @@  discard block
 block discarded – undo
350 350
 					$renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath);
351 351
 					$fileExists = $storage->file_exists($internalPath);
352 352
 					if ($renameOkay === false || $fileExists === false) {
353
-						\OC::$server->get(LoggerInterface::class)->error('renaming part file to final file failed $renameOkay: ' . ($renameOkay ? 'true' : 'false') . ', $fileExists: ' . ($fileExists ? 'true' : 'false') . ')', ['app' => 'webdav']);
353
+						\OC::$server->get(LoggerInterface::class)->error('renaming part file to final file failed $renameOkay: '.($renameOkay ? 'true' : 'false').', $fileExists: '.($fileExists ? 'true' : 'false').')', ['app' => 'webdav']);
354 354
 						throw new Exception($this->l10n->t('Could not rename part file to final file'));
355 355
 					}
356 356
 				} catch (ForbiddenException $ex) {
@@ -410,7 +410,7 @@  discard block
 block discarded – undo
410 410
 			throw new ServiceUnavailable($this->l10n->t('Failed to check file size: %1$s', [$e->getMessage()]), 0, $e);
411 411
 		}
412 412
 
413
-		return '"' . $this->info->getEtag() . '"';
413
+		return '"'.$this->info->getEtag().'"';
414 414
 	}
415 415
 
416 416
 	private function getPartFileBasePath($path) {
@@ -500,7 +500,7 @@  discard block
 block discarded – undo
500 500
 			// if different, fix DB and refresh cache.
501 501
 			if ($this->getSize() !== $this->fileView->filesize($this->getPath())) {
502 502
 				$logger = \OC::$server->get(LoggerInterface::class);
503
-				$logger->warning('fixing cached size of file id=' . $this->getId());
503
+				$logger->warning('fixing cached size of file id='.$this->getId());
504 504
 
505 505
 				$this->getFileInfo()->getStorage()->getUpdater()->update($this->getFileInfo()->getInternalPath());
506 506
 				$this->refreshInfo();
@@ -599,7 +599,7 @@  discard block
 block discarded – undo
599 599
 		//detect aborted upload
600 600
 		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
601 601
 			if (isset($_SERVER['CONTENT_LENGTH'])) {
602
-				$expected = (int)$_SERVER['CONTENT_LENGTH'];
602
+				$expected = (int) $_SERVER['CONTENT_LENGTH'];
603 603
 				if ($bytesWritten !== $expected) {
604 604
 					$chunk_handler->remove($info['index']);
605 605
 					throw new BadRequest(
@@ -617,11 +617,11 @@  discard block
 block discarded – undo
617 617
 
618 618
 		if ($chunk_handler->isComplete()) {
619 619
 			/** @var Storage $storage */
620
-			[$storage,] = $this->fileView->resolvePath($path);
620
+			[$storage, ] = $this->fileView->resolvePath($path);
621 621
 			$needsPartFile = $storage->needsPartFile();
622 622
 			$partFile = null;
623 623
 
624
-			$targetPath = $path . '/' . $info['name'];
624
+			$targetPath = $path.'/'.$info['name'];
625 625
 			/** @var \OC\Files\Storage\Storage $targetStorage */
626 626
 			[$targetStorage, $targetInternalPath] = $this->fileView->resolvePath($targetPath);
627 627
 
@@ -637,7 +637,7 @@  discard block
 block discarded – undo
637 637
 
638 638
 				if ($needsPartFile) {
639 639
 					// we first assembly the target file as a part file
640
-					$partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part';
640
+					$partFile = $this->getPartFileBasePath($path.'/'.$info['name']).'.ocTransferId'.$info['transferid'].'.part';
641 641
 					/** @var \OC\Files\Storage\Storage $targetStorage */
642 642
 					[$partStorage, $partInternalPath] = $this->fileView->resolvePath($partFile);
643 643
 
Please login to merge, or discard this patch.
Indentation   +715 added lines, -715 removed lines patch added patch discarded remove patch
@@ -77,719 +77,719 @@
 block discarded – undo
77 77
 use Sabre\DAV\IFile;
78 78
 
79 79
 class File extends Node implements IFile {
80
-	protected $request;
81
-
82
-	protected IL10N $l10n;
83
-
84
-	/** @var array<string, FileMetadata> */
85
-	private array $metadata = [];
86
-
87
-	/**
88
-	 * Sets up the node, expects a full path name
89
-	 *
90
-	 * @param \OC\Files\View $view
91
-	 * @param \OCP\Files\FileInfo $info
92
-	 * @param \OCP\Share\IManager $shareManager
93
-	 * @param \OC\AppFramework\Http\Request $request
94
-	 */
95
-	public function __construct(View $view, FileInfo $info, IManager $shareManager = null, Request $request = null) {
96
-		parent::__construct($view, $info, $shareManager);
97
-
98
-		// Querying IL10N directly results in a dependency loop
99
-		/** @var IL10NFactory $l10nFactory */
100
-		$l10nFactory = \OC::$server->get(IL10NFactory::class);
101
-		$this->l10n = $l10nFactory->get(Application::APP_ID);
102
-
103
-		if (isset($request)) {
104
-			$this->request = $request;
105
-		} else {
106
-			$this->request = \OC::$server->getRequest();
107
-		}
108
-	}
109
-
110
-	/**
111
-	 * Updates the data
112
-	 *
113
-	 * The data argument is a readable stream resource.
114
-	 *
115
-	 * After a successful put operation, you may choose to return an ETag. The
116
-	 * etag must always be surrounded by double-quotes. These quotes must
117
-	 * appear in the actual string you're returning.
118
-	 *
119
-	 * Clients may use the ETag from a PUT request to later on make sure that
120
-	 * when they update the file, the contents haven't changed in the mean
121
-	 * time.
122
-	 *
123
-	 * If you don't plan to store the file byte-by-byte, and you return a
124
-	 * different object on a subsequent GET you are strongly recommended to not
125
-	 * return an ETag, and just return null.
126
-	 *
127
-	 * @param resource $data
128
-	 *
129
-	 * @throws Forbidden
130
-	 * @throws UnsupportedMediaType
131
-	 * @throws BadRequest
132
-	 * @throws Exception
133
-	 * @throws EntityTooLarge
134
-	 * @throws ServiceUnavailable
135
-	 * @throws FileLocked
136
-	 * @return string|null
137
-	 */
138
-	public function put($data) {
139
-		try {
140
-			$exists = $this->fileView->file_exists($this->path);
141
-			if ($exists && !$this->info->isUpdateable()) {
142
-				throw new Forbidden();
143
-			}
144
-		} catch (StorageNotAvailableException $e) {
145
-			throw new ServiceUnavailable($this->l10n->t('File is not updatable: %1$s', [$e->getMessage()]));
146
-		}
147
-
148
-		// verify path of the target
149
-		$this->verifyPath();
150
-
151
-		// chunked handling
152
-		if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
153
-			try {
154
-				return $this->createFileChunked($data);
155
-			} catch (\Exception $e) {
156
-				$this->convertToSabreException($e);
157
-			}
158
-		}
159
-
160
-		/** @var Storage $partStorage */
161
-		[$partStorage] = $this->fileView->resolvePath($this->path);
162
-		$needsPartFile = $partStorage->needsPartFile() && (strlen($this->path) > 1);
163
-
164
-		$view = \OC\Files\Filesystem::getView();
165
-
166
-		if ($needsPartFile) {
167
-			// mark file as partial while uploading (ignored by the scanner)
168
-			$partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part';
169
-
170
-			if (!$view->isCreatable($partFilePath) && $view->isUpdatable($this->path)) {
171
-				$needsPartFile = false;
172
-			}
173
-		}
174
-		if (!$needsPartFile) {
175
-			// upload file directly as the final path
176
-			$partFilePath = $this->path;
177
-
178
-			if ($view && !$this->emitPreHooks($exists)) {
179
-				throw new Exception($this->l10n->t('Could not write to final file, canceled by hook'));
180
-			}
181
-		}
182
-
183
-		// the part file and target file might be on a different storage in case of a single file storage (e.g. single file share)
184
-		/** @var \OC\Files\Storage\Storage $partStorage */
185
-		[$partStorage, $internalPartPath] = $this->fileView->resolvePath($partFilePath);
186
-		/** @var \OC\Files\Storage\Storage $storage */
187
-		[$storage, $internalPath] = $this->fileView->resolvePath($this->path);
188
-		try {
189
-			if (!$needsPartFile) {
190
-				try {
191
-					$this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
192
-				} catch (LockedException $e) {
193
-					// during very large uploads, the shared lock we got at the start might have been expired
194
-					// meaning that the above lock can fail not just only because somebody else got a shared lock
195
-					// or because there is no existing shared lock to make exclusive
196
-					//
197
-					// Thus we try to get a new exclusive lock, if the original lock failed because of a different shared
198
-					// lock this will still fail, if our original shared lock expired the new lock will be successful and
199
-					// the entire operation will be safe
200
-
201
-					try {
202
-						$this->acquireLock(ILockingProvider::LOCK_EXCLUSIVE);
203
-					} catch (LockedException $ex) {
204
-						throw new FileLocked($e->getMessage(), $e->getCode(), $e);
205
-					}
206
-				}
207
-			}
208
-
209
-			if (!is_resource($data)) {
210
-				$tmpData = fopen('php://temp', 'r+');
211
-				if ($data !== null) {
212
-					fwrite($tmpData, $data);
213
-					rewind($tmpData);
214
-				}
215
-				$data = $tmpData;
216
-			}
217
-
218
-			if ($this->request->getHeader('X-HASH') !== '') {
219
-				$hash = $this->request->getHeader('X-HASH');
220
-				if ($hash === 'all' || $hash === 'md5') {
221
-					$data = HashWrapper::wrap($data, 'md5', function ($hash) {
222
-						$this->header('X-Hash-MD5: ' . $hash);
223
-					});
224
-				}
225
-
226
-				if ($hash === 'all' || $hash === 'sha1') {
227
-					$data = HashWrapper::wrap($data, 'sha1', function ($hash) {
228
-						$this->header('X-Hash-SHA1: ' . $hash);
229
-					});
230
-				}
231
-
232
-				if ($hash === 'all' || $hash === 'sha256') {
233
-					$data = HashWrapper::wrap($data, 'sha256', function ($hash) {
234
-						$this->header('X-Hash-SHA256: ' . $hash);
235
-					});
236
-				}
237
-			}
238
-
239
-			if ($partStorage->instanceOfStorage(Storage\IWriteStreamStorage::class)) {
240
-				$isEOF = false;
241
-				$wrappedData = CallbackWrapper::wrap($data, null, null, null, null, function ($stream) use (&$isEOF) {
242
-					$isEOF = feof($stream);
243
-				});
244
-
245
-				$result = true;
246
-				$count = -1;
247
-				try {
248
-					$count = $partStorage->writeStream($internalPartPath, $wrappedData);
249
-				} catch (GenericFileException $e) {
250
-					$result = false;
251
-				} catch (BadGateway $e) {
252
-					throw $e;
253
-				}
254
-
255
-
256
-				if ($result === false) {
257
-					$result = $isEOF;
258
-					if (is_resource($wrappedData)) {
259
-						$result = feof($wrappedData);
260
-					}
261
-				}
262
-			} else {
263
-				$target = $partStorage->fopen($internalPartPath, 'wb');
264
-				if ($target === false) {
265
-					\OC::$server->get(LoggerInterface::class)->error('\OC\Files\Filesystem::fopen() failed', ['app' => 'webdav']);
266
-					// because we have no clue about the cause we can only throw back a 500/Internal Server Error
267
-					throw new Exception($this->l10n->t('Could not write file contents'));
268
-				}
269
-				[$count, $result] = \OC_Helper::streamCopy($data, $target);
270
-				fclose($target);
271
-			}
272
-
273
-			if ($result === false) {
274
-				$expected = -1;
275
-				if (isset($_SERVER['CONTENT_LENGTH'])) {
276
-					$expected = (int)$_SERVER['CONTENT_LENGTH'];
277
-				}
278
-				if ($expected !== 0) {
279
-					throw new Exception(
280
-						$this->l10n->t(
281
-							'Error while copying file to target location (copied: %1$s, expected filesize: %2$s)',
282
-							[
283
-								$this->l10n->n('%n byte', '%n bytes', $count),
284
-								$this->l10n->n('%n byte', '%n bytes', $expected),
285
-							],
286
-						)
287
-					);
288
-				}
289
-			}
290
-
291
-			// if content length is sent by client:
292
-			// double check if the file was fully received
293
-			// compare expected and actual size
294
-			if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
295
-				$expected = (int)$_SERVER['CONTENT_LENGTH'];
296
-				if ($count !== $expected) {
297
-					throw new BadRequest(
298
-						$this->l10n->t(
299
-							'Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side.',
300
-							[
301
-								$this->l10n->n('%n byte', '%n bytes', $expected),
302
-								$this->l10n->n('%n byte', '%n bytes', $count),
303
-							],
304
-						)
305
-					);
306
-				}
307
-			}
308
-		} catch (\Exception $e) {
309
-			if ($e instanceof LockedException) {
310
-				\OC::$server->get(LoggerInterface::class)->debug($e->getMessage(), ['exception' => $e]);
311
-			} else {
312
-				\OC::$server->get(LoggerInterface::class)->error($e->getMessage(), ['exception' => $e]);
313
-			}
314
-
315
-			if ($needsPartFile) {
316
-				$partStorage->unlink($internalPartPath);
317
-			}
318
-			$this->convertToSabreException($e);
319
-		}
320
-
321
-		try {
322
-			if ($needsPartFile) {
323
-				if ($view && !$this->emitPreHooks($exists)) {
324
-					$partStorage->unlink($internalPartPath);
325
-					throw new Exception($this->l10n->t('Could not rename part file to final file, canceled by hook'));
326
-				}
327
-				try {
328
-					$this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
329
-				} catch (LockedException $e) {
330
-					// during very large uploads, the shared lock we got at the start might have been expired
331
-					// meaning that the above lock can fail not just only because somebody else got a shared lock
332
-					// or because there is no existing shared lock to make exclusive
333
-					//
334
-					// Thus we try to get a new exclusive lock, if the original lock failed because of a different shared
335
-					// lock this will still fail, if our original shared lock expired the new lock will be successful and
336
-					// the entire operation will be safe
337
-
338
-					try {
339
-						$this->acquireLock(ILockingProvider::LOCK_EXCLUSIVE);
340
-					} catch (LockedException $ex) {
341
-						if ($needsPartFile) {
342
-							$partStorage->unlink($internalPartPath);
343
-						}
344
-						throw new FileLocked($e->getMessage(), $e->getCode(), $e);
345
-					}
346
-				}
347
-
348
-				// rename to correct path
349
-				try {
350
-					$renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath);
351
-					$fileExists = $storage->file_exists($internalPath);
352
-					if ($renameOkay === false || $fileExists === false) {
353
-						\OC::$server->get(LoggerInterface::class)->error('renaming part file to final file failed $renameOkay: ' . ($renameOkay ? 'true' : 'false') . ', $fileExists: ' . ($fileExists ? 'true' : 'false') . ')', ['app' => 'webdav']);
354
-						throw new Exception($this->l10n->t('Could not rename part file to final file'));
355
-					}
356
-				} catch (ForbiddenException $ex) {
357
-					if (!$ex->getRetry()) {
358
-						$partStorage->unlink($internalPartPath);
359
-					}
360
-					throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
361
-				} catch (\Exception $e) {
362
-					$partStorage->unlink($internalPartPath);
363
-					$this->convertToSabreException($e);
364
-				}
365
-			}
366
-
367
-			// since we skipped the view we need to scan and emit the hooks ourselves
368
-			$storage->getUpdater()->update($internalPath);
369
-
370
-			try {
371
-				$this->changeLock(ILockingProvider::LOCK_SHARED);
372
-			} catch (LockedException $e) {
373
-				throw new FileLocked($e->getMessage(), $e->getCode(), $e);
374
-			}
375
-
376
-			// allow sync clients to send the mtime along in a header
377
-			if (isset($this->request->server['HTTP_X_OC_MTIME'])) {
378
-				$mtime = $this->sanitizeMtime($this->request->server['HTTP_X_OC_MTIME']);
379
-				if ($this->fileView->touch($this->path, $mtime)) {
380
-					$this->header('X-OC-MTime: accepted');
381
-				}
382
-			}
383
-
384
-			$fileInfoUpdate = [
385
-				'upload_time' => time()
386
-			];
387
-
388
-			// allow sync clients to send the creation time along in a header
389
-			if (isset($this->request->server['HTTP_X_OC_CTIME'])) {
390
-				$ctime = $this->sanitizeMtime($this->request->server['HTTP_X_OC_CTIME']);
391
-				$fileInfoUpdate['creation_time'] = $ctime;
392
-				$this->header('X-OC-CTime: accepted');
393
-			}
394
-
395
-			$this->fileView->putFileInfo($this->path, $fileInfoUpdate);
396
-
397
-			if ($view) {
398
-				$this->emitPostHooks($exists);
399
-			}
400
-
401
-			$this->refreshInfo();
402
-
403
-			if (isset($this->request->server['HTTP_OC_CHECKSUM'])) {
404
-				$checksum = trim($this->request->server['HTTP_OC_CHECKSUM']);
405
-				$this->setChecksum($checksum);
406
-			} elseif ($this->getChecksum() !== null && $this->getChecksum() !== '') {
407
-				$this->setChecksum('');
408
-			}
409
-		} catch (StorageNotAvailableException $e) {
410
-			throw new ServiceUnavailable($this->l10n->t('Failed to check file size: %1$s', [$e->getMessage()]), 0, $e);
411
-		}
412
-
413
-		return '"' . $this->info->getEtag() . '"';
414
-	}
415
-
416
-	private function getPartFileBasePath($path) {
417
-		$partFileInStorage = \OC::$server->getConfig()->getSystemValue('part_file_in_storage', true);
418
-		if ($partFileInStorage) {
419
-			return $path;
420
-		} else {
421
-			return md5($path); // will place it in the root of the view with a unique name
422
-		}
423
-	}
424
-
425
-	/**
426
-	 * @param string $path
427
-	 */
428
-	private function emitPreHooks($exists, $path = null) {
429
-		if (is_null($path)) {
430
-			$path = $this->path;
431
-		}
432
-		$hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
433
-		$run = true;
434
-
435
-		if (!$exists) {
436
-			\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_create, [
437
-				\OC\Files\Filesystem::signal_param_path => $hookPath,
438
-				\OC\Files\Filesystem::signal_param_run => &$run,
439
-			]);
440
-		} else {
441
-			\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_update, [
442
-				\OC\Files\Filesystem::signal_param_path => $hookPath,
443
-				\OC\Files\Filesystem::signal_param_run => &$run,
444
-			]);
445
-		}
446
-		\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_write, [
447
-			\OC\Files\Filesystem::signal_param_path => $hookPath,
448
-			\OC\Files\Filesystem::signal_param_run => &$run,
449
-		]);
450
-		return $run;
451
-	}
452
-
453
-	/**
454
-	 * @param string $path
455
-	 */
456
-	private function emitPostHooks($exists, $path = null) {
457
-		if (is_null($path)) {
458
-			$path = $this->path;
459
-		}
460
-		$hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
461
-		if (!$exists) {
462
-			\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_create, [
463
-				\OC\Files\Filesystem::signal_param_path => $hookPath
464
-			]);
465
-		} else {
466
-			\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_update, [
467
-				\OC\Files\Filesystem::signal_param_path => $hookPath
468
-			]);
469
-		}
470
-		\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_write, [
471
-			\OC\Files\Filesystem::signal_param_path => $hookPath
472
-		]);
473
-	}
474
-
475
-	/**
476
-	 * Returns the data
477
-	 *
478
-	 * @return resource
479
-	 * @throws Forbidden
480
-	 * @throws ServiceUnavailable
481
-	 */
482
-	public function get() {
483
-		//throw exception if encryption is disabled but files are still encrypted
484
-		try {
485
-			if (!$this->info->isReadable()) {
486
-				// do a if the file did not exist
487
-				throw new NotFound();
488
-			}
489
-			try {
490
-				$res = $this->fileView->fopen(ltrim($this->path, '/'), 'rb');
491
-			} catch (\Exception $e) {
492
-				$this->convertToSabreException($e);
493
-			}
494
-
495
-			if ($res === false) {
496
-				throw new ServiceUnavailable($this->l10n->t('Could not open file'));
497
-			}
498
-
499
-			// comparing current file size with the one in DB
500
-			// if different, fix DB and refresh cache.
501
-			if ($this->getSize() !== $this->fileView->filesize($this->getPath())) {
502
-				$logger = \OC::$server->get(LoggerInterface::class);
503
-				$logger->warning('fixing cached size of file id=' . $this->getId());
504
-
505
-				$this->getFileInfo()->getStorage()->getUpdater()->update($this->getFileInfo()->getInternalPath());
506
-				$this->refreshInfo();
507
-			}
508
-
509
-			return $res;
510
-		} catch (GenericEncryptionException $e) {
511
-			// returning 503 will allow retry of the operation at a later point in time
512
-			throw new ServiceUnavailable($this->l10n->t('Encryption not ready: %1$s', [$e->getMessage()]));
513
-		} catch (StorageNotAvailableException $e) {
514
-			throw new ServiceUnavailable($this->l10n->t('Failed to open file: %1$s', [$e->getMessage()]));
515
-		} catch (ForbiddenException $ex) {
516
-			throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
517
-		} catch (LockedException $e) {
518
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
519
-		}
520
-	}
521
-
522
-	/**
523
-	 * Delete the current file
524
-	 *
525
-	 * @throws Forbidden
526
-	 * @throws ServiceUnavailable
527
-	 */
528
-	public function delete() {
529
-		if (!$this->info->isDeletable()) {
530
-			throw new Forbidden();
531
-		}
532
-
533
-		try {
534
-			if (!$this->fileView->unlink($this->path)) {
535
-				// assume it wasn't possible to delete due to permissions
536
-				throw new Forbidden();
537
-			}
538
-		} catch (StorageNotAvailableException $e) {
539
-			throw new ServiceUnavailable($this->l10n->t('Failed to unlink: %1$s', [$e->getMessage()]));
540
-		} catch (ForbiddenException $ex) {
541
-			throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
542
-		} catch (LockedException $e) {
543
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
544
-		}
545
-	}
546
-
547
-	/**
548
-	 * Returns the mime-type for a file
549
-	 *
550
-	 * If null is returned, we'll assume application/octet-stream
551
-	 *
552
-	 * @return string
553
-	 */
554
-	public function getContentType() {
555
-		$mimeType = $this->info->getMimetype();
556
-
557
-		// PROPFIND needs to return the correct mime type, for consistency with the web UI
558
-		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PROPFIND') {
559
-			return $mimeType;
560
-		}
561
-		return \OC::$server->getMimeTypeDetector()->getSecureMimeType($mimeType);
562
-	}
563
-
564
-	/**
565
-	 * @return array|bool
566
-	 */
567
-	public function getDirectDownload() {
568
-		if (\OCP\Server::get(\OCP\App\IAppManager::class)->isEnabledForUser('encryption')) {
569
-			return [];
570
-		}
571
-		/** @var \OCP\Files\Storage $storage */
572
-		[$storage, $internalPath] = $this->fileView->resolvePath($this->path);
573
-		if (is_null($storage)) {
574
-			return [];
575
-		}
576
-
577
-		return $storage->getDirectDownload($internalPath);
578
-	}
579
-
580
-	/**
581
-	 * @param resource $data
582
-	 * @return null|string
583
-	 * @throws Exception
584
-	 * @throws BadRequest
585
-	 * @throws NotImplemented
586
-	 * @throws ServiceUnavailable
587
-	 */
588
-	private function createFileChunked($data) {
589
-		[$path, $name] = \Sabre\Uri\split($this->path);
590
-
591
-		$info = \OC_FileChunking::decodeName($name);
592
-		if (empty($info)) {
593
-			throw new NotImplemented($this->l10n->t('Invalid chunk name'));
594
-		}
595
-
596
-		$chunk_handler = new \OC_FileChunking($info);
597
-		$bytesWritten = $chunk_handler->store($info['index'], $data);
598
-
599
-		//detect aborted upload
600
-		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
601
-			if (isset($_SERVER['CONTENT_LENGTH'])) {
602
-				$expected = (int)$_SERVER['CONTENT_LENGTH'];
603
-				if ($bytesWritten !== $expected) {
604
-					$chunk_handler->remove($info['index']);
605
-					throw new BadRequest(
606
-						$this->l10n->t(
607
-							'Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side.',
608
-							[
609
-								$this->l10n->n('%n byte', '%n bytes', $expected),
610
-								$this->l10n->n('%n byte', '%n bytes', $bytesWritten),
611
-							],
612
-						)
613
-					);
614
-				}
615
-			}
616
-		}
617
-
618
-		if ($chunk_handler->isComplete()) {
619
-			/** @var Storage $storage */
620
-			[$storage,] = $this->fileView->resolvePath($path);
621
-			$needsPartFile = $storage->needsPartFile();
622
-			$partFile = null;
623
-
624
-			$targetPath = $path . '/' . $info['name'];
625
-			/** @var \OC\Files\Storage\Storage $targetStorage */
626
-			[$targetStorage, $targetInternalPath] = $this->fileView->resolvePath($targetPath);
627
-
628
-			$exists = $this->fileView->file_exists($targetPath);
629
-
630
-			try {
631
-				$this->fileView->lockFile($targetPath, ILockingProvider::LOCK_SHARED);
632
-
633
-				$this->emitPreHooks($exists, $targetPath);
634
-				$this->fileView->changeLock($targetPath, ILockingProvider::LOCK_EXCLUSIVE);
635
-				/** @var \OC\Files\Storage\Storage $targetStorage */
636
-				[$targetStorage, $targetInternalPath] = $this->fileView->resolvePath($targetPath);
637
-
638
-				if ($needsPartFile) {
639
-					// we first assembly the target file as a part file
640
-					$partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part';
641
-					/** @var \OC\Files\Storage\Storage $targetStorage */
642
-					[$partStorage, $partInternalPath] = $this->fileView->resolvePath($partFile);
643
-
644
-
645
-					$chunk_handler->file_assemble($partStorage, $partInternalPath);
646
-
647
-					// here is the final atomic rename
648
-					$renameOkay = $targetStorage->moveFromStorage($partStorage, $partInternalPath, $targetInternalPath);
649
-					$fileExists = $targetStorage->file_exists($targetInternalPath);
650
-					if ($renameOkay === false || $fileExists === false) {
651
-						\OC::$server->get(LoggerInterface::class)->error('\OC\Files\Filesystem::rename() failed', ['app' => 'webdav']);
652
-						// only delete if an error occurred and the target file was already created
653
-						if ($fileExists) {
654
-							// set to null to avoid double-deletion when handling exception
655
-							// stray part file
656
-							$partFile = null;
657
-							$targetStorage->unlink($targetInternalPath);
658
-						}
659
-						$this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
660
-						throw new Exception($this->l10n->t('Could not rename part file assembled from chunks'));
661
-					}
662
-				} else {
663
-					// assemble directly into the final file
664
-					$chunk_handler->file_assemble($targetStorage, $targetInternalPath);
665
-				}
666
-
667
-				// allow sync clients to send the mtime along in a header
668
-				if (isset($this->request->server['HTTP_X_OC_MTIME'])) {
669
-					$mtime = $this->sanitizeMtime($this->request->server['HTTP_X_OC_MTIME']);
670
-					if ($targetStorage->touch($targetInternalPath, $mtime)) {
671
-						$this->header('X-OC-MTime: accepted');
672
-					}
673
-				}
674
-
675
-				// since we skipped the view we need to scan and emit the hooks ourselves
676
-				$targetStorage->getUpdater()->update($targetInternalPath);
677
-
678
-				$this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
679
-
680
-				$this->emitPostHooks($exists, $targetPath);
681
-
682
-				// FIXME: should call refreshInfo but can't because $this->path is not the of the final file
683
-				$info = $this->fileView->getFileInfo($targetPath);
684
-
685
-				if (isset($this->request->server['HTTP_OC_CHECKSUM'])) {
686
-					$checksum = trim($this->request->server['HTTP_OC_CHECKSUM']);
687
-					$this->fileView->putFileInfo($targetPath, ['checksum' => $checksum]);
688
-				} elseif ($info->getChecksum() !== null && $info->getChecksum() !== '') {
689
-					$this->fileView->putFileInfo($this->path, ['checksum' => '']);
690
-				}
691
-
692
-				$this->fileView->unlockFile($targetPath, ILockingProvider::LOCK_SHARED);
693
-
694
-				return $info->getEtag();
695
-			} catch (\Exception $e) {
696
-				if ($partFile !== null) {
697
-					$targetStorage->unlink($targetInternalPath);
698
-				}
699
-				$this->convertToSabreException($e);
700
-			}
701
-		}
702
-
703
-		return null;
704
-	}
705
-
706
-	/**
707
-	 * Convert the given exception to a SabreException instance
708
-	 *
709
-	 * @param \Exception $e
710
-	 *
711
-	 * @throws \Sabre\DAV\Exception
712
-	 */
713
-	private function convertToSabreException(\Exception $e) {
714
-		if ($e instanceof \Sabre\DAV\Exception) {
715
-			throw $e;
716
-		}
717
-		if ($e instanceof NotPermittedException) {
718
-			// a more general case - due to whatever reason the content could not be written
719
-			throw new Forbidden($e->getMessage(), 0, $e);
720
-		}
721
-		if ($e instanceof ForbiddenException) {
722
-			// the path for the file was forbidden
723
-			throw new DAVForbiddenException($e->getMessage(), $e->getRetry(), $e);
724
-		}
725
-		if ($e instanceof EntityTooLargeException) {
726
-			// the file is too big to be stored
727
-			throw new EntityTooLarge($e->getMessage(), 0, $e);
728
-		}
729
-		if ($e instanceof InvalidContentException) {
730
-			// the file content is not permitted
731
-			throw new UnsupportedMediaType($e->getMessage(), 0, $e);
732
-		}
733
-		if ($e instanceof InvalidPathException) {
734
-			// the path for the file was not valid
735
-			// TODO: find proper http status code for this case
736
-			throw new Forbidden($e->getMessage(), 0, $e);
737
-		}
738
-		if ($e instanceof LockedException || $e instanceof LockNotAcquiredException) {
739
-			// the file is currently being written to by another process
740
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
741
-		}
742
-		if ($e instanceof GenericEncryptionException) {
743
-			// returning 503 will allow retry of the operation at a later point in time
744
-			throw new ServiceUnavailable($this->l10n->t('Encryption not ready: %1$s', [$e->getMessage()]), 0, $e);
745
-		}
746
-		if ($e instanceof StorageNotAvailableException) {
747
-			throw new ServiceUnavailable($this->l10n->t('Failed to write file contents: %1$s', [$e->getMessage()]), 0, $e);
748
-		}
749
-		if ($e instanceof NotFoundException) {
750
-			throw new NotFound($this->l10n->t('File not found: %1$s', [$e->getMessage()]), 0, $e);
751
-		}
752
-
753
-		throw new \Sabre\DAV\Exception($e->getMessage(), 0, $e);
754
-	}
755
-
756
-	/**
757
-	 * Get the checksum for this file
758
-	 *
759
-	 * @return string|null
760
-	 */
761
-	public function getChecksum() {
762
-		return $this->info->getChecksum();
763
-	}
764
-
765
-	public function setChecksum(string $checksum) {
766
-		$this->fileView->putFileInfo($this->path, ['checksum' => $checksum]);
767
-		$this->refreshInfo();
768
-	}
769
-
770
-	protected function header($string) {
771
-		if (!\OC::$CLI) {
772
-			\header($string);
773
-		}
774
-	}
775
-
776
-	public function hash(string $type) {
777
-		return $this->fileView->hash($type, $this->path);
778
-	}
779
-
780
-	public function getNode(): \OCP\Files\File {
781
-		return $this->node;
782
-	}
783
-
784
-	public function getMetadata(string $group): FileMetadata {
785
-		return $this->metadata[$group];
786
-	}
787
-
788
-	public function setMetadata(string $group, FileMetadata $metadata): void {
789
-		$this->metadata[$group] = $metadata;
790
-	}
791
-
792
-	public function hasMetadata(string $group) {
793
-		return array_key_exists($group, $this->metadata);
794
-	}
80
+    protected $request;
81
+
82
+    protected IL10N $l10n;
83
+
84
+    /** @var array<string, FileMetadata> */
85
+    private array $metadata = [];
86
+
87
+    /**
88
+     * Sets up the node, expects a full path name
89
+     *
90
+     * @param \OC\Files\View $view
91
+     * @param \OCP\Files\FileInfo $info
92
+     * @param \OCP\Share\IManager $shareManager
93
+     * @param \OC\AppFramework\Http\Request $request
94
+     */
95
+    public function __construct(View $view, FileInfo $info, IManager $shareManager = null, Request $request = null) {
96
+        parent::__construct($view, $info, $shareManager);
97
+
98
+        // Querying IL10N directly results in a dependency loop
99
+        /** @var IL10NFactory $l10nFactory */
100
+        $l10nFactory = \OC::$server->get(IL10NFactory::class);
101
+        $this->l10n = $l10nFactory->get(Application::APP_ID);
102
+
103
+        if (isset($request)) {
104
+            $this->request = $request;
105
+        } else {
106
+            $this->request = \OC::$server->getRequest();
107
+        }
108
+    }
109
+
110
+    /**
111
+     * Updates the data
112
+     *
113
+     * The data argument is a readable stream resource.
114
+     *
115
+     * After a successful put operation, you may choose to return an ETag. The
116
+     * etag must always be surrounded by double-quotes. These quotes must
117
+     * appear in the actual string you're returning.
118
+     *
119
+     * Clients may use the ETag from a PUT request to later on make sure that
120
+     * when they update the file, the contents haven't changed in the mean
121
+     * time.
122
+     *
123
+     * If you don't plan to store the file byte-by-byte, and you return a
124
+     * different object on a subsequent GET you are strongly recommended to not
125
+     * return an ETag, and just return null.
126
+     *
127
+     * @param resource $data
128
+     *
129
+     * @throws Forbidden
130
+     * @throws UnsupportedMediaType
131
+     * @throws BadRequest
132
+     * @throws Exception
133
+     * @throws EntityTooLarge
134
+     * @throws ServiceUnavailable
135
+     * @throws FileLocked
136
+     * @return string|null
137
+     */
138
+    public function put($data) {
139
+        try {
140
+            $exists = $this->fileView->file_exists($this->path);
141
+            if ($exists && !$this->info->isUpdateable()) {
142
+                throw new Forbidden();
143
+            }
144
+        } catch (StorageNotAvailableException $e) {
145
+            throw new ServiceUnavailable($this->l10n->t('File is not updatable: %1$s', [$e->getMessage()]));
146
+        }
147
+
148
+        // verify path of the target
149
+        $this->verifyPath();
150
+
151
+        // chunked handling
152
+        if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
153
+            try {
154
+                return $this->createFileChunked($data);
155
+            } catch (\Exception $e) {
156
+                $this->convertToSabreException($e);
157
+            }
158
+        }
159
+
160
+        /** @var Storage $partStorage */
161
+        [$partStorage] = $this->fileView->resolvePath($this->path);
162
+        $needsPartFile = $partStorage->needsPartFile() && (strlen($this->path) > 1);
163
+
164
+        $view = \OC\Files\Filesystem::getView();
165
+
166
+        if ($needsPartFile) {
167
+            // mark file as partial while uploading (ignored by the scanner)
168
+            $partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part';
169
+
170
+            if (!$view->isCreatable($partFilePath) && $view->isUpdatable($this->path)) {
171
+                $needsPartFile = false;
172
+            }
173
+        }
174
+        if (!$needsPartFile) {
175
+            // upload file directly as the final path
176
+            $partFilePath = $this->path;
177
+
178
+            if ($view && !$this->emitPreHooks($exists)) {
179
+                throw new Exception($this->l10n->t('Could not write to final file, canceled by hook'));
180
+            }
181
+        }
182
+
183
+        // the part file and target file might be on a different storage in case of a single file storage (e.g. single file share)
184
+        /** @var \OC\Files\Storage\Storage $partStorage */
185
+        [$partStorage, $internalPartPath] = $this->fileView->resolvePath($partFilePath);
186
+        /** @var \OC\Files\Storage\Storage $storage */
187
+        [$storage, $internalPath] = $this->fileView->resolvePath($this->path);
188
+        try {
189
+            if (!$needsPartFile) {
190
+                try {
191
+                    $this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
192
+                } catch (LockedException $e) {
193
+                    // during very large uploads, the shared lock we got at the start might have been expired
194
+                    // meaning that the above lock can fail not just only because somebody else got a shared lock
195
+                    // or because there is no existing shared lock to make exclusive
196
+                    //
197
+                    // Thus we try to get a new exclusive lock, if the original lock failed because of a different shared
198
+                    // lock this will still fail, if our original shared lock expired the new lock will be successful and
199
+                    // the entire operation will be safe
200
+
201
+                    try {
202
+                        $this->acquireLock(ILockingProvider::LOCK_EXCLUSIVE);
203
+                    } catch (LockedException $ex) {
204
+                        throw new FileLocked($e->getMessage(), $e->getCode(), $e);
205
+                    }
206
+                }
207
+            }
208
+
209
+            if (!is_resource($data)) {
210
+                $tmpData = fopen('php://temp', 'r+');
211
+                if ($data !== null) {
212
+                    fwrite($tmpData, $data);
213
+                    rewind($tmpData);
214
+                }
215
+                $data = $tmpData;
216
+            }
217
+
218
+            if ($this->request->getHeader('X-HASH') !== '') {
219
+                $hash = $this->request->getHeader('X-HASH');
220
+                if ($hash === 'all' || $hash === 'md5') {
221
+                    $data = HashWrapper::wrap($data, 'md5', function ($hash) {
222
+                        $this->header('X-Hash-MD5: ' . $hash);
223
+                    });
224
+                }
225
+
226
+                if ($hash === 'all' || $hash === 'sha1') {
227
+                    $data = HashWrapper::wrap($data, 'sha1', function ($hash) {
228
+                        $this->header('X-Hash-SHA1: ' . $hash);
229
+                    });
230
+                }
231
+
232
+                if ($hash === 'all' || $hash === 'sha256') {
233
+                    $data = HashWrapper::wrap($data, 'sha256', function ($hash) {
234
+                        $this->header('X-Hash-SHA256: ' . $hash);
235
+                    });
236
+                }
237
+            }
238
+
239
+            if ($partStorage->instanceOfStorage(Storage\IWriteStreamStorage::class)) {
240
+                $isEOF = false;
241
+                $wrappedData = CallbackWrapper::wrap($data, null, null, null, null, function ($stream) use (&$isEOF) {
242
+                    $isEOF = feof($stream);
243
+                });
244
+
245
+                $result = true;
246
+                $count = -1;
247
+                try {
248
+                    $count = $partStorage->writeStream($internalPartPath, $wrappedData);
249
+                } catch (GenericFileException $e) {
250
+                    $result = false;
251
+                } catch (BadGateway $e) {
252
+                    throw $e;
253
+                }
254
+
255
+
256
+                if ($result === false) {
257
+                    $result = $isEOF;
258
+                    if (is_resource($wrappedData)) {
259
+                        $result = feof($wrappedData);
260
+                    }
261
+                }
262
+            } else {
263
+                $target = $partStorage->fopen($internalPartPath, 'wb');
264
+                if ($target === false) {
265
+                    \OC::$server->get(LoggerInterface::class)->error('\OC\Files\Filesystem::fopen() failed', ['app' => 'webdav']);
266
+                    // because we have no clue about the cause we can only throw back a 500/Internal Server Error
267
+                    throw new Exception($this->l10n->t('Could not write file contents'));
268
+                }
269
+                [$count, $result] = \OC_Helper::streamCopy($data, $target);
270
+                fclose($target);
271
+            }
272
+
273
+            if ($result === false) {
274
+                $expected = -1;
275
+                if (isset($_SERVER['CONTENT_LENGTH'])) {
276
+                    $expected = (int)$_SERVER['CONTENT_LENGTH'];
277
+                }
278
+                if ($expected !== 0) {
279
+                    throw new Exception(
280
+                        $this->l10n->t(
281
+                            'Error while copying file to target location (copied: %1$s, expected filesize: %2$s)',
282
+                            [
283
+                                $this->l10n->n('%n byte', '%n bytes', $count),
284
+                                $this->l10n->n('%n byte', '%n bytes', $expected),
285
+                            ],
286
+                        )
287
+                    );
288
+                }
289
+            }
290
+
291
+            // if content length is sent by client:
292
+            // double check if the file was fully received
293
+            // compare expected and actual size
294
+            if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
295
+                $expected = (int)$_SERVER['CONTENT_LENGTH'];
296
+                if ($count !== $expected) {
297
+                    throw new BadRequest(
298
+                        $this->l10n->t(
299
+                            'Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side.',
300
+                            [
301
+                                $this->l10n->n('%n byte', '%n bytes', $expected),
302
+                                $this->l10n->n('%n byte', '%n bytes', $count),
303
+                            ],
304
+                        )
305
+                    );
306
+                }
307
+            }
308
+        } catch (\Exception $e) {
309
+            if ($e instanceof LockedException) {
310
+                \OC::$server->get(LoggerInterface::class)->debug($e->getMessage(), ['exception' => $e]);
311
+            } else {
312
+                \OC::$server->get(LoggerInterface::class)->error($e->getMessage(), ['exception' => $e]);
313
+            }
314
+
315
+            if ($needsPartFile) {
316
+                $partStorage->unlink($internalPartPath);
317
+            }
318
+            $this->convertToSabreException($e);
319
+        }
320
+
321
+        try {
322
+            if ($needsPartFile) {
323
+                if ($view && !$this->emitPreHooks($exists)) {
324
+                    $partStorage->unlink($internalPartPath);
325
+                    throw new Exception($this->l10n->t('Could not rename part file to final file, canceled by hook'));
326
+                }
327
+                try {
328
+                    $this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
329
+                } catch (LockedException $e) {
330
+                    // during very large uploads, the shared lock we got at the start might have been expired
331
+                    // meaning that the above lock can fail not just only because somebody else got a shared lock
332
+                    // or because there is no existing shared lock to make exclusive
333
+                    //
334
+                    // Thus we try to get a new exclusive lock, if the original lock failed because of a different shared
335
+                    // lock this will still fail, if our original shared lock expired the new lock will be successful and
336
+                    // the entire operation will be safe
337
+
338
+                    try {
339
+                        $this->acquireLock(ILockingProvider::LOCK_EXCLUSIVE);
340
+                    } catch (LockedException $ex) {
341
+                        if ($needsPartFile) {
342
+                            $partStorage->unlink($internalPartPath);
343
+                        }
344
+                        throw new FileLocked($e->getMessage(), $e->getCode(), $e);
345
+                    }
346
+                }
347
+
348
+                // rename to correct path
349
+                try {
350
+                    $renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath);
351
+                    $fileExists = $storage->file_exists($internalPath);
352
+                    if ($renameOkay === false || $fileExists === false) {
353
+                        \OC::$server->get(LoggerInterface::class)->error('renaming part file to final file failed $renameOkay: ' . ($renameOkay ? 'true' : 'false') . ', $fileExists: ' . ($fileExists ? 'true' : 'false') . ')', ['app' => 'webdav']);
354
+                        throw new Exception($this->l10n->t('Could not rename part file to final file'));
355
+                    }
356
+                } catch (ForbiddenException $ex) {
357
+                    if (!$ex->getRetry()) {
358
+                        $partStorage->unlink($internalPartPath);
359
+                    }
360
+                    throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
361
+                } catch (\Exception $e) {
362
+                    $partStorage->unlink($internalPartPath);
363
+                    $this->convertToSabreException($e);
364
+                }
365
+            }
366
+
367
+            // since we skipped the view we need to scan and emit the hooks ourselves
368
+            $storage->getUpdater()->update($internalPath);
369
+
370
+            try {
371
+                $this->changeLock(ILockingProvider::LOCK_SHARED);
372
+            } catch (LockedException $e) {
373
+                throw new FileLocked($e->getMessage(), $e->getCode(), $e);
374
+            }
375
+
376
+            // allow sync clients to send the mtime along in a header
377
+            if (isset($this->request->server['HTTP_X_OC_MTIME'])) {
378
+                $mtime = $this->sanitizeMtime($this->request->server['HTTP_X_OC_MTIME']);
379
+                if ($this->fileView->touch($this->path, $mtime)) {
380
+                    $this->header('X-OC-MTime: accepted');
381
+                }
382
+            }
383
+
384
+            $fileInfoUpdate = [
385
+                'upload_time' => time()
386
+            ];
387
+
388
+            // allow sync clients to send the creation time along in a header
389
+            if (isset($this->request->server['HTTP_X_OC_CTIME'])) {
390
+                $ctime = $this->sanitizeMtime($this->request->server['HTTP_X_OC_CTIME']);
391
+                $fileInfoUpdate['creation_time'] = $ctime;
392
+                $this->header('X-OC-CTime: accepted');
393
+            }
394
+
395
+            $this->fileView->putFileInfo($this->path, $fileInfoUpdate);
396
+
397
+            if ($view) {
398
+                $this->emitPostHooks($exists);
399
+            }
400
+
401
+            $this->refreshInfo();
402
+
403
+            if (isset($this->request->server['HTTP_OC_CHECKSUM'])) {
404
+                $checksum = trim($this->request->server['HTTP_OC_CHECKSUM']);
405
+                $this->setChecksum($checksum);
406
+            } elseif ($this->getChecksum() !== null && $this->getChecksum() !== '') {
407
+                $this->setChecksum('');
408
+            }
409
+        } catch (StorageNotAvailableException $e) {
410
+            throw new ServiceUnavailable($this->l10n->t('Failed to check file size: %1$s', [$e->getMessage()]), 0, $e);
411
+        }
412
+
413
+        return '"' . $this->info->getEtag() . '"';
414
+    }
415
+
416
+    private function getPartFileBasePath($path) {
417
+        $partFileInStorage = \OC::$server->getConfig()->getSystemValue('part_file_in_storage', true);
418
+        if ($partFileInStorage) {
419
+            return $path;
420
+        } else {
421
+            return md5($path); // will place it in the root of the view with a unique name
422
+        }
423
+    }
424
+
425
+    /**
426
+     * @param string $path
427
+     */
428
+    private function emitPreHooks($exists, $path = null) {
429
+        if (is_null($path)) {
430
+            $path = $this->path;
431
+        }
432
+        $hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
433
+        $run = true;
434
+
435
+        if (!$exists) {
436
+            \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_create, [
437
+                \OC\Files\Filesystem::signal_param_path => $hookPath,
438
+                \OC\Files\Filesystem::signal_param_run => &$run,
439
+            ]);
440
+        } else {
441
+            \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_update, [
442
+                \OC\Files\Filesystem::signal_param_path => $hookPath,
443
+                \OC\Files\Filesystem::signal_param_run => &$run,
444
+            ]);
445
+        }
446
+        \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_write, [
447
+            \OC\Files\Filesystem::signal_param_path => $hookPath,
448
+            \OC\Files\Filesystem::signal_param_run => &$run,
449
+        ]);
450
+        return $run;
451
+    }
452
+
453
+    /**
454
+     * @param string $path
455
+     */
456
+    private function emitPostHooks($exists, $path = null) {
457
+        if (is_null($path)) {
458
+            $path = $this->path;
459
+        }
460
+        $hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
461
+        if (!$exists) {
462
+            \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_create, [
463
+                \OC\Files\Filesystem::signal_param_path => $hookPath
464
+            ]);
465
+        } else {
466
+            \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_update, [
467
+                \OC\Files\Filesystem::signal_param_path => $hookPath
468
+            ]);
469
+        }
470
+        \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_write, [
471
+            \OC\Files\Filesystem::signal_param_path => $hookPath
472
+        ]);
473
+    }
474
+
475
+    /**
476
+     * Returns the data
477
+     *
478
+     * @return resource
479
+     * @throws Forbidden
480
+     * @throws ServiceUnavailable
481
+     */
482
+    public function get() {
483
+        //throw exception if encryption is disabled but files are still encrypted
484
+        try {
485
+            if (!$this->info->isReadable()) {
486
+                // do a if the file did not exist
487
+                throw new NotFound();
488
+            }
489
+            try {
490
+                $res = $this->fileView->fopen(ltrim($this->path, '/'), 'rb');
491
+            } catch (\Exception $e) {
492
+                $this->convertToSabreException($e);
493
+            }
494
+
495
+            if ($res === false) {
496
+                throw new ServiceUnavailable($this->l10n->t('Could not open file'));
497
+            }
498
+
499
+            // comparing current file size with the one in DB
500
+            // if different, fix DB and refresh cache.
501
+            if ($this->getSize() !== $this->fileView->filesize($this->getPath())) {
502
+                $logger = \OC::$server->get(LoggerInterface::class);
503
+                $logger->warning('fixing cached size of file id=' . $this->getId());
504
+
505
+                $this->getFileInfo()->getStorage()->getUpdater()->update($this->getFileInfo()->getInternalPath());
506
+                $this->refreshInfo();
507
+            }
508
+
509
+            return $res;
510
+        } catch (GenericEncryptionException $e) {
511
+            // returning 503 will allow retry of the operation at a later point in time
512
+            throw new ServiceUnavailable($this->l10n->t('Encryption not ready: %1$s', [$e->getMessage()]));
513
+        } catch (StorageNotAvailableException $e) {
514
+            throw new ServiceUnavailable($this->l10n->t('Failed to open file: %1$s', [$e->getMessage()]));
515
+        } catch (ForbiddenException $ex) {
516
+            throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
517
+        } catch (LockedException $e) {
518
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
519
+        }
520
+    }
521
+
522
+    /**
523
+     * Delete the current file
524
+     *
525
+     * @throws Forbidden
526
+     * @throws ServiceUnavailable
527
+     */
528
+    public function delete() {
529
+        if (!$this->info->isDeletable()) {
530
+            throw new Forbidden();
531
+        }
532
+
533
+        try {
534
+            if (!$this->fileView->unlink($this->path)) {
535
+                // assume it wasn't possible to delete due to permissions
536
+                throw new Forbidden();
537
+            }
538
+        } catch (StorageNotAvailableException $e) {
539
+            throw new ServiceUnavailable($this->l10n->t('Failed to unlink: %1$s', [$e->getMessage()]));
540
+        } catch (ForbiddenException $ex) {
541
+            throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
542
+        } catch (LockedException $e) {
543
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
544
+        }
545
+    }
546
+
547
+    /**
548
+     * Returns the mime-type for a file
549
+     *
550
+     * If null is returned, we'll assume application/octet-stream
551
+     *
552
+     * @return string
553
+     */
554
+    public function getContentType() {
555
+        $mimeType = $this->info->getMimetype();
556
+
557
+        // PROPFIND needs to return the correct mime type, for consistency with the web UI
558
+        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PROPFIND') {
559
+            return $mimeType;
560
+        }
561
+        return \OC::$server->getMimeTypeDetector()->getSecureMimeType($mimeType);
562
+    }
563
+
564
+    /**
565
+     * @return array|bool
566
+     */
567
+    public function getDirectDownload() {
568
+        if (\OCP\Server::get(\OCP\App\IAppManager::class)->isEnabledForUser('encryption')) {
569
+            return [];
570
+        }
571
+        /** @var \OCP\Files\Storage $storage */
572
+        [$storage, $internalPath] = $this->fileView->resolvePath($this->path);
573
+        if (is_null($storage)) {
574
+            return [];
575
+        }
576
+
577
+        return $storage->getDirectDownload($internalPath);
578
+    }
579
+
580
+    /**
581
+     * @param resource $data
582
+     * @return null|string
583
+     * @throws Exception
584
+     * @throws BadRequest
585
+     * @throws NotImplemented
586
+     * @throws ServiceUnavailable
587
+     */
588
+    private function createFileChunked($data) {
589
+        [$path, $name] = \Sabre\Uri\split($this->path);
590
+
591
+        $info = \OC_FileChunking::decodeName($name);
592
+        if (empty($info)) {
593
+            throw new NotImplemented($this->l10n->t('Invalid chunk name'));
594
+        }
595
+
596
+        $chunk_handler = new \OC_FileChunking($info);
597
+        $bytesWritten = $chunk_handler->store($info['index'], $data);
598
+
599
+        //detect aborted upload
600
+        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
601
+            if (isset($_SERVER['CONTENT_LENGTH'])) {
602
+                $expected = (int)$_SERVER['CONTENT_LENGTH'];
603
+                if ($bytesWritten !== $expected) {
604
+                    $chunk_handler->remove($info['index']);
605
+                    throw new BadRequest(
606
+                        $this->l10n->t(
607
+                            'Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side.',
608
+                            [
609
+                                $this->l10n->n('%n byte', '%n bytes', $expected),
610
+                                $this->l10n->n('%n byte', '%n bytes', $bytesWritten),
611
+                            ],
612
+                        )
613
+                    );
614
+                }
615
+            }
616
+        }
617
+
618
+        if ($chunk_handler->isComplete()) {
619
+            /** @var Storage $storage */
620
+            [$storage,] = $this->fileView->resolvePath($path);
621
+            $needsPartFile = $storage->needsPartFile();
622
+            $partFile = null;
623
+
624
+            $targetPath = $path . '/' . $info['name'];
625
+            /** @var \OC\Files\Storage\Storage $targetStorage */
626
+            [$targetStorage, $targetInternalPath] = $this->fileView->resolvePath($targetPath);
627
+
628
+            $exists = $this->fileView->file_exists($targetPath);
629
+
630
+            try {
631
+                $this->fileView->lockFile($targetPath, ILockingProvider::LOCK_SHARED);
632
+
633
+                $this->emitPreHooks($exists, $targetPath);
634
+                $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_EXCLUSIVE);
635
+                /** @var \OC\Files\Storage\Storage $targetStorage */
636
+                [$targetStorage, $targetInternalPath] = $this->fileView->resolvePath($targetPath);
637
+
638
+                if ($needsPartFile) {
639
+                    // we first assembly the target file as a part file
640
+                    $partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part';
641
+                    /** @var \OC\Files\Storage\Storage $targetStorage */
642
+                    [$partStorage, $partInternalPath] = $this->fileView->resolvePath($partFile);
643
+
644
+
645
+                    $chunk_handler->file_assemble($partStorage, $partInternalPath);
646
+
647
+                    // here is the final atomic rename
648
+                    $renameOkay = $targetStorage->moveFromStorage($partStorage, $partInternalPath, $targetInternalPath);
649
+                    $fileExists = $targetStorage->file_exists($targetInternalPath);
650
+                    if ($renameOkay === false || $fileExists === false) {
651
+                        \OC::$server->get(LoggerInterface::class)->error('\OC\Files\Filesystem::rename() failed', ['app' => 'webdav']);
652
+                        // only delete if an error occurred and the target file was already created
653
+                        if ($fileExists) {
654
+                            // set to null to avoid double-deletion when handling exception
655
+                            // stray part file
656
+                            $partFile = null;
657
+                            $targetStorage->unlink($targetInternalPath);
658
+                        }
659
+                        $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
660
+                        throw new Exception($this->l10n->t('Could not rename part file assembled from chunks'));
661
+                    }
662
+                } else {
663
+                    // assemble directly into the final file
664
+                    $chunk_handler->file_assemble($targetStorage, $targetInternalPath);
665
+                }
666
+
667
+                // allow sync clients to send the mtime along in a header
668
+                if (isset($this->request->server['HTTP_X_OC_MTIME'])) {
669
+                    $mtime = $this->sanitizeMtime($this->request->server['HTTP_X_OC_MTIME']);
670
+                    if ($targetStorage->touch($targetInternalPath, $mtime)) {
671
+                        $this->header('X-OC-MTime: accepted');
672
+                    }
673
+                }
674
+
675
+                // since we skipped the view we need to scan and emit the hooks ourselves
676
+                $targetStorage->getUpdater()->update($targetInternalPath);
677
+
678
+                $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
679
+
680
+                $this->emitPostHooks($exists, $targetPath);
681
+
682
+                // FIXME: should call refreshInfo but can't because $this->path is not the of the final file
683
+                $info = $this->fileView->getFileInfo($targetPath);
684
+
685
+                if (isset($this->request->server['HTTP_OC_CHECKSUM'])) {
686
+                    $checksum = trim($this->request->server['HTTP_OC_CHECKSUM']);
687
+                    $this->fileView->putFileInfo($targetPath, ['checksum' => $checksum]);
688
+                } elseif ($info->getChecksum() !== null && $info->getChecksum() !== '') {
689
+                    $this->fileView->putFileInfo($this->path, ['checksum' => '']);
690
+                }
691
+
692
+                $this->fileView->unlockFile($targetPath, ILockingProvider::LOCK_SHARED);
693
+
694
+                return $info->getEtag();
695
+            } catch (\Exception $e) {
696
+                if ($partFile !== null) {
697
+                    $targetStorage->unlink($targetInternalPath);
698
+                }
699
+                $this->convertToSabreException($e);
700
+            }
701
+        }
702
+
703
+        return null;
704
+    }
705
+
706
+    /**
707
+     * Convert the given exception to a SabreException instance
708
+     *
709
+     * @param \Exception $e
710
+     *
711
+     * @throws \Sabre\DAV\Exception
712
+     */
713
+    private function convertToSabreException(\Exception $e) {
714
+        if ($e instanceof \Sabre\DAV\Exception) {
715
+            throw $e;
716
+        }
717
+        if ($e instanceof NotPermittedException) {
718
+            // a more general case - due to whatever reason the content could not be written
719
+            throw new Forbidden($e->getMessage(), 0, $e);
720
+        }
721
+        if ($e instanceof ForbiddenException) {
722
+            // the path for the file was forbidden
723
+            throw new DAVForbiddenException($e->getMessage(), $e->getRetry(), $e);
724
+        }
725
+        if ($e instanceof EntityTooLargeException) {
726
+            // the file is too big to be stored
727
+            throw new EntityTooLarge($e->getMessage(), 0, $e);
728
+        }
729
+        if ($e instanceof InvalidContentException) {
730
+            // the file content is not permitted
731
+            throw new UnsupportedMediaType($e->getMessage(), 0, $e);
732
+        }
733
+        if ($e instanceof InvalidPathException) {
734
+            // the path for the file was not valid
735
+            // TODO: find proper http status code for this case
736
+            throw new Forbidden($e->getMessage(), 0, $e);
737
+        }
738
+        if ($e instanceof LockedException || $e instanceof LockNotAcquiredException) {
739
+            // the file is currently being written to by another process
740
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
741
+        }
742
+        if ($e instanceof GenericEncryptionException) {
743
+            // returning 503 will allow retry of the operation at a later point in time
744
+            throw new ServiceUnavailable($this->l10n->t('Encryption not ready: %1$s', [$e->getMessage()]), 0, $e);
745
+        }
746
+        if ($e instanceof StorageNotAvailableException) {
747
+            throw new ServiceUnavailable($this->l10n->t('Failed to write file contents: %1$s', [$e->getMessage()]), 0, $e);
748
+        }
749
+        if ($e instanceof NotFoundException) {
750
+            throw new NotFound($this->l10n->t('File not found: %1$s', [$e->getMessage()]), 0, $e);
751
+        }
752
+
753
+        throw new \Sabre\DAV\Exception($e->getMessage(), 0, $e);
754
+    }
755
+
756
+    /**
757
+     * Get the checksum for this file
758
+     *
759
+     * @return string|null
760
+     */
761
+    public function getChecksum() {
762
+        return $this->info->getChecksum();
763
+    }
764
+
765
+    public function setChecksum(string $checksum) {
766
+        $this->fileView->putFileInfo($this->path, ['checksum' => $checksum]);
767
+        $this->refreshInfo();
768
+    }
769
+
770
+    protected function header($string) {
771
+        if (!\OC::$CLI) {
772
+            \header($string);
773
+        }
774
+    }
775
+
776
+    public function hash(string $type) {
777
+        return $this->fileView->hash($type, $this->path);
778
+    }
779
+
780
+    public function getNode(): \OCP\Files\File {
781
+        return $this->node;
782
+    }
783
+
784
+    public function getMetadata(string $group): FileMetadata {
785
+        return $this->metadata[$group];
786
+    }
787
+
788
+    public function setMetadata(string $group, FileMetadata $metadata): void {
789
+        $this->metadata[$group] = $metadata;
790
+    }
791
+
792
+    public function hasMetadata(string $group) {
793
+        return array_key_exists($group, $this->metadata);
794
+    }
795 795
 }
Please login to merge, or discard this patch.
apps/files/composer/composer/autoload_classmap.php 1 patch
Spacing   +53 added lines, -53 removed lines patch added patch discarded remove patch
@@ -6,57 +6,57 @@
 block discarded – undo
6 6
 $baseDir = $vendorDir;
7 7
 
8 8
 return array(
9
-    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
10
-    'OCA\\Files\\Activity\\FavoriteProvider' => $baseDir . '/../lib/Activity/FavoriteProvider.php',
11
-    'OCA\\Files\\Activity\\Filter\\Favorites' => $baseDir . '/../lib/Activity/Filter/Favorites.php',
12
-    'OCA\\Files\\Activity\\Filter\\FileChanges' => $baseDir . '/../lib/Activity/Filter/FileChanges.php',
13
-    'OCA\\Files\\Activity\\Helper' => $baseDir . '/../lib/Activity/Helper.php',
14
-    'OCA\\Files\\Activity\\Provider' => $baseDir . '/../lib/Activity/Provider.php',
15
-    'OCA\\Files\\Activity\\Settings\\FavoriteAction' => $baseDir . '/../lib/Activity/Settings/FavoriteAction.php',
16
-    'OCA\\Files\\Activity\\Settings\\FileActivitySettings' => $baseDir . '/../lib/Activity/Settings/FileActivitySettings.php',
17
-    'OCA\\Files\\Activity\\Settings\\FileChanged' => $baseDir . '/../lib/Activity/Settings/FileChanged.php',
18
-    'OCA\\Files\\Activity\\Settings\\FileFavoriteChanged' => $baseDir . '/../lib/Activity/Settings/FileFavoriteChanged.php',
19
-    'OCA\\Files\\App' => $baseDir . '/../lib/App.php',
20
-    'OCA\\Files\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php',
21
-    'OCA\\Files\\BackgroundJob\\CleanupDirectEditingTokens' => $baseDir . '/../lib/BackgroundJob/CleanupDirectEditingTokens.php',
22
-    'OCA\\Files\\BackgroundJob\\CleanupFileLocks' => $baseDir . '/../lib/BackgroundJob/CleanupFileLocks.php',
23
-    'OCA\\Files\\BackgroundJob\\DeleteExpiredOpenLocalEditor' => $baseDir . '/../lib/BackgroundJob/DeleteExpiredOpenLocalEditor.php',
24
-    'OCA\\Files\\BackgroundJob\\DeleteOrphanedItems' => $baseDir . '/../lib/BackgroundJob/DeleteOrphanedItems.php',
25
-    'OCA\\Files\\BackgroundJob\\ScanFiles' => $baseDir . '/../lib/BackgroundJob/ScanFiles.php',
26
-    'OCA\\Files\\BackgroundJob\\TransferOwnership' => $baseDir . '/../lib/BackgroundJob/TransferOwnership.php',
27
-    'OCA\\Files\\Capabilities' => $baseDir . '/../lib/Capabilities.php',
28
-    'OCA\\Files\\Collaboration\\Resources\\Listener' => $baseDir . '/../lib/Collaboration/Resources/Listener.php',
29
-    'OCA\\Files\\Collaboration\\Resources\\ResourceProvider' => $baseDir . '/../lib/Collaboration/Resources/ResourceProvider.php',
30
-    'OCA\\Files\\Command\\DeleteOrphanedFiles' => $baseDir . '/../lib/Command/DeleteOrphanedFiles.php',
31
-    'OCA\\Files\\Command\\RepairTree' => $baseDir . '/../lib/Command/RepairTree.php',
32
-    'OCA\\Files\\Command\\Scan' => $baseDir . '/../lib/Command/Scan.php',
33
-    'OCA\\Files\\Command\\ScanAppData' => $baseDir . '/../lib/Command/ScanAppData.php',
34
-    'OCA\\Files\\Command\\TransferOwnership' => $baseDir . '/../lib/Command/TransferOwnership.php',
35
-    'OCA\\Files\\Controller\\ApiController' => $baseDir . '/../lib/Controller/ApiController.php',
36
-    'OCA\\Files\\Controller\\DirectEditingController' => $baseDir . '/../lib/Controller/DirectEditingController.php',
37
-    'OCA\\Files\\Controller\\DirectEditingViewController' => $baseDir . '/../lib/Controller/DirectEditingViewController.php',
38
-    'OCA\\Files\\Controller\\OpenLocalEditorController' => $baseDir . '/../lib/Controller/OpenLocalEditorController.php',
39
-    'OCA\\Files\\Controller\\TemplateController' => $baseDir . '/../lib/Controller/TemplateController.php',
40
-    'OCA\\Files\\Controller\\TransferOwnershipController' => $baseDir . '/../lib/Controller/TransferOwnershipController.php',
41
-    'OCA\\Files\\Controller\\ViewController' => $baseDir . '/../lib/Controller/ViewController.php',
42
-    'OCA\\Files\\Db\\OpenLocalEditor' => $baseDir . '/../lib/Db/OpenLocalEditor.php',
43
-    'OCA\\Files\\Db\\OpenLocalEditorMapper' => $baseDir . '/../lib/Db/OpenLocalEditorMapper.php',
44
-    'OCA\\Files\\Db\\TransferOwnership' => $baseDir . '/../lib/Db/TransferOwnership.php',
45
-    'OCA\\Files\\Db\\TransferOwnershipMapper' => $baseDir . '/../lib/Db/TransferOwnershipMapper.php',
46
-    'OCA\\Files\\DirectEditingCapabilities' => $baseDir . '/../lib/DirectEditingCapabilities.php',
47
-    'OCA\\Files\\Event\\LoadAdditionalScriptsEvent' => $baseDir . '/../lib/Event/LoadAdditionalScriptsEvent.php',
48
-    'OCA\\Files\\Event\\LoadSidebar' => $baseDir . '/../lib/Event/LoadSidebar.php',
49
-    'OCA\\Files\\Exception\\TransferOwnershipException' => $baseDir . '/../lib/Exception/TransferOwnershipException.php',
50
-    'OCA\\Files\\Helper' => $baseDir . '/../lib/Helper.php',
51
-    'OCA\\Files\\Listener\\LegacyLoadAdditionalScriptsAdapter' => $baseDir . '/../lib/Listener/LegacyLoadAdditionalScriptsAdapter.php',
52
-    'OCA\\Files\\Listener\\LoadSidebarListener' => $baseDir . '/../lib/Listener/LoadSidebarListener.php',
53
-    'OCA\\Files\\Migration\\Version11301Date20191205150729' => $baseDir . '/../lib/Migration/Version11301Date20191205150729.php',
54
-    'OCA\\Files\\Migration\\Version12101Date20221011153334' => $baseDir . '/../lib/Migration/Version12101Date20221011153334.php',
55
-    'OCA\\Files\\Notification\\Notifier' => $baseDir . '/../lib/Notification/Notifier.php',
56
-    'OCA\\Files\\Search\\FilesSearchProvider' => $baseDir . '/../lib/Search/FilesSearchProvider.php',
57
-    'OCA\\Files\\Service\\DirectEditingService' => $baseDir . '/../lib/Service/DirectEditingService.php',
58
-    'OCA\\Files\\Service\\OwnershipTransferService' => $baseDir . '/../lib/Service/OwnershipTransferService.php',
59
-    'OCA\\Files\\Service\\TagService' => $baseDir . '/../lib/Service/TagService.php',
60
-    'OCA\\Files\\Service\\UserConfig' => $baseDir . '/../lib/Service/UserConfig.php',
61
-    'OCA\\Files\\Settings\\PersonalSettings' => $baseDir . '/../lib/Settings/PersonalSettings.php',
9
+    'Composer\\InstalledVersions' => $vendorDir.'/composer/InstalledVersions.php',
10
+    'OCA\\Files\\Activity\\FavoriteProvider' => $baseDir.'/../lib/Activity/FavoriteProvider.php',
11
+    'OCA\\Files\\Activity\\Filter\\Favorites' => $baseDir.'/../lib/Activity/Filter/Favorites.php',
12
+    'OCA\\Files\\Activity\\Filter\\FileChanges' => $baseDir.'/../lib/Activity/Filter/FileChanges.php',
13
+    'OCA\\Files\\Activity\\Helper' => $baseDir.'/../lib/Activity/Helper.php',
14
+    'OCA\\Files\\Activity\\Provider' => $baseDir.'/../lib/Activity/Provider.php',
15
+    'OCA\\Files\\Activity\\Settings\\FavoriteAction' => $baseDir.'/../lib/Activity/Settings/FavoriteAction.php',
16
+    'OCA\\Files\\Activity\\Settings\\FileActivitySettings' => $baseDir.'/../lib/Activity/Settings/FileActivitySettings.php',
17
+    'OCA\\Files\\Activity\\Settings\\FileChanged' => $baseDir.'/../lib/Activity/Settings/FileChanged.php',
18
+    'OCA\\Files\\Activity\\Settings\\FileFavoriteChanged' => $baseDir.'/../lib/Activity/Settings/FileFavoriteChanged.php',
19
+    'OCA\\Files\\App' => $baseDir.'/../lib/App.php',
20
+    'OCA\\Files\\AppInfo\\Application' => $baseDir.'/../lib/AppInfo/Application.php',
21
+    'OCA\\Files\\BackgroundJob\\CleanupDirectEditingTokens' => $baseDir.'/../lib/BackgroundJob/CleanupDirectEditingTokens.php',
22
+    'OCA\\Files\\BackgroundJob\\CleanupFileLocks' => $baseDir.'/../lib/BackgroundJob/CleanupFileLocks.php',
23
+    'OCA\\Files\\BackgroundJob\\DeleteExpiredOpenLocalEditor' => $baseDir.'/../lib/BackgroundJob/DeleteExpiredOpenLocalEditor.php',
24
+    'OCA\\Files\\BackgroundJob\\DeleteOrphanedItems' => $baseDir.'/../lib/BackgroundJob/DeleteOrphanedItems.php',
25
+    'OCA\\Files\\BackgroundJob\\ScanFiles' => $baseDir.'/../lib/BackgroundJob/ScanFiles.php',
26
+    'OCA\\Files\\BackgroundJob\\TransferOwnership' => $baseDir.'/../lib/BackgroundJob/TransferOwnership.php',
27
+    'OCA\\Files\\Capabilities' => $baseDir.'/../lib/Capabilities.php',
28
+    'OCA\\Files\\Collaboration\\Resources\\Listener' => $baseDir.'/../lib/Collaboration/Resources/Listener.php',
29
+    'OCA\\Files\\Collaboration\\Resources\\ResourceProvider' => $baseDir.'/../lib/Collaboration/Resources/ResourceProvider.php',
30
+    'OCA\\Files\\Command\\DeleteOrphanedFiles' => $baseDir.'/../lib/Command/DeleteOrphanedFiles.php',
31
+    'OCA\\Files\\Command\\RepairTree' => $baseDir.'/../lib/Command/RepairTree.php',
32
+    'OCA\\Files\\Command\\Scan' => $baseDir.'/../lib/Command/Scan.php',
33
+    'OCA\\Files\\Command\\ScanAppData' => $baseDir.'/../lib/Command/ScanAppData.php',
34
+    'OCA\\Files\\Command\\TransferOwnership' => $baseDir.'/../lib/Command/TransferOwnership.php',
35
+    'OCA\\Files\\Controller\\ApiController' => $baseDir.'/../lib/Controller/ApiController.php',
36
+    'OCA\\Files\\Controller\\DirectEditingController' => $baseDir.'/../lib/Controller/DirectEditingController.php',
37
+    'OCA\\Files\\Controller\\DirectEditingViewController' => $baseDir.'/../lib/Controller/DirectEditingViewController.php',
38
+    'OCA\\Files\\Controller\\OpenLocalEditorController' => $baseDir.'/../lib/Controller/OpenLocalEditorController.php',
39
+    'OCA\\Files\\Controller\\TemplateController' => $baseDir.'/../lib/Controller/TemplateController.php',
40
+    'OCA\\Files\\Controller\\TransferOwnershipController' => $baseDir.'/../lib/Controller/TransferOwnershipController.php',
41
+    'OCA\\Files\\Controller\\ViewController' => $baseDir.'/../lib/Controller/ViewController.php',
42
+    'OCA\\Files\\Db\\OpenLocalEditor' => $baseDir.'/../lib/Db/OpenLocalEditor.php',
43
+    'OCA\\Files\\Db\\OpenLocalEditorMapper' => $baseDir.'/../lib/Db/OpenLocalEditorMapper.php',
44
+    'OCA\\Files\\Db\\TransferOwnership' => $baseDir.'/../lib/Db/TransferOwnership.php',
45
+    'OCA\\Files\\Db\\TransferOwnershipMapper' => $baseDir.'/../lib/Db/TransferOwnershipMapper.php',
46
+    'OCA\\Files\\DirectEditingCapabilities' => $baseDir.'/../lib/DirectEditingCapabilities.php',
47
+    'OCA\\Files\\Event\\LoadAdditionalScriptsEvent' => $baseDir.'/../lib/Event/LoadAdditionalScriptsEvent.php',
48
+    'OCA\\Files\\Event\\LoadSidebar' => $baseDir.'/../lib/Event/LoadSidebar.php',
49
+    'OCA\\Files\\Exception\\TransferOwnershipException' => $baseDir.'/../lib/Exception/TransferOwnershipException.php',
50
+    'OCA\\Files\\Helper' => $baseDir.'/../lib/Helper.php',
51
+    'OCA\\Files\\Listener\\LegacyLoadAdditionalScriptsAdapter' => $baseDir.'/../lib/Listener/LegacyLoadAdditionalScriptsAdapter.php',
52
+    'OCA\\Files\\Listener\\LoadSidebarListener' => $baseDir.'/../lib/Listener/LoadSidebarListener.php',
53
+    'OCA\\Files\\Migration\\Version11301Date20191205150729' => $baseDir.'/../lib/Migration/Version11301Date20191205150729.php',
54
+    'OCA\\Files\\Migration\\Version12101Date20221011153334' => $baseDir.'/../lib/Migration/Version12101Date20221011153334.php',
55
+    'OCA\\Files\\Notification\\Notifier' => $baseDir.'/../lib/Notification/Notifier.php',
56
+    'OCA\\Files\\Search\\FilesSearchProvider' => $baseDir.'/../lib/Search/FilesSearchProvider.php',
57
+    'OCA\\Files\\Service\\DirectEditingService' => $baseDir.'/../lib/Service/DirectEditingService.php',
58
+    'OCA\\Files\\Service\\OwnershipTransferService' => $baseDir.'/../lib/Service/OwnershipTransferService.php',
59
+    'OCA\\Files\\Service\\TagService' => $baseDir.'/../lib/Service/TagService.php',
60
+    'OCA\\Files\\Service\\UserConfig' => $baseDir.'/../lib/Service/UserConfig.php',
61
+    'OCA\\Files\\Settings\\PersonalSettings' => $baseDir.'/../lib/Settings/PersonalSettings.php',
62 62
 );
Please login to merge, or discard this patch.
apps/files/composer/composer/autoload_static.php 1 patch
Spacing   +60 added lines, -60 removed lines patch added patch discarded remove patch
@@ -6,79 +6,79 @@
 block discarded – undo
6 6
 
7 7
 class ComposerStaticInitFiles
8 8
 {
9
-    public static $prefixLengthsPsr4 = array (
9
+    public static $prefixLengthsPsr4 = array(
10 10
         'O' => 
11
-        array (
11
+        array(
12 12
             'OCA\\Files\\' => 10,
13 13
         ),
14 14
     );
15 15
 
16
-    public static $prefixDirsPsr4 = array (
16
+    public static $prefixDirsPsr4 = array(
17 17
         'OCA\\Files\\' => 
18
-        array (
19
-            0 => __DIR__ . '/..' . '/../lib',
18
+        array(
19
+            0 => __DIR__.'/..'.'/../lib',
20 20
         ),
21 21
     );
22 22
 
23
-    public static $classMap = array (
24
-        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
25
-        'OCA\\Files\\Activity\\FavoriteProvider' => __DIR__ . '/..' . '/../lib/Activity/FavoriteProvider.php',
26
-        'OCA\\Files\\Activity\\Filter\\Favorites' => __DIR__ . '/..' . '/../lib/Activity/Filter/Favorites.php',
27
-        'OCA\\Files\\Activity\\Filter\\FileChanges' => __DIR__ . '/..' . '/../lib/Activity/Filter/FileChanges.php',
28
-        'OCA\\Files\\Activity\\Helper' => __DIR__ . '/..' . '/../lib/Activity/Helper.php',
29
-        'OCA\\Files\\Activity\\Provider' => __DIR__ . '/..' . '/../lib/Activity/Provider.php',
30
-        'OCA\\Files\\Activity\\Settings\\FavoriteAction' => __DIR__ . '/..' . '/../lib/Activity/Settings/FavoriteAction.php',
31
-        'OCA\\Files\\Activity\\Settings\\FileActivitySettings' => __DIR__ . '/..' . '/../lib/Activity/Settings/FileActivitySettings.php',
32
-        'OCA\\Files\\Activity\\Settings\\FileChanged' => __DIR__ . '/..' . '/../lib/Activity/Settings/FileChanged.php',
33
-        'OCA\\Files\\Activity\\Settings\\FileFavoriteChanged' => __DIR__ . '/..' . '/../lib/Activity/Settings/FileFavoriteChanged.php',
34
-        'OCA\\Files\\App' => __DIR__ . '/..' . '/../lib/App.php',
35
-        'OCA\\Files\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php',
36
-        'OCA\\Files\\BackgroundJob\\CleanupDirectEditingTokens' => __DIR__ . '/..' . '/../lib/BackgroundJob/CleanupDirectEditingTokens.php',
37
-        'OCA\\Files\\BackgroundJob\\CleanupFileLocks' => __DIR__ . '/..' . '/../lib/BackgroundJob/CleanupFileLocks.php',
38
-        'OCA\\Files\\BackgroundJob\\DeleteExpiredOpenLocalEditor' => __DIR__ . '/..' . '/../lib/BackgroundJob/DeleteExpiredOpenLocalEditor.php',
39
-        'OCA\\Files\\BackgroundJob\\DeleteOrphanedItems' => __DIR__ . '/..' . '/../lib/BackgroundJob/DeleteOrphanedItems.php',
40
-        'OCA\\Files\\BackgroundJob\\ScanFiles' => __DIR__ . '/..' . '/../lib/BackgroundJob/ScanFiles.php',
41
-        'OCA\\Files\\BackgroundJob\\TransferOwnership' => __DIR__ . '/..' . '/../lib/BackgroundJob/TransferOwnership.php',
42
-        'OCA\\Files\\Capabilities' => __DIR__ . '/..' . '/../lib/Capabilities.php',
43
-        'OCA\\Files\\Collaboration\\Resources\\Listener' => __DIR__ . '/..' . '/../lib/Collaboration/Resources/Listener.php',
44
-        'OCA\\Files\\Collaboration\\Resources\\ResourceProvider' => __DIR__ . '/..' . '/../lib/Collaboration/Resources/ResourceProvider.php',
45
-        'OCA\\Files\\Command\\DeleteOrphanedFiles' => __DIR__ . '/..' . '/../lib/Command/DeleteOrphanedFiles.php',
46
-        'OCA\\Files\\Command\\RepairTree' => __DIR__ . '/..' . '/../lib/Command/RepairTree.php',
47
-        'OCA\\Files\\Command\\Scan' => __DIR__ . '/..' . '/../lib/Command/Scan.php',
48
-        'OCA\\Files\\Command\\ScanAppData' => __DIR__ . '/..' . '/../lib/Command/ScanAppData.php',
49
-        'OCA\\Files\\Command\\TransferOwnership' => __DIR__ . '/..' . '/../lib/Command/TransferOwnership.php',
50
-        'OCA\\Files\\Controller\\ApiController' => __DIR__ . '/..' . '/../lib/Controller/ApiController.php',
51
-        'OCA\\Files\\Controller\\DirectEditingController' => __DIR__ . '/..' . '/../lib/Controller/DirectEditingController.php',
52
-        'OCA\\Files\\Controller\\DirectEditingViewController' => __DIR__ . '/..' . '/../lib/Controller/DirectEditingViewController.php',
53
-        'OCA\\Files\\Controller\\OpenLocalEditorController' => __DIR__ . '/..' . '/../lib/Controller/OpenLocalEditorController.php',
54
-        'OCA\\Files\\Controller\\TemplateController' => __DIR__ . '/..' . '/../lib/Controller/TemplateController.php',
55
-        'OCA\\Files\\Controller\\TransferOwnershipController' => __DIR__ . '/..' . '/../lib/Controller/TransferOwnershipController.php',
56
-        'OCA\\Files\\Controller\\ViewController' => __DIR__ . '/..' . '/../lib/Controller/ViewController.php',
57
-        'OCA\\Files\\Db\\OpenLocalEditor' => __DIR__ . '/..' . '/../lib/Db/OpenLocalEditor.php',
58
-        'OCA\\Files\\Db\\OpenLocalEditorMapper' => __DIR__ . '/..' . '/../lib/Db/OpenLocalEditorMapper.php',
59
-        'OCA\\Files\\Db\\TransferOwnership' => __DIR__ . '/..' . '/../lib/Db/TransferOwnership.php',
60
-        'OCA\\Files\\Db\\TransferOwnershipMapper' => __DIR__ . '/..' . '/../lib/Db/TransferOwnershipMapper.php',
61
-        'OCA\\Files\\DirectEditingCapabilities' => __DIR__ . '/..' . '/../lib/DirectEditingCapabilities.php',
62
-        'OCA\\Files\\Event\\LoadAdditionalScriptsEvent' => __DIR__ . '/..' . '/../lib/Event/LoadAdditionalScriptsEvent.php',
63
-        'OCA\\Files\\Event\\LoadSidebar' => __DIR__ . '/..' . '/../lib/Event/LoadSidebar.php',
64
-        'OCA\\Files\\Exception\\TransferOwnershipException' => __DIR__ . '/..' . '/../lib/Exception/TransferOwnershipException.php',
65
-        'OCA\\Files\\Helper' => __DIR__ . '/..' . '/../lib/Helper.php',
66
-        'OCA\\Files\\Listener\\LegacyLoadAdditionalScriptsAdapter' => __DIR__ . '/..' . '/../lib/Listener/LegacyLoadAdditionalScriptsAdapter.php',
67
-        'OCA\\Files\\Listener\\LoadSidebarListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSidebarListener.php',
68
-        'OCA\\Files\\Migration\\Version11301Date20191205150729' => __DIR__ . '/..' . '/../lib/Migration/Version11301Date20191205150729.php',
69
-        'OCA\\Files\\Migration\\Version12101Date20221011153334' => __DIR__ . '/..' . '/../lib/Migration/Version12101Date20221011153334.php',
70
-        'OCA\\Files\\Notification\\Notifier' => __DIR__ . '/..' . '/../lib/Notification/Notifier.php',
71
-        'OCA\\Files\\Search\\FilesSearchProvider' => __DIR__ . '/..' . '/../lib/Search/FilesSearchProvider.php',
72
-        'OCA\\Files\\Service\\DirectEditingService' => __DIR__ . '/..' . '/../lib/Service/DirectEditingService.php',
73
-        'OCA\\Files\\Service\\OwnershipTransferService' => __DIR__ . '/..' . '/../lib/Service/OwnershipTransferService.php',
74
-        'OCA\\Files\\Service\\TagService' => __DIR__ . '/..' . '/../lib/Service/TagService.php',
75
-        'OCA\\Files\\Service\\UserConfig' => __DIR__ . '/..' . '/../lib/Service/UserConfig.php',
76
-        'OCA\\Files\\Settings\\PersonalSettings' => __DIR__ . '/..' . '/../lib/Settings/PersonalSettings.php',
23
+    public static $classMap = array(
24
+        'Composer\\InstalledVersions' => __DIR__.'/..'.'/composer/InstalledVersions.php',
25
+        'OCA\\Files\\Activity\\FavoriteProvider' => __DIR__.'/..'.'/../lib/Activity/FavoriteProvider.php',
26
+        'OCA\\Files\\Activity\\Filter\\Favorites' => __DIR__.'/..'.'/../lib/Activity/Filter/Favorites.php',
27
+        'OCA\\Files\\Activity\\Filter\\FileChanges' => __DIR__.'/..'.'/../lib/Activity/Filter/FileChanges.php',
28
+        'OCA\\Files\\Activity\\Helper' => __DIR__.'/..'.'/../lib/Activity/Helper.php',
29
+        'OCA\\Files\\Activity\\Provider' => __DIR__.'/..'.'/../lib/Activity/Provider.php',
30
+        'OCA\\Files\\Activity\\Settings\\FavoriteAction' => __DIR__.'/..'.'/../lib/Activity/Settings/FavoriteAction.php',
31
+        'OCA\\Files\\Activity\\Settings\\FileActivitySettings' => __DIR__.'/..'.'/../lib/Activity/Settings/FileActivitySettings.php',
32
+        'OCA\\Files\\Activity\\Settings\\FileChanged' => __DIR__.'/..'.'/../lib/Activity/Settings/FileChanged.php',
33
+        'OCA\\Files\\Activity\\Settings\\FileFavoriteChanged' => __DIR__.'/..'.'/../lib/Activity/Settings/FileFavoriteChanged.php',
34
+        'OCA\\Files\\App' => __DIR__.'/..'.'/../lib/App.php',
35
+        'OCA\\Files\\AppInfo\\Application' => __DIR__.'/..'.'/../lib/AppInfo/Application.php',
36
+        'OCA\\Files\\BackgroundJob\\CleanupDirectEditingTokens' => __DIR__.'/..'.'/../lib/BackgroundJob/CleanupDirectEditingTokens.php',
37
+        'OCA\\Files\\BackgroundJob\\CleanupFileLocks' => __DIR__.'/..'.'/../lib/BackgroundJob/CleanupFileLocks.php',
38
+        'OCA\\Files\\BackgroundJob\\DeleteExpiredOpenLocalEditor' => __DIR__.'/..'.'/../lib/BackgroundJob/DeleteExpiredOpenLocalEditor.php',
39
+        'OCA\\Files\\BackgroundJob\\DeleteOrphanedItems' => __DIR__.'/..'.'/../lib/BackgroundJob/DeleteOrphanedItems.php',
40
+        'OCA\\Files\\BackgroundJob\\ScanFiles' => __DIR__.'/..'.'/../lib/BackgroundJob/ScanFiles.php',
41
+        'OCA\\Files\\BackgroundJob\\TransferOwnership' => __DIR__.'/..'.'/../lib/BackgroundJob/TransferOwnership.php',
42
+        'OCA\\Files\\Capabilities' => __DIR__.'/..'.'/../lib/Capabilities.php',
43
+        'OCA\\Files\\Collaboration\\Resources\\Listener' => __DIR__.'/..'.'/../lib/Collaboration/Resources/Listener.php',
44
+        'OCA\\Files\\Collaboration\\Resources\\ResourceProvider' => __DIR__.'/..'.'/../lib/Collaboration/Resources/ResourceProvider.php',
45
+        'OCA\\Files\\Command\\DeleteOrphanedFiles' => __DIR__.'/..'.'/../lib/Command/DeleteOrphanedFiles.php',
46
+        'OCA\\Files\\Command\\RepairTree' => __DIR__.'/..'.'/../lib/Command/RepairTree.php',
47
+        'OCA\\Files\\Command\\Scan' => __DIR__.'/..'.'/../lib/Command/Scan.php',
48
+        'OCA\\Files\\Command\\ScanAppData' => __DIR__.'/..'.'/../lib/Command/ScanAppData.php',
49
+        'OCA\\Files\\Command\\TransferOwnership' => __DIR__.'/..'.'/../lib/Command/TransferOwnership.php',
50
+        'OCA\\Files\\Controller\\ApiController' => __DIR__.'/..'.'/../lib/Controller/ApiController.php',
51
+        'OCA\\Files\\Controller\\DirectEditingController' => __DIR__.'/..'.'/../lib/Controller/DirectEditingController.php',
52
+        'OCA\\Files\\Controller\\DirectEditingViewController' => __DIR__.'/..'.'/../lib/Controller/DirectEditingViewController.php',
53
+        'OCA\\Files\\Controller\\OpenLocalEditorController' => __DIR__.'/..'.'/../lib/Controller/OpenLocalEditorController.php',
54
+        'OCA\\Files\\Controller\\TemplateController' => __DIR__.'/..'.'/../lib/Controller/TemplateController.php',
55
+        'OCA\\Files\\Controller\\TransferOwnershipController' => __DIR__.'/..'.'/../lib/Controller/TransferOwnershipController.php',
56
+        'OCA\\Files\\Controller\\ViewController' => __DIR__.'/..'.'/../lib/Controller/ViewController.php',
57
+        'OCA\\Files\\Db\\OpenLocalEditor' => __DIR__.'/..'.'/../lib/Db/OpenLocalEditor.php',
58
+        'OCA\\Files\\Db\\OpenLocalEditorMapper' => __DIR__.'/..'.'/../lib/Db/OpenLocalEditorMapper.php',
59
+        'OCA\\Files\\Db\\TransferOwnership' => __DIR__.'/..'.'/../lib/Db/TransferOwnership.php',
60
+        'OCA\\Files\\Db\\TransferOwnershipMapper' => __DIR__.'/..'.'/../lib/Db/TransferOwnershipMapper.php',
61
+        'OCA\\Files\\DirectEditingCapabilities' => __DIR__.'/..'.'/../lib/DirectEditingCapabilities.php',
62
+        'OCA\\Files\\Event\\LoadAdditionalScriptsEvent' => __DIR__.'/..'.'/../lib/Event/LoadAdditionalScriptsEvent.php',
63
+        'OCA\\Files\\Event\\LoadSidebar' => __DIR__.'/..'.'/../lib/Event/LoadSidebar.php',
64
+        'OCA\\Files\\Exception\\TransferOwnershipException' => __DIR__.'/..'.'/../lib/Exception/TransferOwnershipException.php',
65
+        'OCA\\Files\\Helper' => __DIR__.'/..'.'/../lib/Helper.php',
66
+        'OCA\\Files\\Listener\\LegacyLoadAdditionalScriptsAdapter' => __DIR__.'/..'.'/../lib/Listener/LegacyLoadAdditionalScriptsAdapter.php',
67
+        'OCA\\Files\\Listener\\LoadSidebarListener' => __DIR__.'/..'.'/../lib/Listener/LoadSidebarListener.php',
68
+        'OCA\\Files\\Migration\\Version11301Date20191205150729' => __DIR__.'/..'.'/../lib/Migration/Version11301Date20191205150729.php',
69
+        'OCA\\Files\\Migration\\Version12101Date20221011153334' => __DIR__.'/..'.'/../lib/Migration/Version12101Date20221011153334.php',
70
+        'OCA\\Files\\Notification\\Notifier' => __DIR__.'/..'.'/../lib/Notification/Notifier.php',
71
+        'OCA\\Files\\Search\\FilesSearchProvider' => __DIR__.'/..'.'/../lib/Search/FilesSearchProvider.php',
72
+        'OCA\\Files\\Service\\DirectEditingService' => __DIR__.'/..'.'/../lib/Service/DirectEditingService.php',
73
+        'OCA\\Files\\Service\\OwnershipTransferService' => __DIR__.'/..'.'/../lib/Service/OwnershipTransferService.php',
74
+        'OCA\\Files\\Service\\TagService' => __DIR__.'/..'.'/../lib/Service/TagService.php',
75
+        'OCA\\Files\\Service\\UserConfig' => __DIR__.'/..'.'/../lib/Service/UserConfig.php',
76
+        'OCA\\Files\\Settings\\PersonalSettings' => __DIR__.'/..'.'/../lib/Settings/PersonalSettings.php',
77 77
     );
78 78
 
79 79
     public static function getInitializer(ClassLoader $loader)
80 80
     {
81
-        return \Closure::bind(function () use ($loader) {
81
+        return \Closure::bind(function() use ($loader) {
82 82
             $loader->prefixLengthsPsr4 = ComposerStaticInitFiles::$prefixLengthsPsr4;
83 83
             $loader->prefixDirsPsr4 = ComposerStaticInitFiles::$prefixDirsPsr4;
84 84
             $loader->classMap = ComposerStaticInitFiles::$classMap;
Please login to merge, or discard this patch.