Completed
Pull Request — master (#9355)
by Robin
15:21
created
apps/dav/lib/Connector/Sabre/Directory.php 2 patches
Indentation   +401 added lines, -401 removed lines patch added patch discarded remove patch
@@ -50,405 +50,405 @@
 block discarded – undo
50 50
 use Sabre\DAV\Exception\NotFound;
51 51
 
52 52
 class Directory extends \OCA\DAV\Connector\Sabre\Node
53
-	implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota, \Sabre\DAV\IMoveTarget {
54
-
55
-	/**
56
-	 * Cached directory content
57
-	 *
58
-	 * @var \OCP\Files\FileInfo[]
59
-	 */
60
-	private $dirContent;
61
-
62
-	/**
63
-	 * Cached quota info
64
-	 *
65
-	 * @var array
66
-	 */
67
-	private $quotaInfo;
68
-
69
-	/**
70
-	 * @var ObjectTree|null
71
-	 */
72
-	private $tree;
73
-
74
-	/**
75
-	 * Sets up the node, expects a full path name
76
-	 *
77
-	 * @param \OC\Files\View $view
78
-	 * @param \OCP\Files\FileInfo $info
79
-	 * @param ObjectTree|null $tree
80
-	 * @param \OCP\Share\IManager $shareManager
81
-	 */
82
-	public function __construct(View $view, FileInfo $info, $tree = null, $shareManager = null) {
83
-		parent::__construct($view, $info, $shareManager);
84
-		$this->tree = $tree;
85
-	}
86
-
87
-	/**
88
-	 * Creates a new file in the directory
89
-	 *
90
-	 * Data will either be supplied as a stream resource, or in certain cases
91
-	 * as a string. Keep in mind that you may have to support either.
92
-	 *
93
-	 * After successful creation of the file, you may choose to return the ETag
94
-	 * of the new file here.
95
-	 *
96
-	 * The returned ETag must be surrounded by double-quotes (The quotes should
97
-	 * be part of the actual string).
98
-	 *
99
-	 * If you cannot accurately determine the ETag, you should not return it.
100
-	 * If you don't store the file exactly as-is (you're transforming it
101
-	 * somehow) you should also not return an ETag.
102
-	 *
103
-	 * This means that if a subsequent GET to this new file does not exactly
104
-	 * return the same contents of what was submitted here, you are strongly
105
-	 * recommended to omit the ETag.
106
-	 *
107
-	 * @param string $name Name of the file
108
-	 * @param resource|string $data Initial payload
109
-	 * @return null|string
110
-	 * @throws Exception\EntityTooLarge
111
-	 * @throws Exception\UnsupportedMediaType
112
-	 * @throws FileLocked
113
-	 * @throws InvalidPath
114
-	 * @throws \Sabre\DAV\Exception
115
-	 * @throws \Sabre\DAV\Exception\BadRequest
116
-	 * @throws \Sabre\DAV\Exception\Forbidden
117
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
118
-	 */
119
-	public function createFile($name, $data = null) {
120
-
121
-		try {
122
-			// for chunked upload also updating a existing file is a "createFile"
123
-			// because we create all the chunks before re-assemble them to the existing file.
124
-			if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
125
-
126
-				// exit if we can't create a new file and we don't updatable existing file
127
-				$chunkInfo = \OC_FileChunking::decodeName($name);
128
-				if (!$this->fileView->isCreatable($this->path) &&
129
-					!$this->fileView->isUpdatable($this->path . '/' . $chunkInfo['name'])
130
-				) {
131
-					throw new \Sabre\DAV\Exception\Forbidden();
132
-				}
133
-
134
-			} else {
135
-				// For non-chunked upload it is enough to check if we can create a new file
136
-				if (!$this->fileView->isCreatable($this->path)) {
137
-					throw new \Sabre\DAV\Exception\Forbidden();
138
-				}
139
-			}
140
-
141
-			$this->fileView->verifyPath($this->path, $name);
142
-
143
-			$path = $this->fileView->getAbsolutePath($this->path) . '/' . $name;
144
-			// in case the file already exists/overwriting
145
-			$info = $this->fileView->getFileInfo($this->path . '/' . $name);
146
-			if (!$info) {
147
-				// use a dummy FileInfo which is acceptable here since it will be refreshed after the put is complete
148
-				$info = new \OC\Files\FileInfo($path, null, null, [], null);
149
-			}
150
-			$node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
151
-
152
-			// only allow 1 process to upload a file at once but still allow reading the file while writing the part file
153
-			$node->acquireLock(ILockingProvider::LOCK_SHARED);
154
-			$this->fileView->lockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
155
-
156
-			$result = $node->put($data);
157
-
158
-			$this->fileView->unlockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
159
-			$node->releaseLock(ILockingProvider::LOCK_SHARED);
160
-			return $result;
161
-		} catch (\OCP\Files\StorageNotAvailableException $e) {
162
-			throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage(), $e->getCode(), $e);
163
-		} catch (InvalidPathException $ex) {
164
-			throw new InvalidPath($ex->getMessage(), false, $ex);
165
-		} catch (ForbiddenException $ex) {
166
-			throw new Forbidden($ex->getMessage(), $ex->getRetry(), $ex);
167
-		} catch (LockedException $e) {
168
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
169
-		}
170
-	}
171
-
172
-	/**
173
-	 * Creates a new subdirectory
174
-	 *
175
-	 * @param string $name
176
-	 * @throws FileLocked
177
-	 * @throws InvalidPath
178
-	 * @throws \Sabre\DAV\Exception\Forbidden
179
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
180
-	 */
181
-	public function createDirectory($name) {
182
-		try {
183
-			if (!$this->info->isCreatable()) {
184
-				throw new \Sabre\DAV\Exception\Forbidden();
185
-			}
186
-
187
-			$this->fileView->verifyPath($this->path, $name);
188
-			$newPath = $this->path . '/' . $name;
189
-			if (!$this->fileView->mkdir($newPath)) {
190
-				throw new \Sabre\DAV\Exception\Forbidden('Could not create directory ' . $newPath);
191
-			}
192
-		} catch (\OCP\Files\StorageNotAvailableException $e) {
193
-			throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
194
-		} catch (InvalidPathException $ex) {
195
-			throw new InvalidPath($ex->getMessage());
196
-		} catch (ForbiddenException $ex) {
197
-			throw new Forbidden($ex->getMessage(), $ex->getRetry());
198
-		} catch (LockedException $e) {
199
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
200
-		}
201
-	}
202
-
203
-	/**
204
-	 * Returns a specific child node, referenced by its name
205
-	 *
206
-	 * @param string $name
207
-	 * @param \OCP\Files\FileInfo $info
208
-	 * @return \Sabre\DAV\INode
209
-	 * @throws InvalidPath
210
-	 * @throws \Sabre\DAV\Exception\NotFound
211
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
212
-	 */
213
-	public function getChild($name, $info = null) {
214
-		if (!$this->info->isReadable()) {
215
-			// avoid detecting files through this way
216
-			throw new NotFound();
217
-		}
218
-
219
-		$path = $this->path . '/' . $name;
220
-		if (is_null($info)) {
221
-			try {
222
-				$this->fileView->verifyPath($this->path, $name);
223
-				$info = $this->fileView->getFileInfo($path);
224
-			} catch (\OCP\Files\StorageNotAvailableException $e) {
225
-				throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
226
-			} catch (InvalidPathException $ex) {
227
-				throw new InvalidPath($ex->getMessage());
228
-			} catch (ForbiddenException $e) {
229
-				throw new \Sabre\DAV\Exception\Forbidden();
230
-			}
231
-		}
232
-
233
-		if (!$info) {
234
-			throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
235
-		}
236
-
237
-		if ($info['mimetype'] === 'httpd/unix-directory') {
238
-			$node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this->tree, $this->shareManager);
239
-		} else {
240
-			$node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info, $this->shareManager);
241
-		}
242
-		if ($this->tree) {
243
-			$this->tree->cacheNode($node);
244
-		}
245
-		return $node;
246
-	}
247
-
248
-	/**
249
-	 * Returns an array with all the child nodes
250
-	 *
251
-	 * @return \Sabre\DAV\INode[]
252
-	 * @throws \Sabre\DAV\Exception\Locked
253
-	 * @throws \OCA\DAV\Connector\Sabre\Exception\Forbidden
254
-	 */
255
-	public function getChildren() {
256
-		if (!is_null($this->dirContent)) {
257
-			return $this->dirContent;
258
-		}
259
-		try {
260
-			if (!$this->info->isReadable()) {
261
-				// return 403 instead of 404 because a 404 would make
262
-				// the caller believe that the collection itself does not exist
263
-				throw new Forbidden('No read permissions');
264
-			}
265
-			$folderContent = $this->fileView->getDirectoryContent($this->path);
266
-		} catch (LockedException $e) {
267
-			throw new Locked();
268
-		}
269
-
270
-		$nodes = array();
271
-		foreach ($folderContent as $info) {
272
-			$node = $this->getChild($info->getName(), $info);
273
-			$nodes[] = $node;
274
-		}
275
-		$this->dirContent = $nodes;
276
-		return $this->dirContent;
277
-	}
278
-
279
-	/**
280
-	 * Checks if a child exists.
281
-	 *
282
-	 * @param string $name
283
-	 * @return bool
284
-	 */
285
-	public function childExists($name) {
286
-		// note: here we do NOT resolve the chunk file name to the real file name
287
-		// to make sure we return false when checking for file existence with a chunk
288
-		// file name.
289
-		// This is to make sure that "createFile" is still triggered
290
-		// (required old code) instead of "updateFile".
291
-		//
292
-		// TODO: resolve chunk file name here and implement "updateFile"
293
-		$path = $this->path . '/' . $name;
294
-		return $this->fileView->file_exists($path);
295
-
296
-	}
297
-
298
-	/**
299
-	 * Deletes all files in this directory, and then itself
300
-	 *
301
-	 * @return void
302
-	 * @throws FileLocked
303
-	 * @throws \Sabre\DAV\Exception\Forbidden
304
-	 */
305
-	public function delete() {
306
-
307
-		if ($this->path === '' || $this->path === '/' || !$this->info->isDeletable()) {
308
-			throw new \Sabre\DAV\Exception\Forbidden();
309
-		}
310
-
311
-		try {
312
-			if (!$this->fileView->rmdir($this->path)) {
313
-				// assume it wasn't possible to remove due to permission issue
314
-				throw new \Sabre\DAV\Exception\Forbidden();
315
-			}
316
-		} catch (ForbiddenException $ex) {
317
-			throw new Forbidden($ex->getMessage(), $ex->getRetry());
318
-		} catch (LockedException $e) {
319
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
320
-		}
321
-	}
322
-
323
-	/**
324
-	 * Returns available diskspace information
325
-	 *
326
-	 * @return array
327
-	 */
328
-	public function getQuotaInfo() {
329
-		if ($this->quotaInfo) {
330
-			return $this->quotaInfo;
331
-		}
332
-		try {
333
-			$storageInfo = \OC_Helper::getStorageInfo($this->info->getPath(), $this->info);
334
-			if ($storageInfo['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED) {
335
-				$free = \OCP\Files\FileInfo::SPACE_UNLIMITED;
336
-			} else {
337
-				$free = $storageInfo['free'];
338
-			}
339
-			$this->quotaInfo = array(
340
-				$storageInfo['used'],
341
-				$free
342
-			);
343
-			return $this->quotaInfo;
344
-		} catch (\OCP\Files\StorageNotAvailableException $e) {
345
-			return array(0, 0);
346
-		}
347
-	}
348
-
349
-	/**
350
-	 * Moves a node into this collection.
351
-	 *
352
-	 * It is up to the implementors to:
353
-	 *   1. Create the new resource.
354
-	 *   2. Remove the old resource.
355
-	 *   3. Transfer any properties or other data.
356
-	 *
357
-	 * Generally you should make very sure that your collection can easily move
358
-	 * the move.
359
-	 *
360
-	 * If you don't, just return false, which will trigger sabre/dav to handle
361
-	 * the move itself. If you return true from this function, the assumption
362
-	 * is that the move was successful.
363
-	 *
364
-	 * @param string $targetName New local file/collection name.
365
-	 * @param string $fullSourcePath Full path to source node
366
-	 * @param INode $sourceNode Source node itself
367
-	 * @return bool
368
-	 * @throws BadRequest
369
-	 * @throws ServiceUnavailable
370
-	 * @throws Forbidden
371
-	 * @throws FileLocked
372
-	 * @throws \Sabre\DAV\Exception\Forbidden
373
-	 */
374
-	public function moveInto($targetName, $fullSourcePath, INode $sourceNode) {
375
-		if (!$sourceNode instanceof Node) {
376
-			// it's a file of another kind, like FutureFile
377
-			if ($sourceNode instanceof IFile) {
378
-				// fallback to default copy+delete handling
379
-				return false;
380
-			}
381
-			throw new BadRequest('Incompatible node types');
382
-		}
383
-
384
-		if (!$this->fileView) {
385
-			throw new ServiceUnavailable('filesystem not setup');
386
-		}
387
-
388
-		$destinationPath = $this->getPath() . '/' . $targetName;
389
-
390
-
391
-		$targetNodeExists = $this->childExists($targetName);
392
-
393
-		// at getNodeForPath we also check the path for isForbiddenFileOrDir
394
-		// with that we have covered both source and destination
395
-		if ($sourceNode instanceof Directory && $targetNodeExists) {
396
-			throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode->getName() . ', target exists');
397
-		}
398
-
399
-		list($sourceDir,) = \Sabre\Uri\split($sourceNode->getPath());
400
-		$destinationDir = $this->getPath();
401
-
402
-		$sourcePath = $sourceNode->getPath();
403
-
404
-		$isMovableMount = false;
405
-		$sourceMount = \OC::$server->getMountManager()->find($this->fileView->getAbsolutePath($sourcePath));
406
-		$internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath));
407
-		if ($sourceMount instanceof MoveableMount && $internalPath === '') {
408
-			$isMovableMount = true;
409
-		}
410
-
411
-		try {
412
-			$sameFolder = ($sourceDir === $destinationDir);
413
-			// if we're overwriting or same folder
414
-			if ($targetNodeExists || $sameFolder) {
415
-				// note that renaming a share mount point is always allowed
416
-				if (!$this->fileView->isUpdatable($destinationDir) && !$isMovableMount) {
417
-					throw new \Sabre\DAV\Exception\Forbidden();
418
-				}
419
-			} else {
420
-				if (!$this->fileView->isCreatable($destinationDir)) {
421
-					throw new \Sabre\DAV\Exception\Forbidden();
422
-				}
423
-			}
424
-
425
-			if (!$sameFolder) {
426
-				// moving to a different folder, source will be gone, like a deletion
427
-				// note that moving a share mount point is always allowed
428
-				if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) {
429
-					throw new \Sabre\DAV\Exception\Forbidden();
430
-				}
431
-			}
432
-
433
-			$fileName = basename($destinationPath);
434
-			try {
435
-				$this->fileView->verifyPath($destinationDir, $fileName);
436
-			} catch (InvalidPathException $ex) {
437
-				throw new InvalidPath($ex->getMessage());
438
-			}
439
-
440
-			$renameOkay = $this->fileView->rename($sourcePath, $destinationPath);
441
-			if (!$renameOkay) {
442
-				throw new \Sabre\DAV\Exception\Forbidden('');
443
-			}
444
-		} catch (StorageNotAvailableException $e) {
445
-			throw new ServiceUnavailable($e->getMessage());
446
-		} catch (ForbiddenException $ex) {
447
-			throw new Forbidden($ex->getMessage(), $ex->getRetry());
448
-		} catch (LockedException $e) {
449
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
450
-		}
451
-
452
-		return true;
453
-	}
53
+    implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota, \Sabre\DAV\IMoveTarget {
54
+
55
+    /**
56
+     * Cached directory content
57
+     *
58
+     * @var \OCP\Files\FileInfo[]
59
+     */
60
+    private $dirContent;
61
+
62
+    /**
63
+     * Cached quota info
64
+     *
65
+     * @var array
66
+     */
67
+    private $quotaInfo;
68
+
69
+    /**
70
+     * @var ObjectTree|null
71
+     */
72
+    private $tree;
73
+
74
+    /**
75
+     * Sets up the node, expects a full path name
76
+     *
77
+     * @param \OC\Files\View $view
78
+     * @param \OCP\Files\FileInfo $info
79
+     * @param ObjectTree|null $tree
80
+     * @param \OCP\Share\IManager $shareManager
81
+     */
82
+    public function __construct(View $view, FileInfo $info, $tree = null, $shareManager = null) {
83
+        parent::__construct($view, $info, $shareManager);
84
+        $this->tree = $tree;
85
+    }
86
+
87
+    /**
88
+     * Creates a new file in the directory
89
+     *
90
+     * Data will either be supplied as a stream resource, or in certain cases
91
+     * as a string. Keep in mind that you may have to support either.
92
+     *
93
+     * After successful creation of the file, you may choose to return the ETag
94
+     * of the new file here.
95
+     *
96
+     * The returned ETag must be surrounded by double-quotes (The quotes should
97
+     * be part of the actual string).
98
+     *
99
+     * If you cannot accurately determine the ETag, you should not return it.
100
+     * If you don't store the file exactly as-is (you're transforming it
101
+     * somehow) you should also not return an ETag.
102
+     *
103
+     * This means that if a subsequent GET to this new file does not exactly
104
+     * return the same contents of what was submitted here, you are strongly
105
+     * recommended to omit the ETag.
106
+     *
107
+     * @param string $name Name of the file
108
+     * @param resource|string $data Initial payload
109
+     * @return null|string
110
+     * @throws Exception\EntityTooLarge
111
+     * @throws Exception\UnsupportedMediaType
112
+     * @throws FileLocked
113
+     * @throws InvalidPath
114
+     * @throws \Sabre\DAV\Exception
115
+     * @throws \Sabre\DAV\Exception\BadRequest
116
+     * @throws \Sabre\DAV\Exception\Forbidden
117
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
118
+     */
119
+    public function createFile($name, $data = null) {
120
+
121
+        try {
122
+            // for chunked upload also updating a existing file is a "createFile"
123
+            // because we create all the chunks before re-assemble them to the existing file.
124
+            if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
125
+
126
+                // exit if we can't create a new file and we don't updatable existing file
127
+                $chunkInfo = \OC_FileChunking::decodeName($name);
128
+                if (!$this->fileView->isCreatable($this->path) &&
129
+                    !$this->fileView->isUpdatable($this->path . '/' . $chunkInfo['name'])
130
+                ) {
131
+                    throw new \Sabre\DAV\Exception\Forbidden();
132
+                }
133
+
134
+            } else {
135
+                // For non-chunked upload it is enough to check if we can create a new file
136
+                if (!$this->fileView->isCreatable($this->path)) {
137
+                    throw new \Sabre\DAV\Exception\Forbidden();
138
+                }
139
+            }
140
+
141
+            $this->fileView->verifyPath($this->path, $name);
142
+
143
+            $path = $this->fileView->getAbsolutePath($this->path) . '/' . $name;
144
+            // in case the file already exists/overwriting
145
+            $info = $this->fileView->getFileInfo($this->path . '/' . $name);
146
+            if (!$info) {
147
+                // use a dummy FileInfo which is acceptable here since it will be refreshed after the put is complete
148
+                $info = new \OC\Files\FileInfo($path, null, null, [], null);
149
+            }
150
+            $node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
151
+
152
+            // only allow 1 process to upload a file at once but still allow reading the file while writing the part file
153
+            $node->acquireLock(ILockingProvider::LOCK_SHARED);
154
+            $this->fileView->lockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
155
+
156
+            $result = $node->put($data);
157
+
158
+            $this->fileView->unlockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
159
+            $node->releaseLock(ILockingProvider::LOCK_SHARED);
160
+            return $result;
161
+        } catch (\OCP\Files\StorageNotAvailableException $e) {
162
+            throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage(), $e->getCode(), $e);
163
+        } catch (InvalidPathException $ex) {
164
+            throw new InvalidPath($ex->getMessage(), false, $ex);
165
+        } catch (ForbiddenException $ex) {
166
+            throw new Forbidden($ex->getMessage(), $ex->getRetry(), $ex);
167
+        } catch (LockedException $e) {
168
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
169
+        }
170
+    }
171
+
172
+    /**
173
+     * Creates a new subdirectory
174
+     *
175
+     * @param string $name
176
+     * @throws FileLocked
177
+     * @throws InvalidPath
178
+     * @throws \Sabre\DAV\Exception\Forbidden
179
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
180
+     */
181
+    public function createDirectory($name) {
182
+        try {
183
+            if (!$this->info->isCreatable()) {
184
+                throw new \Sabre\DAV\Exception\Forbidden();
185
+            }
186
+
187
+            $this->fileView->verifyPath($this->path, $name);
188
+            $newPath = $this->path . '/' . $name;
189
+            if (!$this->fileView->mkdir($newPath)) {
190
+                throw new \Sabre\DAV\Exception\Forbidden('Could not create directory ' . $newPath);
191
+            }
192
+        } catch (\OCP\Files\StorageNotAvailableException $e) {
193
+            throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
194
+        } catch (InvalidPathException $ex) {
195
+            throw new InvalidPath($ex->getMessage());
196
+        } catch (ForbiddenException $ex) {
197
+            throw new Forbidden($ex->getMessage(), $ex->getRetry());
198
+        } catch (LockedException $e) {
199
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
200
+        }
201
+    }
202
+
203
+    /**
204
+     * Returns a specific child node, referenced by its name
205
+     *
206
+     * @param string $name
207
+     * @param \OCP\Files\FileInfo $info
208
+     * @return \Sabre\DAV\INode
209
+     * @throws InvalidPath
210
+     * @throws \Sabre\DAV\Exception\NotFound
211
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
212
+     */
213
+    public function getChild($name, $info = null) {
214
+        if (!$this->info->isReadable()) {
215
+            // avoid detecting files through this way
216
+            throw new NotFound();
217
+        }
218
+
219
+        $path = $this->path . '/' . $name;
220
+        if (is_null($info)) {
221
+            try {
222
+                $this->fileView->verifyPath($this->path, $name);
223
+                $info = $this->fileView->getFileInfo($path);
224
+            } catch (\OCP\Files\StorageNotAvailableException $e) {
225
+                throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
226
+            } catch (InvalidPathException $ex) {
227
+                throw new InvalidPath($ex->getMessage());
228
+            } catch (ForbiddenException $e) {
229
+                throw new \Sabre\DAV\Exception\Forbidden();
230
+            }
231
+        }
232
+
233
+        if (!$info) {
234
+            throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
235
+        }
236
+
237
+        if ($info['mimetype'] === 'httpd/unix-directory') {
238
+            $node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this->tree, $this->shareManager);
239
+        } else {
240
+            $node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info, $this->shareManager);
241
+        }
242
+        if ($this->tree) {
243
+            $this->tree->cacheNode($node);
244
+        }
245
+        return $node;
246
+    }
247
+
248
+    /**
249
+     * Returns an array with all the child nodes
250
+     *
251
+     * @return \Sabre\DAV\INode[]
252
+     * @throws \Sabre\DAV\Exception\Locked
253
+     * @throws \OCA\DAV\Connector\Sabre\Exception\Forbidden
254
+     */
255
+    public function getChildren() {
256
+        if (!is_null($this->dirContent)) {
257
+            return $this->dirContent;
258
+        }
259
+        try {
260
+            if (!$this->info->isReadable()) {
261
+                // return 403 instead of 404 because a 404 would make
262
+                // the caller believe that the collection itself does not exist
263
+                throw new Forbidden('No read permissions');
264
+            }
265
+            $folderContent = $this->fileView->getDirectoryContent($this->path);
266
+        } catch (LockedException $e) {
267
+            throw new Locked();
268
+        }
269
+
270
+        $nodes = array();
271
+        foreach ($folderContent as $info) {
272
+            $node = $this->getChild($info->getName(), $info);
273
+            $nodes[] = $node;
274
+        }
275
+        $this->dirContent = $nodes;
276
+        return $this->dirContent;
277
+    }
278
+
279
+    /**
280
+     * Checks if a child exists.
281
+     *
282
+     * @param string $name
283
+     * @return bool
284
+     */
285
+    public function childExists($name) {
286
+        // note: here we do NOT resolve the chunk file name to the real file name
287
+        // to make sure we return false when checking for file existence with a chunk
288
+        // file name.
289
+        // This is to make sure that "createFile" is still triggered
290
+        // (required old code) instead of "updateFile".
291
+        //
292
+        // TODO: resolve chunk file name here and implement "updateFile"
293
+        $path = $this->path . '/' . $name;
294
+        return $this->fileView->file_exists($path);
295
+
296
+    }
297
+
298
+    /**
299
+     * Deletes all files in this directory, and then itself
300
+     *
301
+     * @return void
302
+     * @throws FileLocked
303
+     * @throws \Sabre\DAV\Exception\Forbidden
304
+     */
305
+    public function delete() {
306
+
307
+        if ($this->path === '' || $this->path === '/' || !$this->info->isDeletable()) {
308
+            throw new \Sabre\DAV\Exception\Forbidden();
309
+        }
310
+
311
+        try {
312
+            if (!$this->fileView->rmdir($this->path)) {
313
+                // assume it wasn't possible to remove due to permission issue
314
+                throw new \Sabre\DAV\Exception\Forbidden();
315
+            }
316
+        } catch (ForbiddenException $ex) {
317
+            throw new Forbidden($ex->getMessage(), $ex->getRetry());
318
+        } catch (LockedException $e) {
319
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
320
+        }
321
+    }
322
+
323
+    /**
324
+     * Returns available diskspace information
325
+     *
326
+     * @return array
327
+     */
328
+    public function getQuotaInfo() {
329
+        if ($this->quotaInfo) {
330
+            return $this->quotaInfo;
331
+        }
332
+        try {
333
+            $storageInfo = \OC_Helper::getStorageInfo($this->info->getPath(), $this->info);
334
+            if ($storageInfo['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED) {
335
+                $free = \OCP\Files\FileInfo::SPACE_UNLIMITED;
336
+            } else {
337
+                $free = $storageInfo['free'];
338
+            }
339
+            $this->quotaInfo = array(
340
+                $storageInfo['used'],
341
+                $free
342
+            );
343
+            return $this->quotaInfo;
344
+        } catch (\OCP\Files\StorageNotAvailableException $e) {
345
+            return array(0, 0);
346
+        }
347
+    }
348
+
349
+    /**
350
+     * Moves a node into this collection.
351
+     *
352
+     * It is up to the implementors to:
353
+     *   1. Create the new resource.
354
+     *   2. Remove the old resource.
355
+     *   3. Transfer any properties or other data.
356
+     *
357
+     * Generally you should make very sure that your collection can easily move
358
+     * the move.
359
+     *
360
+     * If you don't, just return false, which will trigger sabre/dav to handle
361
+     * the move itself. If you return true from this function, the assumption
362
+     * is that the move was successful.
363
+     *
364
+     * @param string $targetName New local file/collection name.
365
+     * @param string $fullSourcePath Full path to source node
366
+     * @param INode $sourceNode Source node itself
367
+     * @return bool
368
+     * @throws BadRequest
369
+     * @throws ServiceUnavailable
370
+     * @throws Forbidden
371
+     * @throws FileLocked
372
+     * @throws \Sabre\DAV\Exception\Forbidden
373
+     */
374
+    public function moveInto($targetName, $fullSourcePath, INode $sourceNode) {
375
+        if (!$sourceNode instanceof Node) {
376
+            // it's a file of another kind, like FutureFile
377
+            if ($sourceNode instanceof IFile) {
378
+                // fallback to default copy+delete handling
379
+                return false;
380
+            }
381
+            throw new BadRequest('Incompatible node types');
382
+        }
383
+
384
+        if (!$this->fileView) {
385
+            throw new ServiceUnavailable('filesystem not setup');
386
+        }
387
+
388
+        $destinationPath = $this->getPath() . '/' . $targetName;
389
+
390
+
391
+        $targetNodeExists = $this->childExists($targetName);
392
+
393
+        // at getNodeForPath we also check the path for isForbiddenFileOrDir
394
+        // with that we have covered both source and destination
395
+        if ($sourceNode instanceof Directory && $targetNodeExists) {
396
+            throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode->getName() . ', target exists');
397
+        }
398
+
399
+        list($sourceDir,) = \Sabre\Uri\split($sourceNode->getPath());
400
+        $destinationDir = $this->getPath();
401
+
402
+        $sourcePath = $sourceNode->getPath();
403
+
404
+        $isMovableMount = false;
405
+        $sourceMount = \OC::$server->getMountManager()->find($this->fileView->getAbsolutePath($sourcePath));
406
+        $internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath));
407
+        if ($sourceMount instanceof MoveableMount && $internalPath === '') {
408
+            $isMovableMount = true;
409
+        }
410
+
411
+        try {
412
+            $sameFolder = ($sourceDir === $destinationDir);
413
+            // if we're overwriting or same folder
414
+            if ($targetNodeExists || $sameFolder) {
415
+                // note that renaming a share mount point is always allowed
416
+                if (!$this->fileView->isUpdatable($destinationDir) && !$isMovableMount) {
417
+                    throw new \Sabre\DAV\Exception\Forbidden();
418
+                }
419
+            } else {
420
+                if (!$this->fileView->isCreatable($destinationDir)) {
421
+                    throw new \Sabre\DAV\Exception\Forbidden();
422
+                }
423
+            }
424
+
425
+            if (!$sameFolder) {
426
+                // moving to a different folder, source will be gone, like a deletion
427
+                // note that moving a share mount point is always allowed
428
+                if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) {
429
+                    throw new \Sabre\DAV\Exception\Forbidden();
430
+                }
431
+            }
432
+
433
+            $fileName = basename($destinationPath);
434
+            try {
435
+                $this->fileView->verifyPath($destinationDir, $fileName);
436
+            } catch (InvalidPathException $ex) {
437
+                throw new InvalidPath($ex->getMessage());
438
+            }
439
+
440
+            $renameOkay = $this->fileView->rename($sourcePath, $destinationPath);
441
+            if (!$renameOkay) {
442
+                throw new \Sabre\DAV\Exception\Forbidden('');
443
+            }
444
+        } catch (StorageNotAvailableException $e) {
445
+            throw new ServiceUnavailable($e->getMessage());
446
+        } catch (ForbiddenException $ex) {
447
+            throw new Forbidden($ex->getMessage(), $ex->getRetry());
448
+        } catch (LockedException $e) {
449
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
450
+        }
451
+
452
+        return true;
453
+    }
454 454
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
126 126
 				// exit if we can't create a new file and we don't updatable existing file
