Passed
Push — master ( bf1943...bfd61d )
by Blizzz
09:37
created

Configuration::getValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Alex Weirig <[email protected]>
6
 * @author Alexander Bergolth <[email protected]>
7
 * @author Arthur Schiwon <[email protected]>
8
 * @author Joas Schilling <[email protected]>
9
 * @author Jörn Friedrich Dreyer <[email protected]>
10
 * @author Lennart Rosam <[email protected]>
11
 * @author Lukas Reschke <[email protected]>
12
 * @author Morris Jobke <[email protected]>
13
 * @author Robin McCorkell <[email protected]>
14
 * @author Roger Szabo <[email protected]>
15
 * @author Victor Dubiniuk <[email protected]>
16
 * @author Xuanwo <[email protected]>
17
 *
18
 * @license AGPL-3.0
19
 *
20
 * This code is free software: you can redistribute it and/or modify
21
 * it under the terms of the GNU Affero General Public License, version 3,
22
 * as published by the Free Software Foundation.
23
 *
24
 * This program is distributed in the hope that it will be useful,
25
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27
 * GNU Affero General Public License for more details.
28
 *
29
 * You should have received a copy of the GNU Affero General Public License, version 3,
30
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
31
 *
32
 */
33
34
namespace OCA\User_LDAP;
35
36
/**
37
 * @property int ldapPagingSize holds an integer
38
 * @property string ldapUserAvatarRule
39
 */
