Passed
Push — master ( bf1943...bfd61d )
by Blizzz
09:37
created
apps/files_external/lib/Lib/Storage/FTP.php 2 patches
Indentation   +108 added lines, -108 removed lines patch added patch discarded remove patch
@@ -38,120 +38,120 @@
 block discarded – undo
38 38
 use Icewind\Streams\RetryWrapper;
39 39
 
40 40
 class FTP extends StreamWrapper{
41
-	private $password;
42
-	private $user;
43
-	private $host;
44
-	private $secure;
45
-	private $root;
41
+    private $password;
42
+    private $user;
43
+    private $host;
44
+    private $secure;
45
+    private $root;
46 46
 
47
-	public function __construct($params) {
48
-		if (isset($params['host']) && isset($params['user']) && isset($params['password'])) {
49
-			$this->host=$params['host'];
50
-			$this->user=$params['user'];
51
-			$this->password=$params['password'];
52
-			if (isset($params['secure'])) {
53
-				$this->secure = $params['secure'];
54
-			} else {
55
-				$this->secure = false;
56
-			}
57
-			$this->root=isset($params['root'])?$params['root']:'/';
58
-			if ( ! $this->root || $this->root[0]!=='/') {
59
-				$this->root='/'.$this->root;
60
-			}
61
-			if (substr($this->root, -1) !== '/') {
62
-				$this->root .= '/';
63
-			}
64
-		} else {
65
-			throw new \Exception('Creating FTP storage failed');
66
-		}
47
+    public function __construct($params) {
48
+        if (isset($params['host']) && isset($params['user']) && isset($params['password'])) {
49
+            $this->host=$params['host'];
50
+            $this->user=$params['user'];
51
+            $this->password=$params['password'];
52
+            if (isset($params['secure'])) {
53
+                $this->secure = $params['secure'];
54
+            } else {
55
+                $this->secure = false;
56
+            }
57
+            $this->root=isset($params['root'])?$params['root']:'/';
58
+            if ( ! $this->root || $this->root[0]!=='/') {
59
+                $this->root='/'.$this->root;
60
+            }
61
+            if (substr($this->root, -1) !== '/') {
62
+                $this->root .= '/';
63
+            }
64
+        } else {
65
+            throw new \Exception('Creating FTP storage failed');
66
+        }
67 67
 		
68
-	}
68
+    }
69 69
 
70
-	public function getId(){
71
-		return 'ftp::' . $this->user . '@' . $this->host . '/' . $this->root;
72
-	}
70
+    public function getId(){
71
+        return 'ftp::' . $this->user . '@' . $this->host . '/' . $this->root;
72
+    }
73 73
 
74
-	/**
75
-	 * construct the ftp url
76
-	 * @param string $path
77
-	 * @return string
78
-	 */
79
-	public function constructUrl($path) {
80
-		$url='ftp';
81
-		if ($this->secure) {
82
-			$url.='s';
83
-		}
84
-		$url.='://'.urlencode($this->user).':'.urlencode($this->password).'@'.$this->host.$this->root.$path;
85
-		return $url;
86
-	}
74
+    /**
75
+     * construct the ftp url
76
+     * @param string $path
77
+     * @return string
78
+     */
79
+    public function constructUrl($path) {
80
+        $url='ftp';
81
+        if ($this->secure) {
82
+            $url.='s';
83
+        }
84
+        $url.='://'.urlencode($this->user).':'.urlencode($this->password).'@'.$this->host.$this->root.$path;
85
+        return $url;
86
+    }
87 87
 
88
-	/**
89
-	 * Unlinks file or directory
90
-	 * @param string $path
91
-	 */
92
-	public function unlink($path) {
93
-		if ($this->is_dir($path)) {
94
-			return $this->rmdir($path);
95
-		}
96
-		else {
97
-			$url = $this->constructUrl($path);
98
-			$result = unlink($url);
99
-			clearstatcache(true, $url);
100
-			return $result;
101
-		}
102
-	}
103
-	public function fopen($path,$mode) {
104
-		switch($mode) {
105
-			case 'r':
106
-			case 'rb':
107
-			case 'w':
108
-			case 'wb':
109
-			case 'a':
110
-			case 'ab':
111
-				//these are supported by the wrapper
112
-				$context = stream_context_create(array('ftp' => array('overwrite' => true)));
113
-				$handle = fopen($this->constructUrl($path), $mode, false, $context);
114
-				return RetryWrapper::wrap($handle);
115
-			case 'r+':
116
-			case 'w+':
117
-			case 'wb+':
118
-			case 'a+':
119
-			case 'x':
120
-			case 'x+':
121
-			case 'c':
122
-			case 'c+':
123
-				//emulate these
124
-				if (strrpos($path, '.')!==false) {
125
-					$ext=substr($path, strrpos($path, '.'));
126
-				} else {
127
-					$ext='';
128
-				}
129
-				$tmpFile = \OC::$server->getTempManager()->getTemporaryFile();
130
-				if ($this->file_exists($path)) {
131
-					$this->getFile($path, $tmpFile);
132
-				}
133
-				$handle = fopen($tmpFile, $mode);
134
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
135
-					$this->writeBack($tmpFile, $path);
136
-				});
137
-		}
138
-		return false;
139
-	}
88
+    /**
89
+     * Unlinks file or directory
90
+     * @param string $path
91
+     */
92
+    public function unlink($path) {
93
+        if ($this->is_dir($path)) {
94
+            return $this->rmdir($path);
95
+        }
96
+        else {
97
+            $url = $this->constructUrl($path);
98
+            $result = unlink($url);
99
+            clearstatcache(true, $url);
100
+            return $result;
101
+        }
102
+    }
103
+    public function fopen($path,$mode) {
104
+        switch($mode) {
105
+            case 'r':
106
+            case 'rb':
107
+            case 'w':
108
+            case 'wb':
109
+            case 'a':
110
+            case 'ab':
111
+                //these are supported by the wrapper
112
+                $context = stream_context_create(array('ftp' => array('overwrite' => true)));
113
+                $handle = fopen($this->constructUrl($path), $mode, false, $context);
114
+                return RetryWrapper::wrap($handle);
115
+            case 'r+':
116
+            case 'w+':
117
+            case 'wb+':
118
+            case 'a+':
119
+            case 'x':
120
+            case 'x+':
121
+            case 'c':
122
+            case 'c+':
123
+                //emulate these
124
+                if (strrpos($path, '.')!==false) {
125
+                    $ext=substr($path, strrpos($path, '.'));
126
+                } else {
127
+                    $ext='';
128
+                }
129
+                $tmpFile = \OC::$server->getTempManager()->getTemporaryFile();
130
+                if ($this->file_exists($path)) {
131
+                    $this->getFile($path, $tmpFile);
132
+                }
133
+                $handle = fopen($tmpFile, $mode);
134
+                return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
135
+                    $this->writeBack($tmpFile, $path);
136
+                });
137
+        }
138
+        return false;
139
+    }
140 140
 
141
-	public function writeBack($tmpFile, $path) {
142
-		$this->uploadFile($tmpFile, $path);
143
-		unlink($tmpFile);
144
-	}
141
+    public function writeBack($tmpFile, $path) {
142
+        $this->uploadFile($tmpFile, $path);
143
+        unlink($tmpFile);
144
+    }
145 145
 
146
-	/**
147
-	 * check if php-ftp is installed
148
-	 */
149
-	public static function checkDependencies() {
150
-		if (function_exists('ftp_login')) {
151
-			return true;
152
-		} else {
153
-			return array('ftp');
154
-		}
155
-	}
146
+    /**
147
+     * check if php-ftp is installed
148
+     */
149
+    public static function checkDependencies() {
150
+        if (function_exists('ftp_login')) {
151
+            return true;
152
+        } else {
153
+            return array('ftp');
154
+        }
155
+    }
156 156
 
157 157
 }
Please login to merge, or discard this patch.
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -37,7 +37,7 @@  discard block
 block discarded – undo
37 37
 use Icewind\Streams\CallbackWrapper;
38 38
 use Icewind\Streams\RetryWrapper;
39 39
 
40
-class FTP extends StreamWrapper{
40
+class FTP extends StreamWrapper {
41 41
 	private $password;
42 42
 	private $user;
43 43
 	private $host;
@@ -46,17 +46,17 @@  discard block
 block discarded – undo
46 46
 
47 47
 	public function __construct($params) {
48 48
 		if (isset($params['host']) && isset($params['user']) && isset($params['password'])) {
49
-			$this->host=$params['host'];
50
-			$this->user=$params['user'];
51
-			$this->password=$params['password'];
49
+			$this->host = $params['host'];
50
+			$this->user = $params['user'];
51
+			$this->password = $params['password'];
52 52
 			if (isset($params['secure'])) {
53 53
 				$this->secure = $params['secure'];
54 54
 			} else {
55 55
 				$this->secure = false;
56 56
 			}
57
-			$this->root=isset($params['root'])?$params['root']:'/';
58
-			if ( ! $this->root || $this->root[0]!=='/') {
59
-				$this->root='/'.$this->root;
57
+			$this->root = isset($params['root']) ? $params['root'] : '/';
58
+			if (!$this->root || $this->root[0] !== '/') {
59
+				$this->root = '/'.$this->root;
60 60
 			}
61 61
 			if (substr($this->root, -1) !== '/') {
62 62
 				$this->root .= '/';
@@ -67,8 +67,8 @@  discard block
 block discarded – undo
67 67
 		
68 68
 	}
69 69
 
70
-	public function getId(){
71
-		return 'ftp::' . $this->user . '@' . $this->host . '/' . $this->root;
70
+	public function getId() {
71
+		return 'ftp::'.$this->user.'@'.$this->host.'/'.$this->root;
72 72
 	}
73 73
 
74 74
 	/**
@@ -77,11 +77,11 @@  discard block
 block discarded – undo
77 77
 	 * @return string
78 78
 	 */
79 79
 	public function constructUrl($path) {
80
-		$url='ftp';
80
+		$url = 'ftp';
81 81
 		if ($this->secure) {
82
-			$url.='s';
82
+			$url .= 's';
83 83
 		}
84
-		$url.='://'.urlencode($this->user).':'.urlencode($this->password).'@'.$this->host.$this->root.$path;
84
+		$url .= '://'.urlencode($this->user).':'.urlencode($this->password).'@'.$this->host.$this->root.$path;
85 85
 		return $url;
86 86
 	}
87 87
 
@@ -100,8 +100,8 @@  discard block
 block discarded – undo
100 100
 			return $result;
101 101
 		}
102 102
 	}
103
-	public function fopen($path,$mode) {
104
-		switch($mode) {
103
+	public function fopen($path, $mode) {
104
+		switch ($mode) {
105 105
 			case 'r':
106 106
 			case 'rb':
107 107
 			case 'w':
@@ -121,17 +121,17 @@  discard block
 block discarded – undo
121 121
 			case 'c':
122 122
 			case 'c+':
123 123
 				//emulate these
124
-				if (strrpos($path, '.')!==false) {
125
-					$ext=substr($path, strrpos($path, '.'));
124
+				if (strrpos($path, '.') !== false) {
125
+					$ext = substr($path, strrpos($path, '.'));
126 126
 				} else {
127
-					$ext='';
127
+					$ext = '';
128 128
 				}
129 129
 				$tmpFile = \OC::$server->getTempManager()->getTemporaryFile();
130 130
 				if ($this->file_exists($path)) {
131 131
 					$this->getFile($path, $tmpFile);
132 132
 				}
133 133
 				$handle = fopen($tmpFile, $mode);
134
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
134
+				return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
135 135
 					$this->writeBack($tmpFile, $path);
136 136
 				});
137 137
 		}
Please login to merge, or discard this patch.
apps/files_external/lib/config.php 2 patches
Indentation   +405 added lines, -405 removed lines patch added patch discarded remove patch
@@ -55,409 +55,409 @@
 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 &$option) {
243
-			$option = self::substitutePlaceholdersInConfig($option);
244
-			if(!self::arePlaceholdersSubstituted($option)) {
245
-				\OC::$server->getLogger()->error(
246
-					'A placeholder was not substituted: {option} for mount type {class}',
247
-					[
248
-						'app' => 'files_external',
249
-						'option' => $option,
250
-						'class' => $class,
251
-					]
252
-				);
253
-				throw new StorageNotAvailableException(
254
-					'Mount configuration incomplete',
255
-					StorageNotAvailableException::STATUS_INCOMPLETE_CONF
256
-				);
257
-			}
258
-		}
259
-		if (class_exists($class)) {
260
-			try {
261
-				/** @var \OC\Files\Storage\Common $storage */
262
-				$storage = new $class($options);
263
-
264
-				try {
265
-					$result = $storage->test($isPersonal, $testOnly);
266
-					$storage->setAvailability($result);
267
-					if ($result) {
268
-						return StorageNotAvailableException::STATUS_SUCCESS;
269
-					}
270
-				} catch (\Exception $e) {
271
-					$storage->setAvailability(false);
272
-					throw $e;
273
-				}
274
-			} catch (Exception $exception) {
275
-				\OC::$server->getLogger()->logException($exception, ['app' => 'files_external']);
276
-				throw $exception;
277
-			}
278
-		}
279
-		return StorageNotAvailableException::STATUS_ERROR;
280
-	}
281
-
282
-	public static function arePlaceholdersSubstituted($option):bool {
283
-		$result = true;
284
-		if(is_array($option)) {
285
-			foreach ($option as $optionItem) {
286
-				if(is_array($optionItem)) {
287
-					$result = $result && self::arePlaceholdersSubstituted($option);
288
-				}
289
-			}
290
-		} else if (is_string($option)) {
291
-			if (strpos($option, '$') !== false) {
292
-				$result = false;
293
-			}
294
-		}
295
-		return $result;
296
-	}
297
-
298
-	/**
299
-	 * Read the mount points in the config file into an array
300
-	 *
301
-	 * @param string|null $user If not null, personal for $user, otherwise system
302
-	 * @return array
303
-	 */
304
-	public static function readData($user = null) {
305
-		if (isset($user)) {
306
-			$jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
307
-		} else {
308
-			$config = \OC::$server->getConfig();
309
-			$datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
310
-			$jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
311
-		}
312
-		if (is_file($jsonFile)) {
313
-			$mountPoints = json_decode(file_get_contents($jsonFile), true);
314
-			if (is_array($mountPoints)) {
315
-				return $mountPoints;
316
-			}
317
-		}
318
-		return array();
319
-	}
320
-
321
-	/**
322
-	 * Get backend dependency message
323
-	 * TODO: move into AppFramework along with templates
324
-	 *
325
-	 * @param Backend[] $backends
326
-	 * @return string
327
-	 */
328
-	public static function dependencyMessage($backends) {
329
-		$l = \OC::$server->getL10N('files_external');
330
-		$message = '';
331
-		$dependencyGroups = [];
332
-
333
-		foreach ($backends as $backend) {
334
-			foreach ($backend->checkDependencies() as $dependency) {
335
-				if ($message = $dependency->getMessage()) {
336
-					$message .= '<p>' . $message . '</p>';
337
-				} else {
338
-					$dependencyGroups[$dependency->getDependency()][] = $backend;
339
-				}
340
-			}
341
-		}
342
-
343
-		foreach ($dependencyGroups as $module => $dependants) {
344
-			$backends = implode(', ', array_map(function($backend) {
345
-				return '"' . $backend->getText() . '"';
346
-			}, $dependants));
347
-			$message .= '<p>' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends) . '</p>';
348
-		}
349
-
350
-		return $message;
351
-	}
352
-
353
-	/**
354
-	 * Returns a dependency missing message
355
-	 *
356
-	 * @param \OCP\IL10N $l
357
-	 * @param string $module
358
-	 * @param string $backend
359
-	 * @return string
360
-	 */
361
-	private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
362
-		switch (strtolower($module)) {
363
-			case 'curl':
364
-				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]);
365
-			case 'ftp':
366
-				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]);
367
-			default:
368
-				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]);
369
-		}
370
-	}
371
-
372
-	/**
373
-	 * Encrypt passwords in the given config options
374
-	 *
375
-	 * @param array $options mount options
376
-	 * @return array updated options
377
-	 */
378
-	public static function encryptPasswords($options) {
379
-		if (isset($options['password'])) {
380
-			$options['password_encrypted'] = self::encryptPassword($options['password']);
381
-			// do not unset the password, we want to keep the keys order
382
-			// on load... because that's how the UI currently works
383
-			$options['password'] = '';
384
-		}
385
-		return $options;
386
-	}
387
-
388
-	/**
389
-	 * Decrypt passwords in the given config options
390
-	 *
391
-	 * @param array $options mount options
392
-	 * @return array updated options
393
-	 */
394
-	public static function decryptPasswords($options) {
395
-		// note: legacy options might still have the unencrypted password in the "password" field
396
-		if (isset($options['password_encrypted'])) {
397
-			$options['password'] = self::decryptPassword($options['password_encrypted']);
398
-			unset($options['password_encrypted']);
399
-		}
400
-		return $options;
401
-	}
402
-
403
-	/**
404
-	 * Encrypt a single password
405
-	 *
406
-	 * @param string $password plain text password
407
-	 * @return string encrypted password
408
-	 */
409
-	private static function encryptPassword($password) {
410
-		$cipher = self::getCipher();
411
-		$iv = \OC::$server->getSecureRandom()->generate(16);
412
-		$cipher->setIV($iv);
413
-		return base64_encode($iv . $cipher->encrypt($password));
414
-	}
415
-
416
-	/**
417
-	 * Decrypts a single password
418
-	 *
419
-	 * @param string $encryptedPassword encrypted password
420
-	 * @return string plain text password
421
-	 */
422
-	private static function decryptPassword($encryptedPassword) {
423
-		$cipher = self::getCipher();
424
-		$binaryPassword = base64_decode($encryptedPassword);
425
-		$iv = substr($binaryPassword, 0, 16);
426
-		$cipher->setIV($iv);
427
-		$binaryPassword = substr($binaryPassword, 16);
428
-		return $cipher->decrypt($binaryPassword);
429
-	}
430
-
431
-	/**
432
-	 * Returns the encryption cipher
433
-	 *
434
-	 * @return AES
435
-	 */
436
-	private static function getCipher() {
437
-		$cipher = new AES(AES::MODE_CBC);
438
-		$cipher->setKey(\OC::$server->getConfig()->getSystemValue('passwordsalt', null));
439
-		return $cipher;
440
-	}
441
-
442
-	/**
443
-	 * Computes a hash based on the given configuration.
444
-	 * This is mostly used to find out whether configurations
445
-	 * are the same.
446
-	 *
447
-	 * @param array $config
448
-	 * @return string
449
-	 */
450
-	public static function makeConfigHash($config) {
451
-		$data = json_encode(
452
-			array(
453
-				'c' => $config['backend'],
454
-				'a' => $config['authMechanism'],
455
-				'm' => $config['mountpoint'],
456
-				'o' => $config['options'],
457
-				'p' => isset($config['priority']) ? $config['priority'] : -1,
458
-				'mo' => isset($config['mountOptions']) ? $config['mountOptions'] : [],
459
-			)
460
-		);
461
-		return hash('md5', $data);
462
-	}
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 &$option) {
243
+            $option = self::substitutePlaceholdersInConfig($option);
244
+            if(!self::arePlaceholdersSubstituted($option)) {
245
+                \OC::$server->getLogger()->error(
246
+                    'A placeholder was not substituted: {option} for mount type {class}',
247
+                    [
248
+                        'app' => 'files_external',
249
+                        'option' => $option,
250
+                        'class' => $class,
251
+                    ]
252
+                );
253
+                throw new StorageNotAvailableException(
254
+                    'Mount configuration incomplete',
255
+                    StorageNotAvailableException::STATUS_INCOMPLETE_CONF
256
+                );
257
+            }
258
+        }
259
+        if (class_exists($class)) {
260
+            try {
261
+                /** @var \OC\Files\Storage\Common $storage */
262
+                $storage = new $class($options);
263
+
264
+                try {
265
+                    $result = $storage->test($isPersonal, $testOnly);
266
+                    $storage->setAvailability($result);
267
+                    if ($result) {
268
+                        return StorageNotAvailableException::STATUS_SUCCESS;
269
+                    }
270
+                } catch (\Exception $e) {
271
+                    $storage->setAvailability(false);
272
+                    throw $e;
273
+                }
274
+            } catch (Exception $exception) {
275
+                \OC::$server->getLogger()->logException($exception, ['app' => 'files_external']);
276
+                throw $exception;
277
+            }
278
+        }
279
+        return StorageNotAvailableException::STATUS_ERROR;
280
+    }
281
+
282
+    public static function arePlaceholdersSubstituted($option):bool {
283
+        $result = true;
284
+        if(is_array($option)) {
285
+            foreach ($option as $optionItem) {
286
+                if(is_array($optionItem)) {
287
+                    $result = $result && self::arePlaceholdersSubstituted($option);
288
+                }
289
+            }
290
+        } else if (is_string($option)) {
291
+            if (strpos($option, '$') !== false) {
292
+                $result = false;
293
+            }
294
+        }
295
+        return $result;
296
+    }
297
+
298
+    /**
299
+     * Read the mount points in the config file into an array
300
+     *
301
+     * @param string|null $user If not null, personal for $user, otherwise system
302
+     * @return array
303
+     */
304
+    public static function readData($user = null) {
305
+        if (isset($user)) {
306
+            $jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
307
+        } else {
308
+            $config = \OC::$server->getConfig();
309
+            $datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
310
+            $jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
311
+        }
312
+        if (is_file($jsonFile)) {
313
+            $mountPoints = json_decode(file_get_contents($jsonFile), true);
314
+            if (is_array($mountPoints)) {
315
+                return $mountPoints;
316
+            }
317
+        }
318
+        return array();
319
+    }
320
+
321
+    /**
322
+     * Get backend dependency message
323
+     * TODO: move into AppFramework along with templates
324
+     *
325
+     * @param Backend[] $backends
326
+     * @return string
327
+     */
328
+    public static function dependencyMessage($backends) {
329
+        $l = \OC::$server->getL10N('files_external');
330
+        $message = '';
331
+        $dependencyGroups = [];
332
+
333
+        foreach ($backends as $backend) {
334
+            foreach ($backend->checkDependencies() as $dependency) {
335
+                if ($message = $dependency->getMessage()) {
336
+                    $message .= '<p>' . $message . '</p>';
337
+                } else {
338
+                    $dependencyGroups[$dependency->getDependency()][] = $backend;
339
+                }
340
+            }
341
+        }
342
+
343
+        foreach ($dependencyGroups as $module => $dependants) {
344
+            $backends = implode(', ', array_map(function($backend) {
345
+                return '"' . $backend->getText() . '"';
346
+            }, $dependants));
347
+            $message .= '<p>' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends) . '</p>';
348
+        }
349
+
350
+        return $message;
351
+    }
352
+
353
+    /**
354
+     * Returns a dependency missing message
355
+     *
356
+     * @param \OCP\IL10N $l
357
+     * @param string $module
358
+     * @param string $backend
359
+     * @return string
360
+     */
361
+    private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
362
+        switch (strtolower($module)) {
363
+            case 'curl':
364
+                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]);
365
+            case 'ftp':
366
+                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]);
367
+            default:
368
+                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]);
369
+        }
370
+    }
371
+
372
+    /**
373
+     * Encrypt passwords in the given config options
374
+     *
375
+     * @param array $options mount options
376
+     * @return array updated options
377
+     */
378
+    public static function encryptPasswords($options) {
379
+        if (isset($options['password'])) {
380
+            $options['password_encrypted'] = self::encryptPassword($options['password']);
381
+            // do not unset the password, we want to keep the keys order
382
+            // on load... because that's how the UI currently works
383
+            $options['password'] = '';
384
+        }
385
+        return $options;
386
+    }
387
+
388
+    /**
389
+     * Decrypt passwords in the given config options
390
+     *
391
+     * @param array $options mount options
392
+     * @return array updated options
393
+     */
394
+    public static function decryptPasswords($options) {
395
+        // note: legacy options might still have the unencrypted password in the "password" field
396
+        if (isset($options['password_encrypted'])) {
397
+            $options['password'] = self::decryptPassword($options['password_encrypted']);
398
+            unset($options['password_encrypted']);
399
+        }
400
+        return $options;
401
+    }
402
+
403
+    /**
404
+     * Encrypt a single password
405
+     *
406
+     * @param string $password plain text password
407
+     * @return string encrypted password
408
+     */
409
+    private static function encryptPassword($password) {
410
+        $cipher = self::getCipher();
411
+        $iv = \OC::$server->getSecureRandom()->generate(16);
412
+        $cipher->setIV($iv);
413
+        return base64_encode($iv . $cipher->encrypt($password));
414
+    }
415
+
416
+    /**
417
+     * Decrypts a single password
418
+     *
419
+     * @param string $encryptedPassword encrypted password
420
+     * @return string plain text password
421
+     */
422
+    private static function decryptPassword($encryptedPassword) {
423
+        $cipher = self::getCipher();
424
+        $binaryPassword = base64_decode($encryptedPassword);
425
+        $iv = substr($binaryPassword, 0, 16);
426
+        $cipher->setIV($iv);
427
+        $binaryPassword = substr($binaryPassword, 16);
428
+        return $cipher->decrypt($binaryPassword);
429
+    }
430
+
431
+    /**
432
+     * Returns the encryption cipher
433
+     *
434
+     * @return AES
435
+     */
436
+    private static function getCipher() {
437
+        $cipher = new AES(AES::MODE_CBC);
438
+        $cipher->setKey(\OC::$server->getConfig()->getSystemValue('passwordsalt', null));
439
+        return $cipher;
440
+    }
441
+
442
+    /**
443
+     * Computes a hash based on the given configuration.
444
+     * This is mostly used to find out whether configurations
445
+     * are the same.
446
+     *
447
+     * @param array $config
448
+     * @return string
449
+     */
450
+    public static function makeConfigHash($config) {
451
+        $data = json_encode(
452
+            array(
453
+                'c' => $config['backend'],
454
+                'a' => $config['authMechanism'],
455
+                'm' => $config['mountpoint'],
456
+                'o' => $config['options'],
457
+                'p' => isset($config['priority']) ? $config['priority'] : -1,
458
+                'mo' => isset($config['mountOptions']) ? $config['mountOptions'] : [],
459
+            )
460
+        );
461
+        return hash('md5', $data);
462
+    }
463 463
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -241,7 +241,7 @@  discard block
 block discarded – undo
