2012-09-07 16:09:41 +04:00
< ? php
/**
* ownCloud
*
* @ author Michael Gapczynski
* @ copyright 2012 Michael Gapczynski mtgap @ owncloud . com
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation ; either
* version 3 of the License , or any later version .
*
* This library 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 along with this library . If not , see < http :// www . gnu . org / licenses />.
*/
/**
* Class to configure the config / mount . php and data / $user / mount . php files
*/
class OC_Mount_Config {
const MOUNT_TYPE_GLOBAL = 'global' ;
const MOUNT_TYPE_GROUP = 'group' ;
const MOUNT_TYPE_USER = 'user' ;
/**
* Get details on each of the external storage backends , used for the mount config UI
* If a custom UI is needed , add the key 'custom' and a javascript file with that name will be loaded
* If the configuration parameter should be secret , add a '*' to the beginning of the value
* If the configuration parameter is a boolean , add a '!' to the beginning of the value
* If the configuration parameter is optional , add a '&' to the beginning of the value
2013-04-19 00:20:52 +04:00
* If the configuration parameter is hidden , add a '#' to the beginning of the value
2014-02-06 19:30:58 +04:00
* @ return string
2012-09-07 16:09:41 +04:00
*/
public static function getBackends () {
2013-02-22 20:21:57 +04:00
2012-12-15 05:21:26 +04:00
$backends [ '\OC\Files\Storage\Local' ] = array (
2012-11-30 19:27:11 +04:00
'backend' => 'Local' ,
'configuration' => array (
2012-12-11 00:44:43 +04:00
'datadir' => 'Location' ));
2012-12-15 05:21:26 +04:00
$backends [ '\OC\Files\Storage\AmazonS3' ] = array (
2012-12-11 00:44:43 +04:00
'backend' => 'Amazon S3' ,
'configuration' => array (
2013-07-03 19:58:44 +04:00
'key' => 'Access Key' ,
'secret' => '*Secret Key' ,
'bucket' => 'Bucket' ,
2013-12-02 19:55:43 +04:00
'hostname' => '&Hostname (optional)' ,
'port' => '&Port (optional)' ,
'region' => '&Region (optional)' ,
2013-07-03 19:58:44 +04:00
'use_ssl' => '!Enable SSL' ,
'use_path_style' => '!Enable Path Style' ));
2012-12-11 00:44:43 +04:00
2012-12-15 05:21:26 +04:00
$backends [ '\OC\Files\Storage\Dropbox' ] = array (
2012-12-11 00:44:43 +04:00
'backend' => 'Dropbox' ,
'configuration' => array (
'configured' => '#configured' ,
'app_key' => 'App key' ,
'app_secret' => 'App secret' ,
'token' => '#token' ,
'token_secret' => '#token_secret' ),
'custom' => 'dropbox' );
2012-12-15 05:21:26 +04:00
if ( OC_Mount_Config :: checkphpftp ()) $backends [ '\OC\Files\Storage\FTP' ] = array (
2012-12-11 00:44:43 +04:00
'backend' => 'FTP' ,
'configuration' => array (
'host' => 'URL' ,
'user' => 'Username' ,
'password' => '*Password' ,
'root' => '&Root' ,
'secure' => '!Secure ftps://' ));
2013-04-23 14:36:30 +04:00
if ( OC_Mount_Config :: checkcurl ()) $backends [ '\OC\Files\Storage\Google' ] = array (
2012-12-11 00:44:43 +04:00
'backend' => 'Google Drive' ,
'configuration' => array (
'configured' => '#configured' ,
2013-05-17 04:09:32 +04:00
'client_id' => 'Client ID' ,
'client_secret' => 'Client secret' ,
'token' => '#token' ),
2012-12-11 00:44:43 +04:00
'custom' => 'google' );
2013-02-22 20:21:57 +04:00
2013-10-22 15:34:24 +04:00
if ( OC_Mount_Config :: checkcurl ()) {
$backends [ '\OC\Files\Storage\Swift' ] = array (
'backend' => 'OpenStack Object Storage' ,
'configuration' => array (
2013-10-29 12:19:43 +04:00
'user' => 'Username (required)' ,
'bucket' => 'Bucket (required)' ,
2013-10-29 13:21:50 +04:00
'region' => '&Region (optional for OpenStack Object Storage)' ,
2013-10-29 12:19:43 +04:00
'key' => '*API Key (required for Rackspace Cloud Files)' ,
2013-10-29 13:21:50 +04:00
'tenant' => '&Tenantname (required for OpenStack Object Storage)' ,
2013-10-29 12:19:43 +04:00
'password' => '*Password (required for OpenStack Object Storage)' ,
2013-10-29 13:21:50 +04:00
'service_name' => '&Service Name (required for OpenStack Object Storage)' ,
'url' => '&URL of identity endpoint (required for OpenStack Object Storage)' ,
'timeout' => '&Timeout of HTTP requests in seconds (optional)' ,
2013-10-22 15:34:24 +04:00
)
);
}
2013-02-22 20:21:57 +04:00
2013-08-15 14:00:02 +04:00
if ( ! OC_Util :: runningOnWindows ()) {
if ( OC_Mount_Config :: checksmbclient ()) {
$backends [ '\OC\Files\Storage\SMB' ] = array (
'backend' => 'SMB / CIFS' ,
'configuration' => array (
'host' => 'URL' ,
'user' => 'Username' ,
'password' => '*Password' ,
'share' => 'Share' ,
'root' => '&Root' ));
}
}
2013-02-22 20:21:57 +04:00
2013-10-09 18:54:36 +04:00
if ( OC_Mount_Config :: checkcurl ()){
$backends [ '\OC\Files\Storage\DAV' ] = array (
'backend' => 'WebDAV' ,
'configuration' => array (
'host' => 'URL' ,
'user' => 'Username' ,
'password' => '*Password' ,
'root' => '&Root' ,
'secure' => '!Secure https://' ));
$backends [ '\OC\Files\Storage\OwnCloud' ] = array (
'backend' => 'ownCloud' ,
'configuration' => array (
'host' => 'URL' ,
'user' => 'Username' ,
'password' => '*Password' ,
'root' => '&Remote subfolder' ,
'secure' => '!Secure https://' ));
}
2013-02-22 20:21:57 +04:00
2013-02-10 18:37:05 +04:00
$backends [ '\OC\Files\Storage\SFTP' ] = array (
2012-12-26 21:03:16 +04:00
'backend' => 'SFTP' ,
'configuration' => array (
'host' => 'URL' ,
2013-02-22 20:21:57 +04:00
'user' => 'Username' ,
'password' => '*Password' ,
2012-12-26 21:03:16 +04:00
'root' => '&Root' ));
2012-12-11 00:44:43 +04:00
2013-04-12 17:51:58 +04:00
$backends [ '\OC\Files\Storage\iRODS' ] = array (
'backend' => 'iRODS' ,
'configuration' => array (
'host' => 'Host' ,
'port' => 'Port' ,
2013-04-19 00:20:52 +04:00
'use_logon_credentials' => '!Use ownCloud login' ,
2013-04-12 17:51:58 +04:00
'user' => 'Username' ,
'password' => '*Password' ,
2013-04-26 19:37:41 +04:00
'auth_mode' => 'Authentication Mode' ,
2013-04-12 17:51:58 +04:00
'zone' => 'Zone' ));
2012-12-11 00:44:43 +04:00
return ( $backends );
2012-09-07 16:09:41 +04:00
}
/**
* Get the system mount points
* The returned array is not in the same format as getUserMountPoints ()
* @ return array
*/
public static function getSystemMountPoints () {
$mountPoints = self :: readData ( false );
$backends = self :: getBackends ();
$system = array ();
if ( isset ( $mountPoints [ self :: MOUNT_TYPE_GROUP ])) {
foreach ( $mountPoints [ self :: MOUNT_TYPE_GROUP ] as $group => $mounts ) {
foreach ( $mounts as $mountPoint => $mount ) {
2013-01-03 21:07:04 +04:00
// Update old classes to new namespace
if ( strpos ( $mount [ 'class' ], 'OC_Filestorage_' ) !== false ) {
2013-01-03 21:13:45 +04:00
$mount [ 'class' ] = '\OC\Files\Storage\\' . substr ( $mount [ 'class' ], 15 );
2013-01-03 21:07:04 +04:00
}
2012-09-07 16:09:41 +04:00
// Remove '/$user/files/' from mount point
$mountPoint = substr ( $mountPoint , 13 );
// Merge the mount point into the current mount points
if ( isset ( $system [ $mountPoint ]) && $system [ $mountPoint ][ 'configuration' ] == $mount [ 'options' ]) {
2012-11-30 19:27:11 +04:00
$system [ $mountPoint ][ 'applicable' ][ 'groups' ]
= array_merge ( $system [ $mountPoint ][ 'applicable' ][ 'groups' ], array ( $group ));
2012-09-07 16:09:41 +04:00
} else {
2012-11-30 19:27:11 +04:00
$system [ $mountPoint ] = array (
'class' => $mount [ 'class' ],
'backend' => $backends [ $mount [ 'class' ]][ 'backend' ],
'configuration' => $mount [ 'options' ],
2012-12-24 22:45:52 +04:00
'applicable' => array ( 'groups' => array ( $group ), 'users' => array ()),
'status' => self :: getBackendStatus ( $mount [ 'class' ], $mount [ 'options' ])
);
2012-09-07 16:09:41 +04:00
}
}
}
}
if ( isset ( $mountPoints [ self :: MOUNT_TYPE_USER ])) {
foreach ( $mountPoints [ self :: MOUNT_TYPE_USER ] as $user => $mounts ) {
foreach ( $mounts as $mountPoint => $mount ) {
2013-01-03 21:07:04 +04:00
// Update old classes to new namespace
if ( strpos ( $mount [ 'class' ], 'OC_Filestorage_' ) !== false ) {
2013-01-03 21:13:45 +04:00
$mount [ 'class' ] = '\OC\Files\Storage\\' . substr ( $mount [ 'class' ], 15 );
2013-01-03 21:07:04 +04:00
}
2012-09-07 16:09:41 +04:00
// Remove '/$user/files/' from mount point
$mountPoint = substr ( $mountPoint , 13 );
// Merge the mount point into the current mount points
if ( isset ( $system [ $mountPoint ]) && $system [ $mountPoint ][ 'configuration' ] == $mount [ 'options' ]) {
2012-11-30 19:27:11 +04:00
$system [ $mountPoint ][ 'applicable' ][ 'users' ]
= array_merge ( $system [ $mountPoint ][ 'applicable' ][ 'users' ], array ( $user ));
2012-09-07 16:09:41 +04:00
} else {
2012-12-24 22:45:52 +04:00
$system [ $mountPoint ] = array (
'class' => $mount [ 'class' ],
2012-11-30 19:27:11 +04:00
'backend' => $backends [ $mount [ 'class' ]][ 'backend' ],
'configuration' => $mount [ 'options' ],
2012-12-24 22:45:52 +04:00
'applicable' => array ( 'groups' => array (), 'users' => array ( $user )),
'status' => self :: getBackendStatus ( $mount [ 'class' ], $mount [ 'options' ])
);
2012-09-07 16:09:41 +04:00
}
}
}
}
return $system ;
}
/**
* Get the personal mount points of the current user
* The returned array is not in the same format as getUserMountPoints ()
* @ return array
*/
public static function getPersonalMountPoints () {
$mountPoints = self :: readData ( true );
$backends = self :: getBackends ();
$uid = OCP\User :: getUser ();
$personal = array ();
if ( isset ( $mountPoints [ self :: MOUNT_TYPE_USER ][ $uid ])) {
foreach ( $mountPoints [ self :: MOUNT_TYPE_USER ][ $uid ] as $mountPoint => $mount ) {
2013-01-03 21:07:04 +04:00
// Update old classes to new namespace
if ( strpos ( $mount [ 'class' ], 'OC_Filestorage_' ) !== false ) {
2013-01-03 21:13:45 +04:00
$mount [ 'class' ] = '\OC\Files\Storage\\' . substr ( $mount [ 'class' ], 15 );
2013-01-03 21:07:04 +04:00
}
2012-09-07 16:09:41 +04:00
// Remove '/uid/files/' from mount point
2012-12-24 22:45:52 +04:00
$personal [ substr ( $mountPoint , strlen ( $uid ) + 8 )] = array (
'class' => $mount [ 'class' ],
'backend' => $backends [ $mount [ 'class' ]][ 'backend' ],
'configuration' => $mount [ 'options' ],
'status' => self :: getBackendStatus ( $mount [ 'class' ], $mount [ 'options' ])
);
2012-09-07 16:09:41 +04:00
}
}
return $personal ;
}
2012-12-24 22:45:52 +04:00
private static function getBackendStatus ( $class , $options ) {
foreach ( $options as & $option ) {
$option = str_replace ( '$user' , OCP\User :: getUser (), $option );
}
if ( class_exists ( $class )) {
try {
2012-12-28 21:00:48 +04:00
$storage = new $class ( $options );
return $storage -> test ();
2012-12-24 22:45:52 +04:00
} catch ( Exception $exception ) {
2013-12-02 19:55:43 +04:00
\OCP\Util :: logException ( 'files_external' , $exception );
2012-12-24 22:45:52 +04:00
return false ;
}
}
return false ;
}
2012-09-07 16:09:41 +04:00
/**
* Add a mount point to the filesystem
* @ param string Mount point
* @ param string Backend class
* @ param array Backend parameters for the class
* @ param string MOUNT_TYPE_GROUP | MOUNT_TYPE_USER
* @ param string User or group to apply mount to
* @ param bool Personal or system mount point i . e . is this being called from the personal or admin page
2014-02-06 19:30:58 +04:00
* @ param string $mountPoint
* @ param string $class
* @ param string $mountType
* @ param string $applicable
2012-09-07 16:09:41 +04:00
* @ return bool
*/
2012-11-30 19:27:11 +04:00
public static function addMountPoint ( $mountPoint ,
$class ,
$classOptions ,
$mountType ,
$applicable ,
$isPersonal = false ) {
2013-11-21 20:21:51 +04:00
$mountPoint = OC\Files\Filesystem :: normalizePath ( $mountPoint );
2013-11-22 21:36:27 +04:00
if ( $mountPoint === '' || $mountPoint === '/' || $mountPoint == '/Shared' ) {
// can't mount at root or "Shared" folder
2013-11-21 20:21:51 +04:00
return false ;
}
2012-09-07 16:09:41 +04:00
if ( $isPersonal ) {
// Verify that the mount point applies for the current user
// Prevent non-admin users from mounting local storage
2012-09-07 20:30:48 +04:00
if ( $applicable != OCP\User :: getUser () || $class == '\OC\Files\Storage\Local' ) {
2012-09-07 16:09:41 +04:00
return false ;
}
$mountPoint = '/' . $applicable . '/files/' . ltrim ( $mountPoint , '/' );
} else {
$mountPoint = '/$user/files/' . ltrim ( $mountPoint , '/' );
}
$mount = array ( $applicable => array ( $mountPoint => array ( 'class' => $class , 'options' => $classOptions )));
$mountPoints = self :: readData ( $isPersonal );
// Merge the new mount point into the current mount points
if ( isset ( $mountPoints [ $mountType ])) {
if ( isset ( $mountPoints [ $mountType ][ $applicable ])) {
2012-11-30 19:27:11 +04:00
$mountPoints [ $mountType ][ $applicable ]
= array_merge ( $mountPoints [ $mountType ][ $applicable ], $mount [ $applicable ]);
2012-09-07 16:09:41 +04:00
} else {
$mountPoints [ $mountType ] = array_merge ( $mountPoints [ $mountType ], $mount );
}
} else {
$mountPoints [ $mountType ] = $mount ;
}
self :: writeData ( $isPersonal , $mountPoints );
2012-12-24 22:45:52 +04:00
return self :: getBackendStatus ( $class , $classOptions );
2012-09-07 16:09:41 +04:00
}
/**
*
* @ param string Mount point
* @ param string MOUNT_TYPE_GROUP | MOUNT_TYPE_USER
* @ param string User or group to remove mount from
* @ param bool Personal or system mount point
* @ return bool
*/
public static function removeMountPoint ( $mountPoint , $mountType , $applicable , $isPersonal = false ) {
// Verify that the mount point applies for the current user
if ( $isPersonal ) {
if ( $applicable != OCP\User :: getUser ()) {
return false ;
}
$mountPoint = '/' . $applicable . '/files/' . ltrim ( $mountPoint , '/' );
} else {
$mountPoint = '/$user/files/' . ltrim ( $mountPoint , '/' );
}
$mountPoints = self :: readData ( $isPersonal );
// Remove mount point
unset ( $mountPoints [ $mountType ][ $applicable ][ $mountPoint ]);
// Unset parent arrays if empty
if ( empty ( $mountPoints [ $mountType ][ $applicable ])) {
unset ( $mountPoints [ $mountType ][ $applicable ]);
if ( empty ( $mountPoints [ $mountType ])) {
unset ( $mountPoints [ $mountType ]);
}
}
self :: writeData ( $isPersonal , $mountPoints );
return true ;
}
/**
* Read the mount points in the config file into an array
* @ param bool Personal or system config file
2014-02-06 19:30:58 +04:00
* @ param boolean $isPersonal
2012-09-07 16:09:41 +04:00
* @ return array
*/
private static function readData ( $isPersonal ) {
2013-02-16 04:30:44 +04:00
$parser = new \OC\ArrayParser ();
2012-09-07 16:09:41 +04:00
if ( $isPersonal ) {
2013-02-16 04:50:40 +04:00
$phpFile = OC_User :: getHome ( OCP\User :: getUser ()) . '/mount.php' ;
$jsonFile = OC_User :: getHome ( OCP\User :: getUser ()) . '/mount.json' ;
2012-09-07 16:09:41 +04:00
} else {
2013-03-10 05:25:03 +04:00
$datadir = \OC_Config :: getValue ( " datadirectory " , \OC :: $SERVERROOT . " /data " );
2013-02-16 04:50:40 +04:00
$phpFile = OC :: $SERVERROOT . '/config/mount.php' ;
2013-03-10 05:25:03 +04:00
$jsonFile = $datadir . '/mount.json' ;
2012-09-07 16:09:41 +04:00
}
2013-02-16 04:50:40 +04:00
if ( is_file ( $jsonFile )) {
$mountPoints = json_decode ( file_get_contents ( $jsonFile ), true );
if ( is_array ( $mountPoints )) {
return $mountPoints ;
}
} elseif ( is_file ( $phpFile )) {
$mountPoints = $parser -> parsePHP ( file_get_contents ( $phpFile ));
2012-09-07 16:09:41 +04:00
if ( is_array ( $mountPoints )) {
return $mountPoints ;
}
}
return array ();
}
/**
* Write the mount points to the config file
* @ param bool Personal or system config file
* @ param array Mount points
2014-02-06 19:30:58 +04:00
* @ param boolean $isPersonal
2012-09-07 16:09:41 +04:00
*/
private static function writeData ( $isPersonal , $data ) {
if ( $isPersonal ) {
2013-02-16 04:50:40 +04:00
$file = OC_User :: getHome ( OCP\User :: getUser ()) . '/mount.json' ;
2012-09-07 16:09:41 +04:00
} else {
2013-03-10 05:25:03 +04:00
$datadir = \OC_Config :: getValue ( " datadirectory " , \OC :: $SERVERROOT . " /data " );
$file = $datadir . '/mount.json' ;
2012-09-07 16:09:41 +04:00
}
2013-02-19 03:48:38 +04:00
$content = json_encode ( $data );
2012-09-07 16:09:41 +04:00
@ file_put_contents ( $file , $content );
2013-04-06 14:21:21 +04:00
@ chmod ( $file , 0640 );
2012-09-07 16:09:41 +04:00
}
/**
* Returns all user uploaded ssl root certificates
* @ return array
*/
public static function getCertificates () {
2013-12-17 13:13:14 +04:00
$path = OC_User :: getHome ( OC_User :: getUser ()) . '/files_external/uploads/' ;
2012-11-06 00:37:59 +04:00
\OCP\Util :: writeLog ( 'files_external' , 'checking path ' . $path , \OCP\Util :: INFO );
2012-11-30 19:27:11 +04:00
if ( ! is_dir ( $path )) {
2012-11-06 00:37:59 +04:00
//path might not exist (e.g. non-standard OC_User::getHome() value)
//in this case create full path using 3rd (recursive=true) parameter.
mkdir ( $path , 0777 , true );
}
2012-09-07 16:09:41 +04:00
$result = array ();
$handle = opendir ( $path );
2013-09-05 13:58:57 +04:00
if ( ! is_resource ( $handle )) {
2012-10-12 16:52:22 +04:00
return array ();
}
2012-09-07 16:09:41 +04:00
while ( false !== ( $file = readdir ( $handle ))) {
2012-11-30 19:27:11 +04:00
if ( $file != '.' && $file != '..' ) $result [] = $file ;
2012-09-07 16:09:41 +04:00
}
return $result ;
}
/**
* creates certificate bundle
*/
public static function createCertificateBundle () {
2013-12-17 13:13:14 +04:00
$path = OC_User :: getHome ( OC_User :: getUser ()) . '/files_external' ;
2012-09-07 16:09:41 +04:00
$certs = OC_Mount_Config :: getCertificates ();
$fh_certs = fopen ( $path . " /rootcerts.crt " , 'w' );
foreach ( $certs as $cert ) {
$file = $path . '/uploads/' . $cert ;
$fh = fopen ( $file , " r " );
$data = fread ( $fh , filesize ( $file ));
fclose ( $fh );
if ( strpos ( $data , 'BEGIN CERTIFICATE' )) {
fwrite ( $fh_certs , $data );
2012-09-21 18:54:08 +04:00
fwrite ( $fh_certs , " \r \n " );
2012-09-07 16:09:41 +04:00
}
}
fclose ( $fh_certs );
return true ;
}
2012-12-11 00:10:28 +04:00
/**
2013-01-14 23:30:39 +04:00
* check if smbclient is installed
2012-12-11 00:10:28 +04:00
*/
public static function checksmbclient () {
2012-12-11 16:20:20 +04:00
if ( function_exists ( 'shell_exec' )) {
2013-12-27 21:10:47 +04:00
$output = shell_exec ( 'which smbclient 2> /dev/null' );
2013-08-17 14:58:10 +04:00
return ! empty ( $output );
2012-12-11 16:20:20 +04:00
} else {
2013-08-17 14:58:10 +04:00
return false ;
2012-12-11 16:20:20 +04:00
}
2012-12-11 00:10:28 +04:00
}
/**
2013-02-22 20:21:57 +04:00
* check if php - ftp is installed
2012-12-11 00:10:28 +04:00
*/
public static function checkphpftp () {
if ( function_exists ( 'ftp_login' )) {
2013-08-17 14:58:10 +04:00
return true ;
2012-12-11 00:10:28 +04:00
} else {
2013-08-17 14:58:10 +04:00
return false ;
2012-12-11 00:10:28 +04:00
}
}
2013-04-23 14:36:30 +04:00
/**
* check if curl is installed
*/
public static function checkcurl () {
2013-08-17 14:58:10 +04:00
return function_exists ( 'curl_init' );
2013-04-23 14:36:30 +04:00
}
2012-12-11 00:10:28 +04:00
/**
* check dependencies
*/
public static function checkDependencies () {
2012-12-11 17:07:01 +04:00
$l = new OC_L10N ( 'files_external' );
2012-12-11 00:10:28 +04:00
$txt = '' ;
2013-08-15 14:00:02 +04:00
if ( ! OC_Util :: runningOnWindows ()) {
if ( ! OC_Mount_Config :: checksmbclient ()) {
$txt .= $l -> t ( '<b>Warning:</b> "smbclient" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it.' ) . '<br />' ;
}
2013-02-14 20:57:19 +04:00
}
if ( ! OC_Mount_Config :: checkphpftp ()) {
2013-02-15 18:54:51 +04:00
$txt .= $l -> t ( '<b>Warning:</b> The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it.' ) . '<br />' ;
2013-02-14 20:57:19 +04:00
}
2013-04-23 14:36:30 +04:00
if ( ! OC_Mount_Config :: checkcurl ()) {
$txt .= $l -> t ( '<b>Warning:</b> The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it.' ) . '<br />' ;
}
2012-12-11 00:10:28 +04:00
2013-08-17 14:58:10 +04:00
return $txt ;
2012-12-11 00:10:28 +04:00
}
2012-09-07 16:09:41 +04:00
}