Completed
Pull Request — master (#7057)
by Blizzz
16:13
created
apps/user_ldap/lib/Proxy.php 1 patch
Indentation   +166 added lines, -166 removed lines patch added patch discarded remove patch
@@ -35,170 +35,170 @@
 block discarded – undo
35 35
 use OCA\User_LDAP\User\Manager;
36 36
 
37 37
 abstract class Proxy {
38
-	static private $accesses = array();
39
-	private $ldap = null;
40
-
41
-	/** @var \OCP\ICache|null */
42
-	private $cache;
43
-
44
-	/**
45
-	 * @param ILDAPWrapper $ldap
46
-	 */
47
-	public function __construct(ILDAPWrapper $ldap) {
48
-		$this->ldap = $ldap;
49
-		$memcache = \OC::$server->getMemCacheFactory();
50
-		if($memcache->isAvailable()) {
51
-			$this->cache = $memcache->create();
52
-		}
53
-	}
54
-
55
-	/**
56
-	 * @param string $configPrefix
57
-	 */
58
-	private function addAccess($configPrefix) {
59
-		static $ocConfig;
60
-		static $fs;
61
-		static $log;
62
-		static $avatarM;
63
-		static $userMap;
64
-		static $groupMap;
65
-		static $db;
66
-		static $coreUserManager;
67
-		static $coreNotificationManager;
68
-		if($fs === null) {
69
-			$ocConfig = \OC::$server->getConfig();
70
-			$fs       = new FilesystemHelper();
71
-			$log      = new LogWrapper();
72
-			$avatarM  = \OC::$server->getAvatarManager();
73
-			$db       = \OC::$server->getDatabaseConnection();
74
-			$userMap  = new UserMapping($db);
75
-			$groupMap = new GroupMapping($db);
76
-			$coreUserManager = \OC::$server->getUserManager();
77
-			$coreNotificationManager = \OC::$server->getNotificationManager();
78
-		}
79
-		$userManager =
80
-			new Manager($ocConfig, $fs, $log, $avatarM, new \OCP\Image(), $db,
81
-				$coreUserManager, $coreNotificationManager);
82
-		$connector = new Connection($this->ldap, $configPrefix);
83
-		$access = new Access($connector, $this->ldap, $userManager, new Helper(\OC::$server->getConfig()), \OC::$server);
84
-		$access->setUserMapper($userMap);
85
-		$access->setGroupMapper($groupMap);
86
-		self::$accesses[$configPrefix] = $access;
87
-	}
88
-
89
-	/**
90
-	 * @param string $configPrefix
91
-	 * @return mixed
92
-	 */
93
-	protected function getAccess($configPrefix) {
94
-		if(!isset(self::$accesses[$configPrefix])) {
95
-			$this->addAccess($configPrefix);
96
-		}
97
-		return self::$accesses[$configPrefix];
98
-	}
99
-
100
-	/**
101
-	 * @param string $uid
102
-	 * @return string
103
-	 */
104
-	protected function getUserCacheKey($uid) {
105
-		return 'user-'.$uid.'-lastSeenOn';
106
-	}
107
-
108
-	/**
109
-	 * @param string $gid
110
-	 * @return string
111
-	 */
112
-	protected function getGroupCacheKey($gid) {
113
-		return 'group-'.$gid.'-lastSeenOn';
114
-	}
115
-
116
-	/**
117
-	 * @param string $id
118
-	 * @param string $method
119
-	 * @param array $parameters
120
-	 * @param bool $passOnWhen
121
-	 * @return mixed
122
-	 */
123
-	abstract protected function callOnLastSeenOn($id, $method, $parameters, $passOnWhen);
124
-
125
-	/**
126
-	 * @param string $id
127
-	 * @param string $method
128
-	 * @param array $parameters
129
-	 * @return mixed
130
-	 */
131
-	abstract protected function walkBackends($id, $method, $parameters);
132
-
133
-	/**
134
-	 * @param string $id
135
-	 * @return Access
136
-	 */
137
-	abstract public function getLDAPAccess($id);
138
-
139
-	/**
140
-	 * Takes care of the request to the User backend
141
-	 * @param string $id
142
-	 * @param string $method string, the method of the user backend that shall be called
143
-	 * @param array $parameters an array of parameters to be passed
144
-	 * @param bool $passOnWhen
145
-	 * @return mixed, the result of the specified method
146
-	 */
147
-	protected function handleRequest($id, $method, $parameters, $passOnWhen = false) {
148
-		$result = $this->callOnLastSeenOn($id,  $method, $parameters, $passOnWhen);
149
-		if($result === $passOnWhen) {
150
-			$result = $this->walkBackends($id, $method, $parameters);
151
-		}
152
-		return $result;
153
-	}
154
-
155
-	/**
156
-	 * @param string|null $key
157
-	 * @return string
158
-	 */
159
-	private function getCacheKey($key) {
160
-		$prefix = 'LDAP-Proxy-';
161
-		if($key === null) {
162
-			return $prefix;
163
-		}
164
-		return $prefix.md5($key);
165
-	}
166
-
167
-	/**
168
-	 * @param string $key
169
-	 * @return mixed|null
170
-	 */
171
-	public function getFromCache($key) {
172
-		if($this->cache === null) {
173
-			return null;
174
-		}
175
-
176
-		$key = $this->getCacheKey($key);
177
-		$value = $this->cache->get($key);
178
-		if ($value === null) {
179
-			return null;
180
-		}
181
-
182
-		return json_decode(base64_decode($value));
183
-	}
184
-
185
-	/**
186
-	 * @param string $key
187
-	 * @param mixed $value
188
-	 */
189
-	public function writeToCache($key, $value) {
190
-		if($this->cache === null) {
191
-			return;
192
-		}
193
-		$key   = $this->getCacheKey($key);
194
-		$value = base64_encode(json_encode($value));
195
-		$this->cache->set($key, $value, 2592000);
196
-	}
197
-
198
-	public function clearCache() {
199
-		if($this->cache === null) {
200
-			return;
201
-		}
202
-		$this->cache->clear($this->getCacheKey(null));
203
-	}
38
+    static private $accesses = array();
39
+    private $ldap = null;
40
+
41
+    /** @var \OCP\ICache|null */
42
+    private $cache;
43
+
44
+    /**
45
+     * @param ILDAPWrapper $ldap
46
+     */
47
+    public function __construct(ILDAPWrapper $ldap) {
48
+        $this->ldap = $ldap;
49
+        $memcache = \OC::$server->getMemCacheFactory();
50
+        if($memcache->isAvailable()) {
51
+            $this->cache = $memcache->create();
52
+        }
53
+    }
54
+
55
+    /**
56
+     * @param string $configPrefix
57
+     */
58
+    private function addAccess($configPrefix) {
59
+        static $ocConfig;
60
+        static $fs;
61
+        static $log;
62
+        static $avatarM;
63
+        static $userMap;
64
+        static $groupMap;
65
+        static $db;
66
+        static $coreUserManager;
67
+        static $coreNotificationManager;
68
+        if($fs === null) {
69
+            $ocConfig = \OC::$server->getConfig();
70
+            $fs       = new FilesystemHelper();
71
+            $log      = new LogWrapper();
72
+            $avatarM  = \OC::$server->getAvatarManager();
73
+            $db       = \OC::$server->getDatabaseConnection();
74
+            $userMap  = new UserMapping($db);
75
+            $groupMap = new GroupMapping($db);
76
+            $coreUserManager = \OC::$server->getUserManager();
77
+            $coreNotificationManager = \OC::$server->getNotificationManager();
78
+        }
79
+        $userManager =
80
+            new Manager($ocConfig, $fs, $log, $avatarM, new \OCP\Image(), $db,
81
+                $coreUserManager, $coreNotificationManager);
82
+        $connector = new Connection($this->ldap, $configPrefix);
83
+        $access = new Access($connector, $this->ldap, $userManager, new Helper(\OC::$server->getConfig()), \OC::$server);
84
+        $access->setUserMapper($userMap);
85
+        $access->setGroupMapper($groupMap);
86
+        self::$accesses[$configPrefix] = $access;
87
+    }
88
+
89
+    /**
90
+     * @param string $configPrefix
91
+     * @return mixed
92
+     */
93
+    protected function getAccess($configPrefix) {
94
+        if(!isset(self::$accesses[$configPrefix])) {
95
+            $this->addAccess($configPrefix);
96
+        }
97
+        return self::$accesses[$configPrefix];
98
+    }
99
+
100
+    /**
101
+     * @param string $uid
102
+     * @return string
103
+     */
104
+    protected function getUserCacheKey($uid) {
105
+        return 'user-'.$uid.'-lastSeenOn';
106
+    }
107
+
108
+    /**
109
+     * @param string $gid
110
+     * @return string
111
+     */
112
+    protected function getGroupCacheKey($gid) {
113
+        return 'group-'.$gid.'-lastSeenOn';
114
+    }
115
+
116
+    /**
117
+     * @param string $id
118
+     * @param string $method
119
+     * @param array $parameters
120
+     * @param bool $passOnWhen
121
+     * @return mixed
122
+     */
123
+    abstract protected function callOnLastSeenOn($id, $method, $parameters, $passOnWhen);
124
+
125
+    /**
126
+     * @param string $id
127
+     * @param string $method
128
+     * @param array $parameters
129
+     * @return mixed
130
+     */
131
+    abstract protected function walkBackends($id, $method, $parameters);
132
+
133
+    /**
134
+     * @param string $id
135
+     * @return Access
136
+     */
137
+    abstract public function getLDAPAccess($id);
138
+
139
+    /**
140
+     * Takes care of the request to the User backend
141
+     * @param string $id
142
+     * @param string $method string, the method of the user backend that shall be called
143
+     * @param array $parameters an array of parameters to be passed
144
+     * @param bool $passOnWhen
145
+     * @return mixed, the result of the specified method
146
+     */
147
+    protected function handleRequest($id, $method, $parameters, $passOnWhen = false) {
148
+        $result = $this->callOnLastSeenOn($id,  $method, $parameters, $passOnWhen);
149
+        if($result === $passOnWhen) {
150
+            $result = $this->walkBackends($id, $method, $parameters);
151
+        }
152
+        return $result;
153
+    }
154
+
155
+    /**
156
+     * @param string|null $key
157
+     * @return string
158
+     */
159
+    private function getCacheKey($key) {
160
+        $prefix = 'LDAP-Proxy-';
161
+        if($key === null) {
162
+            return $prefix;
163
+        }
164
+        return $prefix.md5($key);
165
+    }
166
+
167
+    /**
168
+     * @param string $key
169
+     * @return mixed|null
170
+     */
171
+    public function getFromCache($key) {
172
+        if($this->cache === null) {
173
+            return null;
174
+        }
175
+
176
+        $key = $this->getCacheKey($key);
177
+        $value = $this->cache->get($key);
178
+        if ($value === null) {
179
+            return null;
180
+        }
181
+
182
+        return json_decode(base64_decode($value));
183
+    }
184
+
185
+    /**
186
+     * @param string $key
187
+     * @param mixed $value
188
+     */
189
+    public function writeToCache($key, $value) {
190
+        if($this->cache === null) {
191
+            return;
192
+        }
193
+        $key   = $this->getCacheKey($key);
194
+        $value = base64_encode(json_encode($value));
195
+        $this->cache->set($key, $value, 2592000);
196
+    }
197
+
198
+    public function clearCache() {
199
+        if($this->cache === null) {
200
+            return;
201
+        }
202
+        $this->cache->clear($this->getCacheKey(null));
203
+    }
204 204
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/User_LDAP.php 1 patch
Indentation   +511 added lines, -511 removed lines patch added patch discarded remove patch
@@ -47,518 +47,518 @@
 block discarded – undo
47 47
 use OCP\Util;
48 48
 
49 49
 class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserInterface, IUserLDAP {
50
-	/** @var \OCP\IConfig */
51
-	protected $ocConfig;
52
-
53
-	/** @var INotificationManager */
54
-	protected $notificationManager;
55
-
56
-	/** @var string */
57
-	protected $currentUserInDeletionProcess;
58
-
59
-	/**
60
-	 * @param Access $access
61
-	 * @param \OCP\IConfig $ocConfig
62
-	 * @param \OCP\Notification\IManager $notificationManager
63
-	 * @param IUserSession $userSession
64
-	 */
65
-	public function __construct(Access $access, IConfig $ocConfig, INotificationManager $notificationManager, IUserSession $userSession) {
66
-		parent::__construct($access);
67
-		$this->ocConfig = $ocConfig;
68
-		$this->notificationManager = $notificationManager;
69
-		$this->registerHooks($userSession);
70
-	}
71
-
72
-	protected function registerHooks(IUserSession $userSession) {
73
-		$userSession->listen('\OC\User', 'preDelete', [$this, 'preDeleteUser']);
74
-		$userSession->listen('\OC\User', 'postDelete', [$this, 'postDeleteUser']);
75
-	}
76
-
77
-	public function preDeleteUser(IUser $user) {
78
-		$this->currentUserInDeletionProcess = $user->getUID();
79
-	}
80
-
81
-	public function postDeleteUser() {
82
-		$this->currentUserInDeletionProcess = null;
83
-	}
84
-
85
-	/**
86
-	 * checks whether the user is allowed to change his avatar in Nextcloud
87
-	 * @param string $uid the Nextcloud user name
88
-	 * @return boolean either the user can or cannot
89
-	 */
90
-	public function canChangeAvatar($uid) {
91
-		$user = $this->access->userManager->get($uid);
92
-		if(!$user instanceof User) {
93
-			return false;
94
-		}
95
-		if($user->getAvatarImage() === false) {
96
-			return true;
97
-		}
98
-
99
-		return false;
100
-	}
101
-
102
-	/**
103
-	 * returns the username for the given login name, if available
104
-	 *
105
-	 * @param string $loginName
106
-	 * @return string|false
107
-	 */
108
-	public function loginName2UserName($loginName) {
109
-		$cacheKey = 'loginName2UserName-'.$loginName;
110
-		$username = $this->access->connection->getFromCache($cacheKey);
111
-		if(!is_null($username)) {
112
-			return $username;
113
-		}
114
-
115
-		try {
116
-			$ldapRecord = $this->getLDAPUserByLoginName($loginName);
117
-			$user = $this->access->userManager->get($ldapRecord['dn'][0]);
118
-			if($user instanceof OfflineUser) {
119
-				// this path is not really possible, however get() is documented
120
-				// to return User or OfflineUser so we are very defensive here.
121
-				$this->access->connection->writeToCache($cacheKey, false);
122
-				return false;
123
-			}
124
-			$username = $user->getUsername();
125
-			$this->access->connection->writeToCache($cacheKey, $username);
126
-			return $username;
127
-		} catch (NotOnLDAP $e) {
128
-			$this->access->connection->writeToCache($cacheKey, false);
129
-			return false;
130
-		}
131
-	}
50
+    /** @var \OCP\IConfig */
51
+    protected $ocConfig;
52
+
53
+    /** @var INotificationManager */
54
+    protected $notificationManager;
55
+
56
+    /** @var string */
57
+    protected $currentUserInDeletionProcess;
58
+
59
+    /**
60
+     * @param Access $access
61
+     * @param \OCP\IConfig $ocConfig
62
+     * @param \OCP\Notification\IManager $notificationManager
63
+     * @param IUserSession $userSession
64
+     */
65
+    public function __construct(Access $access, IConfig $ocConfig, INotificationManager $notificationManager, IUserSession $userSession) {
66
+        parent::__construct($access);
67
+        $this->ocConfig = $ocConfig;
68
+        $this->notificationManager = $notificationManager;
69
+        $this->registerHooks($userSession);
70
+    }
71
+
72
+    protected function registerHooks(IUserSession $userSession) {
73
+        $userSession->listen('\OC\User', 'preDelete', [$this, 'preDeleteUser']);
74
+        $userSession->listen('\OC\User', 'postDelete', [$this, 'postDeleteUser']);
75
+    }
76
+
77
+    public function preDeleteUser(IUser $user) {
78
+        $this->currentUserInDeletionProcess = $user->getUID();
79
+    }
80
+
81
+    public function postDeleteUser() {
82
+        $this->currentUserInDeletionProcess = null;
83
+    }
84
+
85
+    /**
86
+     * checks whether the user is allowed to change his avatar in Nextcloud
87
+     * @param string $uid the Nextcloud user name
88
+     * @return boolean either the user can or cannot
89
+     */
90
+    public function canChangeAvatar($uid) {
91
+        $user = $this->access->userManager->get($uid);
92
+        if(!$user instanceof User) {
93
+            return false;
94
+        }
95
+        if($user->getAvatarImage() === false) {
96
+            return true;
97
+        }
98
+
99
+        return false;
100
+    }
101
+
102
+    /**
103
+     * returns the username for the given login name, if available
104
+     *
105
+     * @param string $loginName
106
+     * @return string|false
107
+     */
108
+    public function loginName2UserName($loginName) {
109
+        $cacheKey = 'loginName2UserName-'.$loginName;
110
+        $username = $this->access->connection->getFromCache($cacheKey);
111
+        if(!is_null($username)) {
112
+            return $username;
113
+        }
114
+
115
+        try {
116
+            $ldapRecord = $this->getLDAPUserByLoginName($loginName);
117
+            $user = $this->access->userManager->get($ldapRecord['dn'][0]);
118
+            if($user instanceof OfflineUser) {
119
+                // this path is not really possible, however get() is documented
120
+                // to return User or OfflineUser so we are very defensive here.
121
+                $this->access->connection->writeToCache($cacheKey, false);
122
+                return false;
123
+            }
124
+            $username = $user->getUsername();
125
+            $this->access->connection->writeToCache($cacheKey, $username);
126
+            return $username;
127
+        } catch (NotOnLDAP $e) {
128
+            $this->access->connection->writeToCache($cacheKey, false);
129
+            return false;
130
+        }
131
+    }
132 132
 	
133
-	/**
134
-	 * returns the username for the given LDAP DN, if available
135
-	 *
136
-	 * @param string $dn
137
-	 * @return string|false with the username
138
-	 */
139
-	public function dn2UserName($dn) {
140
-		return $this->access->dn2username($dn);
141
-	}
142
-
143
-	/**
144
-	 * returns an LDAP record based on a given login name
145
-	 *
146
-	 * @param string $loginName
147
-	 * @return array
148
-	 * @throws NotOnLDAP
149
-	 */
150
-	public function getLDAPUserByLoginName($loginName) {
151
-		//find out dn of the user name
152
-		$attrs = $this->access->userManager->getAttributes();
153
-		$users = $this->access->fetchUsersByLoginName($loginName, $attrs);
154
-		if(count($users) < 1) {
155
-			throw new NotOnLDAP('No user available for the given login name on ' .
156
-				$this->access->connection->ldapHost . ':' . $this->access->connection->ldapPort);
157
-		}
158
-		return $users[0];
159
-	}
160
-
161
-	/**
162
-	 * Check if the password is correct without logging in the user
163
-	 *
164
-	 * @param string $uid The username
165
-	 * @param string $password The password
166
-	 * @return false|string
167
-	 */
168
-	public function checkPassword($uid, $password) {
169
-		try {
170
-			$ldapRecord = $this->getLDAPUserByLoginName($uid);
171
-		} catch(NotOnLDAP $e) {
172
-			if($this->ocConfig->getSystemValue('loglevel', Util::WARN) === Util::DEBUG) {
173
-				\OC::$server->getLogger()->logException($e, ['app' => 'user_ldap']);
174
-			}
175
-			return false;
176
-		}
177
-		$dn = $ldapRecord['dn'][0];
178
-		$user = $this->access->userManager->get($dn);
179
-
180
-		if(!$user instanceof User) {
181
-			Util::writeLog('user_ldap',
182
-				'LDAP Login: Could not get user object for DN ' . $dn .
183
-				'. Maybe the LDAP entry has no set display name attribute?',
184
-				Util::WARN);
185
-			return false;
186
-		}
187
-		if($user->getUsername() !== false) {
188
-			//are the credentials OK?
189
-			if(!$this->access->areCredentialsValid($dn, $password)) {
190
-				return false;
191
-			}
192
-
193
-			$this->access->cacheUserExists($user->getUsername());
194
-			$user->processAttributes($ldapRecord);
195
-			$user->markLogin();
196
-
197
-			return $user->getUsername();
198
-		}
199
-
200
-		return false;
201
-	}
202
-
203
-	/**
204
-	 * Set password
205
-	 * @param string $uid The username
206
-	 * @param string $password The new password
207
-	 * @return bool
208
-	 */
209
-	public function setPassword($uid, $password) {
210
-		$user = $this->access->userManager->get($uid);
211
-
212
-		if(!$user instanceof User) {
213
-			throw new \Exception('LDAP setPassword: Could not get user object for uid ' . $uid .
214
-				'. Maybe the LDAP entry has no set display name attribute?');
215
-		}
216
-		if($user->getUsername() !== false && $this->access->setPassword($user->getDN(), $password)) {
217
-			$ldapDefaultPPolicyDN = $this->access->connection->ldapDefaultPPolicyDN;
218
-			$turnOnPasswordChange = $this->access->connection->turnOnPasswordChange;
219
-			if (!empty($ldapDefaultPPolicyDN) && (intval($turnOnPasswordChange) === 1)) {
220
-				//remove last password expiry warning if any
221
-				$notification = $this->notificationManager->createNotification();
222
-				$notification->setApp('user_ldap')
223
-					->setUser($uid)
224
-					->setObject('pwd_exp_warn', $uid)
225
-				;
226
-				$this->notificationManager->markProcessed($notification);
227
-			}
228
-			return true;
229
-		}
230
-
231
-		return false;
232
-	}
233
-
234
-	/**
235
-	 * Get a list of all users
236
-	 *
237
-	 * @param string $search
238
-	 * @param integer $limit
239
-	 * @param integer $offset
240
-	 * @return string[] an array of all uids
241
-	 */
242
-	public function getUsers($search = '', $limit = 10, $offset = 0) {
243
-		$search = $this->access->escapeFilterPart($search, true);
244
-		$cachekey = 'getUsers-'.$search.'-'.$limit.'-'.$offset;
245
-
246
-		//check if users are cached, if so return
247
-		$ldap_users = $this->access->connection->getFromCache($cachekey);
248
-		if(!is_null($ldap_users)) {
249
-			return $ldap_users;
250
-		}
251
-
252
-		// if we'd pass -1 to LDAP search, we'd end up in a Protocol
253
-		// error. With a limit of 0, we get 0 results. So we pass null.
254
-		if($limit <= 0) {
255
-			$limit = null;
256
-		}
257
-		$filter = $this->access->combineFilterWithAnd(array(
258
-			$this->access->connection->ldapUserFilter,
259
-			$this->access->connection->ldapUserDisplayName . '=*',
260
-			$this->access->getFilterPartForUserSearch($search)
261
-		));
262
-
263
-		Util::writeLog('user_ldap',
264
-			'getUsers: Options: search '.$search.' limit '.$limit.' offset '.$offset.' Filter: '.$filter,
265
-			Util::DEBUG);
266
-		//do the search and translate results to Nextcloud names
267
-		$ldap_users = $this->access->fetchListOfUsers(
268
-			$filter,
269
-			$this->access->userManager->getAttributes(true),
270
-			$limit, $offset);
271
-		$ldap_users = $this->access->nextcloudUserNames($ldap_users);
272
-		Util::writeLog('user_ldap', 'getUsers: '.count($ldap_users). ' Users found', Util::DEBUG);
273
-
274
-		$this->access->connection->writeToCache($cachekey, $ldap_users);
275
-		return $ldap_users;
276
-	}
277
-
278
-	/**
279
-	 * checks whether a user is still available on LDAP
280
-	 *
281
-	 * @param string|\OCA\User_LDAP\User\User $user either the Nextcloud user
282
-	 * name or an instance of that user
283
-	 * @return bool
284
-	 * @throws \Exception
285
-	 * @throws \OC\ServerNotAvailableException
286
-	 */
287
-	public function userExistsOnLDAP($user) {
288
-		if(is_string($user)) {
289
-			$user = $this->access->userManager->get($user);
290
-		}
291
-		if(is_null($user)) {
292
-			return false;
293
-		}
294
-
295
-		$dn = $user->getDN();
296
-		//check if user really still exists by reading its entry
297
-		if(!is_array($this->access->readAttribute($dn, '', $this->access->connection->ldapUserFilter))) {
298
-			$lcr = $this->access->connection->getConnectionResource();
299
-			if(is_null($lcr)) {
300
-				throw new \Exception('No LDAP Connection to server ' . $this->access->connection->ldapHost);
301
-			}
302
-
303
-			try {
304
-				$uuid = $this->access->getUserMapper()->getUUIDByDN($dn);
305
-				if(!$uuid) {
306
-					return false;
307
-				}
308
-				$newDn = $this->access->getUserDnByUuid($uuid);
309
-				//check if renamed user is still valid by reapplying the ldap filter
310
-				if(!is_array($this->access->readAttribute($newDn, '', $this->access->connection->ldapUserFilter))) {
311
-					return false;
312
-				}
313
-				$this->access->getUserMapper()->setDNbyUUID($newDn, $uuid);
314
-				return true;
315
-			} catch (\Exception $e) {
316
-				return false;
317
-			}
318
-		}
319
-
320
-		if($user instanceof OfflineUser) {
321
-			$user->unmark();
322
-		}
323
-
324
-		return true;
325
-	}
326
-
327
-	/**
328
-	 * check if a user exists
329
-	 * @param string $uid the username
330
-	 * @return boolean
331
-	 * @throws \Exception when connection could not be established
332
-	 */
333
-	public function userExists($uid) {
334
-		$userExists = $this->access->connection->getFromCache('userExists'.$uid);
335
-		if(!is_null($userExists)) {
336
-			return (bool)$userExists;
337
-		}
338
-		//getting dn, if false the user does not exist. If dn, he may be mapped only, requires more checking.
339
-		$user = $this->access->userManager->get($uid);
340
-
341
-		if(is_null($user)) {
342
-			Util::writeLog('user_ldap', 'No DN found for '.$uid.' on '.
343
-				$this->access->connection->ldapHost, Util::DEBUG);
344
-			$this->access->connection->writeToCache('userExists'.$uid, false);
345
-			return false;
346
-		} else if($user instanceof OfflineUser) {
347
-			//express check for users marked as deleted. Returning true is
348
-			//necessary for cleanup
349
-			return true;
350
-		}
351
-
352
-		$result = $this->userExistsOnLDAP($user);
353
-		$this->access->connection->writeToCache('userExists'.$uid, $result);
354
-		if($result === true) {
355
-			$user->update();
356
-		}
357
-		return $result;
358
-	}
359
-
360
-	/**
361
-	* returns whether a user was deleted in LDAP
362
-	*
363
-	* @param string $uid The username of the user to delete
364
-	* @return bool
365
-	*/
366
-	public function deleteUser($uid) {
367
-		$marked = $this->ocConfig->getUserValue($uid, 'user_ldap', 'isDeleted', 0);
368
-		if(intval($marked) === 0) {
369
-			\OC::$server->getLogger()->notice(
370
-				'User '.$uid . ' is not marked as deleted, not cleaning up.',
371
-				array('app' => 'user_ldap'));
372
-			return false;
373
-		}
374
-		\OC::$server->getLogger()->info('Cleaning up after user ' . $uid,
375
-			array('app' => 'user_ldap'));
376
-
377
-		$this->access->getUserMapper()->unmap($uid);
378
-		$this->access->userManager->invalidate($uid);
379
-		return true;
380
-	}
381
-
382
-	/**
383
-	 * get the user's home directory
384
-	 *
385
-	 * @param string $uid the username
386
-	 * @return bool|string
387
-	 * @throws NoUserException
388
-	 * @throws \Exception
389
-	 */
390
-	public function getHome($uid) {
391
-		// user Exists check required as it is not done in user proxy!
392
-		if(!$this->userExists($uid)) {
393
-			return false;
394
-		}
395
-
396
-		$cacheKey = 'getHome'.$uid;
397
-		$path = $this->access->connection->getFromCache($cacheKey);
398
-		if(!is_null($path)) {
399
-			return $path;
400
-		}
401
-
402
-		// early return path if it is a deleted user
403
-		$user = $this->access->userManager->get($uid);
404
-		if($user instanceof OfflineUser) {
405
-			if($this->currentUserInDeletionProcess !== null
406
-				&& $this->currentUserInDeletionProcess === $user->getOCName()
407
-			) {
408
-				return $user->getHomePath();
409
-			} else {
410
-				throw new NoUserException($uid . ' is not a valid user anymore');
411
-			}
412
-		} else if ($user === null) {
413
-			throw new NoUserException($uid . ' is not a valid user anymore');
414
-		}
415
-
416
-		$path = $user->getHomePath();
417
-		$this->access->cacheUserHome($uid, $path);
418
-
419
-		return $path;
420
-	}
421
-
422
-	/**
423
-	 * get display name of the user
424
-	 * @param string $uid user ID of the user
425
-	 * @return string|false display name
426
-	 */
427
-	public function getDisplayName($uid) {
428
-		if(!$this->userExists($uid)) {
429
-			return false;
430
-		}
431
-
432
-		$cacheKey = 'getDisplayName'.$uid;
433
-		if(!is_null($displayName = $this->access->connection->getFromCache($cacheKey))) {
434
-			return $displayName;
435
-		}
436
-
437
-		//Check whether the display name is configured to have a 2nd feature
438
-		$additionalAttribute = $this->access->connection->ldapUserDisplayName2;
439
-		$displayName2 = '';
440
-		if ($additionalAttribute !== '') {
441
-			$displayName2 = $this->access->readAttribute(
442
-				$this->access->username2dn($uid),
443
-				$additionalAttribute);
444
-		}
445
-
446
-		$displayName = $this->access->readAttribute(
447
-			$this->access->username2dn($uid),
448
-			$this->access->connection->ldapUserDisplayName);
449
-
450
-		if($displayName && (count($displayName) > 0)) {
451
-			$displayName = $displayName[0];
452
-
453
-			if (is_array($displayName2)){
454
-				$displayName2 = count($displayName2) > 0 ? $displayName2[0] : '';
455
-			}
456
-
457
-			$user = $this->access->userManager->get($uid);
458
-			if ($user instanceof User) {
459
-				$displayName = $user->composeAndStoreDisplayName($displayName, $displayName2);
460
-				$this->access->connection->writeToCache($cacheKey, $displayName);
461
-			}
462
-			if ($user instanceof OfflineUser) {
463
-				/** @var OfflineUser $user*/
464
-				$displayName = $user->getDisplayName();
465
-			}
466
-			return $displayName;
467
-		}
468
-
469
-		return null;
470
-	}
471
-
472
-	/**
473
-	 * Get a list of all display names
474
-	 *
475
-	 * @param string $search
476
-	 * @param string|null $limit
477
-	 * @param string|null $offset
478
-	 * @return array an array of all displayNames (value) and the corresponding uids (key)
479
-	 */
480
-	public function getDisplayNames($search = '', $limit = null, $offset = null) {
481
-		$cacheKey = 'getDisplayNames-'.$search.'-'.$limit.'-'.$offset;
482
-		if(!is_null($displayNames = $this->access->connection->getFromCache($cacheKey))) {
483
-			return $displayNames;
484
-		}
485
-
486
-		$displayNames = array();
487
-		$users = $this->getUsers($search, $limit, $offset);
488
-		foreach ($users as $user) {
489
-			$displayNames[$user] = $this->getDisplayName($user);
490
-		}
491
-		$this->access->connection->writeToCache($cacheKey, $displayNames);
492
-		return $displayNames;
493
-	}
494
-
495
-	/**
496
-	* Check if backend implements actions
497
-	* @param int $actions bitwise-or'ed actions
498
-	* @return boolean
499
-	*
500
-	* Returns the supported actions as int to be
501
-	* compared with \OC\User\Backend::CREATE_USER etc.
502
-	*/
503
-	public function implementsActions($actions) {
504
-		return (bool)((Backend::CHECK_PASSWORD
505
-			| Backend::GET_HOME
506
-			| Backend::GET_DISPLAYNAME
507
-			| Backend::PROVIDE_AVATAR
508
-			| Backend::COUNT_USERS
509
-			| ((intval($this->access->connection->turnOnPasswordChange) === 1)?(Backend::SET_PASSWORD):0))
510
-			& $actions);
511
-	}
512
-
513
-	/**
514
-	 * @return bool
515
-	 */
516
-	public function hasUserListings() {
517
-		return true;
518
-	}
519
-
520
-	/**
521
-	 * counts the users in LDAP
522
-	 *
523
-	 * @return int|bool
524
-	 */
525
-	public function countUsers() {
526
-		$filter = $this->access->getFilterForUserCount();
527
-		$cacheKey = 'countUsers-'.$filter;
528
-		if(!is_null($entries = $this->access->connection->getFromCache($cacheKey))) {
529
-			return $entries;
530
-		}
531
-		$entries = $this->access->countUsers($filter);
532
-		$this->access->connection->writeToCache($cacheKey, $entries);
533
-		return $entries;
534
-	}
535
-
536
-	/**
537
-	 * Backend name to be shown in user management
538
-	 * @return string the name of the backend to be shown
539
-	 */
540
-	public function getBackendName(){
541
-		return 'LDAP';
542
-	}
133
+    /**
134
+     * returns the username for the given LDAP DN, if available
135
+     *
136
+     * @param string $dn
137
+     * @return string|false with the username
138
+     */
139
+    public function dn2UserName($dn) {
140
+        return $this->access->dn2username($dn);
141
+    }
142
+
143
+    /**
144
+     * returns an LDAP record based on a given login name
145
+     *
146
+     * @param string $loginName
147
+     * @return array
148
+     * @throws NotOnLDAP
149
+     */
150
+    public function getLDAPUserByLoginName($loginName) {
151
+        //find out dn of the user name
152
+        $attrs = $this->access->userManager->getAttributes();
153
+        $users = $this->access->fetchUsersByLoginName($loginName, $attrs);
154
+        if(count($users) < 1) {
155
+            throw new NotOnLDAP('No user available for the given login name on ' .
156
+                $this->access->connection->ldapHost . ':' . $this->access->connection->ldapPort);
157
+        }
158
+        return $users[0];
159
+    }
160
+
161
+    /**
162
+     * Check if the password is correct without logging in the user
163
+     *
164
+     * @param string $uid The username
165
+     * @param string $password The password
166
+     * @return false|string
167
+     */
168
+    public function checkPassword($uid, $password) {
169
+        try {
170
+            $ldapRecord = $this->getLDAPUserByLoginName($uid);
171
+        } catch(NotOnLDAP $e) {
172
+            if($this->ocConfig->getSystemValue('loglevel', Util::WARN) === Util::DEBUG) {
173
+                \OC::$server->getLogger()->logException($e, ['app' => 'user_ldap']);
174
+            }
175
+            return false;
176
+        }
177
+        $dn = $ldapRecord['dn'][0];
178
+        $user = $this->access->userManager->get($dn);
179
+
180
+        if(!$user instanceof User) {
181
+            Util::writeLog('user_ldap',
182
+                'LDAP Login: Could not get user object for DN ' . $dn .
183
+                '. Maybe the LDAP entry has no set display name attribute?',
184
+                Util::WARN);
185
+            return false;
186
+        }
187
+        if($user->getUsername() !== false) {
188
+            //are the credentials OK?
189
+            if(!$this->access->areCredentialsValid($dn, $password)) {
190
+                return false;
191
+            }
192
+
193
+            $this->access->cacheUserExists($user->getUsername());
194
+            $user->processAttributes($ldapRecord);
195
+            $user->markLogin();
196
+
197
+            return $user->getUsername();
198
+        }
199
+
200
+        return false;
201
+    }
202
+
203
+    /**
204
+     * Set password
205
+     * @param string $uid The username
206
+     * @param string $password The new password
207
+     * @return bool
208
+     */
209
+    public function setPassword($uid, $password) {
210
+        $user = $this->access->userManager->get($uid);
211
+
212
+        if(!$user instanceof User) {
213
+            throw new \Exception('LDAP setPassword: Could not get user object for uid ' . $uid .
214
+                '. Maybe the LDAP entry has no set display name attribute?');
215
+        }
216
+        if($user->getUsername() !== false && $this->access->setPassword($user->getDN(), $password)) {
217
+            $ldapDefaultPPolicyDN = $this->access->connection->ldapDefaultPPolicyDN;
218
+            $turnOnPasswordChange = $this->access->connection->turnOnPasswordChange;
219
+            if (!empty($ldapDefaultPPolicyDN) && (intval($turnOnPasswordChange) === 1)) {
220
+                //remove last password expiry warning if any
221
+                $notification = $this->notificationManager->createNotification();
222
+                $notification->setApp('user_ldap')
223
+                    ->setUser($uid)
224
+                    ->setObject('pwd_exp_warn', $uid)
225
+                ;
226
+                $this->notificationManager->markProcessed($notification);
227
+            }
228
+            return true;
229
+        }
230
+
231
+        return false;
232
+    }
233
+
234
+    /**
235
+     * Get a list of all users
236
+     *
237
+     * @param string $search
238
+     * @param integer $limit
239
+     * @param integer $offset
240
+     * @return string[] an array of all uids
241
+     */
242
+    public function getUsers($search = '', $limit = 10, $offset = 0) {
243
+        $search = $this->access->escapeFilterPart($search, true);
244
+        $cachekey = 'getUsers-'.$search.'-'.$limit.'-'.$offset;
245
+
246
+        //check if users are cached, if so return
247
+        $ldap_users = $this->access->connection->getFromCache($cachekey);
248
+        if(!is_null($ldap_users)) {
249
+            return $ldap_users;
250
+        }
251
+
252
+        // if we'd pass -1 to LDAP search, we'd end up in a Protocol
253
+        // error. With a limit of 0, we get 0 results. So we pass null.
254
+        if($limit <= 0) {
255
+            $limit = null;
256
+        }
257
+        $filter = $this->access->combineFilterWithAnd(array(
258
+            $this->access->connection->ldapUserFilter,
259
+            $this->access->connection->ldapUserDisplayName . '=*',
260
+            $this->access->getFilterPartForUserSearch($search)
261
+        ));
262
+
263
+        Util::writeLog('user_ldap',
264
+            'getUsers: Options: search '.$search.' limit '.$limit.' offset '.$offset.' Filter: '.$filter,
265
+            Util::DEBUG);
266
+        //do the search and translate results to Nextcloud names
267
+        $ldap_users = $this->access->fetchListOfUsers(
268
+            $filter,
269
+            $this->access->userManager->getAttributes(true),
270
+            $limit, $offset);
271
+        $ldap_users = $this->access->nextcloudUserNames($ldap_users);
272
+        Util::writeLog('user_ldap', 'getUsers: '.count($ldap_users). ' Users found', Util::DEBUG);
273
+
274
+        $this->access->connection->writeToCache($cachekey, $ldap_users);
275
+        return $ldap_users;
276
+    }
277
+
278
+    /**
279
+     * checks whether a user is still available on LDAP
280
+     *
281
+     * @param string|\OCA\User_LDAP\User\User $user either the Nextcloud user
282
+     * name or an instance of that user
283
+     * @return bool
284
+     * @throws \Exception
285
+     * @throws \OC\ServerNotAvailableException
286
+     */
287
+    public function userExistsOnLDAP($user) {
288
+        if(is_string($user)) {
289
+            $user = $this->access->userManager->get($user);
290
+        }
291
+        if(is_null($user)) {
292
+            return false;
293
+        }
294
+
295
+        $dn = $user->getDN();
296
+        //check if user really still exists by reading its entry
297
+        if(!is_array($this->access->readAttribute($dn, '', $this->access->connection->ldapUserFilter))) {
298
+            $lcr = $this->access->connection->getConnectionResource();
299
+            if(is_null($lcr)) {
300
+                throw new \Exception('No LDAP Connection to server ' . $this->access->connection->ldapHost);
301
+            }
302
+
303
+            try {
304
+                $uuid = $this->access->getUserMapper()->getUUIDByDN($dn);
305
+                if(!$uuid) {
306
+                    return false;
307
+                }
308
+                $newDn = $this->access->getUserDnByUuid($uuid);
309
+                //check if renamed user is still valid by reapplying the ldap filter
310
+                if(!is_array($this->access->readAttribute($newDn, '', $this->access->connection->ldapUserFilter))) {
311
+                    return false;
312
+                }
313
+                $this->access->getUserMapper()->setDNbyUUID($newDn, $uuid);
314
+                return true;
315
+            } catch (\Exception $e) {
316
+                return false;
317
+            }
318
+        }
319
+
320
+        if($user instanceof OfflineUser) {
321
+            $user->unmark();
322
+        }
323
+
324
+        return true;
325
+    }
326
+
327
+    /**
328
+     * check if a user exists
329
+     * @param string $uid the username
330
+     * @return boolean
331
+     * @throws \Exception when connection could not be established
332
+     */
333
+    public function userExists($uid) {
334
+        $userExists = $this->access->connection->getFromCache('userExists'.$uid);
335
+        if(!is_null($userExists)) {
336
+            return (bool)$userExists;
337
+        }
338
+        //getting dn, if false the user does not exist. If dn, he may be mapped only, requires more checking.
339
+        $user = $this->access->userManager->get($uid);
340
+
341
+        if(is_null($user)) {
342
+            Util::writeLog('user_ldap', 'No DN found for '.$uid.' on '.
343
+                $this->access->connection->ldapHost, Util::DEBUG);
344
+            $this->access->connection->writeToCache('userExists'.$uid, false);
345
+            return false;
346
+        } else if($user instanceof OfflineUser) {
347
+            //express check for users marked as deleted. Returning true is
348
+            //necessary for cleanup
349
+            return true;
350
+        }
351
+
352
+        $result = $this->userExistsOnLDAP($user);
353
+        $this->access->connection->writeToCache('userExists'.$uid, $result);
354
+        if($result === true) {
355
+            $user->update();
356
+        }
357
+        return $result;
358
+    }
359
+
360
+    /**
361
+     * returns whether a user was deleted in LDAP
362
+     *
363
+     * @param string $uid The username of the user to delete
364
+     * @return bool
365
+     */
366
+    public function deleteUser($uid) {
367
+        $marked = $this->ocConfig->getUserValue($uid, 'user_ldap', 'isDeleted', 0);
368
+        if(intval($marked) === 0) {
369
+            \OC::$server->getLogger()->notice(
370
+                'User '.$uid . ' is not marked as deleted, not cleaning up.',
371
+                array('app' => 'user_ldap'));
372
+            return false;
373
+        }
374
+        \OC::$server->getLogger()->info('Cleaning up after user ' . $uid,
375
+            array('app' => 'user_ldap'));
376
+
377
+        $this->access->getUserMapper()->unmap($uid);
378
+        $this->access->userManager->invalidate($uid);
379
+        return true;
380
+    }
381
+
382
+    /**
383
+     * get the user's home directory
384
+     *
385
+     * @param string $uid the username
386
+     * @return bool|string
387
+     * @throws NoUserException
388
+     * @throws \Exception
389
+     */
390
+    public function getHome($uid) {
391
+        // user Exists check required as it is not done in user proxy!
392
+        if(!$this->userExists($uid)) {
393
+            return false;
394
+        }
395
+
396
+        $cacheKey = 'getHome'.$uid;
397
+        $path = $this->access->connection->getFromCache($cacheKey);
398
+        if(!is_null($path)) {
399
+            return $path;
400
+        }
401
+
402
+        // early return path if it is a deleted user
403
+        $user = $this->access->userManager->get($uid);
404
+        if($user instanceof OfflineUser) {
405
+            if($this->currentUserInDeletionProcess !== null
406
+                && $this->currentUserInDeletionProcess === $user->getOCName()
407
+            ) {
408
+                return $user->getHomePath();
409
+            } else {
410
+                throw new NoUserException($uid . ' is not a valid user anymore');
411
+            }
412
+        } else if ($user === null) {
413
+            throw new NoUserException($uid . ' is not a valid user anymore');
414
+        }
415
+
416
+        $path = $user->getHomePath();
417
+        $this->access->cacheUserHome($uid, $path);
418
+
419
+        return $path;
420
+    }
421
+
422
+    /**
423
+     * get display name of the user
424
+     * @param string $uid user ID of the user
425
+     * @return string|false display name
426
+     */
427
+    public function getDisplayName($uid) {
428
+        if(!$this->userExists($uid)) {
429
+            return false;
430
+        }
431
+
432
+        $cacheKey = 'getDisplayName'.$uid;
433
+        if(!is_null($displayName = $this->access->connection->getFromCache($cacheKey))) {
434
+            return $displayName;
435
+        }
436
+
437
+        //Check whether the display name is configured to have a 2nd feature
438
+        $additionalAttribute = $this->access->connection->ldapUserDisplayName2;
439
+        $displayName2 = '';
440
+        if ($additionalAttribute !== '') {
441
+            $displayName2 = $this->access->readAttribute(
442
+                $this->access->username2dn($uid),
443
+                $additionalAttribute);
444
+        }
445
+
446
+        $displayName = $this->access->readAttribute(
447
+            $this->access->username2dn($uid),
448
+            $this->access->connection->ldapUserDisplayName);
449
+
450
+        if($displayName && (count($displayName) > 0)) {
451
+            $displayName = $displayName[0];
452
+
453
+            if (is_array($displayName2)){
454
+                $displayName2 = count($displayName2) > 0 ? $displayName2[0] : '';
455
+            }
456
+
457
+            $user = $this->access->userManager->get($uid);
458
+            if ($user instanceof User) {
459
+                $displayName = $user->composeAndStoreDisplayName($displayName, $displayName2);
460
+                $this->access->connection->writeToCache($cacheKey, $displayName);
461
+            }
462
+            if ($user instanceof OfflineUser) {
463
+                /** @var OfflineUser $user*/
464
+                $displayName = $user->getDisplayName();
465
+            }
466
+            return $displayName;
467
+        }
468
+
469
+        return null;
470
+    }
471
+
472
+    /**
473
+     * Get a list of all display names
474
+     *
475
+     * @param string $search
476
+     * @param string|null $limit
477
+     * @param string|null $offset
478
+     * @return array an array of all displayNames (value) and the corresponding uids (key)
479
+     */
480
+    public function getDisplayNames($search = '', $limit = null, $offset = null) {
481
+        $cacheKey = 'getDisplayNames-'.$search.'-'.$limit.'-'.$offset;
482
+        if(!is_null($displayNames = $this->access->connection->getFromCache($cacheKey))) {
483
+            return $displayNames;
484
+        }
485
+
486
+        $displayNames = array();
487
+        $users = $this->getUsers($search, $limit, $offset);
488
+        foreach ($users as $user) {
489
+            $displayNames[$user] = $this->getDisplayName($user);
490
+        }
491
+        $this->access->connection->writeToCache($cacheKey, $displayNames);
492
+        return $displayNames;
493
+    }
494
+
495
+    /**
496
+     * Check if backend implements actions
497
+     * @param int $actions bitwise-or'ed actions
498
+     * @return boolean
499
+     *
500
+     * Returns the supported actions as int to be
501
+     * compared with \OC\User\Backend::CREATE_USER etc.
502
+     */
503
+    public function implementsActions($actions) {
504
+        return (bool)((Backend::CHECK_PASSWORD
505
+            | Backend::GET_HOME
506
+            | Backend::GET_DISPLAYNAME
507
+            | Backend::PROVIDE_AVATAR
508
+            | Backend::COUNT_USERS
509
+            | ((intval($this->access->connection->turnOnPasswordChange) === 1)?(Backend::SET_PASSWORD):0))
510
+            & $actions);
511
+    }
512
+
513
+    /**
514
+     * @return bool
515
+     */
516
+    public function hasUserListings() {
517
+        return true;
518
+    }
519
+
520
+    /**
521
+     * counts the users in LDAP
522
+     *
523
+     * @return int|bool
524
+     */
525
+    public function countUsers() {
526
+        $filter = $this->access->getFilterForUserCount();
527
+        $cacheKey = 'countUsers-'.$filter;
528
+        if(!is_null($entries = $this->access->connection->getFromCache($cacheKey))) {
529
+            return $entries;
530
+        }
531
+        $entries = $this->access->countUsers($filter);
532
+        $this->access->connection->writeToCache($cacheKey, $entries);
533
+        return $entries;
534
+    }
535
+
536
+    /**
537
+     * Backend name to be shown in user management
538
+     * @return string the name of the backend to be shown
539
+     */
540
+    public function getBackendName(){
541
+        return 'LDAP';
542
+    }
543 543
 	
544
-	/**
545
-	 * Return access for LDAP interaction.
546
-	 * @param string $uid
547
-	 * @return Access instance of Access for LDAP interaction
548
-	 */
549
-	public function getLDAPAccess($uid) {
550
-		return $this->access;
551
-	}
544
+    /**
545
+     * Return access for LDAP interaction.
546
+     * @param string $uid
547
+     * @return Access instance of Access for LDAP interaction
548
+     */
549
+    public function getLDAPAccess($uid) {
550
+        return $this->access;
551
+    }
552 552
 	
553
-	/**
554
-	 * Return LDAP connection resource from a cloned connection.
555
-	 * The cloned connection needs to be closed manually.
556
-	 * of the current access.
557
-	 * @param string $uid
558
-	 * @return resource of the LDAP connection
559
-	 */
560
-	public function getNewLDAPConnection($uid) {
561
-		$connection = clone $this->access->getConnection();
562
-		return $connection->getConnectionResource();
563
-	}
553
+    /**
554
+     * Return LDAP connection resource from a cloned connection.
555
+     * The cloned connection needs to be closed manually.
556
+     * of the current access.
557
+     * @param string $uid
558
+     * @return resource of the LDAP connection
559
+     */
560
+    public function getNewLDAPConnection($uid) {
561
+        $connection = clone $this->access->getConnection();
562
+        return $connection->getConnectionResource();
563
+    }
564 564
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/User/Manager.php 1 patch
Indentation   +193 added lines, -193 removed lines patch added patch discarded remove patch
@@ -44,223 +44,223 @@
 block discarded – undo
44 44
  * cache
45 45
  */
46 46
 class Manager {
47
-	/** @var IUserTools */
48
-	protected $access;
47
+    /** @var IUserTools */
48
+    protected $access;
49 49
 
50
-	/** @var IConfig */
51
-	protected $ocConfig;
50
+    /** @var IConfig */
51
+    protected $ocConfig;
52 52
 
53
-	/** @var IDBConnection */
54
-	protected $db;
53
+    /** @var IDBConnection */
54
+    protected $db;
55 55
 
56
-	/** @var IUserManager */
57
-	protected $userManager;
56
+    /** @var IUserManager */
57
+    protected $userManager;
58 58
 
59
-	/** @var INotificationManager */
60
-	protected $notificationManager;
59
+    /** @var INotificationManager */
60
+    protected $notificationManager;
61 61
 
62
-	/** @var FilesystemHelper */
63
-	protected $ocFilesystem;
62
+    /** @var FilesystemHelper */
63
+    protected $ocFilesystem;
64 64
 
65
-	/** @var LogWrapper */
66
-	protected $ocLog;
65
+    /** @var LogWrapper */
66
+    protected $ocLog;
67 67
 
68
-	/** @var Image */
69
-	protected $image;
68
+    /** @var Image */
69
+    protected $image;
70 70
 
71
-	/** @param \OCP\IAvatarManager */
72
-	protected $avatarManager;
71
+    /** @param \OCP\IAvatarManager */
72
+    protected $avatarManager;
73 73
 
74
-	/**
75
-	 * @var CappedMemoryCache $usersByDN
76
-	 */
77
-	protected $usersByDN;
78
-	/**
79
-	 * @var CappedMemoryCache $usersByUid
80
-	 */
81
-	protected $usersByUid;
74
+    /**
75
+     * @var CappedMemoryCache $usersByDN
76
+     */
77
+    protected $usersByDN;
78
+    /**
79
+     * @var CappedMemoryCache $usersByUid
80
+     */
81
+    protected $usersByUid;
82 82
 
83
-	/**
84
-	 * @param IConfig $ocConfig
85
-	 * @param \OCA\User_LDAP\FilesystemHelper $ocFilesystem object that
86
-	 * gives access to necessary functions from the OC filesystem
87
-	 * @param  \OCA\User_LDAP\LogWrapper $ocLog
88
-	 * @param IAvatarManager $avatarManager
89
-	 * @param Image $image an empty image instance
90
-	 * @param IDBConnection $db
91
-	 * @throws \Exception when the methods mentioned above do not exist
92
-	 */
93
-	public function __construct(IConfig $ocConfig,
94
-								FilesystemHelper $ocFilesystem, LogWrapper $ocLog,
95
-								IAvatarManager $avatarManager, Image $image,
96
-								IDBConnection $db, IUserManager $userManager,
97
-								INotificationManager $notificationManager) {
83
+    /**
84
+     * @param IConfig $ocConfig
85
+     * @param \OCA\User_LDAP\FilesystemHelper $ocFilesystem object that
86
+     * gives access to necessary functions from the OC filesystem
87
+     * @param  \OCA\User_LDAP\LogWrapper $ocLog
88
+     * @param IAvatarManager $avatarManager
89
+     * @param Image $image an empty image instance
90
+     * @param IDBConnection $db
91
+     * @throws \Exception when the methods mentioned above do not exist
92
+     */
93
+    public function __construct(IConfig $ocConfig,
94
+                                FilesystemHelper $ocFilesystem, LogWrapper $ocLog,
95
+                                IAvatarManager $avatarManager, Image $image,
96
+                                IDBConnection $db, IUserManager $userManager,
97
+                                INotificationManager $notificationManager) {
98 98
 
99
-		$this->ocConfig            = $ocConfig;
100
-		$this->ocFilesystem        = $ocFilesystem;
101
-		$this->ocLog               = $ocLog;
102
-		$this->avatarManager       = $avatarManager;
103
-		$this->image               = $image;
104
-		$this->db                  = $db;
105
-		$this->userManager         = $userManager;
106
-		$this->notificationManager = $notificationManager;
107
-		$this->usersByDN           = new CappedMemoryCache();
108
-		$this->usersByUid          = new CappedMemoryCache();
109
-	}
99
+        $this->ocConfig            = $ocConfig;
100
+        $this->ocFilesystem        = $ocFilesystem;
101
+        $this->ocLog               = $ocLog;
102
+        $this->avatarManager       = $avatarManager;
103
+        $this->image               = $image;
104
+        $this->db                  = $db;
105
+        $this->userManager         = $userManager;
106
+        $this->notificationManager = $notificationManager;
107
+        $this->usersByDN           = new CappedMemoryCache();
108
+        $this->usersByUid          = new CappedMemoryCache();
109
+    }
110 110
 
111
-	/**
112
-	 * @brief binds manager to an instance of IUserTools (implemented by
113
-	 * Access). It needs to be assigned first before the manager can be used.
114
-	 * @param IUserTools
115
-	 */
116
-	public function setLdapAccess(IUserTools $access) {
117
-		$this->access = $access;
118
-	}
111
+    /**
112
+     * @brief binds manager to an instance of IUserTools (implemented by
113
+     * Access). It needs to be assigned first before the manager can be used.
114
+     * @param IUserTools
115
+     */
116
+    public function setLdapAccess(IUserTools $access) {
117
+        $this->access = $access;
118
+    }
119 119
 
120
-	/**
121
-	 * @brief creates an instance of User and caches (just runtime) it in the
122
-	 * property array
123
-	 * @param string $dn the DN of the user
124
-	 * @param string $uid the internal (owncloud) username
125
-	 * @return \OCA\User_LDAP\User\User
126
-	 */
127
-	private function createAndCache($dn, $uid) {
128
-		$this->checkAccess();
129
-		$user = new User($uid, $dn, $this->access, $this->ocConfig,
130
-			$this->ocFilesystem, clone $this->image, $this->ocLog,
131
-			$this->avatarManager, $this->userManager, 
132
-			$this->notificationManager);
133
-		$this->usersByDN[$dn]   = $user;
134
-		$this->usersByUid[$uid] = $user;
135
-		return $user;
136
-	}
120
+    /**
121
+     * @brief creates an instance of User and caches (just runtime) it in the
122
+     * property array
123
+     * @param string $dn the DN of the user
124
+     * @param string $uid the internal (owncloud) username
125
+     * @return \OCA\User_LDAP\User\User
126
+     */
127
+    private function createAndCache($dn, $uid) {
128
+        $this->checkAccess();
129
+        $user = new User($uid, $dn, $this->access, $this->ocConfig,
130
+            $this->ocFilesystem, clone $this->image, $this->ocLog,
131
+            $this->avatarManager, $this->userManager, 
132
+            $this->notificationManager);
133
+        $this->usersByDN[$dn]   = $user;
134
+        $this->usersByUid[$uid] = $user;
135
+        return $user;
136
+    }
137 137
 
138
-	/**
139
-	 * removes a user entry from the cache
140
-	 * @param $uid
141
-	 */
142
-	public function invalidate($uid) {
143
-		if(!isset($this->usersByUid[$uid])) {
144
-			return;
145
-		}
146
-		$dn = $this->usersByUid[$uid]->getDN();
147
-		unset($this->usersByUid[$uid]);
148
-		unset($this->usersByDN[$dn]);
149
-	}
138
+    /**
139
+     * removes a user entry from the cache
140
+     * @param $uid
141
+     */
142
+    public function invalidate($uid) {
143
+        if(!isset($this->usersByUid[$uid])) {
144
+            return;
145
+        }
146
+        $dn = $this->usersByUid[$uid]->getDN();
147
+        unset($this->usersByUid[$uid]);
148
+        unset($this->usersByDN[$dn]);
149
+    }
150 150
 
151
-	/**
152
-	 * @brief checks whether the Access instance has been set
153
-	 * @throws \Exception if Access has not been set
154
-	 * @return null
155
-	 */
156
-	private function checkAccess() {
157
-		if(is_null($this->access)) {
158
-			throw new \Exception('LDAP Access instance must be set first');
159
-		}
160
-	}
151
+    /**
152
+     * @brief checks whether the Access instance has been set
153
+     * @throws \Exception if Access has not been set
154
+     * @return null
155
+     */
156
+    private function checkAccess() {
157
+        if(is_null($this->access)) {
158
+            throw new \Exception('LDAP Access instance must be set first');
159
+        }
160
+    }
161 161
 
162
-	/**
163
-	 * returns a list of attributes that will be processed further, e.g. quota,
164
-	 * email, displayname, or others.
165
-	 * @param bool $minimal - optional, set to true to skip attributes with big
166
-	 * payload
167
-	 * @return string[]
168
-	 */
169
-	public function getAttributes($minimal = false) {
170
-		$attributes = array_merge(Access::UUID_ATTRIBUTES, ['dn', 'uid', 'samaccountname', 'memberof']);
171
-		$possible = array(
172
-			$this->access->getConnection()->ldapExpertUUIDUserAttr,
173
-			$this->access->getConnection()->ldapQuotaAttribute,
174
-			$this->access->getConnection()->ldapEmailAttribute,
175
-			$this->access->getConnection()->ldapUserDisplayName,
176
-			$this->access->getConnection()->ldapUserDisplayName2,
177
-		);
178
-		foreach($possible as $attr) {
179
-			if(!is_null($attr)) {
180
-				$attributes[] = $attr;
181
-			}
182
-		}
162
+    /**
163
+     * returns a list of attributes that will be processed further, e.g. quota,
164
+     * email, displayname, or others.
165
+     * @param bool $minimal - optional, set to true to skip attributes with big
166
+     * payload
167
+     * @return string[]
168
+     */
169
+    public function getAttributes($minimal = false) {
170
+        $attributes = array_merge(Access::UUID_ATTRIBUTES, ['dn', 'uid', 'samaccountname', 'memberof']);
171
+        $possible = array(
172
+            $this->access->getConnection()->ldapExpertUUIDUserAttr,
173
+            $this->access->getConnection()->ldapQuotaAttribute,
174
+            $this->access->getConnection()->ldapEmailAttribute,
175
+            $this->access->getConnection()->ldapUserDisplayName,
176
+            $this->access->getConnection()->ldapUserDisplayName2,
177
+        );
178
+        foreach($possible as $attr) {
179
+            if(!is_null($attr)) {
180
+                $attributes[] = $attr;
181
+            }
182
+        }
183 183
 
184
-		$homeRule = $this->access->getConnection()->homeFolderNamingRule;
185
-		if(strpos($homeRule, 'attr:') === 0) {
186
-			$attributes[] = substr($homeRule, strlen('attr:'));
187
-		}
184
+        $homeRule = $this->access->getConnection()->homeFolderNamingRule;
185
+        if(strpos($homeRule, 'attr:') === 0) {
186
+            $attributes[] = substr($homeRule, strlen('attr:'));
187
+        }
188 188
 
189
-		if(!$minimal) {
190
-			// attributes that are not really important but may come with big
191
-			// payload.
192
-			$attributes = array_merge($attributes, array(
193
-				'jpegphoto',
194
-				'thumbnailphoto'
195
-			));
196
-		}
189
+        if(!$minimal) {
190
+            // attributes that are not really important but may come with big
191
+            // payload.
192
+            $attributes = array_merge($attributes, array(
193
+                'jpegphoto',
194
+                'thumbnailphoto'
195
+            ));
196
+        }
197 197
 
198
-		return $attributes;
199
-	}
198
+        return $attributes;
199
+    }
200 200
 
201
-	/**
202
-	 * Checks whether the specified user is marked as deleted
203
-	 * @param string $id the Nextcloud user name
204
-	 * @return bool
205
-	 */
206
-	public function isDeletedUser($id) {
207
-		$isDeleted = $this->ocConfig->getUserValue(
208
-			$id, 'user_ldap', 'isDeleted', 0);
209
-		return intval($isDeleted) === 1;
210
-	}
201
+    /**
202
+     * Checks whether the specified user is marked as deleted
203
+     * @param string $id the Nextcloud user name
204
+     * @return bool
205
+     */
206
+    public function isDeletedUser($id) {
207
+        $isDeleted = $this->ocConfig->getUserValue(
208
+            $id, 'user_ldap', 'isDeleted', 0);
209
+        return intval($isDeleted) === 1;
210
+    }
211 211
 
212
-	/**
213
-	 * creates and returns an instance of OfflineUser for the specified user
214
-	 * @param string $id
215
-	 * @return \OCA\User_LDAP\User\OfflineUser
216
-	 */
217
-	public function getDeletedUser($id) {
218
-		return new OfflineUser(
219
-			$id,
220
-			$this->ocConfig,
221
-			$this->db,
222
-			$this->access->getUserMapper());
223
-	}
212
+    /**
213
+     * creates and returns an instance of OfflineUser for the specified user
214
+     * @param string $id
215
+     * @return \OCA\User_LDAP\User\OfflineUser
216
+     */
217
+    public function getDeletedUser($id) {
218
+        return new OfflineUser(
219
+            $id,
220
+            $this->ocConfig,
221
+            $this->db,
222
+            $this->access->getUserMapper());
223
+    }
224 224
 
225
-	/**
226
-	 * @brief returns a User object by it's Nextcloud username
227
-	 * @param string $id the DN or username of the user
228
-	 * @return \OCA\User_LDAP\User\User|\OCA\User_LDAP\User\OfflineUser|null
229
-	 */
230
-	protected function createInstancyByUserName($id) {
231
-		//most likely a uid. Check whether it is a deleted user
232
-		if($this->isDeletedUser($id)) {
233
-			return $this->getDeletedUser($id);
234
-		}
235
-		$dn = $this->access->username2dn($id);
236
-		if($dn !== false) {
237
-			return $this->createAndCache($dn, $id);
238
-		}
239
-		return null;
240
-	}
225
+    /**
226
+     * @brief returns a User object by it's Nextcloud username
227
+     * @param string $id the DN or username of the user
228
+     * @return \OCA\User_LDAP\User\User|\OCA\User_LDAP\User\OfflineUser|null
229
+     */
230
+    protected function createInstancyByUserName($id) {
231
+        //most likely a uid. Check whether it is a deleted user
232
+        if($this->isDeletedUser($id)) {
233
+            return $this->getDeletedUser($id);
234
+        }
235
+        $dn = $this->access->username2dn($id);
236
+        if($dn !== false) {
237
+            return $this->createAndCache($dn, $id);
238
+        }
239
+        return null;
240
+    }
241 241
 
242
-	/**
243
-	 * @brief returns a User object by it's DN or Nextcloud username
244
-	 * @param string $id the DN or username of the user
245
-	 * @return \OCA\User_LDAP\User\User|\OCA\User_LDAP\User\OfflineUser|null
246
-	 * @throws \Exception when connection could not be established
247
-	 */
248
-	public function get($id) {
249
-		$this->checkAccess();
250
-		if(isset($this->usersByDN[$id])) {
251
-			return $this->usersByDN[$id];
252
-		} else if(isset($this->usersByUid[$id])) {
253
-			return $this->usersByUid[$id];
254
-		}
242
+    /**
243
+     * @brief returns a User object by it's DN or Nextcloud username
244
+     * @param string $id the DN or username of the user
245
+     * @return \OCA\User_LDAP\User\User|\OCA\User_LDAP\User\OfflineUser|null
246
+     * @throws \Exception when connection could not be established
247
+     */
248
+    public function get($id) {
249
+        $this->checkAccess();
250
+        if(isset($this->usersByDN[$id])) {
251
+            return $this->usersByDN[$id];
252
+        } else if(isset($this->usersByUid[$id])) {
253
+            return $this->usersByUid[$id];
254
+        }
255 255
 
256
-		if($this->access->stringResemblesDN($id) ) {
257
-			$uid = $this->access->dn2username($id);
258
-			if($uid !== false) {
259
-				return $this->createAndCache($id, $uid);
260
-			}
261
-		}
256
+        if($this->access->stringResemblesDN($id) ) {
257
+            $uid = $this->access->dn2username($id);
258
+            if($uid !== false) {
259
+                return $this->createAndCache($id, $uid);
260
+            }
261
+        }
262 262
 
263
-		return $this->createInstancyByUserName($id);
264
-	}
263
+        return $this->createInstancyByUserName($id);
264
+    }
265 265
 
266 266
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/User/User.php 1 patch
Indentation   +644 added lines, -644 removed lines patch added patch discarded remove patch
@@ -43,654 +43,654 @@
 block discarded – undo
43 43
  * represents an LDAP user, gets and holds user-specific information from LDAP
44 44
  */
45 45
 class User {
46
-	/**
47
-	 * @var IUserTools
48
-	 */
49
-	protected $access;
50
-	/**
51
-	 * @var Connection
52
-	 */
53
-	protected $connection;
54
-	/**
55
-	 * @var IConfig
56
-	 */
57
-	protected $config;
58
-	/**
59
-	 * @var FilesystemHelper
60
-	 */
61
-	protected $fs;
62
-	/**
63
-	 * @var Image
64
-	 */
65
-	protected $image;
66
-	/**
67
-	 * @var LogWrapper
68
-	 */
69
-	protected $log;
70
-	/**
71
-	 * @var IAvatarManager
72
-	 */
73
-	protected $avatarManager;
74
-	/**
75
-	 * @var IUserManager
76
-	 */
77
-	protected $userManager;
78
-	/**
79
-	 * @var INotificationManager
80
-	 */
81
-	protected $notificationManager;
82
-	/**
83
-	 * @var string
84
-	 */
85
-	protected $dn;
86
-	/**
87
-	 * @var string
88
-	 */
89
-	protected $uid;
90
-	/**
91
-	 * @var string[]
92
-	 */
93
-	protected $refreshedFeatures = array();
94
-	/**
95
-	 * @var string
96
-	 */
97
-	protected $avatarImage;
98
-
99
-	/**
100
-	 * DB config keys for user preferences
101
-	 */
102
-	const USER_PREFKEY_FIRSTLOGIN  = 'firstLoginAccomplished';
103
-	const USER_PREFKEY_LASTREFRESH = 'lastFeatureRefresh';
104
-
105
-	/**
106
-	 * @brief constructor, make sure the subclasses call this one!
107
-	 * @param string $username the internal username
108
-	 * @param string $dn the LDAP DN
109
-	 * @param IUserTools $access an instance that implements IUserTools for
110
-	 * LDAP interaction
111
-	 * @param IConfig $config
112
-	 * @param FilesystemHelper $fs
113
-	 * @param Image $image any empty instance
114
-	 * @param LogWrapper $log
115
-	 * @param IAvatarManager $avatarManager
116
-	 * @param IUserManager $userManager
117
-	 * @param INotificationManager $notificationManager
118
-	 */
119
-	public function __construct($username, $dn, IUserTools $access,
120
-		IConfig $config, FilesystemHelper $fs, Image $image,
121
-		LogWrapper $log, IAvatarManager $avatarManager, IUserManager $userManager,
122
-		INotificationManager $notificationManager) {
46
+    /**
47
+     * @var IUserTools
48
+     */
49
+    protected $access;
50
+    /**
51
+     * @var Connection
52
+     */
53
+    protected $connection;
54
+    /**
55
+     * @var IConfig
56
+     */
57
+    protected $config;
58
+    /**
59
+     * @var FilesystemHelper
60
+     */
61
+    protected $fs;
62
+    /**
63
+     * @var Image
64
+     */
65
+    protected $image;
66
+    /**
67
+     * @var LogWrapper
68
+     */
69
+    protected $log;
70
+    /**
71
+     * @var IAvatarManager
72
+     */
73
+    protected $avatarManager;
74
+    /**
75
+     * @var IUserManager
76
+     */
77
+    protected $userManager;
78
+    /**
79
+     * @var INotificationManager
80
+     */
81
+    protected $notificationManager;
82
+    /**
83
+     * @var string
84
+     */
85
+    protected $dn;
86
+    /**
87
+     * @var string
88
+     */
89
+    protected $uid;
90
+    /**
91
+     * @var string[]
92
+     */
93
+    protected $refreshedFeatures = array();
94
+    /**
95
+     * @var string
96
+     */
97
+    protected $avatarImage;
98
+
99
+    /**
100
+     * DB config keys for user preferences
101
+     */
102
+    const USER_PREFKEY_FIRSTLOGIN  = 'firstLoginAccomplished';
103
+    const USER_PREFKEY_LASTREFRESH = 'lastFeatureRefresh';
104
+
105
+    /**
106
+     * @brief constructor, make sure the subclasses call this one!
107
+     * @param string $username the internal username
108
+     * @param string $dn the LDAP DN
109
+     * @param IUserTools $access an instance that implements IUserTools for
110
+     * LDAP interaction
111
+     * @param IConfig $config
112
+     * @param FilesystemHelper $fs
113
+     * @param Image $image any empty instance
114
+     * @param LogWrapper $log
115
+     * @param IAvatarManager $avatarManager
116
+     * @param IUserManager $userManager
117
+     * @param INotificationManager $notificationManager
118
+     */
119
+    public function __construct($username, $dn, IUserTools $access,
120
+        IConfig $config, FilesystemHelper $fs, Image $image,
121
+        LogWrapper $log, IAvatarManager $avatarManager, IUserManager $userManager,
122
+        INotificationManager $notificationManager) {
123 123
 	
124
-		if ($username === null) {
125
-			$log->log("uid for '$dn' must not be null!", Util::ERROR);
126
-			throw new \InvalidArgumentException('uid must not be null!');
127
-		} else if ($username === '') {
128
-			$log->log("uid for '$dn' must not be an empty string", Util::ERROR);
129
-			throw new \InvalidArgumentException('uid must not be an empty string!');
130
-		}
131
-
132
-		$this->access              = $access;
133
-		$this->connection          = $access->getConnection();
134
-		$this->config              = $config;
135
-		$this->fs                  = $fs;
136
-		$this->dn                  = $dn;
137
-		$this->uid                 = $username;
138
-		$this->image               = $image;
139
-		$this->log                 = $log;
140
-		$this->avatarManager       = $avatarManager;
141
-		$this->userManager         = $userManager;
142
-		$this->notificationManager = $notificationManager;
143
-
144
-		\OCP\Util::connectHook('OC_User', 'post_login', $this, 'handlePasswordExpiry');
145
-	}
146
-
147
-	/**
148
-	 * @brief updates properties like email, quota or avatar provided by LDAP
149
-	 * @return null
150
-	 */
151
-	public function update() {
152
-		if(is_null($this->dn)) {
153
-			return null;
154
-		}
155
-
156
-		$hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap',
157
-				self::USER_PREFKEY_FIRSTLOGIN, 0);
158
-
159
-		if($this->needsRefresh()) {
160
-			$this->updateEmail();
161
-			$this->updateQuota();
162
-			if($hasLoggedIn !== 0) {
163
-				//we do not need to try it, when the user has not been logged in
164
-				//before, because the file system will not be ready.
165
-				$this->updateAvatar();
166
-				//in order to get an avatar as soon as possible, mark the user
167
-				//as refreshed only when updating the avatar did happen
168
-				$this->markRefreshTime();
169
-			}
170
-		}
171
-	}
172
-
173
-	/**
174
-	 * processes results from LDAP for attributes as returned by getAttributesToRead()
175
-	 * @param array $ldapEntry the user entry as retrieved from LDAP
176
-	 */
177
-	public function processAttributes($ldapEntry) {
178
-		$this->markRefreshTime();
179
-		//Quota
180
-		$attr = strtolower($this->connection->ldapQuotaAttribute);
181
-		if(isset($ldapEntry[$attr])) {
182
-			$this->updateQuota($ldapEntry[$attr][0]);
183
-		} else {
184
-			if ($this->connection->ldapQuotaDefault !== '') {
185
-				$this->updateQuota();
186
-			}
187
-		}
188
-		unset($attr);
189
-
190
-		//displayName
191
-		$displayName = $displayName2 = '';
192
-		$attr = strtolower($this->connection->ldapUserDisplayName);
193
-		if(isset($ldapEntry[$attr])) {
194
-			$displayName = strval($ldapEntry[$attr][0]);
195
-		}
196
-		$attr = strtolower($this->connection->ldapUserDisplayName2);
197
-		if(isset($ldapEntry[$attr])) {
198
-			$displayName2 = strval($ldapEntry[$attr][0]);
199
-		}
200
-		if ($displayName !== '') {
201
-			$this->composeAndStoreDisplayName($displayName);
202
-			$this->access->cacheUserDisplayName(
203
-				$this->getUsername(),
204
-				$displayName,
205
-				$displayName2
206
-			);
207
-		}
208
-		unset($attr);
209
-
210
-		//Email
211
-		//email must be stored after displayname, because it would cause a user
212
-		//change event that will trigger fetching the display name again
213
-		$attr = strtolower($this->connection->ldapEmailAttribute);
214
-		if(isset($ldapEntry[$attr])) {
215
-			$this->updateEmail($ldapEntry[$attr][0]);
216
-		}
217
-		unset($attr);
218
-
219
-		// LDAP Username, needed for s2s sharing
220
-		if(isset($ldapEntry['uid'])) {
221
-			$this->storeLDAPUserName($ldapEntry['uid'][0]);
222
-		} else if(isset($ldapEntry['samaccountname'])) {
223
-			$this->storeLDAPUserName($ldapEntry['samaccountname'][0]);
224
-		}
225
-
226
-		//homePath
227
-		if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
228
-			$attr = strtolower(substr($this->connection->homeFolderNamingRule, strlen('attr:')));
229
-			if(isset($ldapEntry[$attr])) {
230
-				$this->access->cacheUserHome(
231
-					$this->getUsername(), $this->getHomePath($ldapEntry[$attr][0]));
232
-			}
233
-		}
234
-
235
-		//memberOf groups
236
-		$cacheKey = 'getMemberOf'.$this->getUsername();
237
-		$groups = false;
238
-		if(isset($ldapEntry['memberof'])) {
239
-			$groups = $ldapEntry['memberof'];
240
-		}
241
-		$this->connection->writeToCache($cacheKey, $groups);
242
-
243
-		//Avatar
244
-		$attrs = array('jpegphoto', 'thumbnailphoto');
245
-		foreach ($attrs as $attr)  {
246
-			if(isset($ldapEntry[$attr])) {
247
-				$this->avatarImage = $ldapEntry[$attr][0];
248
-				// the call to the method that saves the avatar in the file
249
-				// system must be postponed after the login. It is to ensure
250
-				// external mounts are mounted properly (e.g. with login
251
-				// credentials from the session).
252
-				\OCP\Util::connectHook('OC_User', 'post_login', $this, 'updateAvatarPostLogin');
253
-				break;
254
-			}
255
-		}
256
-	}
257
-
258
-	/**
259
-	 * @brief returns the LDAP DN of the user
260
-	 * @return string
261
-	 */
262
-	public function getDN() {
263
-		return $this->dn;
264
-	}
265
-
266
-	/**
267
-	 * @brief returns the Nextcloud internal username of the user
268
-	 * @return string
269
-	 */
270
-	public function getUsername() {
271
-		return $this->uid;
272
-	}
273
-
274
-	/**
275
-	 * returns the home directory of the user if specified by LDAP settings
276
-	 * @param string $valueFromLDAP
277
-	 * @return bool|string
278
-	 * @throws \Exception
279
-	 */
280
-	public function getHomePath($valueFromLDAP = null) {
281
-		$path = strval($valueFromLDAP);
282
-		$attr = null;
283
-
284
-		if (is_null($valueFromLDAP)
285
-		   && strpos($this->access->connection->homeFolderNamingRule, 'attr:') === 0
286
-		   && $this->access->connection->homeFolderNamingRule !== 'attr:')
287
-		{
288
-			$attr = substr($this->access->connection->homeFolderNamingRule, strlen('attr:'));
289
-			$homedir = $this->access->readAttribute(
290
-				$this->access->username2dn($this->getUsername()), $attr);
291
-			if ($homedir && isset($homedir[0])) {
292
-				$path = $homedir[0];
293
-			}
294
-		}
295
-
296
-		if ($path !== '') {
297
-			//if attribute's value is an absolute path take this, otherwise append it to data dir
298
-			//check for / at the beginning or pattern c:\ resp. c:/
299
-			if(   '/' !== $path[0]
300
-			   && !(3 < strlen($path) && ctype_alpha($path[0])
301
-			       && $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))
302
-			) {
303
-				$path = $this->config->getSystemValue('datadirectory',
304
-						\OC::$SERVERROOT.'/data' ) . '/' . $path;
305
-			}
306
-			//we need it to store it in the DB as well in case a user gets
307
-			//deleted so we can clean up afterwards
308
-			$this->config->setUserValue(
309
-				$this->getUsername(), 'user_ldap', 'homePath', $path
310
-			);
311
-			return $path;
312
-		}
313
-
314
-		if(    !is_null($attr)
315
-			&& $this->config->getAppValue('user_ldap', 'enforce_home_folder_naming_rule', true)
316
-		) {
317
-			// a naming rule attribute is defined, but it doesn't exist for that LDAP user
318
-			throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: ' . $this->getUsername());
319
-		}
320
-
321
-		//false will apply default behaviour as defined and done by OC_User
322
-		$this->config->setUserValue($this->getUsername(), 'user_ldap', 'homePath', '');
323
-		return false;
324
-	}
325
-
326
-	public function getMemberOfGroups() {
327
-		$cacheKey = 'getMemberOf'.$this->getUsername();
328
-		$memberOfGroups = $this->connection->getFromCache($cacheKey);
329
-		if(!is_null($memberOfGroups)) {
330
-			return $memberOfGroups;
331
-		}
332
-		$groupDNs = $this->access->readAttribute($this->getDN(), 'memberOf');
333
-		$this->connection->writeToCache($cacheKey, $groupDNs);
334
-		return $groupDNs;
335
-	}
336
-
337
-	/**
338
-	 * @brief reads the image from LDAP that shall be used as Avatar
339
-	 * @return string data (provided by LDAP) | false
340
-	 */
341
-	public function getAvatarImage() {
342
-		if(!is_null($this->avatarImage)) {
343
-			return $this->avatarImage;
344
-		}
345
-
346
-		$this->avatarImage = false;
347
-		$attributes = array('jpegPhoto', 'thumbnailPhoto');
348
-		foreach($attributes as $attribute) {
349
-			$result = $this->access->readAttribute($this->dn, $attribute);
350
-			if($result !== false && is_array($result) && isset($result[0])) {
351
-				$this->avatarImage = $result[0];
352
-				break;
353
-			}
354
-		}
355
-
356
-		return $this->avatarImage;
357
-	}
358
-
359
-	/**
360
-	 * @brief marks the user as having logged in at least once
361
-	 * @return null
362
-	 */
363
-	public function markLogin() {
364
-		$this->config->setUserValue(
365
-			$this->uid, 'user_ldap', self::USER_PREFKEY_FIRSTLOGIN, 1);
366
-	}
367
-
368
-	/**
369
-	 * @brief marks the time when user features like email have been updated
370
-	 * @return null
371
-	 */
372
-	public function markRefreshTime() {
373
-		$this->config->setUserValue(
374
-			$this->uid, 'user_ldap', self::USER_PREFKEY_LASTREFRESH, time());
375
-	}
376
-
377
-	/**
378
-	 * @brief checks whether user features needs to be updated again by
379
-	 * comparing the difference of time of the last refresh to now with the
380
-	 * desired interval
381
-	 * @return bool
382
-	 */
383
-	private function needsRefresh() {
384
-		$lastChecked = $this->config->getUserValue($this->uid, 'user_ldap',
385
-			self::USER_PREFKEY_LASTREFRESH, 0);
386
-
387
-		//TODO make interval configurable
388
-		if((time() - intval($lastChecked)) < 86400 ) {
389
-			return false;
390
-		}
391
-		return  true;
392
-	}
393
-
394
-	/**
395
-	 * Stores a key-value pair in relation to this user
396
-	 *
397
-	 * @param string $key
398
-	 * @param string $value
399
-	 */
400
-	private function store($key, $value) {
401
-		$this->config->setUserValue($this->uid, 'user_ldap', $key, $value);
402
-	}
403
-
404
-	/**
405
-	 * Composes the display name and stores it in the database. The final
406
-	 * display name is returned.
407
-	 *
408
-	 * @param string $displayName
409
-	 * @param string $displayName2
410
-	 * @returns string the effective display name
411
-	 */
412
-	public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
413
-		$displayName2 = strval($displayName2);
414
-		if($displayName2 !== '') {
415
-			$displayName .= ' (' . $displayName2 . ')';
416
-		}
417
-		$this->store('displayName', $displayName);
418
-		return $displayName;
419
-	}
420
-
421
-	/**
422
-	 * Stores the LDAP Username in the Database
423
-	 * @param string $userName
424
-	 */
425
-	public function storeLDAPUserName($userName) {
426
-		$this->store('uid', $userName);
427
-	}
428
-
429
-	/**
430
-	 * @brief checks whether an update method specified by feature was run
431
-	 * already. If not, it will marked like this, because it is expected that
432
-	 * the method will be run, when false is returned.
433
-	 * @param string $feature email | quota | avatar (can be extended)
434
-	 * @return bool
435
-	 */
436
-	private function wasRefreshed($feature) {
437
-		if(isset($this->refreshedFeatures[$feature])) {
438
-			return true;
439
-		}
440
-		$this->refreshedFeatures[$feature] = 1;
441
-		return false;
442
-	}
443
-
444
-	/**
445
-	 * fetches the email from LDAP and stores it as Nextcloud user value
446
-	 * @param string $valueFromLDAP if known, to save an LDAP read request
447
-	 * @return null
448
-	 */
449
-	public function updateEmail($valueFromLDAP = null) {
450
-		if($this->wasRefreshed('email')) {
451
-			return;
452
-		}
453
-		$email = strval($valueFromLDAP);
454
-		if(is_null($valueFromLDAP)) {
455
-			$emailAttribute = $this->connection->ldapEmailAttribute;
456
-			if ($emailAttribute !== '') {
457
-				$aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
458
-				if(is_array($aEmail) && (count($aEmail) > 0)) {
459
-					$email = strval($aEmail[0]);
460
-				}
461
-			}
462
-		}
463
-		if ($email !== '') {
464
-			$user = $this->userManager->get($this->uid);
465
-			if (!is_null($user)) {
466
-				$currentEmail = strval($user->getEMailAddress());
467
-				if ($currentEmail !== $email) {
468
-					$user->setEMailAddress($email);
469
-				}
470
-			}
471
-		}
472
-	}
473
-
474
-	/**
475
-	 * Overall process goes as follow:
476
-	 * 1. fetch the quota from LDAP and check if it's parseable with the "verifyQuotaValue" function
477
-	 * 2. if the value can't be fetched, is empty or not parseable, use the default LDAP quota
478
-	 * 3. if the default LDAP quota can't be parsed, use the Nextcloud's default quota (use 'default')
479
-	 * 4. check if the target user exists and set the quota for the user.
480
-	 *
481
-	 * In order to improve performance and prevent an unwanted extra LDAP call, the $valueFromLDAP
482
-	 * parameter can be passed with the value of the attribute. This value will be considered as the
483
-	 * quota for the user coming from the LDAP server (step 1 of the process) It can be useful to
484
-	 * fetch all the user's attributes in one call and use the fetched values in this function.
485
-	 * The expected value for that parameter is a string describing the quota for the user. Valid
486
-	 * values are 'none' (unlimited), 'default' (the Nextcloud's default quota), '1234' (quota in
487
-	 * bytes), '1234 MB' (quota in MB - check the \OC_Helper::computerFileSize method for more info)
488
-	 *
489
-	 * fetches the quota from LDAP and stores it as Nextcloud user value
490
-	 * @param string $valueFromLDAP the quota attribute's value can be passed,
491
-	 * to save the readAttribute request
492
-	 * @return null
493
-	 */
494
-	public function updateQuota($valueFromLDAP = null) {
495
-		if($this->wasRefreshed('quota')) {
496
-			return;
497
-		}
498
-
499
-		$quota = false;
500
-		if(is_null($valueFromLDAP)) {
501
-			$quotaAttribute = $this->connection->ldapQuotaAttribute;
502
-			if ($quotaAttribute !== '') {
503
-				$aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);
504
-				if($aQuota && (count($aQuota) > 0)) {
505
-					if ($this->verifyQuotaValue($aQuota[0])) {
506
-						$quota = $aQuota[0];
507
-					} else {
508
-						$this->log->log('not suitable LDAP quota found for user ' . $this->uid . ': [' . $aQuota[0] . ']', \OCP\Util::WARN);
509
-					}
510
-				}
511
-			}
512
-		} else {
513
-			if ($this->verifyQuotaValue($valueFromLDAP)) {
514
-				$quota = $valueFromLDAP;
515
-			} else {
516
-				$this->log->log('not suitable LDAP quota found for user ' . $this->uid . ': [' . $valueFromLDAP . ']', \OCP\Util::WARN);
517
-			}
518
-		}
519
-
520
-		if ($quota === false) {
521
-			// quota not found using the LDAP attribute (or not parseable). Try the default quota
522
-			$defaultQuota = $this->connection->ldapQuotaDefault;
523
-			if ($this->verifyQuotaValue($defaultQuota)) {
524
-				$quota = $defaultQuota;
525
-			}
526
-		}
527
-
528
-		$targetUser = $this->userManager->get($this->uid);
529
-		if ($targetUser) {
530
-			if($quota !== false) {
531
-				$targetUser->setQuota($quota);
532
-			} else {
533
-				$this->log->log('not suitable default quota found for user ' . $this->uid . ': [' . $defaultQuota . ']', \OCP\Util::WARN);
534
-			}
535
-		} else {
536
-			$this->log->log('trying to set a quota for user ' . $this->uid . ' but the user is missing', \OCP\Util::ERROR);
537
-		}
538
-	}
539
-
540
-	private function verifyQuotaValue($quotaValue) {
541
-		return $quotaValue === 'none' || $quotaValue === 'default' || \OC_Helper::computerFileSize($quotaValue) !== false;
542
-	}
543
-
544
-	/**
545
-	 * called by a post_login hook to save the avatar picture
546
-	 *
547
-	 * @param array $params
548
-	 */
549
-	public function updateAvatarPostLogin($params) {
550
-		if(isset($params['uid']) && $params['uid'] === $this->getUsername()) {
551
-			$this->updateAvatar();
552
-		}
553
-	}
554
-
555
-	/**
556
-	 * @brief attempts to get an image from LDAP and sets it as Nextcloud avatar
557
-	 * @return null
558
-	 */
559
-	public function updateAvatar() {
560
-		if($this->wasRefreshed('avatar')) {
561
-			return;
562
-		}
563
-		$avatarImage = $this->getAvatarImage();
564
-		if($avatarImage === false) {
565
-			//not set, nothing left to do;
566
-			return;
567
-		}
568
-		$this->image->loadFromBase64(base64_encode($avatarImage));
569
-		$this->setOwnCloudAvatar();
570
-	}
571
-
572
-	/**
573
-	 * @brief sets an image as Nextcloud avatar
574
-	 * @return null
575
-	 */
576
-	private function setOwnCloudAvatar() {
577
-		if(!$this->image->valid()) {
578
-			$this->log->log('jpegPhoto data invalid for '.$this->dn, \OCP\Util::ERROR);
579
-			return;
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, \OCP\Util::ERROR);
585
-			return;
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
-		} catch (\Exception $e) {
596
-			\OC::$server->getLogger()->notice(
597
-				'Could not set avatar for ' . $this->dn	. ', because: ' . $e->getMessage(),
598
-				['app' => 'user_ldap']);
599
-		}
600
-	}
601
-
602
-	/**
603
-	 * called by a post_login hook to handle password expiry
604
-	 *
605
-	 * @param array $params
606
-	 */
607
-	public function handlePasswordExpiry($params) {
608
-		$ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
609
-		if (empty($ppolicyDN) || (intval($this->connection->turnOnPasswordChange) !== 1)) {
610
-			return;//password expiry handling disabled
611
-		}
612
-		$uid = $params['uid'];
613
-		if(isset($uid) && $uid === $this->getUsername()) {
614
-			//retrieve relevant user attributes
615
-			$result = $this->access->search('objectclass=*', $this->dn, ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
124
+        if ($username === null) {
125
+            $log->log("uid for '$dn' must not be null!", Util::ERROR);
126
+            throw new \InvalidArgumentException('uid must not be null!');
127
+        } else if ($username === '') {
128
+            $log->log("uid for '$dn' must not be an empty string", Util::ERROR);
129
+            throw new \InvalidArgumentException('uid must not be an empty string!');
130
+        }
131
+
132
+        $this->access              = $access;
133
+        $this->connection          = $access->getConnection();
134
+        $this->config              = $config;
135
+        $this->fs                  = $fs;
136
+        $this->dn                  = $dn;
137
+        $this->uid                 = $username;
138
+        $this->image               = $image;
139
+        $this->log                 = $log;
140
+        $this->avatarManager       = $avatarManager;
141
+        $this->userManager         = $userManager;
142
+        $this->notificationManager = $notificationManager;
143
+
144
+        \OCP\Util::connectHook('OC_User', 'post_login', $this, 'handlePasswordExpiry');
145
+    }
146
+
147
+    /**
148
+     * @brief updates properties like email, quota or avatar provided by LDAP
149
+     * @return null
150
+     */
151
+    public function update() {
152
+        if(is_null($this->dn)) {
153
+            return null;
154
+        }
155
+
156
+        $hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap',
157
+                self::USER_PREFKEY_FIRSTLOGIN, 0);
158
+
159
+        if($this->needsRefresh()) {
160
+            $this->updateEmail();
161
+            $this->updateQuota();
162
+            if($hasLoggedIn !== 0) {
163
+                //we do not need to try it, when the user has not been logged in
164
+                //before, because the file system will not be ready.
165
+                $this->updateAvatar();
166
+                //in order to get an avatar as soon as possible, mark the user
167
+                //as refreshed only when updating the avatar did happen
168
+                $this->markRefreshTime();
169
+            }
170
+        }
171
+    }
172
+
173
+    /**
174
+     * processes results from LDAP for attributes as returned by getAttributesToRead()
175
+     * @param array $ldapEntry the user entry as retrieved from LDAP
176
+     */
177
+    public function processAttributes($ldapEntry) {
178
+        $this->markRefreshTime();
179
+        //Quota
180
+        $attr = strtolower($this->connection->ldapQuotaAttribute);
181
+        if(isset($ldapEntry[$attr])) {
182
+            $this->updateQuota($ldapEntry[$attr][0]);
183
+        } else {
184
+            if ($this->connection->ldapQuotaDefault !== '') {
185
+                $this->updateQuota();
186
+            }
187
+        }
188
+        unset($attr);
189
+
190
+        //displayName
191
+        $displayName = $displayName2 = '';
192
+        $attr = strtolower($this->connection->ldapUserDisplayName);
193
+        if(isset($ldapEntry[$attr])) {
194
+            $displayName = strval($ldapEntry[$attr][0]);
195
+        }
196
+        $attr = strtolower($this->connection->ldapUserDisplayName2);
197
+        if(isset($ldapEntry[$attr])) {
198
+            $displayName2 = strval($ldapEntry[$attr][0]);
199
+        }
200
+        if ($displayName !== '') {
201
+            $this->composeAndStoreDisplayName($displayName);
202
+            $this->access->cacheUserDisplayName(
203
+                $this->getUsername(),
204
+                $displayName,
205
+                $displayName2
206
+            );
207
+        }
208
+        unset($attr);
209
+
210
+        //Email
211
+        //email must be stored after displayname, because it would cause a user
212
+        //change event that will trigger fetching the display name again
213
+        $attr = strtolower($this->connection->ldapEmailAttribute);
214
+        if(isset($ldapEntry[$attr])) {
215
+            $this->updateEmail($ldapEntry[$attr][0]);
216
+        }
217
+        unset($attr);
218
+
219
+        // LDAP Username, needed for s2s sharing
220
+        if(isset($ldapEntry['uid'])) {
221
+            $this->storeLDAPUserName($ldapEntry['uid'][0]);
222
+        } else if(isset($ldapEntry['samaccountname'])) {
223
+            $this->storeLDAPUserName($ldapEntry['samaccountname'][0]);
224
+        }
225
+
226
+        //homePath
227
+        if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
228
+            $attr = strtolower(substr($this->connection->homeFolderNamingRule, strlen('attr:')));
229
+            if(isset($ldapEntry[$attr])) {
230
+                $this->access->cacheUserHome(
231
+                    $this->getUsername(), $this->getHomePath($ldapEntry[$attr][0]));
232
+            }
233
+        }
234
+
235
+        //memberOf groups
236
+        $cacheKey = 'getMemberOf'.$this->getUsername();
237
+        $groups = false;
238
+        if(isset($ldapEntry['memberof'])) {
239
+            $groups = $ldapEntry['memberof'];
240
+        }
241
+        $this->connection->writeToCache($cacheKey, $groups);
242
+
243
+        //Avatar
244
+        $attrs = array('jpegphoto', 'thumbnailphoto');
245
+        foreach ($attrs as $attr)  {
246
+            if(isset($ldapEntry[$attr])) {
247
+                $this->avatarImage = $ldapEntry[$attr][0];
248
+                // the call to the method that saves the avatar in the file
249
+                // system must be postponed after the login. It is to ensure
250
+                // external mounts are mounted properly (e.g. with login
251
+                // credentials from the session).
252
+                \OCP\Util::connectHook('OC_User', 'post_login', $this, 'updateAvatarPostLogin');
253
+                break;
254
+            }
255
+        }
256
+    }
257
+
258
+    /**
259
+     * @brief returns the LDAP DN of the user
260
+     * @return string
261
+     */
262
+    public function getDN() {
263
+        return $this->dn;
264
+    }
265
+
266
+    /**
267
+     * @brief returns the Nextcloud internal username of the user
268
+     * @return string
269
+     */
270
+    public function getUsername() {
271
+        return $this->uid;
272
+    }
273
+
274
+    /**
275
+     * returns the home directory of the user if specified by LDAP settings
276
+     * @param string $valueFromLDAP
277
+     * @return bool|string
278
+     * @throws \Exception
279
+     */
280
+    public function getHomePath($valueFromLDAP = null) {
281
+        $path = strval($valueFromLDAP);
282
+        $attr = null;
283
+
284
+        if (is_null($valueFromLDAP)
285
+           && strpos($this->access->connection->homeFolderNamingRule, 'attr:') === 0
286
+           && $this->access->connection->homeFolderNamingRule !== 'attr:')
287
+        {
288
+            $attr = substr($this->access->connection->homeFolderNamingRule, strlen('attr:'));
289
+            $homedir = $this->access->readAttribute(
290
+                $this->access->username2dn($this->getUsername()), $attr);
291
+            if ($homedir && isset($homedir[0])) {
292
+                $path = $homedir[0];
293
+            }
294
+        }
295
+
296
+        if ($path !== '') {
297
+            //if attribute's value is an absolute path take this, otherwise append it to data dir
298
+            //check for / at the beginning or pattern c:\ resp. c:/
299
+            if(   '/' !== $path[0]
300
+               && !(3 < strlen($path) && ctype_alpha($path[0])
301
+                   && $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))
302
+            ) {
303
+                $path = $this->config->getSystemValue('datadirectory',
304
+                        \OC::$SERVERROOT.'/data' ) . '/' . $path;
305
+            }
306
+            //we need it to store it in the DB as well in case a user gets
307
+            //deleted so we can clean up afterwards
308
+            $this->config->setUserValue(
309
+                $this->getUsername(), 'user_ldap', 'homePath', $path
310
+            );
311
+            return $path;
312
+        }
313
+
314
+        if(    !is_null($attr)
315
+            && $this->config->getAppValue('user_ldap', 'enforce_home_folder_naming_rule', true)
316
+        ) {
317
+            // a naming rule attribute is defined, but it doesn't exist for that LDAP user
318
+            throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: ' . $this->getUsername());
319
+        }
320
+
321
+        //false will apply default behaviour as defined and done by OC_User
322
+        $this->config->setUserValue($this->getUsername(), 'user_ldap', 'homePath', '');
323
+        return false;
324
+    }
325
+
326
+    public function getMemberOfGroups() {
327
+        $cacheKey = 'getMemberOf'.$this->getUsername();
328
+        $memberOfGroups = $this->connection->getFromCache($cacheKey);
329
+        if(!is_null($memberOfGroups)) {
330
+            return $memberOfGroups;
331
+        }
332
+        $groupDNs = $this->access->readAttribute($this->getDN(), 'memberOf');
333
+        $this->connection->writeToCache($cacheKey, $groupDNs);
334
+        return $groupDNs;
335
+    }
336
+
337
+    /**
338
+     * @brief reads the image from LDAP that shall be used as Avatar
339
+     * @return string data (provided by LDAP) | false
340
+     */
341
+    public function getAvatarImage() {
342
+        if(!is_null($this->avatarImage)) {
343
+            return $this->avatarImage;
344
+        }
345
+
346
+        $this->avatarImage = false;
347
+        $attributes = array('jpegPhoto', 'thumbnailPhoto');
348
+        foreach($attributes as $attribute) {
349
+            $result = $this->access->readAttribute($this->dn, $attribute);
350
+            if($result !== false && is_array($result) && isset($result[0])) {
351
+                $this->avatarImage = $result[0];
352
+                break;
353
+            }
354
+        }
355
+
356
+        return $this->avatarImage;
357
+    }
358
+
359
+    /**
360
+     * @brief marks the user as having logged in at least once
361
+     * @return null
362
+     */
363
+    public function markLogin() {
364
+        $this->config->setUserValue(
365
+            $this->uid, 'user_ldap', self::USER_PREFKEY_FIRSTLOGIN, 1);
366
+    }
367
+
368
+    /**
369
+     * @brief marks the time when user features like email have been updated
370
+     * @return null
371
+     */
372
+    public function markRefreshTime() {
373
+        $this->config->setUserValue(
374
+            $this->uid, 'user_ldap', self::USER_PREFKEY_LASTREFRESH, time());
375
+    }
376
+
377
+    /**
378
+     * @brief checks whether user features needs to be updated again by
379
+     * comparing the difference of time of the last refresh to now with the
380
+     * desired interval
381
+     * @return bool
382
+     */
383
+    private function needsRefresh() {
384
+        $lastChecked = $this->config->getUserValue($this->uid, 'user_ldap',
385
+            self::USER_PREFKEY_LASTREFRESH, 0);
386
+
387
+        //TODO make interval configurable
388
+        if((time() - intval($lastChecked)) < 86400 ) {
389
+            return false;
390
+        }
391
+        return  true;
392
+    }
393
+
394
+    /**
395
+     * Stores a key-value pair in relation to this user
396
+     *
397
+     * @param string $key
398
+     * @param string $value
399
+     */
400
+    private function store($key, $value) {
401
+        $this->config->setUserValue($this->uid, 'user_ldap', $key, $value);
402
+    }
403
+
404
+    /**
405
+     * Composes the display name and stores it in the database. The final
406
+     * display name is returned.
407
+     *
408
+     * @param string $displayName
409
+     * @param string $displayName2
410
+     * @returns string the effective display name
411
+     */
412
+    public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
413
+        $displayName2 = strval($displayName2);
414
+        if($displayName2 !== '') {
415
+            $displayName .= ' (' . $displayName2 . ')';
416
+        }
417
+        $this->store('displayName', $displayName);
418
+        return $displayName;
419
+    }
420
+
421
+    /**
422
+     * Stores the LDAP Username in the Database
423
+     * @param string $userName
424
+     */
425
+    public function storeLDAPUserName($userName) {
426
+        $this->store('uid', $userName);
427
+    }
428
+
429
+    /**
430
+     * @brief checks whether an update method specified by feature was run
431
+     * already. If not, it will marked like this, because it is expected that
432
+     * the method will be run, when false is returned.
433
+     * @param string $feature email | quota | avatar (can be extended)
434
+     * @return bool
435
+     */
436
+    private function wasRefreshed($feature) {
437
+        if(isset($this->refreshedFeatures[$feature])) {
438
+            return true;
439
+        }
440
+        $this->refreshedFeatures[$feature] = 1;
441
+        return false;
442
+    }
443
+
444
+    /**
445
+     * fetches the email from LDAP and stores it as Nextcloud user value
446
+     * @param string $valueFromLDAP if known, to save an LDAP read request
447
+     * @return null
448
+     */
449
+    public function updateEmail($valueFromLDAP = null) {
450
+        if($this->wasRefreshed('email')) {
451
+            return;
452
+        }
453
+        $email = strval($valueFromLDAP);
454
+        if(is_null($valueFromLDAP)) {
455
+            $emailAttribute = $this->connection->ldapEmailAttribute;
456
+            if ($emailAttribute !== '') {
457
+                $aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
458
+                if(is_array($aEmail) && (count($aEmail) > 0)) {
459
+                    $email = strval($aEmail[0]);
460
+                }
461
+            }
462
+        }
463
+        if ($email !== '') {
464
+            $user = $this->userManager->get($this->uid);
465
+            if (!is_null($user)) {
466
+                $currentEmail = strval($user->getEMailAddress());
467
+                if ($currentEmail !== $email) {
468
+                    $user->setEMailAddress($email);
469
+                }
470
+            }
471
+        }
472
+    }
473
+
474
+    /**
475
+     * Overall process goes as follow:
476
+     * 1. fetch the quota from LDAP and check if it's parseable with the "verifyQuotaValue" function
477
+     * 2. if the value can't be fetched, is empty or not parseable, use the default LDAP quota
478
+     * 3. if the default LDAP quota can't be parsed, use the Nextcloud's default quota (use 'default')
479
+     * 4. check if the target user exists and set the quota for the user.
480
+     *
481
+     * In order to improve performance and prevent an unwanted extra LDAP call, the $valueFromLDAP
482
+     * parameter can be passed with the value of the attribute. This value will be considered as the
483
+     * quota for the user coming from the LDAP server (step 1 of the process) It can be useful to
484
+     * fetch all the user's attributes in one call and use the fetched values in this function.
485
+     * The expected value for that parameter is a string describing the quota for the user. Valid
486
+     * values are 'none' (unlimited), 'default' (the Nextcloud's default quota), '1234' (quota in
487
+     * bytes), '1234 MB' (quota in MB - check the \OC_Helper::computerFileSize method for more info)
488
+     *
489
+     * fetches the quota from LDAP and stores it as Nextcloud user value
490
+     * @param string $valueFromLDAP the quota attribute's value can be passed,
491
+     * to save the readAttribute request
492
+     * @return null
493
+     */
494
+    public function updateQuota($valueFromLDAP = null) {
495
+        if($this->wasRefreshed('quota')) {
496
+            return;
497
+        }
498
+
499
+        $quota = false;
500
+        if(is_null($valueFromLDAP)) {
501
+            $quotaAttribute = $this->connection->ldapQuotaAttribute;
502
+            if ($quotaAttribute !== '') {
503
+                $aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);
504
+                if($aQuota && (count($aQuota) > 0)) {
505
+                    if ($this->verifyQuotaValue($aQuota[0])) {
506
+                        $quota = $aQuota[0];
507
+                    } else {
508
+                        $this->log->log('not suitable LDAP quota found for user ' . $this->uid . ': [' . $aQuota[0] . ']', \OCP\Util::WARN);
509
+                    }
510
+                }
511
+            }
512
+        } else {
513
+            if ($this->verifyQuotaValue($valueFromLDAP)) {
514
+                $quota = $valueFromLDAP;
515
+            } else {
516
+                $this->log->log('not suitable LDAP quota found for user ' . $this->uid . ': [' . $valueFromLDAP . ']', \OCP\Util::WARN);
517
+            }
518
+        }
519
+
520
+        if ($quota === false) {
521
+            // quota not found using the LDAP attribute (or not parseable). Try the default quota
522
+            $defaultQuota = $this->connection->ldapQuotaDefault;
523
+            if ($this->verifyQuotaValue($defaultQuota)) {
524
+                $quota = $defaultQuota;
525
+            }
526
+        }
527
+
528
+        $targetUser = $this->userManager->get($this->uid);
529
+        if ($targetUser) {
530
+            if($quota !== false) {
531
+                $targetUser->setQuota($quota);
532
+            } else {
533
+                $this->log->log('not suitable default quota found for user ' . $this->uid . ': [' . $defaultQuota . ']', \OCP\Util::WARN);
534
+            }
535
+        } else {
536
+            $this->log->log('trying to set a quota for user ' . $this->uid . ' but the user is missing', \OCP\Util::ERROR);
537
+        }
538
+    }
539
+
540
+    private function verifyQuotaValue($quotaValue) {
541
+        return $quotaValue === 'none' || $quotaValue === 'default' || \OC_Helper::computerFileSize($quotaValue) !== false;
542
+    }
543
+
544
+    /**
545
+     * called by a post_login hook to save the avatar picture
546
+     *
547
+     * @param array $params
548
+     */
549
+    public function updateAvatarPostLogin($params) {
550
+        if(isset($params['uid']) && $params['uid'] === $this->getUsername()) {
551
+            $this->updateAvatar();
552
+        }
553
+    }
554
+
555
+    /**
556
+     * @brief attempts to get an image from LDAP and sets it as Nextcloud avatar
557
+     * @return null
558
+     */
559
+    public function updateAvatar() {
560
+        if($this->wasRefreshed('avatar')) {
561
+            return;
562
+        }
563
+        $avatarImage = $this->getAvatarImage();
564
+        if($avatarImage === false) {
565
+            //not set, nothing left to do;
566
+            return;
567
+        }
568
+        $this->image->loadFromBase64(base64_encode($avatarImage));
569
+        $this->setOwnCloudAvatar();
570
+    }
571
+
572
+    /**
573
+     * @brief sets an image as Nextcloud avatar
574
+     * @return null
575
+     */
576
+    private function setOwnCloudAvatar() {
577
+        if(!$this->image->valid()) {
578
+            $this->log->log('jpegPhoto data invalid for '.$this->dn, \OCP\Util::ERROR);
579
+            return;
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, \OCP\Util::ERROR);
585
+            return;
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
+        } catch (\Exception $e) {
596
+            \OC::$server->getLogger()->notice(
597
+                'Could not set avatar for ' . $this->dn	. ', because: ' . $e->getMessage(),
598
+                ['app' => 'user_ldap']);
599
+        }
600
+    }
601
+
602
+    /**
603
+     * called by a post_login hook to handle password expiry
604
+     *
605
+     * @param array $params
606
+     */
607
+    public function handlePasswordExpiry($params) {
608
+        $ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
609
+        if (empty($ppolicyDN) || (intval($this->connection->turnOnPasswordChange) !== 1)) {
610
+            return;//password expiry handling disabled
611
+        }
612
+        $uid = $params['uid'];
613
+        if(isset($uid) && $uid === $this->getUsername()) {
614
+            //retrieve relevant user attributes
615
+            $result = $this->access->search('objectclass=*', $this->dn, ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
616 616
 			
617
-			if(array_key_exists('pwdpolicysubentry', $result[0])) {
618
-				$pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
619
-				if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
620
-					$ppolicyDN = $pwdPolicySubentry[0];//custom ppolicy DN
621
-				}
622
-			}
617
+            if(array_key_exists('pwdpolicysubentry', $result[0])) {
618
+                $pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
619
+                if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
620
+                    $ppolicyDN = $pwdPolicySubentry[0];//custom ppolicy DN
621
+                }
622
+            }
623 623
 			
624
-			$pwdGraceUseTime = array_key_exists('pwdgraceusetime', $result[0]) ? $result[0]['pwdgraceusetime'] : null;
625
-			$pwdReset = array_key_exists('pwdreset', $result[0]) ? $result[0]['pwdreset'] : null;
626
-			$pwdChangedTime = array_key_exists('pwdchangedtime', $result[0]) ? $result[0]['pwdchangedtime'] : null;
624
+            $pwdGraceUseTime = array_key_exists('pwdgraceusetime', $result[0]) ? $result[0]['pwdgraceusetime'] : null;
625
+            $pwdReset = array_key_exists('pwdreset', $result[0]) ? $result[0]['pwdreset'] : null;
626
+            $pwdChangedTime = array_key_exists('pwdchangedtime', $result[0]) ? $result[0]['pwdchangedtime'] : null;
627 627
 			
628
-			//retrieve relevant password policy attributes
629
-			$cacheKey = 'ppolicyAttributes' . $ppolicyDN;
630
-			$result = $this->connection->getFromCache($cacheKey);
631
-			if(is_null($result)) {
632
-				$result = $this->access->search('objectclass=*', $ppolicyDN, ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
633
-				$this->connection->writeToCache($cacheKey, $result);
634
-			}
628
+            //retrieve relevant password policy attributes
629
+            $cacheKey = 'ppolicyAttributes' . $ppolicyDN;
630
+            $result = $this->connection->getFromCache($cacheKey);
631
+            if(is_null($result)) {
632
+                $result = $this->access->search('objectclass=*', $ppolicyDN, ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
633
+                $this->connection->writeToCache($cacheKey, $result);
634
+            }
635 635
 			
636
-			$pwdGraceAuthNLimit = array_key_exists('pwdgraceauthnlimit', $result[0]) ? $result[0]['pwdgraceauthnlimit'] : null;
637
-			$pwdMaxAge = array_key_exists('pwdmaxage', $result[0]) ? $result[0]['pwdmaxage'] : null;
638
-			$pwdExpireWarning = array_key_exists('pwdexpirewarning', $result[0]) ? $result[0]['pwdexpirewarning'] : null;
636
+            $pwdGraceAuthNLimit = array_key_exists('pwdgraceauthnlimit', $result[0]) ? $result[0]['pwdgraceauthnlimit'] : null;
637
+            $pwdMaxAge = array_key_exists('pwdmaxage', $result[0]) ? $result[0]['pwdmaxage'] : null;
638
+            $pwdExpireWarning = array_key_exists('pwdexpirewarning', $result[0]) ? $result[0]['pwdexpirewarning'] : null;
639 639
 			
640
-			//handle grace login
641
-			$pwdGraceUseTimeCount = count($pwdGraceUseTime);
642
-			if($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
643
-				if($pwdGraceAuthNLimit 
644
-					&& (count($pwdGraceAuthNLimit) > 0)
645
-					&&($pwdGraceUseTimeCount < intval($pwdGraceAuthNLimit[0]))) { //at least one more grace login available?
646
-					$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
647
-					header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
648
-					'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
649
-				} else { //no more grace login available
650
-					header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
651
-					'user_ldap.renewPassword.showLoginFormInvalidPassword', array('user' => $uid)));
652
-				}
653
-				exit();
654
-			}
655
-			//handle pwdReset attribute
656
-			if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
657
-				$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
658
-				header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
659
-				'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
660
-				exit();
661
-			}
662
-			//handle password expiry warning
663
-			if($pwdChangedTime && (count($pwdChangedTime) > 0)) {
664
-				if($pwdMaxAge && (count($pwdMaxAge) > 0)
665
-					&& $pwdExpireWarning && (count($pwdExpireWarning) > 0)) {
666
-					$pwdMaxAgeInt = intval($pwdMaxAge[0]);
667
-					$pwdExpireWarningInt = intval($pwdExpireWarning[0]);
668
-					if($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0){
669
-						$pwdChangedTimeDt = \DateTime::createFromFormat('YmdHisZ', $pwdChangedTime[0]);
670
-						$pwdChangedTimeDt->add(new \DateInterval('PT'.$pwdMaxAgeInt.'S'));
671
-						$currentDateTime = new \DateTime();
672
-						$secondsToExpiry = $pwdChangedTimeDt->getTimestamp() - $currentDateTime->getTimestamp();
673
-						if($secondsToExpiry <= $pwdExpireWarningInt) {
674
-							//remove last password expiry warning if any
675
-							$notification = $this->notificationManager->createNotification();
676
-							$notification->setApp('user_ldap')
677
-								->setUser($uid)
678
-								->setObject('pwd_exp_warn', $uid)
679
-							;
680
-							$this->notificationManager->markProcessed($notification);
681
-							//create new password expiry warning
682
-							$notification = $this->notificationManager->createNotification();
683
-							$notification->setApp('user_ldap')
684
-								->setUser($uid)
685
-								->setDateTime($currentDateTime)
686
-								->setObject('pwd_exp_warn', $uid) 
687
-								->setSubject('pwd_exp_warn_days', [(int) ceil($secondsToExpiry / 60 / 60 / 24)])
688
-							;
689
-							$this->notificationManager->notify($notification);
690
-						}
691
-					}
692
-				}
693
-			}
694
-		}
695
-	}
640
+            //handle grace login
641
+            $pwdGraceUseTimeCount = count($pwdGraceUseTime);
642
+            if($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
643
+                if($pwdGraceAuthNLimit 
644
+                    && (count($pwdGraceAuthNLimit) > 0)
645
+                    &&($pwdGraceUseTimeCount < intval($pwdGraceAuthNLimit[0]))) { //at least one more grace login available?
646
+                    $this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
647
+                    header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
648
+                    'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
649
+                } else { //no more grace login available
650
+                    header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
651
+                    'user_ldap.renewPassword.showLoginFormInvalidPassword', array('user' => $uid)));
652
+                }
653
+                exit();
654
+            }
655
+            //handle pwdReset attribute
656
+            if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
657
+                $this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
658
+                header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
659
+                'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
660
+                exit();
661
+            }
662
+            //handle password expiry warning
663
+            if($pwdChangedTime && (count($pwdChangedTime) > 0)) {
664
+                if($pwdMaxAge && (count($pwdMaxAge) > 0)
665
+                    && $pwdExpireWarning && (count($pwdExpireWarning) > 0)) {
666
+                    $pwdMaxAgeInt = intval($pwdMaxAge[0]);
667
+                    $pwdExpireWarningInt = intval($pwdExpireWarning[0]);
668
+                    if($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0){
669
+                        $pwdChangedTimeDt = \DateTime::createFromFormat('YmdHisZ', $pwdChangedTime[0]);
670
+                        $pwdChangedTimeDt->add(new \DateInterval('PT'.$pwdMaxAgeInt.'S'));
671
+                        $currentDateTime = new \DateTime();
672
+                        $secondsToExpiry = $pwdChangedTimeDt->getTimestamp() - $currentDateTime->getTimestamp();
673
+                        if($secondsToExpiry <= $pwdExpireWarningInt) {
674
+                            //remove last password expiry warning if any
675
+                            $notification = $this->notificationManager->createNotification();
676
+                            $notification->setApp('user_ldap')
677
+                                ->setUser($uid)
678
+                                ->setObject('pwd_exp_warn', $uid)
679
+                            ;
680
+                            $this->notificationManager->markProcessed($notification);
681
+                            //create new password expiry warning
682
+                            $notification = $this->notificationManager->createNotification();
683
+                            $notification->setApp('user_ldap')
684
+                                ->setUser($uid)
685
+                                ->setDateTime($currentDateTime)
686
+                                ->setObject('pwd_exp_warn', $uid) 
687
+                                ->setSubject('pwd_exp_warn_days', [(int) ceil($secondsToExpiry / 60 / 60 / 24)])
688
+                            ;
689
+                            $this->notificationManager->notify($notification);
690
+                        }
691
+                    }
692
+                }
693
+            }
694
+        }
695
+    }
696 696
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Jobs/Sync.php 1 patch
Indentation   +290 added lines, -290 removed lines patch added patch discarded remove patch
@@ -39,294 +39,294 @@
 block discarded – undo