241 241
 		}
242 242
 		foreach ($options as &$option) {
243 243
 			$option = self::substitutePlaceholdersInConfig($option);
244
-			if(!self::arePlaceholdersSubstituted($option)) {
244
+			if (!self::arePlaceholdersSubstituted($option)) {
245 245
 				\OC::$server->getLogger()->error(
246 246
 					'A placeholder was not substituted: {option} for mount type {class}',
247 247
 					[
@@ -281,9 +281,9 @@  discard block
 block discarded – undo
281 281
 
282 282
 	public static function arePlaceholdersSubstituted($option):bool {
283 283
 		$result = true;
284
-		if(is_array($option)) {
284
+		if (is_array($option)) {
285 285
 			foreach ($option as $optionItem) {
286
-				if(is_array($optionItem)) {
286
+				if (is_array($optionItem)) {
287 287
 					$result = $result && self::arePlaceholdersSubstituted($option);
288 288
 				}
289 289
 			}
@@ -303,11 +303,11 @@  discard block
 block discarded – undo
303 303
 	 */
304 304
 	public static function readData($user = null) {
305 305
 		if (isset($user)) {
306
-			$jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
306
+			$jsonFile = \OC::$server->getUserManager()->get($user)->getHome().'/mount.json';
307 307
 		} else {
308 308
 			$config = \OC::$server->getConfig();
309
-			$datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
310
-			$jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
309
+			$datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data/');
310
+			$jsonFile = $config->getSystemValue('mount_file', $datadir.'/mount.json');
311 311
 		}
312 312
 		if (is_file($jsonFile)) {
313 313
 			$mountPoints = json_decode(file_get_contents($jsonFile), true);
@@ -333,7 +333,7 @@  discard block
 block discarded – undo
333 333
 		foreach ($backends as $backend) {
334 334
 			foreach ($backend->checkDependencies() as $dependency) {
335 335
 				if ($message = $dependency->getMessage()) {
336
-					$message .= '<p>' . $message . '</p>';
336
+					$message .= '<p>'.$message.'</p>';
337 337
 				} else {
338 338
 					$dependencyGroups[$dependency->getDependency()][] = $backend;
339 339
 				}
@@ -342,9 +342,9 @@  discard block
 block discarded – undo
342 342
 
343 343
 		foreach ($dependencyGroups as $module => $dependants) {
344 344
 			$backends = implode(', ', array_map(function($backend) {
345
-				return '"' . $backend->getText() . '"';
345
+				return '"'.$backend->getText().'"';
346 346
 			}, $dependants));
347
-			$message .= '<p>' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends) . '</p>';
347
+			$message .= '<p>'.OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends).'</p>';
348 348
 		}
349 349
 
350 350
 		return $message;
@@ -361,11 +361,11 @@  discard block
 block discarded – undo
361 361
 	private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
362 362
 		switch (strtolower($module)) {
363 363
 			case 'curl':
364
-				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]);
364
+				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]);
365 365
 			case 'ftp':
366
-				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]);
366
+				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]);
367 367
 			default:
368
-				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]);
368
+				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]);
369 369
 		}
370 370
 	}
371 371
 
@@ -410,7 +410,7 @@  discard block
 block discarded – undo
410 410
 		$cipher = self::getCipher();
411 411
 		$iv = \OC::$server->getSecureRandom()->generate(16);
412 412
 		$cipher->setIV($iv);
413
-		return base64_encode($iv . $cipher->encrypt($password));
413
+		return base64_encode($iv.$cipher->encrypt($password));
414 414
 	}
415 415
 
416 416
 	/**
Please login to merge, or discard this patch.
apps/files_external/lib/AppInfo/Application.php 1 patch
Indentation   +95 added lines, -95 removed lines patch added patch discarded remove patch
@@ -68,100 +68,100 @@
 block discarded – undo
68 68
  */
