Passed
Push — master ( b48341...39d134 )
by Roeland
17:15 queued 04:36
created
apps/files_external/lib/config.php 2 patches
Indentation   +409 added lines, -409 removed lines patch added patch discarded remove patch
@@ -55,413 +55,413 @@
 block discarded – undo
55 55
  * Class to configure mount.json globally and for users
56 56
  */
57 57
 class OC_Mount_Config {
58
-	// TODO: make this class non-static and give it a proper namespace
59
-
60
-	const MOUNT_TYPE_GLOBAL = 'global';
61
-	const MOUNT_TYPE_GROUP = 'group';
62
-	const MOUNT_TYPE_USER = 'user';
63
-	const MOUNT_TYPE_PERSONAL = 'personal';
64
-
65
-	// whether to skip backend test (for unit tests, as this static class is not mockable)
66
-	public static $skipTest = false;
67
-
68
-	/** @var Application */
69
-	public static $app;
70
-
71
-	/**
72
-	 * @param string $class
73
-	 * @param array $definition
74
-	 * @return bool
75
-	 * @deprecated 8.2.0 use \OCA\Files_External\Service\BackendService::registerBackend()
76
-	 */
77
-	public static function registerBackend($class, $definition) {
78
-		$backendService = self::$app->getContainer()->query(BackendService::class);
79
-		$auth = self::$app->getContainer()->query(Builtin::class);
80
-
81
-		$backendService->registerBackend(new LegacyBackend($class, $definition, $auth));
82
-
83
-		return true;
84
-	}
85
-
86
-	/**
87
-	 * Returns the mount points for the given user.
88
-	 * The mount point is relative to the data directory.
89
-	 *
90
-	 * @param string $uid user
91
-	 * @return array of mount point string as key, mountpoint config as value
92
-	 *
93
-	 * @deprecated 8.2.0 use UserGlobalStoragesService::getStorages() and UserStoragesService::getStorages()
94
-	 */
95
-	public static function getAbsoluteMountPoints($uid) {
96
-		$mountPoints = array();
97
-
98
-		$userGlobalStoragesService = self::$app->getContainer()->query(UserGlobalStoragesService::class);
99
-		$userStoragesService = self::$app->getContainer()->query(UserStoragesService::class);
100
-		$user = self::$app->getContainer()->query(IUserManager::class)->get($uid);
101
-
102
-		$userGlobalStoragesService->setUser($user);
103
-		$userStoragesService->setUser($user);
104
-
105
-		foreach ($userGlobalStoragesService->getStorages() as $storage) {
106
-			/** @var \OCA\Files_External\Lib\StorageConfig $storage */
107
-			$mountPoint = '/'.$uid.'/files'.$storage->getMountPoint();
108
-			$mountEntry = self::prepareMountPointEntry($storage, false);
109
-			foreach ($mountEntry['options'] as &$option) {
110
-				$option = self::substitutePlaceholdersInConfig($option);
111
-			}
112
-			$mountPoints[$mountPoint] = $mountEntry;
113
-		}
114
-
115
-		foreach ($userStoragesService->getStorages() as $storage) {
116
-			$mountPoint = '/'.$uid.'/files'.$storage->getMountPoint();
117
-			$mountEntry = self::prepareMountPointEntry($storage, true);
118
-			foreach ($mountEntry['options'] as &$option) {
119
-				$option = self::substitutePlaceholdersInConfig($uid, $option);
120
-			}
121
-			$mountPoints[$mountPoint] = $mountEntry;
122
-		}
123
-
124
-		$userGlobalStoragesService->resetUser();
125
-		$userStoragesService->resetUser();
126
-
127
-		return $mountPoints;
128
-	}
129
-
130
-	/**
131
-	 * Get the system mount points
132
-	 *
133
-	 * @return array
134
-	 *
135
-	 * @deprecated 8.2.0 use GlobalStoragesService::getStorages()
136
-	 */
137
-	public static function getSystemMountPoints() {
138
-		$mountPoints = [];
139
-		$service = self::$app->getContainer()->query(GlobalStoragesService::class);
140
-
141
-		foreach ($service->getStorages() as $storage) {
142
-			$mountPoints[] = self::prepareMountPointEntry($storage, false);
143
-		}
144
-
145
-		return $mountPoints;
146
-	}
147
-
148
-	/**
149
-	 * Get the personal mount points of the current user
150
-	 *
151
-	 * @return array
152
-	 *
153
-	 * @deprecated 8.2.0 use UserStoragesService::getStorages()
154
-	 */
155
-	public static function getPersonalMountPoints() {
156
-		$mountPoints = [];
157
-		$service = self::$app->getContainer()->query(UserStoragesService::class);
158
-
159
-		foreach ($service->getStorages() as $storage) {
160
-			$mountPoints[] = self::prepareMountPointEntry($storage, true);
161
-		}
162
-
163
-		return $mountPoints;
164
-	}
165
-
166
-	/**
167
-	 * Convert a StorageConfig to the legacy mountPoints array format
168
-	 * There's a lot of extra information in here, to satisfy all of the legacy functions
169
-	 *
170
-	 * @param StorageConfig $storage
171
-	 * @param bool $isPersonal
172
-	 * @return array
173
-	 */
174
-	private static function prepareMountPointEntry(StorageConfig $storage, $isPersonal) {
175
-		$mountEntry = [];
176
-
177
-		$mountEntry['mountpoint'] = substr($storage->getMountPoint(), 1); // remove leading slash
178
-		$mountEntry['class'] = $storage->getBackend()->getIdentifier();
179
-		$mountEntry['backend'] = $storage->getBackend()->getText();
180
-		$mountEntry['authMechanism'] = $storage->getAuthMechanism()->getIdentifier();
181
-		$mountEntry['personal'] = $isPersonal;
182
-		$mountEntry['options'] = self::decryptPasswords($storage->getBackendOptions());
183
-		$mountEntry['mountOptions'] = $storage->getMountOptions();
184
-		$mountEntry['priority'] = $storage->getPriority();
185
-		$mountEntry['applicable'] = [
186
-			'groups' => $storage->getApplicableGroups(),
187
-			'users' => $storage->getApplicableUsers(),
188
-		];
189
-		// if mountpoint is applicable to all users the old API expects ['all']
190
-		if (empty($mountEntry['applicable']['groups']) && empty($mountEntry['applicable']['users'])) {
191
-			$mountEntry['applicable']['users'] = ['all'];
192
-		}
193
-
194
-		$mountEntry['id'] = $storage->getId();
195
-
196
-		return $mountEntry;
197
-	}
198
-
199
-	/**
200
-	 * fill in the correct values for $user
201
-	 *
202
-	 * @param string $user user value
203
-	 * @param string|array $input
204
-	 * @return string
205
-	 * @deprecated use self::substitutePlaceholdersInConfig($input)
206
-	 */
207
-	public static function setUserVars($user, $input) {
208
-		$handler = self::$app->getContainer()->query(UserPlaceholderHandler::class);
209
-		return $handler->handle($input);
210
-	}
211
-
212
-	/**
213
-	 * @param mixed $input
214
-	 * @return mixed
215
-	 * @throws \OCP\AppFramework\QueryException
216
-	 * @since 16.0.0
217
-	 */
218
-	public static function substitutePlaceholdersInConfig($input) {
219
-		/** @var BackendService $backendService */
220
-		$backendService = self::$app->getContainer()->query(BackendService::class);
221
-		/** @var IConfigHandler[] $handlers */
222
-		$handlers = $backendService->getConfigHandlers();
223
-		foreach ($handlers as $handler) {
224
-			$input = $handler->handle($input);
225
-		}
226
-		return $input;
227
-	}
228
-
229
-	/**
230
-	 * Test connecting using the given backend configuration
231
-	 *
232
-	 * @param string $class backend class name
233
-	 * @param array $options backend configuration options
234
-	 * @param boolean $isPersonal
235
-	 * @return int see self::STATUS_*
236
-	 * @throws Exception
237
-	 */
238
-	public static function getBackendStatus($class, $options, $isPersonal, $testOnly = true) {
239
-		if (self::$skipTest) {
240
-			return StorageNotAvailableException::STATUS_SUCCESS;
241
-		}
242
-		foreach ($options as $key => &$option) {
243
-			if($key === 'password') {
244
-				// no replacements in passwords
245
-				continue;
246
-			}
247
-			$option = self::substitutePlaceholdersInConfig($option);
248
-			if(!self::arePlaceholdersSubstituted($option)) {
249
-				\OC::$server->getLogger()->error(
250
-					'A placeholder was not substituted: {option} for mount type {class}',
251
-					[
252
-						'app' => 'files_external',
253
-						'option' => $option,
254
-						'class' => $class,
255
-					]
256
-				);
257
-				throw new StorageNotAvailableException(
258
-					'Mount configuration incomplete',
259
-					StorageNotAvailableException::STATUS_INCOMPLETE_CONF
260
-				);
261
-			}
262
-		}
263
-		if (class_exists($class)) {
264
-			try {
265
-				/** @var \OC\Files\Storage\Common $storage */
266
-				$storage = new $class($options);
267
-
268
-				try {
269
-					$result = $storage->test($isPersonal, $testOnly);
270
-					$storage->setAvailability($result);
271
-					if ($result) {
272
-						return StorageNotAvailableException::STATUS_SUCCESS;
273
-					}
274
-				} catch (\Exception $e) {
275
-					$storage->setAvailability(false);
276
-					throw $e;
277
-				}
278
-			} catch (Exception $exception) {
279
-				\OC::$server->getLogger()->logException($exception, ['app' => 'files_external']);
280
-				throw $exception;
281
-			}
282
-		}
283
-		return StorageNotAvailableException::STATUS_ERROR;
284
-	}
285
-
286
-	public static function arePlaceholdersSubstituted($option):bool {
287
-		$result = true;
288
-		if(is_array($option)) {
289
-			foreach ($option as $optionItem) {
290
-				if(is_array($optionItem)) {
291
-					$result = $result && self::arePlaceholdersSubstituted($option);
292
-				}
293
-			}
294
-		} else if (is_string($option)) {
295
-			if (strpos($option, '$') !== false) {
296
-				$result = false;
297
-			}
298
-		}
299
-		return $result;
300
-	}
301
-
302
-	/**
303
-	 * Read the mount points in the config file into an array
304
-	 *
305
-	 * @param string|null $user If not null, personal for $user, otherwise system
306
-	 * @return array
307
-	 */
308
-	public static function readData($user = null) {
309
-		if (isset($user)) {
310
-			$jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
311
-		} else {
312
-			$config = \OC::$server->getConfig();
313
-			$datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
314
-			$jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
315
-		}
316
-		if (is_file($jsonFile)) {
317
-			$mountPoints = json_decode(file_get_contents($jsonFile), true);
318
-			if (is_array($mountPoints)) {
319
-				return $mountPoints;
320
-			}
321
-		}
322
-		return array();
323
-	}
324
-
325
-	/**
326
-	 * Get backend dependency message
327
-	 * TODO: move into AppFramework along with templates
328
-	 *
329
-	 * @param Backend[] $backends
330
-	 * @return string
331
-	 */
332
-	public static function dependencyMessage($backends) {
333
-		$l = \OC::$server->getL10N('files_external');
334
-		$message = '';
335
-		$dependencyGroups = [];
336
-
337
-		foreach ($backends as $backend) {
338
-			foreach ($backend->checkDependencies() as $dependency) {
339
-				if ($message = $dependency->getMessage()) {
340
-					$message .= '<p>' . $message . '</p>';
341
-				} else {
342
-					$dependencyGroups[$dependency->getDependency()][] = $backend;
343
-				}
344
-			}
345
-		}
346
-
347
-		foreach ($dependencyGroups as $module => $dependants) {
348
-			$backends = implode(', ', array_map(function($backend) {
349
-				return '"' . $backend->getText() . '"';
350
-			}, $dependants));
351
-			$message .= '<p>' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends) . '</p>';
352
-		}
353
-
354
-		return $message;
355
-	}
356
-
357
-	/**
358
-	 * Returns a dependency missing message
359
-	 *
360
-	 * @param \OCP\IL10N $l
361
-	 * @param string $module
362
-	 * @param string $backend
363
-	 * @return string
364
-	 */
365
-	private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
366
-		switch (strtolower($module)) {
367
-			case 'curl':
368
-				return (string)$l->t('The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
369
-			case 'ftp':
370
-				return (string)$l->t('The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
371
-			default:
372
-				return (string)$l->t('"%1$s" is not installed. Mounting of %2$s is not possible. Please ask your system administrator to install it.', [$module, $backend]);
373
-		}
374
-	}
375
-
376
-	/**
377
-	 * Encrypt passwords in the given config options
378
-	 *
379
-	 * @param array $options mount options
380
-	 * @return array updated options
381
-	 */
382
-	public static function encryptPasswords($options) {
383
-		if (isset($options['password'])) {
384
-			$options['password_encrypted'] = self::encryptPassword($options['password']);
385
-			// do not unset the password, we want to keep the keys order
386
-			// on load... because that's how the UI currently works
387
-			$options['password'] = '';
388
-		}
389
-		return $options;
390
-	}
391
-
392
-	/**
393
-	 * Decrypt passwords in the given config options
394
-	 *
395
-	 * @param array $options mount options
396
-	 * @return array updated options
397
-	 */
398
-	public static function decryptPasswords($options) {
399
-		// note: legacy options might still have the unencrypted password in the "password" field
400
-		if (isset($options['password_encrypted'])) {
401
-			$options['password'] = self::decryptPassword($options['password_encrypted']);
402
-			unset($options['password_encrypted']);
403
-		}
404
-		return $options;
405
-	}
406
-
407
-	/**
408
-	 * Encrypt a single password
409
-	 *
410
-	 * @param string $password plain text password
411
-	 * @return string encrypted password
412
-	 */
413
-	private static function encryptPassword($password) {
414
-		$cipher = self::getCipher();
415
-		$iv = \OC::$server->getSecureRandom()->generate(16);
416
-		$cipher->setIV($iv);
417
-		return base64_encode($iv . $cipher->encrypt($password));
418
-	}
419
-
420
-	/**
421
-	 * Decrypts a single password
422
-	 *
423
-	 * @param string $encryptedPassword encrypted password
424
-	 * @return string plain text password
425
-	 */
426
-	private static function decryptPassword($encryptedPassword) {
427
-		$cipher = self::getCipher();
428
-		$binaryPassword = base64_decode($encryptedPassword);
429
-		$iv = substr($binaryPassword, 0, 16);
430
-		$cipher->setIV($iv);
431
-		$binaryPassword = substr($binaryPassword, 16);
432
-		return $cipher->decrypt($binaryPassword);
433
-	}
434
-
435
-	/**
436
-	 * Returns the encryption cipher
437
-	 *
438
-	 * @return AES
439
-	 */
440
-	private static function getCipher() {
441
-		$cipher = new AES(AES::MODE_CBC);
442
-		$cipher->setKey(\OC::$server->getConfig()->getSystemValue('passwordsalt', null));
443
-		return $cipher;
444
-	}
445
-
446
-	/**
447
-	 * Computes a hash based on the given configuration.
448
-	 * This is mostly used to find out whether configurations
449
-	 * are the same.
450
-	 *
451
-	 * @param array $config
452
-	 * @return string
453
-	 */
454
-	public static function makeConfigHash($config) {
455
-		$data = json_encode(
456
-			array(
457
-				'c' => $config['backend'],
458
-				'a' => $config['authMechanism'],
459
-				'm' => $config['mountpoint'],
460
-				'o' => $config['options'],
461
-				'p' => isset($config['priority']) ? $config['priority'] : -1,
462
-				'mo' => isset($config['mountOptions']) ? $config['mountOptions'] : [],
463
-			)
464
-		);
465
-		return hash('md5', $data);
466
-	}
58
+    // TODO: make this class non-static and give it a proper namespace
59
+
60
+    const MOUNT_TYPE_GLOBAL = 'global';
61
+    const MOUNT_TYPE_GROUP = 'group';
62
+    const MOUNT_TYPE_USER = 'user';
63
+    const MOUNT_TYPE_PERSONAL = 'personal';
64
+
65
+    // whether to skip backend test (for unit tests, as this static class is not mockable)
66
+    public static $skipTest = false;
67
+
68
+    /** @var Application */
69
+    public static $app;
70
+
71
+    /**
72
+     * @param string $class
73
+     * @param array $definition
74
+     * @return bool
75
+     * @deprecated 8.2.0 use \OCA\Files_External\Service\BackendService::registerBackend()
76
+     */
77
+    public static function registerBackend($class, $definition) {
78
+        $backendService = self::$app->getContainer()->query(BackendService::class);
79
+        $auth = self::$app->getContainer()->query(Builtin::class);
80
+
81
+        $backendService->registerBackend(new LegacyBackend($class, $definition, $auth));
82
+
83
+        return true;
84
+    }
85
+
86
+    /**
87
+     * Returns the mount points for the given user.
88
+     * The mount point is relative to the data directory.
89
+     *
90
+     * @param string $uid user
91
+     * @return array of mount point string as key, mountpoint config as value
92
+     *
93
+     * @deprecated 8.2.0 use UserGlobalStoragesService::getStorages() and UserStoragesService::getStorages()
94
+     */
95
+    public static function getAbsoluteMountPoints($uid) {
96
+        $mountPoints = array();
97
+
98
+        $userGlobalStoragesService = self::$app->getContainer()->query(UserGlobalStoragesService::class);
99
+        $userStoragesService = self::$app->getContainer()->query(UserStoragesService::class);
100
+        $user = self::$app->getContainer()->query(IUserManager::class)->get($uid);
101
+
102
+        $userGlobalStoragesService->setUser($user);
103
+        $userStoragesService->setUser($user);
104
+
105
+        foreach ($userGlobalStoragesService->getStorages() as $storage) {
106
+            /** @var \OCA\Files_External\Lib\StorageConfig $storage */
107
+            $mountPoint = '/'.$uid.'/files'.$storage->getMountPoint();
108
+            $mountEntry = self::prepareMountPointEntry($storage, false);
109
+            foreach ($mountEntry['options'] as &$option) {
110
+                $option = self::substitutePlaceholdersInConfig($option);
111
+            }
112
+            $mountPoints[$mountPoint] = $mountEntry;
113
+        }
114
+
115
+        foreach ($userStoragesService->getStorages() as $storage) {
116
+            $mountPoint = '/'.$uid.'/files'.$storage->getMountPoint();
117
+            $mountEntry = self::prepareMountPointEntry($storage, true);
118
+            foreach ($mountEntry['options'] as &$option) {
119
+                $option = self::substitutePlaceholdersInConfig($uid, $option);
120
+            }
121
+            $mountPoints[$mountPoint] = $mountEntry;
122
+        }
123
+
124
+        $userGlobalStoragesService->resetUser();
125
+        $userStoragesService->resetUser();
126
+
127
+        return $mountPoints;
128
+    }
129
+
130
+    /**
131
+     * Get the system mount points
132
+     *
133
+     * @return array
134
+     *
135
+     * @deprecated 8.2.0 use GlobalStoragesService::getStorages()
136
+     */
137
+    public static function getSystemMountPoints() {
138
+        $mountPoints = [];
139
+        $service = self::$app->getContainer()->query(GlobalStoragesService::class);
140
+
141
+        foreach ($service->getStorages() as $storage) {
142
+            $mountPoints[] = self::prepareMountPointEntry($storage, false);
143
+        }
144
+
145
+        return $mountPoints;
146
+    }
147
+
148
+    /**
149
+     * Get the personal mount points of the current user
150
+     *
151
+     * @return array
152
+     *
153
+     * @deprecated 8.2.0 use UserStoragesService::getStorages()
154
+     */
155
+    public static function getPersonalMountPoints() {
156
+        $mountPoints = [];
157
+        $service = self::$app->getContainer()->query(UserStoragesService::class);
158
+
159
+        foreach ($service->getStorages() as $storage) {
160
+            $mountPoints[] = self::prepareMountPointEntry($storage, true);
161
+        }
162
+
163
+        return $mountPoints;
164
+    }
165
+
166
+    /**
167
+     * Convert a StorageConfig to the legacy mountPoints array format
168
+     * There's a lot of extra information in here, to satisfy all of the legacy functions
169
+     *
170
+     * @param StorageConfig $storage
171
+     * @param bool $isPersonal
172
+     * @return array
173
+     */
174
+    private static function prepareMountPointEntry(StorageConfig $storage, $isPersonal) {
175
+        $mountEntry = [];
176
+
177
+        $mountEntry['mountpoint'] = substr($storage->getMountPoint(), 1); // remove leading slash
178
+        $mountEntry['class'] = $storage->getBackend()->getIdentifier();
179
+        $mountEntry['backend'] = $storage->getBackend()->getText();
180
+        $mountEntry['authMechanism'] = $storage->getAuthMechanism()->getIdentifier();
181
+        $mountEntry['personal'] = $isPersonal;
182
+        $mountEntry['options'] = self::decryptPasswords($storage->getBackendOptions());
183
+        $mountEntry['mountOptions'] = $storage->getMountOptions();
184
+        $mountEntry['priority'] = $storage->getPriority();
185
+        $mountEntry['applicable'] = [
186
+            'groups' => $storage->getApplicableGroups(),
187
+            'users' => $storage->getApplicableUsers(),
188
+        ];
189
+        // if mountpoint is applicable to all users the old API expects ['all']
190
+        if (empty($mountEntry['applicable']['groups']) && empty($mountEntry['applicable']['users'])) {
191
+            $mountEntry['applicable']['users'] = ['all'];
192
+        }
193
+
194
+        $mountEntry['id'] = $storage->getId();
195
+
196
+        return $mountEntry;
197
+    }
198
+
199
+    /**
200
+     * fill in the correct values for $user
201
+     *
202
+     * @param string $user user value
203
+     * @param string|array $input
204
+     * @return string
205
+     * @deprecated use self::substitutePlaceholdersInConfig($input)
206
+     */
207
+    public static function setUserVars($user, $input) {
208
+        $handler = self::$app->getContainer()->query(UserPlaceholderHandler::class);
209
+        return $handler->handle($input);
210
+    }
211
+
212
+    /**
213
+     * @param mixed $input
214
+     * @return mixed
215
+     * @throws \OCP\AppFramework\QueryException
216
+     * @since 16.0.0
217
+     */
218
+    public static function substitutePlaceholdersInConfig($input) {
219
+        /** @var BackendService $backendService */
220
+        $backendService = self::$app->getContainer()->query(BackendService::class);
221
+        /** @var IConfigHandler[] $handlers */
222
+        $handlers = $backendService->getConfigHandlers();
223
+        foreach ($handlers as $handler) {
224
+            $input = $handler->handle($input);
225
+        }
226
+        return $input;
227
+    }
228
+
229
+    /**
230
+     * Test connecting using the given backend configuration
231
+     *
232
+     * @param string $class backend class name
233
+     * @param array $options backend configuration options
234
+     * @param boolean $isPersonal
235
+     * @return int see self::STATUS_*
236
+     * @throws Exception
237
+     */
238
+    public static function getBackendStatus($class, $options, $isPersonal, $testOnly = true) {
239
+        if (self::$skipTest) {
240
+            return StorageNotAvailableException::STATUS_SUCCESS;
241
+        }
242
+        foreach ($options as $key => &$option) {
243
+            if($key === 'password') {
244
+                // no replacements in passwords
245
+                continue;
246
+            }
247
+            $option = self::substitutePlaceholdersInConfig($option);
248
+            if(!self::arePlaceholdersSubstituted($option)) {
249
+                \OC::$server->getLogger()->error(
250
+                    'A placeholder was not substituted: {option} for mount type {class}',
251
+                    [
252
+                        'app' => 'files_external',
253
+                        'option' => $option,
254
+                        'class' => $class,
255
+                    ]
256
+                );
257
+                throw new StorageNotAvailableException(
258
+                    'Mount configuration incomplete',
259
+                    StorageNotAvailableException::STATUS_INCOMPLETE_CONF
260
+                );
261
+            }
262
+        }
263
+        if (class_exists($class)) {
264
+            try {
265
+                /** @var \OC\Files\Storage\Common $storage */
266
+                $storage = new $class($options);
267
+
268
+                try {
269
+                    $result = $storage->test($isPersonal, $testOnly);
270
+                    $storage->setAvailability($result);
271
+                    if ($result) {
272
+                        return StorageNotAvailableException::STATUS_SUCCESS;
273
+                    }
274
+                } catch (\Exception $e) {
275
+                    $storage->setAvailability(false);
276
+                    throw $e;
277
+                }
278
+            } catch (Exception $exception) {
279
+                \OC::$server->getLogger()->logException($exception, ['app' => 'files_external']);
280
+                throw $exception;
281
+            }
282
+        }
283
+        return StorageNotAvailableException::STATUS_ERROR;
284
+    }
285
+
286
+    public static function arePlaceholdersSubstituted($option):bool {
287
+        $result = true;
288
+        if(is_array($option)) {
289
+            foreach ($option as $optionItem) {
290
+                if(is_array($optionItem)) {
291
+                    $result = $result && self::arePlaceholdersSubstituted($option);
292
+                }
293
+            }
294
+        } else if (is_string($option)) {
295
+            if (strpos($option, '$') !== false) {
296
+                $result = false;
297
+            }
298
+        }
299
+        return $result;
300
+    }
301
+
302
+    /**
303
+     * Read the mount points in the config file into an array
304
+     *
305
+     * @param string|null $user If not null, personal for $user, otherwise system
306
+     * @return array
307
+     */
308
+    public static function readData($user = null) {
309
+        if (isset($user)) {
310
+            $jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
311
+        } else {
312
+            $config = \OC::$server->getConfig();
313
+            $datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
314
+            $jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
315
+        }
316
+        if (is_file($jsonFile)) {
317
+            $mountPoints = json_decode(file_get_contents($jsonFile), true);
318
+            if (is_array($mountPoints)) {
319
+                return $mountPoints;
320
+            }
321
+        }
322
+        return array();
323
+    }
324
+
325
+    /**
326
+     * Get backend dependency message
327
+     * TODO: move into AppFramework along with templates
328
+     *
329
+     * @param Backend[] $backends
330
+     * @return string
331
+     */
332
+    public static function dependencyMessage($backends) {
333
+        $l = \OC::$server->getL10N('files_external');
334
+        $message = '';
335
+        $dependencyGroups = [];
336
+
337
+        foreach ($backends as $backend) {
338
+            foreach ($backend->checkDependencies() as $dependency) {
339
+                if ($message = $dependency->getMessage()) {
340
+                    $message .= '<p>' . $message . '</p>';
341
+                } else {
342
+                    $dependencyGroups[$dependency->getDependency()][] = $backend;
343
+                }
344
+            }
345
+        }
346
+
347
+        foreach ($dependencyGroups as $module => $dependants) {
348
+            $backends = implode(', ', array_map(function($backend) {
349
+                return '"' . $backend->getText() . '"';
350
+            }, $dependants));
351
+            $message .= '<p>' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends) . '</p>';
352
+        }
353
+
354
+        return $message;
355
+    }
356
+
357
+    /**
358
+     * Returns a dependency missing message
359
+     *
360
+     * @param \OCP\IL10N $l
361
+     * @param string $module
362
+     * @param string $backend
363
+     * @return string
364
+     */
365
+    private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
366
+        switch (strtolower($module)) {
367
+            case 'curl':
368
+                return (string)$l->t('The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
369
+            case 'ftp':
370
+                return (string)$l->t('The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
371
+            default:
372
+                return (string)$l->t('"%1$s" is not installed. Mounting of %2$s is not possible. Please ask your system administrator to install it.', [$module, $backend]);
373
+        }
374
+    }
375
+
376
+    /**
377
+     * Encrypt passwords in the given config options
378
+     *
379
+     * @param array $options mount options
380
+     * @return array updated options
381
+     */
382
+    public static function encryptPasswords($options) {
383
+        if (isset($options['password'])) {
384
+            $options['password_encrypted'] = self::encryptPassword($options['password']);
385
+            // do not unset the password, we want to keep the keys order
386
+            // on load... because that's how the UI currently works
387
+            $options['password'] = '';
388
+        }
389
+        return $options;
390
+    }
391
+
392
+    /**
393
+     * Decrypt passwords in the given config options
394
+     *
395
+     * @param array $options mount options
396
+     * @return array updated options
397
+     */
398
+    public static function decryptPasswords($options) {
399
+        // note: legacy options might still have the unencrypted password in the "password" field
400
+        if (isset($options['password_encrypted'])) {
401
+            $options['password'] = self::decryptPassword($options['password_encrypted']);
402
+            unset($options['password_encrypted']);
403
+        }
404
+        return $options;
405
+    }
406
+
407
+    /**
408
+     * Encrypt a single password
409
+     *
410
+     * @param string $password plain text password
411
+     * @return string encrypted password
412
+     */
413
+    private static function encryptPassword($password) {
414
+        $cipher = self::getCipher();
415
+        $iv = \OC::$server->getSecureRandom()->generate(16);
416
+        $cipher->setIV($iv);
417
+        return base64_encode($iv . $cipher->encrypt($password));
418
+    }
419
+
420
+    /**
421
+     * Decrypts a single password
422
+     *
423
+     * @param string $encryptedPassword encrypted password
424
+     * @return string plain text password
425
+     */
426
+    private static function decryptPassword($encryptedPassword) {
427
+        $cipher = self::getCipher();
428
+        $binaryPassword = base64_decode($encryptedPassword);
429
+        $iv = substr($binaryPassword, 0, 16);
430
+        $cipher->setIV($iv);
431
+        $binaryPassword = substr($binaryPassword, 16);
432
+        return $cipher->decrypt($binaryPassword);
433
+    }
434
+
435
+    /**
436
+     * Returns the encryption cipher
437
+     *
438
+     * @return AES
439
+     */
440
+    private static function getCipher() {
441
+        $cipher = new AES(AES::MODE_CBC);
442
+        $cipher->setKey(\OC::$server->getConfig()->getSystemValue('passwordsalt', null));
443
+        return $cipher;
444
+    }
445
+
446
+    /**
447
+     * Computes a hash based on the given configuration.
448
+     * This is mostly used to find out whether configurations
449
+     * are the same.
450
+     *
451
+     * @param array $config
452
+     * @return string
453
+     */
454
+    public static function makeConfigHash($config) {
455
+        $data = json_encode(
456
+            array(
457
+                'c' => $config['backend'],
458
+                'a' => $config['authMechanism'],
459
+                'm' => $config['mountpoint'],
460
+                'o' => $config['options'],
461
+                'p' => isset($config['priority']) ? $config['priority'] : -1,
462
+                'mo' => isset($config['mountOptions']) ? $config['mountOptions'] : [],
463
+            )
464
+        );
465
+        return hash('md5', $data);
466
+    }
467 467
 }
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -240,12 +240,12 @@  discard block
 block discarded – undo
