Passed
Push — master ( 23e8ae...e8872f )
by Robin
16:16 queued 12s
created

Filesystem::initMountPoints()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 4
nop 1
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Bart Visscher <[email protected]>
7
 * @author Christopher Schäpers <[email protected]>
8
 * @author Christoph Wurst <[email protected]>
9
 * @author Florin Peter <[email protected]>
10
 * @author Joas Schilling <[email protected]>
11
 * @author Jörn Friedrich Dreyer <[email protected]>
12
 * @author korelstar <[email protected]>
13
 * @author Lukas Reschke <[email protected]>
14
 * @author Michael Gapczynski <[email protected]>
15
 * @author Morris Jobke <[email protected]>
16
 * @author Robin Appelman <[email protected]>
17
 * @author Robin McCorkell <[email protected]>
18
 * @author Roeland Jago Douma <[email protected]>
19
 * @author Sam Tuke <[email protected]>
20
 * @author Stephan Peijnik <[email protected]>
21
 * @author Vincent Petry <[email protected]>
22
 *
23
 * @license AGPL-3.0
24
 *
25
 * This code is free software: you can redistribute it and/or modify
26
 * it under the terms of the GNU Affero General Public License, version 3,
27
 * as published by the Free Software Foundation.
28
 *
29
 * This program is distributed in the hope that it will be useful,
30
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32
 * GNU Affero General Public License for more details.
33
 *
34
 * You should have received a copy of the GNU Affero General Public License, version 3,
35
 * along with this program. If not, see <http://www.gnu.org/licenses/>
36
 *
37
 */
