Passed
Push — master ( 71a626...183e2e )
by Joas
21:12 queued 10:11
created

Filesystem::initMountPoints()   C

Complexity

Conditions 12
Paths 28

Size

Total Lines 73
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 42
nc 28
nop 1
dl 0
loc 73
rs 6.9666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 Lukas Reschke <[email protected]>
13
 * @author Michael Gapczynski <[email protected]>
14
 * @author Morris Jobke <[email protected]>
15
 * @author Robin Appelman <[email protected]>
16
 * @author Robin McCorkell <[email protected]>
17
 * @author Roeland Jago Douma <[email protected]>
18
 * @author Sam Tuke <[email protected]>
19
 * @author Stephan Peijnik <[email protected]>
20
 * @author Vincent Petry <[email protected]>
21
 *
22
 * @license AGPL-3.0
23
 *
24
 * This code is free software: you can redistribute it and/or modify
25
 * it under the terms of the GNU Affero General Public License, version 3,
26
 * as published by the Free Software Foundation.
27
 *
28
 * This program is distributed in the hope that it will be useful,
29
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31
 * GNU Affero General Public License for more details.
32
 *
33
 * You should have received a copy of the GNU Affero General Public License, version 3,
34
 * along with this program. If not, see <http://www.gnu.org/licenses/>
35
 *
36
 */
37
38
/**
39
 * Class for abstraction of filesystem functions
40
 * This class won't call any filesystem functions for itself but will pass them to the correct OC_Filestorage object
41
 * this class should also handle all the file permission related stuff
42
 *
43
 * Hooks provided:
44
 *   read(path)
45
 *   write(path, &run)
46
 *   post_write(path)
47
 *   create(path, &run) (when a file is created, both create and write will be emitted in that order)
48
 *   post_create(path)
49
 *   delete(path, &run)
50
 *   post_delete(path)
51
 *   rename(oldpath,newpath, &run)
52
 *   post_rename(oldpath,newpath)
53
 *   copy(oldpath,newpath, &run) (if the newpath doesn't exists yes, copy, create and write will be emitted in that order)
54
 *   post_rename(oldpath,newpath)
55
 *   post_initMountPoints(user, user_dir)
56
 *
57
 *   the &run parameter can be set to false to prevent the operation from occurring
58
 */