40
class Configuration {
41
	const AVATAR_PREFIX_DEFAULT = 'default';
42
	const AVATAR_PREFIX_NONE = 'none';
43
	const AVATAR_PREFIX_DATA_ATTRIBUTE = 'data:';
44
45
	protected $configPrefix = null;
46
	protected $configRead = false;
47
	/**
48
	 * @var string[] pre-filled with one reference key so that at least one entry is written on save request and
49
	 *               the config ID is registered
50
	 */
51
	protected $unsavedChanges = ['ldapConfigurationActive' => 'ldapConfigurationActive'];
52
53
	//settings
54
	protected $config = array(
55
		'ldapHost' => null,
56
		'ldapPort' => null,
57
		'ldapBackupHost' => null,
58
		'ldapBackupPort' => null,
59
		'ldapBase' => null,
60
		'ldapBaseUsers' => null,
61
		'ldapBaseGroups' => null,
62
		'ldapAgentName' => null,
63
		'ldapAgentPassword' => null,
64
		'ldapTLS' => null,
65
		'turnOffCertCheck' => null,
66
		'ldapIgnoreNamingRules' => null,
67
		'ldapUserDisplayName' => null,
68
		'ldapUserDisplayName2' => null,
69
		'ldapUserAvatarRule' => null,
70
		'ldapGidNumber' => null,
71
		'ldapUserFilterObjectclass' => null,
72
		'ldapUserFilterGroups' => null,
73
		'ldapUserFilter' => null,
74
		'ldapUserFilterMode' => null,
75
		'ldapGroupFilter' => null,
76
		'ldapGroupFilterMode' => null,
77
		'ldapGroupFilterObjectclass' => null,
78
		'ldapGroupFilterGroups' => null,
79
		'ldapGroupDisplayName' => null,
80
		'ldapGroupMemberAssocAttr' => null,
81
		'ldapLoginFilter' => null,
82
		'ldapLoginFilterMode' => null,
83
		'ldapLoginFilterEmail' => null,
84
		'ldapLoginFilterUsername' => null,
85
		'ldapLoginFilterAttributes' => null,
86
		'ldapQuotaAttribute' => null,
87
		'ldapQuotaDefault' => null,
88
		'ldapEmailAttribute' => null,
89
		'ldapCacheTTL' => null,
90
		'ldapUuidUserAttribute' => 'auto',
91
		'ldapUuidGroupAttribute' => 'auto',
92
		'ldapOverrideMainServer' => false,
93
		'ldapConfigurationActive' => false,
94
		'ldapAttributesForUserSearch' => null,
95
		'ldapAttributesForGroupSearch' => null,
96
		'ldapExperiencedAdmin' => false,
97
		'homeFolderNamingRule' => null,
98
		'hasMemberOfFilterSupport' => false,
99
		'useMemberOfToDetectMembership' => true,
100
		'ldapExpertUsernameAttr' => null,
101
		'ldapExpertUUIDUserAttr' => null,
102
		'ldapExpertUUIDGroupAttr' => null,
103
		'lastJpegPhotoLookup' => null,
104
		'ldapNestedGroups' => false,
105
		'ldapPagingSize' => null,
106
		'turnOnPasswordChange' => false,
107
		'ldapDynamicGroupMemberURL' => null,
108
		'ldapDefaultPPolicyDN' => null,
109
		'ldapExtStorageHomeAttribute' => null,
110
	);
111
112
	/**
113
	 * @param string $configPrefix
114
	 * @param bool $autoRead
115
	 */
116
	public function __construct($configPrefix, $autoRead = true) {
117
		$this->configPrefix = $configPrefix;
118
		if($autoRead) {
119
			$this->readConfiguration();
120
		}
121
	}
122
123
	/**
124
	 * @param string $name
125
	 * @return mixed|null
126
	 */
127
	public function __get($name) {
128
		if(isset($this->config[$name])) {
129
			return $this->config[$name];
130
		}
131
		return null;
132
	}
133
134
	/**
135
	 * @param string $name
136
	 * @param mixed $value
137
	 */
138
	public function __set($name, $value) {
139
		$this->setConfiguration(array($name => $value));
140
	}
141
142
	/**
143
	 * @return array
144
	 */
145
	public function getConfiguration() {
146
		return $this->config;
147
	}
148
149
	/**
150
	 * set LDAP configuration with values delivered by an array, not read
151
	 * from configuration. It does not save the configuration! To do so, you
152
	 * must call saveConfiguration afterwards.
153
	 * @param array $config array that holds the config parameters in an associated
154
	 * array
155
	 * @param array &$applied optional; array where the set fields will be given to
156
	 * @return false|null
157
	 */
158
	public function setConfiguration($config, &$applied = null) {
159
		if(!is_array($config)) {
0 ignored issues
show
introduced by
The condition is_array($config) is always true.
Loading history...
160
			return false;
161
		}
162
163
		$cta = $this->getConfigTranslationArray();
164
		foreach($config as $inputKey => $val) {
165
			if(strpos($inputKey, '_') !== false && array_key_exists($inputKey, $cta)) {
166
				$key = $cta[$inputKey];
167
			} elseif(array_key_exists($inputKey, $this->config)) {
168
				$key = $inputKey;
169
			} else {
170
				continue;
171
			}
172
173
			$setMethod = 'setValue';
174
			switch($key) {
175
				case 'ldapAgentPassword':
176
					$setMethod = 'setRawValue';
177
					break;
178
				case 'homeFolderNamingRule':
179
					$trimmedVal = trim($val);
180
					if ($trimmedVal !== '' && strpos($val, 'attr:') === false) {
181
						$val = 'attr:'.$trimmedVal;
182
					}
183
					break;
184
				case 'ldapBase':
185
				case 'ldapBaseUsers':
186
				case 'ldapBaseGroups':
187
				case 'ldapAttributesForUserSearch':
188
				case 'ldapAttributesForGroupSearch':
189
				case 'ldapUserFilterObjectclass':
190
				case 'ldapUserFilterGroups':
191
				case 'ldapGroupFilterObjectclass':
192
				case 'ldapGroupFilterGroups':
193
				case 'ldapLoginFilterAttributes':
194
					$setMethod = 'setMultiLine';
195
					break;
196
			}
197
			$this->$setMethod($key, $val);
198
			if(is_array($applied)) {
199
				$applied[] = $inputKey;
200
				// storing key as index avoids duplication, and as value for simplicity
201
			}
202
			$this->unsavedChanges[$key] = $key;
203
		}
204
		return null;
205
	}
206
207
	public function readConfiguration() {
208
		if(!$this->configRead && !is_null($this->configPrefix)) {
209
			$cta = array_flip($this->getConfigTranslationArray());
210
			foreach($this->config as $key => $val) {
211
				if(!isset($cta[$key])) {
212
					//some are determined
213
					continue;
214
				}
215
				$dbKey = $cta[$key];
216
				switch($key) {
217
					case 'ldapBase':
218
					case 'ldapBaseUsers':
219
					case 'ldapBaseGroups':
220
					case 'ldapAttributesForUserSearch':
221
					case 'ldapAttributesForGroupSearch':
222
					case 'ldapUserFilterObjectclass':
223
					case 'ldapUserFilterGroups':
224
					case 'ldapGroupFilterObjectclass':
225
					case 'ldapGroupFilterGroups':
226
					case 'ldapLoginFilterAttributes':
227
						$readMethod = 'getMultiLine';
228
						break;
229
					case 'ldapIgnoreNamingRules':
230
						$readMethod = 'getSystemValue';
231
						$dbKey = $key;
232
						break;
233
					case 'ldapAgentPassword':
234
						$readMethod = 'getPwd';
235
						break;
236
					case 'ldapUserDisplayName2':
237
					case 'ldapGroupDisplayName':
238
						$readMethod = 'getLcValue';
239
						break;
240
					case 'ldapUserDisplayName':
241
					default:
242
						// user display name does not lower case because
243
						// we rely on an upper case N as indicator whether to
244
						// auto-detect it or not. FIXME
245
						$readMethod = 'getValue';
246
						break;
247
				}
248
				$this->config[$key] = $this->$readMethod($dbKey);
249
			}
250
			$this->configRead = true;
251
		}
252
	}
253
254
	/**
255
	 * saves the current config changes in the database
256
	 */
257
	public function saveConfiguration() {
258
		$cta = array_flip($this->getConfigTranslationArray());
259
		foreach($this->unsavedChanges as $key) {
260
			$value = $this->config[$key];
261
			switch ($key) {
262
				case 'ldapAgentPassword':
263
					$value = base64_encode($value);
264
					break;
265
				case 'ldapBase':
266
				case 'ldapBaseUsers':
267
				case 'ldapBaseGroups':
268
				case 'ldapAttributesForUserSearch':
269
				case 'ldapAttributesForGroupSearch':
270
				case 'ldapUserFilterObjectclass':
271
				case 'ldapUserFilterGroups':
272
				case 'ldapGroupFilterObjectclass':
273
				case 'ldapGroupFilterGroups':
274
				case 'ldapLoginFilterAttributes':
275
					if(is_array($value)) {
276
						$value = implode("\n", $value);
277
					}
278
					break;
279
				//following options are not stored but detected, skip them
280
				case 'ldapIgnoreNamingRules':
281
				case 'ldapUuidUserAttribute':
282
				case 'ldapUuidGroupAttribute':
283
					continue 2;
284
			}
285
			if(is_null($value)) {
286
				$value = '';
287
			}
288
			$this->saveValue($cta[$key], $value);
289
		}
290
		$this->saveValue('_lastChange', time());
291
		$this->unsavedChanges = [];
292
	}
293
294
	/**
295
	 * @param string $varName
296
	 * @return array|string
297
	 */
298
	protected function getMultiLine($varName) {
299
		$value = $this->getValue($varName);
300
		if(empty($value)) {
301
			$value = '';
302
		} else {
303
			$value = preg_split('/\r\n|\r|\n/', $value);
304
		}
305
306
		return $value;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $value could also return false which is incompatible with the documented return type array|string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
307
	}
308
309
	/**
310
	 * Sets multi-line values as arrays
311
	 * 
312
	 * @param string $varName name of config-key
313
	 * @param array|string $value to set
314
	 */
315
	protected function setMultiLine($varName, $value) {
316
		if(empty($value)) {
317
			$value = '';
318
		} else if (!is_array($value)) {
319
			$value = preg_split('/\r\n|\r|\n|;/', $value);
320
			if($value === false) {
321
				$value = '';
322
			}
323
		}
324
325
		if(!is_array($value)) {
326
			$finalValue = trim($value);
327
		} else {
328
			$finalValue = [];
329
			foreach($value as $key => $val) {
330
				if(is_string($val)) {
331
					$val = trim($val);
332
					if ($val !== '') {
333
						//accidental line breaks are not wanted and can cause
334
						// odd behaviour. Thus, away with them.
335
						$finalValue[] = $val;
336
					}
337
				} else {
338
					$finalValue[] = $val;
339
				}
340
			}
341
		}
342
343
		$this->setRawValue($varName, $finalValue);
344
	}
345
346
	/**
347
	 * @param string $varName
348
	 * @return string
349
	 */
350
	protected function getPwd($varName) {
351
		return base64_decode($this->getValue($varName));
352
	}
353
354
	/**
355
	 * @param string $varName
356
	 * @return string
357
	 */
358
	protected function getLcValue($varName) {
359
		return mb_strtolower($this->getValue($varName), 'UTF-8');
360
	}
361
362
	/**
363
	 * @param string $varName
364
	 * @return string
365
	 */
366
	protected function getSystemValue($varName) {
367
		//FIXME: if another system value is added, softcode the default value
368
		return \OC::$server->getConfig()->getSystemValue($varName, false);
369
	}
370
371
	/**
372
	 * @param string $varName
373
	 * @return string
374
	 */
375
	protected function getValue($varName) {
376
		static $defaults;
377
		if(is_null($defaults)) {
378
			$defaults = $this->getDefaults();
379
		}
380
		return \OC::$server->getConfig()->getAppValue('user_ldap',
381
										$this->configPrefix.$varName,
382
										$defaults[$varName]);
383
	}
384
385
	/**
386
	 * Sets a scalar value.
387
	 * 
388
	 * @param string $varName name of config key
389
	 * @param mixed $value to set
390
	 */
391
	protected function setValue($varName, $value) {
392
		if(is_string($value)) {
393
			$value = trim($value);
394
		}
395
		$this->config[$varName] = $value;
396
	}
397
398
	/**
399
	 * Sets a scalar value without trimming.
400
	 *
401
	 * @param string $varName name of config key
402
	 * @param mixed $value to set
403
	 */
404
	protected function setRawValue($varName, $value) {
405
		$this->config[$varName] = $value;
406
	}
407
408
	/**
409
	 * @param string $varName
410
	 * @param string $value
411
	 * @return bool
412
	 */
413
	protected function saveValue($varName, $value) {
414
		\OC::$server->getConfig()->setAppValue(
415
			'user_ldap',
416
			$this->configPrefix.$varName,
417
			$value
418
		);
419
		return true;
420
	}
421
422
	/**
423
	 * @return array an associative array with the default values. Keys are correspond
424
	 * to config-value entries in the database table
425
	 */
426
	public function getDefaults() {
427
		return array(
428
			'ldap_host'                         => '',
429
			'ldap_port'                         => '',
430
			'ldap_backup_host'                  => '',
431
			'ldap_backup_port'                  => '',
432
			'ldap_override_main_server'         => '',
433
			'ldap_dn'                           => '',
434
			'ldap_agent_password'               => '',
435
			'ldap_base'                         => '',
436
			'ldap_base_users'                   => '',
437
			'ldap_base_groups'                  => '',
438
			'ldap_userlist_filter'              => '',
439
			'ldap_user_filter_mode'             => 0,
440
			'ldap_userfilter_objectclass'       => '',
441
			'ldap_userfilter_groups'            => '',
442
			'ldap_login_filter'                 => '',
443
			'ldap_login_filter_mode'            => 0,
444
			'ldap_loginfilter_email'            => 0,
445
			'ldap_loginfilter_username'         => 1,
446
			'ldap_loginfilter_attributes'       => '',
447
			'ldap_group_filter'                 => '',
448
			'ldap_group_filter_mode'            => 0,
449
			'ldap_groupfilter_objectclass'      => '',
450
			'ldap_groupfilter_groups'           => '',
451
			'ldap_gid_number'                   => 'gidNumber',
452
			'ldap_display_name'                 => 'displayName',
453
			'ldap_user_display_name_2'			=> '',
454
			'ldap_group_display_name'           => 'cn',
455
			'ldap_tls'                          => 0,
456
			'ldap_quota_def'                    => '',
457
			'ldap_quota_attr'                   => '',
458
			'ldap_email_attr'                   => '',
459
			'ldap_group_member_assoc_attribute' => 'uniqueMember',
460
			'ldap_cache_ttl'                    => 600,
461
			'ldap_uuid_user_attribute'          => 'auto',
462
			'ldap_uuid_group_attribute'         => 'auto',
463
			'home_folder_naming_rule'           => '',
464
			'ldap_turn_off_cert_check'          => 0,
465
			'ldap_configuration_active'         => 0,
466
			'ldap_attributes_for_user_search'   => '',
467
			'ldap_attributes_for_group_search'  => '',
468
			'ldap_expert_username_attr'         => '',
469
			'ldap_expert_uuid_user_attr'        => '',
470
			'ldap_expert_uuid_group_attr'       => '',
471
			'has_memberof_filter_support'       => 0,
472
			'use_memberof_to_detect_membership' => 1,
473
			'last_jpegPhoto_lookup'             => 0,
474
			'ldap_nested_groups'                => 0,
475
			'ldap_paging_size'                  => 500,
476
			'ldap_turn_on_pwd_change'           => 0,
477
			'ldap_experienced_admin'            => 0,
478
			'ldap_dynamic_group_member_url'     => '',
479
			'ldap_default_ppolicy_dn'           => '',
480
			'ldap_user_avatar_rule'             => 'default',
481
			'ldap_ext_storage_home_attribute'   => '',
482
		);
483
	}
484
485
	/**
486
	 * @return array that maps internal variable names to database fields
487
	 */
488
	public function getConfigTranslationArray() {
489
		//TODO: merge them into one representation
490
		static $array = array(
491
			'ldap_host'                         => 'ldapHost',
492
			'ldap_port'                         => 'ldapPort',
493
			'ldap_backup_host'                  => 'ldapBackupHost',
494
			'ldap_backup_port'                  => 'ldapBackupPort',
495
			'ldap_override_main_server'         => 'ldapOverrideMainServer',
496
			'ldap_dn'                           => 'ldapAgentName',
497
			'ldap_agent_password'               => 'ldapAgentPassword',
498
			'ldap_base'                         => 'ldapBase',
499
			'ldap_base_users'                   => 'ldapBaseUsers',
500
			'ldap_base_groups'                  => 'ldapBaseGroups',
501
			'ldap_userfilter_objectclass'       => 'ldapUserFilterObjectclass',
502
			'ldap_userfilter_groups'            => 'ldapUserFilterGroups',
503
			'ldap_userlist_filter'              => 'ldapUserFilter',
504
			'ldap_user_filter_mode'             => 'ldapUserFilterMode',
505
			'ldap_user_avatar_rule'             => 'ldapUserAvatarRule',
506
			'ldap_login_filter'                 => 'ldapLoginFilter',
507
			'ldap_login_filter_mode'            => 'ldapLoginFilterMode',
508
			'ldap_loginfilter_email'            => 'ldapLoginFilterEmail',
509
			'ldap_loginfilter_username'         => 'ldapLoginFilterUsername',
510
			'ldap_loginfilter_attributes'       => 'ldapLoginFilterAttributes',
511
			'ldap_group_filter'                 => 'ldapGroupFilter',
512
			'ldap_group_filter_mode'            => 'ldapGroupFilterMode',
513
			'ldap_groupfilter_objectclass'      => 'ldapGroupFilterObjectclass',
514
			'ldap_groupfilter_groups'           => 'ldapGroupFilterGroups',
515
			'ldap_gid_number'                   => 'ldapGidNumber',
516
			'ldap_display_name'                 => 'ldapUserDisplayName',
517
			'ldap_user_display_name_2'			=> 'ldapUserDisplayName2',
518
			'ldap_group_display_name'           => 'ldapGroupDisplayName',
519
			'ldap_tls'                          => 'ldapTLS',
520
			'ldap_quota_def'                    => 'ldapQuotaDefault',
521
			'ldap_quota_attr'                   => 'ldapQuotaAttribute',
522
			'ldap_email_attr'                   => 'ldapEmailAttribute',
523
			'ldap_group_member_assoc_attribute' => 'ldapGroupMemberAssocAttr',
524
			'ldap_cache_ttl'                    => 'ldapCacheTTL',
525
			'home_folder_naming_rule'           => 'homeFolderNamingRule',
526
			'ldap_turn_off_cert_check'          => 'turnOffCertCheck',
527
			'ldap_configuration_active'         => 'ldapConfigurationActive',
528
			'ldap_attributes_for_user_search'   => 'ldapAttributesForUserSearch',
529
			'ldap_attributes_for_group_search'  => 'ldapAttributesForGroupSearch',
530
			'ldap_expert_username_attr'         => 'ldapExpertUsernameAttr',
531
			'ldap_expert_uuid_user_attr'        => 'ldapExpertUUIDUserAttr',
532
			'ldap_expert_uuid_group_attr'       => 'ldapExpertUUIDGroupAttr',
533
			'has_memberof_filter_support'       => 'hasMemberOfFilterSupport',
534
			'use_memberof_to_detect_membership' => 'useMemberOfToDetectMembership',
535
			'last_jpegPhoto_lookup'             => 'lastJpegPhotoLookup',
536
			'ldap_nested_groups'                => 'ldapNestedGroups',
537
			'ldap_paging_size'                  => 'ldapPagingSize',
538
			'ldap_turn_on_pwd_change'           => 'turnOnPasswordChange',
539
			'ldap_experienced_admin'            => 'ldapExperiencedAdmin',
540
			'ldap_dynamic_group_member_url'     => 'ldapDynamicGroupMemberURL',
541
			'ldap_default_ppolicy_dn'           => 'ldapDefaultPPolicyDN',
542
			'ldap_ext_storage_home_attribute'   => 'ldapExtStorageHomeAttribute',
543
			'ldapIgnoreNamingRules'             => 'ldapIgnoreNamingRules',	// sysconfig
544
		);
545
		return $array;
546
	}
547
548
	/**
549
	 * @param string $rule
550
	 * @return array
551
	 * @throws \RuntimeException
552
	 */
553
	public function resolveRule($rule) {
554
		if($rule === 'avatar') {
555
			return $this->getAvatarAttributes();
556
		}
557
		throw new \RuntimeException('Invalid rule');
558
	}
559
560
	public function getAvatarAttributes() {
561
		$value = $this->ldapUserAvatarRule ?: self::AVATAR_PREFIX_DEFAULT;
562
		$defaultAttributes = ['jpegphoto', 'thumbnailphoto'];
563
564
		if($value === self::AVATAR_PREFIX_NONE) {
565
			return [];
566
		}
567
		if(strpos($value, self::AVATAR_PREFIX_DATA_ATTRIBUTE) === 0) {
568
			$attribute = trim(substr($value, strlen(self::AVATAR_PREFIX_DATA_ATTRIBUTE)));
569
			if($attribute === '') {
570
				return $defaultAttributes;
571
			}
572
			return [strtolower($attribute)];
573
		}
574
		if($value !== self::AVATAR_PREFIX_DEFAULT) {
575
			\OC::$server->getLogger()->warning('Invalid config value to ldapUserAvatarRule; falling back to default.');
576
		}
577
		return $defaultAttributes;
578
	}
579
580
}
581