38
namespace OC\Files;
39
40
use OC\Cache\CappedMemoryCache;
41
use OC\Files\Mount\MountPoint;
42
use OC\User\NoUserException;
43
use OCP\EventDispatcher\IEventDispatcher;
44
use OCP\Files\Events\Node\FilesystemTornDownEvent;
45
use OCP\Files\NotFoundException;
46
use OCP\Files\Storage\IStorageFactory;
47
use OCP\IUser;
48
use OCP\IUserManager;
49
50
class Filesystem {
51
52
	/**
53
	 * @var Mount\Manager $mounts
54
	 */
55
	private static $mounts;
56
57
	public static $loaded = false;
58
	/**
59
	 * @var \OC\Files\View $defaultInstance
60
	 */
61
	private static $defaultInstance;
62
63
	private static $usersSetup = [];
64
65
	private static $normalizedPathCache = null;
66
67
	private static $listeningForProviders = false;
0 ignored issues
show
introduced by
The private property $listeningForProviders is not used, and could be removed.
Loading history...
68
69
	/**
70
	 * classname which used for hooks handling
71
	 * used as signalclass in OC_Hooks::emit()
72
	 */
73
	public const CLASSNAME = 'OC_Filesystem';
74
75
	/**
76
	 * signalname emitted before file renaming
77
	 *
78
	 * @param string $oldpath
79
	 * @param string $newpath
80
	 */
81
	public const signal_rename = 'rename';
82
83
	/**
84
	 * signal emitted after file renaming
85
	 *
86
	 * @param string $oldpath
87
	 * @param string $newpath
88
	 */
89
	public const signal_post_rename = 'post_rename';
90
91
	/**
92
	 * signal emitted before file/dir creation
93
	 *
94
	 * @param string $path
95
	 * @param bool $run changing this flag to false in hook handler will cancel event
96
	 */
97
	public const signal_create = 'create';
98
99
	/**
100
	 * signal emitted after file/dir creation
101
	 *
102
	 * @param string $path
103
	 * @param bool $run changing this flag to false in hook handler will cancel event
104
	 */
105
	public const signal_post_create = 'post_create';
106
107
	/**
108
	 * signal emits before file/dir copy
109
	 *
110
	 * @param string $oldpath
111
	 * @param string $newpath
112
	 * @param bool $run changing this flag to false in hook handler will cancel event
113
	 */
114
	public const signal_copy = 'copy';
115
116
	/**
117
	 * signal emits after file/dir copy
118
	 *
119
	 * @param string $oldpath
120
	 * @param string $newpath
121
	 */
122
	public const signal_post_copy = 'post_copy';
123
124
	/**
125
	 * signal emits before file/dir save
126
	 *
127
	 * @param string $path
128
	 * @param bool $run changing this flag to false in hook handler will cancel event
129
	 */
130
	public const signal_write = 'write';
131
132
	/**
133
	 * signal emits after file/dir save
134
	 *
135
	 * @param string $path
136
	 */
137
	public const signal_post_write = 'post_write';
138
139
	/**
140
	 * signal emitted before file/dir update
141
	 *
142
	 * @param string $path
143
	 * @param bool $run changing this flag to false in hook handler will cancel event
144
	 */
145
	public const signal_update = 'update';
146
147
	/**
148
	 * signal emitted after file/dir update
149
	 *
150
	 * @param string $path
151
	 * @param bool $run changing this flag to false in hook handler will cancel event
152
	 */
153
	public const signal_post_update = 'post_update';
154
155
	/**
156
	 * signal emits when reading file/dir
157
	 *
158
	 * @param string $path
159
	 */
160
	public const signal_read = 'read';
161
162
	/**
163
	 * signal emits when removing file/dir
164
	 *
165
	 * @param string $path
166
	 */
167
	public const signal_delete = 'delete';
168
169
	/**
170
	 * parameters definitions for signals
171
	 */
172
	public const signal_param_path = 'path';
173
	public const signal_param_oldpath = 'oldpath';
174
	public const signal_param_newpath = 'newpath';
175
176
	/**
177
	 * run - changing this flag to false in hook handler will cancel event
178
	 */
179
	public const signal_param_run = 'run';
180
181
	public const signal_create_mount = 'create_mount';
182
	public const signal_delete_mount = 'delete_mount';
183
	public const signal_param_mount_type = 'mounttype';
184
	public const signal_param_users = 'users';
185
186
	/**
187
	 * @var \OC\Files\Storage\StorageFactory $loader
188
	 */
189
	private static $loader;
190
191
	/** @var bool */
192
	private static $logWarningWhenAddingStorageWrapper = true;
193
194
	/**
195
	 * @param bool $shouldLog
196
	 * @return bool previous value
197
	 * @internal
198
	 */
199
	public static function logWarningWhenAddingStorageWrapper($shouldLog) {
200
		$previousValue = self::$logWarningWhenAddingStorageWrapper;
201
		self::$logWarningWhenAddingStorageWrapper = (bool) $shouldLog;
202
		return $previousValue;
203
	}
204
205
	/**
206
	 * @param string $wrapperName
207
	 * @param callable $wrapper
208
	 * @param int $priority
209
	 */
210
	public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) {
211
		if (self::$logWarningWhenAddingStorageWrapper) {
212
			\OC::$server->getLogger()->warning("Storage wrapper '{wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.", [
213
				'wrapper' => $wrapperName,
214
				'app' => 'filesystem',
215
			]);
216
		}
217
218
		$mounts = self::getMountManager()->getAll();
219
		if (!self::getLoader()->addStorageWrapper($wrapperName, $wrapper, $priority, $mounts)) {
220
			// do not re-wrap if storage with this name already existed
221
			return;
222
		}
223
	}
224
225
	/**
226
	 * Returns the storage factory
227
	 *
228
	 * @return IStorageFactory
229
	 */
230
	public static function getLoader() {
231
		if (!self::$loader) {
232
			self::$loader = \OC::$server->query(IStorageFactory::class);
233
		}
234
		return self::$loader;
235
	}
236
237
	/**
238
	 * Returns the mount manager
239
	 *
240
	 * @return \OC\Files\Mount\Manager
241
	 */