59
60
namespace OC\Files;
61
62
use OC\Cache\CappedMemoryCache;
63
use OC\Files\Config\MountProviderCollection;
64
use OC\Files\Mount\MountPoint;
65
use OC\Lockdown\Filesystem\NullStorage;
66
use OCP\Files\Config\IMountProvider;
67
use OCP\Files\NotFoundException;
68
use OCP\Files\Storage\IStorageFactory;
69
use OCP\ILogger;
70
use OCP\IUserManager;
71
72
class Filesystem {
73
74
	/**
75
	 * @var Mount\Manager $mounts
76
	 */
77
	private static $mounts;
78
79
	public static $loaded = false;
80
	/**
81
	 * @var \OC\Files\View $defaultInstance
82
	 */
83
	private static $defaultInstance;
84
85
	private static $usersSetup = [];
86
87
	private static $normalizedPathCache = null;
88
89
	private static $listeningForProviders = false;
90
91
	/**
92
	 * classname which used for hooks handling
93
	 * used as signalclass in OC_Hooks::emit()
94
	 */
95
	public const CLASSNAME = 'OC_Filesystem';
96
97
	/**
98
	 * signalname emitted before file renaming
99
	 *
100
	 * @param string $oldpath
101
	 * @param string $newpath
102
	 */
103
	public const signal_rename = 'rename';
104
105
	/**
106
	 * signal emitted after file renaming
107
	 *
108
	 * @param string $oldpath
109
	 * @param string $newpath
110
	 */
111
	public const signal_post_rename = 'post_rename';
112
113
	/**
114
	 * signal emitted before file/dir creation
115
	 *
116
	 * @param string $path
117
	 * @param bool $run changing this flag to false in hook handler will cancel event
118
	 */
119
	public const signal_create = 'create';
120
121
	/**
122
	 * signal emitted after file/dir creation
123
	 *
124
	 * @param string $path
125
	 * @param bool $run changing this flag to false in hook handler will cancel event
126
	 */
127
	public const signal_post_create = 'post_create';
128
129
	/**
130
	 * signal emits before file/dir copy
131
	 *
132
	 * @param string $oldpath
133
	 * @param string $newpath
134
	 * @param bool $run changing this flag to false in hook handler will cancel event
135
	 */
136
	public const signal_copy = 'copy';
137
138
	/**
139
	 * signal emits after file/dir copy
140
	 *
141
	 * @param string $oldpath
142
	 * @param string $newpath
143
	 */
144
	public const signal_post_copy = 'post_copy';
145
146
	/**
147
	 * signal emits before file/dir save
148
	 *
149
	 * @param string $path
150
	 * @param bool $run changing this flag to false in hook handler will cancel event
151
	 */
152
	public const signal_write = 'write';
153
154
	/**
155
	 * signal emits after file/dir save
156
	 *
157
	 * @param string $path
158
	 */
159
	public const signal_post_write = 'post_write';
160
161
	/**
162
	 * signal emitted before file/dir update
163
	 *
164
	 * @param string $path
165
	 * @param bool $run changing this flag to false in hook handler will cancel event
166
	 */
167
	public const signal_update = 'update';
168
169
	/**
170
	 * signal emitted after file/dir update
171
	 *
172
	 * @param string $path
173
	 * @param bool $run changing this flag to false in hook handler will cancel event
174
	 */
175
	public const signal_post_update = 'post_update';
176
177
	/**
178
	 * signal emits when reading file/dir
179
	 *
180
	 * @param string $path
181
	 */
182
	public const signal_read = 'read';
183
184
	/**
185
	 * signal emits when removing file/dir
186
	 *
187
	 * @param string $path
188
	 */
189
	public const signal_delete = 'delete';
190
191
	/**
192
	 * parameters definitions for signals
193
	 */
194
	public const signal_param_path = 'path';
195
	public const signal_param_oldpath = 'oldpath';
196
	public const signal_param_newpath = 'newpath';
197
198
	/**
199
	 * run - changing this flag to false in hook handler will cancel event
200
	 */
201
	public const signal_param_run = 'run';
202
203
	public const signal_create_mount = 'create_mount';
204
	public const signal_delete_mount = 'delete_mount';
205
	public const signal_param_mount_type = 'mounttype';
206
	public const signal_param_users = 'users';
207
208
	/**
209
	 * @var \OC\Files\Storage\StorageFactory $loader
210
	 */
211
	private static $loader;
212
213
	/** @var bool */
214
	private static $logWarningWhenAddingStorageWrapper = true;
215
216
	/**
217
	 * @param bool $shouldLog
218
	 * @return bool previous value
219
	 * @internal
220
	 */
221
	public static function logWarningWhenAddingStorageWrapper($shouldLog) {
222
		$previousValue = self::$logWarningWhenAddingStorageWrapper;
223
		self::$logWarningWhenAddingStorageWrapper = (bool) $shouldLog;
224
		return $previousValue;
225
	}
226
227
	/**
228
	 * @param string $wrapperName
229
	 * @param callable $wrapper
230
	 * @param int $priority
231
	 */
232
	public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) {
233
		if (self::$logWarningWhenAddingStorageWrapper) {
234
			\OC::$server->getLogger()->warning("Storage wrapper '{wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.", [
235
				'wrapper' => $wrapperName,
236
				'app' => 'filesystem',
237
			]);
238
		}
239
240
		$mounts = self::getMountManager()->getAll();
241
		if (!self::getLoader()->addStorageWrapper($wrapperName, $wrapper, $priority, $mounts)) {
242
			// do not re-wrap if storage with this name already existed
243
			return;
244
		}
245
	}
246
247
	/**
248
	 * Returns the storage factory
249
	 *
250
	 * @return IStorageFactory
251
	 */
252
	public static function getLoader() {
253
		if (!self::$loader) {
254
			self::$loader = \OC::$server->query(IStorageFactory::class);
255
		}
256
		return self::$loader;
257
	}
258
259
	/**
260
	 * Returns the mount manager
261
	 *
262
	 * @return \OC\Files\Mount\Manager
263
	 */
264
	public static function getMountManager($user = '') {
265
		if (!self::$mounts) {
266
			\OC_Util::setupFS($user);
267
		}
268
		return self::$mounts;
269
	}
