Passed
Push — master ( babe13...7e8dfd )
by Blizzz
11:33
created
apps/files_external/lib/config.php 2 patches
Indentation   +407 added lines, -407 removed lines patch added patch discarded remove patch
@@ -55,411 +55,411 @@
 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
-				$result = $result && self::arePlaceholdersSubstituted($optionItem);
291
-			}
292
-		} else if (is_string($option)) {
293
-			if (strpos(rtrim($option, '$'), '$') !== false) {
294
-				$result = false;
295
-			}
296
-		}
297
-		return $result;
298
-	}
299
-
300
-	/**
301
-	 * Read the mount points in the config file into an array
302
-	 *
303
-	 * @param string|null $user If not null, personal for $user, otherwise system
304
-	 * @return array
305
-	 */
306
-	public static function readData($user = null) {
307
-		if (isset($user)) {
308
-			$jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
309
-		} else {
310
-			$config = \OC::$server->getConfig();
311
-			$datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
312
-			$jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
313
-		}
314
-		if (is_file($jsonFile)) {
315
-			$mountPoints = json_decode(file_get_contents($jsonFile), true);
316
-			if (is_array($mountPoints)) {
317
-				return $mountPoints;
318
-			}
319
-		}
320
-		return array();
321
-	}
322
-
323
-	/**
324
-	 * Get backend dependency message
325
-	 * TODO: move into AppFramework along with templates
326
-	 *
327
-	 * @param Backend[] $backends
328
-	 * @return string
329
-	 */
330
-	public static function dependencyMessage($backends) {
331
-		$l = \OC::$server->getL10N('files_external');
332
-		$message = '';
333
-		$dependencyGroups = [];
334
-
335
-		foreach ($backends as $backend) {
336
-			foreach ($backend->checkDependencies() as $dependency) {
337
-				if ($message = $dependency->getMessage()) {
338
-					$message .= '<p>' . $message . '</p>';
339
-				} else {
340
-					$dependencyGroups[$dependency->getDependency()][] = $backend;
341
-				}
342
-			}
343
-		}
344
-
345
-		foreach ($dependencyGroups as $module => $dependants) {
346
-			$backends = implode(', ', array_map(function($backend) {
347
-				return '"' . $backend->getText() . '"';
348
-			}, $dependants));
349
-			$message .= '<p>' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends) . '</p>';
350
-		}
351
-
352
-		return $message;
353
-	}
354
-
355
-	/**
356
-	 * Returns a dependency missing message
357
-	 *
358
-	 * @param \OCP\IL10N $l
359
-	 * @param string $module
360
-	 * @param string $backend
361
-	 * @return string
362
-	 */
363
-	private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
364
-		switch (strtolower($module)) {
365
-			case 'curl':
366
-				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]);
367
-			case 'ftp':
368
-				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]);
369
-			default:
370
-				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]);
371
-		}
372
-	}
373
-
374
-	/**
375
-	 * Encrypt passwords in the given config options
376
-	 *
377
-	 * @param array $options mount options
378
-	 * @return array updated options
379
-	 */
380
-	public static function encryptPasswords($options) {
381
-		if (isset($options['password'])) {
382
-			$options['password_encrypted'] = self::encryptPassword($options['password']);
383
-			// do not unset the password, we want to keep the keys order
384
-			// on load... because that's how the UI currently works
385
-			$options['password'] = '';
386
-		}
387
-		return $options;
388
-	}
389
-
390
-	/**
391
-	 * Decrypt passwords in the given config options
392
-	 *
393
-	 * @param array $options mount options
394
-	 * @return array updated options
395
-	 */
396
-	public static function decryptPasswords($options) {
397
-		// note: legacy options might still have the unencrypted password in the "password" field
398
-		if (isset($options['password_encrypted'])) {
399
-			$options['password'] = self::decryptPassword($options['password_encrypted']);
400
-			unset($options['password_encrypted']);
401
-		}
402
-		return $options;
403
-	}
404
-
405
-	/**
406
-	 * Encrypt a single password
407
-	 *
408
-	 * @param string $password plain text password
409
-	 * @return string encrypted password
410
-	 */
411
-	private static function encryptPassword($password) {
412
-		$cipher = self::getCipher();
413
-		$iv = \OC::$server->getSecureRandom()->generate(16);
414
-		$cipher->setIV($iv);
415
-		return base64_encode($iv . $cipher->encrypt($password));
416
-	}
417
-
418
-	/**
419
-	 * Decrypts a single password
420
-	 *
421
-	 * @param string $encryptedPassword encrypted password
422
-	 * @return string plain text password
423
-	 */
424
-	private static function decryptPassword($encryptedPassword) {
425
-		$cipher = self::getCipher();
426
-		$binaryPassword = base64_decode($encryptedPassword);
427
-		$iv = substr($binaryPassword, 0, 16);
428
-		$cipher->setIV($iv);
429
-		$binaryPassword = substr($binaryPassword, 16);
430
-		return $cipher->decrypt($binaryPassword);
431
-	}
432
-
433
-	/**
434
-	 * Returns the encryption cipher
435
-	 *
436
-	 * @return AES
437
-	 */
438
-	private static function getCipher() {
439
-		$cipher = new AES(AES::MODE_CBC);
440
-		$cipher->setKey(\OC::$server->getConfig()->getSystemValue('passwordsalt', null));
441
-		return $cipher;
442
-	}
443
-
444
-	/**
445
-	 * Computes a hash based on the given configuration.
446
-	 * This is mostly used to find out whether configurations
447
-	 * are the same.
448
-	 *
449
-	 * @param array $config
450
-	 * @return string
451
-	 */
452
-	public static function makeConfigHash($config) {
453
-		$data = json_encode(
454
-			array(
455
-				'c' => $config['backend'],
456
-				'a' => $config['authMechanism'],
457
-				'm' => $config['mountpoint'],
458
-				'o' => $config['options'],
459
-				'p' => isset($config['priority']) ? $config['priority'] : -1,
460
-				'mo' => isset($config['mountOptions']) ? $config['mountOptions'] : [],
461
-			)
462
-		);
463
-		return hash('md5', $data);
464
-	}
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
+                $result = $result && self::arePlaceholdersSubstituted($optionItem);
291
+            }
292
+        } else if (is_string($option)) {
293
+            if (strpos(rtrim($option, '$'), '$') !== false) {
294
+                $result = false;
295
+            }
296
+        }
297
+        return $result;
298
+    }
299
+
300
+    /**
301
+     * Read the mount points in the config file into an array
302
+     *
303
+     * @param string|null $user If not null, personal for $user, otherwise system
304
+     * @return array
305
+     */
306
+    public static function readData($user = null) {
307
+        if (isset($user)) {
308
+            $jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
309
+        } else {
310
+            $config = \OC::$server->getConfig();
311
+            $datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
312
+            $jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
313
+        }
314
+        if (is_file($jsonFile)) {
315
+            $mountPoints = json_decode(file_get_contents($jsonFile), true);
316
+            if (is_array($mountPoints)) {
317
+                return $mountPoints;
318
+            }
319
+        }
320
+        return array();
321
+    }
322
+
323
+    /**
324
+     * Get backend dependency message
325
+     * TODO: move into AppFramework along with templates
326
+     *
327
+     * @param Backend[] $backends
328
+     * @return string
329
+     */
330
+    public static function dependencyMessage($backends) {
331
+        $l = \OC::$server->getL10N('files_external');
332
+        $message = '';
333
+        $dependencyGroups = [];
334
+
335
+        foreach ($backends as $backend) {
336
+            foreach ($backend->checkDependencies() as $dependency) {
337
+                if ($message = $dependency->getMessage()) {
338
+                    $message .= '<p>' . $message . '</p>';
339
+                } else {
340
+                    $dependencyGroups[$dependency->getDependency()][] = $backend;
341
+                }
342
+            }
343
+        }
344
+
345
+        foreach ($dependencyGroups as $module => $dependants) {
346
+            $backends = implode(', ', array_map(function($backend) {
347
+                return '"' . $backend->getText() . '"';
348
+            }, $dependants));
349
+            $message .= '<p>' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends) . '</p>';
350
+        }
351
+
352
+        return $message;
353
+    }
354
+
355
+    /**
356
+     * Returns a dependency missing message
357
+     *
358
+     * @param \OCP\IL10N $l
359
+     * @param string $module
360
+     * @param string $backend
361
+     * @return string
362
+     */
363
+    private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
364
+        switch (strtolower($module)) {
365
+            case 'curl':
366
+                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]);
367
+            case 'ftp':
368
+                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]);
369
+            default:
370
+                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]);
371
+        }
372
+    }
373
+
374
+    /**
375
+     * Encrypt passwords in the given config options
376
+     *
377
+     * @param array $options mount options
378
+     * @return array updated options
379
+     */
380
+    public static function encryptPasswords($options) {
381
+        if (isset($options['password'])) {
382
+            $options['password_encrypted'] = self::encryptPassword($options['password']);
383
+            // do not unset the password, we want to keep the keys order
384
+            // on load... because that's how the UI currently works
385
+            $options['password'] = '';
386
+        }
387
+        return $options;
388
+    }
389
+
390
+    /**
391
+     * Decrypt passwords in the given config options
392
+     *
393
+     * @param array $options mount options
394
+     * @return array updated options
395
+     */
396
+    public static function decryptPasswords($options) {
397
+        // note: legacy options might still have the unencrypted password in the "password" field
398
+        if (isset($options['password_encrypted'])) {
399
+            $options['password'] = self::decryptPassword($options['password_encrypted']);
400
+            unset($options['password_encrypted']);
401
+        }
402
+        return $options;
403
+    }
404
+
405
+    /**
406
+     * Encrypt a single password
407
+     *
408
+     * @param string $password plain text password
409
+     * @return string encrypted password
410
+     */
411
+    private static function encryptPassword($password) {
412
+        $cipher = self::getCipher();
413
+        $iv = \OC::$server->getSecureRandom()->generate(16);
414
+        $cipher->setIV($iv);
415
+        return base64_encode($iv . $cipher->encrypt($password));
416
+    }
417
+
418
+    /**
419
+     * Decrypts a single password
420
+     *
421
+     * @param string $encryptedPassword encrypted password
422
+     * @return string plain text password
423
+     */
424
+    private static function decryptPassword($encryptedPassword) {
425
+        $cipher = self::getCipher();
426
+        $binaryPassword = base64_decode($encryptedPassword);
427
+        $iv = substr($binaryPassword, 0, 16);
428
+        $cipher->setIV($iv);
429
+        $binaryPassword = substr($binaryPassword, 16);
430
+        return $cipher->decrypt($binaryPassword);
431
+    }
432
+
433
+    /**
434
+     * Returns the encryption cipher
435
+     *
436
+     * @return AES
437
+     */
438
+    private static function getCipher() {
439
+        $cipher = new AES(AES::MODE_CBC);
440
+        $cipher->setKey(\OC::$server->getConfig()->getSystemValue('passwordsalt', null));
441
+        return $cipher;
442
+    }
443
+
444
+    /**
445
+     * Computes a hash based on the given configuration.
446
+     * This is mostly used to find out whether configurations
447
+     * are the same.
448
+     *
449
+     * @param array $config
450
+     * @return string
451
+     */
452
+    public static function makeConfigHash($config) {
453
+        $data = json_encode(
454
+            array(
455
+                'c' => $config['backend'],
456
+                'a' => $config['authMechanism'],
457
+                'm' => $config['mountpoint'],
458
+                'o' => $config['options'],
459
+                'p' => isset($config['priority']) ? $config['priority'] : -1,
460
+                'mo' => isset($config['mountOptions']) ? $config['mountOptions'] : [],
461
+            )
462
+        );
463
+        return hash('md5', $data);
464
+    }
465 465
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 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,7 +285,7 @@  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 290
 				$result = $result && self::arePlaceholdersSubstituted($optionItem);
