You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Filesystem.php 20KB

11 vuotta sitten
8 vuotta sitten
8 vuotta sitten
8 vuotta sitten
8 vuotta sitten
8 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
11 vuotta sitten
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. * @author Bart Visscher <bartv@thisnet.nl>
  7. * @author Christopher Schäpers <kondou@ts.unde.re>
  8. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  9. * @author Florin Peter <github@florin-peter.de>
  10. * @author Joas Schilling <coding@schilljs.com>
  11. * @author Jörn Friedrich Dreyer <jfd@butonic.de>
  12. * @author korelstar <korelstar@users.noreply.github.com>
  13. * @author Lukas Reschke <lukas@statuscode.ch>
  14. * @author Michael Gapczynski <GapczynskiM@gmail.com>
  15. * @author Morris Jobke <hey@morrisjobke.de>
  16. * @author Robin Appelman <robin@icewind.nl>
  17. * @author Robin McCorkell <robin@mccorkell.me.uk>
  18. * @author Roeland Jago Douma <roeland@famdouma.nl>
  19. * @author Sam Tuke <mail@samtuke.com>
  20. * @author Stephan Peijnik <speijnik@anexia-it.com>
  21. * @author Vincent Petry <vincent@nextcloud.com>
  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. use OCP\Cache\CappedMemoryCache;
  40. use OC\Files\Mount\MountPoint;
  41. use OC\User\NoUserException;
  42. use OCP\EventDispatcher\IEventDispatcher;
  43. use OCP\Files\Events\Node\FilesystemTornDownEvent;
  44. use OCP\Files\NotFoundException;
  45. use OCP\Files\Storage\IStorageFactory;
  46. use OCP\IUser;
  47. use OCP\IUserManager;
  48. use OCP\IUserSession;
  49. class Filesystem {
  50. /**
  51. * @var Mount\Manager $mounts
  52. */
  53. private static $mounts;
  54. public static $loaded = false;
  55. /**
  56. * @var \OC\Files\View $defaultInstance
  57. */
  58. private static $defaultInstance;
  59. private static $usersSetup = [];
  60. private static $normalizedPathCache = null;
  61. private static $listeningForProviders = false;
  62. /** @var string[]|null */
  63. private static $blacklist = null;
  64. /**
  65. * classname which used for hooks handling
  66. * used as signalclass in OC_Hooks::emit()
  67. */
  68. public const CLASSNAME = 'OC_Filesystem';
  69. /**
  70. * signalname emitted before file renaming
  71. *
  72. * @param string $oldpath
  73. * @param string $newpath
  74. */
  75. public const signal_rename = 'rename';
  76. /**
  77. * signal emitted after file renaming
  78. *
  79. * @param string $oldpath
  80. * @param string $newpath
  81. */
  82. public const signal_post_rename = 'post_rename';
  83. /**
  84. * signal emitted before file/dir creation
  85. *
  86. * @param string $path
  87. * @param bool $run changing this flag to false in hook handler will cancel event
  88. */
  89. public const signal_create = 'create';
  90. /**
  91. * signal emitted after file/dir creation
  92. *
  93. * @param string $path
  94. * @param bool $run changing this flag to false in hook handler will cancel event
  95. */
  96. public const signal_post_create = 'post_create';
  97. /**
  98. * signal emits before file/dir copy
  99. *
  100. * @param string $oldpath
  101. * @param string $newpath
  102. * @param bool $run changing this flag to false in hook handler will cancel event
  103. */
  104. public const signal_copy = 'copy';
  105. /**
  106. * signal emits after file/dir copy
  107. *
  108. * @param string $oldpath
  109. * @param string $newpath
  110. */
  111. public const signal_post_copy = 'post_copy';
  112. /**
  113. * signal emits before file/dir save
  114. *
  115. * @param string $path
  116. * @param bool $run changing this flag to false in hook handler will cancel event
  117. */
  118. public const signal_write = 'write';
  119. /**
  120. * signal emits after file/dir save
  121. *
  122. * @param string $path
  123. */
  124. public const signal_post_write = 'post_write';
  125. /**
  126. * signal emitted before file/dir update
  127. *
  128. * @param string $path
  129. * @param bool $run changing this flag to false in hook handler will cancel event
  130. */
  131. public const signal_update = 'update';
  132. /**
  133. * signal emitted after file/dir update
  134. *
  135. * @param string $path
  136. * @param bool $run changing this flag to false in hook handler will cancel event
  137. */
  138. public const signal_post_update = 'post_update';
  139. /**
  140. * signal emits when reading file/dir
  141. *
  142. * @param string $path
  143. */
  144. public const signal_read = 'read';
  145. /**
  146. * signal emits when removing file/dir
  147. *
  148. * @param string $path
  149. */
  150. public const signal_delete = 'delete';
  151. /**
  152. * parameters definitions for signals
  153. */
  154. public const signal_param_path = 'path';
  155. public const signal_param_oldpath = 'oldpath';
  156. public const signal_param_newpath = 'newpath';
  157. /**
  158. * run - changing this flag to false in hook handler will cancel event
  159. */
  160. public const signal_param_run = 'run';
  161. public const signal_create_mount = 'create_mount';
  162. public const signal_delete_mount = 'delete_mount';
  163. public const signal_param_mount_type = 'mounttype';
  164. public const signal_param_users = 'users';
  165. /**
  166. * @var \OC\Files\Storage\StorageFactory $loader
  167. */
  168. private static $loader;
  169. /** @var bool */
  170. private static $logWarningWhenAddingStorageWrapper = true;
  171. /**
  172. * @param bool $shouldLog
  173. * @return bool previous value
  174. * @internal
  175. */
  176. public static function logWarningWhenAddingStorageWrapper($shouldLog) {
  177. $previousValue = self::$logWarningWhenAddingStorageWrapper;
  178. self::$logWarningWhenAddingStorageWrapper = (bool) $shouldLog;
  179. return $previousValue;
  180. }
  181. /**
  182. * @param string $wrapperName
  183. * @param callable $wrapper
  184. * @param int $priority
  185. */
  186. public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) {
  187. if (self::$logWarningWhenAddingStorageWrapper) {
  188. \OC::$server->getLogger()->warning("Storage wrapper '{wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.", [
  189. 'wrapper' => $wrapperName,
  190. 'app' => 'filesystem',
  191. ]);
  192. }
  193. $mounts = self::getMountManager()->getAll();
  194. if (!self::getLoader()->addStorageWrapper($wrapperName, $wrapper, $priority, $mounts)) {
  195. // do not re-wrap if storage with this name already existed
  196. return;
  197. }
  198. }
  199. /**
  200. * Returns the storage factory
  201. *
  202. * @return IStorageFactory
  203. */
  204. public static function getLoader() {
  205. if (!self::$loader) {
  206. self::$loader = \OC::$server->query(IStorageFactory::class);
  207. }
  208. return self::$loader;
  209. }
  210. /**
  211. * Returns the mount manager
  212. *
  213. * @return \OC\Files\Mount\Manager
  214. */
  215. public static function getMountManager($user = '') {
  216. self::initMountManager();
  217. return self::$mounts;
  218. }
  219. /**
  220. * get the mountpoint of the storage object for a path
  221. * ( note: because a storage is not always mounted inside the fakeroot, the
  222. * returned mountpoint is relative to the absolute root of the filesystem
  223. * and doesn't take the chroot into account )
  224. *
  225. * @param string $path
  226. * @return string
  227. */
  228. public static function getMountPoint($path) {
  229. if (!self::$mounts) {
  230. \OC_Util::setupFS();
  231. }
  232. $mount = self::$mounts->find($path);
  233. return $mount->getMountPoint();
  234. }
  235. /**
  236. * get a list of all mount points in a directory
  237. *
  238. * @param string $path
  239. * @return string[]
  240. */
  241. public static function getMountPoints($path) {
  242. if (!self::$mounts) {
  243. \OC_Util::setupFS();
  244. }
  245. $result = [];
  246. $mounts = self::$mounts->findIn($path);
  247. foreach ($mounts as $mount) {
  248. $result[] = $mount->getMountPoint();
  249. }
  250. return $result;
  251. }
  252. /**
  253. * get the storage mounted at $mountPoint
  254. *
  255. * @param string $mountPoint
  256. * @return \OC\Files\Storage\Storage|null
  257. */
  258. public static function getStorage($mountPoint) {
  259. $mount = self::getMountManager()->find($mountPoint);
  260. return $mount->getStorage();
  261. }
  262. /**
  263. * @param string $id
  264. * @return Mount\MountPoint[]
  265. */
  266. public static function getMountByStorageId($id) {
  267. return self::getMountManager()->findByStorageId($id);
  268. }
  269. /**
  270. * @param int $id
  271. * @return Mount\MountPoint[]
  272. */
  273. public static function getMountByNumericId($id) {
  274. return self::getMountManager()->findByNumericId($id);
  275. }
  276. /**
  277. * resolve a path to a storage and internal path
  278. *
  279. * @param string $path
  280. * @return array an array consisting of the storage and the internal path
  281. */
  282. public static function resolvePath($path) {
  283. $mount = self::getMountManager()->find($path);
  284. return [$mount->getStorage(), rtrim($mount->getInternalPath($path), '/')];
  285. }
  286. public static function init($user, $root) {
  287. if (self::$defaultInstance) {
  288. return false;
  289. }
  290. self::initInternal($root);
  291. //load custom mount config
  292. self::initMountPoints($user);
  293. return true;
  294. }
  295. public static function initInternal($root) {
  296. if (self::$defaultInstance) {
  297. return false;
  298. }
  299. self::getLoader();
  300. self::$defaultInstance = new View($root);
  301. /** @var IEventDispatcher $eventDispatcher */
  302. $eventDispatcher = \OC::$server->get(IEventDispatcher::class);
  303. $eventDispatcher->addListener(FilesystemTornDownEvent::class, function () {
  304. self::$defaultInstance = null;
  305. self::$usersSetup = [];
  306. self::$loaded = false;
  307. });
  308. if (!self::$mounts) {
  309. self::$mounts = \OC::$server->getMountManager();
  310. }
  311. self::$loaded = true;
  312. return true;
  313. }
  314. public static function initMountManager() {
  315. if (!self::$mounts) {
  316. self::$mounts = \OC::$server->getMountManager();
  317. }
  318. }
  319. /**
  320. * Initialize system and personal mount points for a user
  321. *
  322. * @param string|IUser|null $user
  323. * @throws \OC\User\NoUserException if the user is not available
  324. */
  325. public static function initMountPoints($user = '') {
  326. /** @var IUserManager $userManager */
  327. $userManager = \OC::$server->get(IUserManager::class);
  328. $userObject = ($user instanceof IUser) ? $user : $userManager->get($user);
  329. if ($userObject) {
  330. /** @var SetupManager $setupManager */
  331. $setupManager = \OC::$server->get(SetupManager::class);
  332. $setupManager->setupForUser($userObject);
  333. } else {
  334. throw new NoUserException();
  335. }
  336. }
  337. /**
  338. * get the default filesystem view
  339. *
  340. * @return View
  341. */
  342. public static function getView() {
  343. if (!self::$defaultInstance) {
  344. /** @var IUserSession $session */
  345. $session = \OC::$server->get(IUserSession::class);
  346. $user = $session->getUser();
  347. if ($user) {
  348. $userDir = '/' . $user->getUID() . '/files';
  349. self::initInternal($userDir);
  350. }
  351. }
  352. return self::$defaultInstance;
  353. }
  354. /**
  355. * tear down the filesystem, removing all storage providers
  356. */
  357. public static function tearDown() {
  358. \OC_Util::tearDownFS();
  359. }
  360. /**
  361. * get the relative path of the root data directory for the current user
  362. *
  363. * @return string
  364. *
  365. * Returns path like /admin/files
  366. */
  367. public static function getRoot() {
  368. if (!self::$defaultInstance) {
  369. return null;
  370. }
  371. return self::$defaultInstance->getRoot();
  372. }
  373. /**
  374. * mount an \OC\Files\Storage\Storage in our virtual filesystem
  375. *
  376. * @param \OC\Files\Storage\Storage|string $class
  377. * @param array $arguments
  378. * @param string $mountpoint
  379. */
  380. public static function mount($class, $arguments, $mountpoint) {
  381. if (!self::$mounts) {
  382. \OC_Util::setupFS();
  383. }
  384. $mount = new Mount\MountPoint($class, $mountpoint, $arguments, self::getLoader());
  385. self::$mounts->addMount($mount);
  386. }
  387. /**
  388. * return the path to a local version of the file
  389. * we need this because we can't know if a file is stored local or not from
  390. * outside the filestorage and for some purposes a local file is needed
  391. *
  392. * @param string $path
  393. * @return string
  394. */
  395. public static function getLocalFile($path) {
  396. return self::$defaultInstance->getLocalFile($path);
  397. }
  398. /**
  399. * @param string $path
  400. * @return string
  401. */
  402. public static function getLocalFolder($path) {
  403. return self::$defaultInstance->getLocalFolder($path);
  404. }
  405. /**
  406. * return path to file which reflects one visible in browser
  407. *
  408. * @param string $path
  409. * @return string
  410. */
  411. public static function getLocalPath($path) {
  412. $datadir = \OC_User::getHome(\OC_User::getUser()) . '/files';
  413. $newpath = $path;
  414. if (strncmp($newpath, $datadir, strlen($datadir)) == 0) {
  415. $newpath = substr($path, strlen($datadir));
  416. }
  417. return $newpath;
  418. }
  419. /**
  420. * check if the requested path is valid
  421. *
  422. * @param string $path
  423. * @return bool
  424. */
  425. public static function isValidPath($path) {
  426. $path = self::normalizePath($path);
  427. if (!$path || $path[0] !== '/') {
  428. $path = '/' . $path;
  429. }
  430. if (strpos($path, '/../') !== false || strrchr($path, '/') === '/..') {
  431. return false;
  432. }
  433. return true;
  434. }
  435. /**
  436. * @param string $filename
  437. * @return bool
  438. */
  439. public static function isFileBlacklisted($filename) {
  440. $filename = self::normalizePath($filename);
  441. if (self::$blacklist === null) {
  442. self::$blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', ['.htaccess']);
  443. }
  444. $filename = strtolower(basename($filename));
  445. return in_array($filename, self::$blacklist);
  446. }
  447. /**
  448. * check if the directory should be ignored when scanning
  449. * NOTE: the special directories . and .. would cause never ending recursion
  450. *
  451. * @param string $dir
  452. * @return boolean
  453. */
  454. public static function isIgnoredDir($dir) {
  455. if ($dir === '.' || $dir === '..') {
  456. return true;
  457. }
  458. return false;
  459. }
  460. /**
  461. * following functions are equivalent to their php builtin equivalents for arguments/return values.
  462. */
  463. public static function mkdir($path) {
  464. return self::$defaultInstance->mkdir($path);
  465. }
  466. public static function rmdir($path) {
  467. return self::$defaultInstance->rmdir($path);
  468. }
  469. public static function is_dir($path) {
  470. return self::$defaultInstance->is_dir($path);
  471. }
  472. public static function is_file($path) {
  473. return self::$defaultInstance->is_file($path);
  474. }
  475. public static function stat($path) {
  476. return self::$defaultInstance->stat($path);
  477. }
  478. public static function filetype($path) {
  479. return self::$defaultInstance->filetype($path);
  480. }
  481. public static function filesize($path) {
  482. return self::$defaultInstance->filesize($path);
  483. }
  484. public static function readfile($path) {
  485. return self::$defaultInstance->readfile($path);
  486. }
  487. public static function isCreatable($path) {
  488. return self::$defaultInstance->isCreatable($path);
  489. }
  490. public static function isReadable($path) {
  491. return self::$defaultInstance->isReadable($path);
  492. }
  493. public static function isUpdatable($path) {
  494. return self::$defaultInstance->isUpdatable($path);
  495. }
  496. public static function isDeletable($path) {
  497. return self::$defaultInstance->isDeletable($path);
  498. }
  499. public static function isSharable($path) {
  500. return self::$defaultInstance->isSharable($path);
  501. }
  502. public static function file_exists($path) {
  503. return self::$defaultInstance->file_exists($path);
  504. }
  505. public static function filemtime($path) {
  506. return self::$defaultInstance->filemtime($path);
  507. }
  508. public static function touch($path, $mtime = null) {
  509. return self::$defaultInstance->touch($path, $mtime);
  510. }
  511. /**
  512. * @return string
  513. */
  514. public static function file_get_contents($path) {
  515. return self::$defaultInstance->file_get_contents($path);
  516. }
  517. public static function file_put_contents($path, $data) {
  518. return self::$defaultInstance->file_put_contents($path, $data);
  519. }
  520. public static function unlink($path) {
  521. return self::$defaultInstance->unlink($path);
  522. }
  523. public static function rename($path1, $path2) {
  524. return self::$defaultInstance->rename($path1, $path2);
  525. }
  526. public static function copy($path1, $path2) {
  527. return self::$defaultInstance->copy($path1, $path2);
  528. }
  529. public static function fopen($path, $mode) {
  530. return self::$defaultInstance->fopen($path, $mode);
  531. }
  532. /**
  533. * @return string
  534. */
  535. public static function toTmpFile($path) {
  536. return self::$defaultInstance->toTmpFile($path);
  537. }
  538. public static function fromTmpFile($tmpFile, $path) {
  539. return self::$defaultInstance->fromTmpFile($tmpFile, $path);
  540. }
  541. public static function getMimeType($path) {
  542. return self::$defaultInstance->getMimeType($path);
  543. }
  544. public static function hash($type, $path, $raw = false) {
  545. return self::$defaultInstance->hash($type, $path, $raw);
  546. }
  547. public static function free_space($path = '/') {
  548. return self::$defaultInstance->free_space($path);
  549. }
  550. public static function search($query) {
  551. return self::$defaultInstance->search($query);
  552. }
  553. /**
  554. * @param string $query
  555. */
  556. public static function searchByMime($query) {
  557. return self::$defaultInstance->searchByMime($query);
  558. }
  559. /**
  560. * @param string|int $tag name or tag id
  561. * @param string $userId owner of the tags
  562. * @return FileInfo[] array or file info
  563. */
  564. public static function searchByTag($tag, $userId) {
  565. return self::$defaultInstance->searchByTag($tag, $userId);
  566. }
  567. /**
  568. * check if a file or folder has been updated since $time
  569. *
  570. * @param string $path
  571. * @param int $time
  572. * @return bool
  573. */
  574. public static function hasUpdated($path, $time) {
  575. return self::$defaultInstance->hasUpdated($path, $time);
  576. }
  577. /**
  578. * Fix common problems with a file path
  579. *
  580. * @param string $path
  581. * @param bool $stripTrailingSlash whether to strip the trailing slash
  582. * @param bool $isAbsolutePath whether the given path is absolute
  583. * @param bool $keepUnicode true to disable unicode normalization
  584. * @return string
  585. */
  586. public static function normalizePath($path, $stripTrailingSlash = true, $isAbsolutePath = false, $keepUnicode = false) {
  587. /**
  588. * FIXME: This is a workaround for existing classes and files which call
  589. * this function with another type than a valid string. This
  590. * conversion should get removed as soon as all existing
  591. * function calls have been fixed.
  592. */
  593. $path = (string)$path;
  594. if ($path === '') {
  595. return '/';
  596. }
  597. if (is_null(self::$normalizedPathCache)) {
  598. self::$normalizedPathCache = new CappedMemoryCache(2048);
  599. }
  600. $cacheKey = json_encode([$path, $stripTrailingSlash, $isAbsolutePath, $keepUnicode]);
  601. if ($cacheKey && isset(self::$normalizedPathCache[$cacheKey])) {
  602. return self::$normalizedPathCache[$cacheKey];
  603. }
  604. //normalize unicode if possible
  605. if (!$keepUnicode) {
  606. $path = \OC_Util::normalizeUnicode($path);
  607. }
  608. //add leading slash, if it is already there we strip it anyway
  609. $path = '/' . $path;
  610. $patterns = [
  611. '#\\\\#s', // no windows style '\\' slashes
  612. '#/\.(/\.)*/#s', // remove '/./'
  613. '#\//+#s', // remove sequence of slashes
  614. '#/\.$#s', // remove trailing '/.'
  615. ];
  616. do {
  617. $count = 0;
  618. $path = preg_replace($patterns, '/', $path, -1, $count);
  619. } while ($count > 0);
  620. //remove trailing slash
  621. if ($stripTrailingSlash && strlen($path) > 1) {
  622. $path = rtrim($path, '/');
  623. }
  624. self::$normalizedPathCache[$cacheKey] = $path;
  625. return $path;
  626. }
  627. /**
  628. * get the filesystem info
  629. *
  630. * @param string $path
  631. * @param boolean $includeMountPoints whether to add mountpoint sizes,
  632. * defaults to true
  633. * @return \OC\Files\FileInfo|false False if file does not exist
  634. */
  635. public static function getFileInfo($path, $includeMountPoints = true) {
  636. return self::getView()->getFileInfo($path, $includeMountPoints);
  637. }
  638. /**
  639. * change file metadata
  640. *
  641. * @param string $path
  642. * @param array $data
  643. * @return int
  644. *
  645. * returns the fileid of the updated file
  646. */
  647. public static function putFileInfo($path, $data) {
  648. return self::$defaultInstance->putFileInfo($path, $data);
  649. }
  650. /**
  651. * get the content of a directory
  652. *
  653. * @param string $directory path under datadirectory
  654. * @param string $mimetype_filter limit returned content to this mimetype or mimepart
  655. * @return \OC\Files\FileInfo[]
  656. */
  657. public static function getDirectoryContent($directory, $mimetype_filter = '') {
  658. return self::$defaultInstance->getDirectoryContent($directory, $mimetype_filter);
  659. }
  660. /**
  661. * Get the path of a file by id
  662. *
  663. * Note that the resulting path is not guaranteed to be unique for the id, multiple paths can point to the same file
  664. *
  665. * @param int $id
  666. * @throws NotFoundException
  667. * @return string
  668. */
  669. public static function getPath($id) {
  670. return self::$defaultInstance->getPath($id);
  671. }
  672. /**
  673. * Get the owner for a file or folder
  674. *
  675. * @param string $path
  676. * @return string
  677. */
  678. public static function getOwner($path) {
  679. return self::$defaultInstance->getOwner($path);
  680. }
  681. /**
  682. * get the ETag for a file or folder
  683. *
  684. * @param string $path
  685. * @return string
  686. */
  687. public static function getETag($path) {
  688. return self::$defaultInstance->getETag($path);
  689. }
  690. }