270
271
	/**
272
	 * get the mountpoint of the storage object for a path
273
	 * ( note: because a storage is not always mounted inside the fakeroot, the
274
	 * returned mountpoint is relative to the absolute root of the filesystem
275
	 * and doesn't take the chroot into account )
276
	 *
277
	 * @param string $path
278
	 * @return string
279
	 */
280
	public static function getMountPoint($path) {
281
		if (!self::$mounts) {
282
			\OC_Util::setupFS();
283
		}
284
		$mount = self::$mounts->find($path);
285
		if ($mount) {
286
			return $mount->getMountPoint();
287
		} else {
288
			return '';
289
		}
290
	}
291
292
	/**
293
	 * get a list of all mount points in a directory
294
	 *
295
	 * @param string $path
296
	 * @return string[]
297
	 */
298
	public static function getMountPoints($path) {
299
		if (!self::$mounts) {
300
			\OC_Util::setupFS();
301
		}
302
		$result = [];
303
		$mounts = self::$mounts->findIn($path);
304
		foreach ($mounts as $mount) {
305
			$result[] = $mount->getMountPoint();
306
		}
307
		return $result;
308
	}
309
310
	/**
311
	 * get the storage mounted at $mountPoint
312
	 *
313
	 * @param string $mountPoint
314
	 * @return \OC\Files\Storage\Storage
315
	 */
316
	public static function getStorage($mountPoint) {
317
		if (!self::$mounts) {
318
			\OC_Util::setupFS();
319
		}
320
		$mount = self::$mounts->find($mountPoint);
321
		return $mount->getStorage();
322
	}
323
324
	/**
325
	 * @param string $id
326
	 * @return Mount\MountPoint[]
327
	 */
328
	public static function getMountByStorageId($id) {
329
		if (!self::$mounts) {
330
			\OC_Util::setupFS();
331
		}
332
		return self::$mounts->findByStorageId($id);
333
	}
334
335
	/**
336
	 * @param int $id
337
	 * @return Mount\MountPoint[]
338
	 */
339
	public static function getMountByNumericId($id) {
340
		if (!self::$mounts) {
341
			\OC_Util::setupFS();
342
		}
343
		return self::$mounts->findByNumericId($id);
344
	}
345
346
	/**
347
	 * resolve a path to a storage and internal path
348
	 *
349
	 * @param string $path
350
	 * @return array an array consisting of the storage and the internal path
351
	 */
352
	public static function resolvePath($path) {
353
		if (!self::$mounts) {
354
			\OC_Util::setupFS();
355
		}
356
		$mount = self::$mounts->find($path);
357
		if ($mount) {
358
			return [$mount->getStorage(), rtrim($mount->getInternalPath($path), '/')];
359
		} else {
360
			return [null, null];
361
		}
362
	}
363
364
	public static function init($user, $root) {
365
		if (self::$defaultInstance) {
366
			return false;
367
		}
368
		self::getLoader();
369
		self::$defaultInstance = new View($root);
370
371
		if (!self::$mounts) {
372
			self::$mounts = \OC::$server->getMountManager();
373
		}
374
375
		//load custom mount config
376
		self::initMountPoints($user);
377
378
		self::$loaded = true;
379
380
		return true;
381
	}
382
383
	public static function initMountManager() {
384
		if (!self::$mounts) {
385
			self::$mounts = \OC::$server->getMountManager();
386
		}
387
	}
388
389
	/**
390
	 * Initialize system and personal mount points for a user
391
	 *
392
	 * @param string $user
393
	 * @throws \OC\User\NoUserException if the user is not available
394
	 */
395
	public static function initMountPoints($user = '') {
396
		if ($user == '') {
397
			$user = \OC_User::getUser();
398
		}
399
		if ($user === null || $user === false || $user === '') {
400
			throw new \OC\User\NoUserException('Attempted to initialize mount points for null user and no user in session');
401
		}
402
403
		if (isset(self::$usersSetup[$user])) {
404
			return;
405
		}
406
407
		self::$usersSetup[$user] = true;
408
409
		$userManager = \OC::$server->getUserManager();
410
		$userObject = $userManager->get($user);
411
412
		if (is_null($userObject)) {
413
			\OCP\Util::writeLog('files', ' Backends provided no user object for ' . $user, ILogger::ERROR);
0 ignored issues
show
Deprecated Code introduced by
The function OCP\Util::writeLog() has been deprecated: 13.0.0 use log of \OCP\ILogger ( Ignorable by Annotation )

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

413
			/** @scrutinizer ignore-deprecated */ \OCP\Util::writeLog('files', ' Backends provided no user object for ' . $user, ILogger::ERROR);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
Bug introduced by
Are you sure $user of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

413
			\OCP\Util::writeLog('files', ' Backends provided no user object for ' . /** @scrutinizer ignore-type */ $user, ILogger::ERROR);
Loading history...
414
			// reset flag, this will make it possible to rethrow the exception if called again
415
			unset(self::$usersSetup[$user]);
416
			throw new \OC\User\NoUserException('Backends provided no user object for ' . $user);
417
		}
418
419
		$realUid = $userObject->getUID();
420
		// workaround in case of different casings
421
		if ($user !== $realUid) {
422
			$stack = json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 50));
