2011-07-27 21:07:28 +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 Bernhard Posselt < dev @ bernhard - posselt . com >
* @ author Birk Borkason < daniel . niccoli @ gmail . com >
2019-12-03 21:57:53 +03:00
* @ author Bjoern Schiessle < bjoern @ schiessle . org >
2016-05-26 20:56:05 +03:00
* @ author Björn Schießle < bjoern @ schiessle . org >
2015-03-26 13:44:34 +03:00
* @ author Brice Maron < brice @ bmaron . net >
2017-11-06 17:56:42 +03:00
* @ 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 Clark Tomlinson < fallen013 @ gmail . com >
2015-06-25 12:43:55 +03:00
* @ author cmeh < cmeh @ users . noreply . github . com >
2019-12-03 21:57:53 +03:00
* @ author Eric Masseran < rico . masseran @ gmail . com >
2017-11-06 17:56:42 +03:00
* @ author Felix Epp < work @ felixepp . de >
2015-03-26 13:44:34 +03:00
* @ author Florin Peter < github @ florin - peter . de >
2016-05-26 20:56:05 +03:00
* @ author Frank Karlitschek < frank @ karlitschek . de >
2017-11-06 22:15:27 +03:00
* @ author Georg Ehrke < oc . list @ georgehrke . com >
2015-03-26 13:44:34 +03:00
* @ author helix84 < helix84 @ centrum . sk >
2017-11-06 17:56:42 +03:00
* @ author Ilja Neumann < ineumann @ owncloud . com >
2015-10-05 21:54:56 +03:00
* @ author Individual IT Services < info @ individual - it . net >
2015-03-26 13:44:34 +03:00
* @ author Jakob Sack < mail @ jakobsack . de >
2016-07-21 18:07:57 +03:00
* @ author Joas Schilling < coding @ schilljs . com >
2019-12-03 21:57:53 +03:00
* @ author John Molakvoæ ( skjnldsv ) < skjnldsv @ protonmail . com >
2015-03-26 13:44:34 +03:00
* @ author Jörn Friedrich Dreyer < jfd @ butonic . de >
2020-08-24 15:54:25 +03:00
* @ author Julius Härtl < jus @ bitgrid . net >
2017-11-06 17:56:42 +03:00
* @ author Kawohl < john @ owncloud . com >
2016-05-26 20:56:05 +03:00
* @ author Lukas Reschke < lukas @ statuscode . ch >
2015-03-26 13:44:34 +03:00
* @ author Markus Goetz < markus @ woboq . com >
2015-10-05 21:54:56 +03:00
* @ author Martin Mattel < martin . mattel @ diemattels . at >
2015-03-26 13:44:34 +03:00
* @ author Marvin Thomas Rabe < mrabe @ marvinrabe . de >
* @ author Michael Gapczynski < GapczynskiM @ gmail . com >
* @ author Morris Jobke < hey @ morrisjobke . de >
2017-11-06 17:56:42 +03:00
* @ author rakekniven < mark . ziegler @ rakekniven . de >
2019-12-03 21:57:53 +03:00
* @ author Robert Dailey < rcdailey @ gmail . com >
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 >
2017-11-06 17:56:42 +03:00
* @ author Sebastian Wessalowski < sebastian @ wessalowski . org >
2015-03-26 13:44:34 +03:00
* @ author Stefan Rado < owncloud @ sradonia . net >
2016-05-26 20:56:05 +03:00
* @ author Stefan Weil < sw @ weilnetz . de >
2015-03-26 13:44:34 +03:00
* @ author Thomas Müller < thomas . mueller @ tmit . eu >
* @ author Thomas Tanghus < thomas @ tanghus . net >
* @ author Victor Dubiniuk < dubiniuk @ owncloud . com >
2020-12-16 16:54:15 +03:00
* @ author Vincent Petry < vincent @ nextcloud . com >
2015-03-26 13:44:34 +03:00
* @ author Volkan Gezer < volkangezer @ gmail . 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 />
2011-07-27 21:07:28 +04:00
*
*/
2015-11-19 17:35:58 +03:00
2020-08-20 15:08:18 +03:00
use bantu\IniGetWrapper\IniGetWrapper ;
2019-11-22 22:52:10 +03:00
use OC\AppFramework\Http\Request ;
2020-06-10 16:27:30 +03:00
use OC\Files\Storage\LocalRootStorage ;
2015-11-19 17:35:58 +03:00
use OCP\IConfig ;
use OCP\IGroupManager ;
2018-04-25 16:22:28 +03:00
use OCP\ILogger ;
2015-11-19 17:35:58 +03:00
use OCP\IUser ;
2020-08-04 16:07:32 +03:00
use OCP\IUserSession ;
2015-11-19 17:35:58 +03:00
2011-07-29 23:36:03 +04:00
class OC_Util {
2020-03-26 11:30:18 +03:00
public static $scripts = [];
public static $styles = [];
public static $headers = [];
2014-08-19 20:01:26 +04:00
private static $rootMounted = false ;
private static $fsSetup = false ;
2011-07-27 21:07:28 +04:00
2016-11-15 19:51:03 +03:00
/** @var array Local cache of version.php */
private static $versionCache = null ;
2015-02-18 16:24:50 +03:00
protected static function getAppManager () {
return \OC :: $server -> getAppManager ();
}
2014-04-25 16:34:47 +04:00
private static function initLocalStorageRootFS () {
// mount local file backend as root
2015-12-18 13:42:09 +03:00
$configDataDirectory = \OC :: $server -> getSystemConfig () -> getValue ( " datadirectory " , OC :: $SERVERROOT . " /data " );
2014-04-25 16:34:47 +04:00
//first set up the local "root" storage
2015-04-02 14:28:36 +03:00
\OC\Files\Filesystem :: initMountManager ();
2014-08-19 20:01:26 +04:00
if ( ! self :: $rootMounted ) {
2020-06-10 16:27:30 +03:00
\OC\Files\Filesystem :: mount ( LocalRootStorage :: class , [ 'datadir' => $configDataDirectory ], '/' );
2014-04-25 16:34:47 +04:00
self :: $rootMounted = true ;
}
}
2014-07-23 18:42:33 +04:00
2014-04-25 16:34:47 +04:00
/**
* mounting an object storage as the root fs will in essence remove the
* necessity of a data folder being present .
* TODO make home storage aware of this and use the object storage instead of local disk access
2014-08-19 20:01:26 +04:00
*
2014-04-25 16:34:47 +04:00
* @ param array $config containing 'class' and optional 'arguments'
2017-07-19 20:44:10 +03:00
* @ suppress PhanDeprecatedFunction
2014-04-25 16:34:47 +04:00
*/
2014-06-11 15:55:11 +04:00
private static function initObjectStoreRootFS ( $config ) {
2014-04-25 16:34:47 +04:00
// check misconfiguration
if ( empty ( $config [ 'class' ])) {
2018-04-25 16:22:28 +03:00
\OCP\Util :: writeLog ( 'files' , 'No class given for objectstore' , ILogger :: ERROR );
2014-04-25 16:34:47 +04:00
}
if ( ! isset ( $config [ 'arguments' ])) {
2020-03-26 11:30:18 +03:00
$config [ 'arguments' ] = [];
2014-04-25 16:34:47 +04:00
}
2014-06-18 00:06:56 +04:00
// instantiate object store implementation
2016-10-07 13:41:37 +03:00
$name = $config [ 'class' ];
if ( strpos ( $name , 'OCA\\' ) === 0 && substr_count ( $name , '\\' ) >= 2 ) {
$segments = explode ( '\\' , $name );
OC_App :: loadApp ( strtolower ( $segments [ 1 ]));
}
2014-06-18 00:06:56 +04:00
$config [ 'arguments' ][ 'objectstore' ] = new $config [ 'class' ]( $config [ 'arguments' ]);
// mount with plain / root object store implementation
$config [ 'class' ] = '\OC\Files\ObjectStore\ObjectStoreStorage' ;
2014-04-25 16:34:47 +04:00
// mount object storage as root
2015-04-02 14:28:36 +03:00
\OC\Files\Filesystem :: initMountManager ();
2014-08-19 20:01:26 +04:00
if ( ! self :: $rootMounted ) {
2014-04-25 16:34:47 +04:00
\OC\Files\Filesystem :: mount ( $config [ 'class' ], $config [ 'arguments' ], '/' );
self :: $rootMounted = true ;
}
}
2014-07-23 18:42:33 +04:00
2017-05-10 21:21:35 +03:00
/**
* mounting an object storage as the root fs will in essence remove the
* necessity of a data folder being present .
*
* @ param array $config containing 'class' and optional 'arguments'
2017-07-19 20:44:10 +03:00
* @ suppress PhanDeprecatedFunction
2017-05-10 21:21:35 +03:00
*/
private static function initObjectStoreMultibucketRootFS ( $config ) {
// check misconfiguration
if ( empty ( $config [ 'class' ])) {
2018-04-25 16:22:28 +03:00
\OCP\Util :: writeLog ( 'files' , 'No class given for objectstore' , ILogger :: ERROR );
2017-05-10 21:21:35 +03:00
}
if ( ! isset ( $config [ 'arguments' ])) {
2020-03-26 11:30:18 +03:00
$config [ 'arguments' ] = [];
2017-05-10 21:21:35 +03:00
}
// instantiate object store implementation
$name = $config [ 'class' ];
if ( strpos ( $name , 'OCA\\' ) === 0 && substr_count ( $name , '\\' ) >= 2 ) {
$segments = explode ( '\\' , $name );
OC_App :: loadApp ( strtolower ( $segments [ 1 ]));
}
if ( ! isset ( $config [ 'arguments' ][ 'bucket' ])) {
$config [ 'arguments' ][ 'bucket' ] = '' ;
}
// put the root FS always in first bucket for multibucket configuration
$config [ 'arguments' ][ 'bucket' ] .= '0' ;
$config [ 'arguments' ][ 'objectstore' ] = new $config [ 'class' ]( $config [ 'arguments' ]);
// mount with plain / root object store implementation
$config [ 'class' ] = '\OC\Files\ObjectStore\ObjectStoreStorage' ;
// mount object storage as root
\OC\Files\Filesystem :: initMountManager ();
if ( ! self :: $rootMounted ) {
\OC\Files\Filesystem :: mount ( $config [ 'class' ], $config [ 'arguments' ], '/' );
self :: $rootMounted = true ;
}
}
2013-08-15 10:49:19 +04:00
/**
2014-05-19 19:50:53 +04:00
* Can be set up
2014-08-19 20:01:26 +04:00
*
2013-08-23 09:30:42 +04:00
* @ param string $user
2013-08-15 10:49:19 +04:00
* @ return boolean
2013-08-18 12:33:09 +04:00
* @ description configure the initial filesystem based on the configuration
2017-07-19 20:44:10 +03:00
* @ suppress PhanDeprecatedFunction
* @ suppress PhanAccessMethodInternal
2013-08-15 10:49:19 +04:00
*/
2014-08-19 20:01:26 +04:00
public static function setupFS ( $user = '' ) {
2013-08-18 12:33:09 +04:00
//setting up the filesystem twice can only lead to trouble
2014-08-19 20:01:26 +04:00
if ( self :: $fsSetup ) {
2011-07-27 21:07:28 +04:00
return false ;
}
2014-10-04 00:13:55 +04:00
\OC :: $server -> getEventLogger () -> start ( 'setup_fs' , 'Setup filesystem' );
2012-08-29 23:35:55 +04:00
// If we are not forced to load a specific user we load the one that is logged in
2016-02-18 11:21:32 +03:00
if ( $user === null ) {
$user = '' ;
2020-04-10 11:35:09 +03:00
} elseif ( $user == " " && \OC :: $server -> getUserSession () -> isLoggedIn ()) {
2012-08-29 23:35:55 +04:00
$user = OC_User :: getUser ();
}
2012-10-28 16:47:53 +04:00
// load all filesystem apps before, so no setup-hook gets lost
2020-03-26 11:30:18 +03:00
OC_App :: loadApps ([ 'filesystem' ]);
2012-10-28 16:47:53 +04:00
2012-08-29 23:35:55 +04:00
// the filesystem will finish when $user is not empty,
// mark fs setup here to avoid doing the setup from loading
// OC_Filesystem
if ( $user != '' ) {
2014-08-19 20:01:26 +04:00
self :: $fsSetup = true ;
2012-08-29 23:35:55 +04:00
}
2015-04-02 14:28:36 +03:00
\OC\Files\Filesystem :: initMountManager ();
2019-05-15 11:22:51 +03:00
$prevLogging = \OC\Files\Filesystem :: logWarningWhenAddingStorageWrapper ( false );
2015-04-01 18:12:06 +03:00
\OC\Files\Filesystem :: addStorageWrapper ( 'mount_options' , function ( $mountPoint , \OCP\Files\Storage $storage , \OCP\Files\Mount\IMountPoint $mount ) {
if ( $storage -> instanceOfStorage ( '\OC\Files\Storage\Common' )) {
/** @var \OC\Files\Storage\Common $storage */
$storage -> setMountOptions ( $mount -> getOptions ());
}
return $storage ;
});
2017-07-19 21:21:05 +03:00
\OC\Files\Filesystem :: addStorageWrapper ( 'enable_sharing' , function ( $mountPoint , \OCP\Files\Storage\IStorage $storage , \OCP\Files\Mount\IMountPoint $mount ) {
2015-12-02 18:23:50 +03:00
if ( ! $mount -> getOption ( 'enable_sharing' , true )) {
return new \OC\Files\Storage\Wrapper\PermissionsMask ([
'storage' => $storage ,
'mask' => \OCP\Constants :: PERMISSION_ALL - \OCP\Constants :: PERMISSION_SHARE
]);
}
return $storage ;
});
2015-01-24 00:53:21 +03:00
// install storage availability wrapper, before most other wrappers
2017-07-19 21:21:05 +03:00
\OC\Files\Filesystem :: addStorageWrapper ( 'oc_availability' , function ( $mountPoint , \OCP\Files\Storage\IStorage $storage ) {
2016-06-01 15:29:31 +03:00
if ( ! $storage -> instanceOfStorage ( '\OCA\Files_Sharing\SharedStorage' ) && ! $storage -> isLocal ()) {
2015-01-24 00:53:21 +03:00
return new \OC\Files\Storage\Wrapper\Availability ([ 'storage' => $storage ]);
}
return $storage ;
2016-04-29 13:42:37 +03:00
});
2016-05-02 18:34:24 +03:00
\OC\Files\Filesystem :: addStorageWrapper ( 'oc_encoding' , function ( $mountPoint , \OCP\Files\Storage $storage , \OCP\Files\Mount\IMountPoint $mount ) {
2016-06-01 15:29:31 +03:00
if ( $mount -> getOption ( 'encoding_compatibility' , false ) && ! $storage -> instanceOfStorage ( '\OCA\Files_Sharing\SharedStorage' ) && ! $storage -> isLocal ()) {
2016-04-29 13:42:37 +03:00
return new \OC\Files\Storage\Wrapper\Encoding ([ 'storage' => $storage ]);
}
return $storage ;
2015-01-24 00:53:21 +03:00
});
2015-04-01 18:12:06 +03:00
\OC\Files\Filesystem :: addStorageWrapper ( 'oc_quota' , function ( $mountPoint , $storage ) {
// set up quota for home storages, even for other users
// which can happen when using sharing
/**
* @ var \OC\Files\Storage\Storage $storage
*/
if ( $storage -> instanceOfStorage ( '\OC\Files\Storage\Home' )
|| $storage -> instanceOfStorage ( '\OC\Files\ObjectStore\HomeObjectStoreStorage' )
) {
/** @var \OC\Files\Storage\Home $storage */
if ( is_object ( $storage -> getUser ())) {
2020-03-04 19:20:27 +03:00
$quota = OC_Util :: getUserQuota ( $storage -> getUser ());
2015-04-01 18:12:06 +03:00
if ( $quota !== \OCP\Files\FileInfo :: SPACE_UNLIMITED ) {
2020-03-26 11:30:18 +03:00
return new \OC\Files\Storage\Wrapper\Quota ([ 'storage' => $storage , 'quota' => $quota , 'root' => 'files' ]);
2015-04-01 18:12:06 +03:00
}
}
}
return $storage ;
2018-02-27 16:06:14 +03:00
});
\OC\Files\Filesystem :: addStorageWrapper ( 'readonly' , function ( $mountPoint , \OCP\Files\Storage\IStorage $storage , \OCP\Files\Mount\IMountPoint $mount ) {
/*
* Do not allow any operations that modify the storage
*/
if ( $mount -> getOption ( 'readonly' , false )) {
return new \OC\Files\Storage\Wrapper\PermissionsMask ([
'storage' => $storage ,
'mask' => \OCP\Constants :: PERMISSION_ALL & ~ (
\OCP\Constants :: PERMISSION_UPDATE |
\OCP\Constants :: PERMISSION_CREATE |
\OCP\Constants :: PERMISSION_DELETE
),
]);
}
return $storage ;
2015-04-01 18:12:06 +03:00
});
2020-03-26 11:30:18 +03:00
OC_Hook :: emit ( 'OC_Filesystem' , 'preSetup' , [ 'user' => $user ]);
2019-05-15 11:22:51 +03:00
\OC\Files\Filesystem :: logWarningWhenAddingStorageWrapper ( $prevLogging );
2015-04-01 18:12:06 +03:00
2014-04-25 16:34:47 +04:00
//check if we are using an object storage
2015-12-18 13:42:09 +03:00
$objectStore = \OC :: $server -> getSystemConfig () -> getValue ( 'objectstore' , null );
2017-05-10 21:21:35 +03:00
$objectStoreMultibucket = \OC :: $server -> getSystemConfig () -> getValue ( 'objectstore_multibucket' , null );
// use the same order as in ObjectHomeMountProvider
if ( isset ( $objectStoreMultibucket )) {
self :: initObjectStoreMultibucketRootFS ( $objectStoreMultibucket );
} elseif ( isset ( $objectStore )) {
2014-06-13 17:49:40 +04:00
self :: initObjectStoreRootFS ( $objectStore );
2014-04-25 16:34:47 +04:00
} else {
self :: initLocalStorageRootFS ();
2012-02-06 02:49:22 +04:00
}
2012-06-20 10:57:21 +04:00
2020-07-30 23:09:19 +03:00
/** @var \OCP\Files\Config\IMountProviderCollection $mountProviderCollection */
$mountProviderCollection = \OC :: $server -> query ( \OCP\Files\Config\IMountProviderCollection :: class );
$rootMountProviders = $mountProviderCollection -> getRootMounts ();
/** @var \OC\Files\Mount\Manager $mountManager */
$mountManager = \OC\Files\Filesystem :: getMountManager ();
foreach ( $rootMountProviders as $rootMountProvider ) {
$mountManager -> addMount ( $rootMountProvider );
}
2018-01-16 15:27:45 +03:00
if ( $user != '' && ! \OC :: $server -> getUserManager () -> userExists ( $user )) {
2014-10-04 00:13:55 +04:00
\OC :: $server -> getEventLogger () -> end ( 'setup_fs' );
2014-01-21 14:32:30 +04:00
return false ;
}
2013-08-23 09:30:42 +04:00
//if we aren't logged in, there is no use to set up the filesystem
2014-08-19 20:01:26 +04:00
if ( $user != " " ) {
$userDir = '/' . $user . '/files' ;
2014-06-13 17:49:40 +04:00
2012-08-27 17:55:22 +04:00
//jail the user into his "home" directory
2013-08-15 10:49:19 +04:00
\OC\Files\Filesystem :: init ( $user , $userDir );
2012-10-23 18:16:46 +04:00
2020-03-26 11:30:18 +03:00
OC_Hook :: emit ( 'OC_Filesystem' , 'setup' , [ 'user' => $user , 'user_dir' => $userDir ]);
2011-07-27 21:07:28 +04:00
}
2014-10-04 00:13:55 +04:00
\OC :: $server -> getEventLogger () -> end ( 'setup_fs' );
2012-10-26 20:29:24 +04:00
return true ;
2011-07-27 21:07:28 +04:00
}
2014-05-12 14:19:07 +04:00
/**
2014-05-19 19:50:53 +04:00
* check if a password is required for each public link
2014-08-19 20:01:26 +04:00
*
2014-05-12 14:19:07 +04:00
* @ return boolean
2017-07-19 20:44:10 +03:00
* @ suppress PhanDeprecatedFunction
2014-05-12 14:19:07 +04:00
*/
public static function isPublicLinkPasswordRequired () {
2018-01-17 23:10:40 +03:00
$enforcePassword = \OC :: $server -> getConfig () -> getAppValue ( 'core' , 'shareapi_enforce_links_password' , 'no' );
2018-01-26 14:36:25 +03:00
return $enforcePassword === 'yes' ;
2014-05-12 14:19:07 +04:00
}
2014-05-13 17:22:18 +04:00
/**
* check if sharing is disabled for the current user
2015-11-19 17:35:58 +03:00
* @ param IConfig $config
* @ param IGroupManager $groupManager
* @ param IUser | null $user
* @ return bool
2014-05-13 17:22:18 +04:00
*/
2015-11-19 17:35:58 +03:00
public static function isSharingDisabledForUser ( IConfig $config , IGroupManager $groupManager , $user ) {
if ( $config -> getAppValue ( 'core' , 'shareapi_exclude_groups' , 'no' ) === 'yes' ) {
$groupsList = $config -> getAppValue ( 'core' , 'shareapi_exclude_groups_list' , '' );
2015-10-01 16:37:55 +03:00
$excludedGroups = json_decode ( $groupsList );
if ( is_null ( $excludedGroups )) {
$excludedGroups = explode ( ',' , $groupsList );
$newValue = json_encode ( $excludedGroups );
2015-11-19 17:35:58 +03:00
$config -> setAppValue ( 'core' , 'shareapi_exclude_groups_list' , $newValue );
2015-10-01 16:37:55 +03:00
}
2015-11-19 18:20:27 +03:00
$usersGroups = $groupManager -> getUserGroupIds ( $user );
2014-05-13 17:22:18 +04:00
if ( ! empty ( $usersGroups )) {
$remainingGroups = array_diff ( $usersGroups , $excludedGroups );
// if the user is only in groups which are disabled for sharing then
// sharing is also disabled for the user
if ( empty ( $remainingGroups )) {
return true ;
}
}
}
return false ;
}
2014-07-23 18:42:33 +04:00
/**
* check if share API enforces a default expire date
2014-08-19 20:01:26 +04:00
*
2014-07-23 18:42:33 +04:00
* @ return boolean
2017-07-19 20:44:10 +03:00
* @ suppress PhanDeprecatedFunction
2014-07-23 18:42:33 +04:00
*/
public static function isDefaultExpireDateEnforced () {
2018-01-13 16:25:04 +03:00
$isDefaultExpireDateEnabled = \OC :: $server -> getConfig () -> getAppValue ( 'core' , 'shareapi_default_expire_date' , 'no' );
2014-07-23 18:42:33 +04:00
$enforceDefaultExpireDate = false ;
if ( $isDefaultExpireDateEnabled === 'yes' ) {
2018-01-13 16:25:04 +03:00
$value = \OC :: $server -> getConfig () -> getAppValue ( 'core' , 'shareapi_enforce_expire_date' , 'no' );
2018-01-26 14:36:25 +03:00
$enforceDefaultExpireDate = $value === 'yes' ;
2014-07-23 18:42:33 +04:00
}
return $enforceDefaultExpireDate ;
}
2014-02-06 19:30:58 +04:00
/**
2014-04-21 17:44:54 +04:00
* Get the quota of a user
2014-08-19 20:01:26 +04:00
*
2020-03-04 19:20:27 +03:00
* @ param IUser | null $user
2017-07-19 20:44:10 +03:00
* @ return float Quota bytes
2014-02-06 19:30:58 +04:00
*/
2020-03-04 19:20:27 +03:00
public static function getUserQuota ( ? IUser $user ) {
2016-07-29 16:00:18 +03:00
if ( is_null ( $user )) {
return \OCP\Files\FileInfo :: SPACE_UNLIMITED ;
}
$userQuota = $user -> getQuota ();
2020-04-10 15:19:56 +03:00
if ( $userQuota === 'none' ) {
2014-08-19 18:45:22 +04:00
return \OCP\Files\FileInfo :: SPACE_UNLIMITED ;
2013-07-25 18:01:37 +04:00
}
2016-07-29 16:00:18 +03:00
return OC_Helper :: computerFileSize ( $userQuota );
2013-07-25 18:01:37 +04:00
}
2013-10-04 01:22:11 +04:00
/**
2014-08-29 16:36:00 +04:00
* copies the skeleton to the users / files
2014-08-19 20:01:26 +04:00
*
2018-11-15 13:51:28 +03:00
* @ param string $userId
2014-08-29 16:36:00 +04:00
* @ param \OCP\Files\Folder $userDirectory
2018-10-04 16:23:07 +03:00
* @ throws \OCP\Files\NotFoundException
* @ throws \OCP\Files\NotPermittedException
2017-07-19 20:44:10 +03:00
* @ suppress PhanDeprecatedFunction
2013-10-04 01:22:11 +04:00
*/
2015-06-16 17:02:30 +03:00
public static function copySkeleton ( $userId , \OCP\Files\Folder $userDirectory ) {
2017-11-29 11:50:40 +03:00
$plainSkeletonDirectory = \OC :: $server -> getConfig () -> getSystemValue ( 'skeletondirectory' , \OC :: $SERVERROOT . '/core/skeleton' );
$userLang = \OC :: $server -> getL10NFactory () -> findLanguage ();
$skeletonDirectory = str_replace ( '{lang}' , $userLang , $plainSkeletonDirectory );
if ( ! file_exists ( $skeletonDirectory )) {
$dialectStart = strpos ( $userLang , '_' );
if ( $dialectStart !== false ) {
$skeletonDirectory = str_replace ( '{lang}' , substr ( $userLang , 0 , $dialectStart ), $plainSkeletonDirectory );
}
if ( $dialectStart === false || ! file_exists ( $skeletonDirectory )) {
2017-12-08 14:28:41 +03:00
$skeletonDirectory = str_replace ( '{lang}' , 'default' , $plainSkeletonDirectory );
}
if ( ! file_exists ( $skeletonDirectory )) {
$skeletonDirectory = '' ;
2017-11-29 11:50:40 +03:00
}
}
2016-09-12 09:57:40 +03:00
$instanceId = \OC :: $server -> getConfig () -> getSystemValue ( 'instanceid' , '' );
if ( $instanceId === null ) {
throw new \RuntimeException ( 'no instance id!' );
}
$appdata = 'appdata_' . $instanceId ;
if ( $userId === $appdata ) {
throw new \RuntimeException ( 'username is reserved name: ' . $appdata );
}
2014-08-29 16:36:00 +04:00
2014-08-16 03:07:42 +04:00
if ( ! empty ( $skeletonDirectory )) {
2014-08-29 16:36:00 +04:00
\OCP\Util :: writeLog (
'files_skeleton' ,
2015-06-16 17:02:30 +03:00
'copying skeleton for ' . $userId . ' from ' . $skeletonDirectory . ' to ' . $userDirectory -> getFullPath ( '/' ),
2018-04-25 16:22:28 +03:00
ILogger :: DEBUG
2014-08-29 16:36:00 +04:00
);
self :: copyr ( $skeletonDirectory , $userDirectory );
// update the file cache
$userDirectory -> getStorage () -> getScanner () -> scan ( '' , \OC\Files\Cache\Scanner :: SCAN_RECURSIVE );
2014-08-16 03:07:42 +04:00
}
2013-10-04 01:22:11 +04:00
}
/**
2014-08-29 16:36:00 +04:00
* copies a directory recursively by using streams
2014-08-19 20:01:26 +04:00
*
2013-10-04 01:22:11 +04:00
* @ param string $source
2014-08-29 16:36:00 +04:00
* @ param \OCP\Files\Folder $target
2013-10-04 01:22:11 +04:00
* @ return void
*/
2014-08-29 16:36:00 +04:00
public static function copyr ( $source , \OCP\Files\Folder $target ) {
2016-09-25 19:58:05 +03:00
$logger = \OC :: $server -> getLogger ();
// Verify if folder exists
2013-10-04 01:22:11 +04:00
$dir = opendir ( $source );
2020-04-10 15:19:56 +03:00
if ( $dir === false ) {
2016-09-25 19:58:05 +03:00
$logger -> error ( sprintf ( 'Could not opendir "%s"' , $source ), [ 'app' => 'core' ]);
return ;
}
// Copy the files
2014-08-19 20:01:26 +04:00
while ( false !== ( $file = readdir ( $dir ))) {
if ( ! \OC\Files\Filesystem :: isIgnoredDir ( $file )) {
if ( is_dir ( $source . '/' . $file )) {
2014-08-29 16:36:00 +04:00
$child = $target -> newFolder ( $file );
self :: copyr ( $source . '/' . $file , $child );
2013-10-04 01:22:11 +04:00
} else {
2014-08-29 16:36:00 +04:00
$child = $target -> newFile ( $file );
2016-09-25 19:58:05 +03:00
$sourceStream = fopen ( $source . '/' . $file , 'r' );
2020-04-10 15:19:56 +03:00
if ( $sourceStream === false ) {
2016-09-25 19:58:05 +03:00
$logger -> error ( sprintf ( 'Could not fopen "%s"' , $source . '/' . $file ), [ 'app' => 'core' ]);
closedir ( $dir );
return ;
}
stream_copy_to_stream ( $sourceStream , $child -> fopen ( 'w' ));
2013-10-04 01:22:11 +04:00
}
}
}
closedir ( $dir );
}
2013-08-15 10:49:19 +04:00
/**
* @ return void
2017-07-19 20:44:10 +03:00
* @ suppress PhanUndeclaredMethod
2013-08-18 12:33:09 +04:00
*/
2012-09-07 17:22:01 +04:00
public static function tearDownFS () {
2012-10-10 15:18:36 +04:00
\OC\Files\Filesystem :: tearDown ();
2016-08-25 16:49:36 +03:00
\OC :: $server -> getRootFolder () -> clearCache ();
2014-08-19 20:01:26 +04:00
self :: $fsSetup = false ;
self :: $rootMounted = false ;
2011-07-27 21:07:28 +04:00
}
2012-10-28 16:45:37 +04:00
2011-07-27 21:07:28 +04:00
/**
2014-05-19 19:50:53 +04:00
* get the current installed version of ownCloud
2014-08-19 20:01:26 +04:00
*
2011-07-27 21:07:28 +04:00
* @ return array
*/
2012-09-07 17:22:01 +04:00
public static function getVersion () {
2013-09-28 01:41:24 +04:00
OC_Util :: loadVersion ();
2016-11-15 19:51:03 +03:00
return self :: $versionCache [ 'OC_Version' ];
2011-09-28 15:52:26 +04:00
}
/**
2014-05-19 19:50:53 +04:00
* get the current installed version string of ownCloud
2014-08-19 20:01:26 +04:00
*
2011-09-28 15:52:26 +04:00
* @ return string
*/
2012-09-07 17:22:01 +04:00
public static function getVersionString () {
2013-09-28 01:41:24 +04:00
OC_Util :: loadVersion ();
2016-11-15 19:51:03 +03:00
return self :: $versionCache [ 'OC_VersionString' ];
2011-07-27 21:07:28 +04:00
}
2012-07-24 02:39:59 +04:00
/**
2016-09-06 15:11:30 +03:00
* @ deprecated the value is of no use anymore
2012-07-24 02:39:59 +04:00
* @ return string
*/
2012-09-07 17:22:01 +04:00
public static function getEditionString () {
2016-09-06 15:11:30 +03:00
return '' ;
2013-09-28 01:41:24 +04:00
}
/**
* @ description get the update channel of the current installed of ownCloud .
* @ return string
*/
public static function getChannel () {
OC_Util :: loadVersion ();
2016-11-29 13:28:04 +03:00
return \OC :: $server -> getConfig () -> getSystemValue ( 'updater.release.channel' , self :: $versionCache [ 'OC_Channel' ]);
2013-09-28 01:41:24 +04:00
}
2013-10-02 12:11:18 +04:00
2013-09-28 01:41:24 +04:00
/**
* @ description get the build number of the current installed of ownCloud .
* @ return string
*/
public static function getBuild () {
OC_Util :: loadVersion ();
2016-11-15 19:51:03 +03:00
return self :: $versionCache [ 'OC_Build' ];
2013-09-28 01:41:24 +04:00
}
/**
* @ description load the version . php into the session as cache
2017-07-19 20:44:10 +03:00
* @ suppress PhanUndeclaredVariable
2013-09-28 01:41:24 +04:00
*/
private static function loadVersion () {
2016-11-15 19:51:03 +03:00
if ( self :: $versionCache !== null ) {
return ;
}
2014-08-19 20:01:26 +04:00
$timestamp = filemtime ( OC :: $SERVERROOT . '/version.php' );
2016-11-15 19:51:03 +03:00
require OC :: $SERVERROOT . '/version.php' ;
2020-08-17 18:16:50 +03:00
/** @var int $timestamp */
2016-11-15 19:51:03 +03:00
self :: $versionCache [ 'OC_Version_Timestamp' ] = $timestamp ;
2020-08-17 18:16:50 +03:00
/** @var string $OC_Version */
2016-11-15 19:51:03 +03:00
self :: $versionCache [ 'OC_Version' ] = $OC_Version ;
2020-08-17 18:16:50 +03:00
/** @var string $OC_VersionString */
2016-11-15 19:51:03 +03:00
self :: $versionCache [ 'OC_VersionString' ] = $OC_VersionString ;
2020-08-17 18:16:50 +03:00
/** @var string $OC_Build */
2016-11-15 19:51:03 +03:00
self :: $versionCache [ 'OC_Build' ] = $OC_Build ;
2016-11-15 20:10:17 +03:00
2020-08-17 18:16:50 +03:00
/** @var string $OC_Channel */
2016-11-15 20:10:17 +03:00
self :: $versionCache [ 'OC_Channel' ] = $OC_Channel ;
2012-07-24 02:39:59 +04:00
}
2012-04-01 13:20:12 +04:00
2011-07-27 21:07:28 +04:00
/**
2014-11-03 13:18:17 +03:00
* generates a path for JS / CSS files . If no application is provided it will create the path for core .
2011-07-27 21:07:28 +04:00
*
2014-12-10 17:41:38 +03:00
* @ param string $application application to get the files from
2016-04-07 20:51:27 +03:00
* @ param string $directory directory within this application ( css , js , vendor , etc )
2014-12-10 17:41:38 +03:00
* @ param string $file the file inside of the above folder
2014-11-03 13:18:17 +03:00
* @ return string the path
2011-07-27 21:07:28 +04:00
*/
2014-11-03 13:18:17 +03:00
private static function generatePath ( $application , $directory , $file ) {
2014-08-19 20:01:26 +04:00
if ( is_null ( $file )) {
2011-07-27 21:07:28 +04:00
$file = $application ;
$application = " " ;
}
2014-08-19 20:01:26 +04:00
if ( ! empty ( $application )) {
2014-11-03 13:18:17 +03:00
return " $application / $directory / $file " ;
2013-08-15 10:49:19 +04:00
} else {
2014-11-03 13:18:17 +03:00
return " $directory / $file " ;
2011-07-27 21:07:28 +04:00
}
}
2014-11-03 13:18:17 +03:00
/**
* add a javascript file
*
* @ param string $application application id
* @ param string | null $file filename
2015-09-17 10:14:04 +03:00
* @ param bool $prepend prepend the Script to the beginning of the list
2014-11-03 13:18:17 +03:00
* @ return void
*/
2015-09-17 10:14:04 +03:00
public static function addScript ( $application , $file = null , $prepend = false ) {
2014-12-10 17:41:38 +03:00
$path = OC_Util :: generatePath ( $application , 'js' , $file );
2015-09-30 07:09:29 +03:00
// core js files need separate handling
if ( $application !== 'core' && $file !== null ) {
2020-04-09 17:07:47 +03:00
self :: addTranslations ( $application );
2014-12-10 17:41:38 +03:00
}
2015-09-30 07:09:29 +03:00
self :: addExternalResource ( $application , $prepend , $path , " script " );
2014-11-03 13:18:17 +03:00
}
/**
* add a javascript file from the vendor sub folder
*
* @ param string $application application id
* @ param string | null $file filename
2015-09-17 10:14:04 +03:00
* @ param bool $prepend prepend the Script to the beginning of the list
2014-11-03 13:18:17 +03:00
* @ return void
*/
2015-09-17 10:14:04 +03:00
public static function addVendorScript ( $application , $file = null , $prepend = false ) {
2014-12-10 17:41:38 +03:00
$path = OC_Util :: generatePath ( $application , 'vendor' , $file );
2015-09-30 07:09:29 +03:00
self :: addExternalResource ( $application , $prepend , $path , " script " );
2014-11-03 13:18:17 +03:00
}
2014-10-17 21:47:37 +04:00
/**
* add a translation JS file
*
* @ param string $application application id
2017-07-19 20:44:10 +03:00
* @ param string | null $languageCode language code , defaults to the current language
* @ param bool | null $prepend prepend the Script to the beginning of the list
2014-10-17 21:47:37 +04:00
*/
2015-09-17 10:14:04 +03:00
public static function addTranslations ( $application , $languageCode = null , $prepend = false ) {
2014-10-17 21:47:37 +04:00
if ( is_null ( $languageCode )) {
2016-10-28 22:46:28 +03:00
$languageCode = \OC :: $server -> getL10NFactory () -> findLanguage ( $application );
2014-10-17 21:47:37 +04:00
}
if ( ! empty ( $application )) {
2014-12-10 17:41:38 +03:00
$path = " $application /l10n/ $languageCode " ;
2014-10-17 21:47:37 +04:00
} else {
2014-12-10 17:41:38 +03:00
$path = " l10n/ $languageCode " ;
}
2015-09-30 07:09:29 +03:00
self :: addExternalResource ( $application , $prepend , $path , " script " );
2014-10-17 21:47:37 +04:00
}
2011-07-27 21:07:28 +04:00
/**
2014-05-19 19:50:53 +04:00
* add a css file
2011-07-27 21:07:28 +04:00
*
2014-10-17 21:47:37 +04:00
* @ param string $application application id
2014-02-19 12:31:54 +04:00
* @ param string | null $file filename
2015-09-25 12:56:55 +03:00
* @ param bool $prepend prepend the Style to the beginning of the list
2013-08-15 10:49:19 +04:00
* @ return void
2011-07-27 21:07:28 +04:00
*/
2015-09-25 12:56:55 +03:00
public static function addStyle ( $application , $file = null , $prepend = false ) {
2014-12-10 17:41:38 +03:00
$path = OC_Util :: generatePath ( $application , 'css' , $file );
2015-09-30 07:09:29 +03:00
self :: addExternalResource ( $application , $prepend , $path , " style " );
2014-11-03 13:18:17 +03:00
}
/**
* add a css file from the vendor sub folder
*
* @ param string $application application id
* @ param string | null $file filename
2015-09-25 12:56:55 +03:00
* @ param bool $prepend prepend the Style to the beginning of the list
2014-11-03 13:18:17 +03:00
* @ return void
*/
2015-09-25 12:56:55 +03:00
public static function addVendorStyle ( $application , $file = null , $prepend = false ) {
2014-12-10 17:41:38 +03:00
$path = OC_Util :: generatePath ( $application , 'vendor' , $file );
2015-09-30 07:09:29 +03:00
self :: addExternalResource ( $application , $prepend , $path , " style " );
}
/**
* add an external resource css / js file
*
* @ param string $application application id
* @ param bool $prepend prepend the file to the beginning of the list
2016-10-01 13:17:55 +03:00
* @ param string $path
2015-09-30 07:09:29 +03:00
* @ param string $type ( script or style )
* @ return void
*/
private static function addExternalResource ( $application , $prepend , $path , $type = " script " ) {
if ( $type === " style " ) {
if ( ! in_array ( $path , self :: $styles )) {
if ( $prepend === true ) {
2020-04-09 17:07:47 +03:00
array_unshift ( self :: $styles , $path );
2015-09-30 07:09:29 +03:00
} else {
self :: $styles [] = $path ;
}
}
} elseif ( $type === " script " ) {
if ( ! in_array ( $path , self :: $scripts )) {
if ( $prepend === true ) {
2020-04-09 17:07:47 +03:00
array_unshift ( self :: $scripts , $path );
2015-09-30 07:09:29 +03:00
} else {
self :: $scripts [] = $path ;
}
}
2014-12-10 17:41:38 +03:00
}
2011-07-27 21:07:28 +04:00
}
/**
2014-05-19 19:50:53 +04:00
* Add a custom element to the header
2014-10-28 13:15:58 +03:00
* If $text is null then the element will be written as empty element .
* So use " " to get a closing tag .
2013-08-23 09:30:42 +04:00
* @ param string $tag tag name of the element
2012-02-08 01:33:01 +04:00
* @ param array $attributes array of attributes for the element
2011-07-27 21:07:28 +04:00
* @ param string $text the text content for the element
2018-07-04 12:19:45 +03:00
* @ param bool $prepend prepend the header to the beginning of the list
2011-07-27 21:07:28 +04:00
*/
2018-07-04 12:19:45 +03:00
public static function addHeader ( $tag , $attributes , $text = null , $prepend = false ) {
2020-03-26 11:30:18 +03:00
$header = [
2014-08-19 20:01:26 +04:00
'tag' => $tag ,
'attributes' => $attributes ,
'text' => $text
2020-03-26 11:30:18 +03:00
];
2018-07-04 12:19:45 +03:00
if ( $prepend === true ) {
2020-04-09 17:05:56 +03:00
array_unshift ( self :: $headers , $header );
2018-07-04 12:19:45 +03:00
} else {
self :: $headers [] = $header ;
}
2011-07-27 21:07:28 +04:00
}
/**
2014-05-19 19:50:53 +04:00
* check if the current server configuration is suitable for ownCloud
2014-08-19 20:01:26 +04:00
*
2017-03-18 01:37:48 +03:00
* @ param \OC\SystemConfig $config
2011-07-27 21:07:28 +04:00
* @ return array arrays with error messages and hints
*/
2017-03-18 01:37:48 +03:00
public static function checkServer ( \OC\SystemConfig $config ) {
2014-08-31 12:05:59 +04:00
$l = \OC :: $server -> getL10N ( 'lib' );
2020-03-26 11:30:18 +03:00
$errors = [];
2017-03-18 01:37:48 +03:00
$CONFIG_DATADIRECTORY = $config -> getValue ( 'datadirectory' , OC :: $SERVERROOT . '/data' );
2014-03-14 16:03:18 +04:00
2017-03-18 01:37:48 +03:00
if ( ! self :: needUpgrade ( $config ) && $config -> getValue ( 'installed' , false )) {
2014-03-14 16:03:18 +04:00
// this check needs to be done every time
$errors = self :: checkDataDirectoryValidity ( $CONFIG_DATADIRECTORY );
}
2013-08-15 13:58:09 +04:00
// Assume that if checkServer() succeeded before in this session, then all is fine.
2014-07-16 21:40:22 +04:00
if ( \OC :: $server -> getSession () -> exists ( 'checkServer_succeeded' ) && \OC :: $server -> getSession () -> get ( 'checkServer_succeeded' )) {
2014-03-14 16:03:18 +04:00
return $errors ;
2013-08-15 10:49:19 +04:00
}
2013-08-15 13:58:09 +04:00
2013-08-15 10:49:19 +04:00
$webServerRestart = false ;
2017-11-24 12:27:58 +03:00
$setup = new \OC\Setup (
$config ,
2020-08-20 15:08:18 +03:00
\OC :: $server -> get ( IniGetWrapper :: class ),
2017-11-24 12:27:58 +03:00
\OC :: $server -> getL10N ( 'lib' ),
\OC :: $server -> query ( \OCP\Defaults :: class ),
\OC :: $server -> getLogger (),
\OC :: $server -> getSecureRandom (),
\OC :: $server -> query ( \OC\Installer :: class )
);
2015-11-26 12:48:08 +03:00
$urlGenerator = \OC :: $server -> getURLGenerator ();
2014-10-27 14:51:26 +03:00
$availableDatabases = $setup -> getSupportedDatabases ();
if ( empty ( $availableDatabases )) {
2020-03-26 11:30:18 +03:00
$errors [] = [
2014-08-19 20:01:26 +04:00
'error' => $l -> t ( 'No database drivers (sqlite, mysql, or postgresql) installed.' ),
'hint' => '' //TODO: sane hint
2020-03-26 11:30:18 +03:00
];
2013-08-15 10:49:19 +04:00
$webServerRestart = true ;
2011-07-27 21:07:28 +04:00
}
2012-06-20 00:12:05 +04:00
// Check if config folder is writable.
2020-04-10 15:19:56 +03:00
if ( ! OC_Helper :: isReadOnlyConfigEnabled ()) {
2015-12-09 10:54:11 +03:00
if ( ! is_writable ( OC :: $configDir ) or ! is_readable ( OC :: $configDir )) {
2020-03-26 11:30:18 +03:00
$errors [] = [
2015-12-09 10:54:11 +03:00
'error' => $l -> t ( 'Cannot write into "config" directory' ),
2017-05-09 05:16:08 +03:00
'hint' => $l -> t ( 'This can usually be fixed by giving the webserver write access to the config directory. See %s' ,
2017-10-28 01:54:25 +03:00
[ $urlGenerator -> linkToDocs ( 'admin-dir_permissions' ) ]) . '. '
. $l -> t ( 'Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it. See %s' ,
2020-04-09 17:07:47 +03:00
[ $urlGenerator -> linkToDocs ( 'admin-config' ) ])
2020-03-26 11:30:18 +03:00
];
2015-12-09 10:54:11 +03:00
}
2012-06-20 00:12:05 +04:00
}
2012-06-21 23:35:34 +04:00
// Check if there is a writable install folder.
2017-03-18 01:37:48 +03:00
if ( $config -> getValue ( 'appstoreenabled' , true )) {
2014-08-19 20:01:26 +04:00
if ( OC_App :: getInstallPath () === null
2013-02-11 20:44:02 +04:00
|| ! is_writable ( OC_App :: getInstallPath ())
2014-08-19 20:01:26 +04:00
|| ! is_readable ( OC_App :: getInstallPath ())
) {
2020-03-26 11:30:18 +03:00
$errors [] = [
2014-05-29 03:21:54 +04:00
'error' => $l -> t ( 'Cannot write into "apps" directory' ),
2017-05-09 05:16:08 +03:00
'hint' => $l -> t ( 'This can usually be fixed by giving the webserver write access to the apps directory'
2020-03-28 18:17:21 +03:00
. ' or disabling the appstore in the config file.' )
2020-03-26 11:30:18 +03:00
];
2012-06-21 23:35:34 +04:00
}
2012-06-20 00:12:05 +04:00
}
// Create root dir.
2017-03-18 01:37:48 +03:00
if ( $config -> getValue ( 'installed' , false )) {
2014-09-08 17:05:57 +04:00
if ( ! is_dir ( $CONFIG_DATADIRECTORY )) {
$success = @ mkdir ( $CONFIG_DATADIRECTORY );
if ( $success ) {
$errors = array_merge ( $errors , self :: checkDataDirectoryPermissions ( $CONFIG_DATADIRECTORY ));
} else {
2016-11-15 13:41:33 +03:00
$errors [] = [
'error' => $l -> t ( 'Cannot create "data" directory' ),
2017-05-09 05:16:08 +03:00
'hint' => $l -> t ( 'This can usually be fixed by giving the webserver write access to the root directory. See %s' ,
2016-11-15 13:41:33 +03:00
[ $urlGenerator -> linkToDocs ( 'admin-dir_permissions' )])
];
2014-09-08 17:05:57 +04:00
}
2020-04-10 11:35:09 +03:00
} elseif ( ! is_writable ( $CONFIG_DATADIRECTORY ) or ! is_readable ( $CONFIG_DATADIRECTORY )) {
2018-12-22 20:14:55 +03:00
// is_writable doesn't work for NFS mounts, so try to write a file and check if it exists.
$testFile = sprintf ( '%s/%s.tmp' , $CONFIG_DATADIRECTORY , uniqid ( 'data_dir_writability_test_' ));
$handle = fopen ( $testFile , 'w' );
2020-03-25 23:53:04 +03:00
if ( ! $handle || fwrite ( $handle , 'Test write operation' ) === false ) {
2018-12-22 20:14:55 +03:00
$permissionsHint = $l -> t ( 'Permissions can usually be fixed by giving the webserver write access to the root directory. See %s.' ,
[ $urlGenerator -> linkToDocs ( 'admin-dir_permissions' )]);
$errors [] = [
'error' => 'Your data directory is not writable' ,
'hint' => $permissionsHint
];
} else {
fclose ( $handle );
unlink ( $testFile );
}
2014-09-08 17:05:57 +04:00
} else {
$errors = array_merge ( $errors , self :: checkDataDirectoryPermissions ( $CONFIG_DATADIRECTORY ));
2012-06-20 00:12:05 +04:00
}
2011-07-27 21:07:28 +04:00
}
2013-08-15 10:49:19 +04:00
2014-08-19 20:01:26 +04:00
if ( ! OC_Util :: isSetLocaleWorking ()) {
2020-03-26 11:30:18 +03:00
$errors [] = [
2014-05-29 03:21:54 +04:00
'error' => $l -> t ( 'Setting locale to %s failed' ,
2020-03-26 11:30:18 +03:00
[ 'en_US.UTF-8/fr_FR.UTF-8/es_ES.UTF-8/de_DE.UTF-8/ru_RU.UTF-8/'
. 'pt_BR.UTF-8/it_IT.UTF-8/ja_JP.UTF-8/zh_CN.UTF-8' ]),
2014-08-18 17:59:36 +04:00
'hint' => $l -> t ( 'Please install one of these locales on your system and restart your webserver.' )
2020-03-26 11:30:18 +03:00
];
2013-11-08 17:30:08 +04:00
}
2014-09-15 15:46:43 +04:00
// Contains the dependencies that should be checked against
// classes = class_exists
// functions = function_exists
// defined = defined
2015-02-21 14:12:34 +03:00
// ini = ini_get
2014-09-15 15:46:43 +04:00
// If the dependency is not found the missing module name is shown to the EndUser
2015-02-27 12:23:20 +03:00
// When adding new checks always verify that they pass on Travis as well
// for ini settings, see https://github.com/owncloud/administration/blob/master/travis-ci/custom.ini
2020-03-26 11:30:18 +03:00
$dependencies = [
'classes' => [
2014-09-15 15:46:43 +04:00
'ZipArchive' => 'zip' ,
'DOMDocument' => 'dom' ,
2016-03-09 13:11:00 +03:00
'XMLWriter' => 'XMLWriter' ,
'XMLReader' => 'XMLReader' ,
2020-03-26 11:30:18 +03:00
],
2015-03-12 20:39:54 +03:00
'functions' => [
2014-09-15 15:46:43 +04:00
'xml_parser_create' => 'libxml' ,
2018-12-04 19:22:11 +03:00
'mb_strcut' => 'mbstring' ,
2014-09-15 15:46:43 +04:00
'ctype_digit' => 'ctype' ,
'json_encode' => 'JSON' ,
'gd_info' => 'GD' ,
'gzencode' => 'zlib' ,
'iconv' => 'iconv' ,
2014-12-28 15:23:34 +03:00
'simplexml_load_string' => 'SimpleXML' ,
2015-03-12 20:39:54 +03:00
'hash' => 'HASH Message Digest Framework' ,
'curl_init' => 'cURL' ,
2016-10-31 13:07:54 +03:00
'openssl_verify' => 'OpenSSL' ,
2015-03-12 20:39:54 +03:00
],
2020-03-26 11:30:18 +03:00
'defined' => [
2014-09-15 15:46:43 +04:00
'PDO::ATTR_DRIVER_NAME' => 'PDO'
2020-03-26 11:30:18 +03:00
],
2015-02-21 14:12:34 +03:00
'ini' => [
2015-02-25 01:34:38 +03:00
'default_charset' => 'UTF-8' ,
2015-02-21 14:12:34 +03:00
],
2020-03-26 11:30:18 +03:00
];
$missingDependencies = [];
2015-02-21 14:12:34 +03:00
$invalidIniSettings = [];
2014-09-15 15:46:43 +04:00
2020-08-20 15:08:18 +03:00
$iniWrapper = \OC :: $server -> get ( IniGetWrapper :: class );
2018-10-03 23:07:51 +03:00
foreach ( $dependencies [ 'classes' ] as $class => $module ) {
if ( ! class_exists ( $class )) {
$missingDependencies [] = $module ;
2014-09-15 15:46:43 +04:00
}
2018-10-03 23:07:51 +03:00
}
foreach ( $dependencies [ 'functions' ] as $function => $module ) {
if ( ! function_exists ( $function )) {
$missingDependencies [] = $module ;
2015-02-21 14:12:34 +03:00
}
2018-10-03 23:07:51 +03:00
}
foreach ( $dependencies [ 'defined' ] as $defined => $module ) {
if ( ! defined ( $defined )) {
$missingDependencies [] = $module ;
2015-02-21 14:12:34 +03:00
}
2018-10-03 23:07:51 +03:00
}
foreach ( $dependencies [ 'ini' ] as $setting => $expected ) {
if ( is_bool ( $expected )) {
if ( $iniWrapper -> getBool ( $setting ) !== $expected ) {
$invalidIniSettings [] = [ $setting , $expected ];
2015-02-28 12:08:41 +03:00
}
2018-10-03 23:07:51 +03:00
}
if ( is_int ( $expected )) {
if ( $iniWrapper -> getNumeric ( $setting ) !== $expected ) {
$invalidIniSettings [] = [ $setting , $expected ];
2015-02-28 12:08:41 +03:00
}
2018-10-03 23:07:51 +03:00
}
if ( is_string ( $expected )) {
if ( strtolower ( $iniWrapper -> getString ( $setting )) !== strtolower ( $expected )) {
$invalidIniSettings [] = [ $setting , $expected ];
2015-02-25 01:34:38 +03:00
}
}
2015-02-21 14:12:34 +03:00
}
2014-09-15 15:46:43 +04:00
2020-04-10 15:19:56 +03:00
foreach ( $missingDependencies as $missingDependency ) {
2020-03-26 11:30:18 +03:00
$errors [] = [
'error' => $l -> t ( 'PHP module %s not installed.' , [ $missingDependency ]),
2020-07-08 16:12:01 +03:00
'hint' => $l -> t ( 'Please ask your server administrator to install the module.' ),
2020-03-26 11:30:18 +03:00
];
2013-08-15 10:49:19 +04:00
$webServerRestart = true ;
2012-10-06 19:37:38 +04:00
}
2020-04-10 15:19:56 +03:00
foreach ( $invalidIniSettings as $setting ) {
if ( is_bool ( $setting [ 1 ])) {
2018-01-27 01:46:40 +03:00
$setting [ 1 ] = $setting [ 1 ] ? 'on' : 'off' ;
2015-02-23 11:40:15 +03:00
}
2015-02-21 14:12:34 +03:00
$errors [] = [
2015-02-23 11:40:15 +03:00
'error' => $l -> t ( 'PHP setting "%s" is not set to "%s".' , [ $setting [ 0 ], var_export ( $setting [ 1 ], true )]),
2020-10-05 16:12:57 +03:00
'hint' => $l -> t ( 'Adjusting this setting in php.ini will make Nextcloud run again' )
2015-02-21 14:12:34 +03:00
];
$webServerRestart = true ;
}
2014-09-15 15:46:43 +04:00
2015-05-04 17:14:12 +03:00
/**
* The mbstring . func_overload check can only be performed if the mbstring
* module is installed as it will return null if the checking setting is
* not available and thus a check on the boolean value fails .
*
* TODO : Should probably be implemented in the above generic dependency
* check somehow in the long - term .
*/
2020-04-10 15:19:56 +03:00
if ( $iniWrapper -> getBool ( 'mbstring.func_overload' ) !== null &&
2015-05-04 17:14:12 +03:00
$iniWrapper -> getBool ( 'mbstring.func_overload' ) === true ) {
2020-03-26 11:30:18 +03:00
$errors [] = [
2015-05-19 22:15:22 +03:00
'error' => $l -> t ( 'mbstring.func_overload is set to "%s" instead of the expected value "0"' , [ $iniWrapper -> getString ( 'mbstring.func_overload' )]),
2015-05-04 17:14:12 +03:00
'hint' => $l -> t ( 'To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini' )
2020-03-26 11:30:18 +03:00
];
2015-05-04 17:14:12 +03:00
}
2020-04-10 15:19:56 +03:00
if ( function_exists ( 'xml_parser_create' ) &&
2020-04-09 17:07:47 +03:00
LIBXML_LOADED_VERSION < 20700 ) {
2016-07-27 18:33:22 +03:00
$version = LIBXML_LOADED_VERSION ;
2020-10-05 16:12:57 +03:00
$major = floor ( $version / 10000 );
2016-07-27 18:33:22 +03:00
$version -= ( $major * 10000 );
2020-10-05 16:12:57 +03:00
$minor = floor ( $version / 100 );
2016-07-27 18:33:22 +03:00
$version -= ( $minor * 100 );
$patch = $version ;
2020-03-26 11:30:18 +03:00
$errors [] = [
2016-07-27 18:33:22 +03:00
'error' => $l -> t ( 'libxml2 2.7.0 is at least required. Currently %s is installed.' , [ $major . '.' . $minor . '.' . $patch ]),
2016-03-13 00:13:05 +03:00
'hint' => $l -> t ( 'To fix this issue update your libxml2 version and restart your web server.' )
2020-03-26 11:30:18 +03:00
];
2016-03-13 00:13:05 +03:00
}
2014-05-19 23:51:35 +04:00
if ( ! self :: isAnnotationsWorking ()) {
2020-03-26 11:30:18 +03:00
$errors [] = [
2015-05-19 22:15:22 +03:00
'error' => $l -> t ( 'PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible.' ),
2015-01-22 16:52:47 +03:00
'hint' => $l -> t ( 'This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator.' )
2020-03-26 11:30:18 +03:00
];
2014-05-19 23:51:35 +04:00
}
2012-09-12 01:51:12 +04:00
2015-03-11 00:59:23 +03:00
if ( ! \OC :: $CLI && $webServerRestart ) {
2020-03-26 11:30:18 +03:00
$errors [] = [
2014-08-19 20:01:26 +04:00
'error' => $l -> t ( 'PHP modules have been installed, but they are still listed as missing?' ),
'hint' => $l -> t ( 'Please ask your server administrator to restart the web server.' )
2020-03-26 11:30:18 +03:00
];
2012-06-01 22:00:33 +04:00
}
2011-07-27 21:07:28 +04:00
2014-03-15 16:28:20 +04:00
$errors = array_merge ( $errors , self :: checkDatabaseVersion ());
2013-08-15 13:58:09 +04:00
// Cache the result of this function
2014-07-16 21:40:22 +04:00
\OC :: $server -> getSession () -> set ( 'checkServer_succeeded' , count ( $errors ) == 0 );
2013-08-15 13:58:09 +04:00
2011-07-27 21:07:28 +04:00
return $errors ;
}
2011-09-18 23:31:56 +04:00
2014-03-15 16:28:20 +04:00
/**
* Check the database version
2014-08-19 20:01:26 +04:00
*
2014-03-15 16:28:20 +04:00
* @ return array errors array
*/
public static function checkDatabaseVersion () {
2014-08-31 12:05:59 +04:00
$l = \OC :: $server -> getL10N ( 'lib' );
2020-03-26 11:30:18 +03:00
$errors = [];
2015-12-18 13:42:09 +03:00
$dbType = \OC :: $server -> getSystemConfig () -> getValue ( 'dbtype' , 'sqlite' );
2014-03-15 16:28:20 +04:00
if ( $dbType === 'pgsql' ) {
// check PostgreSQL version
try {
$result = \OC_DB :: executeAudited ( 'SHOW SERVER_VERSION' );
$data = $result -> fetchRow ();
2020-11-05 12:50:53 +03:00
$result -> closeCursor ();
2014-03-15 16:28:20 +04:00
if ( isset ( $data [ 'server_version' ])) {
$version = $data [ 'server_version' ];
2019-07-31 01:53:20 +03:00
if ( version_compare ( $version , '9.0.0' , '<' )) {
2020-03-26 11:30:18 +03:00
$errors [] = [
2019-07-31 01:53:20 +03:00
'error' => $l -> t ( 'PostgreSQL >= 9 required' ),
2014-05-29 03:21:54 +04:00
'hint' => $l -> t ( 'Please upgrade your database version' )
2020-03-26 11:30:18 +03:00
];
2014-03-15 16:28:20 +04:00
}
}
2014-03-26 02:17:00 +04:00
} catch ( \Doctrine\DBAL\DBALException $e ) {
2015-11-16 15:11:32 +03:00
$logger = \OC :: $server -> getLogger ();
$logger -> warning ( 'Error occurred while checking PostgreSQL version, assuming >= 9' );
$logger -> logException ( $e );
2014-03-15 16:28:20 +04:00
}
}
return $errors ;
}
2013-01-19 08:30:56 +04:00
/**
2014-05-19 19:50:53 +04:00
* Check for correct file permissions of data directory
2014-08-19 20:01:26 +04:00
*
2014-02-06 19:30:58 +04:00
* @ param string $dataDirectory
2013-08-23 09:30:42 +04:00
* @ return array arrays with error messages and hints
*/
2013-01-19 08:30:56 +04:00
public static function checkDataDirectoryPermissions ( $dataDirectory ) {
2020-04-10 15:19:56 +03:00
if ( \OC :: $server -> getConfig () -> getSystemValue ( 'check_data_directory_permissions' , true ) === false ) {
2017-11-30 13:16:00 +03:00
return [];
}
2020-07-08 22:47:16 +03:00
2016-07-08 16:55:17 +03:00
$perms = substr ( decoct ( @ fileperms ( $dataDirectory )), - 3 );
2017-04-10 12:13:46 +03:00
if ( substr ( $perms , - 1 ) !== '0' ) {
2016-07-08 16:55:17 +03:00
chmod ( $dataDirectory , 0770 );
clearstatcache ();
2013-08-15 10:49:19 +04:00
$perms = substr ( decoct ( @ fileperms ( $dataDirectory )), - 3 );
2017-04-10 12:13:46 +03:00
if ( $perms [ 2 ] !== '0' ) {
2020-07-08 22:47:16 +03:00
$l = \OC :: $server -> getL10N ( 'lib' );
2020-07-09 10:29:44 +03:00
return [[
2017-04-10 12:13:46 +03:00
'error' => $l -> t ( 'Your data directory is readable by other users' ),
2020-07-08 22:47:16 +03:00
'hint' => $l -> t ( 'Please change the permissions to 0770 so that the directory cannot be listed by other users.' ),
2020-07-09 10:29:44 +03:00
]];
2013-01-19 08:30:56 +04:00
}
}
2020-07-08 22:47:16 +03:00
return [];
2013-01-19 08:30:56 +04:00
}
2014-03-14 16:03:18 +04:00
/**
* Check that the data directory exists and is valid by
* checking the existence of the " .ocdata " file .
*
* @ param string $dataDirectory data directory path
2015-03-28 02:27:21 +03:00
* @ return array errors found
2014-03-14 16:03:18 +04:00
*/
public static function checkDataDirectoryValidity ( $dataDirectory ) {
2014-08-31 12:05:59 +04:00
$l = \OC :: $server -> getL10N ( 'lib' );
2015-03-28 02:27:21 +03:00
$errors = [];
2016-07-08 16:55:17 +03:00
if ( $dataDirectory [ 0 ] !== '/' ) {
2015-03-28 02:27:21 +03:00
$errors [] = [
2017-04-10 12:13:46 +03:00
'error' => $l -> t ( 'Your data directory must be an absolute path' ),
2015-03-28 02:27:21 +03:00
'hint' => $l -> t ( 'Check the value of "datadirectory" in your configuration' )
];
}
2014-08-19 20:01:26 +04:00
if ( ! file_exists ( $dataDirectory . '/.ocdata' )) {
2015-03-28 02:27:21 +03:00
$errors [] = [
2017-04-18 10:53:02 +03:00
'error' => $l -> t ( 'Your data directory is invalid' ),
2017-05-30 11:29:18 +03:00
'hint' => $l -> t ( 'Ensure there is a file called ".ocdata"' .
' in the root of the data directory.' )
2015-03-28 02:27:21 +03:00
];
2014-03-14 16:03:18 +04:00
}
return $errors ;
}
2011-09-18 23:31:56 +04:00
/**
2013-01-03 02:02:38 +04:00
* Check if the user is logged in , redirects to home if not . With
* redirect URL parameter to the request URI .
2014-08-19 20:01:26 +04:00
*
2013-08-15 10:49:19 +04:00
* @ return void
2013-01-03 02:02:38 +04:00
*/
2012-09-07 17:22:01 +04:00
public static function checkLoggedIn () {
2011-09-18 23:31:56 +04:00
// Check if we are a user
2017-03-02 18:52:05 +03:00
if ( ! \OC :: $server -> getUserSession () -> isLoggedIn ()) {
2016-06-21 17:14:51 +03:00
header ( 'Location: ' . \OC :: $server -> getURLGenerator () -> linkToRoute (
'core.login.showLoginForm' ,
[
2016-11-09 18:14:46 +03:00
'redirect_url' => \OC :: $server -> getRequest () -> getRequestUri (),
2016-06-21 17:14:51 +03:00
]
)
2015-02-10 15:02:48 +03:00
);
2011-09-18 23:31:56 +04:00
exit ();
}
2017-04-03 15:29:24 +03:00
// Redirect to 2FA challenge selection if 2FA challenge was not solved yet
2016-08-24 11:42:07 +03:00
if ( \OC :: $server -> getTwoFactorAuthManager () -> needsSecondFactor ( \OC :: $server -> getUserSession () -> getUser ())) {
2017-04-03 15:29:24 +03:00
header ( 'Location: ' . \OC :: $server -> getURLGenerator () -> linkToRoute ( 'core.TwoFactorChallenge.selectChallenge' ));
2016-06-10 10:52:52 +03:00
exit ();
}
2011-09-18 23:31:56 +04:00
}
/**
2014-05-19 19:50:53 +04:00
* Check if the user is a admin , redirects to home if not
2014-08-19 20:01:26 +04:00
*
2013-08-15 10:49:19 +04:00
* @ return void
2013-01-03 02:02:38 +04:00
*/
2012-09-07 17:22:01 +04:00
public static function checkAdminUser () {
2013-10-31 01:59:31 +04:00
OC_Util :: checkLoggedIn ();
2014-08-19 20:01:26 +04:00
if ( ! OC_User :: isAdminUser ( OC_User :: getUser ())) {
2015-12-18 13:46:21 +03:00
header ( 'Location: ' . \OCP\Util :: linkToAbsolute ( '' , 'index.php' ));
2011-09-18 23:31:56 +04:00
exit ();
}
}
/**
2014-07-01 18:02:38 +04:00
* Returns the URL of the default page
* based on the system configuration and
* the apps visible for the current user
*
* @ return string URL
2017-07-19 20:44:10 +03:00
* @ suppress PhanDeprecatedFunction
2013-01-03 02:02:38 +04:00
*/
2014-07-01 18:02:38 +04:00
public static function getDefaultPageUrl () {
2020-08-04 16:07:32 +03:00
/** @var IConfig $config */
$config = \OC :: $server -> get ( IConfig :: class );
2014-03-28 21:05:48 +04:00
$urlGenerator = \OC :: $server -> getURLGenerator ();
2014-09-29 19:07:43 +04:00
// Deny the redirect if the URL contains a @
// This prevents unvalidated redirects like ?redirect_url=:user@domain.com
if ( isset ( $_REQUEST [ 'redirect_url' ]) && strpos ( $_REQUEST [ 'redirect_url' ], '@' ) === false ) {
$location = $urlGenerator -> getAbsoluteURL ( urldecode ( $_REQUEST [ 'redirect_url' ]));
2013-08-15 10:49:19 +04:00
} else {
2018-01-17 23:10:40 +03:00
$defaultPage = \OC :: $server -> getConfig () -> getAppValue ( 'core' , 'defaultpage' );
2013-08-15 10:49:19 +04:00
if ( $defaultPage ) {
2014-03-28 21:05:48 +04:00
$location = $urlGenerator -> getAbsoluteURL ( $defaultPage );
2013-08-15 10:49:19 +04:00
} else {
2014-07-01 17:42:26 +04:00
$appId = 'files' ;
2020-08-04 16:07:32 +03:00
$defaultApps = explode ( ',' , $config -> getSystemValue ( 'defaultapp' , 'dashboard,files' ));
/** @var IUserSession $userSession */
$userSession = \OC :: $server -> get ( IUserSession :: class );
$user = $userSession -> getUser ();
if ( $user ) {
$userDefaultApps = explode ( ',' , $config -> getUserValue ( $user -> getUID (), 'core' , 'defaultapp' ));
$defaultApps = array_filter ( array_merge ( $userDefaultApps , $defaultApps ));
}
2014-07-01 17:42:26 +04:00
// find the first app that is enabled for the current user
foreach ( $defaultApps as $defaultApp ) {
$defaultApp = OC_App :: cleanAppId ( strip_tags ( $defaultApp ));
2015-02-18 16:24:50 +03:00
if ( static :: getAppManager () -> isEnabledForUser ( $defaultApp )) {
2014-07-01 17:42:26 +04:00
$appId = $defaultApp ;
break ;
}
}
2015-02-11 03:10:03 +03:00
2020-04-10 15:19:56 +03:00
if ( $config -> getSystemValue ( 'htaccess.IgnoreFrontController' , false ) === true || getenv ( 'front_controller_active' ) === 'true' ) {
2015-02-11 03:10:03 +03:00
$location = $urlGenerator -> getAbsoluteURL ( '/apps/' . $appId . '/' );
} else {
$location = $urlGenerator -> getAbsoluteURL ( '/index.php/apps/' . $appId . '/' );
}
2012-08-06 20:49:06 +04:00
}
2011-10-04 21:27:57 +04:00
}
2014-07-01 18:02:38 +04:00
return $location ;
}
/**
* Redirect to the user default page
2014-08-19 20:01:26 +04:00
*
2014-07-01 18:02:38 +04:00
* @ return void
*/
public static function redirectToDefaultPage () {
$location = self :: getDefaultPageUrl ();
2014-08-19 20:01:26 +04:00
header ( 'Location: ' . $location );
2011-09-18 23:31:56 +04:00
exit ();
}
2012-06-05 21:32:48 +04:00
2013-08-15 10:49:19 +04:00
/**
2014-05-19 19:50:53 +04:00
* get an id unique for this instance
2014-08-19 20:01:26 +04:00
*
2013-08-15 10:49:19 +04:00
* @ return string
*/
public static function getInstanceId () {
2015-12-18 13:42:09 +03:00
$id = \OC :: $server -> getSystemConfig () -> getValue ( 'instanceid' , null );
2014-08-19 20:01:26 +04:00
if ( is_null ( $id )) {
2013-08-15 10:49:19 +04:00
// We need to guarantee at least one letter in instanceid so it can be used as the session_name
2016-01-11 21:59:15 +03:00
$id = 'oc' . \OC :: $server -> getSecureRandom () -> generate ( 10 , \OCP\Security\ISecureRandom :: CHAR_LOWER . \OCP\Security\ISecureRandom :: CHAR_DIGITS );
2015-12-18 13:42:09 +03:00
\OC :: $server -> getSystemConfig () -> setValue ( 'instanceid' , $id );
2013-08-15 10:49:19 +04:00
}
return $id ;
}
2012-06-09 17:05:14 +04:00
2012-06-21 16:07:04 +04:00
/**
2014-05-19 19:50:53 +04:00
* Public function to sanitize HTML
2012-06-21 16:07:04 +04:00
*
2012-06-22 10:17:35 +04:00
* This function is used to sanitize HTML and should be applied on any
* string or array of strings before displaying it on a web page .
2012-08-29 10:38:33 +04:00
*
2015-12-08 10:27:52 +03:00
* @ param string | array $value
2014-05-12 00:51:30 +04:00
* @ return string | array an array of sanitized strings or a single sanitized string , depends on the input parameter .
2012-06-19 19:20:19 +04:00
*/
2015-12-08 10:27:52 +03:00
public static function sanitizeHTML ( $value ) {
2013-02-22 03:51:54 +04:00
if ( is_array ( $value )) {
2020-04-09 14:53:40 +03:00
$value = array_map ( function ( $value ) {
2015-12-08 10:27:52 +03:00
return self :: sanitizeHTML ( $value );
}, $value );
2013-01-15 01:01:52 +04:00
} else {
2015-12-08 10:27:52 +03:00
// Specify encoding for PHP<5.4
2014-04-11 21:42:15 +04:00
$value = htmlspecialchars (( string ) $value , ENT_QUOTES , 'UTF-8' );
2013-01-15 01:01:52 +04:00
}
2012-06-19 19:20:19 +04:00
return $value ;
}
2013-09-27 15:34:48 +04:00
2013-07-04 20:21:49 +04:00
/**
2014-05-19 19:50:53 +04:00
* Public function to encode url parameters
2013-07-04 20:21:49 +04:00
*
* This function is used to encode path to file before output .
* Encoding is done according to RFC 3986 with one exception :
2013-09-27 15:34:48 +04:00
* Character '/' is preserved as is .
2013-07-04 20:21:49 +04:00
*
* @ param string $component part of URI to encode
2013-09-27 15:34:48 +04:00
* @ return string
2013-07-04 20:21:49 +04:00
*/
public static function encodePath ( $component ) {
$encoded = rawurlencode ( $component );
$encoded = str_replace ( '%2F' , '/' , $encoded );
return $encoded ;
}
2012-06-21 16:07:04 +04:00
2014-04-29 17:00:57 +04:00
2016-06-07 19:23:19 +03:00
public function createHtaccessTestFile ( \OCP\IConfig $config ) {
2015-01-08 11:13:18 +03:00
// php dev server does not support htaccess
if ( php_sapi_name () === 'cli-server' ) {
return false ;
}
2012-06-21 16:07:04 +04:00
// testdata
2013-08-18 12:33:09 +04:00
$fileName = '/htaccesstest.txt' ;
2016-06-07 19:23:19 +03:00
$testContent = 'This is used for testing whether htaccess is properly enabled to disallow access from the outside. This file can be safely removed.' ;
2012-06-21 16:07:04 +04:00
// creating a test file
2015-03-26 16:51:33 +03:00
$testFile = $config -> getSystemValue ( 'datadirectory' , OC :: $SERVERROOT . '/data' ) . '/' . $fileName ;
2012-10-26 20:17:43 +04:00
2016-01-11 17:37:08 +03:00
if ( file_exists ( $testFile )) { // already running this test, possible recursive call
return false ;
}
2013-09-11 00:05:20 +04:00
$fp = @ fopen ( $testFile , 'w' );
if ( ! $fp ) {
throw new OC\HintException ( 'Can\'t create test file to check for working .htaccess file.' ,
2014-08-19 20:01:26 +04:00
'Make sure it is possible for the webserver to write to ' . $testFile );
2013-09-11 00:05:20 +04:00
}
fwrite ( $fp , $testContent );
fclose ( $fp );
2016-12-05 19:09:23 +03:00
return $testContent ;
2016-06-07 19:23:19 +03:00
}
/**
* Check if the . htaccess file is working
* @ param \OCP\IConfig $config
* @ return bool
* @ throws Exception
* @ throws \OC\HintException If the test file can ' t get written .
*/
public function isHtaccessWorking ( \OCP\IConfig $config ) {
if ( \OC :: $CLI || ! $config -> getSystemValue ( 'check_for_working_htaccess' , true )) {
return true ;
}
$testContent = $this -> createHtaccessTestFile ( $config );
if ( $testContent === false ) {
return false ;
}
$fileName = '/htaccesstest.txt' ;
$testFile = $config -> getSystemValue ( 'datadirectory' , OC :: $SERVERROOT . '/data' ) . '/' . $fileName ;
2012-06-21 16:07:04 +04:00
// accessing the file via http
2015-12-17 15:03:37 +03:00
$url = \OC :: $server -> getURLGenerator () -> getAbsoluteURL ( OC :: $WEBROOT . '/data' . $fileName );
2015-12-04 20:02:47 +03:00
try {
$content = \OC :: $server -> getHTTPClientService () -> newClient () -> get ( $url ) -> getBody ();
} catch ( \Exception $e ) {
$content = false ;
}
2012-06-21 16:07:04 +04:00
2019-08-23 15:33:58 +03:00
if ( strpos ( $url , 'https:' ) === 0 ) {
$url = 'http:' . substr ( $url , 6 );
} else {
$url = 'https:' . substr ( $url , 5 );
}
try {
$fallbackContent = \OC :: $server -> getHTTPClientService () -> newClient () -> get ( $url ) -> getBody ();
} catch ( \Exception $e ) {
$fallbackContent = false ;
}
2012-06-21 16:07:04 +04:00
// cleanup
2013-09-11 00:05:20 +04:00
@ unlink ( $testFile );
2012-06-21 16:07:04 +04:00
2014-08-19 20:01:26 +04:00
/*
* If the content is not equal to test content our . htaccess
* is working as required
*/
2019-08-23 15:33:58 +03:00
return $content !== $testContent && $fallbackContent !== $testContent ;
2012-07-24 02:39:59 +04:00
}
2012-06-21 16:07:04 +04:00
2013-01-03 02:02:38 +04:00
/**
2013-08-22 03:20:28 +04:00
* Check if the setlocal call does not work . This can happen if the right
2013-02-11 20:44:02 +04:00
* local packages are not available on the server .
2014-08-19 20:01:26 +04:00
*
2013-08-15 10:49:19 +04:00
* @ return bool
2013-01-03 02:02:38 +04:00
*/
2013-08-18 12:33:09 +04:00
public static function isSetLocaleWorking () {
2013-11-15 16:06:35 +04:00
\Patchwork\Utf8\Bootup :: initLocale ();
if ( '' === basename ( '§' )) {
2013-02-08 20:49:54 +04:00
return false ;
2013-04-05 22:49:57 +04:00
}
return true ;
2012-12-19 18:10:33 +04:00
}
2014-03-07 05:53:33 +04:00
/**
* Check if it ' s possible to get the inline annotations
*
* @ return bool
*/
public static function isAnnotationsWorking () {
$reflection = new \ReflectionMethod ( __METHOD__ );
$docs = $reflection -> getDocComment ();
return ( is_string ( $docs ) && strlen ( $docs ) > 50 );
}
2013-02-04 18:04:26 +04:00
/**
2014-05-19 19:50:53 +04:00
* Check if the PHP module fileinfo is loaded .
2014-08-19 20:01:26 +04:00
*
2013-02-04 18:04:26 +04:00
* @ return bool
*/
public static function fileInfoLoaded () {
return function_exists ( 'finfo_open' );
}
2012-11-29 20:58:24 +04:00
/**
2014-05-19 19:50:53 +04:00
* clear all levels of output buffering
2014-08-19 20:01:26 +04:00
*
2013-08-15 10:49:19 +04:00
* @ return void
2012-11-29 20:58:24 +04:00
*/
2014-08-19 20:01:26 +04:00
public static function obEnd () {
2012-11-29 20:58:24 +04:00
while ( ob_get_level ()) {
ob_end_clean ();
}
}
2014-03-20 15:31:36 +04:00
/**
* Checks whether the server is running on Mac OS X
2014-08-19 20:01:26 +04:00
*
2014-03-20 15:31:36 +04:00
* @ return bool true if running on Mac OS X , false otherwise
*/
public static function runningOnMac () {
return ( strtoupper ( substr ( PHP_OS , 0 , 6 )) === 'DARWIN' );
}
2013-04-24 15:45:40 +04:00
/**
* Handles the case that there may not be a theme , then check if a " default "
* theme exists and take that one
2014-08-19 20:01:26 +04:00
*
2013-04-24 15:45:40 +04:00
* @ return string the theme
*/
public static function getTheme () {
2015-12-18 13:42:09 +03:00
$theme = \OC :: $server -> getSystemConfig () -> getValue ( " theme " , '' );
2013-04-24 15:45:40 +04:00
2014-08-19 20:01:26 +04:00
if ( $theme === '' ) {
if ( is_dir ( OC :: $SERVERROOT . '/themes/default' )) {
2013-04-24 15:45:40 +04:00
$theme = 'default' ;
}
}
return $theme ;
}
2013-05-24 22:35:01 +04:00
/**
* Normalize a unicode string
2014-08-19 20:01:26 +04:00
*
2013-05-24 22:35:01 +04:00
* @ param string $value a not normalized string
* @ return bool | string
*/
public static function normalizeUnicode ( $value ) {
2020-04-10 15:19:56 +03:00
if ( Normalizer :: isNormalized ( $value )) {
2015-01-10 01:34:26 +03:00
return $value ;
}
$normalizedValue = Normalizer :: normalize ( $value );
2014-09-09 16:41:45 +04:00
if ( $normalizedValue === null || $normalizedValue === false ) {
2015-01-10 01:34:26 +03:00
\OC :: $server -> getLogger () -> warning ( 'normalizing failed for "' . $value . '"' , [ 'app' => 'core' ]);
return $value ;
2013-05-24 22:35:01 +04:00
}
2013-04-24 15:45:40 +04:00
2015-01-10 01:34:26 +03:00
return $normalizedValue ;
2013-05-24 22:35:01 +04:00
}
2013-07-29 20:24:05 +04:00
2013-11-25 00:26:34 +04:00
/**
2016-12-22 16:19:29 +03:00
* A human readable string is generated based on version and build number
2014-08-19 20:01:26 +04:00
*
2013-11-25 00:26:34 +04:00
* @ return string
*/
public static function getHumanVersion () {
2016-12-22 16:19:29 +03:00
$version = OC_Util :: getVersionString ();
2013-11-25 00:26:34 +04:00
$build = OC_Util :: getBuild ();
2014-08-19 20:01:26 +04:00
if ( ! empty ( $build ) and OC_Util :: getChannel () === 'daily' ) {
2013-11-25 00:26:34 +04:00
$version .= ' Build:' . $build ;
}
return $version ;
}
2014-01-10 19:14:37 +04:00
/**
* Returns whether the given file name is valid
2014-08-19 20:01:26 +04:00
*
2014-05-12 00:51:30 +04:00
* @ param string $file file name to check
2014-01-10 19:14:37 +04:00
* @ return bool true if the file name is valid , false otherwise
2015-02-18 20:35:27 +03:00
* @ deprecated use \OC\Files\View :: verifyPath ()
2014-01-10 19:14:37 +04:00
*/
public static function isValidFileName ( $file ) {
$trimmed = trim ( $file );
if ( $trimmed === '' ) {
return false ;
}
2015-09-21 15:09:28 +03:00
if ( \OC\Files\Filesystem :: isIgnoredDir ( $trimmed )) {
2014-01-10 19:14:37 +04:00
return false ;
}
2017-02-27 20:30:10 +03:00
2017-03-24 13:28:54 +03:00
// detect part files
if ( preg_match ( '/' . \OCP\Files\FileInfo :: BLACKLIST_FILES_REGEX . '/' , $trimmed ) !== 0 ) {
2017-02-27 20:30:10 +03:00
return false ;
}
2014-01-10 19:14:37 +04:00
foreach ( str_split ( $trimmed ) as $char ) {
2014-11-25 18:28:41 +03:00
if ( strpos ( \OCP\Constants :: FILENAME_INVALID_CHARS , $char ) !== false ) {
2014-01-10 19:14:37 +04:00
return false ;
}
}
return true ;
}
2014-06-10 20:01:07 +04:00
/**
2014-09-02 16:30:46 +04:00
* Check whether the instance needs to perform an upgrade ,
* either when the core version is higher or any app requires
* an upgrade .
2014-06-10 20:01:07 +04:00
*
2017-03-18 01:37:48 +03:00
* @ param \OC\SystemConfig $config
2014-09-02 16:30:46 +04:00
* @ return bool whether the core or any app needs an upgrade
2016-01-07 16:13:46 +03:00
* @ throws \OC\HintException When the upgrade from the given version is not allowed
2014-06-10 20:01:07 +04:00
*/
2017-03-18 01:37:48 +03:00
public static function needUpgrade ( \OC\SystemConfig $config ) {
if ( $config -> getValue ( 'installed' , false )) {
$installedVersion = $config -> getValue ( 'version' , '0.0.0' );
2015-12-18 17:26:54 +03:00
$currentVersion = implode ( '.' , \OCP\Util :: getVersion ());
2015-08-30 19:03:33 +03:00
$versionDiff = version_compare ( $currentVersion , $installedVersion );
if ( $versionDiff > 0 ) {
2014-07-24 19:15:38 +04:00
return true ;
2020-04-10 11:35:09 +03:00
} elseif ( $config -> getValue ( 'debug' , false ) && $versionDiff < 0 ) {
2016-01-07 16:13:46 +03:00
// downgrade with debug
$installedMajor = explode ( '.' , $installedVersion );
$installedMajor = $installedMajor [ 0 ] . '.' . $installedMajor [ 1 ];
$currentMajor = explode ( '.' , $currentVersion );
$currentMajor = $currentMajor [ 0 ] . '.' . $currentMajor [ 1 ];
if ( $installedMajor === $currentMajor ) {
// Same major, allow downgrade for developers
return true ;
} else {
// downgrade attempt, throw exception
throw new \OC\HintException ( 'Downgrading is not supported and is likely to cause unpredictable issues (from ' . $installedVersion . ' to ' . $currentVersion . ')' );
}
2020-04-10 11:35:09 +03:00
} elseif ( $versionDiff < 0 ) {
2015-08-30 19:03:33 +03:00
// downgrade attempt, throw exception
throw new \OC\HintException ( 'Downgrading is not supported and is likely to cause unpredictable issues (from ' . $installedVersion . ' to ' . $currentVersion . ')' );
2014-07-24 19:15:38 +04:00
}
2014-09-02 16:30:46 +04:00
// also check for upgrades for apps (independently from the user)
$apps = \OC_App :: getEnabledApps ( false , true );
$shouldUpgrade = false ;
2014-07-24 19:15:38 +04:00
foreach ( $apps as $app ) {
if ( \OC_App :: shouldUpgrade ( $app )) {
2014-09-02 16:30:46 +04:00
$shouldUpgrade = true ;
break ;
2014-07-24 19:15:38 +04:00
}
}
2014-09-02 16:30:46 +04:00
return $shouldUpgrade ;
2014-06-10 20:01:07 +04:00
} else {
return false ;
}
}
2014-07-25 11:53:25 +04:00
2018-07-21 14:28:23 +03:00
/**
* is this Internet explorer ?
*
* @ return boolean
*/
public static function isIe () {
2018-08-08 14:32:03 +03:00
if ( ! isset ( $_SERVER [ 'HTTP_USER_AGENT' ])) {
return false ;
}
2018-07-21 14:28:23 +03:00
return preg_match ( Request :: USER_AGENT_IE , $_SERVER [ 'HTTP_USER_AGENT' ]) === 1 ;
}
2011-07-27 21:07:28 +04:00
}