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