423
			\OCP\Util::writeLog('files', 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "' . $realUid . '" got "' . $user . '". Stack: ' . $stack, ILogger::WARN);
0 ignored issues
show
Deprecated Code introduced by
The function OCP\Util::writeLog() has been deprecated: 13.0.0 use log of \OCP\ILogger ( Ignorable by Annotation )

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

423
			/** @scrutinizer ignore-deprecated */ \OCP\Util::writeLog('files', 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "' . $realUid . '" got "' . $user . '". Stack: ' . $stack, ILogger::WARN);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
424
			$user = $realUid;
425
426
			// again with the correct casing
427
			if (isset(self::$usersSetup[$user])) {
428
				return;
429
			}
430
431
			self::$usersSetup[$user] = true;
432
		}
433
434
		if (\OC::$server->getLockdownManager()->canAccessFilesystem()) {
435
			/** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */
436
			$mountConfigManager = \OC::$server->getMountProviderCollection();
437
438
			// home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers
439
			$homeMount = $mountConfigManager->getHomeMountForUser($userObject);
440
			if ($homeMount->getStorageRootId() === -1) {
441
				$homeMount->getStorage()->mkdir('');
442
				$homeMount->getStorage()->getScanner()->scan('');
443
			}
444
445
			self::getMountManager()->addMount($homeMount);
446
447
			\OC\Files\Filesystem::getStorage($user);
448
449
			// Chance to mount for other storages
450
			if ($userObject) {
0 ignored issues
show
introduced by
$userObject is of type OC\User\User, thus it always evaluated to true.
Loading history...
451
				$mounts = $mountConfigManager->addMountForUser($userObject, self::getMountManager());
452
				$mounts[] = $homeMount;
453
				$mountConfigManager->registerMounts($userObject, $mounts);
454
			}
455
456
			self::listenForNewMountProviders($mountConfigManager, $userManager);
457
		} else {
458
			self::getMountManager()->addMount(new MountPoint(
459
				new NullStorage([]),
460
				'/' . $user
461
			));
462
			self::getMountManager()->addMount(new MountPoint(
463
				new NullStorage([]),
464
				'/' . $user . '/files'
465
			));
466
		}
467
		\OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user]);
468
	}
469
470
	/**
471
	 * Get mounts from mount providers that are registered after setup
472
	 *
473
	 * @param MountProviderCollection $mountConfigManager
474
	 * @param IUserManager $userManager
475
	 */
476
	private static function listenForNewMountProviders(MountProviderCollection $mountConfigManager, IUserManager $userManager) {
477
		if (!self::$listeningForProviders) {
478
			self::$listeningForProviders = true;
479
			$mountConfigManager->listen('\OC\Files\Config', 'registerMountProvider', function (IMountProvider $provider) use ($userManager) {
480
				foreach (Filesystem::$usersSetup as $user => $setup) {
481
					$userObject = $userManager->get($user);
482
					if ($userObject) {
483
						$mounts = $provider->getMountsForUser($userObject, Filesystem::getLoader());
484
						array_walk($mounts, [self::$mounts, 'addMount']);
485
					}
486
				}
487
			});
488
		}
489
	}
490
491
	/**
492
	 * get the default filesystem view
493
	 *
494
	 * @return View
495
	 */
496
	public static function getView() {
497
		return self::$defaultInstance;
498
	}
499
500
	/**
501
	 * tear down the filesystem, removing all storage providers
502
	 */
503
	public static function tearDown() {
504
		self::clearMounts();
505
		self::$defaultInstance = null;
506
	}