69 69
 class Application extends App implements IBackendProvider, IAuthMechanismProvider {
70 70
 
71
-	/**
72
-	 * Application constructor.
73
-	 *
74
-	 * @throws \OCP\AppFramework\QueryException
75
-	 */
76
-	public function __construct(array $urlParams = []) {
77
-		parent::__construct('files_external', $urlParams);
78
-
79
-		$container = $this->getContainer();
80
-
81
-		$container->registerService(IUserMountCache::class, function (IAppContainer $c) {
82
-			return $c->getServer()->query('UserMountCache');
83
-		});
84
-
85
-		/** @var BackendService $backendService */
86
-		$backendService = $container->query(BackendService::class);
87
-		$backendService->registerBackendProvider($this);
88
-		$backendService->registerAuthMechanismProvider($this);
89
-		$backendService->registerConfigHandler('user', function() use ($container) {
90
-			return $container->query(UserPlaceholderHandler::class);
91
-		});
92
-
93
-		// force-load auth mechanisms since some will register hooks
94
-		// TODO: obsolete these and use the TokenProvider to get the user's password from the session
95
-		$this->getAuthMechanisms();
96
-
97
-		// don't remove this, as app loading order might be a side effect and
98
-		// querying the service from the server not reliable
99
-		\OC::$server->getEventDispatcher()->dispatch(
100
-			'OCA\\Files_External::loadAdditionalBackends'
101
-		);
102
-	}
103
-
104
-	/**
105
-	 * @{inheritdoc}
106
-	 */
107
-	public function getBackends() {
108
-		$container = $this->getContainer();
109
-
110
-		$backends = [
111
-			$container->query(Local::class),
112
-			$container->query(FTP::class),
113
-			$container->query(DAV::class),
114
-			$container->query(OwnCloud::class),
115
-			$container->query(SFTP::class),
116
-			$container->query(AmazonS3::class),
117
-			$container->query(Swift::class),
118
-			$container->query(SFTP_Key::class),
119
-			$container->query(SMB::class),
120
-			$container->query(SMB_OC::class),
121
-		];
122
-
123
-		return $backends;
124
-	}
125
-
126
-	/**
127
-	 * @{inheritdoc}
128
-	 */
129
-	public function getAuthMechanisms() {
130
-		$container = $this->getContainer();
131
-
132
-		return [
133
-			// AuthMechanism::SCHEME_NULL mechanism
134
-			$container->query(NullMechanism::class),
135
-
136
-			// AuthMechanism::SCHEME_BUILTIN mechanism
137
-			$container->query(Builtin::class),
138
-
139
-			// AuthMechanism::SCHEME_PASSWORD mechanisms
140
-			$container->query(Password::class),
141
-			$container->query(SessionCredentials::class),
142
-			$container->query(LoginCredentials::class),
143
-			$container->query(UserProvided::class),
144
-			$container->query(GlobalAuth::class),
145
-
146
-			// AuthMechanism::SCHEME_OAUTH1 mechanisms
147
-			$container->query(OAuth1::class),
148
-
149
-			// AuthMechanism::SCHEME_OAUTH2 mechanisms
150
-			$container->query(OAuth2::class),
151
-
152
-			// AuthMechanism::SCHEME_PUBLICKEY mechanisms
153
-			$container->query(RSA::class),
154
-			$container->query(RSAPrivateKey::class),
155
-
156
-			// AuthMechanism::SCHEME_OPENSTACK mechanisms
157
-			$container->query(OpenStackV2::class),
158
-			$container->query(OpenStackV3::class),
159
-			$container->query(Rackspace::class),
160
-
161
-			// Specialized mechanisms
162
-			$container->query(AccessKey::class),
163
-			$container->query(KerberosAuth::class),
164
-		];
165
-	}
71
+    /**
72
+     * Application constructor.
73
+     *
74
+     * @throws \OCP\AppFramework\QueryException
75
+     */
76
+    public function __construct(array $urlParams = []) {
77
+        parent::__construct('files_external', $urlParams);
78
+
79
+        $container = $this->getContainer();
80
+
81
+        $container->registerService(IUserMountCache::class, function (IAppContainer $c) {
82
+            return $c->getServer()->query('UserMountCache');
83
+        });
84
+
85
+        /** @var BackendService $backendService */
86
+        $backendService = $container->query(BackendService::class);
87
+        $backendService->registerBackendProvider($this);
88
+        $backendService->registerAuthMechanismProvider($this);
89
+        $backendService->registerConfigHandler('user', function() use ($container) {
90
+            return $container->query(UserPlaceholderHandler::class);
91
+        });
92
+
93
+        // force-load auth mechanisms since some will register hooks
94
+        // TODO: obsolete these and use the TokenProvider to get the user's password from the session
95
+        $this->getAuthMechanisms();
96
+
97
+        // don't remove this, as app loading order might be a side effect and
98
+        // querying the service from the server not reliable
99
+        \OC::$server->getEventDispatcher()->dispatch(
100
+            'OCA\\Files_External::loadAdditionalBackends'
101
+        );
102
+    }
103
+
104
+    /**
105
+     * @{inheritdoc}
106
+     */
107
+    public function getBackends() {
108
+        $container = $this->getContainer();
109
+
110
+        $backends = [
111
+            $container->query(Local::class),
112
+            $container->query(FTP::class),
113
+            $container->query(DAV::class),
114
+            $container->query(OwnCloud::class),
115
+            $container->query(SFTP::class),
116
+            $container->query(AmazonS3::class),
117
+            $container->query(Swift::class),
118
+            $container->query(SFTP_Key::class),
119
+            $container->query(SMB::class),
120
+            $container->query(SMB_OC::class),
121
+        ];
122
+
123
+        return $backends;
124
+    }
125
+
126
+    /**
127
+     * @{inheritdoc}
128
+     */
129
+    public function getAuthMechanisms() {
130
+        $container = $this->getContainer();
131
+
132
+        return [
133
+            // AuthMechanism::SCHEME_NULL mechanism
134
+            $container->query(NullMechanism::class),
135
+
136
+            // AuthMechanism::SCHEME_BUILTIN mechanism
137
+            $container->query(Builtin::class),
138
+
139
+            // AuthMechanism::SCHEME_PASSWORD mechanisms
140
+            $container->query(Password::class),
141
+            $container->query(SessionCredentials::class),
142
+            $container->query(LoginCredentials::class),
143
+            $container->query(UserProvided::class),
144
+            $container->query(GlobalAuth::class),
145
+
146
+            // AuthMechanism::SCHEME_OAUTH1 mechanisms
147
+            $container->query(OAuth1::class),
148
+
149
+            // AuthMechanism::SCHEME_OAUTH2 mechanisms
150
+            $container->query(OAuth2::class),
151
+
152
+            // AuthMechanism::SCHEME_PUBLICKEY mechanisms
153
+            $container->query(RSA::class),
154
+            $container->query(RSAPrivateKey::class),
155
+
156
+            // AuthMechanism::SCHEME_OPENSTACK mechanisms
157
+            $container->query(OpenStackV2::class),
158
+            $container->query(OpenStackV3::class),
159
+            $container->query(Rackspace::class),
160
+
161
+            // Specialized mechanisms
162
+            $container->query(AccessKey::class),
163
+            $container->query(KerberosAuth::class),
164
+        ];
165
+    }
166 166
 
167 167
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Service/BackendService.php 2 patches
Indentation   +312 added lines, -312 removed lines patch added patch discarded remove patch
@@ -37,316 +37,316 @@
 block discarded – undo
37 37
  */
38 38
 class BackendService {
39 39
 
40
-	/** Visibility constants for VisibilityTrait */
41
-	const VISIBILITY_NONE = 0;
42
-	const VISIBILITY_PERSONAL = 1;
43
-	const VISIBILITY_ADMIN = 2;
44
-	//const VISIBILITY_ALIENS = 4;
45
-
46
-	const VISIBILITY_DEFAULT = 3; // PERSONAL | ADMIN
47
-
48
-	/** Priority constants for PriorityTrait */
49
-	const PRIORITY_DEFAULT = 100;
50
-
51
-	/** @var IConfig */
52
-	protected $config;
53
-
54
-	/** @var bool */
55
-	private $userMountingAllowed = true;
56
-
57
-	/** @var string[] */
58
-	private $userMountingBackends = [];
59
-
60
-	/** @var Backend[] */
61
-	private $backends = [];
62
-
63
-	/** @var IBackendProvider[] */
64
-	private $backendProviders = [];
65
-
66
-	/** @var AuthMechanism[] */
67
-	private $authMechanisms = [];
68
-
69
-	/** @var IAuthMechanismProvider[] */
70
-	private $authMechanismProviders = [];
71
-
72
-	/** @var callable[] */
73
-	private $configHandlerLoaders = [];
74
-
75
-	private $configHandlers = [];
76
-
77
-	/**
78
-	 * @param IConfig $config
79
-	 */
80
-	public function __construct(
81
-		IConfig $config
82
-	) {
83
-		$this->config = $config;
84
-
85
-		// Load config values
86
-		if ($this->config->getAppValue('files_external', 'allow_user_mounting', 'yes') !== 'yes') {
87
-			$this->userMountingAllowed = false;
88
-		}
89
-		$this->userMountingBackends = explode(',',
90
-			$this->config->getAppValue('files_external', 'user_mounting_backends', '')
91
-		);
92
-
93
-		// if no backend is in the list an empty string is in the array and user mounting is disabled
94
-		if ($this->userMountingBackends === ['']) {
95
-			$this->userMountingAllowed = false;
96
-		}
97
-	}
98
-
99
-	/**
100
-	 * Register a backend provider
101
-	 *
102
-	 * @since 9.1.0
103
-	 * @param IBackendProvider $provider
104
-	 */
105
-	public function registerBackendProvider(IBackendProvider $provider) {
106
-		$this->backendProviders[] = $provider;
107
-	}
108
-
109
-	private function loadBackendProviders() {
110
-		foreach ($this->backendProviders as $provider) {
111
-			$this->registerBackends($provider->getBackends());
112
-		}
113
-		$this->backendProviders = [];
114
-	}
115
-
116
-	/**
117
-	 * Register an auth mechanism provider
118
-	 *
119
-	 * @since 9.1.0
120
-	 * @param IAuthMechanismProvider $provider
121
-	 */
122
-	public function registerAuthMechanismProvider(IAuthMechanismProvider $provider) {
123
-		$this->authMechanismProviders[] = $provider;
124
-	}
125
-
126
-	private function loadAuthMechanismProviders() {
127
-		foreach ($this->authMechanismProviders as $provider) {
128
-			$this->registerAuthMechanisms($provider->getAuthMechanisms());
129
-		}
130
-		$this->authMechanismProviders = [];
131
-	}
132
-
133
-	/**
134
-	 * Register a backend
135
-	 *
136
-	 * @deprecated 9.1.0 use registerBackendProvider()
137
-	 * @param Backend $backend
138
-	 */
139
-	public function registerBackend(Backend $backend) {
140
-		if (!$this->isAllowedUserBackend($backend)) {
141
-			$backend->removeVisibility(BackendService::VISIBILITY_PERSONAL);
142
-		}
143
-		foreach ($backend->getIdentifierAliases() as $alias) {
144
-			$this->backends[$alias] = $backend;
145
-		}
146
-	}
147
-
148
-	/**
149
-	 * @deprecated 9.1.0 use registerBackendProvider()
150
-	 * @param Backend[] $backends
151
-	 */
152
-	public function registerBackends(array $backends) {
153
-		foreach ($backends as $backend) {
154
-			$this->registerBackend($backend);
155
-		}
156
-	}
157
-	/**
158
-	 * Register an authentication mechanism
159
-	 *
160
-	 * @deprecated 9.1.0 use registerAuthMechanismProvider()
161
-	 * @param AuthMechanism $authMech
162
-	 */
163
-	public function registerAuthMechanism(AuthMechanism $authMech) {
164
-		if (!$this->isAllowedAuthMechanism($authMech)) {
165
-			$authMech->removeVisibility(BackendService::VISIBILITY_PERSONAL);
166
-		}
167
-		foreach ($authMech->getIdentifierAliases() as $alias) {
168
-			$this->authMechanisms[$alias] = $authMech;
169
-		}
170
-	}
171
-
172
-	/**
173
-	 * @deprecated 9.1.0 use registerAuthMechanismProvider()
174
-	 * @param AuthMechanism[] $mechanisms
175
-	 */
176
-	public function registerAuthMechanisms(array $mechanisms) {
177
-		foreach ($mechanisms as $mechanism) {
178
-			$this->registerAuthMechanism($mechanism);
179
-		}
180
-	}
181
-
182
-	/**
183
-	 * Get all backends
184
-	 *
185
-	 * @return Backend[]
186
-	 */
187
-	public function getBackends() {
188
-		$this->loadBackendProviders();
189
-		// only return real identifiers, no aliases
190
-		$backends = [];
191
-		foreach ($this->backends as $backend) {
192
-			$backends[$backend->getIdentifier()] = $backend;
193
-		}
194
-		return $backends;
195
-	}
196
-
197
-	/**
198
-	 * Get all available backends
199
-	 *
200
-	 * @return Backend[]
201
-	 */
202
-	public function getAvailableBackends() {
203
-		return array_filter($this->getBackends(), function($backend) {
204
-			return !$backend->checkDependencies();
205
-		});
206
-	}
207
-
208
-	/**
209
-	 * @param string $identifier
210
-	 * @return Backend|null
211
-	 */
212
-	public function getBackend($identifier) {
213
-		$this->loadBackendProviders();
214
-		if (isset($this->backends[$identifier])) {
215
-			return $this->backends[$identifier];
216
-		}
217
-		return null;
218
-	}
219
-
220
-	/**
221
-	 * Get all authentication mechanisms
222
-	 *
223
-	 * @return AuthMechanism[]
224
-	 */
225
-	public function getAuthMechanisms() {
226
-		$this->loadAuthMechanismProviders();
227
-		// only return real identifiers, no aliases
228
-		$mechanisms = [];
229
-		foreach ($this->authMechanisms as $mechanism) {
230
-			$mechanisms[$mechanism->getIdentifier()] = $mechanism;
231
-		}
232
-		return $mechanisms;
233
-	}
234
-
235
-	/**
236
-	 * Get all authentication mechanisms for schemes
237
-	 *
238
-	 * @param string[] $schemes
239
-	 * @return AuthMechanism[]
240
-	 */
241
-	public function getAuthMechanismsByScheme(array $schemes) {
242
-		return array_filter($this->getAuthMechanisms(), function($authMech) use ($schemes) {
243
-			return in_array($authMech->getScheme(), $schemes, true);
244
-		});
245
-	}
246
-
247
-	/**
248
-	 * @param string $identifier
249
-	 * @return AuthMechanism|null
250
-	 */
251
-	public function getAuthMechanism($identifier) {
252
-		$this->loadAuthMechanismProviders();
253
-		if (isset($this->authMechanisms[$identifier])) {
254
-			return $this->authMechanisms[$identifier];
255
-		}
256
-		return null;
257
-	}
258
-
259
-	/**
260
-	 * @return bool
261
-	 */
262
-	public function isUserMountingAllowed() {
263
-		return $this->userMountingAllowed;
264
-	}
265
-
266
-	/**
267
-	 * Check a backend if a user is allowed to mount it
268
-	 *
269
-	 * @param Backend $backend
270
-	 * @return bool
271
-	 */
272
-	protected function isAllowedUserBackend(Backend $backend) {
273
-		if ($this->userMountingAllowed &&
274
-			array_intersect($backend->getIdentifierAliases(), $this->userMountingBackends)
275
-		) {
276
-			return true;
277
-		}
278
-		return false;
279
-	}
280
-
281
-	/**
282
-	 * Check an authentication mechanism if a user is allowed to use it
283
-	 *
284
-	 * @param AuthMechanism $authMechanism
285
-	 * @return bool
286
-	 */
287
-	protected function isAllowedAuthMechanism(AuthMechanism $authMechanism) {
288
-		return true; // not implemented
289
-	}
290
-
291
-	/**
292
-	 * registers a configuration handler
293
-	 *
294
-	 * The function of the provided $placeholder is mostly to act a sorting
295
-	 * criteria, so longer placeholders are replaced first. This avoids
296
-	 * "$user" overwriting parts of "$userMail" and "$userLang", for example.
297
-	 * The provided value should not contain the $ prefix, only a-z0-9 are
298
-	 * allowed. Upper case letters are lower cased, the replacement is case-
299
-	 * insensitive.
300
-	 *
301
-	 * The configHandlerLoader should just instantiate the handler on demand.
302
-	 * For now all handlers are instantiated when a mount is loaded, independent
303
-	 * of whether the placeholder is present or not. This may change in future.
304
-	 *
305
-	 * @since 16.0.0
306
-	 */
307
-	public function registerConfigHandler(string $placeholder, callable $configHandlerLoader) {
308
-		$placeholder = trim(strtolower($placeholder));
309
-		if(!(bool)\preg_match('/^[a-z0-9]*$/', $placeholder)) {
310
-			throw new \RuntimeException(sprintf(
311
-				'Invalid placeholder %s, only [a-z0-9] are allowed', $placeholder
312
-			));
313
-		}
314
-		if($placeholder === '') {
315
-			throw new \RuntimeException('Invalid empty placeholder');
316
-		}
317
-		if(isset($this->configHandlerLoaders[$placeholder]) || isset($this->configHandlers[$placeholder])) {
318
-			throw new \RuntimeException(sprintf('A handler is already registered for %s', $placeholder));
319
-		}
320
-		$this->configHandlerLoaders[$placeholder] = $configHandlerLoader;
321
-	}
322
-
323
-	protected function loadConfigHandlers():void {
324
-		$newLoaded = false;
325
-		foreach ($this->configHandlerLoaders as $placeholder => $loader) {
326
-			$handler = $loader();
327
-			if(!$handler instanceof IConfigHandler) {
328
-				throw new \RuntimeException(sprintf(
329
-					'Handler for %s is not an instance of IConfigHandler', $placeholder
330
-				));
331
-			}
332
-			$this->configHandlers[$placeholder] = $handler;
333
-			$newLoaded = true;
334
-		}
335
-		$this->configHandlerLoaders = [];
336
-		if($newLoaded) {
337
-			// ensure those with longest placeholders come first,
338
-			// to avoid substring matches
339
-			uksort($this->configHandlers, function ($phA, $phB) {
340
-				return strlen($phB) <=> strlen($phA);
341
-			});
342
-		}
343
-	}
344
-
345
-	/**
346
-	 * @since 16.0.0
347
-	 */
348
-	public function getConfigHandlers() {
349
-		$this->loadConfigHandlers();
350
-		return $this->configHandlers;
351
-	}
40
+    /** Visibility constants for VisibilityTrait */
41
+    const VISIBILITY_NONE = 0;
42
+    const VISIBILITY_PERSONAL = 1;
43
+    const VISIBILITY_ADMIN = 2;
44
+    //const VISIBILITY_ALIENS = 4;
45
+
46
+    const VISIBILITY_DEFAULT = 3; // PERSONAL | ADMIN
47
+
48
+    /** Priority constants for PriorityTrait */
49
+    const PRIORITY_DEFAULT = 100;
50
+
51
+    /** @var IConfig */
52
+    protected $config;
53
+
54
+    /** @var bool */
55
+    private $userMountingAllowed = true;
56
+
57
+    /** @var string[] */
58
+    private $userMountingBackends = [];
59
+
60
+    /** @var Backend[] */
61
+    private $backends = [];
62
+
63
+    /** @var IBackendProvider[] */
64
+    private $backendProviders = [];
65
+
66
+    /** @var AuthMechanism[] */
67
+    private $authMechanisms = [];
68
+
69
+    /** @var IAuthMechanismProvider[] */
70
+    private $authMechanismProviders = [];
71
+
72
+    /** @var callable[] */
73
+    private $configHandlerLoaders = [];
74
+
75
+    private $configHandlers = [];
76
+
77
+    /**
78
+     * @param IConfig $config
79
+     */
80
+    public function __construct(
81
+        IConfig $config
82
+    ) {
83
+        $this->config = $config;
84
+
85
+        // Load config values
86
+        if ($this->config->getAppValue('files_external', 'allow_user_mounting', 'yes') !== 'yes') {
87
+            $this->userMountingAllowed = false;
88
+        }
89
+        $this->userMountingBackends = explode(',',
90
+            $this->config->getAppValue('files_external', 'user_mounting_backends', '')
91
+        );
92
+
93
+        // if no backend is in the list an empty string is in the array and user mounting is disabled
94
+        if ($this->userMountingBackends === ['']) {
95
+            $this->userMountingAllowed = false;
96
+        }
97
+    }
98
+
99
+    /**
100
+     * Register a backend provider
101
+     *
102
+     * @since 9.1.0
103
+     * @param IBackendProvider $provider
104
+     */
105
+    public function registerBackendProvider(IBackendProvider $provider) {
106
+        $this->backendProviders[] = $provider;
107
+    }
108
+
109
+    private function loadBackendProviders() {
110
+        foreach ($this->backendProviders as $provider) {
111
+            $this->registerBackends($provider->getBackends());
112
+        }
113
+        $this->backendProviders = [];
114
+    }
115
+
116
+    /**
117
+     * Register an auth mechanism provider
118
+     *
119
+     * @since 9.1.0
120
+     * @param IAuthMechanismProvider $provider
121
+     */
122
+    public function registerAuthMechanismProvider(IAuthMechanismProvider $provider) {
123
+        $this->authMechanismProviders[] = $provider;
124
+    }
125
+
126
+    private function loadAuthMechanismProviders() {
127
+        foreach ($this->authMechanismProviders as $provider) {
128
+            $this->registerAuthMechanisms($provider->getAuthMechanisms());
129
+        }
130
+        $this->authMechanismProviders = [];
131
+    }
132
+
133
+    /**
134
+     * Register a backend
135
+     *
136
+     * @deprecated 9.1.0 use registerBackendProvider()
137
+     * @param Backend $backend
138
+     */
139
+    public function registerBackend(Backend $backend) {
140
+        if (!$this->isAllowedUserBackend($backend)) {
141
+            $backend->removeVisibility(BackendService::VISIBILITY_PERSONAL);
142
+        }
143
+        foreach ($backend->getIdentifierAliases() as $alias) {
144
+            $this->backends[$alias] = $backend;
145
+        }
146
+    }
147
+
148
+    /**
149
+     * @deprecated 9.1.0 use registerBackendProvider()
150
+     * @param Backend[] $backends
151
+     */
152
+    public function registerBackends(array $backends) {
153
+        foreach ($backends as $backend) {
154
+            $this->registerBackend($backend);
155
+        }
156
+    }
157
+    /**
158
+     * Register an authentication mechanism
159
+     *
160
+     * @deprecated 9.1.0 use registerAuthMechanismProvider()
161
+     * @param AuthMechanism $authMech
162
+     */
163
+    public function registerAuthMechanism(AuthMechanism $authMech) {
164
+        if (!$this->isAllowedAuthMechanism($authMech)) {
165
+            $authMech->removeVisibility(BackendService::VISIBILITY_PERSONAL);
166
+        }
167
+        foreach ($authMech->getIdentifierAliases() as $alias) {
168
+            $this->authMechanisms[$alias] = $authMech;
169
+        }
170
+    }
171
+
172
+    /**
173
+     * @deprecated 9.1.0 use registerAuthMechanismProvider()
174
+     * @param AuthMechanism[] $mechanisms
175
+     */
176
+    public function registerAuthMechanisms(array $mechanisms) {
177
+        foreach ($mechanisms as $mechanism) {
178
+            $this->registerAuthMechanism($mechanism);
179
+        }
180
+    }
181
+
182
+    /**
183
+     * Get all backends
184
+     *
185
+     * @return Backend[]
186
+     */
187
+    public function getBackends() {
188
+        $this->loadBackendProviders();
189
+        // only return real identifiers, no aliases
190
+        $backends = [];
191
+        foreach ($this->backends as $backend) {
192
+            $backends[$backend->getIdentifier()] = $backend;
193
+        }
194
+        return $backends;
195
+    }
196
+
197
+    /**
198
+     * Get all available backends
199
+     *
200
+     * @return Backend[]
201
+     */
202
+    public function getAvailableBackends() {
203
+        return array_filter($this->getBackends(), function($backend) {
204
+            return !$backend->checkDependencies();
205
+        });
206
+    }
207
+
208
+    /**
209
+     * @param string $identifier
210
+     * @return Backend|null
211
+     */
212
+    public function getBackend($identifier) {
213
+        $this->loadBackendProviders();
214
+        if (isset($this->backends[$identifier])) {
215
+            return $this->backends[$identifier];
216
+        }
217
+        return null;
218
+    }
219
+
220
+    /**
221
+     * Get all authentication mechanisms
222
+     *
223
+     * @return AuthMechanism[]
224
+     */
225
+    public function getAuthMechanisms() {
226
+        $this->loadAuthMechanismProviders();
227
+        // only return real identifiers, no aliases
228
+        $mechanisms = [];
229
+        foreach ($this->authMechanisms as $mechanism) {
230
+            $mechanisms[$mechanism->getIdentifier()] = $mechanism;
231
+        }
232
+        return $mechanisms;
233
+    }
234
+
235
+    /**
236
+     * Get all authentication mechanisms for schemes
237
+     *
238
+     * @param string[] $schemes
239
+     * @return AuthMechanism[]
240
+     */
241
+    public function getAuthMechanismsByScheme(array $schemes) {
242
+        return array_filter($this->getAuthMechanisms(), function($authMech) use ($schemes) {
243
+            return in_array($authMech->getScheme(), $schemes, true);
244
+        });
245
+    }
246
+
247
+    /**
248
+     * @param string $identifier
249
+     * @return AuthMechanism|null
250
+     */
251
+    public function getAuthMechanism($identifier) {
252
+        $this->loadAuthMechanismProviders();
253
+        if (isset($this->authMechanisms[$identifier])) {
254
+            return $this->authMechanisms[$identifier];
255
+        }
256
+        return null;
257
+    }
258
+
259
+    /**
260
+     * @return bool
261
+     */
262
+    public function isUserMountingAllowed() {
263
+        return $this->userMountingAllowed;
264
+    }
265
+
266
+    /**
267
+     * Check a backend if a user is allowed to mount it
268
+     *
269
+     * @param Backend $backend
270
+     * @return bool
271
+     */
272
+    protected function isAllowedUserBackend(Backend $backend) {
273
+        if ($this->userMountingAllowed &&
274
+            array_intersect($backend->getIdentifierAliases(), $this->userMountingBackends)
275
+        ) {
276
+            return true;
277
+        }
278
+        return false;
279
+    }
280
+
281
+    /**
282
+     * Check an authentication mechanism if a user is allowed to use it
283
+     *
284
+     * @param AuthMechanism $authMechanism
285
+     * @return bool
286
+     */
287
+    protected function isAllowedAuthMechanism(AuthMechanism $authMechanism) {
288
+        return true; // not implemented
289
+    }
290
+
291
+    /**
292
+     * registers a configuration handler
293
+     *
294
+     * The function of the provided $placeholder is mostly to act a sorting
295
+     * criteria, so longer placeholders are replaced first. This avoids
296
+     * "$user" overwriting parts of "$userMail" and "$userLang", for example.
297
+     * The provided value should not contain the $ prefix, only a-z0-9 are
298
+     * allowed. Upper case letters are lower cased, the replacement is case-
299
+     * insensitive.
300
+     *
301
+     * The configHandlerLoader should just instantiate the handler on demand.
302
+     * For now all handlers are instantiated when a mount is loaded, independent
303
+     * of whether the placeholder is present or not. This may change in future.
304
+     *
305
+     * @since 16.0.0
306
+     */
307
+    public function registerConfigHandler(string $placeholder, callable $configHandlerLoader) {
308
+        $placeholder = trim(strtolower($placeholder));
309
+        if(!(bool)\preg_match('/^[a-z0-9]*$/', $placeholder)) {
310
+            throw new \RuntimeException(sprintf(
311
+                'Invalid placeholder %s, only [a-z0-9] are allowed', $placeholder
312
+            ));
313
+        }
314
+        if($placeholder === '') {
315
+            throw new \RuntimeException('Invalid empty placeholder');
316
+        }
317
+        if(isset($this->configHandlerLoaders[$placeholder]) || isset($this->configHandlers[$placeholder])) {
318
+            throw new \RuntimeException(sprintf('A handler is already registered for %s', $placeholder));
319
+        }
320
+        $this->configHandlerLoaders[$placeholder] = $configHandlerLoader;
321
+    }
322
+
323
+    protected function loadConfigHandlers():void {
324
+        $newLoaded = false;
325
+        foreach ($this->configHandlerLoaders as $placeholder => $loader) {
326
+            $handler = $loader();
327
+            if(!$handler instanceof IConfigHandler) {
328
+                throw new \RuntimeException(sprintf(
329
+                    'Handler for %s is not an instance of IConfigHandler', $placeholder
330
+                ));
331
+            }
332
+            $this->configHandlers[$placeholder] = $handler;
333
+            $newLoaded = true;
334
+        }
335
+        $this->configHandlerLoaders = [];
336
+        if($newLoaded) {
337
+            // ensure those with longest placeholders come first,
338
+            // to avoid substring matches
339
+            uksort($this->configHandlers, function ($phA, $phB) {
340
+                return strlen($phB) <=> strlen($phA);
341
+            });
342
+        }
343
+    }
344
+
345
+    /**
346
+     * @since 16.0.0
347
+     */
348
+    public function getConfigHandlers() {
349
+        $this->loadConfigHandlers();
350
+        return $this->configHandlers;
351
+    }
352 352
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -306,15 +306,15 @@  discard block
 block discarded – undo
306 306
 	 */
307 307
 	public function registerConfigHandler(string $placeholder, callable $configHandlerLoader) {
308 308
 		$placeholder = trim(strtolower($placeholder));
309
-		if(!(bool)\preg_match('/^[a-z0-9]*$/', $placeholder)) {
309
+		if (!(bool) \preg_match('/^[a-z0-9]*$/', $placeholder)) {
310 310
 			throw new \RuntimeException(sprintf(
311 311
 				'Invalid placeholder %s, only [a-z0-9] are allowed', $placeholder
312 312
 			));
313 313
 		}
314
-		if($placeholder === '') {
314
+		if ($placeholder === '') {
315 315
 			throw new \RuntimeException('Invalid empty placeholder');
316 316
 		}
317
-		if(isset($this->configHandlerLoaders[$placeholder]) || isset($this->configHandlers[$placeholder])) {
317
+		if (isset($this->configHandlerLoaders[$placeholder]) || isset($this->configHandlers[$placeholder])) {
318 318
 			throw new \RuntimeException(sprintf('A handler is already registered for %s', $placeholder));
319 319
 		}
320 320
 		$this->configHandlerLoaders[$placeholder] = $configHandlerLoader;
@@ -324,7 +324,7 @@  discard block
 block discarded – undo
324 324
 		$newLoaded = false;
325 325
 		foreach ($this->configHandlerLoaders as $placeholder => $loader) {
326 326
 			$handler = $loader();
327
-			if(!$handler instanceof IConfigHandler) {
327
+			if (!$handler instanceof IConfigHandler) {
328 328
 				throw new \RuntimeException(sprintf(
329 329
 					'Handler for %s is not an instance of IConfigHandler', $placeholder
330 330
 				));
@@ -333,10 +333,10 @@  discard block
 block discarded – undo
333 333
 			$newLoaded = true;
334 334
 		}
335 335
 		$this->configHandlerLoaders = [];
336
-		if($newLoaded) {
336
+		if ($newLoaded) {
337 337
 			// ensure those with longest placeholders come first,
338 338
 			// to avoid substring matches
339
-			uksort($this->configHandlers, function ($phA, $phB) {
339
+			uksort($this->configHandlers, function($phA, $phB) {
340 340
 				return strlen($phB) <=> strlen($phA);
341 341
 			});
342 342
 		}
Please login to merge, or discard this patch.
apps/files_external/lib/Config/SimpleSubstitutionTrait.php 2 patches
Indentation   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -30,57 +30,57 @@
 block discarded – undo
30 30
  * @since 16.0.0
31 31
  */
32 32
 trait SimpleSubstitutionTrait {
33
-	/**
34
-	 * @var string the placeholder without $ prefix
35
-	 * @since 16.0.0
36
-	 */
37
-	private $placeholder;
33
+    /**
34
+     * @var string the placeholder without $ prefix
35
+     * @since 16.0.0
36
+     */
37
+    private $placeholder;
38 38
 
39
-	/** @var string */
40
-	protected $sanitizedPlaceholder;
39
+    /** @var string */
40
+    protected $sanitizedPlaceholder;
41 41
 
42
-	/**
43
-	 * @param mixed $optionValue
44
-	 * @param string $replacement
45
-	 * @return mixed
46
-	 * @since 16.0.0
47
-	 */
48
-	private function processInput($optionValue, string $replacement) {
49
-		$this->checkPlaceholder();
50
-		if (is_array($optionValue)) {
51
-			foreach ($optionValue as &$value) {
52
-				$value = $this->substituteIfString($value, $replacement);
53
-			}
54
-		} else {
55
-			$optionValue = $this->substituteIfString($optionValue, $replacement);
56
-		}
57
-		return $optionValue;
58
-	}
42
+    /**
43
+     * @param mixed $optionValue
44
+     * @param string $replacement
45
+     * @return mixed
46
+     * @since 16.0.0
47
+     */
48
+    private function processInput($optionValue, string $replacement) {
49
+        $this->checkPlaceholder();
50
+        if (is_array($optionValue)) {
51
+            foreach ($optionValue as &$value) {
52
+                $value = $this->substituteIfString($value, $replacement);
53
+            }
54
+        } else {
55
+            $optionValue = $this->substituteIfString($optionValue, $replacement);
56
+        }
57
+        return $optionValue;
58
+    }
59 59
 
60
-	/**
61
-	 * @throws \RuntimeException
62
-	 */
63
-	protected function checkPlaceholder(): void {
64
-		$this->sanitizedPlaceholder = trim(strtolower($this->placeholder));
65
-		if(!(bool)\preg_match('/^[a-z0-9]*$/', $this->sanitizedPlaceholder)) {
66
-			throw new \RuntimeException(sprintf(
67
-				'Invalid placeholder %s, only [a-z0-9] are allowed', $this->sanitizedPlaceholder
68
-			));
69
-		}
70
-		if($this->sanitizedPlaceholder === '') {
71
-			throw new \RuntimeException('Invalid empty placeholder');
72
-		}
73
-	}
60
+    /**
61
+     * @throws \RuntimeException
62
+     */
63
+    protected function checkPlaceholder(): void {
64
+        $this->sanitizedPlaceholder = trim(strtolower($this->placeholder));
65
+        if(!(bool)\preg_match('/^[a-z0-9]*$/', $this->sanitizedPlaceholder)) {
66
+            throw new \RuntimeException(sprintf(
67
+                'Invalid placeholder %s, only [a-z0-9] are allowed', $this->sanitizedPlaceholder
68
+            ));
69
+        }
70
+        if($this->sanitizedPlaceholder === '') {
71
+            throw new \RuntimeException('Invalid empty placeholder');
72
+        }
73
+    }
74 74
 
75
-	/**
76
-	 * @param mixed $value
77
-	 * @param string $replacement
78
-	 * @return mixed
79
-	 */
80
-	protected function substituteIfString($value, string $replacement) {
81
-		if(is_string($value)) {
82
-			return str_ireplace('$' . $this->sanitizedPlaceholder, $replacement, $value);
83
-		}
84
-		return $value;
85
-	}
75
+    /**
76
+     * @param mixed $value
77
+     * @param string $replacement
78
+     * @return mixed
79
+     */
80
+    protected function substituteIfString($value, string $replacement) {
81
+        if(is_string($value)) {
82
+            return str_ireplace('$' . $this->sanitizedPlaceholder, $replacement, $value);
83
+        }
84
+        return $value;
85
+    }
86 86
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -62,12 +62,12 @@  discard block
 block discarded – undo
62 62
 	 */
63 63
 	protected function checkPlaceholder(): void {
64 64
 		$this->sanitizedPlaceholder = trim(strtolower($this->placeholder));
65
-		if(!(bool)\preg_match('/^[a-z0-9]*$/', $this->sanitizedPlaceholder)) {
65
+		if (!(bool) \preg_match('/^[a-z0-9]*$/', $this->sanitizedPlaceholder)) {
66 66
 			throw new \RuntimeException(sprintf(
67 67
 				'Invalid placeholder %s, only [a-z0-9] are allowed', $this->sanitizedPlaceholder
68 68
 			));
69 69
 		}
70
-		if($this->sanitizedPlaceholder === '') {
70
+		if ($this->sanitizedPlaceholder === '') {
71 71
 			throw new \RuntimeException('Invalid empty placeholder');
72 72
 		}
73 73
 	}
@@ -78,8 +78,8 @@  discard block
 block discarded – undo
78 78
 	 * @return mixed
79 79
 	 */
80 80
 	protected function substituteIfString($value, string $replacement) {
81
-		if(is_string($value)) {
82
-			return str_ireplace('$' . $this->sanitizedPlaceholder, $replacement, $value);
81
+		if (is_string($value)) {
82
+			return str_ireplace('$'.$this->sanitizedPlaceholder, $replacement, $value);
83 83
 		}
84 84
 		return $value;
85 85
 	}
Please login to merge, or discard this patch.
apps/files_external/lib/Config/IConfigHandler.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -30,10 +30,10 @@
 block discarded – undo
30 30
  * @since 16.0.0
31 31
  */
32 32
 interface IConfigHandler {
33
-	/**
34
-	 * @param mixed $optionValue
35
-	 * @return mixed the same type as $optionValue
36
-	 * @since 16.0.0
37
-	 */
38
-	public function handle($optionValue);
33
+    /**
34
+     * @param mixed $optionValue
35
+     * @return mixed the same type as $optionValue
36
+     * @since 16.0.0
37
+     */
38
+    public function handle($optionValue);
39 39
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Config/ConfigAdapter.php 1 patch
Indentation   +138 added lines, -138 removed lines patch added patch discarded remove patch
@@ -44,142 +44,142 @@
 block discarded – undo
44 44
  */
45 45
 class ConfigAdapter implements IMountProvider {
46 46
 
47
-	/** @var UserStoragesService */
48
-	private $userStoragesService;
49
-
50
-	/** @var UserGlobalStoragesService */
51
-	private $userGlobalStoragesService;
52
-	/** @var StorageMigrator  */
53
-	private $migrator;
54
-
55
-	/**
56
-	 * @param UserStoragesService $userStoragesService
57
-	 * @param UserGlobalStoragesService $userGlobalStoragesService
58
-	 * @param StorageMigrator $migrator
59
-	 */
60
-	public function __construct(
61
-		UserStoragesService $userStoragesService,
62
-		UserGlobalStoragesService $userGlobalStoragesService,
63
-		StorageMigrator $migrator
64
-	) {
65
-		$this->userStoragesService = $userStoragesService;
66
-		$this->userGlobalStoragesService = $userGlobalStoragesService;
67
-		$this->migrator = $migrator;
68
-	}
69
-
70
-	/**
71
-	 * Process storage ready for mounting
72
-	 *
73
-	 * @param StorageConfig $storage
74
-	 * @param IUser $user
75
-	 * @throws \OCP\AppFramework\QueryException
76
-	 */
77
-	private function prepareStorageConfig(StorageConfig &$storage, IUser $user) {
78
-		foreach ($storage->getBackendOptions() as $option => $value) {
79
-			$storage->setBackendOption($option, \OC_Mount_Config::substitutePlaceholdersInConfig($value));
80
-		}
81
-
82
-		$objectStore = $storage->getBackendOption('objectstore');
83
-		if ($objectStore) {
84
-			$objectClass = $objectStore['class'];
85
-			if (!is_subclass_of($objectClass, '\OCP\Files\ObjectStore\IObjectStore')) {
86
-				throw new \InvalidArgumentException('Invalid object store');
87
-			}
88
-			$storage->setBackendOption('objectstore', new $objectClass($objectStore));
89
-		}
90
-
91
-		$storage->getAuthMechanism()->manipulateStorageConfig($storage, $user);
92
-		$storage->getBackend()->manipulateStorageConfig($storage, $user);
93
-	}
94
-
95
-	/**
96
-	 * Construct the storage implementation
97
-	 *
98
-	 * @param StorageConfig $storageConfig
99
-	 * @return Storage
100
-	 */
101
-	private function constructStorage(StorageConfig $storageConfig) {
102
-		$class = $storageConfig->getBackend()->getStorageClass();
103
-		$storage = new $class($storageConfig->getBackendOptions());
104
-
105
-		// auth mechanism should fire first
106
-		$storage = $storageConfig->getBackend()->wrapStorage($storage);
107
-		$storage = $storageConfig->getAuthMechanism()->wrapStorage($storage);
108
-
109
-		return $storage;
110
-	}
111
-
112
-	/**
113
-	 * Get all mountpoints applicable for the user
114
-	 *
115
-	 * @param \OCP\IUser $user
116
-	 * @param \OCP\Files\Storage\IStorageFactory $loader
117
-	 * @return \OCP\Files\Mount\IMountPoint[]
118
-	 */
119
-	public function getMountsForUser(IUser $user, IStorageFactory $loader) {
120
-		$this->migrator->migrateUser($user);
121
-
122
-		$this->userStoragesService->setUser($user);
123
-		$this->userGlobalStoragesService->setUser($user);
124
-
125
-		$storageConfigs = $this->userGlobalStoragesService->getAllStoragesForUser();
126
-
127
-		$storages = array_map(function(StorageConfig $storageConfig) use ($user) {
128
-			try {
129
-				$this->prepareStorageConfig($storageConfig, $user);
130
-				return $this->constructStorage($storageConfig);
131
-			} catch (\Exception $e) {
132
-				// propagate exception into filesystem
133
-				return new FailedStorage(['exception' => $e]);
134
-			}
135
-		}, $storageConfigs);
136
-
137
-
138
-		\OC\Files\Cache\Storage::getGlobalCache()->loadForStorageIds(array_map(function(Storage\IStorage $storage) {
139
-			return $storage->getId();
140
-		}, $storages));
141
-
142
-		$availableStorages = array_map(function (Storage\IStorage $storage, StorageConfig $storageConfig) {
143
-			try {
144
-				$availability = $storage->getAvailability();
145
-				if (!$availability['available'] && !Availability::shouldRecheck($availability)) {
146
-					$storage = new FailedStorage([
147
-						'exception' => new StorageNotAvailableException('Storage with mount id ' . $storageConfig->getId() . ' is not available')
148
-					]);
149
-				}
150
-			} catch (\Exception $e) {
151
-				// propagate exception into filesystem
152
-				$storage = new FailedStorage(['exception' => $e]);
153
-			}
154
-			return $storage;
155
-		}, $storages, $storageConfigs);
156
-
157
-		$mounts = array_map(function(StorageConfig $storageConfig, Storage\IStorage $storage) use ($user, $loader) {
158
-			if ($storageConfig->getType() === StorageConfig::MOUNT_TYPE_PERSONAl) {
159
-				return new PersonalMount(
160
-					$this->userStoragesService,
161
-					$storageConfig->getId(),
162
-					$storage,
163
-					'/' . $user->getUID() . '/files' . $storageConfig->getMountPoint(),
164
-					null,
165
-					$loader,
166
-					$storageConfig->getMountOptions()
167
-				);
168
-			} else {
169
-				return new ExternalMountPoint(
170
-					$storage,
171
-					'/' . $user->getUID() . '/files' . $storageConfig->getMountPoint(),
172
-					null,
173
-					$loader,
174
-					$storageConfig->getMountOptions(),
175
-					$storageConfig->getId()
176
-				);
177
-			}
178
-		}, $storageConfigs, $availableStorages);
179
-
180
-		$this->userStoragesService->resetUser();
181
-		$this->userGlobalStoragesService->resetUser();
182
-
183
-		return $mounts;
184
-	}
47
+    /** @var UserStoragesService */
48
+    private $userStoragesService;
49
+
50
+    /** @var UserGlobalStoragesService */
51
+    private $userGlobalStoragesService;
52
+    /** @var StorageMigrator  */
53
+    private $migrator;
54
+
55
+    /**
56
+     * @param UserStoragesService $userStoragesService
57
+     * @param UserGlobalStoragesService $userGlobalStoragesService
58
+     * @param StorageMigrator $migrator
59
+     */
60
+    public function __construct(
61
+        UserStoragesService $userStoragesService,
62
+        UserGlobalStoragesService $userGlobalStoragesService,
63
+        StorageMigrator $migrator
64
+    ) {
65
+        $this->userStoragesService = $userStoragesService;
66
+        $this->userGlobalStoragesService = $userGlobalStoragesService;
67
+        $this->migrator = $migrator;
68
+    }
69
+
70
+    /**
71
+     * Process storage ready for mounting
72
+     *
73
+     * @param StorageConfig $storage
74
+     * @param IUser $user
75
+     * @throws \OCP\AppFramework\QueryException
76
+     */
77
+    private function prepareStorageConfig(StorageConfig &$storage, IUser $user) {
78
+        foreach ($storage->getBackendOptions() as $option => $value) {
79
+            $storage->setBackendOption($option, \OC_Mount_Config::substitutePlaceholdersInConfig($value));
80
+        }
81
+
82
+        $objectStore = $storage->getBackendOption('objectstore');
83
+        if ($objectStore) {
84
+            $objectClass = $objectStore['class'];
85
+            if (!is_subclass_of($objectClass, '\OCP\Files\ObjectStore\IObjectStore')) {
86
+                throw new \InvalidArgumentException('Invalid object store');
87
+            }
88
+            $storage->setBackendOption('objectstore', new $objectClass($objectStore));
89
+        }
90
+
91
+        $storage->getAuthMechanism()->manipulateStorageConfig($storage, $user);
92
+        $storage->getBackend()->manipulateStorageConfig($storage, $user);
93
+    }
94
+
95
+    /**
96
+     * Construct the storage implementation
97
+     *
98
+     * @param StorageConfig $storageConfig
99
+     * @return Storage
100
+     */
101
+    private function constructStorage(StorageConfig $storageConfig) {
102
+        $class = $storageConfig->getBackend()->getStorageClass();
103
+        $storage = new $class($storageConfig->getBackendOptions());
104
+
105
+        // auth mechanism should fire first
106
+        $storage = $storageConfig->getBackend()->wrapStorage($storage);
107
+        $storage = $storageConfig->getAuthMechanism()->wrapStorage($storage);
108
+
109
+        return $storage;
110
+    }
111
+
112
+    /**
113
+     * Get all mountpoints applicable for the user
114
+     *
115
+     * @param \OCP\IUser $user
116
+     * @param \OCP\Files\Storage\IStorageFactory $loader
117
+     * @return \OCP\Files\Mount\IMountPoint[]
118
+     */
119
+    public function getMountsForUser(IUser $user, IStorageFactory $loader) {
120
+        $this->migrator->migrateUser($user);
121
+
122
+        $this->userStoragesService->setUser($user);
123
+        $this->userGlobalStoragesService->setUser($user);
124
+
125
+        $storageConfigs = $this->userGlobalStoragesService->getAllStoragesForUser();
126
+
127
+        $storages = array_map(function(StorageConfig $storageConfig) use ($user) {
128
+            try {
129
+                $this->prepareStorageConfig($storageConfig, $user);
130
+                return $this->constructStorage($storageConfig);
131
+            } catch (\Exception $e) {
132
+                // propagate exception into filesystem
133
+                return new FailedStorage(['exception' => $e]);
134
+            }
135
+        }, $storageConfigs);
136
+
137
+
138
+        \OC\Files\Cache\Storage::getGlobalCache()->loadForStorageIds(array_map(function(Storage\IStorage $storage) {
139
+            return $storage->getId();
140
+        }, $storages));
141
+
142
+        $availableStorages = array_map(function (Storage\IStorage $storage, StorageConfig $storageConfig) {
143
+            try {
144
+                $availability = $storage->getAvailability();
145
+                if (!$availability['available'] && !Availability::shouldRecheck($availability)) {
146
+                    $storage = new FailedStorage([
147
+                        'exception' => new StorageNotAvailableException('Storage with mount id ' . $storageConfig->getId() . ' is not available')
148
+                    ]);
149
+                }
150
+            } catch (\Exception $e) {
151
+                // propagate exception into filesystem
152
+                $storage = new FailedStorage(['exception' => $e]);
153
+            }
154
+            return $storage;
155
+        }, $storages, $storageConfigs);
156
+
157
+        $mounts = array_map(function(StorageConfig $storageConfig, Storage\IStorage $storage) use ($user, $loader) {
158
+            if ($storageConfig->getType() === StorageConfig::MOUNT_TYPE_PERSONAl) {
159
+                return new PersonalMount(
160
+                    $this->userStoragesService,
161
+                    $storageConfig->getId(),
162
+                    $storage,
163
+                    '/' . $user->getUID() . '/files' . $storageConfig->getMountPoint(),
164
+                    null,
165
+                    $loader,
166
+                    $storageConfig->getMountOptions()
167
+                );
168
+            } else {
169
+                return new ExternalMountPoint(
170
+                    $storage,
171
+                    '/' . $user->getUID() . '/files' . $storageConfig->getMountPoint(),
172
+                    null,
173
+                    $loader,
174
+                    $storageConfig->getMountOptions(),
175
+                    $storageConfig->getId()
176
+                );
177
+            }
178
+        }, $storageConfigs, $availableStorages);
179
+
180
+        $this->userStoragesService->resetUser();
181
+        $this->userGlobalStoragesService->resetUser();
182
+
183
+        return $mounts;
184
+    }
185 185
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Config/UserPlaceholderHandler.php 2 patches
Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -26,28 +26,28 @@
 block discarded – undo
26 26
 use OCP\IUserSession;
27 27
 
28 28
 class UserPlaceholderHandler implements IConfigHandler {
29
-	use SimpleSubstitutionTrait;
29
+    use SimpleSubstitutionTrait;
30 30
 
31
-	/** @var IUserSession */
32
-	private $session;
31
+    /** @var IUserSession */
32
+    private $session;
33 33
 
34
-	public function __construct(IUserSession $session) {
35
-		$this->session = $session;
36
-		$this->placeholder = 'user';
37
-	}
34
+    public function __construct(IUserSession $session) {
35
+        $this->session = $session;
36
+        $this->placeholder = 'user';
37
+    }
38 38
 
39
-	/**
40
-	 * @param mixed $optionValue
41
-	 * @return mixed the same type as $optionValue
42
-	 * @since 16.0.0
43
-	 */
44
-	public function handle($optionValue) {
45
-		$user = $this->session->getUser();
46
-		if($user === null) {
47
-			return $optionValue;
48
-		}
49
-		$uid = $user->getUID();
39
+    /**
40
+     * @param mixed $optionValue
41
+     * @return mixed the same type as $optionValue
42
+     * @since 16.0.0
43
+     */
44
+    public function handle($optionValue) {
45
+        $user = $this->session->getUser();
46
+        if($user === null) {
47
+            return $optionValue;
48
+        }
49
+        $uid = $user->getUID();
50 50
 
51
-		return $this->processInput($optionValue, $uid);
52
-	}
51
+        return $this->processInput($optionValue, $uid);
52
+    }
53 53
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -43,7 +43,7 @@
 block discarded – undo
43 43
 	 */
44 44
 	public function handle($optionValue) {
45 45
 		$user = $this->session->getUser();
46
-		if($user === null) {
46
+		if ($user === null) {
47 47
 			return $optionValue;
48 48
 		}
49 49
 		$uid = $user->getUID();
Please login to merge, or discard this patch.
apps/user_ldap/lib/User/User.php 2 patches
Indentation   +704 added lines, -704 removed lines patch added patch discarded remove patch
@@ -49,714 +49,714 @@
 block discarded – undo
49 49
  * represents an LDAP user, gets and holds user-specific information from LDAP
50 50
  */
51 51
 class User {
52
-	/**
53
-	 * @var Access
54
-	 */
55
-	protected $access;
56
-	/**
57
-	 * @var Connection
58
-	 */
59
-	protected $connection;
60
-	/**
61
-	 * @var IConfig
62
-	 */
63
-	protected $config;
64
-	/**
65
-	 * @var FilesystemHelper
66
-	 */
67
-	protected $fs;
68
-	/**
69
-	 * @var Image
70
-	 */
71
-	protected $image;
72
-	/**
73
-	 * @var LogWrapper
74
-	 */
75
-	protected $log;
76
-	/**
77
-	 * @var IAvatarManager
78
-	 */
79
-	protected $avatarManager;
80
-	/**
81
-	 * @var IUserManager
82
-	 */
83
-	protected $userManager;
84
-	/**
85
-	 * @var INotificationManager
86
-	 */
87
-	protected $notificationManager;
88
-	/**
89
-	 * @var string
90
-	 */
91
-	protected $dn;
92
-	/**
93
-	 * @var string
94
-	 */
95
-	protected $uid;
96
-	/**
97
-	 * @var string[]
98
-	 */
99
-	protected $refreshedFeatures = array();
100
-	/**
101
-	 * @var string
102
-	 */
103
-	protected $avatarImage;
104
-
105
-	/**
106
-	 * DB config keys for user preferences
107
-	 */
108
-	const USER_PREFKEY_FIRSTLOGIN  = 'firstLoginAccomplished';
109
-	const USER_PREFKEY_LASTREFRESH = 'lastFeatureRefresh';
110
-
111
-	/**
112
-	 * @brief constructor, make sure the subclasses call this one!
113
-	 * @param string $username the internal username
114
-	 * @param string $dn the LDAP DN
115
-	 * @param Access $access
116
-	 * @param IConfig $config
117
-	 * @param FilesystemHelper $fs
118
-	 * @param Image $image any empty instance
119
-	 * @param LogWrapper $log
120
-	 * @param IAvatarManager $avatarManager
121
-	 * @param IUserManager $userManager
122
-	 * @param INotificationManager $notificationManager
123
-	 */
124
-	public function __construct($username, $dn, Access $access,
125
-		IConfig $config, FilesystemHelper $fs, Image $image,
126
-		LogWrapper $log, IAvatarManager $avatarManager, IUserManager $userManager,
127
-		INotificationManager $notificationManager) {
52
+    /**
53
+     * @var Access
54
+     */
55
+    protected $access;
56
+    /**
57
+     * @var Connection
58
+     */
59
+    protected $connection;
60
+    /**
61
+     * @var IConfig
62
+     */
63
+    protected $config;
64
+    /**
65
+     * @var FilesystemHelper
66
+     */
67
+    protected $fs;
68
+    /**
69
+     * @var Image
70
+     */
71
+    protected $image;
72
+    /**
73
+     * @var LogWrapper
74
+     */
75
+    protected $log;
76
+    /**
77
+     * @var IAvatarManager
78
+     */
79
+    protected $avatarManager;
80
+    /**
81
+     * @var IUserManager
82
+     */
83
+    protected $userManager;
84
+    /**
85
+     * @var INotificationManager
86
+     */
87
+    protected $notificationManager;
88
+    /**
89
+     * @var string
90
+     */
91
+    protected $dn;
92
+    /**
93
+     * @var string
94
+     */
95
+    protected $uid;
96
+    /**
97
+     * @var string[]
98
+     */
99
+    protected $refreshedFeatures = array();
100
+    /**
101
+     * @var string
102
+     */
103
+    protected $avatarImage;
104
+
105
+    /**
106
+     * DB config keys for user preferences
107
+     */
108
+    const USER_PREFKEY_FIRSTLOGIN  = 'firstLoginAccomplished';
109
+    const USER_PREFKEY_LASTREFRESH = 'lastFeatureRefresh';
110
+
111
+    /**
112
+     * @brief constructor, make sure the subclasses call this one!
113
+     * @param string $username the internal username
114
+     * @param string $dn the LDAP DN
115
+     * @param Access $access
116
+     * @param IConfig $config
117
+     * @param FilesystemHelper $fs
118
+     * @param Image $image any empty instance
119
+     * @param LogWrapper $log
120
+     * @param IAvatarManager $avatarManager
121
+     * @param IUserManager $userManager
122
+     * @param INotificationManager $notificationManager
123
+     */
124
+    public function __construct($username, $dn, Access $access,
125
+        IConfig $config, FilesystemHelper $fs, Image $image,
126
+        LogWrapper $log, IAvatarManager $avatarManager, IUserManager $userManager,
127
+        INotificationManager $notificationManager) {
128 128
 	
129
-		if ($username === null) {
130
-			$log->log("uid for '$dn' must not be null!", ILogger::ERROR);
131
-			throw new \InvalidArgumentException('uid must not be null!');
132
-		} else if ($username === '') {
133
-			$log->log("uid for '$dn' must not be an empty string", ILogger::ERROR);
134
-			throw new \InvalidArgumentException('uid must not be an empty string!');
135
-		}
136
-
137
-		$this->access              = $access;
138
-		$this->connection          = $access->getConnection();
139
-		$this->config              = $config;
140
-		$this->fs                  = $fs;
141
-		$this->dn                  = $dn;
142
-		$this->uid                 = $username;
143
-		$this->image               = $image;
144
-		$this->log                 = $log;
145
-		$this->avatarManager       = $avatarManager;
146
-		$this->userManager         = $userManager;
147
-		$this->notificationManager = $notificationManager;
148
-
149
-		\OCP\Util::connectHook('OC_User', 'post_login', $this, 'handlePasswordExpiry');
150
-	}
151
-
152
-	/**
153
-	 * @brief updates properties like email, quota or avatar provided by LDAP
154
-	 * @return null
155
-	 */
156
-	public function update() {
157
-		if(is_null($this->dn)) {
158
-			return null;
159
-		}
160
-
161
-		$hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap',
162
-				self::USER_PREFKEY_FIRSTLOGIN, 0);
163
-
164
-		if($this->needsRefresh()) {
165
-			$this->updateEmail();
166
-			$this->updateQuota();
167
-			if($hasLoggedIn !== 0) {
168
-				//we do not need to try it, when the user has not been logged in
169
-				//before, because the file system will not be ready.
170
-				$this->updateAvatar();
171
-				//in order to get an avatar as soon as possible, mark the user
172
-				//as refreshed only when updating the avatar did happen
173
-				$this->markRefreshTime();
174
-			}
175
-		}
176
-	}
177
-
178
-	/**
179
-	 * processes results from LDAP for attributes as returned by getAttributesToRead()
180
-	 * @param array $ldapEntry the user entry as retrieved from LDAP
181
-	 */
182
-	public function processAttributes($ldapEntry) {
183
-		$this->markRefreshTime();
184
-		//Quota
185
-		$attr = strtolower($this->connection->ldapQuotaAttribute);
186
-		if(isset($ldapEntry[$attr])) {
187
-			$this->updateQuota($ldapEntry[$attr][0]);
188
-		} else {
189
-			if ($this->connection->ldapQuotaDefault !== '') {
190
-				$this->updateQuota();
191
-			}
192
-		}
193
-		unset($attr);
194
-
195
-		//displayName
196
-		$displayName = $displayName2 = '';
197
-		$attr = strtolower($this->connection->ldapUserDisplayName);
198
-		if(isset($ldapEntry[$attr])) {
199
-			$displayName = (string)$ldapEntry[$attr][0];
200
-		}
201
-		$attr = strtolower($this->connection->ldapUserDisplayName2);
202
-		if(isset($ldapEntry[$attr])) {
203
-			$displayName2 = (string)$ldapEntry[$attr][0];
204
-		}
205
-		if ($displayName !== '') {
206
-			$this->composeAndStoreDisplayName($displayName, $displayName2);
207
-			$this->access->cacheUserDisplayName(
208
-				$this->getUsername(),
209
-				$displayName,
210
-				$displayName2
211
-			);
212
-		}
213
-		unset($attr);
214
-
215
-		//Email
216
-		//email must be stored after displayname, because it would cause a user
217
-		//change event that will trigger fetching the display name again
218
-		$attr = strtolower($this->connection->ldapEmailAttribute);
219
-		if(isset($ldapEntry[$attr])) {
220
-			$this->updateEmail($ldapEntry[$attr][0]);
221
-		}
222
-		unset($attr);
223
-
224
-		// LDAP Username, needed for s2s sharing
225
-		if(isset($ldapEntry['uid'])) {
226
-			$this->storeLDAPUserName($ldapEntry['uid'][0]);
227
-		} else if(isset($ldapEntry['samaccountname'])) {
228
-			$this->storeLDAPUserName($ldapEntry['samaccountname'][0]);
229
-		}
230
-
231
-		//homePath
232
-		if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
233
-			$attr = strtolower(substr($this->connection->homeFolderNamingRule, strlen('attr:')));
234
-			if(isset($ldapEntry[$attr])) {
235
-				$this->access->cacheUserHome(
236
-					$this->getUsername(), $this->getHomePath($ldapEntry[$attr][0]));
237
-			}
238
-		}
239
-
240
-		//memberOf groups
241
-		$cacheKey = 'getMemberOf'.$this->getUsername();
242
-		$groups = false;
243
-		if(isset($ldapEntry['memberof'])) {
244
-			$groups = $ldapEntry['memberof'];
245
-		}
246
-		$this->connection->writeToCache($cacheKey, $groups);
247
-
248
-		//external storage var
249
-		$attr = strtolower($this->connection->ldapExtStorageHomeAttribute);
250
-		if(isset($ldapEntry[$attr])) {
251
-			$this->updateExtStorageHome($ldapEntry[$attr][0]);
252
-		}
253
-		unset($attr);
254
-
255
-		//Avatar
256
-		/** @var Connection $connection */
257
-		$connection = $this->access->getConnection();
258
-		$attributes = $connection->resolveRule('avatar');
259
-		foreach ($attributes as $attribute)  {
260
-			if(isset($ldapEntry[$attribute])) {
261
-				$this->avatarImage = $ldapEntry[$attribute][0];
262
-				// the call to the method that saves the avatar in the file
263
-				// system must be postponed after the login. It is to ensure
264
-				// external mounts are mounted properly (e.g. with login
265
-				// credentials from the session).
266
-				\OCP\Util::connectHook('OC_User', 'post_login', $this, 'updateAvatarPostLogin');
267
-				break;
268
-			}
269
-		}
270
-	}
271
-
272
-	/**
273
-	 * @brief returns the LDAP DN of the user
274
-	 * @return string
275
-	 */
276
-	public function getDN() {
277
-		return $this->dn;
278
-	}
279
-
280
-	/**
281
-	 * @brief returns the Nextcloud internal username of the user
282
-	 * @return string
283
-	 */
284
-	public function getUsername() {
285
-		return $this->uid;
286
-	}
287
-
288
-	/**
289
-	 * returns the home directory of the user if specified by LDAP settings
290
-	 * @param string $valueFromLDAP
291
-	 * @return bool|string
292
-	 * @throws \Exception
293
-	 */
294
-	public function getHomePath($valueFromLDAP = null) {
295
-		$path = (string)$valueFromLDAP;
296
-		$attr = null;
297
-
298
-		if (is_null($valueFromLDAP)
299
-		   && strpos($this->access->connection->homeFolderNamingRule, 'attr:') === 0
300
-		   && $this->access->connection->homeFolderNamingRule !== 'attr:')
301
-		{
302
-			$attr = substr($this->access->connection->homeFolderNamingRule, strlen('attr:'));
303
-			$homedir = $this->access->readAttribute(
304
-				$this->access->username2dn($this->getUsername()), $attr);
305
-			if ($homedir && isset($homedir[0])) {
306
-				$path = $homedir[0];
307
-			}
308
-		}
309
-
310
-		if ($path !== '') {
311
-			//if attribute's value is an absolute path take this, otherwise append it to data dir
312
-			//check for / at the beginning or pattern c:\ resp. c:/
313
-			if(   '/' !== $path[0]
314
-			   && !(3 < strlen($path) && ctype_alpha($path[0])
315
-			       && $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))
316
-			) {
317
-				$path = $this->config->getSystemValue('datadirectory',
318
-						\OC::$SERVERROOT.'/data' ) . '/' . $path;
319
-			}
320
-			//we need it to store it in the DB as well in case a user gets
321
-			//deleted so we can clean up afterwards
322
-			$this->config->setUserValue(
323
-				$this->getUsername(), 'user_ldap', 'homePath', $path
324
-			);
325
-			return $path;
326
-		}
327
-
328
-		if(    !is_null($attr)
329
-			&& $this->config->getAppValue('user_ldap', 'enforce_home_folder_naming_rule', true)
330
-		) {
331
-			// a naming rule attribute is defined, but it doesn't exist for that LDAP user
332
-			throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: ' . $this->getUsername());
333
-		}
334
-
335
-		//false will apply default behaviour as defined and done by OC_User
336
-		$this->config->setUserValue($this->getUsername(), 'user_ldap', 'homePath', '');
337
-		return false;
338
-	}
339
-
340
-	public function getMemberOfGroups() {
341
-		$cacheKey = 'getMemberOf'.$this->getUsername();
342
-		$memberOfGroups = $this->connection->getFromCache($cacheKey);
343
-		if(!is_null($memberOfGroups)) {
344
-			return $memberOfGroups;
345
-		}
346
-		$groupDNs = $this->access->readAttribute($this->getDN(), 'memberOf');
347
-		$this->connection->writeToCache($cacheKey, $groupDNs);
348
-		return $groupDNs;
349
-	}
350
-
351
-	/**
352
-	 * @brief reads the image from LDAP that shall be used as Avatar
353
-	 * @return string data (provided by LDAP) | false
354
-	 */
355
-	public function getAvatarImage() {
356
-		if(!is_null($this->avatarImage)) {
357
-			return $this->avatarImage;
358
-		}
359
-
360
-		$this->avatarImage = false;
361
-		/** @var Connection $connection */
362
-		$connection = $this->access->getConnection();
363
-		$attributes = $connection->resolveRule('avatar');
364
-		foreach($attributes as $attribute) {
365
-			$result = $this->access->readAttribute($this->dn, $attribute);
366
-			if($result !== false && is_array($result) && isset($result[0])) {
367
-				$this->avatarImage = $result[0];
368
-				break;
369
-			}
370
-		}
371
-
372
-		return $this->avatarImage;
373
-	}
374
-
375
-	/**
376
-	 * @brief marks the user as having logged in at least once
377
-	 * @return null
378
-	 */
379
-	public function markLogin() {
380
-		$this->config->setUserValue(
381
-			$this->uid, 'user_ldap', self::USER_PREFKEY_FIRSTLOGIN, 1);
382
-	}
383
-
384
-	/**
385
-	 * @brief marks the time when user features like email have been updated
386
-	 * @return null
387
-	 */
388
-	public function markRefreshTime() {
389
-		$this->config->setUserValue(
390
-			$this->uid, 'user_ldap', self::USER_PREFKEY_LASTREFRESH, time());
391
-	}
392
-
393
-	/**
394
-	 * @brief checks whether user features needs to be updated again by
395
-	 * comparing the difference of time of the last refresh to now with the
396
-	 * desired interval
397
-	 * @return bool
398
-	 */
399
-	private function needsRefresh() {
400
-		$lastChecked = $this->config->getUserValue($this->uid, 'user_ldap',
401
-			self::USER_PREFKEY_LASTREFRESH, 0);
402
-
403
-		if((time() - (int)$lastChecked) < (int)$this->config->getAppValue('user_ldap', 'updateAttributesInterval', 86400)) {
404
-			return false;
405
-		}
406
-		return  true;
407
-	}
408
-
409
-	/**
410
-	 * Stores a key-value pair in relation to this user
411
-	 *
412
-	 * @param string $key
413
-	 * @param string $value
414
-	 */
415
-	private function store($key, $value) {
416
-		$this->config->setUserValue($this->uid, 'user_ldap', $key, $value);
417
-	}
418
-
419
-	/**
420
-	 * Composes the display name and stores it in the database. The final
421
-	 * display name is returned.
422
-	 *
423
-	 * @param string $displayName
424
-	 * @param string $displayName2
425
-	 * @return string the effective display name
426
-	 */
427
-	public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
428
-		$displayName2 = (string)$displayName2;
429
-		if($displayName2 !== '') {
430
-			$displayName .= ' (' . $displayName2 . ')';
431
-		}
432
-		$oldName = $this->config->getUserValue($this->uid, 'user_ldap', 'displayName', null);
433
-		if ($oldName !== $displayName)  {
434
-			$this->store('displayName', $displayName);
435
-			$user = $this->userManager->get($this->getUsername());
436
-			if (!empty($oldName) && $user instanceof \OC\User\User) {
437
-				// if it was empty, it would be a new record, not a change emitting the trigger could
438
-				// potentially cause a UniqueConstraintViolationException, depending on some factors.
439
-				$user->triggerChange('displayName', $displayName);
440
-			}
441
-		}
442
-		return $displayName;
443
-	}
444
-
445
-	/**
446
-	 * Stores the LDAP Username in the Database
447
-	 * @param string $userName
448
-	 */
449
-	public function storeLDAPUserName($userName) {
450
-		$this->store('uid', $userName);
451
-	}
452
-
453
-	/**
454
-	 * @brief checks whether an update method specified by feature was run
455
-	 * already. If not, it will marked like this, because it is expected that
456
-	 * the method will be run, when false is returned.
457
-	 * @param string $feature email | quota | avatar (can be extended)
458
-	 * @return bool
459
-	 */
460
-	private function wasRefreshed($feature) {
461
-		if(isset($this->refreshedFeatures[$feature])) {
462
-			return true;
463
-		}
464
-		$this->refreshedFeatures[$feature] = 1;
465
-		return false;
466
-	}
467
-
468
-	/**
469
-	 * fetches the email from LDAP and stores it as Nextcloud user value
470
-	 * @param string $valueFromLDAP if known, to save an LDAP read request
471
-	 * @return null
472
-	 */
473
-	public function updateEmail($valueFromLDAP = null) {
474
-		if($this->wasRefreshed('email')) {
475
-			return;
476
-		}
477
-		$email = (string)$valueFromLDAP;
478
-		if(is_null($valueFromLDAP)) {
479
-			$emailAttribute = $this->connection->ldapEmailAttribute;
480
-			if ($emailAttribute !== '') {
481
-				$aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
482
-				if(is_array($aEmail) && (count($aEmail) > 0)) {
483
-					$email = (string)$aEmail[0];
484
-				}
485
-			}
486
-		}
487
-		if ($email !== '') {
488
-			$user = $this->userManager->get($this->uid);
489
-			if (!is_null($user)) {
490
-				$currentEmail = (string)$user->getEMailAddress();
491
-				if ($currentEmail !== $email) {
492
-					$user->setEMailAddress($email);
493
-				}
494
-			}
495
-		}
496
-	}
497
-
498
-	/**
499
-	 * Overall process goes as follow:
500
-	 * 1. fetch the quota from LDAP and check if it's parseable with the "verifyQuotaValue" function
501
-	 * 2. if the value can't be fetched, is empty or not parseable, use the default LDAP quota
502
-	 * 3. if the default LDAP quota can't be parsed, use the Nextcloud's default quota (use 'default')
503
-	 * 4. check if the target user exists and set the quota for the user.
504
-	 *
505
-	 * In order to improve performance and prevent an unwanted extra LDAP call, the $valueFromLDAP
506
-	 * parameter can be passed with the value of the attribute. This value will be considered as the
507
-	 * quota for the user coming from the LDAP server (step 1 of the process) It can be useful to
508
-	 * fetch all the user's attributes in one call and use the fetched values in this function.
509
-	 * The expected value for that parameter is a string describing the quota for the user. Valid
510
-	 * values are 'none' (unlimited), 'default' (the Nextcloud's default quota), '1234' (quota in
511
-	 * bytes), '1234 MB' (quota in MB - check the \OC_Helper::computerFileSize method for more info)
512
-	 *
513
-	 * fetches the quota from LDAP and stores it as Nextcloud user value
514
-	 * @param string $valueFromLDAP the quota attribute's value can be passed,
515
-	 * to save the readAttribute request
516
-	 * @return null
517
-	 */
518
-	public function updateQuota($valueFromLDAP = null) {
519
-		if($this->wasRefreshed('quota')) {
520
-			return;
521
-		}
522
-
523
-		$quotaAttribute = $this->connection->ldapQuotaAttribute;
524
-		$defaultQuota = $this->connection->ldapQuotaDefault;
525
-		if($quotaAttribute === '' && $defaultQuota === '') {
526
-			return;
527
-		}
528
-
529
-		$quota = false;
530
-		if(is_null($valueFromLDAP) && $quotaAttribute !== '') {
531
-			$aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);
532
-			if($aQuota && (count($aQuota) > 0) && $this->verifyQuotaValue($aQuota[0])) {
533
-				$quota = $aQuota[0];
534
-			} else if(is_array($aQuota) && isset($aQuota[0])) {
535
-				$this->log->log('no suitable LDAP quota found for user ' . $this->uid . ': [' . $aQuota[0] . ']', ILogger::DEBUG);
536
-			}
537
-		} else if ($this->verifyQuotaValue($valueFromLDAP)) {
538
-			$quota = $valueFromLDAP;
539
-		} else {
540
-			$this->log->log('no suitable LDAP quota found for user ' . $this->uid . ': [' . $valueFromLDAP . ']', ILogger::DEBUG);
541
-		}
542
-
543
-		if ($quota === false && $this->verifyQuotaValue($defaultQuota)) {
544
-			// quota not found using the LDAP attribute (or not parseable). Try the default quota
545
-			$quota = $defaultQuota;
546
-		} else if($quota === false) {
547
-			$this->log->log('no suitable default quota found for user ' . $this->uid . ': [' . $defaultQuota . ']', ILogger::DEBUG);
548
-			return;
549
-		}
550
-
551
-		$targetUser = $this->userManager->get($this->uid);
552
-		if ($targetUser instanceof IUser) {
553
-			$targetUser->setQuota($quota);
554
-		} else {
555
-			$this->log->log('trying to set a quota for user ' . $this->uid . ' but the user is missing', ILogger::INFO);
556
-		}
557
-	}
558
-
559
-	private function verifyQuotaValue($quotaValue) {
560
-		return $quotaValue === 'none' || $quotaValue === 'default' || \OC_Helper::computerFileSize($quotaValue) !== false;
561
-	}
562
-
563
-	/**
564
-	 * called by a post_login hook to save the avatar picture
565
-	 *
566
-	 * @param array $params
567
-	 */
568
-	public function updateAvatarPostLogin($params) {
569
-		if(isset($params['uid']) && $params['uid'] === $this->getUsername()) {
570
-			$this->updateAvatar();
571
-		}
572
-	}
573
-
574
-	/**
575
-	 * @brief attempts to get an image from LDAP and sets it as Nextcloud avatar
576
-	 * @return bool
577
-	 */
578
-	public function updateAvatar($force = false) {
579
-		if(!$force && $this->wasRefreshed('avatar')) {
580
-			return false;
581
-		}
582
-		$avatarImage = $this->getAvatarImage();
583
-		if($avatarImage === false) {
584
-			//not set, nothing left to do;
585
-			return false;
586
-		}
587
-		if(!$this->image->loadFromBase64(base64_encode($avatarImage))) {
588
-			return false;
589
-		}
590
-		return $this->setOwnCloudAvatar();
591
-	}
592
-
593
-	/**
594
-	 * @brief sets an image as Nextcloud avatar
595
-	 * @return bool
596
-	 */
597
-	private function setOwnCloudAvatar() {
598
-		if(!$this->image->valid()) {
599
-			$this->log->log('avatar image data from LDAP invalid for '.$this->dn, ILogger::ERROR);
600
-			return false;
601
-		}
602
-		//make sure it is a square and not bigger than 128x128
603
-		$size = min(array($this->image->width(), $this->image->height(), 128));
604
-		if(!$this->image->centerCrop($size)) {
605
-			$this->log->log('croping image for avatar failed for '.$this->dn, ILogger::ERROR);
606
-			return false;
607
-		}
608
-
609
-		if(!$this->fs->isLoaded()) {
610
-			$this->fs->setup($this->uid);
611
-		}
612
-
613
-		try {
614
-			$avatar = $this->avatarManager->getAvatar($this->uid);
615
-			$avatar->set($this->image);
616
-			return true;
617
-		} catch (\Exception $e) {
618
-			\OC::$server->getLogger()->logException($e, [
619
-				'message' => 'Could not set avatar for ' . $this->dn,
620
-				'level' => ILogger::INFO,
621
-				'app' => 'user_ldap',
622
-			]);
623
-		}
624
-		return false;
625
-	}
626
-
627
-	/**
628
-	 * @throws AttributeNotSet
629
-	 * @throws \OC\ServerNotAvailableException
630
-	 * @throws \OCP\PreConditionNotMetException
631
-	 */
632
-	public function getExtStorageHome():string {
633
-		$value = $this->config->getUserValue($this->getUsername(), 'user_ldap', 'extStorageHome', '');
634
-		if ($value !== '') {
635
-			return $value;
636
-		}
637
-
638
-		$value = $this->updateExtStorageHome();
639
-		if ($value !== '') {
640
-			return $value;
641
-		}
642
-
643
-		throw new AttributeNotSet(sprintf(
644
-			'external home storage attribute yield no value for %s', $this->getUsername()
645
-		));
646
-	}
647
-
648
-	/**
649
-	 * @throws \OCP\PreConditionNotMetException
650
-	 * @throws \OC\ServerNotAvailableException
651
-	 */
652
-	public function updateExtStorageHome(string $valueFromLDAP = null):string {
653
-		if($valueFromLDAP === null) {
654
-			$extHomeValues = $this->access->readAttribute($this->getDN(), $this->connection->ldapExtStorageHomeAttribute);
655
-		} else {
656
-			$extHomeValues = [$valueFromLDAP];
657
-		}
658
-		if ($extHomeValues && isset($extHomeValues[0])) {
659
-			$extHome = $extHomeValues[0];
660
-			$this->config->setUserValue($this->getUsername(), 'user_ldap', 'extStorageHome', $extHome);
661
-			return $extHome;
662
-		} else {
663
-			$this->config->deleteUserValue($this->getUsername(), 'user_ldap', 'extStorageHome');
664
-			return '';
665
-		}
666
-	}
667
-
668
-	/**
669
-	 * called by a post_login hook to handle password expiry
670
-	 *
671
-	 * @param array $params
672
-	 */
673
-	public function handlePasswordExpiry($params) {
674
-		$ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
675
-		if (empty($ppolicyDN) || ((int)$this->connection->turnOnPasswordChange !== 1)) {
676
-			return;//password expiry handling disabled
677
-		}
678
-		$uid = $params['uid'];
679
-		if(isset($uid) && $uid === $this->getUsername()) {
680
-			//retrieve relevant user attributes
681
-			$result = $this->access->search('objectclass=*', array($this->dn), ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
129
+        if ($username === null) {
130
+            $log->log("uid for '$dn' must not be null!", ILogger::ERROR);
131
+            throw new \InvalidArgumentException('uid must not be null!');
132
+        } else if ($username === '') {
133
+            $log->log("uid for '$dn' must not be an empty string", ILogger::ERROR);
134
+            throw new \InvalidArgumentException('uid must not be an empty string!');
135
+        }
136
+
137
+        $this->access              = $access;
138
+        $this->connection          = $access->getConnection();
139
+        $this->config              = $config;
140
+        $this->fs                  = $fs;
141
+        $this->dn                  = $dn;
142
+        $this->uid                 = $username;
143
+        $this->image               = $image;
144
+        $this->log                 = $log;
145
+        $this->avatarManager       = $avatarManager;
146
+        $this->userManager         = $userManager;
147
+        $this->notificationManager = $notificationManager;
148
+
149
+        \OCP\Util::connectHook('OC_User', 'post_login', $this, 'handlePasswordExpiry');
150
+    }
151
+
152
+    /**
153
+     * @brief updates properties like email, quota or avatar provided by LDAP
154
+     * @return null
155
+     */
156
+    public function update() {
157
+        if(is_null($this->dn)) {
158
+            return null;
159
+        }
160
+
161
+        $hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap',
162
+                self::USER_PREFKEY_FIRSTLOGIN, 0);
163
+
164
+        if($this->needsRefresh()) {
165
+            $this->updateEmail();
166
+            $this->updateQuota();
167
+            if($hasLoggedIn !== 0) {
168
+                //we do not need to try it, when the user has not been logged in
169
+                //before, because the file system will not be ready.
170
+                $this->updateAvatar();
171
+                //in order to get an avatar as soon as possible, mark the user
172
+                //as refreshed only when updating the avatar did happen
173
+                $this->markRefreshTime();
174
+            }
175
+        }
176
+    }
177
+
178
+    /**
179
+     * processes results from LDAP for attributes as returned by getAttributesToRead()
180
+     * @param array $ldapEntry the user entry as retrieved from LDAP
181
+     */
182
+    public function processAttributes($ldapEntry) {
183
+        $this->markRefreshTime();
184
+        //Quota
185
+        $attr = strtolower($this->connection->ldapQuotaAttribute);
186
+        if(isset($ldapEntry[$attr])) {
187
+            $this->updateQuota($ldapEntry[$attr][0]);
188
+        } else {
189
+            if ($this->connection->ldapQuotaDefault !== '') {
190
+                $this->updateQuota();
191
+            }
192
+        }
193
+        unset($attr);
194
+
195
+        //displayName
196
+        $displayName = $displayName2 = '';
197
+        $attr = strtolower($this->connection->ldapUserDisplayName);
198
+        if(isset($ldapEntry[$attr])) {
199
+            $displayName = (string)$ldapEntry[$attr][0];
200
+        }
201
+        $attr = strtolower($this->connection->ldapUserDisplayName2);
202
+        if(isset($ldapEntry[$attr])) {
203
+            $displayName2 = (string)$ldapEntry[$attr][0];
204
+        }
205
+        if ($displayName !== '') {
206
+            $this->composeAndStoreDisplayName($displayName, $displayName2);
207
+            $this->access->cacheUserDisplayName(
208
+                $this->getUsername(),
209
+                $displayName,
210
+                $displayName2
211
+            );
212
+        }
213
+        unset($attr);
214
+
215
+        //Email
216
+        //email must be stored after displayname, because it would cause a user
217
+        //change event that will trigger fetching the display name again
218
+        $attr = strtolower($this->connection->ldapEmailAttribute);
219
+        if(isset($ldapEntry[$attr])) {
220
+            $this->updateEmail($ldapEntry[$attr][0]);
221
+        }
222
+        unset($attr);
223
+
224
+        // LDAP Username, needed for s2s sharing
225
+        if(isset($ldapEntry['uid'])) {
226
+            $this->storeLDAPUserName($ldapEntry['uid'][0]);
227
+        } else if(isset($ldapEntry['samaccountname'])) {
228
+            $this->storeLDAPUserName($ldapEntry['samaccountname'][0]);
229
+        }
230
+
231
+        //homePath
232
+        if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
233
+            $attr = strtolower(substr($this->connection->homeFolderNamingRule, strlen('attr:')));
234
+            if(isset($ldapEntry[$attr])) {
235
+                $this->access->cacheUserHome(
236
+                    $this->getUsername(), $this->getHomePath($ldapEntry[$attr][0]));
237
+            }
238
+        }
239
+
240
+        //memberOf groups
241
+        $cacheKey = 'getMemberOf'.$this->getUsername();
242
+        $groups = false;
243
+        if(isset($ldapEntry['memberof'])) {
244
+            $groups = $ldapEntry['memberof'];
245
+        }
246
+        $this->connection->writeToCache($cacheKey, $groups);
247
+
248
+        //external storage var
249
+        $attr = strtolower($this->connection->ldapExtStorageHomeAttribute);
250
+        if(isset($ldapEntry[$attr])) {
251
+            $this->updateExtStorageHome($ldapEntry[$attr][0]);
252
+        }
253
+        unset($attr);
254
+
255
+        //Avatar
256
+        /** @var Connection $connection */
257
+        $connection = $this->access->getConnection();
258
+        $attributes = $connection->resolveRule('avatar');
259
+        foreach ($attributes as $attribute)  {
260
+            if(isset($ldapEntry[$attribute])) {
261
+                $this->avatarImage = $ldapEntry[$attribute][0];
262
+                // the call to the method that saves the avatar in the file
263
+                // system must be postponed after the login. It is to ensure
264
+                // external mounts are mounted properly (e.g. with login
265
+                // credentials from the session).
266
+                \OCP\Util::connectHook('OC_User', 'post_login', $this, 'updateAvatarPostLogin');
267
+                break;
268
+            }
269
+        }
270
+    }
271
+
272
+    /**
273
+     * @brief returns the LDAP DN of the user
274
+     * @return string
275
+     */
276
+    public function getDN() {
277
+        return $this->dn;
278
+    }
279
+
280
+    /**
281
+     * @brief returns the Nextcloud internal username of the user
282
+     * @return string
283
+     */
284
+    public function getUsername() {
285
+        return $this->uid;
286
+    }
287
+
288
+    /**
289
+     * returns the home directory of the user if specified by LDAP settings
290
+     * @param string $valueFromLDAP
291
+     * @return bool|string
292
+     * @throws \Exception
293
+     */
294
+    public function getHomePath($valueFromLDAP = null) {
295
+        $path = (string)$valueFromLDAP;
296
+        $attr = null;
297
+
298
+        if (is_null($valueFromLDAP)
299
+           && strpos($this->access->connection->homeFolderNamingRule, 'attr:') === 0
300
+           && $this->access->connection->homeFolderNamingRule !== 'attr:')
301
+        {
302
+            $attr = substr($this->access->connection->homeFolderNamingRule, strlen('attr:'));
303
+            $homedir = $this->access->readAttribute(
304
+                $this->access->username2dn($this->getUsername()), $attr);
305
+            if ($homedir && isset($homedir[0])) {
306
+                $path = $homedir[0];
307
+            }
308
+        }
309
+
310
+        if ($path !== '') {
311
+            //if attribute's value is an absolute path take this, otherwise append it to data dir
312
+            //check for / at the beginning or pattern c:\ resp. c:/
313
+            if(   '/' !== $path[0]
314
+               && !(3 < strlen($path) && ctype_alpha($path[0])
315
+                   && $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))
316
+            ) {
317
+                $path = $this->config->getSystemValue('datadirectory',
318
+                        \OC::$SERVERROOT.'/data' ) . '/' . $path;
319
+            }
320
+            //we need it to store it in the DB as well in case a user gets
321
+            //deleted so we can clean up afterwards
322
+            $this->config->setUserValue(
323
+                $this->getUsername(), 'user_ldap', 'homePath', $path
324
+            );
325
+            return $path;
326
+        }
327
+
328
+        if(    !is_null($attr)
329
+            && $this->config->getAppValue('user_ldap', 'enforce_home_folder_naming_rule', true)
330
+        ) {
331
+            // a naming rule attribute is defined, but it doesn't exist for that LDAP user
332
+            throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: ' . $this->getUsername());
333
+        }
334
+
335
+        //false will apply default behaviour as defined and done by OC_User
336
+        $this->config->setUserValue($this->getUsername(), 'user_ldap', 'homePath', '');
337
+        return false;
338
+    }
339
+
340
+    public function getMemberOfGroups() {
341
+        $cacheKey = 'getMemberOf'.$this->getUsername();
342
+        $memberOfGroups = $this->connection->getFromCache($cacheKey);
343
+        if(!is_null($memberOfGroups)) {
344
+            return $memberOfGroups;
345
+        }
346
+        $groupDNs = $this->access->readAttribute($this->getDN(), 'memberOf');
347
+        $this->connection->writeToCache($cacheKey, $groupDNs);
348
+        return $groupDNs;
349
+    }
350
+
351
+    /**
352
+     * @brief reads the image from LDAP that shall be used as Avatar
353
+     * @return string data (provided by LDAP) | false
354
+     */
355
+    public function getAvatarImage() {
356
+        if(!is_null($this->avatarImage)) {
357
+            return $this->avatarImage;
358
+        }
359
+
360
+        $this->avatarImage = false;
361
+        /** @var Connection $connection */
362
+        $connection = $this->access->getConnection();
363
+        $attributes = $connection->resolveRule('avatar');
364
+        foreach($attributes as $attribute) {
365
+            $result = $this->access->readAttribute($this->dn, $attribute);
366
+            if($result !== false && is_array($result) && isset($result[0])) {
367
+                $this->avatarImage = $result[0];
368
+                break;
369
+            }
370
+        }
371
+
372
+        return $this->avatarImage;
373
+    }
374
+
375
+    /**
376
+     * @brief marks the user as having logged in at least once
377
+     * @return null
378
+     */
379
+    public function markLogin() {
380
+        $this->config->setUserValue(
381
+            $this->uid, 'user_ldap', self::USER_PREFKEY_FIRSTLOGIN, 1);
382
+    }
383
+
384
+    /**
385
+     * @brief marks the time when user features like email have been updated
386
+     * @return null
387
+     */
388
+    public function markRefreshTime() {
389
+        $this->config->setUserValue(
390
+            $this->uid, 'user_ldap', self::USER_PREFKEY_LASTREFRESH, time());
391
+    }
392
+
393
+    /**
394
+     * @brief checks whether user features needs to be updated again by
395
+     * comparing the difference of time of the last refresh to now with the
396
+     * desired interval
397
+     * @return bool
398
+     */
399
+    private function needsRefresh() {
400
+        $lastChecked = $this->config->getUserValue($this->uid, 'user_ldap',
401
+            self::USER_PREFKEY_LASTREFRESH, 0);
402
+
403
+        if((time() - (int)$lastChecked) < (int)$this->config->getAppValue('user_ldap', 'updateAttributesInterval', 86400)) {
404
+            return false;
405
+        }
406
+        return  true;
407
+    }
408
+
409
+    /**
410
+     * Stores a key-value pair in relation to this user
411
+     *
412
+     * @param string $key
413
+     * @param string $value
414
+     */
415
+    private function store($key, $value) {
416
+        $this->config->setUserValue($this->uid, 'user_ldap', $key, $value);
417
+    }
418
+
419
+    /**
420
+     * Composes the display name and stores it in the database. The final
421
+     * display name is returned.
422
+     *
423
+     * @param string $displayName
424
+     * @param string $displayName2
425
+     * @return string the effective display name
426
+     */
427
+    public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
428
+        $displayName2 = (string)$displayName2;
429
+        if($displayName2 !== '') {
430
+            $displayName .= ' (' . $displayName2 . ')';
431
+        }
432
+        $oldName = $this->config->getUserValue($this->uid, 'user_ldap', 'displayName', null);
433
+        if ($oldName !== $displayName)  {
434
+            $this->store('displayName', $displayName);
435
+            $user = $this->userManager->get($this->getUsername());
436
+            if (!empty($oldName) && $user instanceof \OC\User\User) {
437
+                // if it was empty, it would be a new record, not a change emitting the trigger could
438
+                // potentially cause a UniqueConstraintViolationException, depending on some factors.
439
+                $user->triggerChange('displayName', $displayName);
440
+            }
441
+        }
442
+        return $displayName;
443
+    }
444
+
445
+    /**
446
+     * Stores the LDAP Username in the Database
447
+     * @param string $userName
448
+     */
449
+    public function storeLDAPUserName($userName) {
450
+        $this->store('uid', $userName);
451
+    }
452
+
453
+    /**
454
+     * @brief checks whether an update method specified by feature was run
455
+     * already. If not, it will marked like this, because it is expected that
456
+     * the method will be run, when false is returned.
457
+     * @param string $feature email | quota | avatar (can be extended)
458
+     * @return bool
459
+     */
460
+    private function wasRefreshed($feature) {
461
+        if(isset($this->refreshedFeatures[$feature])) {
462
+            return true;
463
+        }
464
+        $this->refreshedFeatures[$feature] = 1;
465
+        return false;
466
+    }
467
+
468
+    /**
469
+     * fetches the email from LDAP and stores it as Nextcloud user value
470
+     * @param string $valueFromLDAP if known, to save an LDAP read request
471
+     * @return null
472
+     */
473
+    public function updateEmail($valueFromLDAP = null) {
474
+        if($this->wasRefreshed('email')) {
475
+            return;
476
+        }
477
+        $email = (string)$valueFromLDAP;
478
+        if(is_null($valueFromLDAP)) {
479
+            $emailAttribute = $this->connection->ldapEmailAttribute;
480
+            if ($emailAttribute !== '') {
481
+                $aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
482
+                if(is_array($aEmail) && (count($aEmail) > 0)) {
483
+                    $email = (string)$aEmail[0];
484
+                }
485
+            }
486
+        }
487
+        if ($email !== '') {
488
+            $user = $this->userManager->get($this->uid);
489
+            if (!is_null($user)) {
490
+                $currentEmail = (string)$user->getEMailAddress();
491
+                if ($currentEmail !== $email) {
492
+                    $user->setEMailAddress($email);
493
+                }
494
+            }
495
+        }
496
+    }
497
+
498
+    /**
499
+     * Overall process goes as follow:
500
+     * 1. fetch the quota from LDAP and check if it's parseable with the "verifyQuotaValue" function
501
+     * 2. if the value can't be fetched, is empty or not parseable, use the default LDAP quota
502
+     * 3. if the default LDAP quota can't be parsed, use the Nextcloud's default quota (use 'default')
503
+     * 4. check if the target user exists and set the quota for the user.
504
+     *
505
+     * In order to improve performance and prevent an unwanted extra LDAP call, the $valueFromLDAP
506
+     * parameter can be passed with the value of the attribute. This value will be considered as the
507
+     * quota for the user coming from the LDAP server (step 1 of the process) It can be useful to
508
+     * fetch all the user's attributes in one call and use the fetched values in this function.
509
+     * The expected value for that parameter is a string describing the quota for the user. Valid
510
+     * values are 'none' (unlimited), 'default' (the Nextcloud's default quota), '1234' (quota in
511
+     * bytes), '1234 MB' (quota in MB - check the \OC_Helper::computerFileSize method for more info)
512
+     *
513
+     * fetches the quota from LDAP and stores it as Nextcloud user value
514
+     * @param string $valueFromLDAP the quota attribute's value can be passed,
515
+     * to save the readAttribute request
516
+     * @return null
517
+     */
518
+    public function updateQuota($valueFromLDAP = null) {
519
+        if($this->wasRefreshed('quota')) {
520
+            return;
521
+        }
522
+
523
+        $quotaAttribute = $this->connection->ldapQuotaAttribute;
524
+        $defaultQuota = $this->connection->ldapQuotaDefault;
525
+        if($quotaAttribute === '' && $defaultQuota === '') {
526
+            return;
527
+        }
528
+
529
+        $quota = false;
530
+        if(is_null($valueFromLDAP) && $quotaAttribute !== '') {
531
+            $aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);
532
+            if($aQuota && (count($aQuota) > 0) && $this->verifyQuotaValue($aQuota[0])) {
533
+                $quota = $aQuota[0];
534
+            } else if(is_array($aQuota) && isset($aQuota[0])) {
535
+                $this->log->log('no suitable LDAP quota found for user ' . $this->uid . ': [' . $aQuota[0] . ']', ILogger::DEBUG);
536
+            }
537
+        } else if ($this->verifyQuotaValue($valueFromLDAP)) {
538
+            $quota = $valueFromLDAP;
539
+        } else {
540
+            $this->log->log('no suitable LDAP quota found for user ' . $this->uid . ': [' . $valueFromLDAP . ']', ILogger::DEBUG);
541
+        }
542
+
543
+        if ($quota === false && $this->verifyQuotaValue($defaultQuota)) {
544
+            // quota not found using the LDAP attribute (or not parseable). Try the default quota
545
+            $quota = $defaultQuota;
546
+        } else if($quota === false) {
547
+            $this->log->log('no suitable default quota found for user ' . $this->uid . ': [' . $defaultQuota . ']', ILogger::DEBUG);
548
+            return;
549
+        }
550
+
551
+        $targetUser = $this->userManager->get($this->uid);
552
+        if ($targetUser instanceof IUser) {
553
+            $targetUser->setQuota($quota);
554
+        } else {
555
+            $this->log->log('trying to set a quota for user ' . $this->uid . ' but the user is missing', ILogger::INFO);
556
+        }
557
+    }
558
+
559
+    private function verifyQuotaValue($quotaValue) {
560
+        return $quotaValue === 'none' || $quotaValue === 'default' || \OC_Helper::computerFileSize($quotaValue) !== false;
561
+    }
562
+
563
+    /**
564
+     * called by a post_login hook to save the avatar picture
565
+     *
566
+     * @param array $params
567
+     */
568
+    public function updateAvatarPostLogin($params) {
569
+        if(isset($params['uid']) && $params['uid'] === $this->getUsername()) {
570
+            $this->updateAvatar();
571
+        }
572
+    }
573
+
574
+    /**
575
+     * @brief attempts to get an image from LDAP and sets it as Nextcloud avatar
576
+     * @return bool
577
+     */
578
+    public function updateAvatar($force = false) {
579
+        if(!$force && $this->wasRefreshed('avatar')) {
580
+            return false;
581
+        }
582
+        $avatarImage = $this->getAvatarImage();
583
+        if($avatarImage === false) {
584
+            //not set, nothing left to do;
585
+            return false;
586
+        }
587
+        if(!$this->image->loadFromBase64(base64_encode($avatarImage))) {
588
+            return false;
589
+        }
590
+        return $this->setOwnCloudAvatar();
591
+    }
592
+
593
+    /**
594
+     * @brief sets an image as Nextcloud avatar
595
+     * @return bool
596
+     */
597
+    private function setOwnCloudAvatar() {
598
+        if(!$this->image->valid()) {
599
+            $this->log->log('avatar image data from LDAP invalid for '.$this->dn, ILogger::ERROR);
600
+            return false;
601
+        }
602
+        //make sure it is a square and not bigger than 128x128
603
+        $size = min(array($this->image->width(), $this->image->height(), 128));
604
+        if(!$this->image->centerCrop($size)) {
605
+            $this->log->log('croping image for avatar failed for '.$this->dn, ILogger::ERROR);
606
+            return false;
607
+        }
608
+
609
+        if(!$this->fs->isLoaded()) {
610
+            $this->fs->setup($this->uid);
611
+        }
612
+
613
+        try {
614
+            $avatar = $this->avatarManager->getAvatar($this->uid);
615
+            $avatar->set($this->image);
616
+            return true;
617
+        } catch (\Exception $e) {
618
+            \OC::$server->getLogger()->logException($e, [
619
+                'message' => 'Could not set avatar for ' . $this->dn,
620
+                'level' => ILogger::INFO,
621
+                'app' => 'user_ldap',
622
+            ]);
623
+        }
624
+        return false;
625
+    }
626
+
627
+    /**
628
+     * @throws AttributeNotSet
629
+     * @throws \OC\ServerNotAvailableException
630
+     * @throws \OCP\PreConditionNotMetException
631
+     */
632
+    public function getExtStorageHome():string {
633
+        $value = $this->config->getUserValue($this->getUsername(), 'user_ldap', 'extStorageHome', '');
634
+        if ($value !== '') {
635
+            return $value;
636
+        }
637
+
638
+        $value = $this->updateExtStorageHome();
639
+        if ($value !== '') {
640
+            return $value;
641
+        }
642
+
643
+        throw new AttributeNotSet(sprintf(
644
+            'external home storage attribute yield no value for %s', $this->getUsername()
645
+        ));
646
+    }
647
+
648
+    /**
649
+     * @throws \OCP\PreConditionNotMetException
650
+     * @throws \OC\ServerNotAvailableException
651
+     */
652
+    public function updateExtStorageHome(string $valueFromLDAP = null):string {
653
+        if($valueFromLDAP === null) {
654
+            $extHomeValues = $this->access->readAttribute($this->getDN(), $this->connection->ldapExtStorageHomeAttribute);
655
+        } else {
656
+            $extHomeValues = [$valueFromLDAP];
657
+        }
658
+        if ($extHomeValues && isset($extHomeValues[0])) {
659
+            $extHome = $extHomeValues[0];
660
+            $this->config->setUserValue($this->getUsername(), 'user_ldap', 'extStorageHome', $extHome);
661
+            return $extHome;
662
+        } else {
663
+            $this->config->deleteUserValue($this->getUsername(), 'user_ldap', 'extStorageHome');
664
+            return '';
665
+        }
666
+    }
667
+
668
+    /**
669
+     * called by a post_login hook to handle password expiry
670
+     *
671
+     * @param array $params
672
+     */
673
+    public function handlePasswordExpiry($params) {
674
+        $ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
675
+        if (empty($ppolicyDN) || ((int)$this->connection->turnOnPasswordChange !== 1)) {
676
+            return;//password expiry handling disabled
677
+        }
678
+        $uid = $params['uid'];
679
+        if(isset($uid) && $uid === $this->getUsername()) {
680
+            //retrieve relevant user attributes
681
+            $result = $this->access->search('objectclass=*', array($this->dn), ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
682 682
 			
683
-			if(array_key_exists('pwdpolicysubentry', $result[0])) {
684
-				$pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
685
-				if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
686
-					$ppolicyDN = $pwdPolicySubentry[0];//custom ppolicy DN
687
-				}
688
-			}
683
+            if(array_key_exists('pwdpolicysubentry', $result[0])) {
684
+                $pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
685
+                if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
686
+                    $ppolicyDN = $pwdPolicySubentry[0];//custom ppolicy DN
687
+                }
688
+            }
689 689
 			
690
-			$pwdGraceUseTime = array_key_exists('pwdgraceusetime', $result[0]) ? $result[0]['pwdgraceusetime'] : null;
691
-			$pwdReset = array_key_exists('pwdreset', $result[0]) ? $result[0]['pwdreset'] : null;
692
-			$pwdChangedTime = array_key_exists('pwdchangedtime', $result[0]) ? $result[0]['pwdchangedtime'] : null;
690
+            $pwdGraceUseTime = array_key_exists('pwdgraceusetime', $result[0]) ? $result[0]['pwdgraceusetime'] : null;
691
+            $pwdReset = array_key_exists('pwdreset', $result[0]) ? $result[0]['pwdreset'] : null;
692
+            $pwdChangedTime = array_key_exists('pwdchangedtime', $result[0]) ? $result[0]['pwdchangedtime'] : null;
693 693
 			
694
-			//retrieve relevant password policy attributes
695
-			$cacheKey = 'ppolicyAttributes' . $ppolicyDN;
696
-			$result = $this->connection->getFromCache($cacheKey);
697
-			if(is_null($result)) {
698
-				$result = $this->access->search('objectclass=*', array($ppolicyDN), ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
699
-				$this->connection->writeToCache($cacheKey, $result);
700
-			}
694
+            //retrieve relevant password policy attributes
695
+            $cacheKey = 'ppolicyAttributes' . $ppolicyDN;
696
+            $result = $this->connection->getFromCache($cacheKey);
697
+            if(is_null($result)) {
698
+                $result = $this->access->search('objectclass=*', array($ppolicyDN), ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
699
+                $this->connection->writeToCache($cacheKey, $result);
700
+            }
701 701
 			
702
-			$pwdGraceAuthNLimit = array_key_exists('pwdgraceauthnlimit', $result[0]) ? $result[0]['pwdgraceauthnlimit'] : null;
703
-			$pwdMaxAge = array_key_exists('pwdmaxage', $result[0]) ? $result[0]['pwdmaxage'] : null;
704
-			$pwdExpireWarning = array_key_exists('pwdexpirewarning', $result[0]) ? $result[0]['pwdexpirewarning'] : null;
702
+            $pwdGraceAuthNLimit = array_key_exists('pwdgraceauthnlimit', $result[0]) ? $result[0]['pwdgraceauthnlimit'] : null;
703
+            $pwdMaxAge = array_key_exists('pwdmaxage', $result[0]) ? $result[0]['pwdmaxage'] : null;
704
+            $pwdExpireWarning = array_key_exists('pwdexpirewarning', $result[0]) ? $result[0]['pwdexpirewarning'] : null;
705 705
 			
706
-			//handle grace login
707
-			$pwdGraceUseTimeCount = count($pwdGraceUseTime);
708
-			if($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
709
-				if($pwdGraceAuthNLimit 
710
-					&& (count($pwdGraceAuthNLimit) > 0)
711
-					&&($pwdGraceUseTimeCount < (int)$pwdGraceAuthNLimit[0])) { //at least one more grace login available?
712
-					$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
713
-					header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
714
-					'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
715
-				} else { //no more grace login available
716
-					header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
717
-					'user_ldap.renewPassword.showLoginFormInvalidPassword', array('user' => $uid)));
718
-				}
719
-				exit();
720
-			}
721
-			//handle pwdReset attribute
722
-			if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
723
-				$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
724
-				header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
725
-				'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
726
-				exit();
727
-			}
728
-			//handle password expiry warning
729
-			if($pwdChangedTime && (count($pwdChangedTime) > 0)) {
730
-				if($pwdMaxAge && (count($pwdMaxAge) > 0)
731
-					&& $pwdExpireWarning && (count($pwdExpireWarning) > 0)) {
732
-					$pwdMaxAgeInt = (int)$pwdMaxAge[0];
733
-					$pwdExpireWarningInt = (int)$pwdExpireWarning[0];
734
-					if($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0){
735
-						$pwdChangedTimeDt = \DateTime::createFromFormat('YmdHisZ', $pwdChangedTime[0]);
736
-						$pwdChangedTimeDt->add(new \DateInterval('PT'.$pwdMaxAgeInt.'S'));
737
-						$currentDateTime = new \DateTime();
738
-						$secondsToExpiry = $pwdChangedTimeDt->getTimestamp() - $currentDateTime->getTimestamp();
739
-						if($secondsToExpiry <= $pwdExpireWarningInt) {
740
-							//remove last password expiry warning if any
741
-							$notification = $this->notificationManager->createNotification();
742
-							$notification->setApp('user_ldap')
743
-								->setUser($uid)
744
-								->setObject('pwd_exp_warn', $uid)
745
-							;
746
-							$this->notificationManager->markProcessed($notification);
747
-							//create new password expiry warning
748
-							$notification = $this->notificationManager->createNotification();
749
-							$notification->setApp('user_ldap')
750
-								->setUser($uid)
751
-								->setDateTime($currentDateTime)
752
-								->setObject('pwd_exp_warn', $uid) 
753
-								->setSubject('pwd_exp_warn_days', [(int) ceil($secondsToExpiry / 60 / 60 / 24)])
754
-							;
755
-							$this->notificationManager->notify($notification);
756
-						}
757
-					}
758
-				}
759
-			}
760
-		}
761
-	}
706
+            //handle grace login
707
+            $pwdGraceUseTimeCount = count($pwdGraceUseTime);
708
+            if($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
709
+                if($pwdGraceAuthNLimit 
710
+                    && (count($pwdGraceAuthNLimit) > 0)
711
+                    &&($pwdGraceUseTimeCount < (int)$pwdGraceAuthNLimit[0])) { //at least one more grace login available?
712
+                    $this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
713
+                    header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
714
+                    'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
715
+                } else { //no more grace login available
716
+                    header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
717
+                    'user_ldap.renewPassword.showLoginFormInvalidPassword', array('user' => $uid)));
718
+                }
719
+                exit();
720
+            }
721
+            //handle pwdReset attribute
722
+            if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
723
+                $this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
724
+                header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
725
+                'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
726
+                exit();
727
+            }
728
+            //handle password expiry warning
729
+            if($pwdChangedTime && (count($pwdChangedTime) > 0)) {
730
+                if($pwdMaxAge && (count($pwdMaxAge) > 0)
731
+                    && $pwdExpireWarning && (count($pwdExpireWarning) > 0)) {
732
+                    $pwdMaxAgeInt = (int)$pwdMaxAge[0];
733
+                    $pwdExpireWarningInt = (int)$pwdExpireWarning[0];
734
+                    if($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0){
735
+                        $pwdChangedTimeDt = \DateTime::createFromFormat('YmdHisZ', $pwdChangedTime[0]);
736
+                        $pwdChangedTimeDt->add(new \DateInterval('PT'.$pwdMaxAgeInt.'S'));
737
+                        $currentDateTime = new \DateTime();
738
+                        $secondsToExpiry = $pwdChangedTimeDt->getTimestamp() - $currentDateTime->getTimestamp();
739
+                        if($secondsToExpiry <= $pwdExpireWarningInt) {
740
+                            //remove last password expiry warning if any
741
+                            $notification = $this->notificationManager->createNotification();
742
+                            $notification->setApp('user_ldap')
743
+                                ->setUser($uid)
744
+                                ->setObject('pwd_exp_warn', $uid)
745
+                            ;
746
+                            $this->notificationManager->markProcessed($notification);
747
+                            //create new password expiry warning
748
+                            $notification = $this->notificationManager->createNotification();
749
+                            $notification->setApp('user_ldap')
750
+                                ->setUser($uid)
751
+                                ->setDateTime($currentDateTime)
752
+                                ->setObject('pwd_exp_warn', $uid) 
753
+                                ->setSubject('pwd_exp_warn_days', [(int) ceil($secondsToExpiry / 60 / 60 / 24)])
754
+                            ;
755
+                            $this->notificationManager->notify($notification);
756
+                        }
757
+                    }
758
+                }
759
+            }
760
+        }
761
+    }
762 762
 }
Please login to merge, or discard this patch.
Spacing   +75 added lines, -75 removed lines patch added patch discarded remove patch
@@ -154,17 +154,17 @@  discard block
 block discarded – undo
154 154
 	 * @return null
155 155
 	 */
156 156
 	public function update() {
157
-		if(is_null($this->dn)) {
157
+		if (is_null($this->dn)) {
158 158
 			return null;
159 159
 		}
160 160
 
161 161
 		$hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap',
162 162
 				self::USER_PREFKEY_FIRSTLOGIN, 0);
163 163
 
164
-		if($this->needsRefresh()) {
164
+		if ($this->needsRefresh()) {
165 165
 			$this->updateEmail();
166 166
 			$this->updateQuota();
167
-			if($hasLoggedIn !== 0) {
167
+			if ($hasLoggedIn !== 0) {
168 168
 				//we do not need to try it, when the user has not been logged in
169 169
 				//before, because the file system will not be ready.
170 170
 				$this->updateAvatar();
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
 		$this->markRefreshTime();
184 184
 		//Quota
185 185
 		$attr = strtolower($this->connection->ldapQuotaAttribute);
186
-		if(isset($ldapEntry[$attr])) {
186
+		if (isset($ldapEntry[$attr])) {
187 187
 			$this->updateQuota($ldapEntry[$attr][0]);
188 188
 		} else {
189 189
 			if ($this->connection->ldapQuotaDefault !== '') {
@@ -195,12 +195,12 @@  discard block
 block discarded – undo
195 195
 		//displayName
196 196
 		$displayName = $displayName2 = '';
197 197
 		$attr = strtolower($this->connection->ldapUserDisplayName);
198
-		if(isset($ldapEntry[$attr])) {
199
-			$displayName = (string)$ldapEntry[$attr][0];
198
+		if (isset($ldapEntry[$attr])) {
199
+			$displayName = (string) $ldapEntry[$attr][0];
200 200
 		}
201 201
 		$attr = strtolower($this->connection->ldapUserDisplayName2);
202
-		if(isset($ldapEntry[$attr])) {
203
-			$displayName2 = (string)$ldapEntry[$attr][0];
202
+		if (isset($ldapEntry[$attr])) {
203
+			$displayName2 = (string) $ldapEntry[$attr][0];
204 204
 		}
205 205
 		if ($displayName !== '') {
206 206
 			$this->composeAndStoreDisplayName($displayName, $displayName2);
@@ -216,22 +216,22 @@  discard block
 block discarded – undo
216 216
 		//email must be stored after displayname, because it would cause a user
217 217
 		//change event that will trigger fetching the display name again
218 218
 		$attr = strtolower($this->connection->ldapEmailAttribute);
219
-		if(isset($ldapEntry[$attr])) {
219
+		if (isset($ldapEntry[$attr])) {
220 220
 			$this->updateEmail($ldapEntry[$attr][0]);
221 221
 		}
222 222
 		unset($attr);
223 223
 
224 224
 		// LDAP Username, needed for s2s sharing
225
-		if(isset($ldapEntry['uid'])) {
225
+		if (isset($ldapEntry['uid'])) {
226 226
 			$this->storeLDAPUserName($ldapEntry['uid'][0]);
227
-		} else if(isset($ldapEntry['samaccountname'])) {
227
+		} else if (isset($ldapEntry['samaccountname'])) {
228 228
 			$this->storeLDAPUserName($ldapEntry['samaccountname'][0]);
229 229
 		}
230 230
 
231 231
 		//homePath
232
-		if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
232
+		if (strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
233 233
 			$attr = strtolower(substr($this->connection->homeFolderNamingRule, strlen('attr:')));
234
-			if(isset($ldapEntry[$attr])) {
234
+			if (isset($ldapEntry[$attr])) {
235 235
 				$this->access->cacheUserHome(
236 236
 					$this->getUsername(), $this->getHomePath($ldapEntry[$attr][0]));
237 237
 			}
@@ -240,14 +240,14 @@  discard block
 block discarded – undo
240 240
 		//memberOf groups
241 241
 		$cacheKey = 'getMemberOf'.$this->getUsername();
242 242
 		$groups = false;
243
-		if(isset($ldapEntry['memberof'])) {
243
+		if (isset($ldapEntry['memberof'])) {
244 244
 			$groups = $ldapEntry['memberof'];
245 245
 		}
246 246
 		$this->connection->writeToCache($cacheKey, $groups);
247 247
 
248 248
 		//external storage var
249 249
 		$attr = strtolower($this->connection->ldapExtStorageHomeAttribute);
250
-		if(isset($ldapEntry[$attr])) {
250
+		if (isset($ldapEntry[$attr])) {
251 251
 			$this->updateExtStorageHome($ldapEntry[$attr][0]);
252 252
 		}
253 253
 		unset($attr);
@@ -256,8 +256,8 @@  discard block
 block discarded – undo
256 256
 		/** @var Connection $connection */
257 257
 		$connection = $this->access->getConnection();
258 258
 		$attributes = $connection->resolveRule('avatar');
259
-		foreach ($attributes as $attribute)  {
260
-			if(isset($ldapEntry[$attribute])) {
259
+		foreach ($attributes as $attribute) {
260
+			if (isset($ldapEntry[$attribute])) {
261 261
 				$this->avatarImage = $ldapEntry[$attribute][0];
262 262
 				// the call to the method that saves the avatar in the file
263 263
 				// system must be postponed after the login. It is to ensure
@@ -292,7 +292,7 @@  discard block
 block discarded – undo
292 292
 	 * @throws \Exception
293 293
 	 */
294 294
 	public function getHomePath($valueFromLDAP = null) {
295
-		$path = (string)$valueFromLDAP;
295
+		$path = (string) $valueFromLDAP;
296 296
 		$attr = null;
297 297
 
298 298
 		if (is_null($valueFromLDAP)
@@ -310,12 +310,12 @@  discard block
 block discarded – undo
310 310
 		if ($path !== '') {
311 311
 			//if attribute's value is an absolute path take this, otherwise append it to data dir
312 312
 			//check for / at the beginning or pattern c:\ resp. c:/
313
-			if(   '/' !== $path[0]
313
+			if ('/' !== $path[0]
314 314
 			   && !(3 < strlen($path) && ctype_alpha($path[0])
315 315
 			       && $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))
316 316
 			) {
317 317
 				$path = $this->config->getSystemValue('datadirectory',
318
-						\OC::$SERVERROOT.'/data' ) . '/' . $path;
318
+						\OC::$SERVERROOT.'/data').'/'.$path;
319 319
 			}
320 320
 			//we need it to store it in the DB as well in case a user gets
321 321
 			//deleted so we can clean up afterwards
@@ -325,11 +325,11 @@  discard block
 block discarded – undo
325 325
 			return $path;
326 326
 		}
327 327
 
328
-		if(    !is_null($attr)
328
+		if (!is_null($attr)
329 329
 			&& $this->config->getAppValue('user_ldap', 'enforce_home_folder_naming_rule', true)
330 330
 		) {
331 331
 			// a naming rule attribute is defined, but it doesn't exist for that LDAP user
332
-			throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: ' . $this->getUsername());
332
+			throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: '.$this->getUsername());
333 333
 		}
334 334
 
335 335
 		//false will apply default behaviour as defined and done by OC_User
@@ -340,7 +340,7 @@  discard block
 block discarded – undo
340 340
 	public function getMemberOfGroups() {
341 341
 		$cacheKey = 'getMemberOf'.$this->getUsername();
342 342
 		$memberOfGroups = $this->connection->getFromCache($cacheKey);
343
-		if(!is_null($memberOfGroups)) {
343
+		if (!is_null($memberOfGroups)) {
344 344
 			return $memberOfGroups;
345 345
 		}
346 346
 		$groupDNs = $this->access->readAttribute($this->getDN(), 'memberOf');
@@ -353,7 +353,7 @@  discard block
 block discarded – undo
353 353
 	 * @return string data (provided by LDAP) | false
354 354
 	 */
355 355
 	public function getAvatarImage() {
356
-		if(!is_null($this->avatarImage)) {
356
+		if (!is_null($this->avatarImage)) {
357 357
 			return $this->avatarImage;
358 358
 		}
359 359
 
@@ -361,9 +361,9 @@  discard block
 block discarded – undo
361 361
 		/** @var Connection $connection */
362 362
 		$connection = $this->access->getConnection();
363 363
 		$attributes = $connection->resolveRule('avatar');
364
-		foreach($attributes as $attribute) {
364
+		foreach ($attributes as $attribute) {
365 365
 			$result = $this->access->readAttribute($this->dn, $attribute);
366
-			if($result !== false && is_array($result) && isset($result[0])) {
366
+			if ($result !== false && is_array($result) && isset($result[0])) {
367 367
 				$this->avatarImage = $result[0];
368 368
 				break;
369 369
 			}
@@ -400,7 +400,7 @@  discard block
 block discarded – undo
400 400
 		$lastChecked = $this->config->getUserValue($this->uid, 'user_ldap',
401 401
 			self::USER_PREFKEY_LASTREFRESH, 0);
402 402
 
403
-		if((time() - (int)$lastChecked) < (int)$this->config->getAppValue('user_ldap', 'updateAttributesInterval', 86400)) {
403
+		if ((time() - (int) $lastChecked) < (int) $this->config->getAppValue('user_ldap', 'updateAttributesInterval', 86400)) {
404 404
 			return false;
405 405
 		}
406 406
 		return  true;
@@ -425,12 +425,12 @@  discard block
 block discarded – undo
425 425
 	 * @return string the effective display name
426 426
 	 */
427 427
 	public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
428
-		$displayName2 = (string)$displayName2;
429
-		if($displayName2 !== '') {
430
-			$displayName .= ' (' . $displayName2 . ')';
428
+		$displayName2 = (string) $displayName2;
429
+		if ($displayName2 !== '') {
430
+			$displayName .= ' ('.$displayName2.')';
431 431
 		}
432 432
 		$oldName = $this->config->getUserValue($this->uid, 'user_ldap', 'displayName', null);
433
-		if ($oldName !== $displayName)  {
433
+		if ($oldName !== $displayName) {
434 434
 			$this->store('displayName', $displayName);
435 435
 			$user = $this->userManager->get($this->getUsername());
436 436
 			if (!empty($oldName) && $user instanceof \OC\User\User) {
@@ -458,7 +458,7 @@  discard block
 block discarded – undo
458 458
 	 * @return bool
459 459
 	 */
460 460
 	private function wasRefreshed($feature) {
461
-		if(isset($this->refreshedFeatures[$feature])) {
461
+		if (isset($this->refreshedFeatures[$feature])) {
462 462
 			return true;
463 463
 		}
464 464
 		$this->refreshedFeatures[$feature] = 1;
@@ -471,23 +471,23 @@  discard block
 block discarded – undo
471 471
 	 * @return null
472 472
 	 */
473 473
 	public function updateEmail($valueFromLDAP = null) {
474
-		if($this->wasRefreshed('email')) {
474
+		if ($this->wasRefreshed('email')) {
475 475
 			return;
476 476
 		}
477
-		$email = (string)$valueFromLDAP;
478
-		if(is_null($valueFromLDAP)) {
477
+		$email = (string) $valueFromLDAP;
478
+		if (is_null($valueFromLDAP)) {
479 479
 			$emailAttribute = $this->connection->ldapEmailAttribute;
480 480
 			if ($emailAttribute !== '') {
481 481
 				$aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
482
-				if(is_array($aEmail) && (count($aEmail) > 0)) {
483
-					$email = (string)$aEmail[0];
482
+				if (is_array($aEmail) && (count($aEmail) > 0)) {
483
+					$email = (string) $aEmail[0];
484 484
 				}
485 485
 			}
486 486
 		}
487 487
 		if ($email !== '') {
488 488
 			$user = $this->userManager->get($this->uid);
489 489
 			if (!is_null($user)) {
490
-				$currentEmail = (string)$user->getEMailAddress();
490
+				$currentEmail = (string) $user->getEMailAddress();
491 491
 				if ($currentEmail !== $email) {
492 492
 					$user->setEMailAddress($email);
493 493
 				}
@@ -516,35 +516,35 @@  discard block
 block discarded – undo
516 516
 	 * @return null
517 517
 	 */
518 518
 	public function updateQuota($valueFromLDAP = null) {
519
-		if($this->wasRefreshed('quota')) {
519
+		if ($this->wasRefreshed('quota')) {
520 520
 			return;
521 521
 		}
522 522
 
523 523
 		$quotaAttribute = $this->connection->ldapQuotaAttribute;
524 524
 		$defaultQuota = $this->connection->ldapQuotaDefault;
525
-		if($quotaAttribute === '' && $defaultQuota === '') {
525
+		if ($quotaAttribute === '' && $defaultQuota === '') {
526 526
 			return;
527 527
 		}
528 528
 
529 529
 		$quota = false;
530
-		if(is_null($valueFromLDAP) && $quotaAttribute !== '') {
530
+		if (is_null($valueFromLDAP) && $quotaAttribute !== '') {
531 531
 			$aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);
532
-			if($aQuota && (count($aQuota) > 0) && $this->verifyQuotaValue($aQuota[0])) {
532
+			if ($aQuota && (count($aQuota) > 0) && $this->verifyQuotaValue($aQuota[0])) {
533 533
 				$quota = $aQuota[0];
534
-			} else if(is_array($aQuota) && isset($aQuota[0])) {
535
-				$this->log->log('no suitable LDAP quota found for user ' . $this->uid . ': [' . $aQuota[0] . ']', ILogger::DEBUG);
534
+			} else if (is_array($aQuota) && isset($aQuota[0])) {
535
+				$this->log->log('no suitable LDAP quota found for user '.$this->uid.': ['.$aQuota[0].']', ILogger::DEBUG);
536 536
 			}
537 537
 		} else if ($this->verifyQuotaValue($valueFromLDAP)) {
538 538
 			$quota = $valueFromLDAP;
539 539
 		} else {
540
-			$this->log->log('no suitable LDAP quota found for user ' . $this->uid . ': [' . $valueFromLDAP . ']', ILogger::DEBUG);
540
+			$this->log->log('no suitable LDAP quota found for user '.$this->uid.': ['.$valueFromLDAP.']', ILogger::DEBUG);
541 541
 		}
542 542
 
543 543
 		if ($quota === false && $this->verifyQuotaValue($defaultQuota)) {
544 544
 			// quota not found using the LDAP attribute (or not parseable). Try the default quota
545 545
 			$quota = $defaultQuota;
546
-		} else if($quota === false) {
547
-			$this->log->log('no suitable default quota found for user ' . $this->uid . ': [' . $defaultQuota . ']', ILogger::DEBUG);
546
+		} else if ($quota === false) {
547
+			$this->log->log('no suitable default quota found for user '.$this->uid.': ['.$defaultQuota.']', ILogger::DEBUG);
548 548
 			return;
549 549
 		}
550 550
 
@@ -552,7 +552,7 @@  discard block
 block discarded – undo
552 552
 		if ($targetUser instanceof IUser) {
553 553
 			$targetUser->setQuota($quota);
554 554
 		} else {
555
-			$this->log->log('trying to set a quota for user ' . $this->uid . ' but the user is missing', ILogger::INFO);
555
+			$this->log->log('trying to set a quota for user '.$this->uid.' but the user is missing', ILogger::INFO);
556 556
 		}
557 557
 	}
558 558
 
@@ -566,7 +566,7 @@  discard block
 block discarded – undo
566 566
 	 * @param array $params
567 567
 	 */
568 568
 	public function updateAvatarPostLogin($params) {
569
-		if(isset($params['uid']) && $params['uid'] === $this->getUsername()) {
569
+		if (isset($params['uid']) && $params['uid'] === $this->getUsername()) {
570 570
 			$this->updateAvatar();
571 571
 		}
572 572
 	}
@@ -576,15 +576,15 @@  discard block
 block discarded – undo
576 576
 	 * @return bool
577 577
 	 */
578 578
 	public function updateAvatar($force = false) {
579
-		if(!$force && $this->wasRefreshed('avatar')) {
579
+		if (!$force && $this->wasRefreshed('avatar')) {
580 580
 			return false;
581 581
 		}
582 582
 		$avatarImage = $this->getAvatarImage();
583
-		if($avatarImage === false) {
583
+		if ($avatarImage === false) {
584 584
 			//not set, nothing left to do;
585 585
 			return false;
586 586
 		}
587
-		if(!$this->image->loadFromBase64(base64_encode($avatarImage))) {
587
+		if (!$this->image->loadFromBase64(base64_encode($avatarImage))) {
588 588
 			return false;
589 589
 		}
590 590
 		return $this->setOwnCloudAvatar();
@@ -595,18 +595,18 @@  discard block
 block discarded – undo
595 595
 	 * @return bool
596 596
 	 */
597 597
 	private function setOwnCloudAvatar() {
598
-		if(!$this->image->valid()) {
598
+		if (!$this->image->valid()) {
599 599
 			$this->log->log('avatar image data from LDAP invalid for '.$this->dn, ILogger::ERROR);
600 600
 			return false;
601 601
 		}
602 602
 		//make sure it is a square and not bigger than 128x128
603 603
 		$size = min(array($this->image->width(), $this->image->height(), 128));
604
-		if(!$this->image->centerCrop($size)) {
604
+		if (!$this->image->centerCrop($size)) {
605 605
 			$this->log->log('croping image for avatar failed for '.$this->dn, ILogger::ERROR);
606 606
 			return false;
607 607
 		}
608 608
 
609
-		if(!$this->fs->isLoaded()) {
609
+		if (!$this->fs->isLoaded()) {
610 610
 			$this->fs->setup($this->uid);
611 611
 		}
612 612
 
@@ -616,7 +616,7 @@  discard block
 block discarded – undo
616 616
 			return true;
617 617
 		} catch (\Exception $e) {
618 618
 			\OC::$server->getLogger()->logException($e, [
619
-				'message' => 'Could not set avatar for ' . $this->dn,
619
+				'message' => 'Could not set avatar for '.$this->dn,
620 620
 				'level' => ILogger::INFO,
621 621
 				'app' => 'user_ldap',
622 622
 			]);
@@ -650,7 +650,7 @@  discard block
 block discarded – undo
650 650
 	 * @throws \OC\ServerNotAvailableException
651 651
 	 */
652 652
 	public function updateExtStorageHome(string $valueFromLDAP = null):string {
653
-		if($valueFromLDAP === null) {
653
+		if ($valueFromLDAP === null) {
654 654
 			$extHomeValues = $this->access->readAttribute($this->getDN(), $this->connection->ldapExtStorageHomeAttribute);
655 655
 		} else {
656 656
 			$extHomeValues = [$valueFromLDAP];
@@ -672,18 +672,18 @@  discard block
 block discarded – undo
672 672
 	 */
673 673
 	public function handlePasswordExpiry($params) {
674 674
 		$ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
675
-		if (empty($ppolicyDN) || ((int)$this->connection->turnOnPasswordChange !== 1)) {
676
-			return;//password expiry handling disabled
675
+		if (empty($ppolicyDN) || ((int) $this->connection->turnOnPasswordChange !== 1)) {
676
+			return; //password expiry handling disabled
677 677
 		}
678 678
 		$uid = $params['uid'];
679
-		if(isset($uid) && $uid === $this->getUsername()) {
679
+		if (isset($uid) && $uid === $this->getUsername()) {
680 680
 			//retrieve relevant user attributes
681 681
 			$result = $this->access->search('objectclass=*', array($this->dn), ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
682 682
 			
683
-			if(array_key_exists('pwdpolicysubentry', $result[0])) {
683
+			if (array_key_exists('pwdpolicysubentry', $result[0])) {
684 684
 				$pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
685
-				if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
686
-					$ppolicyDN = $pwdPolicySubentry[0];//custom ppolicy DN
685
+				if ($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)) {
686
+					$ppolicyDN = $pwdPolicySubentry[0]; //custom ppolicy DN
687 687
 				}
688 688
 			}
689 689
 			
@@ -692,9 +692,9 @@  discard block
 block discarded – undo
692 692
 			$pwdChangedTime = array_key_exists('pwdchangedtime', $result[0]) ? $result[0]['pwdchangedtime'] : null;
693 693
 			
694 694
 			//retrieve relevant password policy attributes
695
-			$cacheKey = 'ppolicyAttributes' . $ppolicyDN;
695
+			$cacheKey = 'ppolicyAttributes'.$ppolicyDN;
696 696
 			$result = $this->connection->getFromCache($cacheKey);
697
-			if(is_null($result)) {
697
+			if (is_null($result)) {
698 698
 				$result = $this->access->search('objectclass=*', array($ppolicyDN), ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
699 699
 				$this->connection->writeToCache($cacheKey, $result);
700 700
 			}
@@ -705,10 +705,10 @@  discard block
 block discarded – undo
705 705
 			
706 706
 			//handle grace login
707 707
 			$pwdGraceUseTimeCount = count($pwdGraceUseTime);
708
-			if($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
709
-				if($pwdGraceAuthNLimit 
708
+			if ($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
709
+				if ($pwdGraceAuthNLimit 
710 710
 					&& (count($pwdGraceAuthNLimit) > 0)
711
-					&&($pwdGraceUseTimeCount < (int)$pwdGraceAuthNLimit[0])) { //at least one more grace login available?
711
+					&&($pwdGraceUseTimeCount < (int) $pwdGraceAuthNLimit[0])) { //at least one more grace login available?
712 712
 					$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
713 713
 					header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
714 714
 					'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
@@ -719,24 +719,24 @@  discard block
 block discarded – undo
719 719
 				exit();
720 720
 			}
721 721
 			//handle pwdReset attribute
722
-			if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
722
+			if ($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
723 723
 				$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
724 724
 				header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
725 725
 				'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
726 726
 				exit();
727 727
 			}
728 728
 			//handle password expiry warning
729
-			if($pwdChangedTime && (count($pwdChangedTime) > 0)) {
730
-				if($pwdMaxAge && (count($pwdMaxAge) > 0)
729
+			if ($pwdChangedTime && (count($pwdChangedTime) > 0)) {
730
+				if ($pwdMaxAge && (count($pwdMaxAge) > 0)
731 731
 					&& $pwdExpireWarning && (count($pwdExpireWarning) > 0)) {
732
-					$pwdMaxAgeInt = (int)$pwdMaxAge[0];
733
-					$pwdExpireWarningInt = (int)$pwdExpireWarning[0];
734
-					if($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0){
732
+					$pwdMaxAgeInt = (int) $pwdMaxAge[0];
733
+					$pwdExpireWarningInt = (int) $pwdExpireWarning[0];
734
+					if ($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0) {
735 735
 						$pwdChangedTimeDt = \DateTime::createFromFormat('YmdHisZ', $pwdChangedTime[0]);
736 736
 						$pwdChangedTimeDt->add(new \DateInterval('PT'.$pwdMaxAgeInt.'S'));
737 737
 						$currentDateTime = new \DateTime();
738 738
 						$secondsToExpiry = $pwdChangedTimeDt->getTimestamp() - $currentDateTime->getTimestamp();
739
-						if($secondsToExpiry <= $pwdExpireWarningInt) {
739
+						if ($secondsToExpiry <= $pwdExpireWarningInt) {
740 740
 							//remove last password expiry warning if any
741 741
 							$notification = $this->notificationManager->createNotification();
742 742
 							$notification->setApp('user_ldap')
Please login to merge, or discard this patch.