291 291
 			}
@@ -305,11 +305,11 @@  discard block
 block discarded – undo
305 305
 	 */
306 306
 	public static function readData($user = null) {
307 307
 		if (isset($user)) {
308
-			$jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
308
+			$jsonFile = \OC::$server->getUserManager()->get($user)->getHome().'/mount.json';
309 309
 		} else {
310 310
 			$config = \OC::$server->getConfig();
311
-			$datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
312
-			$jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
311
+			$datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data/');
312
+			$jsonFile = $config->getSystemValue('mount_file', $datadir.'/mount.json');
313 313
 		}
314 314
 		if (is_file($jsonFile)) {
315 315
 			$mountPoints = json_decode(file_get_contents($jsonFile), true);
@@ -335,7 +335,7 @@  discard block
 block discarded – undo
335 335
 		foreach ($backends as $backend) {
336 336
 			foreach ($backend->checkDependencies() as $dependency) {
337 337
 				if ($message = $dependency->getMessage()) {
338
-					$message .= '<p>' . $message . '</p>';
338
+					$message .= '<p>'.$message.'</p>';
339 339
 				} else {
340 340
 					$dependencyGroups[$dependency->getDependency()][] = $backend;
341 341
 				}
@@ -344,9 +344,9 @@  discard block
 block discarded – undo
344 344
 
345 345
 		foreach ($dependencyGroups as $module => $dependants) {
346 346
 			$backends = implode(', ', array_map(function($backend) {
347
-				return '"' . $backend->getText() . '"';
347
+				return '"'.$backend->getText().'"';
348 348
 			}, $dependants));
349
-			$message .= '<p>' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends) . '</p>';
349
+			$message .= '<p>'.OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends).'</p>';
350 350
 		}
351 351
 
352 352
 		return $message;
@@ -363,11 +363,11 @@  discard block
 block discarded – undo
363 363
 	private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
364 364
 		switch (strtolower($module)) {
365 365
 			case 'curl':
366
-				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]);
366
+				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]);
367 367
 			case 'ftp':
368
-				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]);
368
+				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]);
369 369
 			default:
370
-				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]);
370
+				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]);
371 371
 		}
372 372
 	}
373 373
 
@@ -412,7 +412,7 @@  discard block
 block discarded – undo
412 412
 		$cipher = self::getCipher();
413 413
 		$iv = \OC::$server->getSecureRandom()->generate(16);
414 414
 		$cipher->setIV($iv);
415
-		return base64_encode($iv . $cipher->encrypt($password));
415
+		return base64_encode($iv.$cipher->encrypt($password));
416 416
 	}
417 417
 
418 418
 	/**
Please login to merge, or discard this patch.