39 39
 use OCP\IServerContainer;
40 40
 
41 41
 class Sync extends TimedJob {
42
-	/** @var IServerContainer */
43
-	protected $c;
44
-	/** @var  Helper */
45
-	protected $ldapHelper;
46
-	/** @var  LDAP */
47
-	protected $ldap;
48
-	/** @var  Manager */
49
-	protected $userManager;
50
-	/** @var UserMapping */
51
-	protected $mapper;
52
-	/** @var int */
53
-	protected $maxInterval = 12 * 60 * 60; // 12h
54
-	/** @var int */
55
-	protected $minInterval = 30 * 60; // 30min
56
-
57
-	public function __construct() {
58
-		$this->setInterval(
59
-			\OC::$server->getConfig()->getAppValue(
60
-				'user_ldap',
61
-				'background_sync_interval',
62
-				$this->minInterval
63
-			)
64
-		);
65
-	}
66
-
67
-	/**
68
-	 * updates the interval
69
-	 *
70
-	 * the idea is to adjust the interval depending on the amount of known users
71
-	 * and the attempt to update each user one day. At most it would run every
72
-	 * 30 minutes, and at least every 12 hours.
73
-	 */
74
-	public function updateInterval() {
75
-		$minPagingSize = $this->getMinPagingSize();
76
-		$mappedUsers = $this->mapper->count();
77
-
78
-		$runsPerDay = ($minPagingSize === 0) ? $this->maxInterval : $mappedUsers / $minPagingSize;
79
-		$interval = floor(24 * 60 * 60 / $runsPerDay);
80
-		$interval = min(max($interval, $this->minInterval), $this->maxInterval);
81
-
82
-		$this->c->getConfig()->setAppValue('user_ldap', 'background_sync_interval', $interval);
83
-	}
84
-
85
-	/**
86
-	 * returns the smallest configured paging size
87
-	 * @return int
88
-	 */
89
-	protected function getMinPagingSize() {
90
-		$config = $this->c->getConfig();
91
-		$configKeys = $config->getAppKeys('user_ldap');
92
-		$configKeys = array_filter($configKeys, function($key) {
93
-			return strpos($key, 'ldap_paging_size') !== false;
94
-		});
95
-		$minPagingSize = null;
96
-		foreach ($configKeys as $configKey) {
97
-			$pagingSize = $config->getAppValue('user_ldap', $configKey, $minPagingSize);
98
-			$minPagingSize = $minPagingSize === null ? $pagingSize : min($minPagingSize, $pagingSize);
99
-		}
100
-		return (int)$minPagingSize;
101
-	}
102
-
103
-	/**
104
-	 * @param array $argument
105
-	 */
106
-	protected function run($argument) {
107
-		$this->setArgument($argument);
108
-
109
-		$isBackgroundJobModeAjax = $this->c->getConfig()
110
-				->getAppValue('core', 'backgroundjobs_mode', 'ajax') === 'ajax';
111
-		if($isBackgroundJobModeAjax) {
112
-			return;
113
-		}
114
-
115
-		$cycleData = $this->getCycle();
116
-		if($cycleData === null) {
117
-			$cycleData = $this->determineNextCycle();
118
-			if($cycleData === null) {
119
-				$this->updateInterval();
120
-				return;
121
-			}
122
-		}
123
-
124
-		if(!$this->qualifiesToRun($cycleData)) {
125
-			$this->updateInterval();
126
-			return;
127
-		}
128
-
129
-		try {
130
-			$expectMoreResults = $this->runCycle($cycleData);
131
-			if ($expectMoreResults) {
132
-				$this->increaseOffset($cycleData);
133
-			} else {
134
-				$this->determineNextCycle();
135
-			}
136
-			$this->updateInterval();
137
-		} catch (ServerNotAvailableException $e) {
138
-			$this->determineNextCycle();
139
-		}
140
-	}
141
-
142
-	/**
143
-	 * @param array $cycleData
144
-	 * @return bool whether more results are expected from the same configuration
145
-	 */
146
-	public function runCycle($cycleData) {
147
-		$connection = new Connection($this->ldap, $cycleData['prefix']);
148
-		$access = new Access($connection, $this->ldap, $this->userManager, $this->ldapHelper, $this->c);
149
-		$access->setUserMapper($this->mapper);
150
-
151
-		$filter = $access->combineFilterWithAnd(array(
152
-			$access->connection->ldapUserFilter,
153
-			$access->connection->ldapUserDisplayName . '=*',
154
-			$access->getFilterPartForUserSearch('')
155
-		));
156
-		$results = $access->fetchListOfUsers(
157
-			$filter,
158
-			$access->userManager->getAttributes(),
159
-			$connection->ldapPagingSize,
160
-			$cycleData['offset'],
161
-			true
162
-		);
163
-
164
-		if($connection->ldapPagingSize === 0) {
165
-			return true;
166
-		}
167
-		return count($results) !== $connection->ldapPagingSize;
168
-	}
169
-
170
-	/**
171
-	 * returns the info about the current cycle that should be run, if any,
172
-	 * otherwise null
173
-	 *
174
-	 * @return array|null
175
-	 */
176
-	public function getCycle() {
177
-		$prefixes = $this->ldapHelper->getServerConfigurationPrefixes(true);
178
-		if(count($prefixes) === 0) {
179
-			return null;
180
-		}
181
-
182
-		$config = $this->c->getConfig();
183
-		$cycleData = [
184
-			'prefix' => $config->getAppValue('user_ldap', 'background_sync_prefix', null),
185
-			'offset' => (int)$config->getAppValue('user_ldap', 'background_sync_offset', 0),
186
-		];
187
-
188
-		if(
189
-			$cycleData['prefix'] !== null
190
-			&& in_array($cycleData['prefix'], $prefixes)
191
-		) {
192
-			return $cycleData;
193
-		}
194
-
195
-		return null;
196
-	}
197
-
198
-	/**
199
-	 * Save the provided cycle information in the DB
200
-	 *
201
-	 * @param array $cycleData
202
-	 */
203
-	public function setCycle(array $cycleData) {
204
-		$config = $this->c->getConfig();
205
-		$config->setAppValue('user_ldap', 'background_sync_prefix', $cycleData['prefix']);
206
-		$config->setAppValue('user_ldap', 'background_sync_offset', $cycleData['offset']);
207
-	}
208
-
209
-	/**
210
-	 * returns data about the next cycle that should run, if any, otherwise
211
-	 * null. It also always goes for the next LDAP configuration!
212
-	 *
213
-	 * @param array|null $cycleData the old cycle
214
-	 * @return array|null
215
-	 */
216
-	public function determineNextCycle(array $cycleData = null) {
217
-		$prefixes = $this->ldapHelper->getServerConfigurationPrefixes(true);
218
-		if(count($prefixes) === 0) {
219
-			return null;
220
-		}
221
-
222
-		// get the next prefix in line and remember it
223
-		$oldPrefix = $cycleData === null ? null : $cycleData['prefix'];
224
-		$prefix = $this->getNextPrefix($oldPrefix);
225
-		if($prefix === null) {
226
-			return null;
227
-		}
228
-		$cycleData['prefix'] = $prefix;
229
-		$cycleData['offset'] = 0;
230
-		$this->setCycle(['prefix' => $prefix, 'offset' => 0]);
231
-
232
-		return $cycleData;
233
-	}
234
-
235
-	/**
236
-	 * Checks whether the provided cycle should be run. Currently only the
237
-	 * last configuration change goes into account (at least one hour).
238
-	 *
239
-	 * @param $cycleData
240
-	 * @return bool
241
-	 */
242
-	protected function qualifiesToRun($cycleData) {
243
-		$config = $this->c->getConfig();
244
-		$lastChange = $config->getAppValue('user_ldap', $cycleData['prefix'] . '_lastChange', 0);
245
-		if((time() - $lastChange) > 60 * 30) {
246
-			return true;
247
-		}
248
-		return false;
249
-	}
250
-
251
-	/**
252
-	 * increases the offset of the current cycle for the next run
253
-	 *
254
-	 * @param $cycleData
255
-	 */
256
-	protected function increaseOffset($cycleData) {
257
-		$ldapConfig = new Configuration($cycleData['prefix']);
258
-		$cycleData['offset'] += (int)$ldapConfig->ldapPagingSize;
259
-		$this->setCycle($cycleData);
260
-	}
261
-
262
-	/**
263
-	 * determines the next configuration prefix based on the last one (if any)
264
-	 *
265
-	 * @param string|null $lastPrefix
266
-	 * @return string|null
267
-	 */
268
-	protected function getNextPrefix($lastPrefix) {
269
-		$prefixes = $this->ldapHelper->getServerConfigurationPrefixes(true);
270
-		$noOfPrefixes = count($prefixes);
271
-		if($noOfPrefixes === 0) {
272
-			return null;
273
-		}
274
-		$i = $lastPrefix === null ? false : array_search($lastPrefix, $prefixes, true);
275
-		if($i === false) {
276
-			$i = -1;
277
-		} else {
278
-			$i++;
279
-		}
280
-
281
-		if(!isset($prefixes[$i])) {
282
-			$i = 0;
283
-		}
284
-		return $prefixes[$i];
285
-	}
286
-
287
-	/**
288
-	 * "fixes" DI
289
-	 *
290
-	 * @param array $argument
291
-	 */
292
-	public function setArgument($argument) {
293
-		if(isset($argument['c'])) {
294
-			$this->c = $argument['c'];
295
-		} else {
296
-			$this->c = \OC::$server;
297
-		}
298
-
299
-		if(isset($argument['helper'])) {
300
-			$this->ldapHelper = $argument['helper'];
301
-		} else {
302
-			$this->ldapHelper = new Helper($this->c->getConfig());
303
-		}
304
-
305
-		if(isset($argument['ldapWrapper'])) {
306
-			$this->ldap = $argument['ldapWrapper'];
307
-		} else {
308
-			$this->ldap = new LDAP();
309
-		}
310
-
311
-		if(isset($argument['userManager'])) {
312
-			$this->userManager = $argument['userManager'];
313
-		} else {
314
-			$this->userManager = new Manager(
315
-				$this->c->getConfig(),
316
-				new FilesystemHelper(),
317
-				new LogWrapper(),
318
-				$this->c->getAvatarManager(),
319
-				new Image(),
320
-				$this->c->getDatabaseConnection(),
321
-				$this->c->getUserManager(),
322
-				$this->c->getNotificationManager()
323
-			);
324
-		}
325
-
326
-		if(isset($argument['mapper'])) {
327
-			$this->mapper = $argument['mapper'];
328
-		} else {
329
-			$this->mapper = new UserMapping($this->c->getDatabaseConnection());
330
-		}
331
-	}
42
+    /** @var IServerContainer */
43
+    protected $c;
44
+    /** @var  Helper */
45
+    protected $ldapHelper;
46
+    /** @var  LDAP */
47
+    protected $ldap;
48
+    /** @var  Manager */
49
+    protected $userManager;
50
+    /** @var UserMapping */
51
+    protected $mapper;
52
+    /** @var int */
53
+    protected $maxInterval = 12 * 60 * 60; // 12h
54
+    /** @var int */
55
+    protected $minInterval = 30 * 60; // 30min
56
+
57
+    public function __construct() {
58
+        $this->setInterval(
59
+            \OC::$server->getConfig()->getAppValue(
60
+                'user_ldap',
61
+                'background_sync_interval',
62
+                $this->minInterval
63
+            )
64
+        );
65
+    }
66
+
67
+    /**
68
+     * updates the interval
69
+     *
70
+     * the idea is to adjust the interval depending on the amount of known users
71
+     * and the attempt to update each user one day. At most it would run every
72
+     * 30 minutes, and at least every 12 hours.
73
+     */
74
+    public function updateInterval() {
75
+        $minPagingSize = $this->getMinPagingSize();
76
+        $mappedUsers = $this->mapper->count();
77
+
78
+        $runsPerDay = ($minPagingSize === 0) ? $this->maxInterval : $mappedUsers / $minPagingSize;
79
+        $interval = floor(24 * 60 * 60 / $runsPerDay);
80
+        $interval = min(max($interval, $this->minInterval), $this->maxInterval);
81
+
82
+        $this->c->getConfig()->setAppValue('user_ldap', 'background_sync_interval', $interval);
83
+    }
84
+
85
+    /**
86
+     * returns the smallest configured paging size
87
+     * @return int
88
+     */
89
+    protected function getMinPagingSize() {
90
+        $config = $this->c->getConfig();
91
+        $configKeys = $config->getAppKeys('user_ldap');
92
+        $configKeys = array_filter($configKeys, function($key) {
93
+            return strpos($key, 'ldap_paging_size') !== false;
94
+        });
95
+        $minPagingSize = null;
96
+        foreach ($configKeys as $configKey) {
97
+            $pagingSize = $config->getAppValue('user_ldap', $configKey, $minPagingSize);
98
+            $minPagingSize = $minPagingSize === null ? $pagingSize : min($minPagingSize, $pagingSize);
99
+        }
100
+        return (int)$minPagingSize;
101
+    }
102
+
103
+    /**
104
+     * @param array $argument
105
+     */
106
+    protected function run($argument) {
107
+        $this->setArgument($argument);
108
+
109
+        $isBackgroundJobModeAjax = $this->c->getConfig()
110
+                ->getAppValue('core', 'backgroundjobs_mode', 'ajax') === 'ajax';
111
+        if($isBackgroundJobModeAjax) {
112
+            return;
113
+        }
114
+
115
+        $cycleData = $this->getCycle();
116
+        if($cycleData === null) {
117
+            $cycleData = $this->determineNextCycle();
118
+            if($cycleData === null) {
119
+                $this->updateInterval();
120
+                return;
121
+            }
122
+        }
123
+
124
+        if(!$this->qualifiesToRun($cycleData)) {
125
+            $this->updateInterval();
126
+            return;
127
+        }
128
+
129
+        try {
130
+            $expectMoreResults = $this->runCycle($cycleData);
131
+            if ($expectMoreResults) {
132
+                $this->increaseOffset($cycleData);
133
+            } else {
134
+                $this->determineNextCycle();
135
+            }
136
+            $this->updateInterval();
137
+        } catch (ServerNotAvailableException $e) {
138
+            $this->determineNextCycle();
139
+        }
140
+    }
141
+
142
+    /**
143
+     * @param array $cycleData
144
+     * @return bool whether more results are expected from the same configuration
145
+     */
146
+    public function runCycle($cycleData) {
147
+        $connection = new Connection($this->ldap, $cycleData['prefix']);
148
+        $access = new Access($connection, $this->ldap, $this->userManager, $this->ldapHelper, $this->c);
149
+        $access->setUserMapper($this->mapper);
150
+
151
+        $filter = $access->combineFilterWithAnd(array(
152
+            $access->connection->ldapUserFilter,
153
+            $access->connection->ldapUserDisplayName . '=*',
154
+            $access->getFilterPartForUserSearch('')
155
+        ));
156
+        $results = $access->fetchListOfUsers(
157
+            $filter,
158
+            $access->userManager->getAttributes(),
159
+            $connection->ldapPagingSize,
160
+            $cycleData['offset'],
161
+            true
162
+        );
163
+
164
+        if($connection->ldapPagingSize === 0) {
165
+            return true;
166
+        }
167
+        return count($results) !== $connection->ldapPagingSize;
168
+    }
169
+
170
+    /**
171
+     * returns the info about the current cycle that should be run, if any,
172
+     * otherwise null
173
+     *
174
+     * @return array|null
175
+     */
176
+    public function getCycle() {
177
+        $prefixes = $this->ldapHelper->getServerConfigurationPrefixes(true);
178
+        if(count($prefixes) === 0) {
179
+            return null;
180
+        }
181
+
182
+        $config = $this->c->getConfig();
183
+        $cycleData = [
184
+            'prefix' => $config->getAppValue('user_ldap', 'background_sync_prefix', null),
185
+            'offset' => (int)$config->getAppValue('user_ldap', 'background_sync_offset', 0),
186
+        ];
187
+
188
+        if(
189
+            $cycleData['prefix'] !== null
190
+            && in_array($cycleData['prefix'], $prefixes)
191
+        ) {
192
+            return $cycleData;
193
+        }
194
+
195
+        return null;
196
+    }
197
+
198
+    /**
199
+     * Save the provided cycle information in the DB
200
+     *
201
+     * @param array $cycleData
202
+     */
203
+    public function setCycle(array $cycleData) {
204
+        $config = $this->c->getConfig();
205
+        $config->setAppValue('user_ldap', 'background_sync_prefix', $cycleData['prefix']);
206
+        $config->setAppValue('user_ldap', 'background_sync_offset', $cycleData['offset']);
207
+    }
208
+
209
+    /**
210
+     * returns data about the next cycle that should run, if any, otherwise
211
+     * null. It also always goes for the next LDAP configuration!
212
+     *
213
+     * @param array|null $cycleData the old cycle
214
+     * @return array|null
215
+     */
216
+    public function determineNextCycle(array $cycleData = null) {
217
+        $prefixes = $this->ldapHelper->getServerConfigurationPrefixes(true);
218
+        if(count($prefixes) === 0) {
219
+            return null;
220
+        }
221
+
222
+        // get the next prefix in line and remember it
223
+        $oldPrefix = $cycleData === null ? null : $cycleData['prefix'];
224
+        $prefix = $this->getNextPrefix($oldPrefix);
225
+        if($prefix === null) {
226
+            return null;
227
+        }
228
+        $cycleData['prefix'] = $prefix;
229
+        $cycleData['offset'] = 0;
230
+        $this->setCycle(['prefix' => $prefix, 'offset' => 0]);
231
+
232
+        return $cycleData;
233
+    }
234
+
235
+    /**
236
+     * Checks whether the provided cycle should be run. Currently only the
237
+     * last configuration change goes into account (at least one hour).
238
+     *
239
+     * @param $cycleData
240
+     * @return bool
241
+     */
242
+    protected function qualifiesToRun($cycleData) {
243
+        $config = $this->c->getConfig();
244
+        $lastChange = $config->getAppValue('user_ldap', $cycleData['prefix'] . '_lastChange', 0);
245
+        if((time() - $lastChange) > 60 * 30) {
246
+            return true;
247
+        }
248
+        return false;
249
+    }
250
+
251
+    /**
252
+     * increases the offset of the current cycle for the next run
253
+     *
254
+     * @param $cycleData
255
+     */
256
+    protected function increaseOffset($cycleData) {
257
+        $ldapConfig = new Configuration($cycleData['prefix']);
258
+        $cycleData['offset'] += (int)$ldapConfig->ldapPagingSize;
259
+        $this->setCycle($cycleData);
260
+    }
261
+
262
+    /**
263
+     * determines the next configuration prefix based on the last one (if any)
264
+     *
265
+     * @param string|null $lastPrefix
266
+     * @return string|null
267
+     */
268
+    protected function getNextPrefix($lastPrefix) {
269
+        $prefixes = $this->ldapHelper->getServerConfigurationPrefixes(true);
270
+        $noOfPrefixes = count($prefixes);
271
+        if($noOfPrefixes === 0) {
272
+            return null;
273
+        }
274
+        $i = $lastPrefix === null ? false : array_search($lastPrefix, $prefixes, true);
275
+        if($i === false) {
276
+            $i = -1;
277
+        } else {
278
+            $i++;
279
+        }
280
+
281
+        if(!isset($prefixes[$i])) {
282
+            $i = 0;
283
+        }
284
+        return $prefixes[$i];
285
+    }
286
+
287
+    /**
288
+     * "fixes" DI
289
+     *
290
+     * @param array $argument
291
+     */
292
+    public function setArgument($argument) {
293
+        if(isset($argument['c'])) {
294
+            $this->c = $argument['c'];
295
+        } else {
296
+            $this->c = \OC::$server;
297
+        }
298
+
299
+        if(isset($argument['helper'])) {
300
+            $this->ldapHelper = $argument['helper'];
301
+        } else {
302
+            $this->ldapHelper = new Helper($this->c->getConfig());
303
+        }
304
+
305
+        if(isset($argument['ldapWrapper'])) {
306
+            $this->ldap = $argument['ldapWrapper'];
307
+        } else {
308
+            $this->ldap = new LDAP();
309
+        }
310
+
311
+        if(isset($argument['userManager'])) {
312
+            $this->userManager = $argument['userManager'];
313
+        } else {
314
+            $this->userManager = new Manager(
315
+                $this->c->getConfig(),
316
+                new FilesystemHelper(),
317
+                new LogWrapper(),
318
+                $this->c->getAvatarManager(),
319
+                new Image(),
320
+                $this->c->getDatabaseConnection(),
321
+                $this->c->getUserManager(),
322
+                $this->c->getNotificationManager()
323
+            );
324
+        }
325
+
326
+        if(isset($argument['mapper'])) {
327
+            $this->mapper = $argument['mapper'];
328
+        } else {
329
+            $this->mapper = new UserMapping($this->c->getDatabaseConnection());
330
+        }
331
+    }
332 332
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Jobs/UpdateGroups.php 1 patch
Indentation   +164 added lines, -164 removed lines patch added patch discarded remove patch
@@ -41,183 +41,183 @@
 block discarded – undo
41 41
 use OCA\User_LDAP\User\Manager;
42 42
 
43 43
 class UpdateGroups extends \OC\BackgroundJob\TimedJob {
44
-	static private $groupsFromDB;
45
-
46
-	static private $groupBE;
47
-
48
-	public function __construct(){
49
-		$this->interval = self::getRefreshInterval();
50
-	}
51
-
52
-	/**
53
-	 * @param mixed $argument
54
-	 */
55
-	public function run($argument){
56
-		self::updateGroups();
57
-	}
58
-
59
-	static public function updateGroups() {
60
-		\OCP\Util::writeLog('user_ldap', 'Run background job "updateGroups"', \OCP\Util::DEBUG);
61
-
62
-		$knownGroups = array_keys(self::getKnownGroups());
63
-		$actualGroups = self::getGroupBE()->getGroups();
64
-
65
-		if(empty($actualGroups) && empty($knownGroups)) {
66
-			\OCP\Util::writeLog('user_ldap',
67
-				'bgJ "updateGroups" – groups do not seem to be configured properly, aborting.',
68
-				\OCP\Util::INFO);
69
-			return;
70
-		}
71
-
72
-		self::handleKnownGroups(array_intersect($actualGroups, $knownGroups));
73
-		self::handleCreatedGroups(array_diff($actualGroups, $knownGroups));
74
-		self::handleRemovedGroups(array_diff($knownGroups, $actualGroups));
75
-
76
-		\OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – Finished.', \OCP\Util::DEBUG);
77
-	}
78
-
79
-	/**
80
-	 * @return int
81
-	 */
82
-	static private function getRefreshInterval() {
83
-		//defaults to every hour
84
-		return \OCP\Config::getAppValue('user_ldap', 'bgjRefreshInterval', 3600);
85
-	}
86
-
87
-	/**
88
-	 * @param string[] $groups
89
-	 */
90
-	static private function handleKnownGroups($groups) {
91
-		\OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – Dealing with known Groups.', \OCP\Util::DEBUG);
92
-		$query = \OCP\DB::prepare('
44
+    static private $groupsFromDB;
45
+
46
+    static private $groupBE;
47
+
48
+    public function __construct(){
49
+        $this->interval = self::getRefreshInterval();
50
+    }
51
+
52
+    /**
53
+     * @param mixed $argument
54
+     */
55
+    public function run($argument){
56
+        self::updateGroups();
57
+    }
58
+
59
+    static public function updateGroups() {
60
+        \OCP\Util::writeLog('user_ldap', 'Run background job "updateGroups"', \OCP\Util::DEBUG);
61
+
62
+        $knownGroups = array_keys(self::getKnownGroups());
63
+        $actualGroups = self::getGroupBE()->getGroups();
64
+
65
+        if(empty($actualGroups) && empty($knownGroups)) {
66
+            \OCP\Util::writeLog('user_ldap',
67
+                'bgJ "updateGroups" – groups do not seem to be configured properly, aborting.',
68
+                \OCP\Util::INFO);
69
+            return;
70
+        }
71
+
72
+        self::handleKnownGroups(array_intersect($actualGroups, $knownGroups));
73
+        self::handleCreatedGroups(array_diff($actualGroups, $knownGroups));
74
+        self::handleRemovedGroups(array_diff($knownGroups, $actualGroups));
75
+
76
+        \OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – Finished.', \OCP\Util::DEBUG);
77
+    }
78
+
79
+    /**
80
+     * @return int
81
+     */
82
+    static private function getRefreshInterval() {
83
+        //defaults to every hour
84
+        return \OCP\Config::getAppValue('user_ldap', 'bgjRefreshInterval', 3600);
85
+    }
86
+
87
+    /**
88
+     * @param string[] $groups
89
+     */
90
+    static private function handleKnownGroups($groups) {
91
+        \OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – Dealing with known Groups.', \OCP\Util::DEBUG);
92
+        $query = \OCP\DB::prepare('
93 93
 			UPDATE `*PREFIX*ldap_group_members`
94 94
 			SET `owncloudusers` = ?
95 95
 			WHERE `owncloudname` = ?
96 96
 		');
97
-		foreach($groups as $group) {
98
-			//we assume, that self::$groupsFromDB has been retrieved already
99
-			$knownUsers = unserialize(self::$groupsFromDB[$group]['owncloudusers']);
100
-			$actualUsers = self::getGroupBE()->usersInGroup($group);
101
-			$hasChanged = false;
102
-			foreach(array_diff($knownUsers, $actualUsers) as $removedUser) {
103
-				\OCP\Util::emitHook('OC_User', 'post_removeFromGroup', array('uid' => $removedUser, 'gid' => $group));
104
-				\OCP\Util::writeLog('user_ldap',
105
-				'bgJ "updateGroups" – "'.$removedUser.'" removed from "'.$group.'".',
106
-				\OCP\Util::INFO);
107
-				$hasChanged = true;
108
-			}
109
-			foreach(array_diff($actualUsers, $knownUsers) as $addedUser) {
110
-				\OCP\Util::emitHook('OC_User', 'post_addToGroup', array('uid' => $addedUser, 'gid' => $group));
111
-				\OCP\Util::writeLog('user_ldap',
112
-				'bgJ "updateGroups" – "'.$addedUser.'" added to "'.$group.'".',
113
-				\OCP\Util::INFO);
114
-				$hasChanged = true;
115
-			}
116
-			if($hasChanged) {
117
-				$query->execute(array(serialize($actualUsers), $group));
118
-			}
119
-		}
120
-		\OCP\Util::writeLog('user_ldap',
121
-			'bgJ "updateGroups" – FINISHED dealing with known Groups.',
122
-			\OCP\Util::DEBUG);
123
-	}
124
-
125
-	/**
126
-	 * @param string[] $createdGroups
127
-	 */
128
-	static private function handleCreatedGroups($createdGroups) {
129
-		\OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – dealing with created Groups.', \OCP\Util::DEBUG);
130
-		$query = \OCP\DB::prepare('
97
+        foreach($groups as $group) {
98
+            //we assume, that self::$groupsFromDB has been retrieved already
99
+            $knownUsers = unserialize(self::$groupsFromDB[$group]['owncloudusers']);
100
+            $actualUsers = self::getGroupBE()->usersInGroup($group);
101
+            $hasChanged = false;
102
+            foreach(array_diff($knownUsers, $actualUsers) as $removedUser) {
103
+                \OCP\Util::emitHook('OC_User', 'post_removeFromGroup', array('uid' => $removedUser, 'gid' => $group));
104
+                \OCP\Util::writeLog('user_ldap',
105
+                'bgJ "updateGroups" – "'.$removedUser.'" removed from "'.$group.'".',
106
+                \OCP\Util::INFO);
107
+                $hasChanged = true;
108
+            }
109
+            foreach(array_diff($actualUsers, $knownUsers) as $addedUser) {
110
+                \OCP\Util::emitHook('OC_User', 'post_addToGroup', array('uid' => $addedUser, 'gid' => $group));
111
+                \OCP\Util::writeLog('user_ldap',
112
+                'bgJ "updateGroups" – "'.$addedUser.'" added to "'.$group.'".',
113
+                \OCP\Util::INFO);
114
+                $hasChanged = true;
115
+            }
116
+            if($hasChanged) {
117
+                $query->execute(array(serialize($actualUsers), $group));
118
+            }
119
+        }
120
+        \OCP\Util::writeLog('user_ldap',
121
+            'bgJ "updateGroups" – FINISHED dealing with known Groups.',
122
+            \OCP\Util::DEBUG);
123
+    }
124
+
125
+    /**
126
+     * @param string[] $createdGroups
127
+     */
128
+    static private function handleCreatedGroups($createdGroups) {
129
+        \OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – dealing with created Groups.', \OCP\Util::DEBUG);
130
+        $query = \OCP\DB::prepare('
131 131
 			INSERT
132 132
 			INTO `*PREFIX*ldap_group_members` (`owncloudname`, `owncloudusers`)
133 133
 			VALUES (?, ?)
134 134
 		');
135
-		foreach($createdGroups as $createdGroup) {
136
-			\OCP\Util::writeLog('user_ldap',
137
-				'bgJ "updateGroups" – new group "'.$createdGroup.'" found.',
138
-				\OCP\Util::INFO);
139
-			$users = serialize(self::getGroupBE()->usersInGroup($createdGroup));
140
-			$query->execute(array($createdGroup, $users));
141
-		}
142
-		\OCP\Util::writeLog('user_ldap',
143
-			'bgJ "updateGroups" – FINISHED dealing with created Groups.',
144
-			\OCP\Util::DEBUG);
145
-	}
146
-
147
-	/**
148
-	 * @param string[] $removedGroups
149
-	 */
150
-	static private function handleRemovedGroups($removedGroups) {
151
-		\OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – dealing with removed groups.', \OCP\Util::DEBUG);
152
-		$query = \OCP\DB::prepare('
135
+        foreach($createdGroups as $createdGroup) {
136
+            \OCP\Util::writeLog('user_ldap',
137
+                'bgJ "updateGroups" – new group "'.$createdGroup.'" found.',
138
+                \OCP\Util::INFO);
139
+            $users = serialize(self::getGroupBE()->usersInGroup($createdGroup));
140
+            $query->execute(array($createdGroup, $users));
141
+        }
142
+        \OCP\Util::writeLog('user_ldap',
143
+            'bgJ "updateGroups" – FINISHED dealing with created Groups.',
144
+            \OCP\Util::DEBUG);
145
+    }
146
+
147
+    /**
148
+     * @param string[] $removedGroups
149
+     */
150
+    static private function handleRemovedGroups($removedGroups) {
151
+        \OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – dealing with removed groups.', \OCP\Util::DEBUG);
152
+        $query = \OCP\DB::prepare('
153 153
 			DELETE
154 154
 			FROM `*PREFIX*ldap_group_members`
155 155
 			WHERE `owncloudname` = ?
156 156
 		');
157
-		foreach($removedGroups as $removedGroup) {
158
-			\OCP\Util::writeLog('user_ldap',
159
-				'bgJ "updateGroups" – group "'.$removedGroup.'" was removed.',
160
-				\OCP\Util::INFO);
161
-			$query->execute(array($removedGroup));
162
-		}
163
-		\OCP\Util::writeLog('user_ldap',
164
-			'bgJ "updateGroups" – FINISHED dealing with removed groups.',
165
-			\OCP\Util::DEBUG);
166
-	}
167
-
168
-	/**
169
-	 * @return \OCA\User_LDAP\Group_LDAP|\OCA\User_LDAP\Group_Proxy
170
-	 */
171
-	static private function getGroupBE() {
172
-		if(!is_null(self::$groupBE)) {
173
-			return self::$groupBE;
174
-		}
175
-		$helper = new Helper(\OC::$server->getConfig());
176
-		$configPrefixes = $helper->getServerConfigurationPrefixes(true);
177
-		$ldapWrapper = new LDAP();
178
-		if(count($configPrefixes) === 1) {
179
-			//avoid the proxy when there is only one LDAP server configured
180
-			$dbc = \OC::$server->getDatabaseConnection();
181
-			$userManager = new Manager(
182
-				\OC::$server->getConfig(),
183
-				new FilesystemHelper(),
184
-				new LogWrapper(),
185
-				\OC::$server->getAvatarManager(),
186
-				new \OCP\Image(),
187
-				$dbc,
188
-				\OC::$server->getUserManager(),
189
-				\OC::$server->getNotificationManager());
190
-			$connector = new Connection($ldapWrapper, $configPrefixes[0]);
191
-			$ldapAccess = new Access($connector, $ldapWrapper, $userManager, $helper, \OC::$server);
192
-			$groupMapper = new GroupMapping($dbc);
193
-			$userMapper  = new UserMapping($dbc);
194
-			$ldapAccess->setGroupMapper($groupMapper);
195
-			$ldapAccess->setUserMapper($userMapper);
196
-			self::$groupBE = new \OCA\User_LDAP\Group_LDAP($ldapAccess);
197
-		} else {
198
-			self::$groupBE = new \OCA\User_LDAP\Group_Proxy($configPrefixes, $ldapWrapper);
199
-		}
200
-
201
-		return self::$groupBE;
202
-	}
203
-
204
-	/**
205
-	 * @return array
206
-	 */
207
-	static private function getKnownGroups() {
208
-		if(is_array(self::$groupsFromDB)) {
209
-			return self::$groupsFromDB;
210
-		}
211
-		$query = \OCP\DB::prepare('
157
+        foreach($removedGroups as $removedGroup) {
158
+            \OCP\Util::writeLog('user_ldap',
159
+                'bgJ "updateGroups" – group "'.$removedGroup.'" was removed.',
160
+                \OCP\Util::INFO);
161
+            $query->execute(array($removedGroup));
162
+        }
163
+        \OCP\Util::writeLog('user_ldap',
164
+            'bgJ "updateGroups" – FINISHED dealing with removed groups.',
165
+            \OCP\Util::DEBUG);
166
+    }
167
+
168
+    /**
169
+     * @return \OCA\User_LDAP\Group_LDAP|\OCA\User_LDAP\Group_Proxy
170
+     */
171
+    static private function getGroupBE() {
172
+        if(!is_null(self::$groupBE)) {
173
+            return self::$groupBE;
174
+        }
175
+        $helper = new Helper(\OC::$server->getConfig());
176
+        $configPrefixes = $helper->getServerConfigurationPrefixes(true);
177
+        $ldapWrapper = new LDAP();
178
+        if(count($configPrefixes) === 1) {
179
+            //avoid the proxy when there is only one LDAP server configured
180
+            $dbc = \OC::$server->getDatabaseConnection();
181
+            $userManager = new Manager(
182
+                \OC::$server->getConfig(),
183
+                new FilesystemHelper(),
184
+                new LogWrapper(),
185
+                \OC::$server->getAvatarManager(),
186
+                new \OCP\Image(),
187
+                $dbc,
188
+                \OC::$server->getUserManager(),
189
+                \OC::$server->getNotificationManager());
190
+            $connector = new Connection($ldapWrapper, $configPrefixes[0]);
191
+            $ldapAccess = new Access($connector, $ldapWrapper, $userManager, $helper, \OC::$server);
192
+            $groupMapper = new GroupMapping($dbc);
193
+            $userMapper  = new UserMapping($dbc);
194
+            $ldapAccess->setGroupMapper($groupMapper);
195
+            $ldapAccess->setUserMapper($userMapper);
196
+            self::$groupBE = new \OCA\User_LDAP\Group_LDAP($ldapAccess);
197
+        } else {
198
+            self::$groupBE = new \OCA\User_LDAP\Group_Proxy($configPrefixes, $ldapWrapper);
199
+        }
200
+
201
+        return self::$groupBE;
202
+    }
203
+
204
+    /**
205
+     * @return array
206
+     */
207
+    static private function getKnownGroups() {
208
+        if(is_array(self::$groupsFromDB)) {
209
+            return self::$groupsFromDB;
210
+        }
211
+        $query = \OCP\DB::prepare('
212 212
 			SELECT `owncloudname`, `owncloudusers`
213 213
 			FROM `*PREFIX*ldap_group_members`
214 214
 		');
215
-		$result = $query->execute()->fetchAll();
216
-		self::$groupsFromDB = array();
217
-		foreach($result as $dataset) {
218
-			self::$groupsFromDB[$dataset['owncloudname']] = $dataset;
219
-		}
220
-
221
-		return self::$groupsFromDB;
222
-	}
215
+        $result = $query->execute()->fetchAll();
216
+        self::$groupsFromDB = array();
217
+        foreach($result as $dataset) {
218
+            self::$groupsFromDB[$dataset['owncloudname']] = $dataset;
219
+        }
220
+
221
+        return self::$groupsFromDB;
222
+    }
223 223
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Configuration.php 1 patch
Indentation   +464 added lines, -464 removed lines patch added patch discarded remove patch
@@ -36,493 +36,493 @@
 block discarded – undo
36 36
  */
37 37
 class Configuration {
38 38
 
39
-	protected $configPrefix = null;
40
-	protected $configRead = false;
39
+    protected $configPrefix = null;
40
+    protected $configRead = false;
41 41
 
42
-	//settings
43
-	protected $config = array(
44
-		'ldapHost' => null,
45
-		'ldapPort' => null,
46
-		'ldapBackupHost' => null,
47
-		'ldapBackupPort' => null,
48
-		'ldapBase' => null,
49
-		'ldapBaseUsers' => null,
50
-		'ldapBaseGroups' => null,
51
-		'ldapAgentName' => null,
52
-		'ldapAgentPassword' => null,
53
-		'ldapTLS' => null,
54
-		'turnOffCertCheck' => null,
55
-		'ldapIgnoreNamingRules' => null,
56
-		'ldapUserDisplayName' => null,
57
-		'ldapUserDisplayName2' => null,
58
-		'ldapGidNumber' => null,
59
-		'ldapUserFilterObjectclass' => null,
60
-		'ldapUserFilterGroups' => null,
61
-		'ldapUserFilter' => null,
62
-		'ldapUserFilterMode' => null,
63
-		'ldapGroupFilter' => null,
64
-		'ldapGroupFilterMode' => null,
65
-		'ldapGroupFilterObjectclass' => null,
66
-		'ldapGroupFilterGroups' => null,
67
-		'ldapGroupDisplayName' => null,
68
-		'ldapGroupMemberAssocAttr' => null,
69
-		'ldapLoginFilter' => null,
70
-		'ldapLoginFilterMode' => null,
71
-		'ldapLoginFilterEmail' => null,
72
-		'ldapLoginFilterUsername' => null,
73
-		'ldapLoginFilterAttributes' => null,
74
-		'ldapQuotaAttribute' => null,
75
-		'ldapQuotaDefault' => null,
76
-		'ldapEmailAttribute' => null,
77
-		'ldapCacheTTL' => null,
78
-		'ldapUuidUserAttribute' => 'auto',
79
-		'ldapUuidGroupAttribute' => 'auto',
80
-		'ldapOverrideMainServer' => false,
81
-		'ldapConfigurationActive' => false,
82
-		'ldapAttributesForUserSearch' => null,
83
-		'ldapAttributesForGroupSearch' => null,
84
-		'ldapExperiencedAdmin' => false,
85
-		'homeFolderNamingRule' => null,
86
-		'hasPagedResultSupport' => false,
87
-		'hasMemberOfFilterSupport' => false,
88
-		'useMemberOfToDetectMembership' => true,
89
-		'ldapExpertUsernameAttr' => null,
90
-		'ldapExpertUUIDUserAttr' => null,
91
-		'ldapExpertUUIDGroupAttr' => null,
92
-		'lastJpegPhotoLookup' => null,
93
-		'ldapNestedGroups' => false,
94
-		'ldapPagingSize' => null,
95
-		'turnOnPasswordChange' => false,
96
-		'ldapDynamicGroupMemberURL' => null,
97
-		'ldapDefaultPPolicyDN' => null,
98
-	);
42
+    //settings
43
+    protected $config = array(
44
+        'ldapHost' => null,
45
+        'ldapPort' => null,
46
+        'ldapBackupHost' => null,
47
+        'ldapBackupPort' => null,
48
+        'ldapBase' => null,
49
+        'ldapBaseUsers' => null,
50
+        'ldapBaseGroups' => null,
51
+        'ldapAgentName' => null,
52
+        'ldapAgentPassword' => null,
53
+        'ldapTLS' => null,
54
+        'turnOffCertCheck' => null,
55
+        'ldapIgnoreNamingRules' => null,
56
+        'ldapUserDisplayName' => null,
57
+        'ldapUserDisplayName2' => null,
58
+        'ldapGidNumber' => null,
59
+        'ldapUserFilterObjectclass' => null,
60
+        'ldapUserFilterGroups' => null,
61
+        'ldapUserFilter' => null,
62
+        'ldapUserFilterMode' => null,
63
+        'ldapGroupFilter' => null,
64
+        'ldapGroupFilterMode' => null,
65
+        'ldapGroupFilterObjectclass' => null,
66
+        'ldapGroupFilterGroups' => null,
67
+        'ldapGroupDisplayName' => null,
68
+        'ldapGroupMemberAssocAttr' => null,
69
+        'ldapLoginFilter' => null,
70
+        'ldapLoginFilterMode' => null,
71
+        'ldapLoginFilterEmail' => null,
72
+        'ldapLoginFilterUsername' => null,
73
+        'ldapLoginFilterAttributes' => null,
74
+        'ldapQuotaAttribute' => null,
75
+        'ldapQuotaDefault' => null,
76
+        'ldapEmailAttribute' => null,
77
+        'ldapCacheTTL' => null,
78
+        'ldapUuidUserAttribute' => 'auto',
79
+        'ldapUuidGroupAttribute' => 'auto',
80
+        'ldapOverrideMainServer' => false,
81
+        'ldapConfigurationActive' => false,
82
+        'ldapAttributesForUserSearch' => null,
83
+        'ldapAttributesForGroupSearch' => null,
84
+        'ldapExperiencedAdmin' => false,
85
+        'homeFolderNamingRule' => null,
86
+        'hasPagedResultSupport' => false,
87
+        'hasMemberOfFilterSupport' => false,
88
+        'useMemberOfToDetectMembership' => true,
89
+        'ldapExpertUsernameAttr' => null,
90
+        'ldapExpertUUIDUserAttr' => null,
91
+        'ldapExpertUUIDGroupAttr' => null,
92
+        'lastJpegPhotoLookup' => null,
93
+        'ldapNestedGroups' => false,
94
+        'ldapPagingSize' => null,
95
+        'turnOnPasswordChange' => false,
96
+        'ldapDynamicGroupMemberURL' => null,
97
+        'ldapDefaultPPolicyDN' => null,
98
+    );
99 99
 
100
-	/**
101
-	 * @param string $configPrefix
102
-	 * @param bool $autoRead
103
-	 */
104
-	public function __construct($configPrefix, $autoRead = true) {
105
-		$this->configPrefix = $configPrefix;
106
-		if($autoRead) {
107
-			$this->readConfiguration();
108
-		}
109
-	}
100
+    /**
101
+     * @param string $configPrefix
102
+     * @param bool $autoRead
103
+     */
104
+    public function __construct($configPrefix, $autoRead = true) {
105
+        $this->configPrefix = $configPrefix;
106
+        if($autoRead) {
107
+            $this->readConfiguration();
108
+        }
109
+    }
110 110
 
111
-	/**
112
-	 * @param string $name
113
-	 * @return mixed|null
114
-	 */
115
-	public function __get($name) {
116
-		if(isset($this->config[$name])) {
117
-			return $this->config[$name];
118
-		}
119
-		return null;
120
-	}
111
+    /**
112
+     * @param string $name
113
+     * @return mixed|null
114
+     */
115
+    public function __get($name) {
116
+        if(isset($this->config[$name])) {
117
+            return $this->config[$name];
118
+        }
119
+        return null;
120
+    }
121 121
 
122
-	/**
123
-	 * @param string $name
124
-	 * @param mixed $value
125
-	 */
126
-	public function __set($name, $value) {
127
-		$this->setConfiguration(array($name => $value));
128
-	}
122
+    /**
123
+     * @param string $name
124
+     * @param mixed $value
125
+     */
126
+    public function __set($name, $value) {
127
+        $this->setConfiguration(array($name => $value));
128
+    }
129 129
 
130
-	/**
131
-	 * @return array
132
-	 */
133
-	public function getConfiguration() {
134
-		return $this->config;
135
-	}
130
+    /**
131
+     * @return array
132
+     */
133
+    public function getConfiguration() {
134
+        return $this->config;
135
+    }
136 136
 
137
-	/**
138
-	 * set LDAP configuration with values delivered by an array, not read
139
-	 * from configuration. It does not save the configuration! To do so, you
140
-	 * must call saveConfiguration afterwards.
141
-	 * @param array $config array that holds the config parameters in an associated
142
-	 * array
143
-	 * @param array &$applied optional; array where the set fields will be given to
144
-	 * @return false|null
145
-	 */
146
-	public function setConfiguration($config, &$applied = null) {
147
-		if(!is_array($config)) {
148
-			return false;
149
-		}
137
+    /**
138
+     * set LDAP configuration with values delivered by an array, not read
139
+     * from configuration. It does not save the configuration! To do so, you
140
+     * must call saveConfiguration afterwards.
141
+     * @param array $config array that holds the config parameters in an associated
142
+     * array
143
+     * @param array &$applied optional; array where the set fields will be given to
144
+     * @return false|null
145
+     */
146
+    public function setConfiguration($config, &$applied = null) {
147
+        if(!is_array($config)) {
148
+            return false;
149
+        }
150 150
 
151
-		$cta = $this->getConfigTranslationArray();
152
-		foreach($config as $inputKey => $val) {
153
-			if(strpos($inputKey, '_') !== false && array_key_exists($inputKey, $cta)) {
154
-				$key = $cta[$inputKey];
155
-			} elseif(array_key_exists($inputKey, $this->config)) {
156
-				$key = $inputKey;
157
-			} else {
158
-				continue;
159
-			}
151
+        $cta = $this->getConfigTranslationArray();
152
+        foreach($config as $inputKey => $val) {
153
+            if(strpos($inputKey, '_') !== false && array_key_exists($inputKey, $cta)) {
154
+                $key = $cta[$inputKey];
155
+            } elseif(array_key_exists($inputKey, $this->config)) {
156
+                $key = $inputKey;
157
+            } else {
158
+                continue;
159
+            }
160 160
 
161
-			$setMethod = 'setValue';
162
-			switch($key) {
163
-				case 'ldapAgentPassword':
164
-					$setMethod = 'setRawValue';
165
-					break;
166
-				case 'homeFolderNamingRule':
167
-					$trimmedVal = trim($val);
168
-					if ($trimmedVal !== '' && strpos($val, 'attr:') === false) {
169
-						$val = 'attr:'.$trimmedVal;
170
-					}
171
-					break;
172
-				case 'ldapBase':
173
-				case 'ldapBaseUsers':
174
-				case 'ldapBaseGroups':
175
-				case 'ldapAttributesForUserSearch':
176
-				case 'ldapAttributesForGroupSearch':
177
-				case 'ldapUserFilterObjectclass':
178
-				case 'ldapUserFilterGroups':
179
-				case 'ldapGroupFilterObjectclass':
180
-				case 'ldapGroupFilterGroups':
181
-				case 'ldapLoginFilterAttributes':
182
-					$setMethod = 'setMultiLine';
183
-					break;
184
-			}
185
-			$this->$setMethod($key, $val);
186
-			if(is_array($applied)) {
187
-				$applied[] = $inputKey;
188
-			}
189
-		}
190
-		return null;
191
-	}
161
+            $setMethod = 'setValue';
162
+            switch($key) {
163
+                case 'ldapAgentPassword':
164
+                    $setMethod = 'setRawValue';
165
+                    break;
166
+                case 'homeFolderNamingRule':
167
+                    $trimmedVal = trim($val);
168
+                    if ($trimmedVal !== '' && strpos($val, 'attr:') === false) {
169
+                        $val = 'attr:'.$trimmedVal;
170
+                    }
171
+                    break;
172
+                case 'ldapBase':
173
+                case 'ldapBaseUsers':
174
+                case 'ldapBaseGroups':
175
+                case 'ldapAttributesForUserSearch':
176
+                case 'ldapAttributesForGroupSearch':
177
+                case 'ldapUserFilterObjectclass':
178
+                case 'ldapUserFilterGroups':
179
+                case 'ldapGroupFilterObjectclass':
180
+                case 'ldapGroupFilterGroups':
181
+                case 'ldapLoginFilterAttributes':
182
+                    $setMethod = 'setMultiLine';
183
+                    break;
184
+            }
185
+            $this->$setMethod($key, $val);
186
+            if(is_array($applied)) {
187
+                $applied[] = $inputKey;
188
+            }
189
+        }
190
+        return null;
191
+    }
192 192
 
193
-	public function readConfiguration() {
194
-		if(!$this->configRead && !is_null($this->configPrefix)) {
195
-			$cta = array_flip($this->getConfigTranslationArray());
196
-			foreach($this->config as $key => $val) {
197
-				if(!isset($cta[$key])) {
198
-					//some are determined
199
-					continue;
200
-				}
201
-				$dbKey = $cta[$key];
202
-				switch($key) {
203
-					case 'ldapBase':
204
-					case 'ldapBaseUsers':
205
-					case 'ldapBaseGroups':
206
-					case 'ldapAttributesForUserSearch':
207
-					case 'ldapAttributesForGroupSearch':
208
-					case 'ldapUserFilterObjectclass':
209
-					case 'ldapUserFilterGroups':
210
-					case 'ldapGroupFilterObjectclass':
211
-					case 'ldapGroupFilterGroups':
212
-					case 'ldapLoginFilterAttributes':
213
-						$readMethod = 'getMultiLine';
214
-						break;
215
-					case 'ldapIgnoreNamingRules':
216
-						$readMethod = 'getSystemValue';
217
-						$dbKey = $key;
218
-						break;
219
-					case 'ldapAgentPassword':
220
-						$readMethod = 'getPwd';
221
-						break;
222
-					case 'ldapUserDisplayName2':
223
-					case 'ldapGroupDisplayName':
224
-						$readMethod = 'getLcValue';
225
-						break;
226
-					case 'ldapUserDisplayName':
227
-					default:
228
-						// user display name does not lower case because
229
-						// we rely on an upper case N as indicator whether to
230
-						// auto-detect it or not. FIXME
231
-						$readMethod = 'getValue';
232
-						break;
233
-				}
234
-				$this->config[$key] = $this->$readMethod($dbKey);
235
-			}
236
-			$this->configRead = true;
237
-		}
238
-	}
193
+    public function readConfiguration() {
194
+        if(!$this->configRead && !is_null($this->configPrefix)) {
195
+            $cta = array_flip($this->getConfigTranslationArray());
196
+            foreach($this->config as $key => $val) {
197
+                if(!isset($cta[$key])) {
198
+                    //some are determined
199
+                    continue;
200
+                }
201
+                $dbKey = $cta[$key];
202
+                switch($key) {
203
+                    case 'ldapBase':
204
+                    case 'ldapBaseUsers':
205
+                    case 'ldapBaseGroups':
206
+                    case 'ldapAttributesForUserSearch':
207
+                    case 'ldapAttributesForGroupSearch':
208
+                    case 'ldapUserFilterObjectclass':
209
+                    case 'ldapUserFilterGroups':
210
+                    case 'ldapGroupFilterObjectclass':
211
+                    case 'ldapGroupFilterGroups':
212
+                    case 'ldapLoginFilterAttributes':
213
+                        $readMethod = 'getMultiLine';
214
+                        break;
215
+                    case 'ldapIgnoreNamingRules':
216
+                        $readMethod = 'getSystemValue';
217
+                        $dbKey = $key;
218
+                        break;
219
+                    case 'ldapAgentPassword':
220
+                        $readMethod = 'getPwd';
221
+                        break;
222
+                    case 'ldapUserDisplayName2':
223
+                    case 'ldapGroupDisplayName':
224
+                        $readMethod = 'getLcValue';
225
+                        break;
226
+                    case 'ldapUserDisplayName':
227
+                    default:
228
+                        // user display name does not lower case because
229
+                        // we rely on an upper case N as indicator whether to
230
+                        // auto-detect it or not. FIXME
231
+                        $readMethod = 'getValue';
232
+                        break;
233
+                }
234
+                $this->config[$key] = $this->$readMethod($dbKey);
235
+            }
236
+            $this->configRead = true;
237
+        }
238
+    }
239 239
 
240
-	/**
241
-	 * saves the current Configuration in the database
242
-	 */
243
-	public function saveConfiguration() {
244
-		$cta = array_flip($this->getConfigTranslationArray());
245
-		foreach($this->config as $key => $value) {
246
-			switch ($key) {
247
-				case 'ldapAgentPassword':
248
-					$value = base64_encode($value);
249
-					break;
250
-				case 'ldapBase':
251
-				case 'ldapBaseUsers':
252
-				case 'ldapBaseGroups':
253
-				case 'ldapAttributesForUserSearch':
254
-				case 'ldapAttributesForGroupSearch':
255
-				case 'ldapUserFilterObjectclass':
256
-				case 'ldapUserFilterGroups':
257
-				case 'ldapGroupFilterObjectclass':
258
-				case 'ldapGroupFilterGroups':
259
-				case 'ldapLoginFilterAttributes':
260
-					if(is_array($value)) {
261
-						$value = implode("\n", $value);
262
-					}
263
-					break;
264
-				//following options are not stored but detected, skip them
265
-				case 'ldapIgnoreNamingRules':
266
-				case 'hasPagedResultSupport':
267
-				case 'ldapUuidUserAttribute':
268
-				case 'ldapUuidGroupAttribute':
269
-					continue 2;
270
-			}
271
-			if(is_null($value)) {
272
-				$value = '';
273
-			}
274
-			$this->saveValue($cta[$key], $value);
275
-		}
276
-		$this->saveValue('_lastChange', time());
277
-	}
240
+    /**
241
+     * saves the current Configuration in the database
242
+     */
243
+    public function saveConfiguration() {
244
+        $cta = array_flip($this->getConfigTranslationArray());
245
+        foreach($this->config as $key => $value) {
246
+            switch ($key) {
247
+                case 'ldapAgentPassword':
248
+                    $value = base64_encode($value);
249
+                    break;
250
+                case 'ldapBase':
251
+                case 'ldapBaseUsers':
252
+                case 'ldapBaseGroups':
253
+                case 'ldapAttributesForUserSearch':
254
+                case 'ldapAttributesForGroupSearch':
255
+                case 'ldapUserFilterObjectclass':
256
+                case 'ldapUserFilterGroups':
257
+                case 'ldapGroupFilterObjectclass':
258
+                case 'ldapGroupFilterGroups':
259
+                case 'ldapLoginFilterAttributes':
260
+                    if(is_array($value)) {
261
+                        $value = implode("\n", $value);
262
+                    }
263
+                    break;
264
+                //following options are not stored but detected, skip them
265
+                case 'ldapIgnoreNamingRules':
266
+                case 'hasPagedResultSupport':
267
+                case 'ldapUuidUserAttribute':
268
+                case 'ldapUuidGroupAttribute':
269
+                    continue 2;
270
+            }
271
+            if(is_null($value)) {
272
+                $value = '';
273
+            }
274
+            $this->saveValue($cta[$key], $value);
275
+        }
276
+        $this->saveValue('_lastChange', time());
277
+    }
278 278
 
279
-	/**
280
-	 * @param string $varName
281
-	 * @return array|string
282
-	 */
283
-	protected function getMultiLine($varName) {
284
-		$value = $this->getValue($varName);
285
-		if(empty($value)) {
286
-			$value = '';
287
-		} else {
288
-			$value = preg_split('/\r\n|\r|\n/', $value);
289
-		}
279
+    /**
280
+     * @param string $varName
281
+     * @return array|string
282
+     */
283
+    protected function getMultiLine($varName) {
284
+        $value = $this->getValue($varName);
285
+        if(empty($value)) {
286
+            $value = '';
287
+        } else {
288
+            $value = preg_split('/\r\n|\r|\n/', $value);
289
+        }
290 290
 
291
-		return $value;
292
-	}
291
+        return $value;
292
+    }
293 293
 
294
-	/**
295
-	 * Sets multi-line values as arrays
296
-	 * 
297
-	 * @param string $varName name of config-key
298
-	 * @param array|string $value to set
299
-	 */
300
-	protected function setMultiLine($varName, $value) {
301
-		if(empty($value)) {
302
-			$value = '';
303
-		} else if (!is_array($value)) {
304
-			$value = preg_split('/\r\n|\r|\n|;/', $value);
305
-			if($value === false) {
306
-				$value = '';
307
-			}
308
-		}
294
+    /**
295
+     * Sets multi-line values as arrays
296
+     * 
297
+     * @param string $varName name of config-key
298
+     * @param array|string $value to set
299
+     */
300
+    protected function setMultiLine($varName, $value) {
301
+        if(empty($value)) {
302
+            $value = '';
303
+        } else if (!is_array($value)) {
304
+            $value = preg_split('/\r\n|\r|\n|;/', $value);
305
+            if($value === false) {
306
+                $value = '';
307
+            }
308
+        }
309 309
 
310
-		if(!is_array($value)) {
311
-			$finalValue = trim($value);
312
-		} else {
313
-			$finalValue = [];
314
-			foreach($value as $key => $val) {
315
-				if(is_string($val)) {
316
-					$val = trim($val);
317
-					if ($val !== '') {
318
-						//accidental line breaks are not wanted and can cause
319
-						// odd behaviour. Thus, away with them.
320
-						$finalValue[] = $val;
321
-					}
322
-				} else {
323
-					$finalValue[] = $val;
324
-				}
325
-			}
326
-		}
310
+        if(!is_array($value)) {
311
+            $finalValue = trim($value);
312
+        } else {
313
+            $finalValue = [];
314
+            foreach($value as $key => $val) {
315
+                if(is_string($val)) {
316
+                    $val = trim($val);
317
+                    if ($val !== '') {
318
+                        //accidental line breaks are not wanted and can cause
319
+                        // odd behaviour. Thus, away with them.
320
+                        $finalValue[] = $val;
321
+                    }
322
+                } else {
323
+                    $finalValue[] = $val;
324
+                }
325
+            }
326
+        }
327 327
 
328
-		$this->setRawValue($varName, $finalValue);
329
-	}
328
+        $this->setRawValue($varName, $finalValue);
329
+    }
330 330
 
331
-	/**
332
-	 * @param string $varName
333
-	 * @return string
334
-	 */
335
-	protected function getPwd($varName) {
336
-		return base64_decode($this->getValue($varName));
337
-	}
331
+    /**
332
+     * @param string $varName
333
+     * @return string
334
+     */
335
+    protected function getPwd($varName) {
336
+        return base64_decode($this->getValue($varName));
337
+    }
338 338
 
339
-	/**
340
-	 * @param string $varName
341
-	 * @return string
342
-	 */
343
-	protected function getLcValue($varName) {
344
-		return mb_strtolower($this->getValue($varName), 'UTF-8');
345
-	}
339
+    /**
340
+     * @param string $varName
341
+     * @return string
342
+     */
343
+    protected function getLcValue($varName) {
344
+        return mb_strtolower($this->getValue($varName), 'UTF-8');
345
+    }
346 346
 
347
-	/**
348
-	 * @param string $varName
349
-	 * @return string
350
-	 */
351
-	protected function getSystemValue($varName) {
352
-		//FIXME: if another system value is added, softcode the default value
353
-		return \OC::$server->getConfig()->getSystemValue($varName, false);
354
-	}
347
+    /**
348
+     * @param string $varName
349
+     * @return string
350
+     */
351
+    protected function getSystemValue($varName) {
352
+        //FIXME: if another system value is added, softcode the default value
353
+        return \OC::$server->getConfig()->getSystemValue($varName, false);
354
+    }
355 355
 
356
-	/**
357
-	 * @param string $varName
358
-	 * @return string
359
-	 */
360
-	protected function getValue($varName) {
361
-		static $defaults;
362
-		if(is_null($defaults)) {
363
-			$defaults = $this->getDefaults();
364
-		}
365
-		return \OCP\Config::getAppValue('user_ldap',
366
-										$this->configPrefix.$varName,
367
-										$defaults[$varName]);
368
-	}
356
+    /**
357
+     * @param string $varName
358
+     * @return string
359
+     */
360
+    protected function getValue($varName) {
361
+        static $defaults;
362
+        if(is_null($defaults)) {
363
+            $defaults = $this->getDefaults();
364
+        }
365
+        return \OCP\Config::getAppValue('user_ldap',
366
+                                        $this->configPrefix.$varName,
367
+                                        $defaults[$varName]);
368
+    }
369 369
 
370
-	/**
371
-	 * Sets a scalar value.
372
-	 * 
373
-	 * @param string $varName name of config key
374
-	 * @param mixed $value to set
375
-	 */
376
-	protected function setValue($varName, $value) {
377
-		if(is_string($value)) {
378
-			$value = trim($value);
379
-		}
380
-		$this->config[$varName] = $value;
381
-	}
370
+    /**
371
+     * Sets a scalar value.
372
+     * 
373
+     * @param string $varName name of config key
374
+     * @param mixed $value to set
375
+     */
376
+    protected function setValue($varName, $value) {
377
+        if(is_string($value)) {
378
+            $value = trim($value);
379
+        }
380
+        $this->config[$varName] = $value;
381
+    }
382 382
 
383
-	/**
384
-	 * Sets a scalar value without trimming.
385
-	 *
386
-	 * @param string $varName name of config key
387
-	 * @param mixed $value to set
388
-	 */
389
-	protected function setRawValue($varName, $value) {
390
-		$this->config[$varName] = $value;
391
-	}
383
+    /**
384
+     * Sets a scalar value without trimming.
385
+     *
386
+     * @param string $varName name of config key
387
+     * @param mixed $value to set
388
+     */
389
+    protected function setRawValue($varName, $value) {
390
+        $this->config[$varName] = $value;
391
+    }
392 392
 
393
-	/**
394
-	 * @param string $varName
395
-	 * @param string $value
396
-	 * @return bool
397
-	 */
398
-	protected function saveValue($varName, $value) {
399
-		\OC::$server->getConfig()->setAppValue(
400
-			'user_ldap',
401
-			$this->configPrefix.$varName,
402
-			$value
403
-		);
404
-		return true;
405
-	}
393
+    /**
394
+     * @param string $varName
395
+     * @param string $value
396
+     * @return bool
397
+     */
398
+    protected function saveValue($varName, $value) {
399
+        \OC::$server->getConfig()->setAppValue(
400
+            'user_ldap',
401
+            $this->configPrefix.$varName,
402
+            $value
403
+        );
404
+        return true;
405
+    }
406 406
 
407
-	/**
408
-	 * @return array an associative array with the default values. Keys are correspond
409
-	 * to config-value entries in the database table
410
-	 */
411
-	public function getDefaults() {
412
-		return array(
413
-			'ldap_host'                         => '',
414
-			'ldap_port'                         => '',
415
-			'ldap_backup_host'                  => '',
416
-			'ldap_backup_port'                  => '',
417
-			'ldap_override_main_server'         => '',
418
-			'ldap_dn'                           => '',
419
-			'ldap_agent_password'               => '',
420
-			'ldap_base'                         => '',
421
-			'ldap_base_users'                   => '',
422
-			'ldap_base_groups'                  => '',
423
-			'ldap_userlist_filter'              => '',
424
-			'ldap_user_filter_mode'             => 0,
425
-			'ldap_userfilter_objectclass'       => '',
426
-			'ldap_userfilter_groups'            => '',
427
-			'ldap_login_filter'                 => '',
428
-			'ldap_login_filter_mode'            => 0,
429
-			'ldap_loginfilter_email'            => 0,
430
-			'ldap_loginfilter_username'         => 1,
431
-			'ldap_loginfilter_attributes'       => '',
432
-			'ldap_group_filter'                 => '',
433
-			'ldap_group_filter_mode'            => 0,
434
-			'ldap_groupfilter_objectclass'      => '',
435
-			'ldap_groupfilter_groups'           => '',
436
-			'ldap_gid_number'                   => 'gidNumber',
437
-			'ldap_display_name'                 => 'displayName',
438
-			'ldap_user_display_name_2'			=> '',
439
-			'ldap_group_display_name'           => 'cn',
440
-			'ldap_tls'                          => 0,
441
-			'ldap_quota_def'                    => '',
442
-			'ldap_quota_attr'                   => '',
443
-			'ldap_email_attr'                   => '',
444
-			'ldap_group_member_assoc_attribute' => 'uniqueMember',
445
-			'ldap_cache_ttl'                    => 600,
446
-			'ldap_uuid_user_attribute'          => 'auto',
447
-			'ldap_uuid_group_attribute'         => 'auto',
448
-			'home_folder_naming_rule'           => '',
449
-			'ldap_turn_off_cert_check'          => 0,
450
-			'ldap_configuration_active'         => 0,
451
-			'ldap_attributes_for_user_search'   => '',
452
-			'ldap_attributes_for_group_search'  => '',
453
-			'ldap_expert_username_attr'         => '',
454
-			'ldap_expert_uuid_user_attr'        => '',
455
-			'ldap_expert_uuid_group_attr'       => '',
456
-			'has_memberof_filter_support'       => 0,
457
-			'use_memberof_to_detect_membership' => 1,
458
-			'last_jpegPhoto_lookup'             => 0,
459
-			'ldap_nested_groups'                => 0,
460
-			'ldap_paging_size'                  => 500,
461
-			'ldap_turn_on_pwd_change'           => 0,
462
-			'ldap_experienced_admin'            => 0,
463
-			'ldap_dynamic_group_member_url'     => '',
464
-			'ldap_default_ppolicy_dn'           => '',
465
-		);
466
-	}
407
+    /**
408
+     * @return array an associative array with the default values. Keys are correspond
409
+     * to config-value entries in the database table
410
+     */
411
+    public function getDefaults() {
412
+        return array(
413
+            'ldap_host'                         => '',
414
+            'ldap_port'                         => '',
415
+            'ldap_backup_host'                  => '',
416
+            'ldap_backup_port'                  => '',
417
+            'ldap_override_main_server'         => '',
418
+            'ldap_dn'                           => '',
419
+            'ldap_agent_password'               => '',
420
+            'ldap_base'                         => '',
421
+            'ldap_base_users'                   => '',
422
+            'ldap_base_groups'                  => '',
423
+            'ldap_userlist_filter'              => '',
424
+            'ldap_user_filter_mode'             => 0,
425
+            'ldap_userfilter_objectclass'       => '',
426
+            'ldap_userfilter_groups'            => '',
427
+            'ldap_login_filter'                 => '',
428
+            'ldap_login_filter_mode'            => 0,
429
+            'ldap_loginfilter_email'            => 0,
430
+            'ldap_loginfilter_username'         => 1,
431
+            'ldap_loginfilter_attributes'       => '',
432
+            'ldap_group_filter'                 => '',
433
+            'ldap_group_filter_mode'            => 0,
434
+            'ldap_groupfilter_objectclass'      => '',
435
+            'ldap_groupfilter_groups'           => '',
436
+            'ldap_gid_number'                   => 'gidNumber',
437
+            'ldap_display_name'                 => 'displayName',
438
+            'ldap_user_display_name_2'			=> '',
439
+            'ldap_group_display_name'           => 'cn',
440
+            'ldap_tls'                          => 0,
441
+            'ldap_quota_def'                    => '',
442
+            'ldap_quota_attr'                   => '',
443
+            'ldap_email_attr'                   => '',
444
+            'ldap_group_member_assoc_attribute' => 'uniqueMember',
445
+            'ldap_cache_ttl'                    => 600,
446
+            'ldap_uuid_user_attribute'          => 'auto',
447
+            'ldap_uuid_group_attribute'         => 'auto',
448
+            'home_folder_naming_rule'           => '',
449
+            'ldap_turn_off_cert_check'          => 0,
450
+            'ldap_configuration_active'         => 0,
451
+            'ldap_attributes_for_user_search'   => '',
452
+            'ldap_attributes_for_group_search'  => '',
453
+            'ldap_expert_username_attr'         => '',
454
+            'ldap_expert_uuid_user_attr'        => '',
455
+            'ldap_expert_uuid_group_attr'       => '',
456
+            'has_memberof_filter_support'       => 0,
457
+            'use_memberof_to_detect_membership' => 1,
458
+            'last_jpegPhoto_lookup'             => 0,
459
+            'ldap_nested_groups'                => 0,
460
+            'ldap_paging_size'                  => 500,
461
+            'ldap_turn_on_pwd_change'           => 0,
462
+            'ldap_experienced_admin'            => 0,
463
+            'ldap_dynamic_group_member_url'     => '',
464
+            'ldap_default_ppolicy_dn'           => '',
465
+        );
466
+    }
467 467
 
468
-	/**
469
-	 * @return array that maps internal variable names to database fields
470
-	 */
471
-	public function getConfigTranslationArray() {
472
-		//TODO: merge them into one representation
473
-		static $array = array(
474
-			'ldap_host'                         => 'ldapHost',
475
-			'ldap_port'                         => 'ldapPort',
476
-			'ldap_backup_host'                  => 'ldapBackupHost',
477
-			'ldap_backup_port'                  => 'ldapBackupPort',
478
-			'ldap_override_main_server'         => 'ldapOverrideMainServer',
479
-			'ldap_dn'                           => 'ldapAgentName',
480
-			'ldap_agent_password'               => 'ldapAgentPassword',
481
-			'ldap_base'                         => 'ldapBase',
482
-			'ldap_base_users'                   => 'ldapBaseUsers',
483
-			'ldap_base_groups'                  => 'ldapBaseGroups',
484
-			'ldap_userfilter_objectclass'       => 'ldapUserFilterObjectclass',
485
-			'ldap_userfilter_groups'            => 'ldapUserFilterGroups',
486
-			'ldap_userlist_filter'              => 'ldapUserFilter',
487
-			'ldap_user_filter_mode'             => 'ldapUserFilterMode',
488
-			'ldap_login_filter'                 => 'ldapLoginFilter',
489
-			'ldap_login_filter_mode'            => 'ldapLoginFilterMode',
490
-			'ldap_loginfilter_email'            => 'ldapLoginFilterEmail',
491
-			'ldap_loginfilter_username'         => 'ldapLoginFilterUsername',
492
-			'ldap_loginfilter_attributes'       => 'ldapLoginFilterAttributes',
493
-			'ldap_group_filter'                 => 'ldapGroupFilter',
494
-			'ldap_group_filter_mode'            => 'ldapGroupFilterMode',
495
-			'ldap_groupfilter_objectclass'      => 'ldapGroupFilterObjectclass',
496
-			'ldap_groupfilter_groups'           => 'ldapGroupFilterGroups',
497
-			'ldap_gid_number'                   => 'ldapGidNumber',
498
-			'ldap_display_name'                 => 'ldapUserDisplayName',
499
-			'ldap_user_display_name_2'			=> 'ldapUserDisplayName2',
500
-			'ldap_group_display_name'           => 'ldapGroupDisplayName',
501
-			'ldap_tls'                          => 'ldapTLS',
502
-			'ldap_quota_def'                    => 'ldapQuotaDefault',
503
-			'ldap_quota_attr'                   => 'ldapQuotaAttribute',
504
-			'ldap_email_attr'                   => 'ldapEmailAttribute',
505
-			'ldap_group_member_assoc_attribute' => 'ldapGroupMemberAssocAttr',
506
-			'ldap_cache_ttl'                    => 'ldapCacheTTL',
507
-			'home_folder_naming_rule'           => 'homeFolderNamingRule',
508
-			'ldap_turn_off_cert_check'          => 'turnOffCertCheck',
509
-			'ldap_configuration_active'         => 'ldapConfigurationActive',
510
-			'ldap_attributes_for_user_search'   => 'ldapAttributesForUserSearch',
511
-			'ldap_attributes_for_group_search'  => 'ldapAttributesForGroupSearch',
512
-			'ldap_expert_username_attr'         => 'ldapExpertUsernameAttr',
513
-			'ldap_expert_uuid_user_attr'        => 'ldapExpertUUIDUserAttr',
514
-			'ldap_expert_uuid_group_attr'       => 'ldapExpertUUIDGroupAttr',
515
-			'has_memberof_filter_support'       => 'hasMemberOfFilterSupport',
516
-			'use_memberof_to_detect_membership' => 'useMemberOfToDetectMembership',
517
-			'last_jpegPhoto_lookup'             => 'lastJpegPhotoLookup',
518
-			'ldap_nested_groups'                => 'ldapNestedGroups',
519
-			'ldap_paging_size'                  => 'ldapPagingSize',
520
-			'ldap_turn_on_pwd_change'           => 'turnOnPasswordChange',
521
-			'ldap_experienced_admin'            => 'ldapExperiencedAdmin',
522
-			'ldap_dynamic_group_member_url'     => 'ldapDynamicGroupMemberURL',
523
-			'ldap_default_ppolicy_dn'           => 'ldapDefaultPPolicyDN',
524
-		);
525
-		return $array;
526
-	}
468
+    /**
469
+     * @return array that maps internal variable names to database fields
470
+     */
471
+    public function getConfigTranslationArray() {
472
+        //TODO: merge them into one representation
473
+        static $array = array(
474
+            'ldap_host'                         => 'ldapHost',
475
+            'ldap_port'                         => 'ldapPort',
476
+            'ldap_backup_host'                  => 'ldapBackupHost',
477
+            'ldap_backup_port'                  => 'ldapBackupPort',
478
+            'ldap_override_main_server'         => 'ldapOverrideMainServer',
479
+            'ldap_dn'                           => 'ldapAgentName',
480
+            'ldap_agent_password'               => 'ldapAgentPassword',
481
+            'ldap_base'                         => 'ldapBase',
482
+            'ldap_base_users'                   => 'ldapBaseUsers',
483
+            'ldap_base_groups'                  => 'ldapBaseGroups',
484
+            'ldap_userfilter_objectclass'       => 'ldapUserFilterObjectclass',
485
+            'ldap_userfilter_groups'            => 'ldapUserFilterGroups',
486
+            'ldap_userlist_filter'              => 'ldapUserFilter',
487
+            'ldap_user_filter_mode'             => 'ldapUserFilterMode',
488
+            'ldap_login_filter'                 => 'ldapLoginFilter',
489
+            'ldap_login_filter_mode'            => 'ldapLoginFilterMode',
490
+            'ldap_loginfilter_email'            => 'ldapLoginFilterEmail',
491
+            'ldap_loginfilter_username'         => 'ldapLoginFilterUsername',
492
+            'ldap_loginfilter_attributes'       => 'ldapLoginFilterAttributes',
493
+            'ldap_group_filter'                 => 'ldapGroupFilter',
494
+            'ldap_group_filter_mode'            => 'ldapGroupFilterMode',
495
+            'ldap_groupfilter_objectclass'      => 'ldapGroupFilterObjectclass',
496
+            'ldap_groupfilter_groups'           => 'ldapGroupFilterGroups',
497
+            'ldap_gid_number'                   => 'ldapGidNumber',
498
+            'ldap_display_name'                 => 'ldapUserDisplayName',
499
+            'ldap_user_display_name_2'			=> 'ldapUserDisplayName2',
500
+            'ldap_group_display_name'           => 'ldapGroupDisplayName',
501
+            'ldap_tls'                          => 'ldapTLS',
502
+            'ldap_quota_def'                    => 'ldapQuotaDefault',
503
+            'ldap_quota_attr'                   => 'ldapQuotaAttribute',
504
+            'ldap_email_attr'                   => 'ldapEmailAttribute',
505
+            'ldap_group_member_assoc_attribute' => 'ldapGroupMemberAssocAttr',
506
+            'ldap_cache_ttl'                    => 'ldapCacheTTL',
507
+            'home_folder_naming_rule'           => 'homeFolderNamingRule',
508
+            'ldap_turn_off_cert_check'          => 'turnOffCertCheck',
509
+            'ldap_configuration_active'         => 'ldapConfigurationActive',
510
+            'ldap_attributes_for_user_search'   => 'ldapAttributesForUserSearch',
511
+            'ldap_attributes_for_group_search'  => 'ldapAttributesForGroupSearch',
512
+            'ldap_expert_username_attr'         => 'ldapExpertUsernameAttr',
513
+            'ldap_expert_uuid_user_attr'        => 'ldapExpertUUIDUserAttr',
514
+            'ldap_expert_uuid_group_attr'       => 'ldapExpertUUIDGroupAttr',
515
+            'has_memberof_filter_support'       => 'hasMemberOfFilterSupport',
516
+            'use_memberof_to_detect_membership' => 'useMemberOfToDetectMembership',
517
+            'last_jpegPhoto_lookup'             => 'lastJpegPhotoLookup',
518
+            'ldap_nested_groups'                => 'ldapNestedGroups',
519
+            'ldap_paging_size'                  => 'ldapPagingSize',
520
+            'ldap_turn_on_pwd_change'           => 'turnOnPasswordChange',
521
+            'ldap_experienced_admin'            => 'ldapExperiencedAdmin',
522
+            'ldap_dynamic_group_member_url'     => 'ldapDynamicGroupMemberURL',
523
+            'ldap_default_ppolicy_dn'           => 'ldapDefaultPPolicyDN',
524
+        );
525
+        return $array;
526
+    }
527 527
 
528 528
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Mapping/AbstractMapping.php 1 patch
Indentation   +214 added lines, -214 removed lines patch added patch discarded remove patch
@@ -29,267 +29,267 @@
 block discarded – undo
29 29
 * @package OCA\User_LDAP\Mapping
30 30
 */
31 31
 abstract class AbstractMapping {
32
-	/**
33
-	 * @var \OCP\IDBConnection $dbc
34
-	 */
35
-	protected $dbc;
32
+    /**
33
+     * @var \OCP\IDBConnection $dbc
34
+     */
35
+    protected $dbc;
36 36
 
37
-	/**
38
-	 * returns the DB table name which holds the mappings
39
-	 * @return string
40
-	 */
41
-	abstract protected function getTableName();
37
+    /**
38
+     * returns the DB table name which holds the mappings
39
+     * @return string
40
+     */
41
+    abstract protected function getTableName();
42 42
 
43
-	/**
44
-	 * @param \OCP\IDBConnection $dbc
45
-	 */
46
-	public function __construct(\OCP\IDBConnection $dbc) {
47
-		$this->dbc = $dbc;
48
-	}
43
+    /**
44
+     * @param \OCP\IDBConnection $dbc
45
+     */
46
+    public function __construct(\OCP\IDBConnection $dbc) {
47
+        $this->dbc = $dbc;
48
+    }
49 49
 
50
-	/**
51
-	 * checks whether a provided string represents an existing table col
52
-	 * @param string $col
53
-	 * @return bool
54
-	 */
55
-	public function isColNameValid($col) {
56
-		switch($col) {
57
-			case 'ldap_dn':
58
-			case 'owncloud_name':
59
-			case 'directory_uuid':
60
-				return true;
61
-			default:
62
-				return false;
63
-		}
64
-	}
50
+    /**
51
+     * checks whether a provided string represents an existing table col
52
+     * @param string $col
53
+     * @return bool
54
+     */
55
+    public function isColNameValid($col) {
56
+        switch($col) {
57
+            case 'ldap_dn':
58
+            case 'owncloud_name':
59
+            case 'directory_uuid':
60
+                return true;
61
+            default:
62
+                return false;
63
+        }
64
+    }
65 65
 
66
-	/**
67
-	 * Gets the value of one column based on a provided value of another column
68
-	 * @param string $fetchCol
69
-	 * @param string $compareCol
70
-	 * @param string $search
71
-	 * @throws \Exception
72
-	 * @return string|false
73
-	 */
74
-	protected function getXbyY($fetchCol, $compareCol, $search) {
75
-		if(!$this->isColNameValid($fetchCol)) {
76
-			//this is used internally only, but we don't want to risk
77
-			//having SQL injection at all.
78
-			throw new \Exception('Invalid Column Name');
79
-		}
80
-		$query = $this->dbc->prepare('
66
+    /**
67
+     * Gets the value of one column based on a provided value of another column
68
+     * @param string $fetchCol
69
+     * @param string $compareCol
70
+     * @param string $search
71
+     * @throws \Exception
72
+     * @return string|false
73
+     */
74
+    protected function getXbyY($fetchCol, $compareCol, $search) {
75
+        if(!$this->isColNameValid($fetchCol)) {
76
+            //this is used internally only, but we don't want to risk
77
+            //having SQL injection at all.
78
+            throw new \Exception('Invalid Column Name');
79
+        }
80
+        $query = $this->dbc->prepare('
81 81
 			SELECT `' . $fetchCol . '`
82 82
 			FROM `'. $this->getTableName() .'`
83 83
 			WHERE `' . $compareCol . '` = ?
84 84
 		');
85 85
 
86
-		$res = $query->execute(array($search));
87
-		if($res !== false) {
88
-			return $query->fetchColumn();
89
-		}
86
+        $res = $query->execute(array($search));
87
+        if($res !== false) {
88
+            return $query->fetchColumn();
89
+        }
90 90
 
91
-		return false;
92
-	}
91
+        return false;
92
+    }
93 93
 
94
-	/**
95
-	 * Performs a DELETE or UPDATE query to the database.
96
-	 * @param \Doctrine\DBAL\Driver\Statement $query
97
-	 * @param array $parameters
98
-	 * @return bool true if at least one row was modified, false otherwise
99
-	 */
100
-	protected function modify($query, $parameters) {
101
-		$result = $query->execute($parameters);
102
-		return ($result === true && $query->rowCount() > 0);
103
-	}
94
+    /**
95
+     * Performs a DELETE or UPDATE query to the database.
96
+     * @param \Doctrine\DBAL\Driver\Statement $query
97
+     * @param array $parameters
98
+     * @return bool true if at least one row was modified, false otherwise
99
+     */
100
+    protected function modify($query, $parameters) {
101
+        $result = $query->execute($parameters);
102
+        return ($result === true && $query->rowCount() > 0);
103
+    }
104 104
 
105
-	/**
106
-	 * Gets the LDAP DN based on the provided name.
107
-	 * Replaces Access::ocname2dn
108
-	 * @param string $name
109
-	 * @return string|false
110
-	 */
111
-	public function getDNByName($name) {
112
-		return $this->getXbyY('ldap_dn', 'owncloud_name', $name);
113
-	}
105
+    /**
106
+     * Gets the LDAP DN based on the provided name.
107
+     * Replaces Access::ocname2dn
108
+     * @param string $name
109
+     * @return string|false
110
+     */
111
+    public function getDNByName($name) {
112
+        return $this->getXbyY('ldap_dn', 'owncloud_name', $name);
113
+    }
114 114
 
115
-	/**
116
-	 * Updates the DN based on the given UUID
117
-	 * @param string $fdn
118
-	 * @param string $uuid
119
-	 * @return bool
120
-	 */
121
-	public function setDNbyUUID($fdn, $uuid) {
122
-		$query = $this->dbc->prepare('
115
+    /**
116
+     * Updates the DN based on the given UUID
117
+     * @param string $fdn
118
+     * @param string $uuid
119
+     * @return bool
120
+     */
121
+    public function setDNbyUUID($fdn, $uuid) {
122
+        $query = $this->dbc->prepare('
123 123
 			UPDATE `' . $this->getTableName() . '`
124 124
 			SET `ldap_dn` = ?
125 125
 			WHERE `directory_uuid` = ?
126 126
 		');
127 127
 
128
-		return $this->modify($query, array($fdn, $uuid));
129
-	}
128
+        return $this->modify($query, array($fdn, $uuid));
129
+    }
130 130
 
131
-	/**
132
-	 * Updates the UUID based on the given DN
133
-	 *
134
-	 * required by Migration/UUIDFix
135
-	 *
136
-	 * @param $uuid
137
-	 * @param $fdn
138
-	 * @return bool
139
-	 */
140
-	public function setUUIDbyDN($uuid, $fdn) {
141
-		$query = $this->dbc->prepare('
131
+    /**
132
+     * Updates the UUID based on the given DN
133
+     *
134
+     * required by Migration/UUIDFix
135
+     *
136
+     * @param $uuid
137
+     * @param $fdn
138
+     * @return bool
139
+     */
140
+    public function setUUIDbyDN($uuid, $fdn) {
141
+        $query = $this->dbc->prepare('
142 142
 			UPDATE `' . $this->getTableName() . '`
143 143
 			SET `directory_uuid` = ?
144 144
 			WHERE `ldap_dn` = ?
145 145
 		');
146 146
 
147
-		return $this->modify($query, [$uuid, $fdn]);
148
-	}
147
+        return $this->modify($query, [$uuid, $fdn]);
148
+    }
149 149
 
150
-	/**
151
-	 * Gets the name based on the provided LDAP DN.
152
-	 * @param string $fdn
153
-	 * @return string|false
154
-	 */
155
-	public function getNameByDN($fdn) {
156
-		return $this->getXbyY('owncloud_name', 'ldap_dn', $fdn);
157
-	}
150
+    /**
151
+     * Gets the name based on the provided LDAP DN.
152
+     * @param string $fdn
153
+     * @return string|false
154
+     */
155
+    public function getNameByDN($fdn) {
156
+        return $this->getXbyY('owncloud_name', 'ldap_dn', $fdn);
157
+    }
158 158
 
159
-	/**
160
-	 * Searches mapped names by the giving string in the name column
161
-	 * @param string $search
162
-	 * @param string $prefixMatch
163
-	 * @param string $postfixMatch
164
-	 * @return string[]
165
-	 */
166
-	public function getNamesBySearch($search, $prefixMatch = "", $postfixMatch = "") {
167
-		$query = $this->dbc->prepare('
159
+    /**
160
+     * Searches mapped names by the giving string in the name column
161
+     * @param string $search
162
+     * @param string $prefixMatch
163
+     * @param string $postfixMatch
164
+     * @return string[]
165
+     */
166
+    public function getNamesBySearch($search, $prefixMatch = "", $postfixMatch = "") {
167
+        $query = $this->dbc->prepare('
168 168
 			SELECT `owncloud_name`
169 169
 			FROM `'. $this->getTableName() .'`
170 170
 			WHERE `owncloud_name` LIKE ?
171 171
 		');
172 172
 
173
-		$res = $query->execute(array($prefixMatch.$this->dbc->escapeLikeParameter($search).$postfixMatch));
174
-		$names = array();
175
-		if($res !== false) {
176
-			while($row = $query->fetch()) {
177
-				$names[] = $row['owncloud_name'];
178
-			}
179
-		}
180
-		return $names;
181
-	}
173
+        $res = $query->execute(array($prefixMatch.$this->dbc->escapeLikeParameter($search).$postfixMatch));
174
+        $names = array();
175
+        if($res !== false) {
176
+            while($row = $query->fetch()) {
177
+                $names[] = $row['owncloud_name'];
178
+            }
179
+        }
180
+        return $names;
181
+    }
182 182
 
183
-	/**
184
-	 * Gets the name based on the provided LDAP UUID.
185
-	 * @param string $uuid
186
-	 * @return string|false
187
-	 */
188
-	public function getNameByUUID($uuid) {
189
-		return $this->getXbyY('owncloud_name', 'directory_uuid', $uuid);
190
-	}
183
+    /**
184
+     * Gets the name based on the provided LDAP UUID.
185
+     * @param string $uuid
186
+     * @return string|false
187
+     */
188
+    public function getNameByUUID($uuid) {
189
+        return $this->getXbyY('owncloud_name', 'directory_uuid', $uuid);
190
+    }
191 191
 
192
-	/**
193
-	 * Gets the UUID based on the provided LDAP DN
194
-	 * @param string $dn
195
-	 * @return false|string
196
-	 * @throws \Exception
197
-	 */
198
-	public function getUUIDByDN($dn) {
199
-		return $this->getXbyY('directory_uuid', 'ldap_dn', $dn);
200
-	}
192
+    /**
193
+     * Gets the UUID based on the provided LDAP DN
194
+     * @param string $dn
195
+     * @return false|string
196
+     * @throws \Exception
197
+     */
198
+    public function getUUIDByDN($dn) {
199
+        return $this->getXbyY('directory_uuid', 'ldap_dn', $dn);
200
+    }
201 201
 
202
-	/**
203
-	 * gets a piece of the mapping list
204
-	 * @param int $offset
205
-	 * @param int $limit
206
-	 * @return array
207
-	 */
208
-	public function getList($offset = null, $limit = null) {
209
-		$query = $this->dbc->prepare('
202
+    /**
203
+     * gets a piece of the mapping list
204
+     * @param int $offset
205
+     * @param int $limit
206
+     * @return array
207
+     */
208
+    public function getList($offset = null, $limit = null) {
209
+        $query = $this->dbc->prepare('
210 210
 			SELECT
211 211
 				`ldap_dn` AS `dn`,
212 212
 				`owncloud_name` AS `name`,
213 213
 				`directory_uuid` AS `uuid`
214 214
 			FROM `' . $this->getTableName() . '`',
215
-			$limit,
216
-			$offset
217
-		);
215
+            $limit,
216
+            $offset
217
+        );
218 218
 
219
-		$query->execute();
220
-		return $query->fetchAll();
221
-	}
219
+        $query->execute();
220
+        return $query->fetchAll();
221
+    }
222 222
 
223
-	/**
224
-	 * attempts to map the given entry
225
-	 * @param string $fdn fully distinguished name (from LDAP)
226
-	 * @param string $name
227
-	 * @param string $uuid a unique identifier as used in LDAP
228
-	 * @return bool
229
-	 */
230
-	public function map($fdn, $name, $uuid) {
231
-		if(mb_strlen($fdn) > 255) {
232
-			\OC::$server->getLogger()->error(
233
-				'Cannot map, because the DN exceeds 255 characters: {dn}',
234
-				[
235
-					'app' => 'user_ldap',
236
-					'dn' => $fdn,
237
-				]
238
-			);
239
-			return false;
240
-		}
223
+    /**
224
+     * attempts to map the given entry
225
+     * @param string $fdn fully distinguished name (from LDAP)
226
+     * @param string $name
227
+     * @param string $uuid a unique identifier as used in LDAP
228
+     * @return bool
229
+     */
230
+    public function map($fdn, $name, $uuid) {
231
+        if(mb_strlen($fdn) > 255) {
232
+            \OC::$server->getLogger()->error(
233
+                'Cannot map, because the DN exceeds 255 characters: {dn}',
234
+                [
235
+                    'app' => 'user_ldap',
236
+                    'dn' => $fdn,
237
+                ]
238
+            );
239
+            return false;
240
+        }
241 241
 
242
-		$row = array(
243
-			'ldap_dn'        => $fdn,
244
-			'owncloud_name'  => $name,
245
-			'directory_uuid' => $uuid
246
-		);
242
+        $row = array(
243
+            'ldap_dn'        => $fdn,
244
+            'owncloud_name'  => $name,
245
+            'directory_uuid' => $uuid
246
+        );
247 247
 
248
-		try {
249
-			$result = $this->dbc->insertIfNotExist($this->getTableName(), $row);
250
-			// insertIfNotExist returns values as int
251
-			return (bool)$result;
252
-		} catch (\Exception $e) {
253
-			return false;
254
-		}
255
-	}
248
+        try {
249
+            $result = $this->dbc->insertIfNotExist($this->getTableName(), $row);
250
+            // insertIfNotExist returns values as int
251
+            return (bool)$result;
252
+        } catch (\Exception $e) {
253
+            return false;
254
+        }
255
+    }
256 256
 
257
-	/**
258
-	 * removes a mapping based on the owncloud_name of the entry
259
-	 * @param string $name
260
-	 * @return bool
261
-	 */
262
-	public function unmap($name) {
263
-		$query = $this->dbc->prepare('
257
+    /**
258
+     * removes a mapping based on the owncloud_name of the entry
259
+     * @param string $name
260
+     * @return bool
261
+     */
262
+    public function unmap($name) {
263
+        $query = $this->dbc->prepare('
264 264
 			DELETE FROM `'. $this->getTableName() .'`
265 265
 			WHERE `owncloud_name` = ?');
266 266
 
267
-		return $this->modify($query, array($name));
268
-	}
267
+        return $this->modify($query, array($name));
268
+    }
269 269
 
270
-	/**
271
-	 * Truncate's the mapping table
272
-	 * @return bool
273
-	 */
274
-	public function clear() {
275
-		$sql = $this->dbc
276
-			->getDatabasePlatform()
277
-			->getTruncateTableSQL('`' . $this->getTableName() . '`');
278
-		return $this->dbc->prepare($sql)->execute();
279
-	}
270
+    /**
271
+     * Truncate's the mapping table
272
+     * @return bool
273
+     */
274
+    public function clear() {
275
+        $sql = $this->dbc
276
+            ->getDatabasePlatform()
277
+            ->getTruncateTableSQL('`' . $this->getTableName() . '`');
278
+        return $this->dbc->prepare($sql)->execute();
279
+    }
280 280
 
281
-	/**
282
-	 * returns the number of entries in the mappings table
283
-	 *
284
-	 * @return int
285
-	 */
286
-	public function count() {
287
-		$qb = $this->dbc->getQueryBuilder();
288
-		$query = $qb->select($qb->createFunction('COUNT(`ldap_dn`)'))
289
-			->from($this->getTableName());
290
-		$res = $query->execute();
291
-		$count = $res->fetchColumn();
292
-		$res->closeCursor();
293
-		return (int)$count;
294
-	}
281
+    /**
282
+     * returns the number of entries in the mappings table
283
+     *
284
+     * @return int
285
+     */
286
+    public function count() {
287
+        $qb = $this->dbc->getQueryBuilder();
288
+        $query = $qb->select($qb->createFunction('COUNT(`ldap_dn`)'))
289
+            ->from($this->getTableName());
290
+        $res = $query->execute();
291
+        $count = $res->fetchColumn();
292
+        $res->closeCursor();
293
+        return (int)$count;
294
+    }
295 295
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Connection.php 1 patch
Indentation   +577 added lines, -577 removed lines patch added patch discarded remove patch
@@ -54,582 +54,582 @@
 block discarded – undo
54 54
  * @property string ldapExpertUUIDGroupAttr
55 55
  */
56 56
 class Connection extends LDAPUtility {
57
-	private $ldapConnectionRes = null;
58
-	private $configPrefix;
59
-	private $configID;
60
-	private $configured = false;
61
-	private $hasPagedResultSupport = true;
62
-	//whether connection should be kept on __destruct
63
-	private $dontDestruct = false;
64
-
65
-	/**
66
-	 * @var bool runtime flag that indicates whether supported primary groups are available
67
-	 */
68
-	public $hasPrimaryGroups = true;
69
-
70
-	/**
71
-	 * @var bool runtime flag that indicates whether supported POSIX gidNumber are available
72
-	 */
73
-	public $hasGidNumber = true;
74
-
75
-	//cache handler
76
-	protected $cache;
77
-
78
-	/** @var Configuration settings handler **/
79
-	protected $configuration;
80
-
81
-	protected $doNotValidate = false;
82
-
83
-	protected $ignoreValidation = false;
84
-
85
-	/**
86
-	 * Constructor
87
-	 * @param ILDAPWrapper $ldap
88
-	 * @param string $configPrefix a string with the prefix for the configkey column (appconfig table)
89
-	 * @param string|null $configID a string with the value for the appid column (appconfig table) or null for on-the-fly connections
90
-	 */
91
-	public function __construct(ILDAPWrapper $ldap, $configPrefix = '', $configID = 'user_ldap') {
92
-		parent::__construct($ldap);
93
-		$this->configPrefix = $configPrefix;
94
-		$this->configID = $configID;
95
-		$this->configuration = new Configuration($configPrefix,
96
-												 !is_null($configID));
97
-		$memcache = \OC::$server->getMemCacheFactory();
98
-		if($memcache->isAvailable()) {
99
-			$this->cache = $memcache->create();
100
-		}
101
-		$helper = new Helper(\OC::$server->getConfig());
102
-		$this->doNotValidate = !in_array($this->configPrefix,
103
-			$helper->getServerConfigurationPrefixes());
104
-		$this->hasPagedResultSupport =
105
-			intval($this->configuration->ldapPagingSize) !== 0
106
-			|| $this->ldap->hasPagedResultSupport();
107
-	}
108
-
109
-	public function __destruct() {
110
-		if(!$this->dontDestruct && $this->ldap->isResource($this->ldapConnectionRes)) {
111
-			@$this->ldap->unbind($this->ldapConnectionRes);
112
-		};
113
-	}
114
-
115
-	/**
116
-	 * defines behaviour when the instance is cloned
117
-	 */
118
-	public function __clone() {
119
-		$this->configuration = new Configuration($this->configPrefix,
120
-												 !is_null($this->configID));
121
-		$this->ldapConnectionRes = null;
122
-		$this->dontDestruct = true;
123
-	}
124
-
125
-	/**
126
-	 * @param string $name
127
-	 * @return bool|mixed
128
-	 */
129
-	public function __get($name) {
130
-		if(!$this->configured) {
131
-			$this->readConfiguration();
132
-		}
133
-
134
-		if($name === 'hasPagedResultSupport') {
135
-			return $this->hasPagedResultSupport;
136
-		}
137
-
138
-		return $this->configuration->$name;
139
-	}
140
-
141
-	/**
142
-	 * @param string $name
143
-	 * @param mixed $value
144
-	 */
145
-	public function __set($name, $value) {
146
-		$this->doNotValidate = false;
147
-		$before = $this->configuration->$name;
148
-		$this->configuration->$name = $value;
149
-		$after = $this->configuration->$name;
150
-		if($before !== $after) {
151
-			if ($this->configID !== '') {
152
-				$this->configuration->saveConfiguration();
153
-			}
154
-			$this->validateConfiguration();
155
-		}
156
-	}
157
-
158
-	/**
159
-	 * sets whether the result of the configuration validation shall
160
-	 * be ignored when establishing the connection. Used by the Wizard
161
-	 * in early configuration state.
162
-	 * @param bool $state
163
-	 */
164
-	public function setIgnoreValidation($state) {
165
-		$this->ignoreValidation = (bool)$state;
166
-	}
167
-
168
-	/**
169
-	 * initializes the LDAP backend
170
-	 * @param bool $force read the config settings no matter what
171
-	 */
172
-	public function init($force = false) {
173
-		$this->readConfiguration($force);
174
-		$this->establishConnection();
175
-	}
176
-
177
-	/**
178
-	 * Returns the LDAP handler
179
-	 */
180
-	public function getConnectionResource() {
181
-		if(!$this->ldapConnectionRes) {
182
-			$this->init();
183
-		} else if(!$this->ldap->isResource($this->ldapConnectionRes)) {
184
-			$this->ldapConnectionRes = null;
185
-			$this->establishConnection();
186
-		}
187
-		if(is_null($this->ldapConnectionRes)) {
188
-			\OCP\Util::writeLog('user_ldap', 'No LDAP Connection to server ' . $this->configuration->ldapHost, \OCP\Util::ERROR);
189
-			throw new ServerNotAvailableException('Connection to LDAP server could not be established');
190
-		}
191
-		return $this->ldapConnectionRes;
192
-	}
193
-
194
-	/**
195
-	 * resets the connection resource
196
-	 */
197
-	public function resetConnectionResource() {
198
-		if(!is_null($this->ldapConnectionRes)) {
199
-			@$this->ldap->unbind($this->ldapConnectionRes);
200
-			$this->ldapConnectionRes = null;
201
-		}
202
-	}
203
-
204
-	/**
205
-	 * @param string|null $key
206
-	 * @return string
207
-	 */
208
-	private function getCacheKey($key) {
209
-		$prefix = 'LDAP-'.$this->configID.'-'.$this->configPrefix.'-';
210
-		if(is_null($key)) {
211
-			return $prefix;
212
-		}
213
-		return $prefix.md5($key);
214
-	}
215
-
216
-	/**
217
-	 * @param string $key
218
-	 * @return mixed|null
219
-	 */
220
-	public function getFromCache($key) {
221
-		if(!$this->configured) {
222
-			$this->readConfiguration();
223
-		}
224
-		if(is_null($this->cache) || !$this->configuration->ldapCacheTTL) {
225
-			return null;
226
-		}
227
-		$key = $this->getCacheKey($key);
228
-
229
-		return json_decode(base64_decode($this->cache->get($key)), true);
230
-	}
231
-
232
-	/**
233
-	 * @param string $key
234
-	 * @param mixed $value
235
-	 *
236
-	 * @return string
237
-	 */
238
-	public function writeToCache($key, $value) {
239
-		if(!$this->configured) {
240
-			$this->readConfiguration();
241
-		}
242
-		if(is_null($this->cache)
243
-			|| !$this->configuration->ldapCacheTTL
244
-			|| !$this->configuration->ldapConfigurationActive) {
245
-			return null;
246
-		}
247
-		$key   = $this->getCacheKey($key);
248
-		$value = base64_encode(json_encode($value));
249
-		$this->cache->set($key, $value, $this->configuration->ldapCacheTTL);
250
-	}
251
-
252
-	public function clearCache() {
253
-		if(!is_null($this->cache)) {
254
-			$this->cache->clear($this->getCacheKey(null));
255
-		}
256
-	}
257
-
258
-	/**
259
-	 * Caches the general LDAP configuration.
260
-	 * @param bool $force optional. true, if the re-read should be forced. defaults
261
-	 * to false.
262
-	 * @return null
263
-	 */
264
-	private function readConfiguration($force = false) {
265
-		if((!$this->configured || $force) && !is_null($this->configID)) {
266
-			$this->configuration->readConfiguration();
267
-			$this->configured = $this->validateConfiguration();
268
-		}
269
-	}
270
-
271
-	/**
272
-	 * set LDAP configuration with values delivered by an array, not read from configuration
273
-	 * @param array $config array that holds the config parameters in an associated array
274
-	 * @param array &$setParameters optional; array where the set fields will be given to
275
-	 * @return boolean true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters
276
-	 */
277
-	public function setConfiguration($config, &$setParameters = null) {
278
-		if(is_null($setParameters)) {
279
-			$setParameters = array();
280
-		}
281
-		$this->doNotValidate = false;
282
-		$this->configuration->setConfiguration($config, $setParameters);
283
-		if(count($setParameters) > 0) {
284
-			$this->configured = $this->validateConfiguration();
285
-		}
286
-
287
-
288
-		return $this->configured;
289
-	}
290
-
291
-	/**
292
-	 * saves the current Configuration in the database and empties the
293
-	 * cache
294
-	 * @return null
295
-	 */
296
-	public function saveConfiguration() {
297
-		$this->configuration->saveConfiguration();
298
-		$this->clearCache();
299
-	}
300
-
301
-	/**
302
-	 * get the current LDAP configuration
303
-	 * @return array
304
-	 */
305
-	public function getConfiguration() {
306
-		$this->readConfiguration();
307
-		$config = $this->configuration->getConfiguration();
308
-		$cta = $this->configuration->getConfigTranslationArray();
309
-		$result = array();
310
-		foreach($cta as $dbkey => $configkey) {
311
-			switch($configkey) {
312
-				case 'homeFolderNamingRule':
313
-					if(strpos($config[$configkey], 'attr:') === 0) {
314
-						$result[$dbkey] = substr($config[$configkey], 5);
315
-					} else {
316
-						$result[$dbkey] = '';
317
-					}
318
-					break;
319
-				case 'ldapBase':
320
-				case 'ldapBaseUsers':
321
-				case 'ldapBaseGroups':
322
-				case 'ldapAttributesForUserSearch':
323
-				case 'ldapAttributesForGroupSearch':
324
-					if(is_array($config[$configkey])) {
325
-						$result[$dbkey] = implode("\n", $config[$configkey]);
326
-						break;
327
-					} //else follows default
328
-				default:
329
-					$result[$dbkey] = $config[$configkey];
330
-			}
331
-		}
332
-		return $result;
333
-	}
334
-
335
-	private function doSoftValidation() {
336
-		//if User or Group Base are not set, take over Base DN setting
337
-		foreach(array('ldapBaseUsers', 'ldapBaseGroups') as $keyBase) {
338
-			$val = $this->configuration->$keyBase;
339
-			if(empty($val)) {
340
-				$this->configuration->$keyBase = $this->configuration->ldapBase;
341
-			}
342
-		}
343
-
344
-		foreach(array('ldapExpertUUIDUserAttr'  => 'ldapUuidUserAttribute',
345
-					  'ldapExpertUUIDGroupAttr' => 'ldapUuidGroupAttribute')
346
-				as $expertSetting => $effectiveSetting) {
347
-			$uuidOverride = $this->configuration->$expertSetting;
348
-			if(!empty($uuidOverride)) {
349
-				$this->configuration->$effectiveSetting = $uuidOverride;
350
-			} else {
351
-				$uuidAttributes = Access::UUID_ATTRIBUTES;
352
-				array_unshift($uuidAttributes, 'auto');
353
-				if(!in_array($this->configuration->$effectiveSetting,
354
-							$uuidAttributes)
355
-					&& (!is_null($this->configID))) {
356
-					$this->configuration->$effectiveSetting = 'auto';
357
-					$this->configuration->saveConfiguration();
358
-					\OCP\Util::writeLog('user_ldap',
359
-										'Illegal value for the '.
360
-										$effectiveSetting.', '.'reset to '.
361
-										'autodetect.', \OCP\Util::INFO);
362
-				}
363
-
364
-			}
365
-		}
366
-
367
-		$backupPort = intval($this->configuration->ldapBackupPort);
368
-		if ($backupPort <= 0) {
369
-			$this->configuration->backupPort = $this->configuration->ldapPort;
370
-		}
371
-
372
-		//make sure empty search attributes are saved as simple, empty array
373
-		$saKeys = array('ldapAttributesForUserSearch',
374
-						'ldapAttributesForGroupSearch');
375
-		foreach($saKeys as $key) {
376
-			$val = $this->configuration->$key;
377
-			if(is_array($val) && count($val) === 1 && empty($val[0])) {
378
-				$this->configuration->$key = array();
379
-			}
380
-		}
381
-
382
-		if((stripos($this->configuration->ldapHost, 'ldaps://') === 0)
383
-			&& $this->configuration->ldapTLS) {
384
-			$this->configuration->ldapTLS = false;
385
-			\OCP\Util::writeLog('user_ldap',
386
-								'LDAPS (already using secure connection) and '.
387
-								'TLS do not work together. Switched off TLS.',
388
-								\OCP\Util::INFO);
389
-		}
390
-	}
391
-
392
-	/**
393
-	 * @return bool
394
-	 */
395
-	private function doCriticalValidation() {
396
-		$configurationOK = true;
397
-		$errorStr = 'Configuration Error (prefix '.
398
-					strval($this->configPrefix).'): ';
399
-
400
-		//options that shall not be empty
401
-		$options = array('ldapHost', 'ldapPort', 'ldapUserDisplayName',
402
-						 'ldapGroupDisplayName', 'ldapLoginFilter');
403
-		foreach($options as $key) {
404
-			$val = $this->configuration->$key;
405
-			if(empty($val)) {
406
-				switch($key) {
407
-					case 'ldapHost':
408
-						$subj = 'LDAP Host';
409
-						break;
410
-					case 'ldapPort':
411
-						$subj = 'LDAP Port';
412
-						break;
413
-					case 'ldapUserDisplayName':
414
-						$subj = 'LDAP User Display Name';
415
-						break;
416
-					case 'ldapGroupDisplayName':
417
-						$subj = 'LDAP Group Display Name';
418
-						break;
419
-					case 'ldapLoginFilter':
420
-						$subj = 'LDAP Login Filter';
421
-						break;
422
-					default:
423
-						$subj = $key;
424
-						break;
425
-				}
426
-				$configurationOK = false;
427
-				\OCP\Util::writeLog('user_ldap',
428
-									$errorStr.'No '.$subj.' given!',
429
-									\OCP\Util::WARN);
430
-			}
431
-		}
432
-
433
-		//combinations
434
-		$agent = $this->configuration->ldapAgentName;
435
-		$pwd = $this->configuration->ldapAgentPassword;
436
-		if (
437
-			($agent === ''  && $pwd !== '')
438
-			|| ($agent !== '' && $pwd === '')
439
-		) {
440
-			\OCP\Util::writeLog('user_ldap',
441
-								$errorStr.'either no password is given for the '.
442
-								'user agent or a password is given, but not an '.
443
-								'LDAP agent.',
444
-				\OCP\Util::WARN);
445
-			$configurationOK = false;
446
-		}
447
-
448
-		$base = $this->configuration->ldapBase;
449
-		$baseUsers = $this->configuration->ldapBaseUsers;
450
-		$baseGroups = $this->configuration->ldapBaseGroups;
451
-
452
-		if(empty($base) && empty($baseUsers) && empty($baseGroups)) {
453
-			\OCP\Util::writeLog('user_ldap',
454
-								$errorStr.'Not a single Base DN given.',
455
-								\OCP\Util::WARN);
456
-			$configurationOK = false;
457
-		}
458
-
459
-		if(mb_strpos($this->configuration->ldapLoginFilter, '%uid', 0, 'UTF-8')
460
-		   === false) {
461
-			\OCP\Util::writeLog('user_ldap',
462
-								$errorStr.'login filter does not contain %uid '.
463
-								'place holder.',
464
-								\OCP\Util::WARN);
465
-			$configurationOK = false;
466
-		}
467
-
468
-		return $configurationOK;
469
-	}
470
-
471
-	/**
472
-	 * Validates the user specified configuration
473
-	 * @return bool true if configuration seems OK, false otherwise
474
-	 */
475
-	private function validateConfiguration() {
476
-
477
-		if($this->doNotValidate) {
478
-			//don't do a validation if it is a new configuration with pure
479
-			//default values. Will be allowed on changes via __set or
480
-			//setConfiguration
481
-			return false;
482
-		}
483
-
484
-		// first step: "soft" checks: settings that are not really
485
-		// necessary, but advisable. If left empty, give an info message
486
-		$this->doSoftValidation();
487
-
488
-		//second step: critical checks. If left empty or filled wrong, mark as
489
-		//not configured and give a warning.
490
-		return $this->doCriticalValidation();
491
-	}
492
-
493
-
494
-	/**
495
-	 * Connects and Binds to LDAP
496
-	 */
497
-	private function establishConnection() {
498
-		if(!$this->configuration->ldapConfigurationActive) {
499
-			return null;
500
-		}
501
-		static $phpLDAPinstalled = true;
502
-		if(!$phpLDAPinstalled) {
503
-			return false;
504
-		}
505
-		if(!$this->ignoreValidation && !$this->configured) {
506
-			\OCP\Util::writeLog('user_ldap',
507
-								'Configuration is invalid, cannot connect',
508
-								\OCP\Util::WARN);
509
-			return false;
510
-		}
511
-		if(!$this->ldapConnectionRes) {
512
-			if(!$this->ldap->areLDAPFunctionsAvailable()) {
513
-				$phpLDAPinstalled = false;
514
-				\OCP\Util::writeLog('user_ldap',
515
-									'function ldap_connect is not available. Make '.
516
-									'sure that the PHP ldap module is installed.',
517
-									\OCP\Util::ERROR);
518
-
519
-				return false;
520
-			}
521
-			if($this->configuration->turnOffCertCheck) {
522
-				if(putenv('LDAPTLS_REQCERT=never')) {
523
-					\OCP\Util::writeLog('user_ldap',
524
-						'Turned off SSL certificate validation successfully.',
525
-						\OCP\Util::DEBUG);
526
-				} else {
527
-					\OCP\Util::writeLog('user_ldap',
528
-										'Could not turn off SSL certificate validation.',
529
-										\OCP\Util::WARN);
530
-				}
531
-			}
532
-
533
-			$isOverrideMainServer = ($this->configuration->ldapOverrideMainServer
534
-				|| $this->getFromCache('overrideMainServer'));
535
-			$isBackupHost = (trim($this->configuration->ldapBackupHost) !== "");
536
-			$bindStatus = false;
537
-			$error = -1;
538
-			try {
539
-				if (!$isOverrideMainServer) {
540
-					$this->doConnect($this->configuration->ldapHost,
541
-						$this->configuration->ldapPort);
542
-					$bindStatus = $this->bind();
543
-					$error = $this->ldap->isResource($this->ldapConnectionRes) ?
544
-						$this->ldap->errno($this->ldapConnectionRes) : -1;
545
-				}
546
-				if($bindStatus === true) {
547
-					return $bindStatus;
548
-				}
549
-			} catch (ServerNotAvailableException $e) {
550
-				if(!$isBackupHost) {
551
-					throw $e;
552
-				}
553
-			}
554
-
555
-			//if LDAP server is not reachable, try the Backup (Replica!) Server
556
-			if($isBackupHost && ($error !== 0 || $isOverrideMainServer)) {
557
-				$this->doConnect($this->configuration->ldapBackupHost,
558
-								 $this->configuration->ldapBackupPort);
559
-				$bindStatus = $this->bind();
560
-				$error = $this->ldap->isResource($this->ldapConnectionRes) ?
561
-					$this->ldap->errno($this->ldapConnectionRes) : -1;
562
-				if($bindStatus && $error === 0 && !$this->getFromCache('overrideMainServer')) {
563
-					//when bind to backup server succeeded and failed to main server,
564
-					//skip contacting him until next cache refresh
565
-					$this->writeToCache('overrideMainServer', true);
566
-				}
567
-			}
568
-
569
-			return $bindStatus;
570
-		}
571
-		return null;
572
-	}
573
-
574
-	/**
575
-	 * @param string $host
576
-	 * @param string $port
577
-	 * @return bool
578
-	 * @throws \OC\ServerNotAvailableException
579
-	 */
580
-	private function doConnect($host, $port) {
581
-		if ($host === '') {
582
-			return false;
583
-		}
584
-
585
-		$this->ldapConnectionRes = $this->ldap->connect($host, $port);
586
-
587
-		if(!$this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
588
-			throw new ServerNotAvailableException('Could not set required LDAP Protocol version.');
589
-		}
590
-
591
-		if(!$this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
592
-			throw new ServerNotAvailableException('Could not disable LDAP referrals.');
593
-		}
594
-
595
-		if($this->configuration->ldapTLS) {
596
-			if(!$this->ldap->startTls($this->ldapConnectionRes)) {
597
-				throw new ServerNotAvailableException('Start TLS failed, when connecting to LDAP host ' . $host . '.');
598
-			}
599
-		}
600
-
601
-		return true;
602
-	}
603
-
604
-	/**
605
-	 * Binds to LDAP
606
-	 */
607
-	public function bind() {
608
-		if(!$this->configuration->ldapConfigurationActive) {
609
-			return false;
610
-		}
611
-		$cr = $this->getConnectionResource();
612
-		if(!$this->ldap->isResource($cr)) {
613
-			return false;
614
-		}
615
-		$ldapLogin = @$this->ldap->bind($cr,
616
-										$this->configuration->ldapAgentName,
617
-										$this->configuration->ldapAgentPassword);
618
-		if(!$ldapLogin) {
619
-			$errno = $this->ldap->errno($cr);
620
-
621
-			\OCP\Util::writeLog('user_ldap',
622
-				'Bind failed: ' . $errno . ': ' . $this->ldap->error($cr),
623
-				\OCP\Util::WARN);
624
-
625
-			// Set to failure mode, if LDAP error code is not LDAP_SUCCESS or LDAP_INVALID_CREDENTIALS
626
-			if($errno !== 0x00 && $errno !== 0x31) {
627
-				$this->ldapConnectionRes = null;
628
-			}
629
-
630
-			return false;
631
-		}
632
-		return true;
633
-	}
57
+    private $ldapConnectionRes = null;
58
+    private $configPrefix;
59
+    private $configID;
60
+    private $configured = false;
61
+    private $hasPagedResultSupport = true;
62
+    //whether connection should be kept on __destruct
63
+    private $dontDestruct = false;
64
+
65
+    /**
66
+     * @var bool runtime flag that indicates whether supported primary groups are available
67
+     */
68
+    public $hasPrimaryGroups = true;
69
+
70
+    /**
71
+     * @var bool runtime flag that indicates whether supported POSIX gidNumber are available
72
+     */
73
+    public $hasGidNumber = true;
74
+
75
+    //cache handler
76
+    protected $cache;
77
+
78
+    /** @var Configuration settings handler **/
79
+    protected $configuration;
80
+
81
+    protected $doNotValidate = false;
82
+
83
+    protected $ignoreValidation = false;
84
+
85
+    /**
86
+     * Constructor
87
+     * @param ILDAPWrapper $ldap
88
+     * @param string $configPrefix a string with the prefix for the configkey column (appconfig table)
89
+     * @param string|null $configID a string with the value for the appid column (appconfig table) or null for on-the-fly connections
90
+     */
91
+    public function __construct(ILDAPWrapper $ldap, $configPrefix = '', $configID = 'user_ldap') {
92
+        parent::__construct($ldap);
93
+        $this->configPrefix = $configPrefix;
94
+        $this->configID = $configID;
95
+        $this->configuration = new Configuration($configPrefix,
96
+                                                    !is_null($configID));
97
+        $memcache = \OC::$server->getMemCacheFactory();
98
+        if($memcache->isAvailable()) {
99
+            $this->cache = $memcache->create();
100
+        }
101
+        $helper = new Helper(\OC::$server->getConfig());
102
+        $this->doNotValidate = !in_array($this->configPrefix,
103
+            $helper->getServerConfigurationPrefixes());
104
+        $this->hasPagedResultSupport =
105
+            intval($this->configuration->ldapPagingSize) !== 0
106
+            || $this->ldap->hasPagedResultSupport();
107
+    }
108
+
109
+    public function __destruct() {
110
+        if(!$this->dontDestruct && $this->ldap->isResource($this->ldapConnectionRes)) {
111
+            @$this->ldap->unbind($this->ldapConnectionRes);
112
+        };
113
+    }
114
+
115
+    /**
116
+     * defines behaviour when the instance is cloned
117
+     */
118
+    public function __clone() {
119
+        $this->configuration = new Configuration($this->configPrefix,
120
+                                                    !is_null($this->configID));
121
+        $this->ldapConnectionRes = null;
122
+        $this->dontDestruct = true;
123
+    }
124
+
125
+    /**
126
+     * @param string $name
127
+     * @return bool|mixed
128
+     */
129
+    public function __get($name) {
130
+        if(!$this->configured) {
131
+            $this->readConfiguration();
132
+        }
133
+
134
+        if($name === 'hasPagedResultSupport') {
135
+            return $this->hasPagedResultSupport;
136
+        }
137
+
138
+        return $this->configuration->$name;
139
+    }
140
+
141
+    /**
142
+     * @param string $name
143
+     * @param mixed $value
144
+     */
145
+    public function __set($name, $value) {
146
+        $this->doNotValidate = false;
147
+        $before = $this->configuration->$name;
148
+        $this->configuration->$name = $value;
149
+        $after = $this->configuration->$name;
150
+        if($before !== $after) {
151
+            if ($this->configID !== '') {
152
+                $this->configuration->saveConfiguration();
153
+            }
154
+            $this->validateConfiguration();
155
+        }
156
+    }
157
+
158
+    /**
159
+     * sets whether the result of the configuration validation shall
160
+     * be ignored when establishing the connection. Used by the Wizard
161
+     * in early configuration state.
162
+     * @param bool $state
163
+     */
164
+    public function setIgnoreValidation($state) {
165
+        $this->ignoreValidation = (bool)$state;
166
+    }
167
+
168
+    /**
169
+     * initializes the LDAP backend
170
+     * @param bool $force read the config settings no matter what
171
+     */
172
+    public function init($force = false) {
173
+        $this->readConfiguration($force);
174
+        $this->establishConnection();
175
+    }
176
+
177
+    /**
178
+     * Returns the LDAP handler
179
+     */
180
+    public function getConnectionResource() {
181
+        if(!$this->ldapConnectionRes) {
182
+            $this->init();
183
+        } else if(!$this->ldap->isResource($this->ldapConnectionRes)) {
184
+            $this->ldapConnectionRes = null;
185
+            $this->establishConnection();
186
+        }
187
+        if(is_null($this->ldapConnectionRes)) {
188
+            \OCP\Util::writeLog('user_ldap', 'No LDAP Connection to server ' . $this->configuration->ldapHost, \OCP\Util::ERROR);
189
+            throw new ServerNotAvailableException('Connection to LDAP server could not be established');
190
+        }
191
+        return $this->ldapConnectionRes;
192
+    }
193
+
194
+    /**
195
+     * resets the connection resource
196
+     */
197
+    public function resetConnectionResource() {
198
+        if(!is_null($this->ldapConnectionRes)) {
199
+            @$this->ldap->unbind($this->ldapConnectionRes);
200
+            $this->ldapConnectionRes = null;
201
+        }
202
+    }
203
+
204
+    /**
205
+     * @param string|null $key
206
+     * @return string
207
+     */
208
+    private function getCacheKey($key) {
209
+        $prefix = 'LDAP-'.$this->configID.'-'.$this->configPrefix.'-';
210
+        if(is_null($key)) {
211
+            return $prefix;
212
+        }
213
+        return $prefix.md5($key);
214
+    }
215
+
216
+    /**
217
+     * @param string $key
218
+     * @return mixed|null
219
+     */
220
+    public function getFromCache($key) {
221
+        if(!$this->configured) {
222
+            $this->readConfiguration();
223
+        }
224
+        if(is_null($this->cache) || !$this->configuration->ldapCacheTTL) {
225
+            return null;
226
+        }
227
+        $key = $this->getCacheKey($key);
228
+
229
+        return json_decode(base64_decode($this->cache->get($key)), true);
230
+    }
231
+
232
+    /**
233
+     * @param string $key
234
+     * @param mixed $value
235
+     *
236
+     * @return string
237
+     */
238
+    public function writeToCache($key, $value) {
239
+        if(!$this->configured) {
240
+            $this->readConfiguration();
241
+        }
242
+        if(is_null($this->cache)
243
+            || !$this->configuration->ldapCacheTTL
244
+            || !$this->configuration->ldapConfigurationActive) {
245
+            return null;
246
+        }
247
+        $key   = $this->getCacheKey($key);
248
+        $value = base64_encode(json_encode($value));
249
+        $this->cache->set($key, $value, $this->configuration->ldapCacheTTL);
250
+    }
251
+
252
+    public function clearCache() {
253
+        if(!is_null($this->cache)) {
254
+            $this->cache->clear($this->getCacheKey(null));
255
+        }
256
+    }
257
+
258
+    /**
259
+     * Caches the general LDAP configuration.
260
+     * @param bool $force optional. true, if the re-read should be forced. defaults
261
+     * to false.
262
+     * @return null
263
+     */
264
+    private function readConfiguration($force = false) {
265
+        if((!$this->configured || $force) && !is_null($this->configID)) {
266
+            $this->configuration->readConfiguration();
267
+            $this->configured = $this->validateConfiguration();
268
+        }
269
+    }
270
+
271
+    /**
272
+     * set LDAP configuration with values delivered by an array, not read from configuration
273
+     * @param array $config array that holds the config parameters in an associated array
274
+     * @param array &$setParameters optional; array where the set fields will be given to
275
+     * @return boolean true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters
276
+     */
277
+    public function setConfiguration($config, &$setParameters = null) {
278
+        if(is_null($setParameters)) {
279
+            $setParameters = array();
280
+        }
281
+        $this->doNotValidate = false;
282
+        $this->configuration->setConfiguration($config, $setParameters);
283
+        if(count($setParameters) > 0) {
284
+            $this->configured = $this->validateConfiguration();
285
+        }
286
+
287
+
288
+        return $this->configured;
289
+    }
290
+
291
+    /**
292
+     * saves the current Configuration in the database and empties the
293
+     * cache
294
+     * @return null
295
+     */
296
+    public function saveConfiguration() {
297
+        $this->configuration->saveConfiguration();
298
+        $this->clearCache();
299
+    }
300
+
301
+    /**
302
+     * get the current LDAP configuration
303
+     * @return array
304
+     */
305
+    public function getConfiguration() {
306
+        $this->readConfiguration();
307
+        $config = $this->configuration->getConfiguration();
308
+        $cta = $this->configuration->getConfigTranslationArray();
309
+        $result = array();
310
+        foreach($cta as $dbkey => $configkey) {
311
+            switch($configkey) {
312
+                case 'homeFolderNamingRule':
313
+                    if(strpos($config[$configkey], 'attr:') === 0) {
314
+                        $result[$dbkey] = substr($config[$configkey], 5);
315
+                    } else {
316
+                        $result[$dbkey] = '';
317
+                    }
318
+                    break;
319
+                case 'ldapBase':
320
+                case 'ldapBaseUsers':
321
+                case 'ldapBaseGroups':
322
+                case 'ldapAttributesForUserSearch':
323
+                case 'ldapAttributesForGroupSearch':
324
+                    if(is_array($config[$configkey])) {
325
+                        $result[$dbkey] = implode("\n", $config[$configkey]);
326
+                        break;
327
+                    } //else follows default
328
+                default:
329
+                    $result[$dbkey] = $config[$configkey];
330
+            }
331
+        }
332
+        return $result;
333
+    }
334
+
335
+    private function doSoftValidation() {
336
+        //if User or Group Base are not set, take over Base DN setting
337
+        foreach(array('ldapBaseUsers', 'ldapBaseGroups') as $keyBase) {
338
+            $val = $this->configuration->$keyBase;
339
+            if(empty($val)) {
340
+                $this->configuration->$keyBase = $this->configuration->ldapBase;
341
+            }
342
+        }
343
+
344
+        foreach(array('ldapExpertUUIDUserAttr'  => 'ldapUuidUserAttribute',
345
+                        'ldapExpertUUIDGroupAttr' => 'ldapUuidGroupAttribute')
346
+                as $expertSetting => $effectiveSetting) {
347
+            $uuidOverride = $this->configuration->$expertSetting;
348
+            if(!empty($uuidOverride)) {
349
+                $this->configuration->$effectiveSetting = $uuidOverride;
350
+            } else {
351
+                $uuidAttributes = Access::UUID_ATTRIBUTES;
352
+                array_unshift($uuidAttributes, 'auto');
353
+                if(!in_array($this->configuration->$effectiveSetting,
354
+                            $uuidAttributes)
355
+                    && (!is_null($this->configID))) {
356
+                    $this->configuration->$effectiveSetting = 'auto';
357
+                    $this->configuration->saveConfiguration();
358
+                    \OCP\Util::writeLog('user_ldap',
359
+                                        'Illegal value for the '.
360
+                                        $effectiveSetting.', '.'reset to '.
361
+                                        'autodetect.', \OCP\Util::INFO);
362
+                }
363
+
364
+            }
365
+        }
366
+
367
+        $backupPort = intval($this->configuration->ldapBackupPort);
368
+        if ($backupPort <= 0) {
369
+            $this->configuration->backupPort = $this->configuration->ldapPort;
370
+        }
371
+
372
+        //make sure empty search attributes are saved as simple, empty array
373
+        $saKeys = array('ldapAttributesForUserSearch',
374
+                        'ldapAttributesForGroupSearch');
375
+        foreach($saKeys as $key) {
376
+            $val = $this->configuration->$key;
377
+            if(is_array($val) && count($val) === 1 && empty($val[0])) {
378
+                $this->configuration->$key = array();
379
+            }
380
+        }
381
+
382
+        if((stripos($this->configuration->ldapHost, 'ldaps://') === 0)
383
+            && $this->configuration->ldapTLS) {
384
+            $this->configuration->ldapTLS = false;
385
+            \OCP\Util::writeLog('user_ldap',
386
+                                'LDAPS (already using secure connection) and '.
387
+                                'TLS do not work together. Switched off TLS.',
388
+                                \OCP\Util::INFO);
389
+        }
390
+    }
391
+
392
+    /**
393
+     * @return bool
394
+     */
395
+    private function doCriticalValidation() {
396
+        $configurationOK = true;
397
+        $errorStr = 'Configuration Error (prefix '.
398
+                    strval($this->configPrefix).'): ';
399
+
400
+        //options that shall not be empty
401
+        $options = array('ldapHost', 'ldapPort', 'ldapUserDisplayName',
402
+                            'ldapGroupDisplayName', 'ldapLoginFilter');
403
+        foreach($options as $key) {
404
+            $val = $this->configuration->$key;
405
+            if(empty($val)) {
406
+                switch($key) {
407
+                    case 'ldapHost':
408
+                        $subj = 'LDAP Host';
409
+                        break;
410
+                    case 'ldapPort':
411
+                        $subj = 'LDAP Port';
412
+                        break;
413
+                    case 'ldapUserDisplayName':
414
+                        $subj = 'LDAP User Display Name';
415
+                        break;
416
+                    case 'ldapGroupDisplayName':
417
+                        $subj = 'LDAP Group Display Name';
418
+                        break;
419
+                    case 'ldapLoginFilter':
420
+                        $subj = 'LDAP Login Filter';
421
+                        break;
422
+                    default:
423
+                        $subj = $key;
424
+                        break;
425
+                }
426
+                $configurationOK = false;
427
+                \OCP\Util::writeLog('user_ldap',
428
+                                    $errorStr.'No '.$subj.' given!',
429
+                                    \OCP\Util::WARN);
430
+            }
431
+        }
432
+
433
+        //combinations
434
+        $agent = $this->configuration->ldapAgentName;
435
+        $pwd = $this->configuration->ldapAgentPassword;
436
+        if (
437
+            ($agent === ''  && $pwd !== '')
438
+            || ($agent !== '' && $pwd === '')
439
+        ) {
440
+            \OCP\Util::writeLog('user_ldap',
441
+                                $errorStr.'either no password is given for the '.
442
+                                'user agent or a password is given, but not an '.
443
+                                'LDAP agent.',
444
+                \OCP\Util::WARN);
445
+            $configurationOK = false;
446
+        }
447
+
448
+        $base = $this->configuration->ldapBase;
449
+        $baseUsers = $this->configuration->ldapBaseUsers;
450
+        $baseGroups = $this->configuration->ldapBaseGroups;
451
+
452
+        if(empty($base) && empty($baseUsers) && empty($baseGroups)) {
453
+            \OCP\Util::writeLog('user_ldap',
454
+                                $errorStr.'Not a single Base DN given.',
455
+                                \OCP\Util::WARN);
456
+            $configurationOK = false;
457
+        }
458
+
459
+        if(mb_strpos($this->configuration->ldapLoginFilter, '%uid', 0, 'UTF-8')
460
+            === false) {
461
+            \OCP\Util::writeLog('user_ldap',
462
+                                $errorStr.'login filter does not contain %uid '.
463
+                                'place holder.',
464
+                                \OCP\Util::WARN);
465
+            $configurationOK = false;
466
+        }
467
+
468
+        return $configurationOK;
469
+    }
470
+
471
+    /**
472
+     * Validates the user specified configuration
473
+     * @return bool true if configuration seems OK, false otherwise
474
+     */
475
+    private function validateConfiguration() {
476
+
477
+        if($this->doNotValidate) {
478
+            //don't do a validation if it is a new configuration with pure
479
+            //default values. Will be allowed on changes via __set or
480
+            //setConfiguration
481
+            return false;
482
+        }
483
+
484
+        // first step: "soft" checks: settings that are not really
485
+        // necessary, but advisable. If left empty, give an info message
486
+        $this->doSoftValidation();
487
+
488
+        //second step: critical checks. If left empty or filled wrong, mark as
489
+        //not configured and give a warning.
490
+        return $this->doCriticalValidation();
491
+    }
492
+
493
+
494
+    /**
495
+     * Connects and Binds to LDAP
496
+     */
497
+    private function establishConnection() {
498
+        if(!$this->configuration->ldapConfigurationActive) {
499
+            return null;
500
+        }
501
+        static $phpLDAPinstalled = true;
502
+        if(!$phpLDAPinstalled) {
503
+            return false;
504
+        }
505
+        if(!$this->ignoreValidation && !$this->configured) {
506
+            \OCP\Util::writeLog('user_ldap',
507
+                                'Configuration is invalid, cannot connect',
508
+                                \OCP\Util::WARN);
509
+            return false;
510
+        }
511
+        if(!$this->ldapConnectionRes) {
512
+            if(!$this->ldap->areLDAPFunctionsAvailable()) {
513
+                $phpLDAPinstalled = false;
514
+                \OCP\Util::writeLog('user_ldap',
515
+                                    'function ldap_connect is not available. Make '.
516
+                                    'sure that the PHP ldap module is installed.',
517
+                                    \OCP\Util::ERROR);
518
+
519
+                return false;
520
+            }
521
+            if($this->configuration->turnOffCertCheck) {
522
+                if(putenv('LDAPTLS_REQCERT=never')) {
523
+                    \OCP\Util::writeLog('user_ldap',
524
+                        'Turned off SSL certificate validation successfully.',
525
+                        \OCP\Util::DEBUG);
526
+                } else {
527
+                    \OCP\Util::writeLog('user_ldap',
528
+                                        'Could not turn off SSL certificate validation.',
529
+                                        \OCP\Util::WARN);
530
+                }
531
+            }
532
+
533
+            $isOverrideMainServer = ($this->configuration->ldapOverrideMainServer
534
+                || $this->getFromCache('overrideMainServer'));
535
+            $isBackupHost = (trim($this->configuration->ldapBackupHost) !== "");
536
+            $bindStatus = false;
537
+            $error = -1;
538
+            try {
539
+                if (!$isOverrideMainServer) {
540
+                    $this->doConnect($this->configuration->ldapHost,
541
+                        $this->configuration->ldapPort);
542
+                    $bindStatus = $this->bind();
543
+                    $error = $this->ldap->isResource($this->ldapConnectionRes) ?
544
+                        $this->ldap->errno($this->ldapConnectionRes) : -1;
545
+                }
546
+                if($bindStatus === true) {
547
+                    return $bindStatus;
548
+                }
549
+            } catch (ServerNotAvailableException $e) {
550
+                if(!$isBackupHost) {
551
+                    throw $e;
552
+                }
553
+            }
554
+
555
+            //if LDAP server is not reachable, try the Backup (Replica!) Server
556
+            if($isBackupHost && ($error !== 0 || $isOverrideMainServer)) {
557
+                $this->doConnect($this->configuration->ldapBackupHost,
558
+                                    $this->configuration->ldapBackupPort);
559
+                $bindStatus = $this->bind();
560
+                $error = $this->ldap->isResource($this->ldapConnectionRes) ?
561
+                    $this->ldap->errno($this->ldapConnectionRes) : -1;
562
+                if($bindStatus && $error === 0 && !$this->getFromCache('overrideMainServer')) {
563
+                    //when bind to backup server succeeded and failed to main server,
564
+                    //skip contacting him until next cache refresh
565
+                    $this->writeToCache('overrideMainServer', true);
566
+                }
567
+            }
568
+
569
+            return $bindStatus;
570
+        }
571
+        return null;
572
+    }
573
+
574
+    /**
575
+     * @param string $host
576
+     * @param string $port
577
+     * @return bool
578
+     * @throws \OC\ServerNotAvailableException
579
+     */
580
+    private function doConnect($host, $port) {
581
+        if ($host === '') {
582
+            return false;
583
+        }
584
+
585
+        $this->ldapConnectionRes = $this->ldap->connect($host, $port);
586
+
587
+        if(!$this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
588
+            throw new ServerNotAvailableException('Could not set required LDAP Protocol version.');
589
+        }
590
+
591
+        if(!$this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
592
+            throw new ServerNotAvailableException('Could not disable LDAP referrals.');
593
+        }
594
+
595
+        if($this->configuration->ldapTLS) {
596
+            if(!$this->ldap->startTls($this->ldapConnectionRes)) {
597
+                throw new ServerNotAvailableException('Start TLS failed, when connecting to LDAP host ' . $host . '.');
598
+            }
599
+        }
600
+
601
+        return true;
602
+    }
603
+
604
+    /**
605
+     * Binds to LDAP
606
+     */
607
+    public function bind() {
608
+        if(!$this->configuration->ldapConfigurationActive) {
609
+            return false;
610
+        }
611
+        $cr = $this->getConnectionResource();
612
+        if(!$this->ldap->isResource($cr)) {
613
+            return false;
614
+        }
615
+        $ldapLogin = @$this->ldap->bind($cr,
616
+                                        $this->configuration->ldapAgentName,
617
+                                        $this->configuration->ldapAgentPassword);
618
+        if(!$ldapLogin) {
619
+            $errno = $this->ldap->errno($cr);
620
+
621
+            \OCP\Util::writeLog('user_ldap',
622
+                'Bind failed: ' . $errno . ': ' . $this->ldap->error($cr),
623
+                \OCP\Util::WARN);
624
+
625
+            // Set to failure mode, if LDAP error code is not LDAP_SUCCESS or LDAP_INVALID_CREDENTIALS
626
+            if($errno !== 0x00 && $errno !== 0x31) {
627
+                $this->ldapConnectionRes = null;
628
+            }
629
+
630
+            return false;
631
+        }
632
+        return true;
633
+    }
634 634
 
635 635
 }
Please login to merge, or discard this patch.