2011-03-02 21:18:22 +00:00
< ? php
/**
2015-03-26 10:44:34 +00:00
* @ author Arthur Schiwon < blizzz @ owncloud . com >
* @ author Bart Visscher < bartv @ thisnet . nl >
2015-04-02 19:37:57 +00:00
* @ author Björn Schießle < schiessle @ owncloud . com >
* @ author Christopher Schäpers < kondou @ ts . unde . re >
2015-03-26 10:44:34 +00:00
* @ author Fabian Henze < flyser42 @ gmx . de >
* @ author Felix Moeller < mail @ felixmoeller . de >
2015-04-02 19:37:57 +00:00
* @ author François Kubler < francois @ kubler . org >
2015-03-26 10:44:34 +00:00
* @ author Frank Karlitschek < frank @ owncloud . org >
* @ author Georg Ehrke < georg @ owncloud . com >
* @ author Jakob Sack < mail @ jakobsack . de >
* @ author Jan - Christoph Borchardt < hey @ jancborchardt . net >
* @ author Joas Schilling < nickvergessen @ owncloud . com >
2015-04-02 19:37:57 +00:00
* @ author Jörn Friedrich Dreyer < jfd @ butonic . de >
2015-03-26 10:44:34 +00:00
* @ author Lukas Reschke < lukas @ owncloud . com >
* @ author Michael Gapczynski < GapczynskiM @ gmail . com >
* @ author Morris Jobke < hey @ morrisjobke . de >
2015-06-25 09:43:55 +00:00
* @ author Olivier Paroz < github @ oparoz . com >
2015-03-26 10:44:34 +00:00
* @ author Owen Winkler < a_github @ midnightcircus . com >
* @ author Pellaeon Lin < nfsmwlin @ gmail . com >
* @ author Robin Appelman < icewind @ owncloud . com >
* @ author Robin McCorkell < rmccorkell @ karoshi . org . uk >
* @ author Roeland Jago Douma < roeland @ famdouma . nl >
2015-04-02 19:37:57 +00:00
* @ author Simon Könnecke < simonkoennecke @ gmail . com >
* @ author Thomas Müller < thomas . mueller @ tmit . eu >
2015-03-26 10:44:34 +00:00
* @ author Thomas Tanghus < thomas @ tanghus . net >
* @ author Valerio Ponte < valerio . ponte @ gmail . com >
* @ author Vincent Petry < pvince81 @ owncloud . com >
2011-03-13 16:25:34 +00:00
*
2015-03-26 10:44:34 +00:00
* @ copyright Copyright ( c ) 2015 , ownCloud , Inc .
* @ license AGPL - 3.0
2011-03-13 16:25:34 +00:00
*
2015-03-26 10:44:34 +00:00
* 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 .
2011-03-13 16:25:34 +00:00
*
2015-03-26 10:44:34 +00:00
* This program is distributed in the hope that it will be useful ,
2011-03-13 16:25:34 +00:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
2015-03-26 10:44:34 +00:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
2011-03-13 16:25:34 +00:00
*
2015-03-26 10:44:34 +00:00
* You should have received a copy of the GNU Affero General Public License , version 3 ,
* along with this program . If not , see < http :// www . gnu . org / licenses />
2011-03-13 16:25:34 +00:00
*
*/
2015-01-26 11:32:17 +00:00
use Symfony\Component\Process\ExecutableFinder ;
2015-02-26 10:37:37 +00:00
/**
* Collection of useful functions
*/
2011-07-29 19:36:03 +00:00
class OC_Helper {
2013-08-07 14:53:09 +00:00
private static $templateManager ;
2012-04-13 20:59:47 +00:00
2012-09-12 16:00:33 +00:00
/**
2014-05-19 15:50:53 +00:00
* Creates an url using a defined route
2014-05-11 20:51:30 +00:00
* @ param string $route
2015-04-27 12:45:05 +00:00
* @ param array $parameters with param => value , will be appended to the returned url
2014-05-11 17:05:28 +00:00
* @ return string the url
2015-04-01 12:32:49 +00:00
* @ deprecated Use \OC :: $server -> getURLGenerator () -> linkToRoute ( $route , $parameters )
2012-09-12 16:00:33 +00:00
*
* Returns a url to the given app and file .
*/
2013-08-07 14:38:57 +00:00
public static function linkToRoute ( $route , $parameters = array ()) {
2013-09-26 16:41:19 +00:00
return OC :: $server -> getURLGenerator () -> linkToRoute ( $route , $parameters );
2012-09-12 16:00:33 +00:00
}
2011-03-02 21:18:22 +00:00
/**
2014-05-19 15:50:53 +00:00
* Creates an url
2012-09-23 00:39:11 +00:00
* @ param string $app app
* @ param string $file file
* @ param array $args array with param => value , will be appended to the returned url
2013-08-07 14:38:57 +00:00
* The value of $args will be urlencoded
2012-09-23 00:39:11 +00:00
* @ return string the url
2015-04-01 12:32:49 +00:00
* @ deprecated Use \OC :: $server -> getURLGenerator () -> linkTo ( $app , $file , $args )
2011-03-02 21:18:22 +00:00
*
2011-03-13 16:25:34 +00:00
* Returns a url to the given app and file .
2011-03-02 21:18:22 +00:00
*/
2012-09-07 13:22:01 +00:00
public static function linkTo ( $app , $file , $args = array () ) {
2013-09-26 16:41:19 +00:00
return OC :: $server -> getURLGenerator () -> linkTo ( $app , $file , $args );
2011-03-02 21:18:22 +00:00
}
2013-10-21 20:01:27 +00:00
/**
2014-11-24 15:24:26 +00:00
* @ param string $key
2013-10-21 20:01:27 +00:00
* @ return string url to the online documentation
2015-04-01 12:32:49 +00:00
* @ deprecated Use \OC :: $server -> getURLGenerator () -> linkToDocs ( $key )
2013-10-21 20:01:27 +00:00
*/
public static function linkToDocs ( $key ) {
2014-11-24 15:24:26 +00:00
return OC :: $server -> getURLGenerator () -> linkToDocs ( $key );
2013-10-21 20:01:27 +00:00
}
2012-02-16 18:45:00 +00:00
/**
2014-05-19 15:50:53 +00:00
* Creates an absolute url
2012-09-23 00:39:11 +00:00
* @ param string $app app
* @ param string $file file
* @ param array $args array with param => value , will be appended to the returned url
2013-08-07 14:38:57 +00:00
* The value of $args will be urlencoded
2012-09-23 00:39:11 +00:00
* @ return string the url
2012-02-16 18:45:00 +00:00
*
* Returns a absolute url to the given app and file .
*/
2013-08-07 14:38:57 +00:00
public static function linkToAbsolute ( $app , $file , $args = array ()) {
2014-04-16 12:30:24 +00:00
return OC :: $server -> getURLGenerator () -> getAbsoluteURL (
self :: linkTo ( $app , $file , $args )
);
2012-08-06 20:15:55 +00:00
}
/**
2014-05-19 15:50:53 +00:00
* Makes an $url absolute
2012-09-23 00:39:11 +00:00
* @ param string $url the url
* @ return string the absolute url
2015-04-01 12:32:49 +00:00
* @ deprecated Use \OC :: $server -> getURLGenerator () -> getAbsoluteURL ( $url )
2012-08-06 20:15:55 +00:00
*
* Returns a absolute url to the given app and file .
*/
2013-08-07 14:38:57 +00:00
public static function makeURLAbsolute ( $url ) {
2013-10-06 22:35:05 +00:00
return OC :: $server -> getURLGenerator () -> getAbsoluteURL ( $url );
2012-02-16 18:45:00 +00:00
}
2012-10-17 08:52:16 +00:00
/**
2014-05-19 15:50:53 +00:00
* Creates an url for remote use
2012-10-17 08:52:16 +00:00
* @ param string $service id
* @ return string the url
*
* Returns a url to the given service .
*/
2013-08-07 14:38:57 +00:00
public static function linkToRemoteBase ( $service ) {
return self :: linkTo ( '' , 'remote.php' ) . '/' . $service ;
2012-10-17 08:52:16 +00:00
}
2012-05-07 18:22:55 +00:00
/**
2014-05-19 15:50:53 +00:00
* Creates an absolute url for remote use
2012-09-23 00:39:11 +00:00
* @ param string $service id
2013-01-04 22:00:51 +00:00
* @ param bool $add_slash
2012-09-23 00:39:11 +00:00
* @ return string the url
2012-05-07 18:22:55 +00:00
*
* Returns a absolute url to the given service .
*/
2013-08-07 14:38:57 +00:00
public static function linkToRemote ( $service , $add_slash = true ) {
2014-04-16 12:30:24 +00:00
return OC :: $server -> getURLGenerator () -> getAbsoluteURL (
self :: linkToRemoteBase ( $service )
. (( $add_slash && $service [ strlen ( $service ) - 1 ] != '/' ) ? '/' : '' )
);
2012-05-07 18:22:55 +00:00
}
2012-08-27 19:46:05 +00:00
/**
2014-05-19 15:50:53 +00:00
* Creates an absolute url for public use
2012-09-23 00:39:11 +00:00
* @ param string $service id
2013-01-04 22:00:51 +00:00
* @ param bool $add_slash
2012-09-23 00:39:11 +00:00
* @ return string the url
2012-08-27 19:46:05 +00:00
*
* Returns a absolute url to the given service .
*/
public static function linkToPublic ( $service , $add_slash = false ) {
2014-09-04 17:51:38 +00:00
if ( $service === 'files' ) {
$url = OC :: $server -> getURLGenerator () -> getAbsoluteURL ( '/s' );
} else {
$url = OC :: $server -> getURLGenerator () -> getAbsoluteURL ( self :: linkTo ( '' , 'public.php' ) . '?service=' . $service );
}
return $url . (( $add_slash && $service [ strlen ( $service ) - 1 ] != '/' ) ? '/' : '' );
2012-08-27 19:46:05 +00:00
}
2011-03-02 21:18:22 +00:00
/**
2014-05-19 15:50:53 +00:00
* Creates path to an image
2012-09-23 00:39:11 +00:00
* @ param string $app app
* @ param string $image image name
* @ return string the url
2015-04-01 12:32:49 +00:00
* @ deprecated Use \OC :: $server -> getURLGenerator () -> imagePath ( $app , $image )
2011-03-02 21:18:22 +00:00
*
2011-03-13 16:25:34 +00:00
* Returns the path to the image .
2011-03-02 21:18:22 +00:00
*/
2013-08-07 14:38:57 +00:00
public static function imagePath ( $app , $image ) {
2013-09-26 16:41:19 +00:00
return OC :: $server -> getURLGenerator () -> imagePath ( $app , $image );
2012-02-27 17:01:43 +00:00
}
2011-03-02 21:18:22 +00:00
/**
2014-05-19 15:50:53 +00:00
* get path to icon of file type
2012-09-23 00:39:11 +00:00
* @ param string $mimetype mimetype
* @ return string the url
2011-03-02 21:18:22 +00:00
*
2011-08-11 16:59:01 +00:00
* Returns the path to the image of this file type .
2015-07-14 06:43:14 +00:00
* @ deprecated 8.2 . 0 Use \OC :: $server -> getMimeTypeDetector () -> mimeTypeIcon ( $mimetype )
2011-03-02 21:18:22 +00:00
*/
2013-05-29 14:56:28 +00:00
public static function mimetypeIcon ( $mimetype ) {
2015-07-14 06:43:14 +00:00
return \OC :: $server -> getMimeTypeDetector () -> mimeTypeIcon ( $mimetype );
2011-03-02 21:18:22 +00:00
}
2011-03-02 21:28:32 +00:00
2013-06-26 16:04:18 +00:00
/**
2014-05-19 15:50:53 +00:00
* get path to preview of file
2013-06-26 16:04:18 +00:00
* @ param string $path path
* @ return string the url
*
* Returns the path to the preview of the file .
*/
public static function previewIcon ( $path ) {
2015-09-30 08:49:48 +00:00
return self :: linkToRoute ( 'core_ajax_preview' , array ( 'x' => 32 , 'y' => 32 , 'file' => $path ));
2013-06-26 16:04:18 +00:00
}
2013-07-30 10:29:12 +00:00
public static function publicPreviewIcon ( $path , $token ) {
2015-09-30 08:49:48 +00:00
return self :: linkToRoute ( 'core_ajax_public_preview' , array ( 'x' => 32 , 'y' => 32 , 'file' => $path , 't' => $token ));
2013-07-11 09:58:52 +00:00
}
2014-03-15 14:27:48 +00:00
/**
* shows whether the user has an avatar
* @ param string $user username
* @ return bool avatar set or not
**/
public static function userAvatarSet ( $user ) {
2015-03-03 11:52:27 +00:00
$avatar = new \OC\Avatar ( $user );
2015-02-03 13:54:06 +00:00
return $avatar -> exists ();
2014-03-15 14:27:48 +00:00
}
2011-03-02 21:28:32 +00:00
/**
2014-05-19 15:50:53 +00:00
* Make a human file size
2012-09-23 00:39:11 +00:00
* @ param int $bytes file size in bytes
* @ return string a human readable file size
2011-03-02 21:28:32 +00:00
*
2011-03-13 16:25:34 +00:00
* Makes 2048 to 2 kB .
2011-03-02 21:28:32 +00:00
*/
2013-08-07 14:38:57 +00:00
public static function humanFileSize ( $bytes ) {
if ( $bytes < 0 ) {
2013-08-04 14:27:17 +00:00
return " ? " ;
2013-01-14 22:39:31 +00:00
}
2013-08-07 14:38:57 +00:00
if ( $bytes < 1024 ) {
2011-03-02 21:28:32 +00:00
return " $bytes B " ;
}
2013-11-25 11:26:03 +00:00
$bytes = round ( $bytes / 1024 , 0 );
2013-08-07 14:38:57 +00:00
if ( $bytes < 1024 ) {
2011-03-02 21:28:32 +00:00
return " $bytes kB " ;
}
2013-08-07 14:38:57 +00:00
$bytes = round ( $bytes / 1024 , 1 );
if ( $bytes < 1024 ) {
2011-03-02 21:28:32 +00:00
return " $bytes MB " ;
}
2013-09-13 15:22:45 +00:00
$bytes = round ( $bytes / 1024 , 1 );
if ( $bytes < 1024 ) {
return " $bytes GB " ;
}
$bytes = round ( $bytes / 1024 , 1 );
if ( $bytes < 1024 ) {
return " $bytes TB " ;
}
2011-03-02 21:28:32 +00:00
2013-08-07 14:38:57 +00:00
$bytes = round ( $bytes / 1024 , 1 );
2013-09-13 15:22:45 +00:00
return " $bytes PB " ;
2011-03-02 21:28:32 +00:00
}
2012-04-13 20:59:47 +00:00
2014-04-02 23:17:28 +00:00
/**
2014-05-19 15:50:53 +00:00
* Make a php file size
2014-04-02 23:17:28 +00:00
* @ param int $bytes file size in bytes
* @ return string a php parseable file size
*
* Makes 2048 to 2 k and 2 ^ 41 to 2048 G
*/
public static function phpFileSize ( $bytes ) {
if ( $bytes < 0 ) {
return " ? " ;
}
if ( $bytes < 1024 ) {
return $bytes . " B " ;
}
$bytes = round ( $bytes / 1024 , 1 );
if ( $bytes < 1024 ) {
return $bytes . " K " ;
}
$bytes = round ( $bytes / 1024 , 1 );
if ( $bytes < 1024 ) {
return $bytes . " M " ;
}
$bytes = round ( $bytes / 1024 , 1 );
return $bytes . " G " ;
}
2011-04-17 10:03:23 +00:00
/**
2014-05-19 15:50:53 +00:00
* Make a computer file size
2014-03-17 11:15:12 +00:00
* @ param string $str file size in human readable format
2015-10-01 11:45:49 +00:00
* @ return float a file size in bytes
2011-04-17 10:03:23 +00:00
*
* Makes 2 kB to 2048.
*
* Inspired by : http :// www . php . net / manual / en / function . filesize . php #92418
*/
2013-08-07 14:38:57 +00:00
public static function computerFileSize ( $str ) {
$str = strtolower ( $str );
2015-05-08 08:54:54 +00:00
if ( is_numeric ( $str )) {
2015-10-01 11:45:49 +00:00
return floatval ( $str );
2015-05-08 08:54:54 +00:00
}
2011-04-17 10:03:23 +00:00
$bytes_array = array (
2011-12-11 22:33:24 +00:00
'b' => 1 ,
'k' => 1024 ,
'kb' => 1024 ,
'mb' => 1024 * 1024 ,
2013-08-07 14:38:57 +00:00
'm' => 1024 * 1024 ,
2011-12-11 22:33:24 +00:00
'gb' => 1024 * 1024 * 1024 ,
2013-08-07 14:38:57 +00:00
'g' => 1024 * 1024 * 1024 ,
2011-12-11 22:33:24 +00:00
'tb' => 1024 * 1024 * 1024 * 1024 ,
2013-08-07 14:38:57 +00:00
't' => 1024 * 1024 * 1024 * 1024 ,
2011-12-11 22:33:24 +00:00
'pb' => 1024 * 1024 * 1024 * 1024 * 1024 ,
2013-08-07 14:38:57 +00:00
'p' => 1024 * 1024 * 1024 * 1024 * 1024 ,
2011-04-17 10:03:23 +00:00
);
$bytes = floatval ( $str );
2011-12-11 22:33:24 +00:00
if ( preg_match ( '#([kmgtp]?b?)$#si' , $str , $matches ) && ! empty ( $bytes_array [ $matches [ 1 ]])) {
2011-04-17 10:03:23 +00:00
$bytes *= $bytes_array [ $matches [ 1 ]];
2015-05-07 15:56:13 +00:00
} else {
return false ;
2011-04-17 10:03:23 +00:00
}
2014-03-17 11:15:12 +00:00
$bytes = round ( $bytes );
2011-04-17 10:03:23 +00:00
2012-04-13 20:59:47 +00:00
return $bytes ;
2011-04-17 10:03:23 +00:00
}
2012-04-13 20:59:47 +00:00
2011-05-28 15:33:25 +00:00
/**
2014-05-19 15:50:53 +00:00
* Recursive copying of folders
2011-05-28 15:33:25 +00:00
* @ param string $src source folder
* @ param string $dest target folder
*
*/
static function copyr ( $src , $dest ) {
2013-08-07 14:38:57 +00:00
if ( is_dir ( $src )) {
if ( ! is_dir ( $dest )) {
2011-05-28 15:33:25 +00:00
mkdir ( $dest );
}
$files = scandir ( $src );
2012-09-07 13:22:01 +00:00
foreach ( $files as $file ) {
if ( $file != " . " && $file != " .. " ) {
2011-05-28 15:33:25 +00:00
self :: copyr ( " $src / $file " , " $dest / $file " );
}
}
2013-08-07 14:38:57 +00:00
} elseif ( file_exists ( $src ) && ! \OC\Files\Filesystem :: isFileBlacklisted ( $src )) {
2011-05-28 15:33:25 +00:00
copy ( $src , $dest );
}
}
2012-04-13 20:59:47 +00:00
2011-05-28 15:33:25 +00:00
/**
2014-05-19 15:50:53 +00:00
* Recursive deletion of folders
2011-05-28 15:33:25 +00:00
* @ param string $dir path to the folder
2014-10-06 10:38:59 +00:00
* @ param bool $deleteSelf if set to false only the content of the folder will be deleted
2012-09-23 00:39:11 +00:00
* @ return bool
2011-05-28 15:33:25 +00:00
*/
2014-10-06 10:38:59 +00:00
static function rmdirr ( $dir , $deleteSelf = true ) {
2013-08-07 14:38:57 +00:00
if ( is_dir ( $dir )) {
2014-06-23 11:33:55 +00:00
$files = new RecursiveIteratorIterator (
new RecursiveDirectoryIterator ( $dir , RecursiveDirectoryIterator :: SKIP_DOTS ),
RecursiveIteratorIterator :: CHILD_FIRST
);
foreach ( $files as $fileInfo ) {
2014-06-23 21:15:30 +00:00
/** @var SplFileInfo $fileInfo */
2014-06-23 11:33:55 +00:00
if ( $fileInfo -> isDir ()) {
rmdir ( $fileInfo -> getRealPath ());
} else {
unlink ( $fileInfo -> getRealPath ());
2011-05-28 15:33:25 +00:00
}
}
2014-10-06 10:38:59 +00:00
if ( $deleteSelf ) {
rmdir ( $dir );
}
2013-08-07 14:38:57 +00:00
} elseif ( file_exists ( $dir )) {
2014-10-06 10:38:59 +00:00
if ( $deleteSelf ) {
unlink ( $dir );
}
2011-05-28 15:33:25 +00:00
}
2014-10-06 10:38:59 +00:00
if ( ! $deleteSelf ) {
2012-09-23 00:39:11 +00:00
return true ;
2012-04-13 20:59:47 +00:00
}
2014-10-06 10:38:59 +00:00
return ! file_exists ( $dir );
2011-05-28 15:33:25 +00:00
}
2012-02-15 20:44:58 +00:00
2013-08-07 14:53:09 +00:00
/**
* @ return \OC\Files\Type\Detection
2015-07-14 06:43:14 +00:00
* @ deprecated 8.2 . 0 use \OC :: $server -> getMimeTypeDetector ()
2013-08-07 14:53:09 +00:00
*/
2013-08-07 14:38:57 +00:00
static public function getMimetypeDetector () {
2015-07-14 06:43:14 +00:00
return \OC :: $server -> getMimeTypeDetector ();
2013-08-07 14:38:57 +00:00
}
2013-08-07 14:53:09 +00:00
/**
* @ return \OC\Files\Type\TemplateManager
*/
static public function getFileTemplateManager () {
if ( ! self :: $templateManager ) {
self :: $templateManager = new \OC\Files\Type\TemplateManager ();
}
return self :: $templateManager ;
}
2012-02-15 20:44:58 +00:00
/**
2013-06-06 21:51:44 +00:00
* Try to guess the mimetype based on filename
*
2013-06-06 22:17:51 +00:00
* @ param string $path
2012-02-15 20:44:58 +00:00
* @ return string
2015-07-18 19:51:12 +00:00
* @ deprecated 8.2 . 0 Use \OC :: $server -> getMimeTypeDetector () -> detectPath ( $path )
2012-02-15 20:44:58 +00:00
*/
2013-08-07 14:38:57 +00:00
static public function getFileNameMimeType ( $path ) {
2015-07-14 06:43:14 +00:00
return \OC :: $server -> getMimeTypeDetector () -> detectPath ( $path );
2013-06-06 21:51:44 +00:00
}
/**
* get the mimetype form a local file
2013-08-07 14:38:57 +00:00
*
2013-06-06 21:51:44 +00:00
* @ param string $path
* @ return string
* does NOT work for ownClouds filesystem , use OC_FileSystem :: getMimeType instead
2015-07-18 19:51:12 +00:00
* @ deprecated 8.2 . 0 Use \OC :: $server -> getMimeTypeDetector () -> detect ( $path )
2013-06-06 21:51:44 +00:00
*/
static function getMimeType ( $path ) {
2015-07-14 06:43:14 +00:00
return \OC :: $server -> getMimeTypeDetector () -> detect ( $path );
2012-02-15 20:44:58 +00:00
}
2012-04-13 20:59:47 +00:00
2014-04-14 15:17:50 +00:00
/**
* Get a secure mimetype that won ' t expose potential XSS .
*
* @ param string $mimeType
* @ return string
2015-07-18 19:51:12 +00:00
* @ deprecated 8.2 . 0 Use \OC :: $server -> getMimeTypeDetector () -> getSecureMimeType ( $mimeType )
2014-04-14 15:17:50 +00:00
*/
static function getSecureMimeType ( $mimeType ) {
2015-07-14 06:43:14 +00:00
return \OC :: $server -> getMimeTypeDetector () -> getSecureMimeType ( $mimeType );
2014-04-14 15:17:50 +00:00
}
2012-04-18 18:24:22 +00:00
/**
* get the mimetype form a data string
2013-08-07 14:38:57 +00:00
*
2012-09-23 00:39:11 +00:00
* @ param string $data
2012-04-18 18:24:22 +00:00
* @ return string
2015-07-18 19:51:12 +00:00
* @ deprecated 8.2 . 0 Use \OC :: $server -> getMimeTypeDetector () -> detectString ( $data )
2012-04-18 18:24:22 +00:00
*/
2012-09-07 13:22:01 +00:00
static function getStringMimeType ( $data ) {
2015-07-14 06:43:14 +00:00
return \OC :: $server -> getMimeTypeDetector () -> detectString ( $data );
2012-04-18 18:24:22 +00:00
}
2011-07-28 18:10:58 +00:00
/**
2013-01-04 22:00:51 +00:00
* detect if a given program is found in the search PATH
*
2014-05-11 20:51:30 +00:00
* @ param string $name
2013-01-04 22:00:51 +00:00
* @ param bool $path
* @ internal param string $program name
* @ internal param string $optional search path , defaults to $PATH
* @ return bool true if executable program found in path
*/
2012-09-07 13:22:01 +00:00
public static function canExecute ( $name , $path = false ) {
2011-07-28 18:10:58 +00:00
// path defaults to PATH from environment if not set
if ( $path === false ) {
$path = getenv ( " PATH " );
}
// check method depends on operating system
if ( ! strncmp ( PHP_OS , " WIN " , 3 )) {
// on Windows an appropriate COM or EXE file needs to exist
$exts = array ( " .exe " , " .com " );
$check_fn = " file_exists " ;
} else {
// anywhere else we look for an executable file of that name
$exts = array ( " " );
$check_fn = " is_executable " ;
}
// Default check will be done with $path directories :
$dirs = explode ( PATH_SEPARATOR , $path );
// WARNING : We have to check if open_basedir is enabled :
$obd = ini_get ( 'open_basedir' );
2013-08-07 14:38:57 +00:00
if ( $obd != " none " ) {
2011-07-28 18:10:58 +00:00
$obd_values = explode ( PATH_SEPARATOR , $obd );
2013-08-07 14:38:57 +00:00
if ( count ( $obd_values ) > 0 and $obd_values [ 0 ]) {
2012-09-23 00:39:11 +00:00
// open_basedir is in effect !
// We need to check if the program is in one of these dirs :
$dirs = $obd_values ;
}
}
2013-08-07 14:38:57 +00:00
foreach ( $dirs as $dir ) {
foreach ( $exts as $ext ) {
if ( $check_fn ( " $dir / $name " . $ext ))
2011-07-28 18:10:58 +00:00
return true ;
}
}
return false ;
}
2012-04-13 20:59:47 +00:00
2012-02-27 11:04:04 +00:00
/**
* copy the contents of one stream to another
2013-08-07 14:38:57 +00:00
*
2012-09-23 00:39:11 +00:00
* @ param resource $source
* @ param resource $target
2013-10-14 19:33:23 +00:00
* @ return array the number of bytes copied and result
2012-02-27 11:04:04 +00:00
*/
2012-11-02 18:53:02 +00:00
public static function streamCopy ( $source , $target ) {
2013-08-07 14:38:57 +00:00
if ( ! $source or ! $target ) {
2013-10-14 19:33:23 +00:00
return array ( 0 , false );
2012-02-27 11:04:04 +00:00
}
2015-02-23 11:31:22 +00:00
$bufSize = 8192 ;
2013-02-22 15:43:11 +00:00
$result = true ;
$count = 0 ;
2013-08-07 14:38:57 +00:00
while ( ! feof ( $source )) {
2015-02-23 11:31:22 +00:00
$buf = fread ( $source , $bufSize );
$bytesWritten = fwrite ( $target , $buf );
if ( $bytesWritten !== false ) {
$count += $bytesWritten ;
}
// note: strlen is expensive so only use it when necessary,
// on the last block
if ( $bytesWritten === false
|| ( $bytesWritten < $bufSize && $bytesWritten < strlen ( $buf ))
) {
// write error, could be disk full ?
2013-02-22 13:56:50 +00:00
$result = false ;
2015-02-23 11:31:22 +00:00
break ;
2013-02-22 13:56:50 +00:00
}
2012-02-27 11:04:04 +00:00
}
2013-02-22 15:43:11 +00:00
return array ( $count , $result );
2012-02-27 11:04:04 +00:00
}
2012-04-13 20:59:47 +00:00
2012-02-28 10:16:19 +00:00
/**
* create a temporary file with an unique filename
2013-08-07 14:38:57 +00:00
*
2012-09-23 00:39:11 +00:00
* @ param string $postfix
2012-02-28 10:16:19 +00:00
* @ return string
2014-10-22 15:36:52 +00:00
* @ deprecated Use the TempManager instead
2012-02-28 10:16:19 +00:00
*
* temporary files are automatically cleaned up after the script is finished
*/
2013-08-07 14:38:57 +00:00
public static function tmpFile ( $postfix = '' ) {
2014-10-22 15:36:52 +00:00
return \OC :: $server -> getTempManager () -> getTemporaryFile ( $postfix );
2012-10-18 22:11:20 +00:00
}
2013-01-14 19:30:39 +00:00
2012-03-28 20:30:55 +00:00
/**
* create a temporary folder with an unique filename
2013-08-07 14:38:57 +00:00
*
2012-03-28 20:30:55 +00:00
* @ return string
2014-10-22 15:36:52 +00:00
* @ deprecated Use the TempManager instead
2012-03-28 20:30:55 +00:00
*
* temporary files are automatically cleaned up after the script is finished
*/
2012-09-07 13:22:01 +00:00
public static function tmpFolder () {
2014-10-22 15:36:52 +00:00
return \OC :: $server -> getTempManager () -> getTemporaryFolder ();
2012-10-18 22:11:20 +00:00
}
2012-06-14 10:57:30 +00:00
/**
2013-08-07 14:38:57 +00:00
* Adds a suffix to the name in case the file exists
*
2014-05-11 20:51:30 +00:00
* @ param string $path
* @ param string $filename
2013-08-07 14:38:57 +00:00
* @ return string
*/
2012-09-07 13:22:01 +00:00
public static function buildNotExistingFileName ( $path , $filename ) {
2013-03-08 13:22:04 +00:00
$view = \OC\Files\Filesystem :: getView ();
return self :: buildNotExistingFileNameForView ( $path , $filename , $view );
}
/**
2013-08-07 14:38:57 +00:00
* Adds a suffix to the name in case the file exists
*
2014-05-11 20:51:30 +00:00
* @ param string $path
* @ param string $filename
2013-08-07 14:38:57 +00:00
* @ return string
*/
2013-03-08 13:22:04 +00:00
public static function buildNotExistingFileNameForView ( $path , $filename , \OC\Files\View $view ) {
2013-08-07 14:38:57 +00:00
if ( $path === '/' ) {
$path = '' ;
2012-06-14 10:57:30 +00:00
}
if ( $pos = strrpos ( $filename , '.' )) {
$name = substr ( $filename , 0 , $pos );
$ext = substr ( $filename , $pos );
} else {
$name = $filename ;
2012-09-23 00:39:11 +00:00
$ext = '' ;
2012-06-14 10:57:30 +00:00
}
$newpath = $path . '/' . $filename ;
2013-07-05 13:38:09 +00:00
if ( $view -> file_exists ( $newpath )) {
2013-08-07 14:38:57 +00:00
if ( preg_match_all ( '/\((\d+)\)/' , $name , $matches , PREG_OFFSET_CAPTURE )) {
2013-09-05 09:58:57 +00:00
//Replace the last "(number)" with "(number+1)"
2013-08-07 14:38:57 +00:00
$last_match = count ( $matches [ 0 ]) - 1 ;
$counter = $matches [ 1 ][ $last_match ][ 0 ] + 1 ;
2013-07-05 13:38:09 +00:00
$offset = $matches [ 0 ][ $last_match ][ 1 ];
$match_length = strlen ( $matches [ 0 ][ $last_match ][ 0 ]);
} else {
$counter = 2 ;
2015-04-27 12:45:05 +00:00
$match_length = 0 ;
2013-07-05 13:38:09 +00:00
$offset = false ;
}
do {
2013-08-07 14:38:57 +00:00
if ( $offset ) {
2013-09-05 09:58:57 +00:00
//Replace the last "(number)" with "(number+1)"
2013-08-07 14:38:57 +00:00
$newname = substr_replace ( $name , '(' . $counter . ')' , $offset , $match_length );
2013-07-05 13:38:09 +00:00
} else {
$newname = $name . ' (' . $counter . ')' ;
}
$newpath = $path . '/' . $newname . $ext ;
$counter ++ ;
} while ( $view -> file_exists ( $newpath ));
2012-06-14 10:57:30 +00:00
}
return $newpath ;
}
2012-07-02 18:24:26 +00:00
2013-01-13 13:54:18 +00:00
/**
2014-05-19 15:50:53 +00:00
* Checks if $sub is a subdirectory of $parent
2012-07-02 18:24:26 +00:00
*
2012-09-23 00:39:11 +00:00
* @ param string $sub
* @ param string $parent
2012-04-18 06:20:51 +00:00
* @ return bool
*/
2014-05-11 13:50:59 +00:00
public static function isSubDirectory ( $sub , $parent ) {
2014-05-11 13:49:19 +00:00
$realpathSub = realpath ( $sub );
$realpathParent = realpath ( $parent );
// realpath() may return false in case the directory does not exist
// since we can not be sure how different PHP versions may behave here
// we do an additional check whether realpath returned false
if ( $realpathSub === false || $realpathParent === false ) {
return false ;
}
// Check whether $sub is a subdirectory of $parent
if ( strpos ( $realpathSub , $realpathParent ) === 0 ) {
2013-01-13 13:33:19 +00:00
return true ;
2012-04-26 15:55:00 +00:00
}
2014-05-11 13:49:19 +00:00
2012-04-26 15:55:00 +00:00
return false ;
2012-04-18 06:20:51 +00:00
}
2012-07-02 18:24:26 +00:00
/**
2014-05-19 15:50:53 +00:00
* Returns an array with all keys from input lowercased or uppercased . Numbered indices are left as is .
2013-08-07 14:38:57 +00:00
*
* @ param array $input The array to work on
* @ param int $case Either MB_CASE_UPPER or MB_CASE_LOWER ( default )
* @ param string $encoding The encoding parameter is the character encoding . Defaults to UTF - 8
* @ return array
*
* Returns an array with all keys from input lowercased or uppercased . Numbered indices are left as is .
* based on http :// www . php . net / manual / en / function . array - change - key - case . php #107715
*
*/
2012-09-07 13:22:01 +00:00
public static function mb_array_change_key_case ( $input , $case = MB_CASE_LOWER , $encoding = 'UTF-8' ) {
2012-07-02 18:24:26 +00:00
$case = ( $case != MB_CASE_UPPER ) ? MB_CASE_LOWER : MB_CASE_UPPER ;
$ret = array ();
foreach ( $input as $k => $v ) {
$ret [ mb_convert_case ( $k , $case , $encoding )] = $v ;
}
return $ret ;
}
/**
2014-05-19 15:50:53 +00:00
* replaces a copy of string delimited by the start and ( optionally ) length parameters with the string given in replacement .
2013-01-04 22:00:51 +00:00
*
2014-05-11 20:51:30 +00:00
* @ param string $string
2013-01-04 22:00:51 +00:00
* @ param string $replacement The replacement string .
* @ param int $start If start is positive , the replacing will begin at the start 'th offset into string. If start is negative, the replacing will begin at the start' th character from the end of string .
* @ param int $length Length of the part to be replaced
* @ param string $encoding The encoding parameter is the character encoding . Defaults to UTF - 8
* @ return string
2015-06-19 12:55:04 +00:00
* @ deprecated 8.2 . 0 Use substr_replace () instead .
2013-01-04 22:00:51 +00:00
*/
2015-06-19 12:55:04 +00:00
public static function mb_substr_replace ( $string , $replacement , $start , $length = 0 , $encoding = 'UTF-8' ) {
return substr_replace ( $string , $replacement , $start , $length );
2012-07-02 18:24:26 +00:00
}
/**
2014-05-19 15:50:53 +00:00
* Replace all occurrences of the search string with the replacement string
2013-08-07 14:38:57 +00:00
*
* @ param string $search The value being searched for , otherwise known as the needle .
* @ param string $replace The replacement
* @ param string $subject The string or array being searched and replaced on , otherwise known as the haystack .
* @ param string $encoding The encoding parameter is the character encoding . Defaults to UTF - 8
* @ param int $count If passed , this will be set to the number of replacements performed .
* @ return string
2015-06-19 12:55:04 +00:00
* @ deprecated 8.2 . 0 Use str_replace () instead .
2013-08-07 14:38:57 +00:00
*
*/
2012-07-02 18:24:26 +00:00
public static function mb_str_replace ( $search , $replace , $subject , $encoding = 'UTF-8' , & $count = null ) {
2015-06-19 12:55:04 +00:00
return str_replace ( $search , $replace , $subject , $count );
2012-07-02 18:24:26 +00:00
}
2012-07-24 08:54:56 +00:00
/**
2014-05-19 15:50:53 +00:00
* performs a search in a nested array
2013-08-07 14:38:57 +00:00
* @ param array $haystack the array to be searched
* @ param string $needle the search string
* @ param string $index optional , only search this key name
* @ return mixed the key of the matching field , otherwise false
*
* performs a search in a nested array
*
* taken from http :// www . php . net / manual / en / function . array - search . php #97645
*/
2012-07-24 08:54:56 +00:00
public static function recursiveArraySearch ( $haystack , $needle , $index = null ) {
$aIt = new RecursiveArrayIterator ( $haystack );
$it = new RecursiveIteratorIterator ( $aIt );
2013-08-07 14:38:57 +00:00
while ( $it -> valid ()) {
2012-07-24 08:54:56 +00:00
if ((( isset ( $index ) AND ( $it -> key () == $index )) OR ( ! isset ( $index ))) AND ( $it -> current () == $needle )) {
return $aIt -> key ();
}
$it -> next ();
}
return false ;
}
2012-11-12 12:56:29 +00:00
2012-11-12 13:04:23 +00:00
/**
* Shortens str to maxlen by replacing characters in the middle with '...' , eg .
* ellipsis ( 'a very long string with lots of useless info to make a better example' , 14 ) becomes 'a very ...example'
2013-08-07 14:38:57 +00:00
*
2012-11-12 13:04:23 +00:00
* @ param string $str the string
* @ param string $maxlen the maximum length of the result
* @ return string with at most maxlen characters
*/
2012-11-12 12:56:29 +00:00
public static function ellipsis ( $str , $maxlen ) {
if ( strlen ( $str ) > $maxlen ) {
$characters = floor ( $maxlen / 2 );
return substr ( $str , 0 , $characters ) . '...' . substr ( $str , - 1 * $characters );
}
return $str ;
}
2013-01-04 22:00:51 +00:00
2013-01-18 19:09:03 +00:00
/**
2014-05-19 15:50:53 +00:00
* calculates the maximum upload size respecting system settings , free space and user quota
2013-01-18 19:09:03 +00:00
*
2014-01-27 14:56:57 +00:00
* @ param string $dir the current folder where the user currently operates
2014-02-05 12:36:55 +00:00
* @ param int $freeSpace the number of bytes free on the storage holding $dir , if not set this will be received from the storage directly
* @ return int number of bytes representing
2013-01-18 19:09:03 +00:00
*/
2014-01-27 14:56:57 +00:00
public static function maxUploadFilesize ( $dir , $freeSpace = null ) {
2014-03-06 12:50:53 +00:00
if ( is_null ( $freeSpace ) || $freeSpace < 0 ){
2014-02-05 12:36:55 +00:00
$freeSpace = self :: freeSpace ( $dir );
2013-03-15 15:31:35 +00:00
}
2014-02-05 12:36:55 +00:00
return min ( $freeSpace , self :: uploadLimit ());
2013-12-08 14:59:46 +00:00
}
2012-12-20 16:16:01 +00:00
2013-12-08 14:59:46 +00:00
/**
* Calculate free space left within user quota
2014-05-19 15:50:53 +00:00
*
2014-02-05 12:36:55 +00:00
* @ param string $dir the current folder where the user currently operates
* @ return int number of bytes representing
2013-12-08 14:59:46 +00:00
*/
public static function freeSpace ( $dir ) {
$freeSpace = \OC\Files\Filesystem :: free_space ( $dir );
2014-08-19 12:05:08 +00:00
if ( $freeSpace !== \OCP\Files\FileInfo :: SPACE_UNKNOWN ) {
2013-02-16 02:27:50 +00:00
$freeSpace = max ( $freeSpace , 0 );
2013-12-08 14:59:46 +00:00
return $freeSpace ;
} else {
2015-10-02 12:16:13 +00:00
return ( INF > 0 ) ? INF : PHP_INT_MAX ; // work around https://bugs.php.net/bug.php?id=69188
2013-12-08 14:59:46 +00:00
}
}
2012-12-20 16:16:01 +00:00
2013-12-08 14:59:46 +00:00
/**
* Calculate PHP upload limit
*
2015-04-27 12:45:05 +00:00
* @ return int PHP upload file size limit
2013-12-08 14:59:46 +00:00
*/
public static function uploadLimit () {
$upload_max_filesize = OCP\Util :: computerFileSize ( ini_get ( 'upload_max_filesize' ));
$post_max_size = OCP\Util :: computerFileSize ( ini_get ( 'post_max_size' ));
if (( int ) $upload_max_filesize === 0 and ( int ) $post_max_size === 0 ) {
return INF ;
} elseif (( int ) $upload_max_filesize === 0 or ( int ) $post_max_size === 0 ) {
return max ( $upload_max_filesize , $post_max_size ); //only the non 0 value counts
2013-02-16 02:27:50 +00:00
} else {
2013-12-08 14:59:46 +00:00
return min ( $upload_max_filesize , $post_max_size );
2013-02-16 02:27:50 +00:00
}
2013-01-18 19:09:03 +00:00
}
2013-01-06 21:40:35 +00:00
2013-01-04 22:00:51 +00:00
/**
* Checks if a function is available
2013-08-07 14:38:57 +00:00
*
2013-01-04 22:00:51 +00:00
* @ param string $function_name
* @ return bool
*/
public static function is_function_enabled ( $function_name ) {
if ( ! function_exists ( $function_name )) {
return false ;
}
2014-01-07 13:53:02 +00:00
$disabled = explode ( ',' , ini_get ( 'disable_functions' ));
2014-01-07 18:47:01 +00:00
$disabled = array_map ( 'trim' , $disabled );
2013-01-04 22:00:51 +00:00
if ( in_array ( $function_name , $disabled )) {
return false ;
}
2014-01-07 18:47:01 +00:00
$disabled = explode ( ',' , ini_get ( 'suhosin.executor.func.blacklist' ));
$disabled = array_map ( 'trim' , $disabled );
2013-01-04 22:00:51 +00:00
if ( in_array ( $function_name , $disabled )) {
return false ;
}
return true ;
}
2013-01-06 11:18:21 +00:00
2014-11-20 11:37:59 +00:00
/**
* Try to find a program
* Note : currently windows is not supported
*
* @ param string $program
* @ return null | string
*/
public static function findBinaryPath ( $program ) {
2015-01-09 13:13:02 +00:00
$memcache = \OC :: $server -> getMemCacheFactory () -> create ( 'findBinaryPath' );
if ( $memcache -> hasKey ( $program )) {
return $memcache -> get ( $program );
}
$result = null ;
2014-11-20 11:37:59 +00:00
if ( ! \OC_Util :: runningOnWindows () && self :: is_function_enabled ( 'exec' )) {
2015-01-26 11:32:17 +00:00
$exeSniffer = new ExecutableFinder ();
// Returns null if nothing is found
$result = $exeSniffer -> find ( $program );
if ( empty ( $result )) {
2015-04-14 12:06:58 +00:00
$paths = getenv ( 'PATH' );
if ( empty ( $paths )) {
$paths = '/usr/local/bin /usr/bin /opt/bin /bin' ;
} else {
$paths = str_replace ( ':' , ' ' , getenv ( 'PATH' ));
}
2015-03-02 21:15:07 +00:00
$command = 'find ' . $paths . ' -name ' . escapeshellarg ( $program ) . ' 2> /dev/null' ;
exec ( $command , $output , $returnCode );
if ( count ( $output ) > 0 ) {
2015-01-26 11:32:17 +00:00
$result = escapeshellcmd ( $output [ 0 ]);
}
2014-11-20 11:37:59 +00:00
}
}
2015-01-09 13:13:02 +00:00
$memcache -> set ( $program , $result , 3600 );
return $result ;
2014-11-20 11:37:59 +00:00
}
2013-01-02 13:35:45 +00:00
/**
2013-08-26 22:59:58 +00:00
* Calculate the disc space for the given path
*
* @ param string $path
2014-04-02 15:10:57 +00:00
* @ param \OCP\Files\FileInfo $rootInfo ( optional )
2013-08-26 22:59:58 +00:00
* @ return array
2015-04-27 12:45:05 +00:00
* @ throws \OCP\Files\NotFoundException
2013-01-02 13:35:45 +00:00
*/
2014-04-02 15:10:57 +00:00
public static function getStorageInfo ( $path , $rootInfo = null ) {
2013-11-18 16:29:30 +00:00
// return storage info without adding mount points
2014-03-25 15:37:46 +00:00
$includeExtStorage = \OC_Config :: getValue ( 'quota_include_external_storage' , false );
2014-04-29 13:14:48 +00:00
if ( ! $rootInfo ) {
2014-04-02 15:10:57 +00:00
$rootInfo = \OC\Files\Filesystem :: getFileInfo ( $path , false );
}
2015-01-06 14:56:06 +00:00
if ( ! $rootInfo instanceof \OCP\Files\FileInfo ) {
throw new \OCP\Files\NotFoundException ();
}
2014-04-02 15:10:57 +00:00
$used = $rootInfo -> getSize ();
2013-01-02 13:35:45 +00:00
if ( $used < 0 ) {
$used = 0 ;
}
2014-03-10 14:19:18 +00:00
$quota = 0 ;
$storage = $rootInfo -> getStorage ();
2014-03-25 15:37:46 +00:00
if ( $includeExtStorage && $storage -> instanceOfStorage ( '\OC\Files\Storage\Shared' )) {
$includeExtStorage = false ;
}
if ( $includeExtStorage ) {
$quota = OC_Util :: getUserQuota ( \OCP\User :: getUser ());
2014-08-19 12:05:08 +00:00
if ( $quota !== \OCP\Files\FileInfo :: SPACE_UNLIMITED ) {
2014-03-25 15:37:46 +00:00
// always get free space / total space from root + mount points
return self :: getGlobalStorageInfo ();
}
}
// TODO: need a better way to get total space from storage
2014-06-02 19:52:31 +00:00
if ( $storage -> instanceOfStorage ( '\OC\Files\Storage\Wrapper\Quota' )) {
2015-04-27 12:45:05 +00:00
/** @var \OC\Files\Storage\Wrapper\Quota $storage */
2014-03-10 14:19:18 +00:00
$quota = $storage -> getQuota ();
}
$free = $storage -> free_space ( '' );
2013-08-07 14:38:57 +00:00
if ( $free >= 0 ) {
2013-03-15 15:46:20 +00:00
$total = $free + $used ;
} else {
$total = $free ; //either unknown or unlimited
}
2013-08-27 08:58:17 +00:00
if ( $total > 0 ) {
2014-03-10 14:19:18 +00:00
if ( $quota > 0 && $total > $quota ) {
$total = $quota ;
}
2013-08-27 08:58:17 +00:00
// prevent division by zero or error codes (negative values)
2013-03-15 15:46:20 +00:00
$relative = round (( $used / $total ) * 10000 ) / 100 ;
} else {
$relative = 0 ;
}
2013-01-02 13:35:45 +00:00
2015-06-05 16:21:41 +00:00
$ownerId = $storage -> getOwner ( $path );
$ownerDisplayName = '' ;
$owner = \OC :: $server -> getUserManager () -> get ( $ownerId );
if ( $owner ) {
$ownerDisplayName = $owner -> getDisplayName ();
}
return [
'free' => $free ,
'used' => $used ,
'total' => $total ,
'relative' => $relative ,
'owner' => $ownerId ,
'ownerDisplayName' => $ownerDisplayName ,
];
2013-01-02 13:35:45 +00:00
}
2014-03-25 15:37:46 +00:00
/**
* Get storage info including all mount points and quota
*
* @ return array
*/
private static function getGlobalStorageInfo () {
$quota = OC_Util :: getUserQuota ( \OCP\User :: getUser ());
$rootInfo = \OC\Files\Filesystem :: getFileInfo ( '' , 'ext' );
$used = $rootInfo [ 'size' ];
if ( $used < 0 ) {
$used = 0 ;
}
$total = $quota ;
$free = $quota - $used ;
if ( $total > 0 ) {
if ( $quota > 0 && $total > $quota ) {
$total = $quota ;
}
// prevent division by zero or error codes (negative values)
$relative = round (( $used / $total ) * 10000 ) / 100 ;
} else {
$relative = 0 ;
}
return array ( 'free' => $free , 'used' => $used , 'total' => $total , 'relative' => $relative );
}
2014-11-25 15:12:12 +00:00
/**
* Returns whether the config file is set manually to read - only
* @ return bool
*/
public static function isReadOnlyConfigEnabled () {
return \OC :: $server -> getConfig () -> getSystemValue ( 'config_is_read_only' , false );
}
2011-03-02 21:18:22 +00:00
}