Completed
Push — stable13 ( f5bbe2...486dff )
by Blizzz
21:41
created
apps/user_ldap/lib/User/User.php 2 patches
Indentation   +642 added lines, -642 removed lines patch added patch discarded remove patch
@@ -47,652 +47,652 @@
 block discarded – undo
47 47
  * represents an LDAP user, gets and holds user-specific information from LDAP
48 48
  */
49 49
 class User {
50
-	/**
51
-	 * @var IUserTools
52
-	 */
53
-	protected $access;
54
-	/**
55
-	 * @var Connection
56
-	 */
57
-	protected $connection;
58
-	/**
59
-	 * @var IConfig
60
-	 */
61
-	protected $config;
62
-	/**
63
-	 * @var FilesystemHelper
64
-	 */
65
-	protected $fs;
66
-	/**
67
-	 * @var Image
68
-	 */
69
-	protected $image;
70
-	/**
71
-	 * @var LogWrapper
72
-	 */
73
-	protected $log;
74
-	/**
75
-	 * @var IAvatarManager
76
-	 */
77
-	protected $avatarManager;
78
-	/**
79
-	 * @var IUserManager
80
-	 */
81
-	protected $userManager;
82
-	/**
83
-	 * @var INotificationManager
84
-	 */
85
-	protected $notificationManager;
86
-	/**
87
-	 * @var string
88
-	 */
89
-	protected $dn;
90
-	/**
91
-	 * @var string
92
-	 */
93
-	protected $uid;
94
-	/**
95
-	 * @var string[]
96
-	 */
97
-	protected $refreshedFeatures = array();
98
-	/**
99
-	 * @var string
100
-	 */
101
-	protected $avatarImage;
102
-
103
-	/**
104
-	 * DB config keys for user preferences
105
-	 */
106
-	const USER_PREFKEY_FIRSTLOGIN  = 'firstLoginAccomplished';
107
-	const USER_PREFKEY_LASTREFRESH = 'lastFeatureRefresh';
108
-
109
-	/**
110
-	 * @brief constructor, make sure the subclasses call this one!
111
-	 * @param string $username the internal username
112
-	 * @param string $dn the LDAP DN
113
-	 * @param IUserTools $access an instance that implements IUserTools for
114
-	 * LDAP interaction
115
-	 * @param IConfig $config
116
-	 * @param FilesystemHelper $fs
117
-	 * @param Image $image any empty instance
118
-	 * @param LogWrapper $log
119
-	 * @param IAvatarManager $avatarManager
120
-	 * @param IUserManager $userManager
121
-	 * @param INotificationManager $notificationManager
122
-	 */
123
-	public function __construct($username, $dn, IUserTools $access,
124
-		IConfig $config, FilesystemHelper $fs, Image $image,
125
-		LogWrapper $log, IAvatarManager $avatarManager, IUserManager $userManager,
126
-		INotificationManager $notificationManager) {
50
+    /**
51
+     * @var IUserTools
52
+     */
53
+    protected $access;
54
+    /**
55
+     * @var Connection
56
+     */
57
+    protected $connection;
58
+    /**
59
+     * @var IConfig
60
+     */
61
+    protected $config;
62
+    /**
63
+     * @var FilesystemHelper
64
+     */
65
+    protected $fs;
66
+    /**
67
+     * @var Image
68
+     */
69
+    protected $image;
70
+    /**
71
+     * @var LogWrapper
72
+     */
73
+    protected $log;
74
+    /**
75
+     * @var IAvatarManager
76
+     */
77
+    protected $avatarManager;
78
+    /**
79
+     * @var IUserManager
80
+     */
81
+    protected $userManager;
82
+    /**
83
+     * @var INotificationManager
84
+     */
85
+    protected $notificationManager;
86
+    /**
87
+     * @var string
88
+     */
89
+    protected $dn;
90
+    /**
91
+     * @var string
92
+     */
93
+    protected $uid;
94
+    /**
95
+     * @var string[]
96
+     */
97
+    protected $refreshedFeatures = array();
98
+    /**
99
+     * @var string
100
+     */
101
+    protected $avatarImage;
102
+
103
+    /**
104
+     * DB config keys for user preferences
105
+     */
106
+    const USER_PREFKEY_FIRSTLOGIN  = 'firstLoginAccomplished';
107
+    const USER_PREFKEY_LASTREFRESH = 'lastFeatureRefresh';
108
+
109
+    /**
110
+     * @brief constructor, make sure the subclasses call this one!
111
+     * @param string $username the internal username
112
+     * @param string $dn the LDAP DN
113
+     * @param IUserTools $access an instance that implements IUserTools for
114
+     * LDAP interaction
115
+     * @param IConfig $config
116
+     * @param FilesystemHelper $fs
117
+     * @param Image $image any empty instance
118
+     * @param LogWrapper $log
119
+     * @param IAvatarManager $avatarManager
120
+     * @param IUserManager $userManager
121
+     * @param INotificationManager $notificationManager
122
+     */
123
+    public function __construct($username, $dn, IUserTools $access,
124
+        IConfig $config, FilesystemHelper $fs, Image $image,
125
+        LogWrapper $log, IAvatarManager $avatarManager, IUserManager $userManager,
126
+        INotificationManager $notificationManager) {
127 127
 	
128
-		if ($username === null) {
129
-			$log->log("uid for '$dn' must not be null!", Util::ERROR);
130
-			throw new \InvalidArgumentException('uid must not be null!');
131
-		} else if ($username === '') {
132
-			$log->log("uid for '$dn' must not be an empty string", Util::ERROR);
133
-			throw new \InvalidArgumentException('uid must not be an empty string!');
134
-		}
135
-
136
-		$this->access              = $access;
137
-		$this->connection          = $access->getConnection();
138
-		$this->config              = $config;
139
-		$this->fs                  = $fs;
140
-		$this->dn                  = $dn;
141
-		$this->uid                 = $username;
142
-		$this->image               = $image;
143
-		$this->log                 = $log;
144
-		$this->avatarManager       = $avatarManager;
145
-		$this->userManager         = $userManager;
146
-		$this->notificationManager = $notificationManager;
147
-
148
-		Util::connectHook('OC_User', 'post_login', $this, 'handlePasswordExpiry');
149
-	}
150
-
151
-	/**
152
-	 * @brief updates properties like email, quota or avatar provided by LDAP
153
-	 * @return null
154
-	 */
155
-	public function update() {
156
-		if(is_null($this->dn)) {
157
-			return null;
158
-		}
159
-
160
-		$hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap',
161
-				self::USER_PREFKEY_FIRSTLOGIN, 0);
162
-
163
-		if($this->needsRefresh()) {
164
-			$this->updateEmail();
165
-			$this->updateQuota();
166
-			if($hasLoggedIn !== 0) {
167
-				//we do not need to try it, when the user has not been logged in
168
-				//before, because the file system will not be ready.
169
-				$this->updateAvatar();
170
-				//in order to get an avatar as soon as possible, mark the user
171
-				//as refreshed only when updating the avatar did happen
172
-				$this->markRefreshTime();
173
-			}
174
-		}
175
-	}
176
-
177
-	/**
178
-	 * processes results from LDAP for attributes as returned by getAttributesToRead()
179
-	 * @param array $ldapEntry the user entry as retrieved from LDAP
180
-	 */
181
-	public function processAttributes($ldapEntry) {
182
-		$this->markRefreshTime();
183
-		//Quota
184
-		$attr = strtolower($this->connection->ldapQuotaAttribute);
185
-		if(isset($ldapEntry[$attr])) {
186
-			$this->updateQuota($ldapEntry[$attr][0]);
187
-		} else {
188
-			if ($this->connection->ldapQuotaDefault !== '') {
189
-				$this->updateQuota();
190
-			}
191
-		}
192
-		unset($attr);
193
-
194
-		//displayName
195
-		$displayName = $displayName2 = '';
196
-		$attr = strtolower($this->connection->ldapUserDisplayName);
197
-		if(isset($ldapEntry[$attr])) {
198
-			$displayName = strval($ldapEntry[$attr][0]);
199
-		}
200
-		$attr = strtolower($this->connection->ldapUserDisplayName2);
201
-		if(isset($ldapEntry[$attr])) {
202
-			$displayName2 = strval($ldapEntry[$attr][0]);
203
-		}
204
-		if ($displayName !== '') {
205
-			$this->composeAndStoreDisplayName($displayName);
206
-			$this->access->cacheUserDisplayName(
207
-				$this->getUsername(),
208
-				$displayName,
209
-				$displayName2
210
-			);
211
-		}
212
-		unset($attr);
213
-
214
-		//Email
215
-		//email must be stored after displayname, because it would cause a user
216
-		//change event that will trigger fetching the display name again
217
-		$attr = strtolower($this->connection->ldapEmailAttribute);
218
-		if(isset($ldapEntry[$attr])) {
219
-			$this->updateEmail($ldapEntry[$attr][0]);
220
-		}
221
-		unset($attr);
222
-
223
-		// LDAP Username, needed for s2s sharing
224
-		if(isset($ldapEntry['uid'])) {
225
-			$this->storeLDAPUserName($ldapEntry['uid'][0]);
226
-		} else if(isset($ldapEntry['samaccountname'])) {
227
-			$this->storeLDAPUserName($ldapEntry['samaccountname'][0]);
228
-		}
229
-
230
-		//homePath
231
-		if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
232
-			$attr = strtolower(substr($this->connection->homeFolderNamingRule, strlen('attr:')));
233
-			if(isset($ldapEntry[$attr])) {
234
-				$this->access->cacheUserHome(
235
-					$this->getUsername(), $this->getHomePath($ldapEntry[$attr][0]));
236
-			}
237
-		}
238
-
239
-		//memberOf groups
240
-		$cacheKey = 'getMemberOf'.$this->getUsername();
241
-		$groups = false;
242
-		if(isset($ldapEntry['memberof'])) {
243
-			$groups = $ldapEntry['memberof'];
244
-		}
245
-		$this->connection->writeToCache($cacheKey, $groups);
246
-
247
-		//Avatar
248
-		$attrs = array('jpegphoto', 'thumbnailphoto');
249
-		foreach ($attrs as $attr)  {
250
-			if(isset($ldapEntry[$attr])) {
251
-				$this->avatarImage = $ldapEntry[$attr][0];
252
-				// the call to the method that saves the avatar in the file
253
-				// system must be postponed after the login. It is to ensure
254
-				// external mounts are mounted properly (e.g. with login
255
-				// credentials from the session).
256
-				Util::connectHook('OC_User', 'post_login', $this, 'updateAvatarPostLogin');
257
-				break;
258
-			}
259
-		}
260
-	}
261
-
262
-	/**
263
-	 * @brief returns the LDAP DN of the user
264
-	 * @return string
265
-	 */
266
-	public function getDN() {
267
-		return $this->dn;
268
-	}
269
-
270
-	/**
271
-	 * @brief returns the Nextcloud internal username of the user
272
-	 * @return string
273
-	 */
274
-	public function getUsername() {
275
-		return $this->uid;
276
-	}
277
-
278
-	/**
279
-	 * returns the home directory of the user if specified by LDAP settings
280
-	 * @param string $valueFromLDAP
281
-	 * @return bool|string
282
-	 * @throws \Exception
283
-	 */
284
-	public function getHomePath($valueFromLDAP = null) {
285
-		$path = strval($valueFromLDAP);
286
-		$attr = null;
287
-
288
-		if (is_null($valueFromLDAP)
289
-		   && strpos($this->access->connection->homeFolderNamingRule, 'attr:') === 0
290
-		   && $this->access->connection->homeFolderNamingRule !== 'attr:')
291
-		{
292
-			$attr = substr($this->access->connection->homeFolderNamingRule, strlen('attr:'));
293
-			$homedir = $this->access->readAttribute(
294
-				$this->access->username2dn($this->getUsername()), $attr);
295
-			if ($homedir && isset($homedir[0])) {
296
-				$path = $homedir[0];
297
-			}
298
-		}
299
-
300
-		if ($path !== '') {
301
-			//if attribute's value is an absolute path take this, otherwise append it to data dir
302
-			//check for / at the beginning or pattern c:\ resp. c:/
303
-			if(   '/' !== $path[0]
304
-			   && !(3 < strlen($path) && ctype_alpha($path[0])
305
-			       && $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))
306
-			) {
307
-				$path = $this->config->getSystemValue('datadirectory',
308
-						\OC::$SERVERROOT.'/data' ) . '/' . $path;
309
-			}
310
-			//we need it to store it in the DB as well in case a user gets
311
-			//deleted so we can clean up afterwards
312
-			$this->config->setUserValue(
313
-				$this->getUsername(), 'user_ldap', 'homePath', $path
314
-			);
315
-			return $path;
316
-		}
317
-
318
-		if(    !is_null($attr)
319
-			&& $this->config->getAppValue('user_ldap', 'enforce_home_folder_naming_rule', true)
320
-		) {
321
-			// a naming rule attribute is defined, but it doesn't exist for that LDAP user
322
-			throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: ' . $this->getUsername());
323
-		}
324
-
325
-		//false will apply default behaviour as defined and done by OC_User
326
-		$this->config->setUserValue($this->getUsername(), 'user_ldap', 'homePath', '');
327
-		return false;
328
-	}
329
-
330
-	public function getMemberOfGroups() {
331
-		$cacheKey = 'getMemberOf'.$this->getUsername();
332
-		$memberOfGroups = $this->connection->getFromCache($cacheKey);
333
-		if(!is_null($memberOfGroups)) {
334
-			return $memberOfGroups;
335
-		}
336
-		$groupDNs = $this->access->readAttribute($this->getDN(), 'memberOf');
337
-		$this->connection->writeToCache($cacheKey, $groupDNs);
338
-		return $groupDNs;
339
-	}
340
-
341
-	/**
342
-	 * @brief reads the image from LDAP that shall be used as Avatar
343
-	 * @return string data (provided by LDAP) | false
344
-	 */
345
-	public function getAvatarImage() {
346
-		if(!is_null($this->avatarImage)) {
347
-			return $this->avatarImage;
348
-		}
349
-
350
-		$this->avatarImage = false;
351
-		$attributes = array('jpegPhoto', 'thumbnailPhoto');
352
-		foreach($attributes as $attribute) {
353
-			$result = $this->access->readAttribute($this->dn, $attribute);
354
-			if($result !== false && is_array($result) && isset($result[0])) {
355
-				$this->avatarImage = $result[0];
356
-				break;
357
-			}
358
-		}
359
-
360
-		return $this->avatarImage;
361
-	}
362
-
363
-	/**
364
-	 * @brief marks the user as having logged in at least once
365
-	 * @return null
366
-	 */
367
-	public function markLogin() {
368
-		$this->config->setUserValue(
369
-			$this->uid, 'user_ldap', self::USER_PREFKEY_FIRSTLOGIN, 1);
370
-	}
371
-
372
-	/**
373
-	 * @brief marks the time when user features like email have been updated
374
-	 * @return null
375
-	 */
376
-	public function markRefreshTime() {
377
-		$this->config->setUserValue(
378
-			$this->uid, 'user_ldap', self::USER_PREFKEY_LASTREFRESH, time());
379
-	}
380
-
381
-	/**
382
-	 * @brief checks whether user features needs to be updated again by
383
-	 * comparing the difference of time of the last refresh to now with the
384
-	 * desired interval
385
-	 * @return bool
386
-	 */
387
-	private function needsRefresh() {
388
-		$lastChecked = $this->config->getUserValue($this->uid, 'user_ldap',
389
-			self::USER_PREFKEY_LASTREFRESH, 0);
390
-
391
-		if((time() - intval($lastChecked)) < intval($this->config->getAppValue('user_ldap', 'updateAttributesInterval', 86400)) ) {
392
-			return false;
393
-		}
394
-		return  true;
395
-	}
396
-
397
-	/**
398
-	 * Stores a key-value pair in relation to this user
399
-	 *
400
-	 * @param string $key
401
-	 * @param string $value
402
-	 */
403
-	private function store($key, $value) {
404
-		$this->config->setUserValue($this->uid, 'user_ldap', $key, $value);
405
-	}
406
-
407
-	/**
408
-	 * Composes the display name and stores it in the database. The final
409
-	 * display name is returned.
410
-	 *
411
-	 * @param string $displayName
412
-	 * @param string $displayName2
413
-	 * @returns string the effective display name
414
-	 */
415
-	public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
416
-		$displayName2 = strval($displayName2);
417
-		if($displayName2 !== '') {
418
-			$displayName .= ' (' . $displayName2 . ')';
419
-		}
420
-		$this->store('displayName', $displayName);
421
-		return $displayName;
422
-	}
423
-
424
-	/**
425
-	 * Stores the LDAP Username in the Database
426
-	 * @param string $userName
427
-	 */
428
-	public function storeLDAPUserName($userName) {
429
-		$this->store('uid', $userName);
430
-	}
431
-
432
-	/**
433
-	 * @brief checks whether an update method specified by feature was run
434
-	 * already. If not, it will marked like this, because it is expected that
435
-	 * the method will be run, when false is returned.
436
-	 * @param string $feature email | quota | avatar (can be extended)
437
-	 * @return bool
438
-	 */
439
-	private function wasRefreshed($feature) {
440
-		if(isset($this->refreshedFeatures[$feature])) {
441
-			return true;
442
-		}
443
-		$this->refreshedFeatures[$feature] = 1;
444
-		return false;
445
-	}
446
-
447
-	/**
448
-	 * fetches the email from LDAP and stores it as Nextcloud user value
449
-	 * @param string $valueFromLDAP if known, to save an LDAP read request
450
-	 * @return null
451
-	 */
452
-	public function updateEmail($valueFromLDAP = null) {
453
-		if($this->wasRefreshed('email')) {
454
-			return;
455
-		}
456
-		$email = strval($valueFromLDAP);
457
-		if(is_null($valueFromLDAP)) {
458
-			$emailAttribute = $this->connection->ldapEmailAttribute;
459
-			if ($emailAttribute !== '') {
460
-				$aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
461
-				if(is_array($aEmail) && (count($aEmail) > 0)) {
462
-					$email = strval($aEmail[0]);
463
-				}
464
-			}
465
-		}
466
-		if ($email !== '') {
467
-			$user = $this->userManager->get($this->uid);
468
-			if (!is_null($user)) {
469
-				$currentEmail = strval($user->getEMailAddress());
470
-				if ($currentEmail !== $email) {
471
-					$user->setEMailAddress($email);
472
-				}
473
-			}
474
-		}
475
-	}
476
-
477
-	/**
478
-	 * Overall process goes as follow:
479
-	 * 1. fetch the quota from LDAP and check if it's parseable with the "verifyQuotaValue" function
480
-	 * 2. if the value can't be fetched, is empty or not parseable, use the default LDAP quota
481
-	 * 3. if the default LDAP quota can't be parsed, use the Nextcloud's default quota (use 'default')
482
-	 * 4. check if the target user exists and set the quota for the user.
483
-	 *
484
-	 * In order to improve performance and prevent an unwanted extra LDAP call, the $valueFromLDAP
485
-	 * parameter can be passed with the value of the attribute. This value will be considered as the
486
-	 * quota for the user coming from the LDAP server (step 1 of the process) It can be useful to
487
-	 * fetch all the user's attributes in one call and use the fetched values in this function.
488
-	 * The expected value for that parameter is a string describing the quota for the user. Valid
489
-	 * values are 'none' (unlimited), 'default' (the Nextcloud's default quota), '1234' (quota in
490
-	 * bytes), '1234 MB' (quota in MB - check the \OC_Helper::computerFileSize method for more info)
491
-	 *
492
-	 * fetches the quota from LDAP and stores it as Nextcloud user value
493
-	 * @param string $valueFromLDAP the quota attribute's value can be passed,
494
-	 * to save the readAttribute request
495
-	 * @return null
496
-	 */
497
-	public function updateQuota($valueFromLDAP = null) {
498
-		if($this->wasRefreshed('quota')) {
499
-			return;
500
-		}
501
-
502
-		$quotaAttribute = $this->connection->ldapQuotaAttribute;
503
-		$defaultQuota = $this->connection->ldapQuotaDefault;
504
-		if($quotaAttribute === '' && $defaultQuota === '') {
505
-			return;
506
-		}
507
-
508
-		$quota = false;
509
-		if(is_null($valueFromLDAP) && $quotaAttribute !== '') {
510
-			$aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);
511
-			if($aQuota && (count($aQuota) > 0) && $this->verifyQuotaValue($aQuota[0])) {
512
-				$quota = $aQuota[0];
513
-			} else if(is_array($aQuota) && isset($aQuota[0])) {
514
-				$this->log->log('no suitable LDAP quota found for user ' . $this->uid . ': [' . $aQuota[0] . ']', Util::DEBUG);
515
-			}
516
-		} else if ($this->verifyQuotaValue($valueFromLDAP)) {
517
-			$quota = $valueFromLDAP;
518
-		} else {
519
-			$this->log->log('no suitable LDAP quota found for user ' . $this->uid . ': [' . $valueFromLDAP . ']', Util::DEBUG);
520
-		}
521
-
522
-		if ($quota === false && $this->verifyQuotaValue($defaultQuota)) {
523
-			// quota not found using the LDAP attribute (or not parseable). Try the default quota
524
-			$quota = $defaultQuota;
525
-		} else if($quota === false) {
526
-			$this->log->log('no suitable default quota found for user ' . $this->uid . ': [' . $defaultQuota . ']', Util::DEBUG);
527
-			return;
528
-		}
529
-
530
-		$targetUser = $this->userManager->get($this->uid);
531
-		if ($targetUser instanceof IUser) {
532
-			$targetUser->setQuota($quota);
533
-		} else {
534
-			$this->log->log('trying to set a quota for user ' . $this->uid . ' but the user is missing', Util::INFO);
535
-		}
536
-	}
537
-
538
-	private function verifyQuotaValue($quotaValue) {
539
-		return $quotaValue === 'none' || $quotaValue === 'default' || \OC_Helper::computerFileSize($quotaValue) !== false;
540
-	}
541
-
542
-	/**
543
-	 * called by a post_login hook to save the avatar picture
544
-	 *
545
-	 * @param array $params
546
-	 */
547
-	public function updateAvatarPostLogin($params) {
548
-		if(isset($params['uid']) && $params['uid'] === $this->getUsername()) {
549
-			$this->updateAvatar();
550
-		}
551
-	}
552
-
553
-	/**
554
-	 * @brief attempts to get an image from LDAP and sets it as Nextcloud avatar
555
-	 * @return bool
556
-	 */
557
-	public function updateAvatar($force = false) {
558
-		if(!$force && $this->wasRefreshed('avatar')) {
559
-			return false;
560
-		}
561
-		$avatarImage = $this->getAvatarImage();
562
-		if($avatarImage === false) {
563
-			//not set, nothing left to do;
564
-			return false;
565
-		}
566
-		if(!$this->image->loadFromBase64(base64_encode($avatarImage))) {
567
-			return false;
568
-		}
569
-		return $this->setOwnCloudAvatar();
570
-	}
571
-
572
-	/**
573
-	 * @brief sets an image as Nextcloud avatar
574
-	 * @return bool
575
-	 */
576
-	private function setOwnCloudAvatar() {
577
-		if(!$this->image->valid()) {
578
-			$this->log->log('jpegPhoto data invalid for '.$this->dn, Util::ERROR);
579
-			return false;
580
-		}
581
-		//make sure it is a square and not bigger than 128x128
582
-		$size = min(array($this->image->width(), $this->image->height(), 128));
583
-		if(!$this->image->centerCrop($size)) {
584
-			$this->log->log('croping image for avatar failed for '.$this->dn, Util::ERROR);
585
-			return false;
586
-		}
587
-
588
-		if(!$this->fs->isLoaded()) {
589
-			$this->fs->setup($this->uid);
590
-		}
591
-
592
-		try {
593
-			$avatar = $this->avatarManager->getAvatar($this->uid);
594
-			$avatar->set($this->image);
595
-			return true;
596
-		} catch (\Exception $e) {
597
-			\OC::$server->getLogger()->notice(
598
-				'Could not set avatar for ' . $this->dn	. ', because: ' . $e->getMessage(),
599
-				['app' => 'user_ldap']);
600
-		}
601
-		return false;
602
-	}
603
-
604
-	/**
605
-	 * called by a post_login hook to handle password expiry
606
-	 *
607
-	 * @param array $params
608
-	 */
609
-	public function handlePasswordExpiry($params) {
610
-		$ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
611
-		if (empty($ppolicyDN) || (intval($this->connection->turnOnPasswordChange) !== 1)) {
612
-			return;//password expiry handling disabled
613
-		}
614
-		$uid = $params['uid'];
615
-		if(isset($uid) && $uid === $this->getUsername()) {
616
-			//retrieve relevant user attributes
617
-			$result = $this->access->search('objectclass=*', array($this->dn), ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
128
+        if ($username === null) {
129
+            $log->log("uid for '$dn' must not be null!", Util::ERROR);
130
+            throw new \InvalidArgumentException('uid must not be null!');
131
+        } else if ($username === '') {
132
+            $log->log("uid for '$dn' must not be an empty string", Util::ERROR);
133
+            throw new \InvalidArgumentException('uid must not be an empty string!');
134
+        }
135
+
136
+        $this->access              = $access;
137
+        $this->connection          = $access->getConnection();
138
+        $this->config              = $config;
139
+        $this->fs                  = $fs;
140
+        $this->dn                  = $dn;
141
+        $this->uid                 = $username;
142
+        $this->image               = $image;
143
+        $this->log                 = $log;
144
+        $this->avatarManager       = $avatarManager;
145
+        $this->userManager         = $userManager;
146
+        $this->notificationManager = $notificationManager;
147
+
148
+        Util::connectHook('OC_User', 'post_login', $this, 'handlePasswordExpiry');
149
+    }
150
+
151
+    /**
152
+     * @brief updates properties like email, quota or avatar provided by LDAP
153
+     * @return null
154
+     */
155
+    public function update() {
156
+        if(is_null($this->dn)) {
157
+            return null;
158
+        }
159
+
160
+        $hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap',
161
+                self::USER_PREFKEY_FIRSTLOGIN, 0);
162
+
163
+        if($this->needsRefresh()) {
164
+            $this->updateEmail();
165
+            $this->updateQuota();
166
+            if($hasLoggedIn !== 0) {
167
+                //we do not need to try it, when the user has not been logged in
168
+                //before, because the file system will not be ready.
169
+                $this->updateAvatar();
170
+                //in order to get an avatar as soon as possible, mark the user
171
+                //as refreshed only when updating the avatar did happen
172
+                $this->markRefreshTime();
173
+            }
174
+        }
175
+    }
176
+
177
+    /**
178
+     * processes results from LDAP for attributes as returned by getAttributesToRead()
179
+     * @param array $ldapEntry the user entry as retrieved from LDAP
180
+     */
181
+    public function processAttributes($ldapEntry) {
182
+        $this->markRefreshTime();
183
+        //Quota
184
+        $attr = strtolower($this->connection->ldapQuotaAttribute);
185
+        if(isset($ldapEntry[$attr])) {
186
+            $this->updateQuota($ldapEntry[$attr][0]);
187
+        } else {
188
+            if ($this->connection->ldapQuotaDefault !== '') {
189
+                $this->updateQuota();
190
+            }
191
+        }
192
+        unset($attr);
193
+
194
+        //displayName
195
+        $displayName = $displayName2 = '';
196
+        $attr = strtolower($this->connection->ldapUserDisplayName);
197
+        if(isset($ldapEntry[$attr])) {
198
+            $displayName = strval($ldapEntry[$attr][0]);
199
+        }
200
+        $attr = strtolower($this->connection->ldapUserDisplayName2);
201
+        if(isset($ldapEntry[$attr])) {
202
+            $displayName2 = strval($ldapEntry[$attr][0]);
203
+        }
204
+        if ($displayName !== '') {
205
+            $this->composeAndStoreDisplayName($displayName);
206
+            $this->access->cacheUserDisplayName(
207
+                $this->getUsername(),
208
+                $displayName,
209
+                $displayName2
210
+            );
211
+        }
212
+        unset($attr);
213
+
214
+        //Email
215
+        //email must be stored after displayname, because it would cause a user
216
+        //change event that will trigger fetching the display name again
217
+        $attr = strtolower($this->connection->ldapEmailAttribute);
218
+        if(isset($ldapEntry[$attr])) {
219
+            $this->updateEmail($ldapEntry[$attr][0]);
220
+        }
221
+        unset($attr);
222
+
223
+        // LDAP Username, needed for s2s sharing
224
+        if(isset($ldapEntry['uid'])) {
225
+            $this->storeLDAPUserName($ldapEntry['uid'][0]);
226
+        } else if(isset($ldapEntry['samaccountname'])) {
227
+            $this->storeLDAPUserName($ldapEntry['samaccountname'][0]);
228
+        }
229
+
230
+        //homePath
231
+        if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
232
+            $attr = strtolower(substr($this->connection->homeFolderNamingRule, strlen('attr:')));
233
+            if(isset($ldapEntry[$attr])) {
234
+                $this->access->cacheUserHome(
235
+                    $this->getUsername(), $this->getHomePath($ldapEntry[$attr][0]));
236
+            }
237
+        }
238
+
239
+        //memberOf groups
240
+        $cacheKey = 'getMemberOf'.$this->getUsername();
241
+        $groups = false;
242
+        if(isset($ldapEntry['memberof'])) {
243
+            $groups = $ldapEntry['memberof'];
244
+        }
245
+        $this->connection->writeToCache($cacheKey, $groups);
246
+
247
+        //Avatar
248
+        $attrs = array('jpegphoto', 'thumbnailphoto');
249
+        foreach ($attrs as $attr)  {
250
+            if(isset($ldapEntry[$attr])) {
251
+                $this->avatarImage = $ldapEntry[$attr][0];
252
+                // the call to the method that saves the avatar in the file
253
+                // system must be postponed after the login. It is to ensure
254
+                // external mounts are mounted properly (e.g. with login
255
+                // credentials from the session).
256
+                Util::connectHook('OC_User', 'post_login', $this, 'updateAvatarPostLogin');
257
+                break;
258
+            }
259
+        }
260
+    }
261
+
262
+    /**
263
+     * @brief returns the LDAP DN of the user
264
+     * @return string
265
+     */
266
+    public function getDN() {
267
+        return $this->dn;
268
+    }
269
+
270
+    /**
271
+     * @brief returns the Nextcloud internal username of the user
272
+     * @return string
273
+     */
274
+    public function getUsername() {
275
+        return $this->uid;
276
+    }
277
+
278
+    /**
279
+     * returns the home directory of the user if specified by LDAP settings
280
+     * @param string $valueFromLDAP
281
+     * @return bool|string
282
+     * @throws \Exception
283
+     */
284
+    public function getHomePath($valueFromLDAP = null) {
285
+        $path = strval($valueFromLDAP);
286
+        $attr = null;
287
+
288
+        if (is_null($valueFromLDAP)
289
+           && strpos($this->access->connection->homeFolderNamingRule, 'attr:') === 0
290
+           && $this->access->connection->homeFolderNamingRule !== 'attr:')
291
+        {
292
+            $attr = substr($this->access->connection->homeFolderNamingRule, strlen('attr:'));
293
+            $homedir = $this->access->readAttribute(
294
+                $this->access->username2dn($this->getUsername()), $attr);
295
+            if ($homedir && isset($homedir[0])) {
296
+                $path = $homedir[0];
297
+            }
298
+        }
299
+
300
+        if ($path !== '') {
301
+            //if attribute's value is an absolute path take this, otherwise append it to data dir
302
+            //check for / at the beginning or pattern c:\ resp. c:/
303
+            if(   '/' !== $path[0]
304
+               && !(3 < strlen($path) && ctype_alpha($path[0])
305
+                   && $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))
306
+            ) {
307
+                $path = $this->config->getSystemValue('datadirectory',
308
+                        \OC::$SERVERROOT.'/data' ) . '/' . $path;
309
+            }
310
+            //we need it to store it in the DB as well in case a user gets
311
+            //deleted so we can clean up afterwards
312
+            $this->config->setUserValue(
313
+                $this->getUsername(), 'user_ldap', 'homePath', $path
314
+            );
315
+            return $path;
316
+        }
317
+
318
+        if(    !is_null($attr)
319
+            && $this->config->getAppValue('user_ldap', 'enforce_home_folder_naming_rule', true)
320
+        ) {
321
+            // a naming rule attribute is defined, but it doesn't exist for that LDAP user
322
+            throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: ' . $this->getUsername());
323
+        }
324
+
325
+        //false will apply default behaviour as defined and done by OC_User
326
+        $this->config->setUserValue($this->getUsername(), 'user_ldap', 'homePath', '');
327
+        return false;
328
+    }
329
+
330
+    public function getMemberOfGroups() {
331
+        $cacheKey = 'getMemberOf'.$this->getUsername();
332
+        $memberOfGroups = $this->connection->getFromCache($cacheKey);
333
+        if(!is_null($memberOfGroups)) {
334
+            return $memberOfGroups;
335
+        }
336
+        $groupDNs = $this->access->readAttribute($this->getDN(), 'memberOf');
337
+        $this->connection->writeToCache($cacheKey, $groupDNs);
338
+        return $groupDNs;
339
+    }
340
+
341
+    /**
342
+     * @brief reads the image from LDAP that shall be used as Avatar
343
+     * @return string data (provided by LDAP) | false
344
+     */
345
+    public function getAvatarImage() {
346
+        if(!is_null($this->avatarImage)) {
347
+            return $this->avatarImage;
348
+        }
349
+
350
+        $this->avatarImage = false;
351
+        $attributes = array('jpegPhoto', 'thumbnailPhoto');
352
+        foreach($attributes as $attribute) {
353
+            $result = $this->access->readAttribute($this->dn, $attribute);
354
+            if($result !== false && is_array($result) && isset($result[0])) {
355
+                $this->avatarImage = $result[0];
356
+                break;
357
+            }
358
+        }
359
+
360
+        return $this->avatarImage;
361
+    }
362
+
363
+    /**
364
+     * @brief marks the user as having logged in at least once
365
+     * @return null
366
+     */
367
+    public function markLogin() {
368
+        $this->config->setUserValue(
369
+            $this->uid, 'user_ldap', self::USER_PREFKEY_FIRSTLOGIN, 1);
370
+    }
371
+
372
+    /**
373
+     * @brief marks the time when user features like email have been updated
374
+     * @return null
375
+     */
376
+    public function markRefreshTime() {
377
+        $this->config->setUserValue(
378
+            $this->uid, 'user_ldap', self::USER_PREFKEY_LASTREFRESH, time());
379
+    }
380
+
381
+    /**
382
+     * @brief checks whether user features needs to be updated again by
383
+     * comparing the difference of time of the last refresh to now with the
384
+     * desired interval
385
+     * @return bool
386
+     */
387
+    private function needsRefresh() {
388
+        $lastChecked = $this->config->getUserValue($this->uid, 'user_ldap',
389
+            self::USER_PREFKEY_LASTREFRESH, 0);
390
+
391
+        if((time() - intval($lastChecked)) < intval($this->config->getAppValue('user_ldap', 'updateAttributesInterval', 86400)) ) {
392
+            return false;
393
+        }
394
+        return  true;
395
+    }
396
+
397
+    /**
398
+     * Stores a key-value pair in relation to this user
399
+     *
400
+     * @param string $key
401
+     * @param string $value
402
+     */
403
+    private function store($key, $value) {
404
+        $this->config->setUserValue($this->uid, 'user_ldap', $key, $value);
405
+    }
406
+
407
+    /**
408
+     * Composes the display name and stores it in the database. The final
409
+     * display name is returned.
410
+     *
411
+     * @param string $displayName
412
+     * @param string $displayName2
413
+     * @returns string the effective display name
414
+     */
415
+    public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
416
+        $displayName2 = strval($displayName2);
417
+        if($displayName2 !== '') {
418
+            $displayName .= ' (' . $displayName2 . ')';
419
+        }
420
+        $this->store('displayName', $displayName);
421
+        return $displayName;
422
+    }
423
+
424
+    /**
425
+     * Stores the LDAP Username in the Database
426
+     * @param string $userName
427
+     */
428
+    public function storeLDAPUserName($userName) {
429
+        $this->store('uid', $userName);
430
+    }
431
+
432
+    /**
433
+     * @brief checks whether an update method specified by feature was run
434
+     * already. If not, it will marked like this, because it is expected that
435
+     * the method will be run, when false is returned.
436
+     * @param string $feature email | quota | avatar (can be extended)
437
+     * @return bool
438
+     */
439
+    private function wasRefreshed($feature) {
440
+        if(isset($this->refreshedFeatures[$feature])) {
441
+            return true;
442
+        }
443
+        $this->refreshedFeatures[$feature] = 1;
444
+        return false;
445
+    }
446
+
447
+    /**
448
+     * fetches the email from LDAP and stores it as Nextcloud user value
449
+     * @param string $valueFromLDAP if known, to save an LDAP read request
450
+     * @return null
451
+     */
452
+    public function updateEmail($valueFromLDAP = null) {
453
+        if($this->wasRefreshed('email')) {
454
+            return;
455
+        }
456
+        $email = strval($valueFromLDAP);
457
+        if(is_null($valueFromLDAP)) {
458
+            $emailAttribute = $this->connection->ldapEmailAttribute;
459
+            if ($emailAttribute !== '') {
460
+                $aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
461
+                if(is_array($aEmail) && (count($aEmail) > 0)) {
462
+                    $email = strval($aEmail[0]);
463
+                }
464
+            }
465
+        }
466
+        if ($email !== '') {
467
+            $user = $this->userManager->get($this->uid);
468
+            if (!is_null($user)) {
469
+                $currentEmail = strval($user->getEMailAddress());
470
+                if ($currentEmail !== $email) {
471
+                    $user->setEMailAddress($email);
472
+                }
473
+            }
474
+        }
475
+    }
476
+
477
+    /**
478
+     * Overall process goes as follow:
479
+     * 1. fetch the quota from LDAP and check if it's parseable with the "verifyQuotaValue" function
480
+     * 2. if the value can't be fetched, is empty or not parseable, use the default LDAP quota
481
+     * 3. if the default LDAP quota can't be parsed, use the Nextcloud's default quota (use 'default')
482
+     * 4. check if the target user exists and set the quota for the user.
483
+     *
484
+     * In order to improve performance and prevent an unwanted extra LDAP call, the $valueFromLDAP
485
+     * parameter can be passed with the value of the attribute. This value will be considered as the
486
+     * quota for the user coming from the LDAP server (step 1 of the process) It can be useful to
487
+     * fetch all the user's attributes in one call and use the fetched values in this function.
488
+     * The expected value for that parameter is a string describing the quota for the user. Valid
489
+     * values are 'none' (unlimited), 'default' (the Nextcloud's default quota), '1234' (quota in
490
+     * bytes), '1234 MB' (quota in MB - check the \OC_Helper::computerFileSize method for more info)
491
+     *
492
+     * fetches the quota from LDAP and stores it as Nextcloud user value
493
+     * @param string $valueFromLDAP the quota attribute's value can be passed,
494
+     * to save the readAttribute request
495
+     * @return null
496
+     */
497
+    public function updateQuota($valueFromLDAP = null) {
498
+        if($this->wasRefreshed('quota')) {
499
+            return;
500
+        }
501
+
502
+        $quotaAttribute = $this->connection->ldapQuotaAttribute;
503
+        $defaultQuota = $this->connection->ldapQuotaDefault;
504
+        if($quotaAttribute === '' && $defaultQuota === '') {
505
+            return;
506
+        }
507
+
508
+        $quota = false;
509
+        if(is_null($valueFromLDAP) && $quotaAttribute !== '') {
510
+            $aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);
511
+            if($aQuota && (count($aQuota) > 0) && $this->verifyQuotaValue($aQuota[0])) {
512
+                $quota = $aQuota[0];
513
+            } else if(is_array($aQuota) && isset($aQuota[0])) {
514
+                $this->log->log('no suitable LDAP quota found for user ' . $this->uid . ': [' . $aQuota[0] . ']', Util::DEBUG);
515
+            }
516
+        } else if ($this->verifyQuotaValue($valueFromLDAP)) {
517
+            $quota = $valueFromLDAP;
518
+        } else {
519
+            $this->log->log('no suitable LDAP quota found for user ' . $this->uid . ': [' . $valueFromLDAP . ']', Util::DEBUG);
520
+        }
521
+
522
+        if ($quota === false && $this->verifyQuotaValue($defaultQuota)) {
523
+            // quota not found using the LDAP attribute (or not parseable). Try the default quota
524
+            $quota = $defaultQuota;
525
+        } else if($quota === false) {
526
+            $this->log->log('no suitable default quota found for user ' . $this->uid . ': [' . $defaultQuota . ']', Util::DEBUG);
527
+            return;
528
+        }
529
+
530
+        $targetUser = $this->userManager->get($this->uid);
531
+        if ($targetUser instanceof IUser) {
532
+            $targetUser->setQuota($quota);
533
+        } else {
534
+            $this->log->log('trying to set a quota for user ' . $this->uid . ' but the user is missing', Util::INFO);
535
+        }
536
+    }
537
+
538
+    private function verifyQuotaValue($quotaValue) {
539
+        return $quotaValue === 'none' || $quotaValue === 'default' || \OC_Helper::computerFileSize($quotaValue) !== false;
540
+    }
541
+
542
+    /**
543
+     * called by a post_login hook to save the avatar picture
544
+     *
545
+     * @param array $params
546
+     */
547
+    public function updateAvatarPostLogin($params) {
548
+        if(isset($params['uid']) && $params['uid'] === $this->getUsername()) {
549
+            $this->updateAvatar();
550
+        }
551
+    }
552
+
553
+    /**
554
+     * @brief attempts to get an image from LDAP and sets it as Nextcloud avatar
555
+     * @return bool
556
+     */
557
+    public function updateAvatar($force = false) {
558
+        if(!$force && $this->wasRefreshed('avatar')) {
559
+            return false;
560
+        }
561
+        $avatarImage = $this->getAvatarImage();
562
+        if($avatarImage === false) {
563
+            //not set, nothing left to do;
564
+            return false;
565
+        }
566
+        if(!$this->image->loadFromBase64(base64_encode($avatarImage))) {
567
+            return false;
568
+        }
569
+        return $this->setOwnCloudAvatar();
570
+    }
571
+
572
+    /**
573
+     * @brief sets an image as Nextcloud avatar
574
+     * @return bool
575
+     */
576
+    private function setOwnCloudAvatar() {
577
+        if(!$this->image->valid()) {
578
+            $this->log->log('jpegPhoto data invalid for '.$this->dn, Util::ERROR);
579
+            return false;
580
+        }
581
+        //make sure it is a square and not bigger than 128x128
582
+        $size = min(array($this->image->width(), $this->image->height(), 128));
583
+        if(!$this->image->centerCrop($size)) {
584
+            $this->log->log('croping image for avatar failed for '.$this->dn, Util::ERROR);
585
+            return false;
586
+        }
587
+
588
+        if(!$this->fs->isLoaded()) {
589
+            $this->fs->setup($this->uid);
590
+        }
591
+
592
+        try {
593
+            $avatar = $this->avatarManager->getAvatar($this->uid);
594
+            $avatar->set($this->image);
595
+            return true;
596
+        } catch (\Exception $e) {
597
+            \OC::$server->getLogger()->notice(
598
+                'Could not set avatar for ' . $this->dn	. ', because: ' . $e->getMessage(),
599
+                ['app' => 'user_ldap']);
600
+        }
601
+        return false;
602
+    }
603
+
604
+    /**
605
+     * called by a post_login hook to handle password expiry
606
+     *
607
+     * @param array $params
608
+     */
609
+    public function handlePasswordExpiry($params) {
610
+        $ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
611
+        if (empty($ppolicyDN) || (intval($this->connection->turnOnPasswordChange) !== 1)) {
612
+            return;//password expiry handling disabled
613
+        }
614
+        $uid = $params['uid'];
615
+        if(isset($uid) && $uid === $this->getUsername()) {
616
+            //retrieve relevant user attributes
617
+            $result = $this->access->search('objectclass=*', array($this->dn), ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
618 618
 			
619
-			if(array_key_exists('pwdpolicysubentry', $result[0])) {
620
-				$pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
621
-				if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
622
-					$ppolicyDN = $pwdPolicySubentry[0];//custom ppolicy DN
623
-				}
624
-			}
619
+            if(array_key_exists('pwdpolicysubentry', $result[0])) {
620
+                $pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
621
+                if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
622
+                    $ppolicyDN = $pwdPolicySubentry[0];//custom ppolicy DN
623
+                }
624
+            }
625 625
 			
626
-			$pwdGraceUseTime = array_key_exists('pwdgraceusetime', $result[0]) ? $result[0]['pwdgraceusetime'] : null;
627
-			$pwdReset = array_key_exists('pwdreset', $result[0]) ? $result[0]['pwdreset'] : null;
628
-			$pwdChangedTime = array_key_exists('pwdchangedtime', $result[0]) ? $result[0]['pwdchangedtime'] : null;
626
+            $pwdGraceUseTime = array_key_exists('pwdgraceusetime', $result[0]) ? $result[0]['pwdgraceusetime'] : null;
627
+            $pwdReset = array_key_exists('pwdreset', $result[0]) ? $result[0]['pwdreset'] : null;
628
+            $pwdChangedTime = array_key_exists('pwdchangedtime', $result[0]) ? $result[0]['pwdchangedtime'] : null;
629 629
 			
630
-			//retrieve relevant password policy attributes
631
-			$cacheKey = 'ppolicyAttributes' . $ppolicyDN;
632
-			$result = $this->connection->getFromCache($cacheKey);
633
-			if(is_null($result)) {
634
-				$result = $this->access->search('objectclass=*', array($ppolicyDN), ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
635
-				$this->connection->writeToCache($cacheKey, $result);
636
-			}
630
+            //retrieve relevant password policy attributes
631
+            $cacheKey = 'ppolicyAttributes' . $ppolicyDN;
632
+            $result = $this->connection->getFromCache($cacheKey);
633
+            if(is_null($result)) {
634
+                $result = $this->access->search('objectclass=*', array($ppolicyDN), ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
635
+                $this->connection->writeToCache($cacheKey, $result);
636
+            }
637 637
 			
638
-			$pwdGraceAuthNLimit = array_key_exists('pwdgraceauthnlimit', $result[0]) ? $result[0]['pwdgraceauthnlimit'] : null;
639
-			$pwdMaxAge = array_key_exists('pwdmaxage', $result[0]) ? $result[0]['pwdmaxage'] : null;
640
-			$pwdExpireWarning = array_key_exists('pwdexpirewarning', $result[0]) ? $result[0]['pwdexpirewarning'] : null;
638
+            $pwdGraceAuthNLimit = array_key_exists('pwdgraceauthnlimit', $result[0]) ? $result[0]['pwdgraceauthnlimit'] : null;
639
+            $pwdMaxAge = array_key_exists('pwdmaxage', $result[0]) ? $result[0]['pwdmaxage'] : null;
640
+            $pwdExpireWarning = array_key_exists('pwdexpirewarning', $result[0]) ? $result[0]['pwdexpirewarning'] : null;
641 641
 			
642
-			//handle grace login
643
-			$pwdGraceUseTimeCount = count($pwdGraceUseTime);
644
-			if($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
645
-				if($pwdGraceAuthNLimit 
646
-					&& (count($pwdGraceAuthNLimit) > 0)
647
-					&&($pwdGraceUseTimeCount < intval($pwdGraceAuthNLimit[0]))) { //at least one more grace login available?
648
-					$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
649
-					header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
650
-					'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
651
-				} else { //no more grace login available
652
-					header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
653
-					'user_ldap.renewPassword.showLoginFormInvalidPassword', array('user' => $uid)));
654
-				}
655
-				exit();
656
-			}
657
-			//handle pwdReset attribute
658
-			if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
659
-				$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
660
-				header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
661
-				'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
662
-				exit();
663
-			}
664
-			//handle password expiry warning
665
-			if($pwdChangedTime && (count($pwdChangedTime) > 0)) {
666
-				if($pwdMaxAge && (count($pwdMaxAge) > 0)
667
-					&& $pwdExpireWarning && (count($pwdExpireWarning) > 0)) {
668
-					$pwdMaxAgeInt = intval($pwdMaxAge[0]);
669
-					$pwdExpireWarningInt = intval($pwdExpireWarning[0]);
670
-					if($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0){
671
-						$pwdChangedTimeDt = \DateTime::createFromFormat('YmdHisZ', $pwdChangedTime[0]);
672
-						$pwdChangedTimeDt->add(new \DateInterval('PT'.$pwdMaxAgeInt.'S'));
673
-						$currentDateTime = new \DateTime();
674
-						$secondsToExpiry = $pwdChangedTimeDt->getTimestamp() - $currentDateTime->getTimestamp();
675
-						if($secondsToExpiry <= $pwdExpireWarningInt) {
676
-							//remove last password expiry warning if any
677
-							$notification = $this->notificationManager->createNotification();
678
-							$notification->setApp('user_ldap')
679
-								->setUser($uid)
680
-								->setObject('pwd_exp_warn', $uid)
681
-							;
682
-							$this->notificationManager->markProcessed($notification);
683
-							//create new password expiry warning
684
-							$notification = $this->notificationManager->createNotification();
685
-							$notification->setApp('user_ldap')
686
-								->setUser($uid)
687
-								->setDateTime($currentDateTime)
688
-								->setObject('pwd_exp_warn', $uid) 
689
-								->setSubject('pwd_exp_warn_days', [(int) ceil($secondsToExpiry / 60 / 60 / 24)])
690
-							;
691
-							$this->notificationManager->notify($notification);
692
-						}
693
-					}
694
-				}
695
-			}
696
-		}
697
-	}
642
+            //handle grace login
643
+            $pwdGraceUseTimeCount = count($pwdGraceUseTime);
644
+            if($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
645
+                if($pwdGraceAuthNLimit 
646
+                    && (count($pwdGraceAuthNLimit) > 0)
647
+                    &&($pwdGraceUseTimeCount < intval($pwdGraceAuthNLimit[0]))) { //at least one more grace login available?
648
+                    $this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
649
+                    header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
650
+                    'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
651
+                } else { //no more grace login available
652
+                    header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
653
+                    'user_ldap.renewPassword.showLoginFormInvalidPassword', array('user' => $uid)));
654
+                }
655
+                exit();
656
+            }
657
+            //handle pwdReset attribute
658
+            if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
659
+                $this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
660
+                header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
661
+                'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
662
+                exit();
663
+            }
664
+            //handle password expiry warning
665
+            if($pwdChangedTime && (count($pwdChangedTime) > 0)) {
666
+                if($pwdMaxAge && (count($pwdMaxAge) > 0)
667
+                    && $pwdExpireWarning && (count($pwdExpireWarning) > 0)) {
668
+                    $pwdMaxAgeInt = intval($pwdMaxAge[0]);
669
+                    $pwdExpireWarningInt = intval($pwdExpireWarning[0]);
670
+                    if($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0){
671
+                        $pwdChangedTimeDt = \DateTime::createFromFormat('YmdHisZ', $pwdChangedTime[0]);
672
+                        $pwdChangedTimeDt->add(new \DateInterval('PT'.$pwdMaxAgeInt.'S'));
673
+                        $currentDateTime = new \DateTime();
674
+                        $secondsToExpiry = $pwdChangedTimeDt->getTimestamp() - $currentDateTime->getTimestamp();
675
+                        if($secondsToExpiry <= $pwdExpireWarningInt) {
676
+                            //remove last password expiry warning if any
677
+                            $notification = $this->notificationManager->createNotification();
678
+                            $notification->setApp('user_ldap')
679
+                                ->setUser($uid)
680
+                                ->setObject('pwd_exp_warn', $uid)
681
+                            ;
682
+                            $this->notificationManager->markProcessed($notification);
683
+                            //create new password expiry warning
684
+                            $notification = $this->notificationManager->createNotification();
685
+                            $notification->setApp('user_ldap')
686
+                                ->setUser($uid)
687
+                                ->setDateTime($currentDateTime)
688
+                                ->setObject('pwd_exp_warn', $uid) 
689
+                                ->setSubject('pwd_exp_warn_days', [(int) ceil($secondsToExpiry / 60 / 60 / 24)])
690
+                            ;
691
+                            $this->notificationManager->notify($notification);
692
+                        }
693
+                    }
694
+                }
695
+            }
696
+        }
697
+    }
698 698
 }