507
508
	/**
509
	 * get the relative path of the root data directory for the current user
510
	 *
511
	 * @return string
512
	 *
513
	 * Returns path like /admin/files
514
	 */
515
	public static function getRoot() {
516
		if (!self::$defaultInstance) {
517
			return null;
518
		}
519
		return self::$defaultInstance->getRoot();
520
	}
521
522
	/**
523
	 * clear all mounts and storage backends
524
	 */
525
	public static function clearMounts() {
526
		if (self::$mounts) {
527
			self::$usersSetup = [];
528
			self::$mounts->clear();
529
		}
530
	}
531
532
	/**
533
	 * mount an \OC\Files\Storage\Storage in our virtual filesystem
534
	 *
535
	 * @param \OC\Files\Storage\Storage|string $class
536
	 * @param array $arguments
537
	 * @param string $mountpoint
538
	 */
539
	public static function mount($class, $arguments, $mountpoint) {
540
		if (!self::$mounts) {
541
			\OC_Util::setupFS();
542
		}
543
		$mount = new Mount\MountPoint($class, $mountpoint, $arguments, self::getLoader());
544
		self::$mounts->addMount($mount);
545
	}
546
547
	/**
548
	 * return the path to a local version of the file
549
	 * we need this because we can't know if a file is stored local or not from
550
	 * outside the filestorage and for some purposes a local file is needed
551
	 *
552
	 * @param string $path
553
	 * @return string
554
	 */
555
	public static function getLocalFile($path) {
556
		return self::$defaultInstance->getLocalFile($path);
557
	}
558
559
	/**
560
	 * @param string $path
561
	 * @return string
562
	 */
563
	public static function getLocalFolder($path) {
564
		return self::$defaultInstance->getLocalFolder($path);
565
	}
566
567
	/**
568
	 * return path to file which reflects one visible in browser
569
	 *
570
	 * @param string $path
571
	 * @return string
572
	 */
573
	public static function getLocalPath($path) {
574
		$datadir = \OC_User::getHome(\OC_User::getUser()) . '/files';
0 ignored issues
show
Deprecated Code introduced by
The function OC_User::getHome() has been deprecated: Use \OC::$server->getUserManager->getHome() ( Ignorable by Annotation )

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

574
		$datadir = /** @scrutinizer ignore-deprecated */ \OC_User::getHome(\OC_User::getUser()) . '/files';

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
575
		$newpath = $path;
576
		if (strncmp($newpath, $datadir, strlen($datadir)) == 0) {
577
			$newpath = substr($path, strlen($datadir));
578
		}
579
		return $newpath;
580
	}
581
582
	/**
583
	 * check if the requested path is valid
584
	 *
585
	 * @param string $path
586
	 * @return bool
587
	 */
588
	public static function isValidPath($path) {
589
		$path = self::normalizePath($path);
590
		if (!$path || $path[0] !== '/') {
591
			$path = '/' . $path;
592
		}
593
		if (strpos($path, '/../') !== false || strrchr($path, '/') === '/..') {
594
			return false;
595
		}
596
		return true;
597
	}
598
599
	/**
600
	 * checks if a file is blacklisted for storage in the filesystem
601
	 * Listens to write and rename hooks
602
	 *
603
	 * @param array $data from hook
604
	 */
605
	public static function isBlacklisted($data) {
606
		if (isset($data['path'])) {
607
			$path = $data['path'];
608
		} elseif (isset($data['newpath'])) {
609
			$path = $data['newpath'];
610
		}
611
		if (isset($path)) {
612
			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...
613
				$data['run'] = false;
614
			}
615
		}
616
	}
617
618
	/**
619
	 * @param string $filename
620
	 * @return bool
621
	 */
622
	public static function isFileBlacklisted($filename) {
623
		$filename = self::normalizePath($filename);
624
625
		$blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', ['.htaccess']);
626
		$filename = strtolower(basename($filename));
627
		return in_array($filename, $blacklist);
628
	}
629
630
	/**
631
	 * check if the directory should be ignored when scanning
632
	 * NOTE: the special directories . and .. would cause never ending recursion
633
	 *
634
	 * @param string $dir
635
	 * @return boolean
636
	 */
637
	public static function isIgnoredDir($dir) {
638
		if ($dir === '.' || $dir === '..') {
639
			return true;
640
		}
641
		return false;
642
	}