242
	public static function getMountManager($user = '') {
0 ignored issues
show
Unused Code introduced by
The parameter $user is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

242
	public static function getMountManager(/** @scrutinizer ignore-unused */ $user = '') {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
243
		self::initMountManager();
244
		return self::$mounts;
245
	}
246
247
	/**
248
	 * get the mountpoint of the storage object for a path
249
	 * ( note: because a storage is not always mounted inside the fakeroot, the
250
	 * returned mountpoint is relative to the absolute root of the filesystem
251
	 * and doesn't take the chroot into account )
252
	 *
253
	 * @param string $path
254
	 * @return string
255
	 */
256
	public static function getMountPoint($path) {
257
		if (!self::$mounts) {
258
			\OC_Util::setupFS();
259
		}
260
		$mount = self::$mounts->find($path);
261
		return $mount->getMountPoint();
262
	}
263
264
	/**
265
	 * get a list of all mount points in a directory
266
	 *
267
	 * @param string $path
268
	 * @return string[]
269
	 */
270
	public static function getMountPoints($path) {
271
		if (!self::$mounts) {
272
			\OC_Util::setupFS();
273
		}
274
		$result = [];
275
		$mounts = self::$mounts->findIn($path);
276
		foreach ($mounts as $mount) {
277
			$result[] = $mount->getMountPoint();
278
		}
279
		return $result;
280
	}
281
282
	/**
283
	 * get the storage mounted at $mountPoint
284
	 *
285
	 * @param string $mountPoint
286
	 * @return \OC\Files\Storage\Storage|null
287
	 */
288
	public static function getStorage($mountPoint) {
289
		$mount = self::getMountManager()->find($mountPoint);
290
		return $mount->getStorage();
291
	}
292
293
	/**
294
	 * @param string $id
295
	 * @return Mount\MountPoint[]
296
	 */
297
	public static function getMountByStorageId($id) {
298
		return self::getMountManager()->findByStorageId($id);
299
	}
300
301
	/**
302
	 * @param int $id
303
	 * @return Mount\MountPoint[]
304
	 */
305
	public static function getMountByNumericId($id) {
306
		return self::getMountManager()->findByNumericId($id);
307
	}
308
309
	/**
310
	 * resolve a path to a storage and internal path
311
	 *
312
	 * @param string $path
313
	 * @return array an array consisting of the storage and the internal path
314
	 */
315
	public static function resolvePath($path) {
316
		$mount = self::getMountManager()->find($path);
317
		return [$mount->getStorage(), rtrim($mount->getInternalPath($path), '/')];
318
	}
319
320
	public static function init($user, $root) {
321
		if (self::$defaultInstance) {
322
			return false;
323
		}
324
		self::getLoader();
325
		self::$defaultInstance = new View($root);
326
		/** @var IEventDispatcher $eventDispatcher */
327
		$eventDispatcher = \OC::$server->get(IEventDispatcher::class);
328
		$eventDispatcher->addListener(FilesystemTornDownEvent::class, function () {
329
			self::$defaultInstance = null;
330
			self::$usersSetup = [];
331
			self::$loaded = false;
332
		});
333
334
		if (!self::$mounts) {
335
			self::$mounts = \OC::$server->getMountManager();
336
		}
337
338
		//load custom mount config
339
		self::initMountPoints($user);
340
341
		self::$loaded = true;
342
343
		return true;
344
	}
345
346
	public static function initMountManager() {
347
		if (!self::$mounts) {
348
			self::$mounts = \OC::$server->getMountManager();
349
		}
350
	}
351
352
	/**
353
	 * Initialize system and personal mount points for a user
354
	 *
355
	 * @param string|IUser|null $user
356
	 * @throws \OC\User\NoUserException if the user is not available
357
	 */
358
	public static function initMountPoints($user = '') {
359
		/** @var IUserManager $userManager */
360
		$userManager = \OC::$server->get(IUserManager::class);
361
362
		$userObject = ($user instanceof IUser) ? $user : $userManager->get($user);
363
		if ($userObject) {
364
			/** @var SetupManager $setupManager */
365
			$setupManager = \OC::$server->get(SetupManager::class);
366
			$setupManager->setupForUser($userObject);
367
		} else {
368
			throw new NoUserException();
369
		}
370
	}
371
372
	/**
373
	 * get the default filesystem view
374
	 *
375
	 * @return View
376
	 */
377
	public static function getView() {
378
		return self::$defaultInstance;
379
	}
380
381
	/**
382
	 * tear down the filesystem, removing all storage providers
383
	 */
384
	public static function tearDown() {
385
		\OC_Util::tearDownFS();
386
	}
387
388
	/**
389
	 * get the relative path of the root data directory for the current user
390
	 *
391
	 * @return string
392
	 *
393
	 * Returns path like /admin/files
394
	 */
395
	public static function getRoot() {
396
		if (!self::$defaultInstance) {
397
			return null;
398
		}
399
		return self::$defaultInstance->getRoot();
400
	}
401
402
	/**
403
	 * mount an \OC\Files\Storage\Storage in our virtual filesystem
404
	 *
405
	 * @param \OC\Files\Storage\Storage|string $class
406
	 * @param array $arguments
407
	 * @param string $mountpoint
408
	 */
409
	public static function mount($class, $arguments, $mountpoint) {
410
		if (!self::$mounts) {
411
			\OC_Util::setupFS();
412
		}
413
		$mount = new Mount\MountPoint($class, $mountpoint, $arguments, self::getLoader());
414
		self::$mounts->addMount($mount);
415
	}
416
417
	/**
418
	 * return the path to a local version of the file
419
	 * we need this because we can't know if a file is stored local or not from
420
	 * outside the filestorage and for some purposes a local file is needed
421
	 *
422
	 * @param string $path
423
	 * @return string
424
	 */
425
	public static function getLocalFile($path) {
426
		return self::$defaultInstance->getLocalFile($path);
427
	}
428
429
	/**
430
	 * @param string $path
431
	 * @return string
432
	 */
433
	public static function getLocalFolder($path) {
434
		return self::$defaultInstance->getLocalFolder($path);
435
	}
436
437
	/**
438
	 * return path to file which reflects one visible in browser
439
	 *
440
	 * @param string $path
441
	 * @return string
442
	 */
443
	public static function getLocalPath($path) {
444
		$datadir = \OC_User::getHome(\OC_User::getUser()) . '/files';
445
		$newpath = $path;
446
		if (strncmp($newpath, $datadir, strlen($datadir)) == 0) {
447
			$newpath = substr($path, strlen($datadir));
448
		}
449
		return $newpath;
450
	}
451
452
	/**
453
	 * check if the requested path is valid
454
	 *
455
	 * @param string $path
456
	 * @return bool
457
	 */
458
	public static function isValidPath($path) {
459
		$path = self::normalizePath($path);
460
		if (!$path || $path[0] !== '/') {
461
			$path = '/' . $path;
462
		}
463
		if (strpos($path, '/../') !== false || strrchr($path, '/') === '/..') {
464
			return false;
465
		}
466
		return true;
467
	}
468
469
	/**
470
	 * checks if a file is blacklisted for storage in the filesystem
471
	 * Listens to write and rename hooks
472
	 *
473
	 * @param array $data from hook
474
	 */
475
	public static function isBlacklisted($data) {
476
		if (isset($data['path'])) {
477
			$path = $data['path'];
478
		} elseif (isset($data['newpath'])) {
479
			$path = $data['newpath'];
480
		}
481
		if (isset($path)) {
482
			if (self::isFileBlacklisted($path)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $path does not seem to be defined for all execution paths leading up to this point.
Loading history...
483
				$data['run'] = false;
484
			}
485
		}
486
	}
487
488
	/**
489
	 * @param string $filename
490
	 * @return bool
491
	 */
492
	public static function isFileBlacklisted($filename) {
493
		$filename = self::normalizePath($filename);
494
495
		$blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', ['.htaccess']);
496
		$filename = strtolower(basename($filename));
497
		return in_array($filename, $blacklist);
498
	}
499
500
	/**
501
	 * check if the directory should be ignored when scanning
502
	 * NOTE: the special directories . and .. would cause never ending recursion
503
	 *
504
	 * @param string $dir
505
	 * @return boolean
506
	 */
507
	public static function isIgnoredDir($dir) {
508
		if ($dir === '.' || $dir === '..') {
509
			return true;
510
		}
511
		return false;
512
	}
513
514
	/**
515
	 * following functions are equivalent to their php builtin equivalents for arguments/return values.
516
	 */
517
	public static function mkdir($path) {
518
		return self::$defaultInstance->mkdir($path);
519
	}
520
521
	public static function rmdir($path) {
522
		return self::$defaultInstance->rmdir($path);
523
	}
524
525
	public static function is_dir($path) {
526
		return self::$defaultInstance->is_dir($path);
527
	}
528
529
	public static function is_file($path) {
530
		return self::$defaultInstance->is_file($path);
531
	}
532
533
	public static function stat($path) {
534
		return self::$defaultInstance->stat($path);
535
	}
536
537
	public static function filetype($path) {
538
		return self::$defaultInstance->filetype($path);
539
	}
540
541
	public static function filesize($path) {
542
		return self::$defaultInstance->filesize($path);
543
	}
544
545
	public static function readfile($path) {
546
		return self::$defaultInstance->readfile($path);
547
	}
548
549
	public static function isCreatable($path) {
550
		return self::$defaultInstance->isCreatable($path);
551
	}
552
553
	public static function isReadable($path) {
554
		return self::$defaultInstance->isReadable($path);
555
	}
556
557
	public static function isUpdatable($path) {
558
		return self::$defaultInstance->isUpdatable($path);
559
	}
560
561
	public static function isDeletable($path) {
562
		return self::$defaultInstance->isDeletable($path);
563
	}
564
565
	public static function isSharable($path) {
566
		return self::$defaultInstance->isSharable($path);
567
	}
568
569
	public static function file_exists($path) {
570
		return self::$defaultInstance->file_exists($path);
571
	}
572
573
	public static function filemtime($path) {
574
		return self::$defaultInstance->filemtime($path);
575
	}
576
577
	public static function touch($path, $mtime = null) {
578
		return self::$defaultInstance->touch($path, $mtime);
579
	}
580
581
	/**
582
	 * @return string
583
	 */
584
	public static function file_get_contents($path) {
585
		return self::$defaultInstance->file_get_contents($path);
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::defaultInst...ile_get_contents($path) also could return the type boolean which is incompatible with the documented return type string.
Loading history...
586
	}
587
588
	public static function file_put_contents($path, $data) {
589
		return self::$defaultInstance->file_put_contents($path, $data);
590
	}
591
592
	public static function unlink($path) {
593
		return self::$defaultInstance->unlink($path);
594
	}
595
596
	public static function rename($path1, $path2) {
597
		return self::$defaultInstance->rename($path1, $path2);
598
	}
599
600
	public static function copy($path1, $path2) {
601
		return self::$defaultInstance->copy($path1, $path2);
602
	}
603
604
	public static function fopen($path, $mode) {
605
		return self::$defaultInstance->fopen($path, $mode);
606
	}
607
608
	/**
609
	 * @return string
610
	 */
611
	public static function toTmpFile($path) {
612
		return self::$defaultInstance->toTmpFile($path);
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::defaultInstance->toTmpFile($path) returns the type false which is incompatible with the documented return type string.
Loading history...
613
	}
614
615
	public static function fromTmpFile($tmpFile, $path) {
616
		return self::$defaultInstance->fromTmpFile($tmpFile, $path);
617
	}
618
619
	public static function getMimeType($path) {
620
		return self::$defaultInstance->getMimeType($path);
621
	}
622
623
	public static function hash($type, $path, $raw = false) {
624
		return self::$defaultInstance->hash($type, $path, $raw);
625
	}
626
627
	public static function free_space($path = '/') {
628
		return self::$defaultInstance->free_space($path);
629
	}
630
631
	public static function search($query) {
632
		return self::$defaultInstance->search($query);
633
	}
634
635
	/**
636
	 * @param string $query
637
	 */
638
	public static function searchByMime($query) {
639
		return self::$defaultInstance->searchByMime($query);
640
	}
641
642
	/**
643
	 * @param string|int $tag name or tag id
644
	 * @param string $userId owner of the tags
645
	 * @return FileInfo[] array or file info
646
	 */
647
	public static function searchByTag($tag, $userId) {
648
		return self::$defaultInstance->searchByTag($tag, $userId);
649
	}
650
651
	/**
652
	 * check if a file or folder has been updated since $time
653
	 *
654
	 * @param string $path
655
	 * @param int $time
656
	 * @return bool
657
	 */
658
	public static function hasUpdated($path, $time) {
659
		return self::$defaultInstance->hasUpdated($path, $time);
660
	}
661
662
	/**
663
	 * Fix common problems with a file path
664
	 *
665
	 * @param string $path
666
	 * @param bool $stripTrailingSlash whether to strip the trailing slash
667
	 * @param bool $isAbsolutePath whether the given path is absolute
668
	 * @param bool $keepUnicode true to disable unicode normalization
669
	 * @return string
670
	 */
671
	public static function normalizePath($path, $stripTrailingSlash = true, $isAbsolutePath = false, $keepUnicode = false) {
672
		/**
673
		 * FIXME: This is a workaround for existing classes and files which call
674
		 *        this function with another type than a valid string. This
675
		 *        conversion should get removed as soon as all existing
676
		 *        function calls have been fixed.
677
		 */
678
		$path = (string)$path;
679
680
		if ($path === '') {
681
			return '/';
682
		}
683
684
		if (is_null(self::$normalizedPathCache)) {
685
			self::$normalizedPathCache = new CappedMemoryCache(2048);
686
		}
687
688
		$cacheKey = json_encode([$path, $stripTrailingSlash, $isAbsolutePath, $keepUnicode]);
689
690
		if ($cacheKey && isset(self::$normalizedPathCache[$cacheKey])) {
691
			return self::$normalizedPathCache[$cacheKey];
692
		}
693
694
		//normalize unicode if possible
695
		if (!$keepUnicode) {
696
			$path = \OC_Util::normalizeUnicode($path);
697
		}
698
699
		//add leading slash, if it is already there we strip it anyway
700
		$path = '/' . $path;
701
702
		$patterns = [
703
			'#\\\\#s',       // no windows style '\\' slashes
704
			'#/\.(/\.)*/#s', // remove '/./'
705
			'#\//+#s',       // remove sequence of slashes
706
			'#/\.$#s',       // remove trailing '/.'
707
		];
708
709
		do {
710
			$count = 0;
711
			$path = preg_replace($patterns, '/', $path, -1, $count);
712
		} while ($count > 0);
713
714
		//remove trailing slash
715
		if ($stripTrailingSlash && strlen($path) > 1) {
716
			$path = rtrim($path, '/');
717
		}
718
719
		self::$normalizedPathCache[$cacheKey] = $path;
720
721
		return $path;
722
	}
723
724
	/**
725
	 * get the filesystem info
726
	 *
727
	 * @param string $path
728
	 * @param boolean $includeMountPoints whether to add mountpoint sizes,
729
	 * defaults to true
730
	 * @return \OC\Files\FileInfo|false False if file does not exist
731
	 */
732
	public static function getFileInfo($path, $includeMountPoints = true) {
733
		return self::$defaultInstance->getFileInfo($path, $includeMountPoints);
734
	}
735
736
	/**
737
	 * change file metadata
738
	 *
739
	 * @param string $path
740
	 * @param array $data
741
	 * @return int
742
	 *
743
	 * returns the fileid of the updated file
744
	 */
745
	public static function putFileInfo($path, $data) {
746
		return self::$defaultInstance->putFileInfo($path, $data);
747
	}
748
749
	/**
750
	 * get the content of a directory
751
	 *
752
	 * @param string $directory path under datadirectory
753
	 * @param string $mimetype_filter limit returned content to this mimetype or mimepart
754
	 * @return \OC\Files\FileInfo[]
755
	 */
756
	public static function getDirectoryContent($directory, $mimetype_filter = '') {
757
		return self::$defaultInstance->getDirectoryContent($directory, $mimetype_filter);
758
	}
759
760
	/**
761
	 * Get the path of a file by id
762
	 *
763
	 * Note that the resulting path is not guaranteed to be unique for the id, multiple paths can point to the same file
764
	 *
765
	 * @param int $id
766
	 * @throws NotFoundException
767
	 * @return string
768
	 */
769
	public static function getPath($id) {
770
		return self::$defaultInstance->getPath($id);
771
	}
772
773
	/**
774
	 * Get the owner for a file or folder
775
	 *
776
	 * @param string $path
777
	 * @return string
778
	 */
779
	public static function getOwner($path) {
780
		return self::$defaultInstance->getOwner($path);
781
	}
782
783
	/**
784
	 * get the ETag for a file or folder
785
	 *
786
	 * @param string $path
787
	 * @return string
788
	 */
789
	public static function getETag($path) {
790
		return self::$defaultInstance->getETag($path);
791
	}
792
}
793