summaryrefslogtreecommitdiffstats
path: root/apps/files_external/lib/config.php
blob: 9a8b95c14c999c00f1e3ad3b07ce36cb7e75e140 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
<?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
	* If the configuration parameter is hidden, add a '#' to the beginning of the value
	* @return string
	*/
	public static function getBackends() {

		$backends['\OC\Files\Storage\Local']=array(
				'backend' => 'Local',
				'configuration' => array(
					'datadir' => 'Location'));

		$backends['\OC\Files\Storage\AmazonS3']=array(
			'backend' => 'Amazon S3',
			'configuration' => array(
				'key' => 'Access Key',
				'secret' => '*Secret Key',
				'bucket' => 'Bucket',
				'hostname' => '&Hostname (optional)',
				'port' => '&Port (optional)',
				'region' => '&Region (optional)',
				'use_ssl' => '!Enable SSL',
				'use_path_style' => '!Enable Path Style'));

		$backends['\OC\Files\Storage\Dropbox']=array(
			'backend' => 'Dropbox',
			'configuration' => array(
				'configured' => '#configured',
				'app_key' => 'App key',
				'app_secret' => '*App secret',
				'token' => '#token',
				'token_secret' => '#token_secret'),
				'custom' => 'dropbox');

		if(OC_Mount_Config::checkphpftp()) $backends['\OC\Files\Storage\FTP']=array(
			'backend' => 'FTP',
			'configuration' => array(
				'host' => 'Hostname',
				'user' => 'Username',
				'password' => '*Password',
				'root' => '&Root',
				'secure' => '!Secure ftps://'));

		if(OC_Mount_Config::checkcurl()) $backends['\OC\Files\Storage\Google']=array(
			'backend' => 'Google Drive',
			'configuration' => array(
				'configured' => '#configured',
				'client_id' => 'Client ID',
				'client_secret' => '*Client secret',
				'token' => '#token'),
				'custom' => 'google');

		if(OC_Mount_Config::checkcurl()) {
			$backends['\OC\Files\Storage\Swift'] = array(
				'backend' => 'OpenStack Object Storage',
				'configuration' => array(
					'user' => 'Username (required)',
					'bucket' => 'Bucket (required)',
					'region' => '&Region (optional for OpenStack Object Storage)',
					'key' => '*API Key (required for Rackspace Cloud Files)',
					'tenant' => '&Tenantname (required for OpenStack Object Storage)',
					'password' => '*Password (required for OpenStack Object Storage)',
					'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)',
				)
			);
                }

		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'));
			}
		}

		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://'));
		}

		$backends['\OC\Files\Storage\SFTP']=array(
			'backend' => 'SFTP',
			'configuration' => array(
				'host' => 'URL',
				'user' => 'Username',
				'password' => '*Password',
				'root' => '&Root'));

		$backends['\OC\Files\Storage\iRODS']=array(
			'backend' => 'iRODS',
			'configuration' => array(
				'host' => 'Host',
				'port' => 'Port',
				'use_logon_credentials' => '!Use ownCloud login',
				'user' => 'Username',
				'password' => '*Password',
				'auth_mode' => 'Authentication Mode',
				'zone' => 'Zone'));

		return($backends);
	}

	/**
	* 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) {
					// Update old classes to new namespace
					if (strpos($mount['class'], 'OC_Filestorage_') !== false) {
						$mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15);
					}
					// 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']) {
						$system[$mountPoint]['applicable']['groups']
							= array_merge($system[$mountPoint]['applicable']['groups'], array($group));
					} else {
						$system[$mountPoint] = array(
							'class' => $mount['class'],
							'backend' => $backends[$mount['class']]['backend'],
							'configuration' => $mount['options'],
							'applicable' => array('groups' => array($group), 'users' => array()),
							'status' => self::getBackendStatus($mount['class'], $mount['options'])
						);
					}
				}
			}
		}
		if (isset($mountPoints[self::MOUNT_TYPE_USER])) {
			foreach ($mountPoints[self::MOUNT_TYPE_USER] as $user => $mounts) {
				foreach ($mounts as $mountPoint => $mount) {
					// Update old classes to new namespace
					if (strpos($mount['class'], 'OC_Filestorage_') !== false) {
						$mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15);
					}
					// 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']) {
						$system[$mountPoint]['applicable']['users']
							= array_merge($system[$mountPoint]['applicable']['users'], array($user));
					} else {
						$system[$mountPoint] = array(
							'class' => $mount['class'],
							'backend' => $backends[$mount['class']]['backend'],
							'configuration' => $mount['options'],
							'applicable' => array('groups' => array(), 'users' => array($user)),
							'status' => self::getBackendStatus($mount['class'], $mount['options'])
						);
					}
				}
			}
		}
		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) {
				// Update old classes to new namespace
				if (strpos($mount['class'], 'OC_Filestorage_') !== false) {
					$mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15);
				}
				// Remove '/uid/files/' from mount point
				$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'])
				);
			}
		}
		return $personal;
	}

	private static function getBackendStatus($class, $options) {
		foreach ($options as &$option) {
			$option = str_replace('$user', OCP\User::getUser(), $option);
		}
		if (class_exists($class)) {
			try {
				$storage = new $class($options);
				return $storage->test();
			} catch (Exception $exception) {
				\OCP\Util::logException('files_external', $exception);
				return false;
			}
		}
		return false;
	}

	/**
	* Add a mount point to the filesystem
	* @param string $mountPoint Mount point
	* @param string $class Backend class
	* @param array Backend parameters for the class
	* @param string $mountType MOUNT_TYPE_GROUP | MOUNT_TYPE_USER
	* @param string $applicable 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
	* @return boolean
	*/
	public static function addMountPoint($mountPoint,
										 $class,
										 $classOptions,
										 $mountType,
										 $applicable,
										 $isPersonal = false) {
		$backends = self::getBackends();
		$mountPoint = OC\Files\Filesystem::normalizePath($mountPoint);
		if ($mountPoint === '' || $mountPoint === '/' || $mountPoint == '/Shared') {
			// can't mount at root or "Shared" folder
			return false;
		}

		if (!isset($backends[$class])) {
			// invalid backend
			return false;
		}	
		if ($isPersonal) {
			// Verify that the mount point applies for the current user
			// Prevent non-admin users from mounting local storage
			if ($applicable !== OCP\User::getUser() || strtolower($class) === '\oc\files\storage\local') {
				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])) {
				$mountPoints[$mountType][$applicable]
					= array_merge($mountPoints[$mountType][$applicable], $mount[$applicable]);
			} else {
				$mountPoints[$mountType] = array_merge($mountPoints[$mountType], $mount);
			}
		} else {
			$mountPoints[$mountType] = $mount;
		}
		self::writeData($isPersonal, $mountPoints);
		return self::getBackendStatus($class, $classOptions);
	}

	/**
	*
	* @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 boolean $isPersonal Personal or system config file
	* @return array
	*/
	private static function readData($isPersonal) {
		$parser = new \OC\ArrayParser();
		if ($isPersonal) {
			$phpFile = OC_User::getHome(OCP\User::getUser()).'/mount.php';
			$jsonFile = OC_User::getHome(OCP\User::getUser()).'/mount.json';
		} else {
			$phpFile = OC::$SERVERROOT.'/config/mount.php';
			$jsonFile = \OC_Config::getValue("mount_file", \OC::$SERVERROOT . "/data/mount.json");
		}
		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));
			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
	* @param boolean $isPersonal
	*/
	private static function writeData($isPersonal, $data) {
		if ($isPersonal) {
			$file = OC_User::getHome(OCP\User::getUser()).'/mount.json';
		} else {
			$file = \OC_Config::getValue("mount_file", \OC::$SERVERROOT . "/data/mount.json");
		}
		$content = json_encode($data);
		@file_put_contents($file, $content);
		@chmod($file, 0640);
	}

	/**
	 * Returns all user uploaded ssl root certificates
	 * @return array
	 */
	public static function getCertificates() {
		$path=OC_User::getHome(OC_User::getUser()) . '/files_external/uploads/';
		\OCP\Util::writeLog('files_external', 'checking path '.$path, \OCP\Util::INFO);
		if ( ! is_dir($path)) {
			//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);
		}
		$result = array();
		$handle = opendir($path);
		if(!is_resource($handle)) {
			return array();
		}
		while (false !== ($file = readdir($handle))) {
			if ($file != '.' && $file != '..') $result[] = $file;
		}
		return $result;
	}

	/**
	 * creates certificate bundle
	 */
	public static function createCertificateBundle() {
		$path=OC_User::getHome(OC_User::getUser()) . '/files_external';

		$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);
				fwrite($fh_certs, "\r\n");
			}
		}

		fclose($fh_certs);

		return true;
	}

	/**
	 * check if smbclient is installed
	 */
	public static function checksmbclient() {
		if(function_exists('shell_exec')) {
			$output=shell_exec('which smbclient 2> /dev/null');
			return !empty($output);
		}else{
			return false;
		}
	}

	/**
	 * check if php-ftp is installed
	 */
	public static function checkphpftp() {
		if(function_exists('ftp_login')) {
			return true;
		}else{
			return false;
		}
	}

	/**
	 * check if curl is installed
	 */
	public static function checkcurl() {
		return function_exists('curl_init');
	}

	/**
	 * check dependencies
	 */
	public static function checkDependencies() {
		$l= new OC_L10N('files_external');
		$txt='';
		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 />';
			}
		}
		if(!OC_Mount_Config::checkphpftp()) {
			$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 />';
		}
		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 />';
		}

		return $txt;
	}
}