127 127
 				$chunkInfo = \OC_FileChunking::decodeName($name);
128 128
 				if (!$this->fileView->isCreatable($this->path) &&
129
-					!$this->fileView->isUpdatable($this->path . '/' . $chunkInfo['name'])
129
+					!$this->fileView->isUpdatable($this->path.'/'.$chunkInfo['name'])
130 130
 				) {
131 131
 					throw new \Sabre\DAV\Exception\Forbidden();
132 132
 				}
@@ -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, [], null);
@@ -151,11 +151,11 @@  discard block
 block discarded – undo
151 151
 
152 152
 			// only allow 1 process to upload a file at once but still allow reading the file while writing the part file
153 153
 			$node->acquireLock(ILockingProvider::LOCK_SHARED);
154
-			$this->fileView->lockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
154
+			$this->fileView->lockFile($path.'.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
155 155
 
156 156
 			$result = $node->put($data);
157 157
 
158
-			$this->fileView->unlockFile($path . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
158
+			$this->fileView->unlockFile($path.'.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
159 159
 			$node->releaseLock(ILockingProvider::LOCK_SHARED);
160 160
 			return $result;
161 161
 		} catch (\OCP\Files\StorageNotAvailableException $e) {
@@ -185,9 +185,9 @@  discard block
 block discarded – undo
185 185
 			}
186 186
 
187 187
 			$this->fileView->verifyPath($this->path, $name);
188
-			$newPath = $this->path . '/' . $name;
188
+			$newPath = $this->path.'/'.$name;
189 189
 			if (!$this->fileView->mkdir($newPath)) {
190
-				throw new \Sabre\DAV\Exception\Forbidden('Could not create directory ' . $newPath);
190
+				throw new \Sabre\DAV\Exception\Forbidden('Could not create directory '.$newPath);
191 191
 			}
192 192
 		} catch (\OCP\Files\StorageNotAvailableException $e) {
193 193
 			throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
@@ -216,7 +216,7 @@  discard block
 block discarded – undo
216 216
 			throw new NotFound();
217 217
 		}
218 218
 
219
-		$path = $this->path . '/' . $name;
219
+		$path = $this->path.'/'.$name;
220 220
 		if (is_null($info)) {
221 221
 			try {
222 222
 				$this->fileView->verifyPath($this->path, $name);
@@ -231,7 +231,7 @@  discard block
 block discarded – undo
231 231
 		}
232 232
 
233 233
 		if (!$info) {
234
-			throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
234
+			throw new \Sabre\DAV\Exception\NotFound('File with name '.$path.' could not be located');
235 235
 		}
236 236
 
237 237
 		if ($info['mimetype'] === 'httpd/unix-directory') {
@@ -290,7 +290,7 @@  discard block
 block discarded – undo
290 290
 		// (required old code) instead of "updateFile".
291 291
 		//
292 292
 		// TODO: resolve chunk file name here and implement "updateFile"
293
-		$path = $this->path . '/' . $name;
293
+		$path = $this->path.'/'.$name;
294 294
 		return $this->fileView->file_exists($path);
295 295
 
296 296
 	}
@@ -385,7 +385,7 @@  discard block
 block discarded – undo
385 385
 			throw new ServiceUnavailable('filesystem not setup');
386 386
 		}
387 387
 
388
-		$destinationPath = $this->getPath() . '/' . $targetName;
388
+		$destinationPath = $this->getPath().'/'.$targetName;
389 389
 
390 390
 
391 391
 		$targetNodeExists = $this->childExists($targetName);
@@ -393,7 +393,7 @@  discard block
 block discarded – undo
393 393
 		// at getNodeForPath we also check the path for isForbiddenFileOrDir
394 394
 		// with that we have covered both source and destination
395 395
 		if ($sourceNode instanceof Directory && $targetNodeExists) {
396
-			throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode->getName() . ', target exists');
396
+			throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory '.$sourceNode->getName().', target exists');
397 397
 		}
398 398
 
399 399
 		list($sourceDir,) = \Sabre\Uri\split($sourceNode->getPath());
Please login to merge, or discard this patch.