240 240
 			return StorageNotAvailableException::STATUS_SUCCESS;
241 241
 		}
242 242
 		foreach ($options as $key => &$option) {
243
-			if($key === 'password') {
243
+			if ($key === 'password') {
244 244
 				// no replacements in passwords
245 245
 				continue;
246 246
 			}
247 247
 			$option = self::substitutePlaceholdersInConfig($option);
248
-			if(!self::arePlaceholdersSubstituted($option)) {
248
+			if (!self::arePlaceholdersSubstituted($option)) {
249 249
 				\OC::$server->getLogger()->error(
250 250
 					'A placeholder was not substituted: {option} for mount type {class}',
251 251
 					[
@@ -285,9 +285,9 @@  discard block
 block discarded – undo
285 285
 
286 286
 	public static function arePlaceholdersSubstituted($option):bool {
287 287
 		$result = true;
288
-		if(is_array($option)) {
288
+		if (is_array($option)) {
289 289
 			foreach ($option as $optionItem) {
290
-				if(is_array($optionItem)) {
290
+				if (is_array($optionItem)) {
291 291
 					$result = $result && self::arePlaceholdersSubstituted($option);
292 292
 				}
293 293
 			}
@@ -307,11 +307,11 @@  discard block
 block discarded – undo
307 307
 	 */
308 308
 	public static function readData($user = null) {
309 309
 		if (isset($user)) {
310
-			$jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
310
+			$jsonFile = \OC::$server->getUserManager()->get($user)->getHome().'/mount.json';
311 311
 		} else {
312 312
 			$config = \OC::$server->getConfig();
313
-			$datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
314
-			$jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
313
+			$datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data/');
314
+			$jsonFile = $config->getSystemValue('mount_file', $datadir.'/mount.json');
315 315
 		}
316 316
 		if (is_file($jsonFile)) {
317 317
 			$mountPoints = json_decode(file_get_contents($jsonFile), true);
@@ -337,7 +337,7 @@  discard block
 block discarded – undo
337 337
 		foreach ($backends as $backend) {
338 338
 			foreach ($backend->checkDependencies() as $dependency) {
339 339
 				if ($message = $dependency->getMessage()) {
340
-					$message .= '<p>' . $message . '</p>';
340
+					$message .= '<p>'.$message.'</p>';
341 341
 				} else {
342 342
 					$dependencyGroups[$dependency->getDependency()][] = $backend;
343 343
 				}
@@ -346,9 +346,9 @@  discard block
 block discarded – undo
346 346
 
347 347
 		foreach ($dependencyGroups as $module => $dependants) {
348 348
 			$backends = implode(', ', array_map(function($backend) {
349
-				return '"' . $backend->getText() . '"';
349
+				return '"'.$backend->getText().'"';
350 350
 			}, $dependants));
351
-			$message .= '<p>' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends) . '</p>';
351
+			$message .= '<p>'.OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends).'</p>';
352 352
 		}
353 353
 
354 354
 		return $message;
@@ -365,11 +365,11 @@  discard block
 block discarded – undo
365 365
 	private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
366 366
 		switch (strtolower($module)) {
367 367
 			case 'curl':
368
-				return (string)$l->t('The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
368
+				return (string) $l->t('The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
369 369
 			case 'ftp':
370
-				return (string)$l->t('The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
370
+				return (string) $l->t('The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
371 371
 			default:
372
-				return (string)$l->t('"%1$s" is not installed. Mounting of %2$s is not possible. Please ask your system administrator to install it.', [$module, $backend]);
372
+				return (string) $l->t('"%1$s" is not installed. Mounting of %2$s is not possible. Please ask your system administrator to install it.', [$module, $backend]);
373 373
 		}
374 374
 	}
375 375
 
@@ -414,7 +414,7 @@  discard block
 block discarded – undo
414 414
 		$cipher = self::getCipher();
415 415
 		$iv = \OC::$server->getSecureRandom()->generate(16);
416 416
 		$cipher->setIV($iv);
417
-		return base64_encode($iv . $cipher->encrypt($password));
417
+		return base64_encode($iv.$cipher->encrypt($password));
418 418
 	}
419 419
 
420 420
 	/**
Please login to merge, or discard this patch.