643
644
	/**
645
	 * following functions are equivalent to their php builtin equivalents for arguments/return values.
646
	 */
647
	public static function mkdir($path) {
648
		return self::$defaultInstance->mkdir($path);
649
	}
650
651
	public static function rmdir($path) {
652
		return self::$defaultInstance->rmdir($path);
653
	}
654
655
	public static function is_dir($path) {
656
		return self::$defaultInstance->is_dir($path);
657
	}
658
659
	public static function is_file($path) {
660
		return self::$defaultInstance->is_file($path);
661
	}
662
663
	public static function stat($path) {
664
		return self::$defaultInstance->stat($path);
665
	}
666
667
	public static function filetype($path) {
668
		return self::$defaultInstance->filetype($path);
669
	}
670
671
	public static function filesize($path) {
672
		return self::$defaultInstance->filesize($path);
673
	}
674
675
	public static function readfile($path) {
676
		return self::$defaultInstance->readfile($path);
677
	}
678
679
	public static function isCreatable($path) {
680
		return self::$defaultInstance->isCreatable($path);
681
	}
682
683
	public static function isReadable($path) {
684
		return self::$defaultInstance->isReadable($path);
685
	}
686
687
	public static function isUpdatable($path) {
688
		return self::$defaultInstance->isUpdatable($path);
689
	}
690
691
	public static function isDeletable($path) {
692
		return self::$defaultInstance->isDeletable($path);
693
	}
694
695
	public static function isSharable($path) {
696
		return self::$defaultInstance->isSharable($path);
697
	}
698
699
	public static function file_exists($path) {
700
		return self::$defaultInstance->file_exists($path);
701
	}
702
703
	public static function filemtime($path) {
704
		return self::$defaultInstance->filemtime($path);
705
	}
706
707
	public static function touch($path, $mtime = null) {
708
		return self::$defaultInstance->touch($path, $mtime);
709
	}
710
711
	/**
712
	 * @return string
713
	 */
714
	public static function file_get_contents($path) {
715
		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) could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
716
	}
717
718
	public static function file_put_contents($path, $data) {
719
		return self::$defaultInstance->file_put_contents($path, $data);
720
	}
721
722
	public static function unlink($path) {
723
		return self::$defaultInstance->unlink($path);
724
	}
725
726
	public static function rename($path1, $path2) {
727
		return self::$defaultInstance->rename($path1, $path2);
728
	}
729
730
	public static function copy($path1, $path2) {
731
		return self::$defaultInstance->copy($path1, $path2);
732
	}
733
734
	public static function fopen($path, $mode) {
735
		return self::$defaultInstance->fopen($path, $mode);
736
	}
737
738
	/**
739
	 * @return string
740
	 */
741
	public static function toTmpFile($path) {
742
		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...
743
	}
744
745
	public static function fromTmpFile($tmpFile, $path) {
746
		return self::$defaultInstance->fromTmpFile($tmpFile, $path);
747
	}
748
749
	public static function getMimeType($path) {
750
		return self::$defaultInstance->getMimeType($path);
751
	}
752
753
	public static function hash($type, $path, $raw = false) {
754
		return self::$defaultInstance->hash($type, $path, $raw);
755
	}
756
757
	public static function free_space($path = '/') {
758
		return self::$defaultInstance->free_space($path);
759
	}
760
761
	public static function search($query) {
762
		return self::$defaultInstance->search($query);
763
	}
764
765
	/**
766
	 * @param string $query
767
	 */
768
	public static function searchByMime($query) {
769
		return self::$defaultInstance->searchByMime($query);
770
	}
771
772
	/**
773
	 * @param string|int $tag name or tag id
774
	 * @param string $userId owner of the tags
775
	 * @return FileInfo[] array or file info
776
	 */
777
	public static function searchByTag($tag, $userId) {
778
		return self::$defaultInstance->searchByTag($tag, $userId);
779
	}
780
781
	/**
782
	 * check if a file or folder has been updated since $time
783
	 *
784
	 * @param string $path
785
	 * @param int $time
786
	 * @return bool
787
	 */
788
	public static function hasUpdated($path, $time) {
789
		return self::$defaultInstance->hasUpdated($path, $time);
790
	}