Please login to merge, or discard this patch.
Spacing   +61 added lines, -61 removed lines patch added patch discarded remove patch
@@ -153,17 +153,17 @@  discard block
 block discarded – undo
153 153
 	 * @return null
154 154
 	 */
155 155
 	public function update() {
156
-		if(is_null($this->dn)) {
156
+		if (is_null($this->dn)) {
157 157
 			return null;
158 158
 		}
159 159
 
160 160
 		$hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap',
161 161
 				self::USER_PREFKEY_FIRSTLOGIN, 0);
162 162
 
163
-		if($this->needsRefresh()) {
163
+		if ($this->needsRefresh()) {
164 164
 			$this->updateEmail();
165 165
 			$this->updateQuota();
166
-			if($hasLoggedIn !== 0) {
166
+			if ($hasLoggedIn !== 0) {
167 167
 				//we do not need to try it, when the user has not been logged in
168 168
 				//before, because the file system will not be ready.
169 169
 				$this->updateAvatar();
@@ -182,7 +182,7 @@  discard block
 block discarded – undo
182 182
 		$this->markRefreshTime();
183 183
 		//Quota
184 184
 		$attr = strtolower($this->connection->ldapQuotaAttribute);
185
-		if(isset($ldapEntry[$attr])) {
185
+		if (isset($ldapEntry[$attr])) {
186 186
 			$this->updateQuota($ldapEntry[$attr][0]);
187 187
 		} else {
188 188
 			if ($this->connection->ldapQuotaDefault !== '') {
@@ -194,11 +194,11 @@  discard block
 block discarded – undo
194 194
 		//displayName
195 195
 		$displayName = $displayName2 = '';
196 196
 		$attr = strtolower($this->connection->ldapUserDisplayName);
197
-		if(isset($ldapEntry[$attr])) {
197
+		if (isset($ldapEntry[$attr])) {
198 198
 			$displayName = strval($ldapEntry[$attr][0]);
199 199
 		}
200 200
 		$attr = strtolower($this->connection->ldapUserDisplayName2);
201
-		if(isset($ldapEntry[$attr])) {
201
+		if (isset($ldapEntry[$attr])) {
202 202
 			$displayName2 = strval($ldapEntry[$attr][0]);
203 203
 		}
204 204
 		if ($displayName !== '') {
@@ -215,22 +215,22 @@  discard block
 block discarded – undo
215 215
 		//email must be stored after displayname, because it would cause a user
216 216
 		//change event that will trigger fetching the display name again
217 217
 		$attr = strtolower($this->connection->ldapEmailAttribute);
218
-		if(isset($ldapEntry[$attr])) {
218
+		if (isset($ldapEntry[$attr])) {
219 219
 			$this->updateEmail($ldapEntry[$attr][0]);
220 220
 		}
221 221
 		unset($attr);
222 222
 
223 223
 		// LDAP Username, needed for s2s sharing
224
-		if(isset($ldapEntry['uid'])) {
224
+		if (isset($ldapEntry['uid'])) {
225 225
 			$this->storeLDAPUserName($ldapEntry['uid'][0]);
226
-		} else if(isset($ldapEntry['samaccountname'])) {
226
+		} else if (isset($ldapEntry['samaccountname'])) {
227 227
 			$this->storeLDAPUserName($ldapEntry['samaccountname'][0]);
228 228
 		}
229 229
 
230 230
 		//homePath
231
-		if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
231
+		if (strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
232 232
 			$attr = strtolower(substr($this->connection->homeFolderNamingRule, strlen('attr:')));
233
-			if(isset($ldapEntry[$attr])) {
233
+			if (isset($ldapEntry[$attr])) {
234 234
 				$this->access->cacheUserHome(
235 235
 					$this->getUsername(), $this->getHomePath($ldapEntry[$attr][0]));
236 236
 			}
@@ -239,15 +239,15 @@  discard block
 block discarded – undo
239 239
 		//memberOf groups
240 240
 		$cacheKey = 'getMemberOf'.$this->getUsername();
241 241
 		$groups = false;
242
-		if(isset($ldapEntry['memberof'])) {
242
+		if (isset($ldapEntry['memberof'])) {
243 243
 			$groups = $ldapEntry['memberof'];
244 244
 		}
245 245
 		$this->connection->writeToCache($cacheKey, $groups);
246 246
 
247 247
 		//Avatar
248 248
 		$attrs = array('jpegphoto', 'thumbnailphoto');
249
-		foreach ($attrs as $attr)  {
250
-			if(isset($ldapEntry[$attr])) {
249
+		foreach ($attrs as $attr) {
250
+			if (isset($ldapEntry[$attr])) {
251 251
 				$this->avatarImage = $ldapEntry[$attr][0];
252 252
 				// the call to the method that saves the avatar in the file
253 253
 				// system must be postponed after the login. It is to ensure
@@ -300,12 +300,12 @@  discard block
 block discarded – undo
300 300
 		if ($path !== '') {
301 301
 			//if attribute's value is an absolute path take this, otherwise append it to data dir
302 302
 			//check for / at the beginning or pattern c:\ resp. c:/
303
-			if(   '/' !== $path[0]
303
+			if ('/' !== $path[0]
304 304
 			   && !(3 < strlen($path) && ctype_alpha($path[0])
305 305
 			       && $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))
306 306
 			) {
307 307
 				$path = $this->config->getSystemValue('datadirectory',
308
-						\OC::$SERVERROOT.'/data' ) . '/' . $path;
308
+						\OC::$SERVERROOT.'/data').'/'.$path;
309 309
 			}
310 310
 			//we need it to store it in the DB as well in case a user gets
311 311
 			//deleted so we can clean up afterwards
@@ -315,11 +315,11 @@  discard block
 block discarded – undo
315 315
 			return $path;
316 316
 		}
317 317
 
318
-		if(    !is_null($attr)
318
+		if (!is_null($attr)
319 319
 			&& $this->config->getAppValue('user_ldap', 'enforce_home_folder_naming_rule', true)
320 320
 		) {
321 321
 			// a naming rule attribute is defined, but it doesn't exist for that LDAP user
322
-			throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: ' . $this->getUsername());
322
+			throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: '.$this->getUsername());
323 323
 		}
324 324
 
325 325
 		//false will apply default behaviour as defined and done by OC_User
@@ -330,7 +330,7 @@  discard block
 block discarded – undo
330 330
 	public function getMemberOfGroups() {
331 331
 		$cacheKey = 'getMemberOf'.$this->getUsername();
332 332
 		$memberOfGroups = $this->connection->getFromCache($cacheKey);
333
-		if(!is_null($memberOfGroups)) {
333
+		if (!is_null($memberOfGroups)) {
334 334
 			return $memberOfGroups;
335 335
 		}
336 336
 		$groupDNs = $this->access->readAttribute($this->getDN(), 'memberOf');
@@ -343,15 +343,15 @@  discard block
 block discarded – undo
343 343
 	 * @return string data (provided by LDAP) | false
344 344
 	 */
345 345
 	public function getAvatarImage() {
346
-		if(!is_null($this->avatarImage)) {
346
+		if (!is_null($this->avatarImage)) {
347 347
 			return $this->avatarImage;
348 348
 		}
349 349
 
350 350
 		$this->avatarImage = false;
351 351
 		$attributes = array('jpegPhoto', 'thumbnailPhoto');
352
-		foreach($attributes as $attribute) {
352
+		foreach ($attributes as $attribute) {
353 353
 			$result = $this->access->readAttribute($this->dn, $attribute);
354
-			if($result !== false && is_array($result) && isset($result[0])) {
354
+			if ($result !== false && is_array($result) && isset($result[0])) {
355 355
 				$this->avatarImage = $result[0];
356 356
 				break;
357 357
 			}
@@ -388,7 +388,7 @@  discard block
 block discarded – undo
388 388
 		$lastChecked = $this->config->getUserValue($this->uid, 'user_ldap',
389 389
 			self::USER_PREFKEY_LASTREFRESH, 0);
390 390
 
391
-		if((time() - intval($lastChecked)) < intval($this->config->getAppValue('user_ldap', 'updateAttributesInterval', 86400)) ) {
391
+		if ((time() - intval($lastChecked)) < intval($this->config->getAppValue('user_ldap', 'updateAttributesInterval', 86400))) {
392 392
 			return false;
393 393
 		}
394 394
 		return  true;
@@ -414,8 +414,8 @@  discard block
 block discarded – undo
414 414
 	 */
415 415
 	public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
416 416
 		$displayName2 = strval($displayName2);
417
-		if($displayName2 !== '') {
418
-			$displayName .= ' (' . $displayName2 . ')';
417
+		if ($displayName2 !== '') {
418
+			$displayName .= ' ('.$displayName2.')';
419 419
 		}
420 420
 		$this->store('displayName', $displayName);
421 421
 		return $displayName;
@@ -437,7 +437,7 @@  discard block
 block discarded – undo
437 437
 	 * @return bool
438 438
 	 */
439 439
 	private function wasRefreshed($feature) {
440
-		if(isset($this->refreshedFeatures[$feature])) {
440
+		if (isset($this->refreshedFeatures[$feature])) {
441 441
 			return true;
442 442
 		}
443 443
 		$this->refreshedFeatures[$feature] = 1;
@@ -450,15 +450,15 @@  discard block
 block discarded – undo
450 450
 	 * @return null
451 451
 	 */
452 452
 	public function updateEmail($valueFromLDAP = null) {
453
-		if($this->wasRefreshed('email')) {
453
+		if ($this->wasRefreshed('email')) {
454 454
 			return;
455 455
 		}
456 456
 		$email = strval($valueFromLDAP);
457
-		if(is_null($valueFromLDAP)) {
457
+		if (is_null($valueFromLDAP)) {
458 458
 			$emailAttribute = $this->connection->ldapEmailAttribute;
459 459
 			if ($emailAttribute !== '') {
460 460
 				$aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
461
-				if(is_array($aEmail) && (count($aEmail) > 0)) {
461
+				if (is_array($aEmail) && (count($aEmail) > 0)) {
462 462
 					$email = strval($aEmail[0]);
463 463
 				}
464 464
 			}
@@ -495,35 +495,35 @@  discard block
 block discarded – undo
495 495
 	 * @return null
496 496
 	 */
497 497
 	public function updateQuota($valueFromLDAP = null) {
498
-		if($this->wasRefreshed('quota')) {
498
+		if ($this->wasRefreshed('quota')) {
499 499
 			return;
500 500
 		}
501 501
 
502 502
 		$quotaAttribute = $this->connection->ldapQuotaAttribute;
503 503
 		$defaultQuota = $this->connection->ldapQuotaDefault;
504
-		if($quotaAttribute === '' && $defaultQuota === '') {
504
+		if ($quotaAttribute === '' && $defaultQuota === '') {
505 505
 			return;
506 506
 		}
507 507
 
508 508
 		$quota = false;
509
-		if(is_null($valueFromLDAP) && $quotaAttribute !== '') {
509
+		if (is_null($valueFromLDAP) && $quotaAttribute !== '') {
510 510
 			$aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);
511
-			if($aQuota && (count($aQuota) > 0) && $this->verifyQuotaValue($aQuota[0])) {
511
+			if ($aQuota && (count($aQuota) > 0) && $this->verifyQuotaValue($aQuota[0])) {
512 512
 				$quota = $aQuota[0];
513
-			} else if(is_array($aQuota) && isset($aQuota[0])) {
514
-				$this->log->log('no suitable LDAP quota found for user ' . $this->uid . ': [' . $aQuota[0] . ']', Util::DEBUG);
513
+			} else if (is_array($aQuota) && isset($aQuota[0])) {
514
+				$this->log->log('no suitable LDAP quota found for user '.$this->uid.': ['.$aQuota[0].']', Util::DEBUG);
515 515
 			}
516 516
 		} else if ($this->verifyQuotaValue($valueFromLDAP)) {
517 517
 			$quota = $valueFromLDAP;
518 518
 		} else {
519
-			$this->log->log('no suitable LDAP quota found for user ' . $this->uid . ': [' . $valueFromLDAP . ']', Util::DEBUG);
519
+			$this->log->log('no suitable LDAP quota found for user '.$this->uid.': ['.$valueFromLDAP.']', Util::DEBUG);
520 520
 		}
521 521
 
522 522
 		if ($quota === false && $this->verifyQuotaValue($defaultQuota)) {
523 523
 			// quota not found using the LDAP attribute (or not parseable). Try the default quota
524 524
 			$quota = $defaultQuota;
525
-		} else if($quota === false) {
526
-			$this->log->log('no suitable default quota found for user ' . $this->uid . ': [' . $defaultQuota . ']', Util::DEBUG);
525
+		} else if ($quota === false) {
526
+			$this->log->log('no suitable default quota found for user '.$this->uid.': ['.$defaultQuota.']', Util::DEBUG);
527 527
 			return;
528 528
 		}
529 529
 
@@ -531,7 +531,7 @@  discard block
 block discarded – undo
531 531
 		if ($targetUser instanceof IUser) {
532 532
 			$targetUser->setQuota($quota);
533 533
 		} else {
534
-			$this->log->log('trying to set a quota for user ' . $this->uid . ' but the user is missing', Util::INFO);
534
+			$this->log->log('trying to set a quota for user '.$this->uid.' but the user is missing', Util::INFO);
535 535
 		}
536 536
 	}
537 537
 
@@ -545,7 +545,7 @@  discard block
 block discarded – undo
545 545
 	 * @param array $params
546 546
 	 */
547 547
 	public function updateAvatarPostLogin($params) {
548
-		if(isset($params['uid']) && $params['uid'] === $this->getUsername()) {
548
+		if (isset($params['uid']) && $params['uid'] === $this->getUsername()) {
549 549
 			$this->updateAvatar();
550 550
 		}
551 551
 	}
@@ -555,15 +555,15 @@  discard block
 block discarded – undo
555 555
 	 * @return bool
556 556
 	 */
557 557
 	public function updateAvatar($force = false) {
558
-		if(!$force && $this->wasRefreshed('avatar')) {
558
+		if (!$force && $this->wasRefreshed('avatar')) {
559 559
 			return false;
560 560
 		}
561 561
 		$avatarImage = $this->getAvatarImage();
562
-		if($avatarImage === false) {
562
+		if ($avatarImage === false) {
563 563
 			//not set, nothing left to do;
564 564
 			return false;
565 565
 		}
566
-		if(!$this->image->loadFromBase64(base64_encode($avatarImage))) {
566
+		if (!$this->image->loadFromBase64(base64_encode($avatarImage))) {
567 567
 			return false;
568 568
 		}
569 569
 		return $this->setOwnCloudAvatar();
@@ -574,18 +574,18 @@  discard block
 block discarded – undo
574 574
 	 * @return bool
575 575
 	 */
576 576
 	private function setOwnCloudAvatar() {
577
-		if(!$this->image->valid()) {
577
+		if (!$this->image->valid()) {
578 578
 			$this->log->log('jpegPhoto data invalid for '.$this->dn, Util::ERROR);
579 579
 			return false;
580 580
 		}
581 581
 		//make sure it is a square and not bigger than 128x128
582 582
 		$size = min(array($this->image->width(), $this->image->height(), 128));
583
-		if(!$this->image->centerCrop($size)) {
583
+		if (!$this->image->centerCrop($size)) {
584 584
 			$this->log->log('croping image for avatar failed for '.$this->dn, Util::ERROR);
585 585
 			return false;
586 586
 		}
587 587
 
588
-		if(!$this->fs->isLoaded()) {
588
+		if (!$this->fs->isLoaded()) {
589 589
 			$this->fs->setup($this->uid);
590 590
 		}
591 591
 
@@ -595,7 +595,7 @@  discard block
 block discarded – undo
595 595
 			return true;
596 596
 		} catch (\Exception $e) {
597 597
 			\OC::$server->getLogger()->notice(
598
-				'Could not set avatar for ' . $this->dn	. ', because: ' . $e->getMessage(),
598
+				'Could not set avatar for '.$this->dn.', because: '.$e->getMessage(),
599 599
 				['app' => 'user_ldap']);
600 600
 		}
601 601
 		return false;
@@ -609,17 +609,17 @@  discard block
 block discarded – undo
609 609
 	public function handlePasswordExpiry($params) {
610 610
 		$ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
611 611
 		if (empty($ppolicyDN) || (intval($this->connection->turnOnPasswordChange) !== 1)) {
612
-			return;//password expiry handling disabled
612
+			return; //password expiry handling disabled
613 613
 		}
614 614
 		$uid = $params['uid'];
615
-		if(isset($uid) && $uid === $this->getUsername()) {
615
+		if (isset($uid) && $uid === $this->getUsername()) {
616 616
 			//retrieve relevant user attributes
617 617
 			$result = $this->access->search('objectclass=*', array($this->dn), ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
618 618
 			
619
-			if(array_key_exists('pwdpolicysubentry', $result[0])) {
619
+			if (array_key_exists('pwdpolicysubentry', $result[0])) {
620 620
 				$pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
621
-				if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
622
-					$ppolicyDN = $pwdPolicySubentry[0];//custom ppolicy DN
621
+				if ($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)) {
622
+					$ppolicyDN = $pwdPolicySubentry[0]; //custom ppolicy DN
623 623
 				}
624 624
 			}
625 625
 			
@@ -628,9 +628,9 @@  discard block
 block discarded – undo
628 628
 			$pwdChangedTime = array_key_exists('pwdchangedtime', $result[0]) ? $result[0]['pwdchangedtime'] : null;
629 629
 			
630 630
 			//retrieve relevant password policy attributes
631
-			$cacheKey = 'ppolicyAttributes' . $ppolicyDN;
631
+			$cacheKey = 'ppolicyAttributes'.$ppolicyDN;
632 632
 			$result = $this->connection->getFromCache($cacheKey);
633
-			if(is_null($result)) {
633
+			if (is_null($result)) {
634 634
 				$result = $this->access->search('objectclass=*', array($ppolicyDN), ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
635 635
 				$this->connection->writeToCache($cacheKey, $result);
636 636
 			}
@@ -641,8 +641,8 @@  discard block
 block discarded – undo
641 641
 			
642 642
 			//handle grace login
643 643
 			$pwdGraceUseTimeCount = count($pwdGraceUseTime);
644
-			if($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
645
-				if($pwdGraceAuthNLimit 
644
+			if ($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
645
+				if ($pwdGraceAuthNLimit 
646 646
 					&& (count($pwdGraceAuthNLimit) > 0)
647 647
 					&&($pwdGraceUseTimeCount < intval($pwdGraceAuthNLimit[0]))) { //at least one more grace login available?
648 648
 					$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
@@ -655,24 +655,24 @@  discard block
 block discarded – undo
655 655
 				exit();
656 656
 			}
657 657
 			//handle pwdReset attribute
658
-			if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
658
+			if ($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
659 659
 				$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
660 660
 				header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
661 661
 				'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
662 662
 				exit();
663 663
 			}
664 664
 			//handle password expiry warning
665
-			if($pwdChangedTime && (count($pwdChangedTime) > 0)) {
666
-				if($pwdMaxAge && (count($pwdMaxAge) > 0)
665
+			if ($pwdChangedTime && (count($pwdChangedTime) > 0)) {
666
+				if ($pwdMaxAge && (count($pwdMaxAge) > 0)
667 667
 					&& $pwdExpireWarning && (count($pwdExpireWarning) > 0)) {
668 668
 					$pwdMaxAgeInt = intval($pwdMaxAge[0]);
669 669
 					$pwdExpireWarningInt = intval($pwdExpireWarning[0]);
670
-					if($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0){
670
+					if ($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0) {
671 671
 						$pwdChangedTimeDt = \DateTime::createFromFormat('YmdHisZ', $pwdChangedTime[0]);
672 672
 						$pwdChangedTimeDt->add(new \DateInterval('PT'.$pwdMaxAgeInt.'S'));
673 673
 						$currentDateTime = new \DateTime();
674 674
 						$secondsToExpiry = $pwdChangedTimeDt->getTimestamp() - $currentDateTime->getTimestamp();
675
-						if($secondsToExpiry <= $pwdExpireWarningInt) {
675
+						if ($secondsToExpiry <= $pwdExpireWarningInt) {
676 676
 							//remove last password expiry warning if any
677 677
 							$notification = $this->notificationManager->createNotification();
678 678
 							$notification->setApp('user_ldap')
Please login to merge, or discard this patch.
apps/user_ldap/lib/User_LDAP.php 2 patches
Indentation   +570 added lines, -570 removed lines patch added patch discarded remove patch
@@ -51,578 +51,578 @@
 block discarded – undo
51 51
 use OCP\Util;
52 52
 
53 53
 class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserInterface, IUserLDAP {
54
-	/** @var \OCP\IConfig */
55
-	protected $ocConfig;
56
-
57
-	/** @var INotificationManager */
58
-	protected $notificationManager;
59
-
60
-	/** @var string */
61
-	protected $currentUserInDeletionProcess;
62
-
63
-	/** @var UserPluginManager */
64
-	protected $userPluginManager;
65
-
66
-	/**
67
-	 * @param Access $access
68
-	 * @param \OCP\IConfig $ocConfig
69
-	 * @param \OCP\Notification\IManager $notificationManager
70
-	 * @param IUserSession $userSession
71
-	 */
72
-	public function __construct(Access $access, IConfig $ocConfig, INotificationManager $notificationManager, IUserSession $userSession, UserPluginManager $userPluginManager) {
73
-		parent::__construct($access);
74
-		$this->ocConfig = $ocConfig;
75
-		$this->notificationManager = $notificationManager;
76
-		$this->userPluginManager = $userPluginManager;
77
-		$this->registerHooks($userSession);
78
-	}
79
-
80
-	protected function registerHooks(IUserSession $userSession) {
81
-		$userSession->listen('\OC\User', 'preDelete', [$this, 'preDeleteUser']);
82
-		$userSession->listen('\OC\User', 'postDelete', [$this, 'postDeleteUser']);
83
-	}
84
-
85
-	public function preDeleteUser(IUser $user) {
86
-		$this->currentUserInDeletionProcess = $user->getUID();
87
-	}
88
-
89
-	public function postDeleteUser() {
90
-		$this->currentUserInDeletionProcess = null;
91
-	}
92
-
93
-	/**
94
-	 * checks whether the user is allowed to change his avatar in Nextcloud
95
-	 *
96
-	 * @param string $uid the Nextcloud user name
97
-	 * @return boolean either the user can or cannot
98
-	 * @throws \Exception
99
-	 */
100
-	public function canChangeAvatar($uid) {
101
-		if ($this->userPluginManager->implementsActions(Backend::PROVIDE_AVATAR)) {
102
-			return $this->userPluginManager->canChangeAvatar($uid);
103
-		}
104
-
105
-		$user = $this->access->userManager->get($uid);
106
-		if(!$user instanceof User) {
107
-			return false;
108
-		}
109
-		$imageData = $user->getAvatarImage();
110
-		if($imageData === false) {
111
-			return true;
112
-		}
113
-		return !$user->updateAvatar(true);
114
-	}
115
-
116
-	/**
117
-	 * returns the username for the given login name, if available
118
-	 *
119
-	 * @param string $loginName
120
-	 * @return string|false
121
-	 */
122
-	public function loginName2UserName($loginName) {
123
-		$cacheKey = 'loginName2UserName-'.$loginName;
124
-		$username = $this->access->connection->getFromCache($cacheKey);
125
-		if(!is_null($username)) {
126
-			return $username;
127
-		}
128
-
129
-		try {
130
-			$ldapRecord = $this->getLDAPUserByLoginName($loginName);
131
-			$user = $this->access->userManager->get($ldapRecord['dn'][0]);
132
-			if($user instanceof OfflineUser) {
133
-				// this path is not really possible, however get() is documented
134
-				// to return User or OfflineUser so we are very defensive here.
135
-				$this->access->connection->writeToCache($cacheKey, false);
136
-				return false;
137
-			}
138
-			$username = $user->getUsername();
139
-			$this->access->connection->writeToCache($cacheKey, $username);
140
-			return $username;
141
-		} catch (NotOnLDAP $e) {
142
-			$this->access->connection->writeToCache($cacheKey, false);
143
-			return false;
144
-		}
145
-	}
54
+    /** @var \OCP\IConfig */
55
+    protected $ocConfig;
56
+
57
+    /** @var INotificationManager */
58
+    protected $notificationManager;
59
+
60
+    /** @var string */
61
+    protected $currentUserInDeletionProcess;
62
+
63
+    /** @var UserPluginManager */
64
+    protected $userPluginManager;
65
+
66
+    /**
67
+     * @param Access $access
68
+     * @param \OCP\IConfig $ocConfig
69
+     * @param \OCP\Notification\IManager $notificationManager
70
+     * @param IUserSession $userSession
71
+     */
72
+    public function __construct(Access $access, IConfig $ocConfig, INotificationManager $notificationManager, IUserSession $userSession, UserPluginManager $userPluginManager) {
73
+        parent::__construct($access);
74
+        $this->ocConfig = $ocConfig;
75
+        $this->notificationManager = $notificationManager;
76
+        $this->userPluginManager = $userPluginManager;
77
+        $this->registerHooks($userSession);
78
+    }
79
+
80
+    protected function registerHooks(IUserSession $userSession) {
81
+        $userSession->listen('\OC\User', 'preDelete', [$this, 'preDeleteUser']);
82
+        $userSession->listen('\OC\User', 'postDelete', [$this, 'postDeleteUser']);
83
+    }
84
+
85
+    public function preDeleteUser(IUser $user) {
86
+        $this->currentUserInDeletionProcess = $user->getUID();
87
+    }
88
+
89
+    public function postDeleteUser() {
90
+        $this->currentUserInDeletionProcess = null;
91
+    }
92
+
93
+    /**
94
+     * checks whether the user is allowed to change his avatar in Nextcloud
95
+     *
96
+     * @param string $uid the Nextcloud user name
97
+     * @return boolean either the user can or cannot
98
+     * @throws \Exception
99
+     */
100
+    public function canChangeAvatar($uid) {
101
+        if ($this->userPluginManager->implementsActions(Backend::PROVIDE_AVATAR)) {
102
+            return $this->userPluginManager->canChangeAvatar($uid);
103
+        }
104
+
105
+        $user = $this->access->userManager->get($uid);
106
+        if(!$user instanceof User) {
107
+            return false;
108
+        }
109
+        $imageData = $user->getAvatarImage();
110
+        if($imageData === false) {
111
+            return true;
112
+        }
113
+        return !$user->updateAvatar(true);
114
+    }
115
+
116
+    /**
117
+     * returns the username for the given login name, if available
118
+     *
119
+     * @param string $loginName
120
+     * @return string|false
121
+     */
122
+    public function loginName2UserName($loginName) {
123
+        $cacheKey = 'loginName2UserName-'.$loginName;
124
+        $username = $this->access->connection->getFromCache($cacheKey);
125
+        if(!is_null($username)) {
126
+            return $username;
127
+        }
128
+
129
+        try {
130
+            $ldapRecord = $this->getLDAPUserByLoginName($loginName);
131
+            $user = $this->access->userManager->get($ldapRecord['dn'][0]);
132
+            if($user instanceof OfflineUser) {
133
+                // this path is not really possible, however get() is documented
134
+                // to return User or OfflineUser so we are very defensive here.
135
+                $this->access->connection->writeToCache($cacheKey, false);
136
+                return false;
137
+            }
138
+            $username = $user->getUsername();
139
+            $this->access->connection->writeToCache($cacheKey, $username);
140
+            return $username;
141
+        } catch (NotOnLDAP $e) {
142
+            $this->access->connection->writeToCache($cacheKey, false);
143
+            return false;
144
+        }
145
+    }
146 146
 	
147
-	/**
148
-	 * returns the username for the given LDAP DN, if available
149
-	 *
150
-	 * @param string $dn
151
-	 * @return string|false with the username
152
-	 */
153
-	public function dn2UserName($dn) {
154
-		return $this->access->dn2username($dn);
155
-	}
156
-
157
-	/**
158
-	 * returns an LDAP record based on a given login name
159
-	 *
160
-	 * @param string $loginName
161
-	 * @return array
162
-	 * @throws NotOnLDAP
163
-	 */
164
-	public function getLDAPUserByLoginName($loginName) {
165
-		//find out dn of the user name
166
-		$attrs = $this->access->userManager->getAttributes();
167
-		$users = $this->access->fetchUsersByLoginName($loginName, $attrs);
168
-		if(count($users) < 1) {
169
-			throw new NotOnLDAP('No user available for the given login name on ' .
170
-				$this->access->connection->ldapHost . ':' . $this->access->connection->ldapPort);
171
-		}
172
-		return $users[0];
173
-	}
174
-
175
-	/**
176
-	 * Check if the password is correct without logging in the user
177
-	 *
178
-	 * @param string $uid The username
179
-	 * @param string $password The password
180
-	 * @return false|string
181
-	 */
182
-	public function checkPassword($uid, $password) {
183
-		try {
184
-			$ldapRecord = $this->getLDAPUserByLoginName($uid);
185
-		} catch(NotOnLDAP $e) {
186
-			if($this->ocConfig->getSystemValue('loglevel', Util::WARN) === Util::DEBUG) {
187
-				\OC::$server->getLogger()->logException($e, ['app' => 'user_ldap']);
188
-			}
189
-			return false;
190
-		}
191
-		$dn = $ldapRecord['dn'][0];
192
-		$user = $this->access->userManager->get($dn);
193
-
194
-		if(!$user instanceof User) {
195
-			Util::writeLog('user_ldap',
196
-				'LDAP Login: Could not get user object for DN ' . $dn .
197
-				'. Maybe the LDAP entry has no set display name attribute?',
198
-				Util::WARN);
199
-			return false;
200
-		}
201
-		if($user->getUsername() !== false) {
202
-			//are the credentials OK?
203
-			if(!$this->access->areCredentialsValid($dn, $password)) {
204
-				return false;
205
-			}
206
-
207
-			$this->access->cacheUserExists($user->getUsername());
208
-			$user->processAttributes($ldapRecord);
209
-			$user->markLogin();
210
-
211
-			return $user->getUsername();
212
-		}
213
-
214
-		return false;
215
-	}
216
-
217
-	/**
218
-	 * Set password
219
-	 * @param string $uid The username
220
-	 * @param string $password The new password
221
-	 * @return bool
222
-	 */
223
-	public function setPassword($uid, $password) {
224
-		if ($this->userPluginManager->implementsActions(Backend::SET_PASSWORD)) {
225
-			return $this->userPluginManager->setPassword($uid, $password);
226
-		}
227
-
228
-		$user = $this->access->userManager->get($uid);
229
-
230
-		if(!$user instanceof User) {
231
-			throw new \Exception('LDAP setPassword: Could not get user object for uid ' . $uid .
232
-				'. Maybe the LDAP entry has no set display name attribute?');
233
-		}
234
-		if($user->getUsername() !== false && $this->access->setPassword($user->getDN(), $password)) {
235
-			$ldapDefaultPPolicyDN = $this->access->connection->ldapDefaultPPolicyDN;
236
-			$turnOnPasswordChange = $this->access->connection->turnOnPasswordChange;
237
-			if (!empty($ldapDefaultPPolicyDN) && (intval($turnOnPasswordChange) === 1)) {
238
-				//remove last password expiry warning if any
239
-				$notification = $this->notificationManager->createNotification();
240
-				$notification->setApp('user_ldap')
241
-					->setUser($uid)
242
-					->setObject('pwd_exp_warn', $uid)
243
-				;
244
-				$this->notificationManager->markProcessed($notification);
245
-			}
246
-			return true;
247
-		}
248
-
249
-		return false;
250
-	}
251
-
252
-	/**
253
-	 * Get a list of all users
254
-	 *
255
-	 * @param string $search
256
-	 * @param integer $limit
257
-	 * @param integer $offset
258
-	 * @return string[] an array of all uids
259
-	 */
260
-	public function getUsers($search = '', $limit = 10, $offset = 0) {
261
-		$search = $this->access->escapeFilterPart($search, true);
262
-		$cachekey = 'getUsers-'.$search.'-'.$limit.'-'.$offset;
263
-
264
-		//check if users are cached, if so return
265
-		$ldap_users = $this->access->connection->getFromCache($cachekey);
266
-		if(!is_null($ldap_users)) {
267
-			return $ldap_users;
268
-		}
269
-
270
-		// if we'd pass -1 to LDAP search, we'd end up in a Protocol
271
-		// error. With a limit of 0, we get 0 results. So we pass null.
272
-		if($limit <= 0) {
273
-			$limit = null;
274
-		}
275
-		$filter = $this->access->combineFilterWithAnd(array(
276
-			$this->access->connection->ldapUserFilter,
277
-			$this->access->connection->ldapUserDisplayName . '=*',
278
-			$this->access->getFilterPartForUserSearch($search)
279
-		));
280
-
281
-		Util::writeLog('user_ldap',
282
-			'getUsers: Options: search '.$search.' limit '.$limit.' offset '.$offset.' Filter: '.$filter,
283
-			Util::DEBUG);
284
-		//do the search and translate results to Nextcloud names
285
-		$ldap_users = $this->access->fetchListOfUsers(
286
-			$filter,
287
-			$this->access->userManager->getAttributes(true),
288
-			$limit, $offset);
289
-		$ldap_users = $this->access->nextcloudUserNames($ldap_users);
290
-		Util::writeLog('user_ldap', 'getUsers: '.count($ldap_users). ' Users found', Util::DEBUG);
291
-
292
-		$this->access->connection->writeToCache($cachekey, $ldap_users);
293
-		return $ldap_users;
294
-	}
295
-
296
-	/**
297
-	 * checks whether a user is still available on LDAP
298
-	 *
299
-	 * @param string|\OCA\User_LDAP\User\User $user either the Nextcloud user
300
-	 * name or an instance of that user
301
-	 * @return bool
302
-	 * @throws \Exception
303
-	 * @throws \OC\ServerNotAvailableException
304
-	 */
305
-	public function userExistsOnLDAP($user) {
306
-		if(is_string($user)) {
307
-			$user = $this->access->userManager->get($user);
308
-		}
309
-		if(is_null($user)) {
310
-			return false;
311
-		}
312
-
313
-		$dn = $user->getDN();
314
-		//check if user really still exists by reading its entry
315
-		if(!is_array($this->access->readAttribute($dn, '', $this->access->connection->ldapUserFilter))) {
316
-			$lcr = $this->access->connection->getConnectionResource();
317
-			if(is_null($lcr)) {
318
-				throw new \Exception('No LDAP Connection to server ' . $this->access->connection->ldapHost);
319
-			}
320
-
321
-			try {
322
-				$uuid = $this->access->getUserMapper()->getUUIDByDN($dn);
323
-				if (!$uuid) {
324
-					return false;
325
-				}
326
-				$newDn = $this->access->getUserDnByUuid($uuid);
327
-				//check if renamed user is still valid by reapplying the ldap filter
328
-				if (!is_array($this->access->readAttribute($newDn, '', $this->access->connection->ldapUserFilter))) {
329
-					return false;
330
-				}
331
-				$this->access->getUserMapper()->setDNbyUUID($newDn, $uuid);
332
-				return true;
333
-			} catch (ServerNotAvailableException $e) {
334
-				throw $e;
335
-			} catch (\Exception $e) {
336
-				return false;
337
-			}
338
-		}
339
-
340
-		if($user instanceof OfflineUser) {
341
-			$user->unmark();
342
-		}
343
-
344
-		return true;
345
-	}
346
-
347
-	/**
348
-	 * check if a user exists
349
-	 * @param string $uid the username
350
-	 * @return boolean
351
-	 * @throws \Exception when connection could not be established
352
-	 */
353
-	public function userExists($uid) {
354
-		$userExists = $this->access->connection->getFromCache('userExists'.$uid);
355
-		if(!is_null($userExists)) {
356
-			return (bool)$userExists;
357
-		}
358
-		//getting dn, if false the user does not exist. If dn, he may be mapped only, requires more checking.
359
-		$user = $this->access->userManager->get($uid);
360
-
361
-		if(is_null($user)) {
362
-			Util::writeLog('user_ldap', 'No DN found for '.$uid.' on '.
363
-				$this->access->connection->ldapHost, Util::DEBUG);
364
-			$this->access->connection->writeToCache('userExists'.$uid, false);
365
-			return false;
366
-		} else if($user instanceof OfflineUser) {
367
-			//express check for users marked as deleted. Returning true is
368
-			//necessary for cleanup
369
-			return true;
370
-		}
371
-
372
-		$result = $this->userExistsOnLDAP($user);
373
-		$this->access->connection->writeToCache('userExists'.$uid, $result);
374
-		if($result === true) {
375
-			$user->update();
376
-		}
377
-		return $result;
378
-	}
379
-
380
-	/**
381
-	* returns whether a user was deleted in LDAP
382
-	*
383
-	* @param string $uid The username of the user to delete
384
-	* @return bool
385
-	*/
386
-	public function deleteUser($uid) {
387
-		if ($this->userPluginManager->canDeleteUser()) {
388
-			return $this->userPluginManager->deleteUser($uid);
389
-		}
390
-
391
-		$marked = $this->ocConfig->getUserValue($uid, 'user_ldap', 'isDeleted', 0);
392
-		if(intval($marked) === 0) {
393
-			\OC::$server->getLogger()->notice(
394
-				'User '.$uid . ' is not marked as deleted, not cleaning up.',
395
-				array('app' => 'user_ldap'));
396
-			return false;
397
-		}
398
-		\OC::$server->getLogger()->info('Cleaning up after user ' . $uid,
399
-			array('app' => 'user_ldap'));
400
-
401
-		$this->access->getUserMapper()->unmap($uid);
402
-		$this->access->userManager->invalidate($uid);
403
-		return true;
404
-	}
405
-
406
-	/**
407
-	 * get the user's home directory
408
-	 *
409
-	 * @param string $uid the username
410
-	 * @return bool|string
411
-	 * @throws NoUserException
412
-	 * @throws \Exception
413
-	 */
414
-	public function getHome($uid) {
415
-		// user Exists check required as it is not done in user proxy!
416
-		if(!$this->userExists($uid)) {
417
-			return false;
418
-		}
419
-
420
-		if ($this->userPluginManager->implementsActions(Backend::GET_HOME)) {
421
-			return $this->userPluginManager->getHome($uid);
422
-		}
423
-
424
-		$cacheKey = 'getHome'.$uid;
425
-		$path = $this->access->connection->getFromCache($cacheKey);
426
-		if(!is_null($path)) {
427
-			return $path;
428
-		}
429
-
430
-		// early return path if it is a deleted user
431
-		$user = $this->access->userManager->get($uid);
432
-		if($user instanceof OfflineUser) {
433
-			if($this->currentUserInDeletionProcess !== null
434
-				&& $this->currentUserInDeletionProcess === $user->getOCName()
435
-			) {
436
-				return $user->getHomePath();
437
-			} else {
438
-				throw new NoUserException($uid . ' is not a valid user anymore');
439
-			}
440
-		} else if ($user === null) {
441
-			throw new NoUserException($uid . ' is not a valid user anymore');
442
-		}
443
-
444
-		$path = $user->getHomePath();
445
-		$this->access->cacheUserHome($uid, $path);
446
-
447
-		return $path;
448
-	}
449
-
450
-	/**
451
-	 * get display name of the user
452
-	 * @param string $uid user ID of the user
453
-	 * @return string|false display name
454
-	 */
455
-	public function getDisplayName($uid) {
456
-		if ($this->userPluginManager->implementsActions(Backend::GET_DISPLAYNAME)) {
457
-			return $this->userPluginManager->getDisplayName($uid);
458
-		}
459
-
460
-		if(!$this->userExists($uid)) {
461
-			return false;
462
-		}
463
-
464
-		$cacheKey = 'getDisplayName'.$uid;
465
-		if(!is_null($displayName = $this->access->connection->getFromCache($cacheKey))) {
466
-			return $displayName;
467
-		}
468
-
469
-		//Check whether the display name is configured to have a 2nd feature
470
-		$additionalAttribute = $this->access->connection->ldapUserDisplayName2;
471
-		$displayName2 = '';
472
-		if ($additionalAttribute !== '') {
473
-			$displayName2 = $this->access->readAttribute(
474
-				$this->access->username2dn($uid),
475
-				$additionalAttribute);
476
-		}
477
-
478
-		$displayName = $this->access->readAttribute(
479
-			$this->access->username2dn($uid),
480
-			$this->access->connection->ldapUserDisplayName);
481
-
482
-		if($displayName && (count($displayName) > 0)) {
483
-			$displayName = $displayName[0];
484
-
485
-			if (is_array($displayName2)){
486
-				$displayName2 = count($displayName2) > 0 ? $displayName2[0] : '';
487
-			}
488
-
489
-			$user = $this->access->userManager->get($uid);
490
-			if ($user instanceof User) {
491
-				$displayName = $user->composeAndStoreDisplayName($displayName, $displayName2);
492
-				$this->access->connection->writeToCache($cacheKey, $displayName);
493
-			}
494
-			if ($user instanceof OfflineUser) {
495
-				/** @var OfflineUser $user*/
496
-				$displayName = $user->getDisplayName();
497
-			}
498
-			return $displayName;
499
-		}
500
-
501
-		return null;
502
-	}
503
-
504
-	/**
505
-	 * set display name of the user
506
-	 * @param string $uid user ID of the user
507
-	 * @param string $displayName new display name of the user
508
-	 * @return string|false display name
509
-	 */
510
-	public function setDisplayName($uid, $displayName) {
511
-		if ($this->userPluginManager->implementsActions(Backend::SET_DISPLAYNAME)) {
512
-			return $this->userPluginManager->setDisplayName($uid, $displayName);
513
-		}
514
-		return false;
515
-	}
516
-
517
-	/**
518
-	 * Get a list of all display names
519
-	 *
520
-	 * @param string $search
521
-	 * @param string|null $limit
522
-	 * @param string|null $offset
523
-	 * @return array an array of all displayNames (value) and the corresponding uids (key)
524
-	 */
525
-	public function getDisplayNames($search = '', $limit = null, $offset = null) {
526
-		$cacheKey = 'getDisplayNames-'.$search.'-'.$limit.'-'.$offset;
527
-		if(!is_null($displayNames = $this->access->connection->getFromCache($cacheKey))) {
528
-			return $displayNames;
529
-		}
530
-
531
-		$displayNames = array();
532
-		$users = $this->getUsers($search, $limit, $offset);
533
-		foreach ($users as $user) {
534
-			$displayNames[$user] = $this->getDisplayName($user);
535
-		}
536
-		$this->access->connection->writeToCache($cacheKey, $displayNames);
537
-		return $displayNames;
538
-	}
539
-
540
-	/**
541
-	* Check if backend implements actions
542
-	* @param int $actions bitwise-or'ed actions
543
-	* @return boolean
544
-	*
545
-	* Returns the supported actions as int to be
546
-	* compared with \OC\User\Backend::CREATE_USER etc.
547
-	*/
548
-	public function implementsActions($actions) {
549
-		return (bool)((Backend::CHECK_PASSWORD
550
-			| Backend::GET_HOME
551
-			| Backend::GET_DISPLAYNAME
552
-			| Backend::PROVIDE_AVATAR
553
-			| Backend::COUNT_USERS
554
-			| ((intval($this->access->connection->turnOnPasswordChange) === 1)?(Backend::SET_PASSWORD):0)
555
-			| $this->userPluginManager->getImplementedActions())
556
-			& $actions);
557
-	}
558
-
559
-	/**
560
-	 * @return bool
561
-	 */
562
-	public function hasUserListings() {
563
-		return true;
564
-	}
565
-
566
-	/**
567
-	 * counts the users in LDAP
568
-	 *
569
-	 * @return int|bool
570
-	 */
571
-	public function countUsers() {
572
-		if ($this->userPluginManager->implementsActions(Backend::COUNT_USERS)) {
573
-			return $this->userPluginManager->countUsers();
574
-		}
575
-
576
-		$filter = $this->access->getFilterForUserCount();
577
-		$cacheKey = 'countUsers-'.$filter;
578
-		if(!is_null($entries = $this->access->connection->getFromCache($cacheKey))) {
579
-			return $entries;
580
-		}
581
-		$entries = $this->access->countUsers($filter);
582
-		$this->access->connection->writeToCache($cacheKey, $entries);
583
-		return $entries;
584
-	}
585
-
586
-	/**
587
-	 * Backend name to be shown in user management
588
-	 * @return string the name of the backend to be shown
589
-	 */
590
-	public function getBackendName(){
591
-		return 'LDAP';
592
-	}
147
+    /**
148
+     * returns the username for the given LDAP DN, if available
149
+     *
150
+     * @param string $dn
151
+     * @return string|false with the username
152
+     */
153
+    public function dn2UserName($dn) {
154
+        return $this->access->dn2username($dn);
155
+    }
156
+
157
+    /**
158
+     * returns an LDAP record based on a given login name
159
+     *
160
+     * @param string $loginName
161
+     * @return array
162
+     * @throws NotOnLDAP
163
+     */
164
+    public function getLDAPUserByLoginName($loginName) {
165
+        //find out dn of the user name
166
+        $attrs = $this->access->userManager->getAttributes();
167
+        $users = $this->access->fetchUsersByLoginName($loginName, $attrs);
168
+        if(count($users) < 1) {
169
+            throw new NotOnLDAP('No user available for the given login name on ' .
170
+                $this->access->connection->ldapHost . ':' . $this->access->connection->ldapPort);
171
+        }
172
+        return $users[0];
173
+    }
174
+
175
+    /**
176
+     * Check if the password is correct without logging in the user
177
+     *
178
+     * @param string $uid The username
179
+     * @param string $password The password
180
+     * @return false|string
181
+     */
182
+    public function checkPassword($uid, $password) {
183
+        try {
184
+            $ldapRecord = $this->getLDAPUserByLoginName($uid);
185
+        } catch(NotOnLDAP $e) {
186
+            if($this->ocConfig->getSystemValue('loglevel', Util::WARN) === Util::DEBUG) {
187
+                \OC::$server->getLogger()->logException($e, ['app' => 'user_ldap']);
188
+            }
189
+            return false;
190
+        }
191
+        $dn = $ldapRecord['dn'][0];
192
+        $user = $this->access->userManager->get($dn);
193
+
194
+        if(!$user instanceof User) {
195
+            Util::writeLog('user_ldap',
196
+                'LDAP Login: Could not get user object for DN ' . $dn .
197
+                '. Maybe the LDAP entry has no set display name attribute?',
198
+                Util::WARN);
199
+            return false;
200
+        }
201
+        if($user->getUsername() !== false) {
202
+            //are the credentials OK?
203
+            if(!$this->access->areCredentialsValid($dn, $password)) {
204
+                return false;
205
+            }
206
+
207
+            $this->access->cacheUserExists($user->getUsername());
208
+            $user->processAttributes($ldapRecord);
209
+            $user->markLogin();
210
+
211
+            return $user->getUsername();
212
+        }
213
+
214
+        return false;
215
+    }
216
+
217
+    /**
218
+     * Set password
219
+     * @param string $uid The username
220
+     * @param string $password The new password
221
+     * @return bool
222
+     */
223
+    public function setPassword($uid, $password) {
224
+        if ($this->userPluginManager->implementsActions(Backend::SET_PASSWORD)) {
225
+            return $this->userPluginManager->setPassword($uid, $password);
226
+        }
227
+
228
+        $user = $this->access->userManager->get($uid);
229
+
230
+        if(!$user instanceof User) {
231
+            throw new \Exception('LDAP setPassword: Could not get user object for uid ' . $uid .
232
+                '. Maybe the LDAP entry has no set display name attribute?');
233
+        }
234
+        if($user->getUsername() !== false && $this->access->setPassword($user->getDN(), $password)) {
235
+            $ldapDefaultPPolicyDN = $this->access->connection->ldapDefaultPPolicyDN;
236
+            $turnOnPasswordChange = $this->access->connection->turnOnPasswordChange;
237
+            if (!empty($ldapDefaultPPolicyDN) && (intval($turnOnPasswordChange) === 1)) {
238
+                //remove last password expiry warning if any
239
+                $notification = $this->notificationManager->createNotification();
240
+                $notification->setApp('user_ldap')
241
+                    ->setUser($uid)
242
+                    ->setObject('pwd_exp_warn', $uid)
243
+                ;
244
+                $this->notificationManager->markProcessed($notification);
245
+            }
246
+            return true;
247
+        }
248
+
249
+        return false;
250
+    }
251
+
252
+    /**
253
+     * Get a list of all users
254
+     *
255
+     * @param string $search
256
+     * @param integer $limit
257
+     * @param integer $offset
258
+     * @return string[] an array of all uids
259
+     */
260
+    public function getUsers($search = '', $limit = 10, $offset = 0) {
261
+        $search = $this->access->escapeFilterPart($search, true);
262
+        $cachekey = 'getUsers-'.$search.'-'.$limit.'-'.$offset;
263
+
264
+        //check if users are cached, if so return
265
+        $ldap_users = $this->access->connection->getFromCache($cachekey);
266
+        if(!is_null($ldap_users)) {
267
+            return $ldap_users;
268
+        }
269
+
270
+        // if we'd pass -1 to LDAP search, we'd end up in a Protocol
271
+        // error. With a limit of 0, we get 0 results. So we pass null.
272
+        if($limit <= 0) {
273
+            $limit = null;
274
+        }
275
+        $filter = $this->access->combineFilterWithAnd(array(
276
+            $this->access->connection->ldapUserFilter,
277
+            $this->access->connection->ldapUserDisplayName . '=*',
278
+            $this->access->getFilterPartForUserSearch($search)
279
+        ));
280
+
281
+        Util::writeLog('user_ldap',
282
+            'getUsers: Options: search '.$search.' limit '.$limit.' offset '.$offset.' Filter: '.$filter,
283
+            Util::DEBUG);
284
+        //do the search and translate results to Nextcloud names
285
+        $ldap_users = $this->access->fetchListOfUsers(
286
+            $filter,
287
+            $this->access->userManager->getAttributes(true),
288
+            $limit, $offset);
289
+        $ldap_users = $this->access->nextcloudUserNames($ldap_users);
290
+        Util::writeLog('user_ldap', 'getUsers: '.count($ldap_users). ' Users found', Util::DEBUG);
291
+
292
+        $this->access->connection->writeToCache($cachekey, $ldap_users);
293
+        return $ldap_users;
294
+    }
295
+
296
+    /**
297
+     * checks whether a user is still available on LDAP
298
+     *
299
+     * @param string|\OCA\User_LDAP\User\User $user either the Nextcloud user
300
+     * name or an instance of that user
301
+     * @return bool
302
+     * @throws \Exception
303
+     * @throws \OC\ServerNotAvailableException
304
+     */
305
+    public function userExistsOnLDAP($user) {
306
+        if(is_string($user)) {
307
+            $user = $this->access->userManager->get($user);
308
+        }
309
+        if(is_null($user)) {
310
+            return false;
311
+        }
312
+
313
+        $dn = $user->getDN();
314
+        //check if user really still exists by reading its entry
315
+        if(!is_array($this->access->readAttribute($dn, '', $this->access->connection->ldapUserFilter))) {
316
+            $lcr = $this->access->connection->getConnectionResource();
317
+            if(is_null($lcr)) {
318
+                throw new \Exception('No LDAP Connection to server ' . $this->access->connection->ldapHost);
319
+            }
320
+
321
+            try {
322
+                $uuid = $this->access->getUserMapper()->getUUIDByDN($dn);
323
+                if (!$uuid) {
324
+                    return false;
325
+                }
326
+                $newDn = $this->access->getUserDnByUuid($uuid);
327
+                //check if renamed user is still valid by reapplying the ldap filter
328
+                if (!is_array($this->access->readAttribute($newDn, '', $this->access->connection->ldapUserFilter))) {
329
+                    return false;
330
+                }
331
+                $this->access->getUserMapper()->setDNbyUUID($newDn, $uuid);
332
+                return true;
333
+            } catch (ServerNotAvailableException $e) {
334
+                throw $e;
335
+            } catch (\Exception $e) {
336
+                return false;
337
+            }
338
+        }
339
+
340
+        if($user instanceof OfflineUser) {
341
+            $user->unmark();
342
+        }
343
+
344
+        return true;
345
+    }
346
+
347
+    /**
348
+     * check if a user exists
349
+     * @param string $uid the username
350
+     * @return boolean
351
+     * @throws \Exception when connection could not be established
352
+     */
353
+    public function userExists($uid) {
354
+        $userExists = $this->access->connection->getFromCache('userExists'.$uid);
355
+        if(!is_null($userExists)) {
356
+            return (bool)$userExists;
357
+        }
358
+        //getting dn, if false the user does not exist. If dn, he may be mapped only, requires more checking.
359
+        $user = $this->access->userManager->get($uid);
360
+
361
+        if(is_null($user)) {
362
+            Util::writeLog('user_ldap', 'No DN found for '.$uid.' on '.
363
+                $this->access->connection->ldapHost, Util::DEBUG);
364
+            $this->access->connection->writeToCache('userExists'.$uid, false);
365
+            return false;
366
+        } else if($user instanceof OfflineUser) {
367
+            //express check for users marked as deleted. Returning true is
368
+            //necessary for cleanup
369
+            return true;
370
+        }
371
+
372
+        $result = $this->userExistsOnLDAP($user);
373
+        $this->access->connection->writeToCache('userExists'.$uid, $result);
374
+        if($result === true) {
375
+            $user->update();
376
+        }
377
+        return $result;
378
+    }
379
+
380
+    /**
381
+     * returns whether a user was deleted in LDAP
382
+     *
383
+     * @param string $uid The username of the user to delete
384
+     * @return bool
385
+     */
386
+    public function deleteUser($uid) {
387
+        if ($this->userPluginManager->canDeleteUser()) {
388
+            return $this->userPluginManager->deleteUser($uid);
389
+        }
390
+
391
+        $marked = $this->ocConfig->getUserValue($uid, 'user_ldap', 'isDeleted', 0);
392
+        if(intval($marked) === 0) {
393
+            \OC::$server->getLogger()->notice(
394
+                'User '.$uid . ' is not marked as deleted, not cleaning up.',
395
+                array('app' => 'user_ldap'));
396
+            return false;
397
+        }
398
+        \OC::$server->getLogger()->info('Cleaning up after user ' . $uid,
399
+            array('app' => 'user_ldap'));
400
+
401
+        $this->access->getUserMapper()->unmap($uid);
402
+        $this->access->userManager->invalidate($uid);
403
+        return true;
404
+    }
405
+
406
+    /**
407
+     * get the user's home directory
408
+     *
409
+     * @param string $uid the username
410
+     * @return bool|string
411
+     * @throws NoUserException
412
+     * @throws \Exception
413
+     */
414
+    public function getHome($uid) {
415
+        // user Exists check required as it is not done in user proxy!
416
+        if(!$this->userExists($uid)) {
417
+            return false;
418
+        }
419
+
420
+        if ($this->userPluginManager->implementsActions(Backend::GET_HOME)) {
421
+            return $this->userPluginManager->getHome($uid);
422
+        }
423
+
424
+        $cacheKey = 'getHome'.$uid;
425
+        $path = $this->access->connection->getFromCache($cacheKey);
426
+        if(!is_null($path)) {
427
+            return $path;
428
+        }
429
+
430
+        // early return path if it is a deleted user
431
+        $user = $this->access->userManager->get($uid);
432
+        if($user instanceof OfflineUser) {
433
+            if($this->currentUserInDeletionProcess !== null
434
+                && $this->currentUserInDeletionProcess === $user->getOCName()
435
+            ) {
436
+                return $user->getHomePath();
437
+            } else {
438
+                throw new NoUserException($uid . ' is not a valid user anymore');
439
+            }
440
+        } else if ($user === null) {
441
+            throw new NoUserException($uid . ' is not a valid user anymore');
442
+        }
443
+
444
+        $path = $user->getHomePath();
445
+        $this->access->cacheUserHome($uid, $path);
446
+
447
+        return $path;
448
+    }
449
+
450
+    /**
451
+     * get display name of the user
452
+     * @param string $uid user ID of the user
453
+     * @return string|false display name
454
+     */
455
+    public function getDisplayName($uid) {
456
+        if ($this->userPluginManager->implementsActions(Backend::GET_DISPLAYNAME)) {
457
+            return $this->userPluginManager->getDisplayName($uid);
458
+        }
459
+
460
+        if(!$this->userExists($uid)) {
461
+            return false;
462
+        }
463
+
464
+        $cacheKey = 'getDisplayName'.$uid;
465
+        if(!is_null($displayName = $this->access->connection->getFromCache($cacheKey))) {
466
+            return $displayName;
467
+        }
468
+
469
+        //Check whether the display name is configured to have a 2nd feature
470
+        $additionalAttribute = $this->access->connection->ldapUserDisplayName2;
471
+        $displayName2 = '';
472
+        if ($additionalAttribute !== '') {
473
+            $displayName2 = $this->access->readAttribute(
474
+                $this->access->username2dn($uid),
475
+                $additionalAttribute);
476
+        }
477
+
478
+        $displayName = $this->access->readAttribute(
479
+            $this->access->username2dn($uid),
480
+            $this->access->connection->ldapUserDisplayName);
481
+
482
+        if($displayName && (count($displayName) > 0)) {
483
+            $displayName = $displayName[0];
484
+
485
+            if (is_array($displayName2)){
486
+                $displayName2 = count($displayName2) > 0 ? $displayName2[0] : '';
487
+            }
488
+
489
+            $user = $this->access->userManager->get($uid);
490
+            if ($user instanceof User) {
491
+                $displayName = $user->composeAndStoreDisplayName($displayName, $displayName2);
492
+                $this->access->connection->writeToCache($cacheKey, $displayName);
493
+            }
494
+            if ($user instanceof OfflineUser) {
495
+                /** @var OfflineUser $user*/
496
+                $displayName = $user->getDisplayName();
497
+            }
498
+            return $displayName;
499
+        }
500
+
501
+        return null;
502
+    }
503
+
504
+    /**
505
+     * set display name of the user
506
+     * @param string $uid user ID of the user
507
+     * @param string $displayName new display name of the user
508
+     * @return string|false display name
509
+     */
510
+    public function setDisplayName($uid, $displayName) {
511
+        if ($this->userPluginManager->implementsActions(Backend::SET_DISPLAYNAME)) {
512
+            return $this->userPluginManager->setDisplayName($uid, $displayName);
513
+        }
514
+        return false;
515
+    }
516
+
517
+    /**
518
+     * Get a list of all display names
519
+     *
520
+     * @param string $search
521
+     * @param string|null $limit
522
+     * @param string|null $offset
523
+     * @return array an array of all displayNames (value) and the corresponding uids (key)
524
+     */
525
+    public function getDisplayNames($search = '', $limit = null, $offset = null) {
526
+        $cacheKey = 'getDisplayNames-'.$search.'-'.$limit.'-'.$offset;
527
+        if(!is_null($displayNames = $this->access->connection->getFromCache($cacheKey))) {
528
+            return $displayNames;
529
+        }
530
+
531
+        $displayNames = array();
532
+        $users = $this->getUsers($search, $limit, $offset);
533
+        foreach ($users as $user) {
534
+            $displayNames[$user] = $this->getDisplayName($user);
535
+        }
536
+        $this->access->connection->writeToCache($cacheKey, $displayNames);
537
+        return $displayNames;
538
+    }
539
+
540
+    /**
541
+     * Check if backend implements actions
542
+     * @param int $actions bitwise-or'ed actions
543
+     * @return boolean
544
+     *
545
+     * Returns the supported actions as int to be
546
+     * compared with \OC\User\Backend::CREATE_USER etc.
547
+     */
548
+    public function implementsActions($actions) {
549
+        return (bool)((Backend::CHECK_PASSWORD
550
+            | Backend::GET_HOME
551
+            | Backend::GET_DISPLAYNAME
552
+            | Backend::PROVIDE_AVATAR
553
+            | Backend::COUNT_USERS
554
+            | ((intval($this->access->connection->turnOnPasswordChange) === 1)?(Backend::SET_PASSWORD):0)
555
+            | $this->userPluginManager->getImplementedActions())
556
+            & $actions);
557
+    }
558
+
559
+    /**
560
+     * @return bool
561
+     */
562
+    public function hasUserListings() {
563
+        return true;
564
+    }
565
+
566
+    /**
567
+     * counts the users in LDAP
568
+     *
569
+     * @return int|bool
570
+     */
571
+    public function countUsers() {
572
+        if ($this->userPluginManager->implementsActions(Backend::COUNT_USERS)) {
573
+            return $this->userPluginManager->countUsers();
574
+        }
575
+
576
+        $filter = $this->access->getFilterForUserCount();
577
+        $cacheKey = 'countUsers-'.$filter;
578
+        if(!is_null($entries = $this->access->connection->getFromCache($cacheKey))) {
579
+            return $entries;
580
+        }
581
+        $entries = $this->access->countUsers($filter);
582
+        $this->access->connection->writeToCache($cacheKey, $entries);
583
+        return $entries;
584
+    }
585
+
586
+    /**
587
+     * Backend name to be shown in user management
588
+     * @return string the name of the backend to be shown
589
+     */
590
+    public function getBackendName(){
591
+        return 'LDAP';
592
+    }
593 593
 	
594
-	/**
595
-	 * Return access for LDAP interaction.
596
-	 * @param string $uid
597
-	 * @return Access instance of Access for LDAP interaction
598
-	 */
599
-	public function getLDAPAccess($uid) {
600
-		return $this->access;
601
-	}
594
+    /**
595
+     * Return access for LDAP interaction.
596
+     * @param string $uid
597
+     * @return Access instance of Access for LDAP interaction
598
+     */
599
+    public function getLDAPAccess($uid) {
600
+        return $this->access;
601
+    }
602 602
 	
603
-	/**
604
-	 * Return LDAP connection resource from a cloned connection.
605
-	 * The cloned connection needs to be closed manually.
606
-	 * of the current access.
607
-	 * @param string $uid
608
-	 * @return resource of the LDAP connection
609
-	 */
610
-	public function getNewLDAPConnection($uid) {
611
-		$connection = clone $this->access->getConnection();
612
-		return $connection->getConnectionResource();
613
-	}
614
-
615
-	/**
616
-	 * create new user
617
-	 * @param string $username username of the new user
618
-	 * @param string $password password of the new user
619
-	 * @return bool was the user created?
620
-	 */
621
-	public function createUser($username, $password) {
622
-		if ($this->userPluginManager->implementsActions(Backend::CREATE_USER)) {
623
-			return $this->userPluginManager->createUser($username, $password);
624
-		}
625
-		return false;
626
-	}
603
+    /**
604
+     * Return LDAP connection resource from a cloned connection.
605
+     * The cloned connection needs to be closed manually.
606
+     * of the current access.
607
+     * @param string $uid
608
+     * @return resource of the LDAP connection
609
+     */
610
+    public function getNewLDAPConnection($uid) {
611
+        $connection = clone $this->access->getConnection();
612
+        return $connection->getConnectionResource();
613
+    }
614
+
615
+    /**
616
+     * create new user
617
+     * @param string $username username of the new user
618
+     * @param string $password password of the new user
619
+     * @return bool was the user created?
620
+     */
621
+    public function createUser($username, $password) {
622
+        if ($this->userPluginManager->implementsActions(Backend::CREATE_USER)) {
623
+            return $this->userPluginManager->createUser($username, $password);
624
+        }
625
+        return false;
626
+    }
627 627
 
628 628
 }
Please login to merge, or discard this patch.
Spacing   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -103,11 +103,11 @@  discard block
 block discarded – undo
103 103
 		}
104 104
 
105 105
 		$user = $this->access->userManager->get($uid);
106
-		if(!$user instanceof User) {
106
+		if (!$user instanceof User) {
107 107
 			return false;
108 108
 		}
109 109
 		$imageData = $user->getAvatarImage();
110
-		if($imageData === false) {
110
+		if ($imageData === false) {
111 111
 			return true;
112 112
 		}
113 113
 		return !$user->updateAvatar(true);
@@ -122,14 +122,14 @@  discard block
 block discarded – undo
122 122
 	public function loginName2UserName($loginName) {
123 123
 		$cacheKey = 'loginName2UserName-'.$loginName;
124 124
 		$username = $this->access->connection->getFromCache($cacheKey);
125
-		if(!is_null($username)) {
125
+		if (!is_null($username)) {
126 126
 			return $username;
127 127
 		}
128 128
 
129 129
 		try {
130 130
 			$ldapRecord = $this->getLDAPUserByLoginName($loginName);
131 131
 			$user = $this->access->userManager->get($ldapRecord['dn'][0]);
132
-			if($user instanceof OfflineUser) {
132
+			if ($user instanceof OfflineUser) {
133 133
 				// this path is not really possible, however get() is documented
134 134
 				// to return User or OfflineUser so we are very defensive here.
135 135
 				$this->access->connection->writeToCache($cacheKey, false);
@@ -165,9 +165,9 @@  discard block
 block discarded – undo
165 165
 		//find out dn of the user name
166 166
 		$attrs = $this->access->userManager->getAttributes();
167 167
 		$users = $this->access->fetchUsersByLoginName($loginName, $attrs);
168
-		if(count($users) < 1) {
169
-			throw new NotOnLDAP('No user available for the given login name on ' .
170
-				$this->access->connection->ldapHost . ':' . $this->access->connection->ldapPort);
168
+		if (count($users) < 1) {
169
+			throw new NotOnLDAP('No user available for the given login name on '.
170
+				$this->access->connection->ldapHost.':'.$this->access->connection->ldapPort);
171 171
 		}
172 172
 		return $users[0];
173 173
 	}
@@ -182,8 +182,8 @@  discard block
 block discarded – undo
182 182
 	public function checkPassword($uid, $password) {
183 183
 		try {
184 184
 			$ldapRecord = $this->getLDAPUserByLoginName($uid);
185
-		} catch(NotOnLDAP $e) {
186
-			if($this->ocConfig->getSystemValue('loglevel', Util::WARN) === Util::DEBUG) {
185
+		} catch (NotOnLDAP $e) {
186
+			if ($this->ocConfig->getSystemValue('loglevel', Util::WARN) === Util::DEBUG) {
187 187
 				\OC::$server->getLogger()->logException($e, ['app' => 'user_ldap']);
188 188
 			}
189 189
 			return false;
@@ -191,16 +191,16 @@  discard block
 block discarded – undo
191 191
 		$dn = $ldapRecord['dn'][0];
192 192
 		$user = $this->access->userManager->get($dn);
193 193
 
194
-		if(!$user instanceof User) {
194
+		if (!$user instanceof User) {
195 195
 			Util::writeLog('user_ldap',
196
-				'LDAP Login: Could not get user object for DN ' . $dn .
196
+				'LDAP Login: Could not get user object for DN '.$dn.
197 197
 				'. Maybe the LDAP entry has no set display name attribute?',
198 198
 				Util::WARN);
199 199
 			return false;
200 200
 		}
201
-		if($user->getUsername() !== false) {
201
+		if ($user->getUsername() !== false) {
202 202
 			//are the credentials OK?
203
-			if(!$this->access->areCredentialsValid($dn, $password)) {
203
+			if (!$this->access->areCredentialsValid($dn, $password)) {
204 204
 				return false;
205 205
 			}
206 206
 
@@ -227,11 +227,11 @@  discard block
 block discarded – undo
227 227
 
228 228
 		$user = $this->access->userManager->get($uid);
229 229
 
230
-		if(!$user instanceof User) {
231
-			throw new \Exception('LDAP setPassword: Could not get user object for uid ' . $uid .
230
+		if (!$user instanceof User) {
231
+			throw new \Exception('LDAP setPassword: Could not get user object for uid '.$uid.
232 232
 				'. Maybe the LDAP entry has no set display name attribute?');
233 233
 		}
234
-		if($user->getUsername() !== false && $this->access->setPassword($user->getDN(), $password)) {
234
+		if ($user->getUsername() !== false && $this->access->setPassword($user->getDN(), $password)) {
235 235
 			$ldapDefaultPPolicyDN = $this->access->connection->ldapDefaultPPolicyDN;
236 236
 			$turnOnPasswordChange = $this->access->connection->turnOnPasswordChange;
237 237
 			if (!empty($ldapDefaultPPolicyDN) && (intval($turnOnPasswordChange) === 1)) {
@@ -263,18 +263,18 @@  discard block
 block discarded – undo
263 263
 
264 264
 		//check if users are cached, if so return
265 265
 		$ldap_users = $this->access->connection->getFromCache($cachekey);
266
-		if(!is_null($ldap_users)) {
266
+		if (!is_null($ldap_users)) {
267 267
 			return $ldap_users;
268 268
 		}
269 269
 
270 270
 		// if we'd pass -1 to LDAP search, we'd end up in a Protocol
271 271
 		// error. With a limit of 0, we get 0 results. So we pass null.
272
-		if($limit <= 0) {
272
+		if ($limit <= 0) {
273 273
 			$limit = null;
274 274
 		}
275 275
 		$filter = $this->access->combineFilterWithAnd(array(
276 276
 			$this->access->connection->ldapUserFilter,
277
-			$this->access->connection->ldapUserDisplayName . '=*',
277
+			$this->access->connection->ldapUserDisplayName.'=*',
278 278
 			$this->access->getFilterPartForUserSearch($search)
279 279
 		));
280 280
 
@@ -287,7 +287,7 @@  discard block
 block discarded – undo
287 287
 			$this->access->userManager->getAttributes(true),
288 288
 			$limit, $offset);
289 289
 		$ldap_users = $this->access->nextcloudUserNames($ldap_users);
290
-		Util::writeLog('user_ldap', 'getUsers: '.count($ldap_users). ' Users found', Util::DEBUG);
290
+		Util::writeLog('user_ldap', 'getUsers: '.count($ldap_users).' Users found', Util::DEBUG);
291 291
 
292 292
 		$this->access->connection->writeToCache($cachekey, $ldap_users);
293 293
 		return $ldap_users;
@@ -303,19 +303,19 @@  discard block
 block discarded – undo
303 303
 	 * @throws \OC\ServerNotAvailableException
304 304
 	 */
305 305
 	public function userExistsOnLDAP($user) {
306
-		if(is_string($user)) {
306
+		if (is_string($user)) {
307 307
 			$user = $this->access->userManager->get($user);
308 308
 		}
309
-		if(is_null($user)) {
309
+		if (is_null($user)) {
310 310
 			return false;
311 311
 		}
312 312
 
313 313
 		$dn = $user->getDN();
314 314
 		//check if user really still exists by reading its entry
315
-		if(!is_array($this->access->readAttribute($dn, '', $this->access->connection->ldapUserFilter))) {
315
+		if (!is_array($this->access->readAttribute($dn, '', $this->access->connection->ldapUserFilter))) {
316 316
 			$lcr = $this->access->connection->getConnectionResource();
317
-			if(is_null($lcr)) {
318
-				throw new \Exception('No LDAP Connection to server ' . $this->access->connection->ldapHost);
317
+			if (is_null($lcr)) {
318
+				throw new \Exception('No LDAP Connection to server '.$this->access->connection->ldapHost);
319 319
 			}
320 320
 
321 321
 			try {
@@ -337,7 +337,7 @@  discard block
 block discarded – undo
337 337
 			}
338 338
 		}
339 339
 
340
-		if($user instanceof OfflineUser) {
340
+		if ($user instanceof OfflineUser) {
341 341
 			$user->unmark();
342 342
 		}
343 343
 
@@ -352,18 +352,18 @@  discard block
 block discarded – undo
352 352
 	 */
353 353
 	public function userExists($uid) {
354 354
 		$userExists = $this->access->connection->getFromCache('userExists'.$uid);
355
-		if(!is_null($userExists)) {
356
-			return (bool)$userExists;
355
+		if (!is_null($userExists)) {
356
+			return (bool) $userExists;
357 357
 		}
358 358
 		//getting dn, if false the user does not exist. If dn, he may be mapped only, requires more checking.
359 359
 		$user = $this->access->userManager->get($uid);
360 360
 
361
-		if(is_null($user)) {
361
+		if (is_null($user)) {
362 362
 			Util::writeLog('user_ldap', 'No DN found for '.$uid.' on '.
363 363
 				$this->access->connection->ldapHost, Util::DEBUG);
364 364
 			$this->access->connection->writeToCache('userExists'.$uid, false);
365 365
 			return false;
366
-		} else if($user instanceof OfflineUser) {
366
+		} else if ($user instanceof OfflineUser) {
367 367
 			//express check for users marked as deleted. Returning true is
368 368
 			//necessary for cleanup
369 369
 			return true;
@@ -371,7 +371,7 @@  discard block
 block discarded – undo
371 371
 
372 372
 		$result = $this->userExistsOnLDAP($user);
373 373
 		$this->access->connection->writeToCache('userExists'.$uid, $result);
374
-		if($result === true) {
374
+		if ($result === true) {
375 375
 			$user->update();
376 376
 		}
377 377
 		return $result;
@@ -389,13 +389,13 @@  discard block
 block discarded – undo
389 389
 		}
390 390
 
391 391
 		$marked = $this->ocConfig->getUserValue($uid, 'user_ldap', 'isDeleted', 0);
392
-		if(intval($marked) === 0) {
392
+		if (intval($marked) === 0) {
393 393
 			\OC::$server->getLogger()->notice(
394
-				'User '.$uid . ' is not marked as deleted, not cleaning up.',
394
+				'User '.$uid.' is not marked as deleted, not cleaning up.',
395 395
 				array('app' => 'user_ldap'));
396 396
 			return false;
397 397
 		}
398
-		\OC::$server->getLogger()->info('Cleaning up after user ' . $uid,
398
+		\OC::$server->getLogger()->info('Cleaning up after user '.$uid,
399 399
 			array('app' => 'user_ldap'));
400 400
 
401 401
 		$this->access->getUserMapper()->unmap($uid);
@@ -413,7 +413,7 @@  discard block
 block discarded – undo
413 413
 	 */
414 414
 	public function getHome($uid) {
415 415
 		// user Exists check required as it is not done in user proxy!
416
-		if(!$this->userExists($uid)) {
416
+		if (!$this->userExists($uid)) {
417 417
 			return false;
418 418
 		}
419 419
 
@@ -423,22 +423,22 @@  discard block
 block discarded – undo
423 423
 
424 424
 		$cacheKey = 'getHome'.$uid;
425 425
 		$path = $this->access->connection->getFromCache($cacheKey);
426
-		if(!is_null($path)) {
426
+		if (!is_null($path)) {
427 427
 			return $path;
428 428
 		}
429 429
 
430 430
 		// early return path if it is a deleted user
431 431
 		$user = $this->access->userManager->get($uid);
432
-		if($user instanceof OfflineUser) {
433
-			if($this->currentUserInDeletionProcess !== null
432
+		if ($user instanceof OfflineUser) {
433
+			if ($this->currentUserInDeletionProcess !== null
434 434
 				&& $this->currentUserInDeletionProcess === $user->getOCName()
435 435
 			) {
436 436
 				return $user->getHomePath();
437 437
 			} else {
438
-				throw new NoUserException($uid . ' is not a valid user anymore');
438
+				throw new NoUserException($uid.' is not a valid user anymore');
439 439
 			}
440 440
 		} else if ($user === null) {
441
-			throw new NoUserException($uid . ' is not a valid user anymore');
441
+			throw new NoUserException($uid.' is not a valid user anymore');
442 442
 		}
443 443
 
444 444
 		$path = $user->getHomePath();
@@ -457,12 +457,12 @@  discard block
 block discarded – undo
457 457
 			return $this->userPluginManager->getDisplayName($uid);
458 458
 		}
459 459
 
460
-		if(!$this->userExists($uid)) {
460
+		if (!$this->userExists($uid)) {
461 461
 			return false;
462 462
 		}
463 463
 
464 464
 		$cacheKey = 'getDisplayName'.$uid;
465
-		if(!is_null($displayName = $this->access->connection->getFromCache($cacheKey))) {
465
+		if (!is_null($displayName = $this->access->connection->getFromCache($cacheKey))) {
466 466
 			return $displayName;
467 467
 		}
468 468
 
@@ -479,10 +479,10 @@  discard block
 block discarded – undo
479 479
 			$this->access->username2dn($uid),
480 480
 			$this->access->connection->ldapUserDisplayName);
481 481
 
482
-		if($displayName && (count($displayName) > 0)) {
482
+		if ($displayName && (count($displayName) > 0)) {
483 483
 			$displayName = $displayName[0];
484 484
 
485
-			if (is_array($displayName2)){
485
+			if (is_array($displayName2)) {
486 486
 				$displayName2 = count($displayName2) > 0 ? $displayName2[0] : '';
487 487
 			}
488 488
 
@@ -524,7 +524,7 @@  discard block
 block discarded – undo
524 524
 	 */
525 525
 	public function getDisplayNames($search = '', $limit = null, $offset = null) {
526 526
 		$cacheKey = 'getDisplayNames-'.$search.'-'.$limit.'-'.$offset;
527
-		if(!is_null($displayNames = $this->access->connection->getFromCache($cacheKey))) {
527
+		if (!is_null($displayNames = $this->access->connection->getFromCache($cacheKey))) {
528 528
 			return $displayNames;
529 529
 		}
530 530
 
@@ -546,12 +546,12 @@  discard block
 block discarded – undo
546 546
 	* compared with \OC\User\Backend::CREATE_USER etc.
547 547
 	*/
548 548
 	public function implementsActions($actions) {
549
-		return (bool)((Backend::CHECK_PASSWORD
549
+		return (bool) ((Backend::CHECK_PASSWORD
550 550
 			| Backend::GET_HOME
551 551
 			| Backend::GET_DISPLAYNAME
552 552
 			| Backend::PROVIDE_AVATAR
553 553
 			| Backend::COUNT_USERS
554
-			| ((intval($this->access->connection->turnOnPasswordChange) === 1)?(Backend::SET_PASSWORD):0)
554
+			| ((intval($this->access->connection->turnOnPasswordChange) === 1) ? (Backend::SET_PASSWORD) : 0)
555 555
 			| $this->userPluginManager->getImplementedActions())
556 556
 			& $actions);
557 557
 	}
@@ -575,7 +575,7 @@  discard block
 block discarded – undo
575 575
 
576 576
 		$filter = $this->access->getFilterForUserCount();
577 577
 		$cacheKey = 'countUsers-'.$filter;
578
-		if(!is_null($entries = $this->access->connection->getFromCache($cacheKey))) {
578
+		if (!is_null($entries = $this->access->connection->getFromCache($cacheKey))) {
579 579
 			return $entries;
580 580
 		}
581 581
 		$entries = $this->access->countUsers($filter);
@@ -587,7 +587,7 @@  discard block
 block discarded – undo
587 587
 	 * Backend name to be shown in user management
588 588
 	 * @return string the name of the backend to be shown
589 589
 	 */
590
-	public function getBackendName(){
590
+	public function getBackendName() {
591 591
 		return 'LDAP';
592 592
 	}
593 593
 	
Please login to merge, or discard this patch.