2012-10-10 13:54:44 +04:00
< ? php
/**
2016-07-21 18:07:57 +03:00
* @ copyright Copyright ( c ) 2016 , ownCloud , Inc .
*
2016-05-26 20:56:05 +03:00
* @ author Arthur Schiwon < blizzz @ arthur - schiwon . de >
2015-03-26 13:44:34 +03:00
* @ author Bart Visscher < bartv @ thisnet . nl >
* @ author Christopher Schäpers < kondou @ ts . unde . re >
2019-12-03 21:57:53 +03:00
* @ author Christoph Wurst < christoph @ winzerhof - wurst . at >
2015-03-26 13:44:34 +03:00
* @ author Florin Peter < github @ florin - peter . de >
2016-07-21 18:07:57 +03:00
* @ author Joas Schilling < coding @ schilljs . com >
2015-03-26 13:44:34 +03:00
* @ author Jörn Friedrich Dreyer < jfd @ butonic . de >
2020-09-07 15:37:44 +03:00
* @ author korelstar < korelstar @ users . noreply . github . com >
2016-05-26 20:56:05 +03:00
* @ author Lukas Reschke < lukas @ statuscode . ch >
2015-03-26 13:44:34 +03:00
* @ author Michael Gapczynski < GapczynskiM @ gmail . com >
* @ author Morris Jobke < hey @ morrisjobke . de >
2016-07-21 19:13:36 +03:00
* @ author Robin Appelman < robin @ icewind . nl >
2016-01-12 17:02:16 +03:00
* @ author Robin McCorkell < robin @ mccorkell . me . uk >
2016-07-21 18:07:57 +03:00
* @ author Roeland Jago Douma < roeland @ famdouma . nl >
2015-03-26 13:44:34 +03:00
* @ author Sam Tuke < mail @ samtuke . com >
* @ author Stephan Peijnik < speijnik @ anexia - it . com >
* @ author Vincent Petry < pvince81 @ owncloud . com >
*
* @ license AGPL - 3.0
*
* This code is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License , version 3 ,
* as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License , version 3 ,
2019-12-03 21:57:53 +03:00
* along with this program . If not , see < http :// www . gnu . org / licenses />
2015-03-26 13:44:34 +03:00
*
2015-02-26 13:37:37 +03:00
*/
/**
* Class for abstraction of filesystem functions
* This class won ' t call any filesystem functions for itself but will pass them to the correct OC_Filestorage object
* this class should also handle all the file permission related stuff
2015-02-23 13:28:53 +03:00
*
2015-02-26 13:37:37 +03:00
* Hooks provided :
* read ( path )
* write ( path , & run )
* post_write ( path )
* create ( path , & run ) ( when a file is created , both create and write will be emitted in that order )
* post_create ( path )
* delete ( path , & run )
* post_delete ( path )
* rename ( oldpath , newpath , & run )
* post_rename ( oldpath , newpath )
* copy ( oldpath , newpath , & run ) ( if the newpath doesn ' t exists yes , copy , create and write will be emitted in that order )
* post_rename ( oldpath , newpath )
* post_initMountPoints ( user , user_dir )
2012-10-10 13:54:44 +04:00
*
2015-02-26 13:37:37 +03:00
* the & run parameter can be set to false to prevent the operation from occurring
2012-10-10 13:54:44 +04:00
*/
2015-02-26 13:37:37 +03:00
2012-10-10 13:54:44 +04:00
namespace OC\Files ;
2016-04-29 14:17:41 +03:00
use OC\Cache\CappedMemoryCache ;
2015-05-07 15:07:02 +03:00
use OC\Files\Config\MountProviderCollection ;
2015-11-26 19:47:53 +03:00
use OC\Files\Mount\MountPoint ;
2016-08-01 19:27:07 +03:00
use OC\Lockdown\Filesystem\NullStorage ;
2015-05-07 15:07:02 +03:00
use OCP\Files\Config\IMountProvider ;
2015-06-15 15:10:10 +03:00
use OCP\Files\NotFoundException ;
2018-09-19 20:02:15 +03:00
use OCP\Files\Storage\IStorageFactory ;
2018-04-25 16:22:28 +03:00
use OCP\ILogger ;
2015-05-07 15:07:02 +03:00
use OCP\IUserManager ;
2013-02-16 06:27:50 +04:00
2012-10-10 13:54:44 +04:00
class Filesystem {
2014-07-11 12:36:28 +04:00
2013-04-26 02:01:36 +04:00
/**
* @ var Mount\Manager $mounts
*/
private static $mounts ;
2012-10-10 13:54:44 +04:00
public static $loaded = false ;
/**
2012-10-10 14:25:46 +04:00
* @ var \OC\Files\View $defaultInstance
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:48:31 +03:00
private static $defaultInstance ;
2012-10-10 13:54:44 +04:00
2020-04-10 17:48:31 +03:00
private static $usersSetup = [];
2012-10-10 13:54:44 +04:00
2020-04-10 17:48:31 +03:00
private static $normalizedPathCache = null ;
2015-01-10 12:48:28 +03:00
2020-04-10 17:48:31 +03:00
private static $listeningForProviders = false ;
2015-05-07 15:07:02 +03:00
2012-10-10 13:54:44 +04:00
/**
* classname which used for hooks handling
* used as signalclass in OC_Hooks :: emit ()
*/
2020-04-10 17:54:27 +03:00
public const CLASSNAME = 'OC_Filesystem' ;
2012-10-10 13:54:44 +04:00
/**
2012-10-10 14:25:46 +04:00
* signalname emitted before file renaming
2012-10-10 13:54:44 +04:00
*
2012-10-10 14:25:46 +04:00
* @ param string $oldpath
* @ param string $newpath
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:54:27 +03:00
public const signal_rename = 'rename' ;
2012-10-10 13:54:44 +04:00
/**
2012-10-10 14:25:46 +04:00
* signal emitted after file renaming
2012-10-10 13:54:44 +04:00
*
2012-10-10 14:25:46 +04:00
* @ param string $oldpath
* @ param string $newpath
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:54:27 +03:00
public const signal_post_rename = 'post_rename' ;
2012-10-10 13:54:44 +04:00
/**
2012-10-10 14:25:46 +04:00
* signal emitted before file / dir creation
2012-10-10 13:54:44 +04:00
*
2012-10-10 14:25:46 +04:00
* @ param string $path
* @ param bool $run changing this flag to false in hook handler will cancel event
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:54:27 +03:00
public const signal_create = 'create' ;
2012-10-10 13:54:44 +04:00
/**
2012-10-10 14:25:46 +04:00
* signal emitted after file / dir creation
2012-10-10 13:54:44 +04:00
*
2012-10-10 14:25:46 +04:00
* @ param string $path
* @ param bool $run changing this flag to false in hook handler will cancel event
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:54:27 +03:00
public const signal_post_create = 'post_create' ;
2012-10-10 13:54:44 +04:00
/**
* signal emits before file / dir copy
*
2012-10-10 14:25:46 +04:00
* @ param string $oldpath
* @ param string $newpath
* @ param bool $run changing this flag to false in hook handler will cancel event
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:54:27 +03:00
public const signal_copy = 'copy' ;
2012-10-10 13:54:44 +04:00
/**
* signal emits after file / dir copy
*
2012-10-10 14:25:46 +04:00
* @ param string $oldpath
* @ param string $newpath
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:54:27 +03:00
public const signal_post_copy = 'post_copy' ;
2012-10-10 13:54:44 +04:00
/**
* signal emits before file / dir save
*
2012-10-10 14:25:46 +04:00
* @ param string $path
* @ param bool $run changing this flag to false in hook handler will cancel event
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:54:27 +03:00
public const signal_write = 'write' ;
2012-10-10 13:54:44 +04:00
/**
* signal emits after file / dir save
*
2012-10-10 14:25:46 +04:00
* @ param string $path
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:54:27 +03:00
public const signal_post_write = 'post_write' ;
2012-10-10 13:54:44 +04:00
2014-04-09 18:42:10 +04:00
/**
* signal emitted before file / dir update
*
* @ param string $path
* @ param bool $run changing this flag to false in hook handler will cancel event
*/
2020-04-10 17:54:27 +03:00
public const signal_update = 'update' ;
2014-04-09 18:42:10 +04:00
/**
* signal emitted after file / dir update
*
* @ param string $path
* @ param bool $run changing this flag to false in hook handler will cancel event
*/
2020-04-10 17:54:27 +03:00
public const signal_post_update = 'post_update' ;
2014-04-09 18:42:10 +04:00
2012-10-10 13:54:44 +04:00
/**
* signal emits when reading file / dir
*
2012-10-10 14:25:46 +04:00
* @ param string $path
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:54:27 +03:00
public const signal_read = 'read' ;
2012-10-10 13:54:44 +04:00
/**
* signal emits when removing file / dir
*
2012-10-10 14:25:46 +04:00
* @ param string $path
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:54:27 +03:00
public const signal_delete = 'delete' ;
2012-10-10 13:54:44 +04:00
/**
* parameters definitions for signals
*/
2020-04-10 17:54:27 +03:00
public const signal_param_path = 'path' ;
public const signal_param_oldpath = 'oldpath' ;
public const signal_param_newpath = 'newpath' ;
2012-10-10 13:54:44 +04:00
/**
* run - changing this flag to false in hook handler will cancel event
*/
2020-04-10 17:54:27 +03:00
public const signal_param_run = 'run' ;
2012-10-10 13:54:44 +04:00
2020-04-10 17:54:27 +03:00
public const signal_create_mount = 'create_mount' ;
public const signal_delete_mount = 'delete_mount' ;
public const signal_param_mount_type = 'mounttype' ;
public const signal_param_users = 'users' ;
2014-09-26 14:51:25 +04:00
2013-06-07 19:07:13 +04:00
/**
2014-11-24 17:54:42 +03:00
* @ var \OC\Files\Storage\StorageFactory $loader
2013-06-07 19:07:13 +04:00
*/
2013-06-07 19:50:10 +04:00
private static $loader ;
2016-04-29 10:08:40 +03:00
/** @var bool */
private static $logWarningWhenAddingStorageWrapper = true ;
/**
* @ param bool $shouldLog
2016-11-02 12:22:36 +03:00
* @ return bool previous value
2016-04-29 10:08:40 +03:00
* @ internal
*/
public static function logWarningWhenAddingStorageWrapper ( $shouldLog ) {
2016-11-02 12:22:36 +03:00
$previousValue = self :: $logWarningWhenAddingStorageWrapper ;
self :: $logWarningWhenAddingStorageWrapper = ( bool ) $shouldLog ;
return $previousValue ;
2016-04-29 10:08:40 +03:00
}
2013-07-25 18:01:05 +04:00
/**
2015-03-26 21:24:49 +03:00
* @ param string $wrapperName
2013-07-25 18:01:05 +04:00
* @ param callable $wrapper
2015-03-26 21:24:49 +03:00
* @ param int $priority
2013-07-25 18:01:05 +04:00
*/
2015-03-26 21:24:49 +03:00
public static function addStorageWrapper ( $wrapperName , $wrapper , $priority = 50 ) {
2016-11-14 18:13:05 +03:00
if ( self :: $logWarningWhenAddingStorageWrapper ) {
2016-04-29 10:08:40 +03:00
\OC :: $server -> getLogger () -> warning ( " Storage wrapper ' { wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems. " , [
'wrapper' => $wrapperName ,
'app' => 'filesystem' ,
]);
}
2015-01-23 15:48:35 +03:00
$mounts = self :: getMountManager () -> getAll ();
2015-03-26 21:24:49 +03:00
if ( ! self :: getLoader () -> addStorageWrapper ( $wrapperName , $wrapper , $priority , $mounts )) {
2015-01-22 00:27:59 +03:00
// do not re-wrap if storage with this name already existed
return ;
}
2013-07-25 18:01:05 +04:00
}
2015-01-21 23:54:43 +03:00
/**
* Returns the storage factory
*
2018-09-19 20:02:15 +03:00
* @ return IStorageFactory
2015-01-21 23:54:43 +03:00
*/
2013-07-19 18:33:00 +04:00
public static function getLoader () {
2013-06-07 19:50:10 +04:00
if ( ! self :: $loader ) {
2018-09-19 20:02:15 +03:00
self :: $loader = \OC :: $server -> query ( IStorageFactory :: class );
2013-06-07 19:50:10 +04:00
}
return self :: $loader ;
}
2013-06-07 19:07:13 +04:00
2015-01-21 23:54:43 +03:00
/**
* Returns the mount manager
*
2015-01-23 15:48:35 +03:00
* @ return \OC\Files\Mount\Manager
2015-01-21 23:54:43 +03:00
*/
2016-02-18 11:21:32 +03:00
public static function getMountManager ( $user = '' ) {
2013-07-19 18:33:00 +04:00
if ( ! self :: $mounts ) {
2016-02-18 11:21:32 +03:00
\OC_Util :: setupFS ( $user );
2013-07-19 18:33:00 +04:00
}
return self :: $mounts ;
}
2012-10-10 13:54:44 +04:00
/**
* get the mountpoint of the storage object for a path
2013-02-11 20:44:02 +04:00
* ( note : because a storage is not always mounted inside the fakeroot , the
* returned mountpoint is relative to the absolute root of the filesystem
* and doesn ' t take the chroot into account )
2012-10-10 13:54:44 +04:00
*
2012-10-10 14:25:46 +04:00
* @ param string $path
2012-10-10 13:54:44 +04:00
* @ return string
*/
2020-04-10 17:51:06 +03:00
public static function getMountPoint ( $path ) {
2013-06-03 00:09:44 +04:00
if ( ! self :: $mounts ) {
\OC_Util :: setupFS ();
}
2013-04-26 02:01:36 +04:00
$mount = self :: $mounts -> find ( $path );
2013-01-27 00:42:59 +04:00
if ( $mount ) {
return $mount -> getMountPoint ();
} else {
return '' ;
2012-10-10 13:54:44 +04:00
}
}
2012-10-21 04:12:58 +04:00
/**
* get a list of all mount points in a directory
*
* @ param string $path
* @ return string []
*/
2020-04-10 17:51:06 +03:00
public static function getMountPoints ( $path ) {
2013-06-03 00:09:44 +04:00
if ( ! self :: $mounts ) {
\OC_Util :: setupFS ();
}
2020-03-26 11:30:18 +03:00
$result = [];
2013-04-26 02:01:36 +04:00
$mounts = self :: $mounts -> findIn ( $path );
2013-01-27 00:42:59 +04:00
foreach ( $mounts as $mount ) {
$result [] = $mount -> getMountPoint ();
2012-10-21 04:12:58 +04:00
}
return $result ;
}
/**
* get the storage mounted at $mountPoint
*
* @ param string $mountPoint
* @ return \OC\Files\Storage\Storage
*/
public static function getStorage ( $mountPoint ) {
2013-06-03 00:09:44 +04:00
if ( ! self :: $mounts ) {
\OC_Util :: setupFS ();
}
2013-04-26 02:01:36 +04:00
$mount = self :: $mounts -> find ( $mountPoint );
2013-01-27 00:42:59 +04:00
return $mount -> getStorage ();
2012-10-21 04:12:58 +04:00
}
2013-04-26 02:01:36 +04:00
/**
2014-05-12 00:51:30 +04:00
* @ param string $id
2014-11-24 17:54:42 +03:00
* @ return Mount\MountPoint []
2013-04-26 02:01:36 +04:00
*/
public static function getMountByStorageId ( $id ) {
2013-06-03 00:09:44 +04:00
if ( ! self :: $mounts ) {
\OC_Util :: setupFS ();
}
2013-04-26 02:01:36 +04:00
return self :: $mounts -> findByStorageId ( $id );
}
/**
2014-05-12 00:51:30 +04:00
* @ param int $id
2014-11-24 17:54:42 +03:00
* @ return Mount\MountPoint []
2013-04-26 02:01:36 +04:00
*/
public static function getMountByNumericId ( $id ) {
2013-06-03 00:09:44 +04:00
if ( ! self :: $mounts ) {
\OC_Util :: setupFS ();
}
2013-05-03 01:47:11 +04:00
return self :: $mounts -> findByNumericId ( $id );
2013-04-26 02:01:36 +04:00
}
2012-10-10 13:54:44 +04:00
/**
* resolve a path to a storage and internal path
*
* @ param string $path
2014-05-11 21:13:51 +04:00
* @ return array an array consisting of the storage and the internal path
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:51:06 +03:00
public static function resolvePath ( $path ) {
2013-06-03 00:09:44 +04:00
if ( ! self :: $mounts ) {
\OC_Util :: setupFS ();
}
2013-04-26 02:01:36 +04:00
$mount = self :: $mounts -> find ( $path );
2013-01-27 00:42:59 +04:00
if ( $mount ) {
2020-03-26 11:30:18 +03:00
return [ $mount -> getStorage (), rtrim ( $mount -> getInternalPath ( $path ), '/' )];
2012-10-21 04:12:58 +04:00
} else {
2020-03-26 11:30:18 +03:00
return [ null , null ];
2012-10-10 13:54:44 +04:00
}
}
2020-04-10 17:51:06 +03:00
public static function init ( $user , $root ) {
2012-10-10 13:54:44 +04:00
if ( self :: $defaultInstance ) {
return false ;
}
2013-06-07 19:50:10 +04:00
self :: getLoader ();
2012-10-10 14:25:46 +04:00
self :: $defaultInstance = new View ( $root );
2013-05-15 12:19:38 +04:00
2013-06-03 00:09:44 +04:00
if ( ! self :: $mounts ) {
2015-07-01 16:57:04 +03:00
self :: $mounts = \OC :: $server -> getMountManager ();
2013-05-15 12:19:38 +04:00
}
2012-10-10 13:54:44 +04:00
2012-10-10 14:25:46 +04:00
//load custom mount config
2013-02-11 04:09:58 +04:00
self :: initMountPoints ( $user );
2012-11-22 09:44:48 +04:00
self :: $loaded = true ;
return true ;
}
2020-04-10 17:51:06 +03:00
public static function initMountManager () {
2013-06-03 00:09:44 +04:00
if ( ! self :: $mounts ) {
2015-07-01 16:57:04 +03:00
self :: $mounts = \OC :: $server -> getMountManager ();
2013-05-20 03:57:16 +04:00
}
2013-04-26 02:01:36 +04:00
}
2012-11-22 09:44:48 +04:00
/**
2013-01-22 23:58:09 +04:00
* Initialize system and personal mount points for a user
*
* @ param string $user
2015-06-23 18:09:00 +03:00
* @ throws \OC\User\NoUserException if the user is not available
2013-01-22 23:58:09 +04:00
*/
2012-11-22 09:44:48 +04:00
public static function initMountPoints ( $user = '' ) {
if ( $user == '' ) {
$user = \OC_User :: getUser ();
}
2016-04-22 12:10:51 +03:00
if ( $user === null || $user === false || $user === '' ) {
throw new \OC\User\NoUserException ( 'Attempted to initialize mount points for null user and no user in session' );
}
2013-10-29 03:26:35 +04:00
2016-10-18 12:35:54 +03:00
if ( isset ( self :: $usersSetup [ $user ])) {
return ;
}
self :: $usersSetup [ $user ] = true ;
2015-05-07 15:07:02 +03:00
$userManager = \OC :: $server -> getUserManager ();
$userObject = $userManager -> get ( $user );
2013-11-12 18:46:01 +04:00
2015-04-02 12:05:14 +03:00
if ( is_null ( $userObject )) {
2018-04-25 16:22:28 +03:00
\OCP\Util :: writeLog ( 'files' , ' Backends provided no user object for ' . $user , ILogger :: ERROR );
2016-10-18 12:35:54 +03:00
// reset flag, this will make it possible to rethrow the exception if called again
unset ( self :: $usersSetup [ $user ]);
2015-06-23 10:54:03 +03:00
throw new \OC\User\NoUserException ( 'Backends provided no user object for ' . $user );
2015-04-02 12:05:14 +03:00
}
2014-06-18 00:06:56 +04:00
2016-10-18 12:35:54 +03:00
$realUid = $userObject -> getUID ();
2016-10-04 13:28:41 +03:00
// workaround in case of different casings
2016-10-18 12:35:54 +03:00
if ( $user !== $realUid ) {
2016-10-04 13:28:41 +03:00
$stack = json_encode ( debug_backtrace ( DEBUG_BACKTRACE_IGNORE_ARGS , 50 ));
2018-04-25 16:22:28 +03:00
\OCP\Util :: writeLog ( 'files' , 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "' . $realUid . '" got "' . $user . '". Stack: ' . $stack , ILogger :: WARN );
2016-10-18 12:35:54 +03:00
$user = $realUid ;
2016-10-04 13:28:41 +03:00
2016-10-18 12:35:54 +03:00
// again with the correct casing
if ( isset ( self :: $usersSetup [ $user ])) {
return ;
}
2016-10-04 13:28:41 +03:00
2016-10-18 12:35:54 +03:00
self :: $usersSetup [ $user ] = true ;
}
2016-04-22 12:17:36 +03:00
2016-08-01 19:27:07 +03:00
if ( \OC :: $server -> getLockdownManager () -> canAccessFilesystem ()) {
/** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */
$mountConfigManager = \OC :: $server -> getMountProviderCollection ();
2015-04-02 12:05:14 +03:00
2016-08-01 19:27:07 +03:00
// home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers
$homeMount = $mountConfigManager -> getHomeMountForUser ( $userObject );
2020-07-17 15:14:51 +03:00
self :: getMountManager () -> addMount ( $homeMount );
2020-07-08 14:58:27 +03:00
if ( $homeMount -> getStorageRootId () === - 1 ) {
$homeMount -> getStorage () -> mkdir ( '' );
$homeMount -> getStorage () -> getScanner () -> scan ( '' );
}
2013-04-13 02:33:21 +04:00
2016-08-01 19:27:07 +03:00
\OC\Files\Filesystem :: getStorage ( $user );
2015-04-02 12:05:14 +03:00
2016-08-01 19:27:07 +03:00
// Chance to mount for other storages
if ( $userObject ) {
2017-02-15 17:00:21 +03:00
$mounts = $mountConfigManager -> addMountForUser ( $userObject , self :: getMountManager ());
2016-08-01 19:27:07 +03:00
$mounts [] = $homeMount ;
$mountConfigManager -> registerMounts ( $userObject , $mounts );
}
2015-05-07 15:07:02 +03:00
2016-08-01 19:27:07 +03:00
self :: listenForNewMountProviders ( $mountConfigManager , $userManager );
} else {
2016-11-16 19:24:37 +03:00
self :: getMountManager () -> addMount ( new MountPoint (
2016-08-01 19:27:07 +03:00
new NullStorage ([]),
'/' . $user
));
2016-11-16 19:24:37 +03:00
self :: getMountManager () -> addMount ( new MountPoint (
2016-08-01 19:27:07 +03:00
new NullStorage ([]),
'/' . $user . '/files'
));
}
2020-03-26 11:30:18 +03:00
\OC_Hook :: emit ( 'OC_Filesystem' , 'post_initMountPoints' , [ 'user' => $user ]);
2012-10-10 13:54:44 +04:00
}
2015-05-08 14:51:32 +03:00
/**
* Get mounts from mount providers that are registered after setup
*
* @ param MountProviderCollection $mountConfigManager
* @ param IUserManager $userManager
*/
2015-05-07 15:07:02 +03:00
private static function listenForNewMountProviders ( MountProviderCollection $mountConfigManager , IUserManager $userManager ) {
if ( ! self :: $listeningForProviders ) {
self :: $listeningForProviders = true ;
$mountConfigManager -> listen ( '\OC\Files\Config' , 'registerMountProvider' , function ( IMountProvider $provider ) use ( $userManager ) {
foreach ( Filesystem :: $usersSetup as $user => $setup ) {
$userObject = $userManager -> get ( $user );
2015-05-07 15:40:44 +03:00
if ( $userObject ) {
$mounts = $provider -> getMountsForUser ( $userObject , Filesystem :: getLoader ());
2020-03-26 11:30:18 +03:00
array_walk ( $mounts , [ self :: $mounts , 'addMount' ]);
2015-05-07 15:40:44 +03:00
}
2015-05-07 15:07:02 +03:00
}
});
}
}
2012-10-10 13:54:44 +04:00
/**
* get the default filesystem view
*
2012-10-10 14:25:46 +04:00
* @ return View
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:51:06 +03:00
public static function getView () {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance ;
}
/**
* tear down the filesystem , removing all storage providers
*/
2020-04-10 17:51:06 +03:00
public static function tearDown () {
2013-01-27 00:42:59 +04:00
self :: clearMounts ();
2013-04-25 18:56:48 +04:00
self :: $defaultInstance = null ;
2012-10-10 13:54:44 +04:00
}
/**
2014-05-19 19:50:53 +04:00
* get the relative path of the root data directory for the current user
2015-05-07 15:07:02 +03:00
*
2012-10-10 13:54:44 +04:00
* @ return string
*
* Returns path like / admin / files
*/
2020-04-10 17:51:06 +03:00
public static function getRoot () {
2014-04-23 14:54:18 +04:00
if ( ! self :: $defaultInstance ) {
return null ;
}
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> getRoot ();
}
/**
* clear all mounts and storage backends
*/
public static function clearMounts () {
2013-06-02 23:44:24 +04:00
if ( self :: $mounts ) {
2020-03-26 11:30:18 +03:00
self :: $usersSetup = [];
2013-06-02 23:44:24 +04:00
self :: $mounts -> clear ();
}
2012-10-10 13:54:44 +04:00
}
/**
* mount an \OC\Files\Storage\Storage in our virtual filesystem
*
2012-10-21 04:12:58 +04:00
* @ param \OC\Files\Storage\Storage | string $class
2012-10-10 14:25:46 +04:00
* @ param array $arguments
* @ param string $mountpoint
2012-10-10 13:54:44 +04:00
*/
2020-04-10 17:51:06 +03:00
public static function mount ( $class , $arguments , $mountpoint ) {
2013-06-03 00:09:44 +04:00
if ( ! self :: $mounts ) {
\OC_Util :: setupFS ();
}
2014-11-24 17:54:42 +03:00
$mount = new Mount\MountPoint ( $class , $mountpoint , $arguments , self :: getLoader ());
2013-04-26 02:01:36 +04:00
self :: $mounts -> addMount ( $mount );
2012-10-10 13:54:44 +04:00
}
/**
* return the path to a local version of the file
2013-02-11 20:44:02 +04:00
* we need this because we can ' t know if a file is stored local or not from
* outside the filestorage and for some purposes a local file is needed
2012-10-10 13:54:44 +04:00
*
2012-10-10 14:25:46 +04:00
* @ param string $path
2012-10-10 13:54:44 +04:00
* @ return string
*/
2020-04-10 17:51:06 +03:00
public static function getLocalFile ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> getLocalFile ( $path );
}
/**
2012-10-10 14:25:46 +04:00
* @ param string $path
2012-10-10 13:54:44 +04:00
* @ return string
*/
2020-04-10 17:51:06 +03:00
public static function getLocalFolder ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> getLocalFolder ( $path );
}
/**
* return path to file which reflects one visible in browser
*
2012-10-10 14:25:46 +04:00
* @ param string $path
2012-10-10 13:54:44 +04:00
* @ return string
*/
2020-04-10 17:51:06 +03:00
public static function getLocalPath ( $path ) {
2012-10-10 14:25:46 +04:00
$datadir = \OC_User :: getHome ( \OC_User :: getUser ()) . '/files' ;
2012-10-10 13:54:44 +04:00
$newpath = $path ;
if ( strncmp ( $newpath , $datadir , strlen ( $datadir )) == 0 ) {
$newpath = substr ( $path , strlen ( $datadir ));
}
return $newpath ;
}
/**
* check if the requested path is valid
*
2012-10-10 14:25:46 +04:00
* @ param string $path
2012-10-10 13:54:44 +04:00
* @ return bool
*/
2020-04-10 17:51:06 +03:00
public static function isValidPath ( $path ) {
2012-11-03 00:42:29 +04:00
$path = self :: normalizePath ( $path );
2012-10-10 13:54:44 +04:00
if ( ! $path || $path [ 0 ] !== '/' ) {
$path = '/' . $path ;
}
2015-05-07 15:07:02 +03:00
if ( strpos ( $path , '/../' ) !== false || strrchr ( $path , '/' ) === '/..' ) {
2012-10-10 13:54:44 +04:00
return false ;
}
return true ;
}
/**
* checks if a file is blacklisted for storage in the filesystem
* Listens to write and rename hooks
*
* @ param array $data from hook
*/
2020-04-10 17:51:06 +03:00
public static function isBlacklisted ( $data ) {
2012-10-10 13:54:44 +04:00
if ( isset ( $data [ 'path' ])) {
$path = $data [ 'path' ];
2020-04-10 11:35:09 +03:00
} elseif ( isset ( $data [ 'newpath' ])) {
2012-10-10 13:54:44 +04:00
$path = $data [ 'newpath' ];
}
if ( isset ( $path )) {
2013-02-22 19:13:08 +04:00
if ( self :: isFileBlacklisted ( $path )) {
2012-10-10 13:54:44 +04:00
$data [ 'run' ] = false ;
}
}
}
2013-02-22 19:13:08 +04:00
/**
* @ param string $filename
* @ return bool
*/
2020-04-10 17:51:06 +03:00
public static function isFileBlacklisted ( $filename ) {
2015-02-06 17:03:29 +03:00
$filename = self :: normalizePath ( $filename );
2020-03-26 11:30:18 +03:00
$blacklist = \OC :: $server -> getConfig () -> getSystemValue ( 'blacklisted_files' , [ '.htaccess' ]);
2013-02-22 19:13:08 +04:00
$filename = strtolower ( basename ( $filename ));
2015-02-06 17:03:29 +03:00
return in_array ( $filename , $blacklist );
2013-02-22 19:13:08 +04:00
}
2013-05-19 22:15:49 +04:00
/**
2014-05-19 19:50:53 +04:00
* check if the directory should be ignored when scanning
2013-05-19 22:15:49 +04:00
* NOTE : the special directories . and .. would cause never ending recursion
2015-05-07 15:07:02 +03:00
*
2018-11-15 13:51:28 +03:00
* @ param string $dir
2013-05-19 22:15:49 +04:00
* @ return boolean
*/
2020-04-10 17:51:06 +03:00
public static function isIgnoredDir ( $dir ) {
2013-05-19 22:15:49 +04:00
if ( $dir === '.' || $dir === '..' ) {
return true ;
}
return false ;
}
2012-10-10 13:54:44 +04:00
/**
* following functions are equivalent to their php builtin equivalents for arguments / return values .
*/
2020-04-10 17:51:06 +03:00
public static function mkdir ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> mkdir ( $path );
}
2020-04-10 17:51:06 +03:00
public static function rmdir ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> rmdir ( $path );
}
2020-04-10 17:51:06 +03:00
public static function is_dir ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> is_dir ( $path );
}
2020-04-10 17:51:06 +03:00
public static function is_file ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> is_file ( $path );
}
2020-04-10 17:51:06 +03:00
public static function stat ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> stat ( $path );
}
2020-04-10 17:51:06 +03:00
public static function filetype ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> filetype ( $path );
}
2020-04-10 17:51:06 +03:00
public static function filesize ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> filesize ( $path );
}
2020-04-10 17:51:06 +03:00
public static function readfile ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> readfile ( $path );
}
2020-04-10 17:51:06 +03:00
public static function isCreatable ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> isCreatable ( $path );
}
2020-04-10 17:51:06 +03:00
public static function isReadable ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> isReadable ( $path );
}
2020-04-10 17:51:06 +03:00
public static function isUpdatable ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> isUpdatable ( $path );
}
2020-04-10 17:51:06 +03:00
public static function isDeletable ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> isDeletable ( $path );
}
2020-04-10 17:51:06 +03:00
public static function isSharable ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> isSharable ( $path );
}
2020-04-10 17:51:06 +03:00
public static function file_exists ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> file_exists ( $path );
}
2020-04-10 17:51:06 +03:00
public static function filemtime ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> filemtime ( $path );
}
2020-04-10 17:51:06 +03:00
public static function touch ( $path , $mtime = null ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> touch ( $path , $mtime );
}
2014-02-06 19:30:58 +04:00
/**
* @ return string
*/
2020-04-10 17:51:06 +03:00
public static function file_get_contents ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> file_get_contents ( $path );
}
2020-04-10 17:51:06 +03:00
public static function file_put_contents ( $path , $data ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> file_put_contents ( $path , $data );
}
2020-04-10 17:51:06 +03:00
public static function unlink ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> unlink ( $path );
}
2020-04-10 17:51:06 +03:00
public static function rename ( $path1 , $path2 ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> rename ( $path1 , $path2 );
}
2020-04-10 17:51:06 +03:00
public static function copy ( $path1 , $path2 ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> copy ( $path1 , $path2 );
}
2020-04-10 17:51:06 +03:00
public static function fopen ( $path , $mode ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> fopen ( $path , $mode );
}
2014-02-06 19:30:58 +04:00
/**
* @ return string
*/
2020-04-10 17:51:06 +03:00
public static function toTmpFile ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> toTmpFile ( $path );
}
2020-04-10 17:51:06 +03:00
public static function fromTmpFile ( $tmpFile , $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> fromTmpFile ( $tmpFile , $path );
}
2020-04-10 17:51:06 +03:00
public static function getMimeType ( $path ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> getMimeType ( $path );
}
2020-04-10 17:51:06 +03:00
public static function hash ( $type , $path , $raw = false ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> hash ( $type , $path , $raw );
}
2020-04-10 17:51:06 +03:00
public static function free_space ( $path = '/' ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> free_space ( $path );
}
2020-04-10 17:51:06 +03:00
public static function search ( $query ) {
2012-10-26 15:23:15 +04:00
return self :: $defaultInstance -> search ( $query );
2012-10-10 13:54:44 +04:00
}
2014-02-19 12:31:54 +04:00
/**
* @ param string $query
*/
2020-04-10 17:51:06 +03:00
public static function searchByMime ( $query ) {
2012-10-27 12:34:25 +04:00
return self :: $defaultInstance -> searchByMime ( $query );
}
2014-12-04 16:01:15 +03:00
/**
* @ param string | int $tag name or tag id
2014-12-12 13:18:35 +03:00
* @ param string $userId owner of the tags
2014-12-04 16:01:15 +03:00
* @ return FileInfo [] array or file info
*/
2020-04-10 17:51:06 +03:00
public static function searchByTag ( $tag , $userId ) {
2014-12-12 13:18:35 +03:00
return self :: $defaultInstance -> searchByTag ( $tag , $userId );
2014-12-04 16:01:15 +03:00
}
2012-10-10 13:54:44 +04:00
/**
* check if a file or folder has been updated since $time
*
2013-01-27 00:42:59 +04:00
* @ param string $path
2012-10-10 13:54:44 +04:00
* @ param int $time
* @ return bool
*/
2020-04-10 17:51:06 +03:00
public static function hasUpdated ( $path , $time ) {
2012-10-10 13:54:44 +04:00
return self :: $defaultInstance -> hasUpdated ( $path , $time );
}
/**
2014-05-19 19:50:53 +04:00
* Fix common problems with a file path
2015-05-07 15:07:02 +03:00
*
2012-10-10 14:25:46 +04:00
* @ param string $path
2016-04-29 12:19:00 +03:00
* @ param bool $stripTrailingSlash whether to strip the trailing slash
* @ param bool $isAbsolutePath whether the given path is absolute
* @ param bool $keepUnicode true to disable unicode normalization
2012-10-10 13:54:44 +04:00
* @ return string
*/
2016-04-29 12:19:00 +03:00
public static function normalizePath ( $path , $stripTrailingSlash = true , $isAbsolutePath = false , $keepUnicode = false ) {
2016-04-29 14:17:41 +03:00
if ( is_null ( self :: $normalizedPathCache )) {
2018-03-26 20:47:38 +03:00
self :: $normalizedPathCache = new CappedMemoryCache ( 2048 );
2016-04-29 14:17:41 +03:00
}
2015-02-13 14:49:34 +03:00
/**
* FIXME : This is a workaround for existing classes and files which call
* this function with another type than a valid string . This
* conversion should get removed as soon as all existing
* function calls have been fixed .
*/
$path = ( string ) $path ;
2016-06-01 13:20:38 +03:00
$cacheKey = json_encode ([ $path , $stripTrailingSlash , $isAbsolutePath , $keepUnicode ]);
2015-01-10 12:48:28 +03:00
2020-08-31 18:29:36 +03:00
if ( $cacheKey && isset ( self :: $normalizedPathCache [ $cacheKey ])) {
2015-01-10 12:48:28 +03:00
return self :: $normalizedPathCache [ $cacheKey ];
}
2018-10-08 23:51:40 +03:00
if ( $path === '' ) {
2012-10-10 13:54:44 +04:00
return '/' ;
}
2014-11-07 12:52:37 +03:00
2015-02-06 17:03:29 +03:00
//normalize unicode if possible
2016-04-29 12:19:00 +03:00
if ( ! $keepUnicode ) {
$path = \OC_Util :: normalizeUnicode ( $path );
}
2015-02-06 17:03:29 +03:00
2018-10-08 23:51:40 +03:00
//add leading slash, if it is already there we strip it anyway
$path = '/' . $path ;
2013-11-14 16:15:03 +04:00
2018-10-08 23:51:40 +03:00
$patterns = [
'/\\\\/s' , // no windows style slashes
'/\/\.(\/\.)?\//s' , // remove '/./'
2020-04-08 16:41:20 +03:00
'/\/{2,}/s' , // remove sequence of slashes
2018-10-08 23:51:40 +03:00
'/\/\.$/s' , // remove trailing /.
];
2013-11-14 16:15:03 +04:00
2018-10-08 23:51:40 +03:00
do {
$count = 0 ;
$path = preg_replace ( $patterns , '/' , $path , - 1 , $count );
} while ( $count > 0 );
2013-11-14 16:15:03 +04:00
2013-02-05 19:37:40 +04:00
//remove trailing slash
2018-10-08 23:51:40 +03:00
if ( $stripTrailingSlash && strlen ( $path ) > 1 ) {
2018-01-26 00:26:47 +03:00
$path = rtrim ( $path , '/' );
2012-10-26 14:37:49 +04:00
}
2013-11-14 16:15:03 +04:00
2018-10-08 23:51:40 +03:00
self :: $normalizedPathCache [ $cacheKey ] = $path ;
2015-01-10 12:48:28 +03:00
2018-10-08 23:51:40 +03:00
return $path ;
2012-10-10 13:54:44 +04:00
}
2012-10-26 14:30:25 +04:00
/**
* get the filesystem info
*
* @ param string $path
2013-11-18 20:29:30 +04:00
* @ param boolean $includeMountPoints whether to add mountpoint sizes ,
* defaults to true
2015-06-15 15:10:10 +03:00
* @ return \OC\Files\FileInfo | bool False if file does not exist
2012-10-26 14:30:25 +04:00
*/
2013-11-18 20:29:30 +04:00
public static function getFileInfo ( $path , $includeMountPoints = true ) {
return self :: $defaultInstance -> getFileInfo ( $path , $includeMountPoints );
2012-10-26 14:30:25 +04:00
}
2012-10-27 01:05:02 +04:00
/**
* change file metadata
*
* @ param string $path
* @ param array $data
* @ return int
*
* returns the fileid of the updated file
*/
public static function putFileInfo ( $path , $data ) {
return self :: $defaultInstance -> putFileInfo ( $path , $data );
}
2012-10-26 14:30:25 +04:00
/**
* get the content of a directory
*
* @ param string $directory path under datadirectory
2013-04-09 00:40:03 +04:00
* @ param string $mimetype_filter limit returned content to this mimetype or mimepart
2014-02-27 17:04:19 +04:00
* @ return \OC\Files\FileInfo []
2012-10-26 14:30:25 +04:00
*/
2013-04-09 00:40:03 +04:00
public static function getDirectoryContent ( $directory , $mimetype_filter = '' ) {
return self :: $defaultInstance -> getDirectoryContent ( $directory , $mimetype_filter );
2012-10-26 14:30:25 +04:00
}
2012-11-08 20:47:00 +04:00
2013-01-27 03:18:15 +04:00
/**
* Get the path of a file by id
*
2013-07-16 07:56:52 +04:00
* Note that the resulting path is not guaranteed to be unique for the id , multiple paths can point to the same file
2013-01-27 03:18:15 +04:00
*
* @ param int $id
2015-06-15 15:10:10 +03:00
* @ throws NotFoundException
2013-01-27 03:18:15 +04:00
* @ return string
*/
public static function getPath ( $id ) {
return self :: $defaultInstance -> getPath ( $id );
}
2013-02-03 03:50:40 +04:00
/**
2013-02-16 04:30:44 +04:00
* Get the owner for a file or folder
*
* @ param string $path
* @ return string
*/
2013-02-03 03:50:40 +04:00
public static function getOwner ( $path ) {
return self :: $defaultInstance -> getOwner ( $path );
}
2012-11-08 20:47:00 +04:00
/**
* get the ETag for a file or folder
*
* @ param string $path
* @ return string
*/
2020-04-10 17:51:06 +03:00
public static function getETag ( $path ) {
2012-11-08 20:47:00 +04:00
return self :: $defaultInstance -> getETag ( $path );
}
2012-10-10 13:54:44 +04:00
}