791
792
	/**
793
	 * Fix common problems with a file path
794
	 *
795
	 * @param string $path
796
	 * @param bool $stripTrailingSlash whether to strip the trailing slash
797
	 * @param bool $isAbsolutePath whether the given path is absolute
798
	 * @param bool $keepUnicode true to disable unicode normalization
799
	 * @return string
800
	 */
801
	public static function normalizePath($path, $stripTrailingSlash = true, $isAbsolutePath = false, $keepUnicode = false) {
802
		if (is_null(self::$normalizedPathCache)) {
803
			self::$normalizedPathCache = new CappedMemoryCache(2048);
804
		}
805
806
		/**
807
		 * FIXME: This is a workaround for existing classes and files which call
808
		 *        this function with another type than a valid string. This
809
		 *        conversion should get removed as soon as all existing
810
		 *        function calls have been fixed.
811
		 */
812
		$path = (string)$path;
813
814
		$cacheKey = json_encode([$path, $stripTrailingSlash, $isAbsolutePath, $keepUnicode]);
815
816
		if (isset(self::$normalizedPathCache[$cacheKey])) {
817
			return self::$normalizedPathCache[$cacheKey];
818
		}
819
820
		if ($path === '') {
821
			return '/';
822
		}
823
824
		//normalize unicode if possible
825
		if (!$keepUnicode) {
826
			$path = \OC_Util::normalizeUnicode($path);
827
		}
828
829
		//add leading slash, if it is already there we strip it anyway
830
		$path = '/' . $path;
831
832
		$patterns = [
833
			'/\\\\/s',          // no windows style slashes
834
			'/\/\.(\/\.)?\//s', // remove '/./'
835
			'/\/{2,}/s',        // remove sequence of slashes
836
			'/\/\.$/s',         // remove trailing /.
837
		];
838
839
		do {
840
			$count = 0;
841
			$path = preg_replace($patterns, '/', $path, -1, $count);
842
		} while ($count > 0);
843
844
		//remove trailing slash
845
		if ($stripTrailingSlash && strlen($path) > 1) {
846
			$path = rtrim($path, '/');
847
		}
848
849
		self::$normalizedPathCache[$cacheKey] = $path;
850
851
		return $path;
852
	}
853
854
	/**
855
	 * get the filesystem info
856
	 *
857
	 * @param string $path
858
	 * @param boolean $includeMountPoints whether to add mountpoint sizes,
859
	 * defaults to true
860
	 * @return \OC\Files\FileInfo|bool False if file does not exist
861
	 */
862
	public static function getFileInfo($path, $includeMountPoints = true) {
863
		return self::$defaultInstance->getFileInfo($path, $includeMountPoints);
864
	}
865
866
	/**
867
	 * change file metadata
868
	 *
869
	 * @param string $path
870
	 * @param array $data
871
	 * @return int
872
	 *
873
	 * returns the fileid of the updated file
874
	 */
875
	public static function putFileInfo($path, $data) {
876
		return self::$defaultInstance->putFileInfo($path, $data);
877
	}
878
879
	/**
880
	 * get the content of a directory
881
	 *
882
	 * @param string $directory path under datadirectory
883
	 * @param string $mimetype_filter limit returned content to this mimetype or mimepart
884
	 * @return \OC\Files\FileInfo[]
885
	 */
886
	public static function getDirectoryContent($directory, $mimetype_filter = '') {
887
		return self::$defaultInstance->getDirectoryContent($directory, $mimetype_filter);
888
	}
889
890
	/**
891
	 * Get the path of a file by id
892
	 *
893
	 * Note that the resulting path is not guaranteed to be unique for the id, multiple paths can point to the same file
894
	 *
895
	 * @param int $id
896
	 * @throws NotFoundException
897
	 * @return string
898
	 */
899
	public static function getPath($id) {
900
		return self::$defaultInstance->getPath($id);
901
	}
902
903
	/**
904
	 * Get the owner for a file or folder
905
	 *
906
	 * @param string $path
907
	 * @return string
908
	 */
909
	public static function getOwner($path) {
910
		return self::$defaultInstance->getOwner($path);
911
	}
912
913
	/**
914
	 * get the ETag for a file or folder
915
	 *
916
	 * @param string $path
917
	 * @return string
918
	 */
919
	public static function getETag($path) {
920
		return self::$defaultInstance->getETag($path);
921
	}
922
}
923