Completed
Pull Request — master (#4212)
by Individual IT
33:24
created
apps/user_ldap/lib/Wizard.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -1104,7 +1104,7 @@
 block discarded – undo
1104 1104
 	}
1105 1105
 
1106 1106
 	/**
1107
-	 * @param array $reqs
1107
+	 * @param string[] $reqs
1108 1108
 	 * @return bool
1109 1109
 	 */
1110 1110
 	private function checkRequirements($reqs) {
Please login to merge, or discard this patch.
Indentation   +1318 added lines, -1318 removed lines patch added patch discarded remove patch
@@ -37,1324 +37,1324 @@
 block discarded – undo
37 37
 use OC\ServerNotAvailableException;
38 38
 
39 39
 class Wizard extends LDAPUtility {
40
-	/** @var \OCP\IL10N */
41
-	static protected $l;
42
-	protected $access;
43
-	protected $cr;
44
-	protected $configuration;
45
-	protected $result;
46
-	protected $resultCache = array();
47
-
48
-	const LRESULT_PROCESSED_OK = 2;
49
-	const LRESULT_PROCESSED_INVALID = 3;
50
-	const LRESULT_PROCESSED_SKIP = 4;
51
-
52
-	const LFILTER_LOGIN      = 2;
53
-	const LFILTER_USER_LIST  = 3;
54
-	const LFILTER_GROUP_LIST = 4;
55
-
56
-	const LFILTER_MODE_ASSISTED = 2;
57
-	const LFILTER_MODE_RAW = 1;
58
-
59
-	const LDAP_NW_TIMEOUT = 4;
60
-
61
-	/**
62
-	 * Constructor
63
-	 * @param Configuration $configuration an instance of Configuration
64
-	 * @param ILDAPWrapper $ldap an instance of ILDAPWrapper
65
-	 * @param Access $access
66
-	 */
67
-	public function __construct(Configuration $configuration, ILDAPWrapper $ldap, Access $access) {
68
-		parent::__construct($ldap);
69
-		$this->configuration = $configuration;
70
-		if(is_null(Wizard::$l)) {
71
-			Wizard::$l = \OC::$server->getL10N('user_ldap');
72
-		}
73
-		$this->access = $access;
74
-		$this->result = new WizardResult();
75
-	}
76
-
77
-	public function  __destruct() {
78
-		if($this->result->hasChanges()) {
79
-			$this->configuration->saveConfiguration();
80
-		}
81
-	}
82
-
83
-	/**
84
-	 * counts entries in the LDAP directory
85
-	 *
86
-	 * @param string $filter the LDAP search filter
87
-	 * @param string $type a string being either 'users' or 'groups';
88
-	 * @return bool|int
89
-	 * @throws \Exception
90
-	 */
91
-	public function countEntries($filter, $type) {
92
-		$reqs = array('ldapHost', 'ldapPort', 'ldapBase');
93
-		if($type === 'users') {
94
-			$reqs[] = 'ldapUserFilter';
95
-		}
96
-		if(!$this->checkRequirements($reqs)) {
97
-			throw new \Exception('Requirements not met', 400);
98
-		}
99
-
100
-		$attr = array('dn'); // default
101
-		$limit = 1001;
102
-		if($type === 'groups') {
103
-			$result =  $this->access->countGroups($filter, $attr, $limit);
104
-		} else if($type === 'users') {
105
-			$result = $this->access->countUsers($filter, $attr, $limit);
106
-		} else if ($type === 'objects') {
107
-			$result = $this->access->countObjects($limit);
108
-		} else {
109
-			throw new \Exception('internal error: invalid object type', 500);
110
-		}
111
-
112
-		return $result;
113
-	}
114
-
115
-	/**
116
-	 * formats the return value of a count operation to the string to be
117
-	 * inserted.
118
-	 *
119
-	 * @param bool|int $count
120
-	 * @return int|string
121
-	 */
122
-	private function formatCountResult($count) {
123
-		$formatted = ($count !== false) ? $count : 0;
124
-		if($formatted > 1000) {
125
-			$formatted = '> 1000';
126
-		}
127
-		return $formatted;
128
-	}
129
-
130
-	public function countGroups() {
131
-		$filter = $this->configuration->ldapGroupFilter;
132
-
133
-		if(empty($filter)) {
134
-			$output = self::$l->n('%s group found', '%s groups found', 0, array(0));
135
-			$this->result->addChange('ldap_group_count', $output);
136
-			return $this->result;
137
-		}
138
-
139
-		try {
140
-			$groupsTotal = $this->formatCountResult($this->countEntries($filter, 'groups'));
141
-		} catch (\Exception $e) {
142
-			//400 can be ignored, 500 is forwarded
143
-			if($e->getCode() === 500) {
144
-				throw $e;
145
-			}
146
-			return false;
147
-		}
148
-		$output = self::$l->n('%s group found', '%s groups found', $groupsTotal, array($groupsTotal));
149
-		$this->result->addChange('ldap_group_count', $output);
150
-		return $this->result;
151
-	}
152
-
153
-	/**
154
-	 * @return WizardResult
155
-	 * @throws \Exception
156
-	 */
157
-	public function countUsers() {
158
-		$filter = $this->access->getFilterForUserCount();
159
-
160
-		$usersTotal = $this->formatCountResult($this->countEntries($filter, 'users'));
161
-		$output = self::$l->n('%s user found', '%s users found', $usersTotal, array($usersTotal));
162
-		$this->result->addChange('ldap_user_count', $output);
163
-		return $this->result;
164
-	}
165
-
166
-	/**
167
-	 * counts any objects in the currently set base dn
168
-	 *
169
-	 * @return WizardResult
170
-	 * @throws \Exception
171
-	 */
172
-	public function countInBaseDN() {
173
-		// we don't need to provide a filter in this case
174
-		$total = $this->countEntries(null, 'objects');
175
-		if($total === false) {
176
-			throw new \Exception('invalid results received');
177
-		}
178
-		$this->result->addChange('ldap_test_base', $total);
179
-		return $this->result;
180
-	}
181
-
182
-	/**
183
-	 * counts users with a specified attribute
184
-	 * @param string $attr
185
-	 * @param bool $existsCheck
186
-	 * @return int|bool
187
-	 */
188
-	public function countUsersWithAttribute($attr, $existsCheck = false) {
189
-		if(!$this->checkRequirements(array('ldapHost',
190
-										   'ldapPort',
191
-										   'ldapBase',
192
-										   'ldapUserFilter',
193
-										   ))) {
194
-			return  false;
195
-		}
196
-
197
-		$filter = $this->access->combineFilterWithAnd(array(
198
-			$this->configuration->ldapUserFilter,
199
-			$attr . '=*'
200
-		));
201
-
202
-		$limit = ($existsCheck === false) ? null : 1;
203
-
204
-		return $this->access->countUsers($filter, array('dn'), $limit);
205
-	}
206
-
207
-	/**
208
-	 * detects the display name attribute. If a setting is already present that
209
-	 * returns at least one hit, the detection will be canceled.
210
-	 * @return WizardResult|bool
211
-	 * @throws \Exception
212
-	 */
213
-	public function detectUserDisplayNameAttribute() {
214
-		if(!$this->checkRequirements(array('ldapHost',
215
-										'ldapPort',
216
-										'ldapBase',
217
-										'ldapUserFilter',
218
-										))) {
219
-			return  false;
220
-		}
221
-
222
-		$attr = $this->configuration->ldapUserDisplayName;
223
-		if ($attr !== '' && $attr !== 'displayName') {
224
-			// most likely not the default value with upper case N,
225
-			// verify it still produces a result
226
-			$count = intval($this->countUsersWithAttribute($attr, true));
227
-			if($count > 0) {
228
-				//no change, but we sent it back to make sure the user interface
229
-				//is still correct, even if the ajax call was cancelled meanwhile
230
-				$this->result->addChange('ldap_display_name', $attr);
231
-				return $this->result;
232
-			}
233
-		}
234
-
235
-		// first attribute that has at least one result wins
236
-		$displayNameAttrs = array('displayname', 'cn');
237
-		foreach ($displayNameAttrs as $attr) {
238
-			$count = intval($this->countUsersWithAttribute($attr, true));
239
-
240
-			if($count > 0) {
241
-				$this->applyFind('ldap_display_name', $attr);
242
-				return $this->result;
243
-			}
244
-		};
245
-
246
-		throw new \Exception(self::$l->t('Could not detect user display name attribute. Please specify it yourself in advanced ldap settings.'));
247
-	}
248
-
249
-	/**
250
-	 * detects the most often used email attribute for users applying to the
251
-	 * user list filter. If a setting is already present that returns at least
252
-	 * one hit, the detection will be canceled.
253
-	 * @return WizardResult|bool
254
-	 */
255
-	public function detectEmailAttribute() {
256
-		if(!$this->checkRequirements(array('ldapHost',
257
-										   'ldapPort',
258
-										   'ldapBase',
259
-										   'ldapUserFilter',
260
-										   ))) {
261
-			return  false;
262
-		}
263
-
264
-		$attr = $this->configuration->ldapEmailAttribute;
265
-		if ($attr !== '') {
266
-			$count = intval($this->countUsersWithAttribute($attr, true));
267
-			if($count > 0) {
268
-				return false;
269
-			}
270
-			$writeLog = true;
271
-		} else {
272
-			$writeLog = false;
273
-		}
274
-
275
-		$emailAttributes = array('mail', 'mailPrimaryAddress');
276
-		$winner = '';
277
-		$maxUsers = 0;
278
-		foreach($emailAttributes as $attr) {
279
-			$count = $this->countUsersWithAttribute($attr);
280
-			if($count > $maxUsers) {
281
-				$maxUsers = $count;
282
-				$winner = $attr;
283
-			}
284
-		}
285
-
286
-		if($winner !== '') {
287
-			$this->applyFind('ldap_email_attr', $winner);
288
-			if($writeLog) {
289
-				\OCP\Util::writeLog('user_ldap', 'The mail attribute has ' .
290
-					'automatically been reset, because the original value ' .
291
-					'did not return any results.', \OCP\Util::INFO);
292
-			}
293
-		}
294
-
295
-		return $this->result;
296
-	}
297
-
298
-	/**
299
-	 * @return WizardResult
300
-	 * @throws \Exception
301
-	 */
302
-	public function determineAttributes() {
303
-		if(!$this->checkRequirements(array('ldapHost',
304
-										   'ldapPort',
305
-										   'ldapBase',
306
-										   'ldapUserFilter',
307
-										   ))) {
308
-			return  false;
309
-		}
310
-
311
-		$attributes = $this->getUserAttributes();
312
-
313
-		natcasesort($attributes);
314
-		$attributes = array_values($attributes);
315
-
316
-		$this->result->addOptions('ldap_loginfilter_attributes', $attributes);
317
-
318
-		$selected = $this->configuration->ldapLoginFilterAttributes;
319
-		if(is_array($selected) && !empty($selected)) {
320
-			$this->result->addChange('ldap_loginfilter_attributes', $selected);
321
-		}
322
-
323
-		return $this->result;
324
-	}
325
-
326
-	/**
327
-	 * detects the available LDAP attributes
328
-	 * @return array|false The instance's WizardResult instance
329
-	 * @throws \Exception
330
-	 */
331
-	private function getUserAttributes() {
332
-		if(!$this->checkRequirements(array('ldapHost',
333
-										   'ldapPort',
334
-										   'ldapBase',
335
-										   'ldapUserFilter',
336
-										   ))) {
337
-			return  false;
338
-		}
339
-		$cr = $this->getConnection();
340
-		if(!$cr) {
341
-			throw new \Exception('Could not connect to LDAP');
342
-		}
343
-
344
-		$base = $this->configuration->ldapBase[0];
345
-		$filter = $this->configuration->ldapUserFilter;
346
-		$rr = $this->ldap->search($cr, $base, $filter, array(), 1, 1);
347
-		if(!$this->ldap->isResource($rr)) {
348
-			return false;
349
-		}
350
-		$er = $this->ldap->firstEntry($cr, $rr);
351
-		$attributes = $this->ldap->getAttributes($cr, $er);
352
-		$pureAttributes = array();
353
-		for($i = 0; $i < $attributes['count']; $i++) {
354
-			$pureAttributes[] = $attributes[$i];
355
-		}
356
-
357
-		return $pureAttributes;
358
-	}
359
-
360
-	/**
361
-	 * detects the available LDAP groups
362
-	 * @return WizardResult|false the instance's WizardResult instance
363
-	 */
364
-	public function determineGroupsForGroups() {
365
-		return $this->determineGroups('ldap_groupfilter_groups',
366
-									  'ldapGroupFilterGroups',
367
-									  false);
368
-	}
369
-
370
-	/**
371
-	 * detects the available LDAP groups
372
-	 * @return WizardResult|false the instance's WizardResult instance
373
-	 */
374
-	public function determineGroupsForUsers() {
375
-		return $this->determineGroups('ldap_userfilter_groups',
376
-									  'ldapUserFilterGroups');
377
-	}
378
-
379
-	/**
380
-	 * detects the available LDAP groups
381
-	 * @param string $dbKey
382
-	 * @param string $confKey
383
-	 * @param bool $testMemberOf
384
-	 * @return WizardResult|false the instance's WizardResult instance
385
-	 * @throws \Exception
386
-	 */
387
-	private function determineGroups($dbKey, $confKey, $testMemberOf = true) {
388
-		if(!$this->checkRequirements(array('ldapHost',
389
-										   'ldapPort',
390
-										   'ldapBase',
391
-										   ))) {
392
-			return  false;
393
-		}
394
-		$cr = $this->getConnection();
395
-		if(!$cr) {
396
-			throw new \Exception('Could not connect to LDAP');
397
-		}
398
-
399
-		$this->fetchGroups($dbKey, $confKey);
400
-
401
-		if($testMemberOf) {
402
-			$this->configuration->hasMemberOfFilterSupport = $this->testMemberOf();
403
-			$this->result->markChange();
404
-			if(!$this->configuration->hasMemberOfFilterSupport) {
405
-				throw new \Exception('memberOf is not supported by the server');
406
-			}
407
-		}
408
-
409
-		return $this->result;
410
-	}
411
-
412
-	/**
413
-	 * fetches all groups from LDAP and adds them to the result object
414
-	 *
415
-	 * @param string $dbKey
416
-	 * @param string $confKey
417
-	 * @return array $groupEntries
418
-	 * @throws \Exception
419
-	 */
420
-	public function fetchGroups($dbKey, $confKey) {
421
-		$obclasses = array('posixGroup', 'group', 'zimbraDistributionList', 'groupOfNames');
422
-
423
-		$filterParts = array();
424
-		foreach($obclasses as $obclass) {
425
-			$filterParts[] = 'objectclass='.$obclass;
426
-		}
427
-		//we filter for everything
428
-		//- that looks like a group and
429
-		//- has the group display name set
430
-		$filter = $this->access->combineFilterWithOr($filterParts);
431
-		$filter = $this->access->combineFilterWithAnd(array($filter, 'cn=*'));
432
-
433
-		$groupNames = array();
434
-		$groupEntries = array();
435
-		$limit = 400;
436
-		$offset = 0;
437
-		do {
438
-			// we need to request dn additionally here, otherwise memberOf
439
-			// detection will fail later
440
-			$result = $this->access->searchGroups($filter, array('cn', 'dn'), $limit, $offset);
441
-			foreach($result as $item) {
442
-				if(!isset($item['cn']) && !is_array($item['cn']) && !isset($item['cn'][0])) {
443
-					// just in case - no issue known
444
-					continue;
445
-				}
446
-				$groupNames[] = $item['cn'][0];
447
-				$groupEntries[] = $item;
448
-			}
449
-			$offset += $limit;
450
-		} while ($this->access->hasMoreResults());
451
-
452
-		if(count($groupNames) > 0) {
453
-			natsort($groupNames);
454
-			$this->result->addOptions($dbKey, array_values($groupNames));
455
-		} else {
456
-			throw new \Exception(self::$l->t('Could not find the desired feature'));
457
-		}
458
-
459
-		$setFeatures = $this->configuration->$confKey;
460
-		if(is_array($setFeatures) && !empty($setFeatures)) {
461
-			//something is already configured? pre-select it.
462
-			$this->result->addChange($dbKey, $setFeatures);
463
-		}
464
-		return $groupEntries;
465
-	}
466
-
467
-	public function determineGroupMemberAssoc() {
468
-		if(!$this->checkRequirements(array('ldapHost',
469
-										   'ldapPort',
470
-										   'ldapGroupFilter',
471
-										   ))) {
472
-			return  false;
473
-		}
474
-		$attribute = $this->detectGroupMemberAssoc();
475
-		if($attribute === false) {
476
-			return false;
477
-		}
478
-		$this->configuration->setConfiguration(array('ldapGroupMemberAssocAttr' => $attribute));
479
-		$this->result->addChange('ldap_group_member_assoc_attribute', $attribute);
480
-
481
-		return $this->result;
482
-	}
483
-
484
-	/**
485
-	 * Detects the available object classes
486
-	 * @return WizardResult|false the instance's WizardResult instance
487
-	 * @throws \Exception
488
-	 */
489
-	public function determineGroupObjectClasses() {
490
-		if(!$this->checkRequirements(array('ldapHost',
491
-										   'ldapPort',
492
-										   'ldapBase',
493
-										   ))) {
494
-			return  false;
495
-		}
496
-		$cr = $this->getConnection();
497
-		if(!$cr) {
498
-			throw new \Exception('Could not connect to LDAP');
499
-		}
500
-
501
-		$obclasses = array('groupOfNames', 'groupOfUniqueNames', 'group', 'posixGroup', '*');
502
-		$this->determineFeature($obclasses,
503
-								'objectclass',
504
-								'ldap_groupfilter_objectclass',
505
-								'ldapGroupFilterObjectclass',
506
-								false);
507
-
508
-		return $this->result;
509
-	}
510
-
511
-	/**
512
-	 * detects the available object classes
513
-	 * @return WizardResult
514
-	 * @throws \Exception
515
-	 */
516
-	public function determineUserObjectClasses() {
517
-		if(!$this->checkRequirements(array('ldapHost',
518
-										   'ldapPort',
519
-										   'ldapBase',
520
-										   ))) {
521
-			return  false;
522
-		}
523
-		$cr = $this->getConnection();
524
-		if(!$cr) {
525
-			throw new \Exception('Could not connect to LDAP');
526
-		}
527
-
528
-		$obclasses = array('inetOrgPerson', 'person', 'organizationalPerson',
529
-						   'user', 'posixAccount', '*');
530
-		$filter = $this->configuration->ldapUserFilter;
531
-		//if filter is empty, it is probably the first time the wizard is called
532
-		//then, apply suggestions.
533
-		$this->determineFeature($obclasses,
534
-								'objectclass',
535
-								'ldap_userfilter_objectclass',
536
-								'ldapUserFilterObjectclass',
537
-								empty($filter));
538
-
539
-		return $this->result;
540
-	}
541
-
542
-	/**
543
-	 * @return WizardResult|false
544
-	 * @throws \Exception
545
-	 */
546
-	public function getGroupFilter() {
547
-		if(!$this->checkRequirements(array('ldapHost',
548
-										   'ldapPort',
549
-										   'ldapBase',
550
-										   ))) {
551
-			return false;
552
-		}
553
-		//make sure the use display name is set
554
-		$displayName = $this->configuration->ldapGroupDisplayName;
555
-		if ($displayName === '') {
556
-			$d = $this->configuration->getDefaults();
557
-			$this->applyFind('ldap_group_display_name',
558
-							 $d['ldap_group_display_name']);
559
-		}
560
-		$filter = $this->composeLdapFilter(self::LFILTER_GROUP_LIST);
561
-
562
-		$this->applyFind('ldap_group_filter', $filter);
563
-		return $this->result;
564
-	}
565
-
566
-	/**
567
-	 * @return WizardResult|false
568
-	 * @throws \Exception
569
-	 */
570
-	public function getUserListFilter() {
571
-		if(!$this->checkRequirements(array('ldapHost',
572
-										   'ldapPort',
573
-										   'ldapBase',
574
-										   ))) {
575
-			return false;
576
-		}
577
-		//make sure the use display name is set
578
-		$displayName = $this->configuration->ldapUserDisplayName;
579
-		if ($displayName === '') {
580
-			$d = $this->configuration->getDefaults();
581
-			$this->applyFind('ldap_display_name', $d['ldap_display_name']);
582
-		}
583
-		$filter = $this->composeLdapFilter(self::LFILTER_USER_LIST);
584
-		if(!$filter) {
585
-			throw new \Exception('Cannot create filter');
586
-		}
587
-
588
-		$this->applyFind('ldap_userlist_filter', $filter);
589
-		return $this->result;
590
-	}
591
-
592
-	/**
593
-	 * @return bool|WizardResult
594
-	 * @throws \Exception
595
-	 */
596
-	public function getUserLoginFilter() {
597
-		if(!$this->checkRequirements(array('ldapHost',
598
-										   'ldapPort',
599
-										   'ldapBase',
600
-										   'ldapUserFilter',
601
-										   ))) {
602
-			return false;
603
-		}
604
-
605
-		$filter = $this->composeLdapFilter(self::LFILTER_LOGIN);
606
-		if(!$filter) {
607
-			throw new \Exception('Cannot create filter');
608
-		}
609
-
610
-		$this->applyFind('ldap_login_filter', $filter);
611
-		return $this->result;
612
-	}
613
-
614
-	/**
615
-	 * @return bool|WizardResult
616
-	 * @param string $loginName
617
-	 * @throws \Exception
618
-	 */
619
-	public function testLoginName($loginName) {
620
-		if(!$this->checkRequirements(array('ldapHost',
621
-			'ldapPort',
622
-			'ldapBase',
623
-			'ldapLoginFilter',
624
-		))) {
625
-			return false;
626
-		}
627
-
628
-		$cr = $this->access->connection->getConnectionResource();
629
-		if(!$this->ldap->isResource($cr)) {
630
-			throw new \Exception('connection error');
631
-		}
632
-
633
-		if(mb_strpos($this->access->connection->ldapLoginFilter, '%uid', 0, 'UTF-8')
634
-			=== false) {
635
-			throw new \Exception('missing placeholder');
636
-		}
637
-
638
-		$users = $this->access->countUsersByLoginName($loginName);
639
-		if($this->ldap->errno($cr) !== 0) {
640
-			throw new \Exception($this->ldap->error($cr));
641
-		}
642
-		$filter = str_replace('%uid', $loginName, $this->access->connection->ldapLoginFilter);
643
-		$this->result->addChange('ldap_test_loginname', $users);
644
-		$this->result->addChange('ldap_test_effective_filter', $filter);
645
-		return $this->result;
646
-	}
647
-
648
-	/**
649
-	 * Tries to determine the port, requires given Host, User DN and Password
650
-	 * @return WizardResult|false WizardResult on success, false otherwise
651
-	 * @throws \Exception
652
-	 */
653
-	public function guessPortAndTLS() {
654
-		if(!$this->checkRequirements(array('ldapHost',
655
-										   ))) {
656
-			return false;
657
-		}
658
-		$this->checkHost();
659
-		$portSettings = $this->getPortSettingsToTry();
660
-
661
-		if(!is_array($portSettings)) {
662
-			throw new \Exception(print_r($portSettings, true));
663
-		}
664
-
665
-		//proceed from the best configuration and return on first success
666
-		foreach($portSettings as $setting) {
667
-			$p = $setting['port'];
668
-			$t = $setting['tls'];
669
-			\OCP\Util::writeLog('user_ldap', 'Wiz: trying port '. $p . ', TLS '. $t, \OCP\Util::DEBUG);
670
-			//connectAndBind may throw Exception, it needs to be catched by the
671
-			//callee of this method
672
-
673
-			try {
674
-				$settingsFound = $this->connectAndBind($p, $t);
675
-			} catch (\Exception $e) {
676
-				// any reply other than -1 (= cannot connect) is already okay,
677
-				// because then we found the server
678
-				// unavailable startTLS returns -11
679
-				if($e->getCode() > 0) {
680
-					$settingsFound = true;
681
-				} else {
682
-					throw $e;
683
-				}
684
-			}
685
-
686
-			if ($settingsFound === true) {
687
-				$config = array(
688
-					'ldapPort' => $p,
689
-					'ldapTLS' => intval($t)
690
-				);
691
-				$this->configuration->setConfiguration($config);
692
-				\OCP\Util::writeLog('user_ldap', 'Wiz: detected Port ' . $p, \OCP\Util::DEBUG);
693
-				$this->result->addChange('ldap_port', $p);
694
-				return $this->result;
695
-			}
696
-		}
697
-
698
-		//custom port, undetected (we do not brute force)
699
-		return false;
700
-	}
701
-
702
-	/**
703
-	 * tries to determine a base dn from User DN or LDAP Host
704
-	 * @return WizardResult|false WizardResult on success, false otherwise
705
-	 */
706
-	public function guessBaseDN() {
707
-		if(!$this->checkRequirements(array('ldapHost',
708
-										   'ldapPort',
709
-										   ))) {
710
-			return false;
711
-		}
712
-
713
-		//check whether a DN is given in the agent name (99.9% of all cases)
714
-		$base = null;
715
-		$i = stripos($this->configuration->ldapAgentName, 'dc=');
716
-		if($i !== false) {
717
-			$base = substr($this->configuration->ldapAgentName, $i);
718
-			if($this->testBaseDN($base)) {
719
-				$this->applyFind('ldap_base', $base);
720
-				return $this->result;
721
-			}
722
-		}
723
-
724
-		//this did not help :(
725
-		//Let's see whether we can parse the Host URL and convert the domain to
726
-		//a base DN
727
-		$helper = new Helper(\OC::$server->getConfig());
728
-		$domain = $helper->getDomainFromURL($this->configuration->ldapHost);
729
-		if(!$domain) {
730
-			return false;
731
-		}
732
-
733
-		$dparts = explode('.', $domain);
734
-		while(count($dparts) > 0) {
735
-			$base2 = 'dc=' . implode(',dc=', $dparts);
736
-			if ($base !== $base2 && $this->testBaseDN($base2)) {
737
-				$this->applyFind('ldap_base', $base2);
738
-				return $this->result;
739
-			}
740
-			array_shift($dparts);
741
-		}
742
-
743
-		return false;
744
-	}
745
-
746
-	/**
747
-	 * sets the found value for the configuration key in the WizardResult
748
-	 * as well as in the Configuration instance
749
-	 * @param string $key the configuration key
750
-	 * @param string $value the (detected) value
751
-	 *
752
-	 */
753
-	private function applyFind($key, $value) {
754
-		$this->result->addChange($key, $value);
755
-		$this->configuration->setConfiguration(array($key => $value));
756
-	}
757
-
758
-	/**
759
-	 * Checks, whether a port was entered in the Host configuration
760
-	 * field. In this case the port will be stripped off, but also stored as
761
-	 * setting.
762
-	 */
763
-	private function checkHost() {
764
-		$host = $this->configuration->ldapHost;
765
-		$hostInfo = parse_url($host);
766
-
767
-		//removes Port from Host
768
-		if(is_array($hostInfo) && isset($hostInfo['port'])) {
769
-			$port = $hostInfo['port'];
770
-			$host = str_replace(':'.$port, '', $host);
771
-			$this->applyFind('ldap_host', $host);
772
-			$this->applyFind('ldap_port', $port);
773
-		}
774
-	}
775
-
776
-	/**
777
-	 * tries to detect the group member association attribute which is
778
-	 * one of 'uniqueMember', 'memberUid', 'member'
779
-	 * @return string|false, string with the attribute name, false on error
780
-	 * @throws \Exception
781
-	 */
782
-	private function detectGroupMemberAssoc() {
783
-		$possibleAttrs = array('uniqueMember', 'memberUid', 'member');
784
-		$filter = $this->configuration->ldapGroupFilter;
785
-		if(empty($filter)) {
786
-			return false;
787
-		}
788
-		$cr = $this->getConnection();
789
-		if(!$cr) {
790
-			throw new \Exception('Could not connect to LDAP');
791
-		}
792
-		$base = $this->configuration->ldapBase[0];
793
-		$rr = $this->ldap->search($cr, $base, $filter, $possibleAttrs, 0, 1000);
794
-		if(!$this->ldap->isResource($rr)) {
795
-			return false;
796
-		}
797
-		$er = $this->ldap->firstEntry($cr, $rr);
798
-		while(is_resource($er)) {
799
-			$this->ldap->getDN($cr, $er);
800
-			$attrs = $this->ldap->getAttributes($cr, $er);
801
-			$result = array();
802
-			$possibleAttrsCount = count($possibleAttrs);
803
-			for($i = 0; $i < $possibleAttrsCount; $i++) {
804
-				if(isset($attrs[$possibleAttrs[$i]])) {
805
-					$result[$possibleAttrs[$i]] = $attrs[$possibleAttrs[$i]]['count'];
806
-				}
807
-			}
808
-			if(!empty($result)) {
809
-				natsort($result);
810
-				return key($result);
811
-			}
812
-
813
-			$er = $this->ldap->nextEntry($cr, $er);
814
-		}
815
-
816
-		return false;
817
-	}
818
-
819
-	/**
820
-	 * Checks whether for a given BaseDN results will be returned
821
-	 * @param string $base the BaseDN to test
822
-	 * @return bool true on success, false otherwise
823
-	 * @throws \Exception
824
-	 */
825
-	private function testBaseDN($base) {
826
-		$cr = $this->getConnection();
827
-		if(!$cr) {
828
-			throw new \Exception('Could not connect to LDAP');
829
-		}
830
-
831
-		//base is there, let's validate it. If we search for anything, we should
832
-		//get a result set > 0 on a proper base
833
-		$rr = $this->ldap->search($cr, $base, 'objectClass=*', array('dn'), 0, 1);
834
-		if(!$this->ldap->isResource($rr)) {
835
-			$errorNo  = $this->ldap->errno($cr);
836
-			$errorMsg = $this->ldap->error($cr);
837
-			\OCP\Util::writeLog('user_ldap', 'Wiz: Could not search base '.$base.
838
-							' Error '.$errorNo.': '.$errorMsg, \OCP\Util::INFO);
839
-			return false;
840
-		}
841
-		$entries = $this->ldap->countEntries($cr, $rr);
842
-		return ($entries !== false) && ($entries > 0);
843
-	}
844
-
845
-	/**
846
-	 * Checks whether the server supports memberOf in LDAP Filter.
847
-	 * Note: at least in OpenLDAP, availability of memberOf is dependent on
848
-	 * a configured objectClass. I.e. not necessarily for all available groups
849
-	 * memberOf does work.
850
-	 *
851
-	 * @return bool true if it does, false otherwise
852
-	 * @throws \Exception
853
-	 */
854
-	private function testMemberOf() {
855
-		$cr = $this->getConnection();
856
-		if(!$cr) {
857
-			throw new \Exception('Could not connect to LDAP');
858
-		}
859
-		$result = $this->access->countUsers('memberOf=*', array('memberOf'), 1);
860
-		if(is_int($result) &&  $result > 0) {
861
-			return true;
862
-		}
863
-		return false;
864
-	}
865
-
866
-	/**
867
-	 * creates an LDAP Filter from given configuration
868
-	 * @param integer $filterType int, for which use case the filter shall be created
869
-	 * can be any of self::LFILTER_USER_LIST, self::LFILTER_LOGIN or
870
-	 * self::LFILTER_GROUP_LIST
871
-	 * @return string|false string with the filter on success, false otherwise
872
-	 * @throws \Exception
873
-	 */
874
-	private function composeLdapFilter($filterType) {
875
-		$filter = '';
876
-		$parts = 0;
877
-		switch ($filterType) {
878
-			case self::LFILTER_USER_LIST:
879
-				$objcs = $this->configuration->ldapUserFilterObjectclass;
880
-				//glue objectclasses
881
-				if(is_array($objcs) && count($objcs) > 0) {
882
-					$filter .= '(|';
883
-					foreach($objcs as $objc) {
884
-						$filter .= '(objectclass=' . $objc . ')';
885
-					}
886
-					$filter .= ')';
887
-					$parts++;
888
-				}
889
-				//glue group memberships
890
-				if($this->configuration->hasMemberOfFilterSupport) {
891
-					$cns = $this->configuration->ldapUserFilterGroups;
892
-					if(is_array($cns) && count($cns) > 0) {
893
-						$filter .= '(|';
894
-						$cr = $this->getConnection();
895
-						if(!$cr) {
896
-							throw new \Exception('Could not connect to LDAP');
897
-						}
898
-						$base = $this->configuration->ldapBase[0];
899
-						foreach($cns as $cn) {
900
-							$rr = $this->ldap->search($cr, $base, 'cn=' . $cn, array('dn', 'primaryGroupToken'));
901
-							if(!$this->ldap->isResource($rr)) {
902
-								continue;
903
-							}
904
-							$er = $this->ldap->firstEntry($cr, $rr);
905
-							$attrs = $this->ldap->getAttributes($cr, $er);
906
-							$dn = $this->ldap->getDN($cr, $er);
907
-							if ($dn == false || $dn === '') {
908
-								continue;
909
-							}
910
-							$filterPart = '(memberof=' . $dn . ')';
911
-							if(isset($attrs['primaryGroupToken'])) {
912
-								$pgt = $attrs['primaryGroupToken'][0];
913
-								$primaryFilterPart = '(primaryGroupID=' . $pgt .')';
914
-								$filterPart = '(|' . $filterPart . $primaryFilterPart . ')';
915
-							}
916
-							$filter .= $filterPart;
917
-						}
918
-						$filter .= ')';
919
-					}
920
-					$parts++;
921
-				}
922
-				//wrap parts in AND condition
923
-				if($parts > 1) {
924
-					$filter = '(&' . $filter . ')';
925
-				}
926
-				if ($filter === '') {
927
-					$filter = '(objectclass=*)';
928
-				}
929
-				break;
930
-
931
-			case self::LFILTER_GROUP_LIST:
932
-				$objcs = $this->configuration->ldapGroupFilterObjectclass;
933
-				//glue objectclasses
934
-				if(is_array($objcs) && count($objcs) > 0) {
935
-					$filter .= '(|';
936
-					foreach($objcs as $objc) {
937
-						$filter .= '(objectclass=' . $objc . ')';
938
-					}
939
-					$filter .= ')';
940
-					$parts++;
941
-				}
942
-				//glue group memberships
943
-				$cns = $this->configuration->ldapGroupFilterGroups;
944
-				if(is_array($cns) && count($cns) > 0) {
945
-					$filter .= '(|';
946
-					foreach($cns as $cn) {
947
-						$filter .= '(cn=' . $cn . ')';
948
-					}
949
-					$filter .= ')';
950
-				}
951
-				$parts++;
952
-				//wrap parts in AND condition
953
-				if($parts > 1) {
954
-					$filter = '(&' . $filter . ')';
955
-				}
956
-				break;
957
-
958
-			case self::LFILTER_LOGIN:
959
-				$ulf = $this->configuration->ldapUserFilter;
960
-				$loginpart = '=%uid';
961
-				$filterUsername = '';
962
-				$userAttributes = $this->getUserAttributes();
963
-				$userAttributes = array_change_key_case(array_flip($userAttributes));
964
-				$parts = 0;
965
-
966
-				if($this->configuration->ldapLoginFilterUsername === '1') {
967
-					$attr = '';
968
-					if(isset($userAttributes['uid'])) {
969
-						$attr = 'uid';
970
-					} else if(isset($userAttributes['samaccountname'])) {
971
-						$attr = 'samaccountname';
972
-					} else if(isset($userAttributes['cn'])) {
973
-						//fallback
974
-						$attr = 'cn';
975
-					}
976
-					if ($attr !== '') {
977
-						$filterUsername = '(' . $attr . $loginpart . ')';
978
-						$parts++;
979
-					}
980
-				}
981
-
982
-				$filterEmail = '';
983
-				if($this->configuration->ldapLoginFilterEmail === '1') {
984
-					$filterEmail = '(|(mailPrimaryAddress=%uid)(mail=%uid))';
985
-					$parts++;
986
-				}
987
-
988
-				$filterAttributes = '';
989
-				$attrsToFilter = $this->configuration->ldapLoginFilterAttributes;
990
-				if(is_array($attrsToFilter) && count($attrsToFilter) > 0) {
991
-					$filterAttributes = '(|';
992
-					foreach($attrsToFilter as $attribute) {
993
-						$filterAttributes .= '(' . $attribute . $loginpart . ')';
994
-					}
995
-					$filterAttributes .= ')';
996
-					$parts++;
997
-				}
998
-
999
-				$filterLogin = '';
1000
-				if($parts > 1) {
1001
-					$filterLogin = '(|';
1002
-				}
1003
-				$filterLogin .= $filterUsername;
1004
-				$filterLogin .= $filterEmail;
1005
-				$filterLogin .= $filterAttributes;
1006
-				if($parts > 1) {
1007
-					$filterLogin .= ')';
1008
-				}
1009
-
1010
-				$filter = '(&'.$ulf.$filterLogin.')';
1011
-				break;
1012
-		}
1013
-
1014
-		\OCP\Util::writeLog('user_ldap', 'Wiz: Final filter '.$filter, \OCP\Util::DEBUG);
1015
-
1016
-		return $filter;
1017
-	}
1018
-
1019
-	/**
1020
-	 * Connects and Binds to an LDAP Server
1021
-	 * @param int $port the port to connect with
1022
-	 * @param bool $tls whether startTLS is to be used
1023
-	 * @param bool $ncc
1024
-	 * @return bool
1025
-	 * @throws \Exception
1026
-	 */
1027
-	private function connectAndBind($port = 389, $tls = false, $ncc = false) {
1028
-		if($ncc) {
1029
-			//No certificate check
1030
-			//FIXME: undo afterwards
1031
-			putenv('LDAPTLS_REQCERT=never');
1032
-		}
1033
-
1034
-		//connect, does not really trigger any server communication
1035
-		\OCP\Util::writeLog('user_ldap', 'Wiz: Checking Host Info ', \OCP\Util::DEBUG);
1036
-		$host = $this->configuration->ldapHost;
1037
-		$hostInfo = parse_url($host);
1038
-		if(!$hostInfo) {
1039
-			throw new \Exception(self::$l->t('Invalid Host'));
1040
-		}
1041
-		\OCP\Util::writeLog('user_ldap', 'Wiz: Attempting to connect ', \OCP\Util::DEBUG);
1042
-		$cr = $this->ldap->connect($host, $port);
1043
-		if(!is_resource($cr)) {
1044
-			throw new \Exception(self::$l->t('Invalid Host'));
1045
-		}
1046
-
1047
-		\OCP\Util::writeLog('user_ldap', 'Wiz: Setting LDAP Options ', \OCP\Util::DEBUG);
1048
-		//set LDAP options
1049
-		$this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3);
1050
-		$this->ldap->setOption($cr, LDAP_OPT_REFERRALS, 0);
1051
-		$this->ldap->setOption($cr, LDAP_OPT_NETWORK_TIMEOUT, self::LDAP_NW_TIMEOUT);
1052
-
1053
-		try {
1054
-			if($tls) {
1055
-				$isTlsWorking = @$this->ldap->startTls($cr);
1056
-				if(!$isTlsWorking) {
1057
-					return false;
1058
-				}
1059
-			}
1060
-
1061
-			\OCP\Util::writeLog('user_ldap', 'Wiz: Attemping to Bind ', \OCP\Util::DEBUG);
1062
-			//interesting part: do the bind!
1063
-			$login = $this->ldap->bind($cr,
1064
-				$this->configuration->ldapAgentName,
1065
-				$this->configuration->ldapAgentPassword
1066
-			);
1067
-			$errNo = $this->ldap->errno($cr);
1068
-			$error = ldap_error($cr);
1069
-			$this->ldap->unbind($cr);
1070
-		} catch(ServerNotAvailableException $e) {
1071
-			return false;
1072
-		}
1073
-
1074
-		if($login === true) {
1075
-			$this->ldap->unbind($cr);
1076
-			if($ncc) {
1077
-				throw new \Exception('Certificate cannot be validated.');
1078
-			}
1079
-			\OCP\Util::writeLog('user_ldap', 'Wiz: Bind successful to Port '. $port . ' TLS ' . intval($tls), \OCP\Util::DEBUG);
1080
-			return true;
1081
-		}
1082
-
1083
-		if($errNo === -1 || ($errNo === 2 && $ncc)) {
1084
-			//host, port or TLS wrong
1085
-			return false;
1086
-		} else if ($errNo === 2) {
1087
-			return $this->connectAndBind($port, $tls, true);
1088
-		}
1089
-		throw new \Exception($error, $errNo);
1090
-	}
1091
-
1092
-	/**
1093
-	 * checks whether a valid combination of agent and password has been
1094
-	 * provided (either two values or nothing for anonymous connect)
1095
-	 * @return bool, true if everything is fine, false otherwise
1096
-	 */
1097
-	private function checkAgentRequirements() {
1098
-		$agent = $this->configuration->ldapAgentName;
1099
-		$pwd = $this->configuration->ldapAgentPassword;
1100
-
1101
-		return
1102
-			($agent !== '' && $pwd !== '')
1103
-			||  ($agent === '' && $pwd === '')
1104
-		;
1105
-	}
1106
-
1107
-	/**
1108
-	 * @param array $reqs
1109
-	 * @return bool
1110
-	 */
1111
-	private function checkRequirements($reqs) {
1112
-		$this->checkAgentRequirements();
1113
-		foreach($reqs as $option) {
1114
-			$value = $this->configuration->$option;
1115
-			if(empty($value)) {
1116
-				return false;
1117
-			}
1118
-		}
1119
-		return true;
1120
-	}
1121
-
1122
-	/**
1123
-	 * does a cumulativeSearch on LDAP to get different values of a
1124
-	 * specified attribute
1125
-	 * @param string[] $filters array, the filters that shall be used in the search
1126
-	 * @param string $attr the attribute of which a list of values shall be returned
1127
-	 * @param int $dnReadLimit the amount of how many DNs should be analyzed.
1128
-	 * The lower, the faster
1129
-	 * @param string $maxF string. if not null, this variable will have the filter that
1130
-	 * yields most result entries
1131
-	 * @return array|false an array with the values on success, false otherwise
1132
-	 */
1133
-	public function cumulativeSearchOnAttribute($filters, $attr, $dnReadLimit = 3, &$maxF = null) {
1134
-		$dnRead = array();
1135
-		$foundItems = array();
1136
-		$maxEntries = 0;
1137
-		if(!is_array($this->configuration->ldapBase)
1138
-		   || !isset($this->configuration->ldapBase[0])) {
1139
-			return false;
1140
-		}
1141
-		$base = $this->configuration->ldapBase[0];
1142
-		$cr = $this->getConnection();
1143
-		if(!$this->ldap->isResource($cr)) {
1144
-			return false;
1145
-		}
1146
-		$lastFilter = null;
1147
-		if(isset($filters[count($filters)-1])) {
1148
-			$lastFilter = $filters[count($filters)-1];
1149
-		}
1150
-		foreach($filters as $filter) {
1151
-			if($lastFilter === $filter && count($foundItems) > 0) {
1152
-				//skip when the filter is a wildcard and results were found
1153
-				continue;
1154
-			}
1155
-			// 20k limit for performance and reason
1156
-			$rr = $this->ldap->search($cr, $base, $filter, array($attr), 0, 20000);
1157
-			if(!$this->ldap->isResource($rr)) {
1158
-				continue;
1159
-			}
1160
-			$entries = $this->ldap->countEntries($cr, $rr);
1161
-			$getEntryFunc = 'firstEntry';
1162
-			if(($entries !== false) && ($entries > 0)) {
1163
-				if(!is_null($maxF) && $entries > $maxEntries) {
1164
-					$maxEntries = $entries;
1165
-					$maxF = $filter;
1166
-				}
1167
-				$dnReadCount = 0;
1168
-				do {
1169
-					$entry = $this->ldap->$getEntryFunc($cr, $rr);
1170
-					$getEntryFunc = 'nextEntry';
1171
-					if(!$this->ldap->isResource($entry)) {
1172
-						continue 2;
1173
-					}
1174
-					$rr = $entry; //will be expected by nextEntry next round
1175
-					$attributes = $this->ldap->getAttributes($cr, $entry);
1176
-					$dn = $this->ldap->getDN($cr, $entry);
1177
-					if($dn === false || in_array($dn, $dnRead)) {
1178
-						continue;
1179
-					}
1180
-					$newItems = array();
1181
-					$state = $this->getAttributeValuesFromEntry($attributes,
1182
-																$attr,
1183
-																$newItems);
1184
-					$dnReadCount++;
1185
-					$foundItems = array_merge($foundItems, $newItems);
1186
-					$this->resultCache[$dn][$attr] = $newItems;
1187
-					$dnRead[] = $dn;
1188
-				} while(($state === self::LRESULT_PROCESSED_SKIP
1189
-						|| $this->ldap->isResource($entry))
1190
-						&& ($dnReadLimit === 0 || $dnReadCount < $dnReadLimit));
1191
-			}
1192
-		}
1193
-
1194
-		return array_unique($foundItems);
1195
-	}
1196
-
1197
-	/**
1198
-	 * determines if and which $attr are available on the LDAP server
1199
-	 * @param string[] $objectclasses the objectclasses to use as search filter
1200
-	 * @param string $attr the attribute to look for
1201
-	 * @param string $dbkey the dbkey of the setting the feature is connected to
1202
-	 * @param string $confkey the confkey counterpart for the $dbkey as used in the
1203
-	 * Configuration class
1204
-	 * @param bool $po whether the objectClass with most result entries
1205
-	 * shall be pre-selected via the result
1206
-	 * @return array|false list of found items.
1207
-	 * @throws \Exception
1208
-	 */
1209
-	private function determineFeature($objectclasses, $attr, $dbkey, $confkey, $po = false) {
1210
-		$cr = $this->getConnection();
1211
-		if(!$cr) {
1212
-			throw new \Exception('Could not connect to LDAP');
1213
-		}
1214
-		$p = 'objectclass=';
1215
-		foreach($objectclasses as $key => $value) {
1216
-			$objectclasses[$key] = $p.$value;
1217
-		}
1218
-		$maxEntryObjC = '';
1219
-
1220
-		//how deep to dig?
1221
-		//When looking for objectclasses, testing few entries is sufficient,
1222
-		$dig = 3;
1223
-
1224
-		$availableFeatures =
1225
-			$this->cumulativeSearchOnAttribute($objectclasses, $attr,
1226
-											   $dig, $maxEntryObjC);
1227
-		if(is_array($availableFeatures)
1228
-		   && count($availableFeatures) > 0) {
1229
-			natcasesort($availableFeatures);
1230
-			//natcasesort keeps indices, but we must get rid of them for proper
1231
-			//sorting in the web UI. Therefore: array_values
1232
-			$this->result->addOptions($dbkey, array_values($availableFeatures));
1233
-		} else {
1234
-			throw new \Exception(self::$l->t('Could not find the desired feature'));
1235
-		}
1236
-
1237
-		$setFeatures = $this->configuration->$confkey;
1238
-		if(is_array($setFeatures) && !empty($setFeatures)) {
1239
-			//something is already configured? pre-select it.
1240
-			$this->result->addChange($dbkey, $setFeatures);
1241
-		} else if ($po && $maxEntryObjC !== '') {
1242
-			//pre-select objectclass with most result entries
1243
-			$maxEntryObjC = str_replace($p, '', $maxEntryObjC);
1244
-			$this->applyFind($dbkey, $maxEntryObjC);
1245
-			$this->result->addChange($dbkey, $maxEntryObjC);
1246
-		}
1247
-
1248
-		return $availableFeatures;
1249
-	}
1250
-
1251
-	/**
1252
-	 * appends a list of values fr
1253
-	 * @param resource $result the return value from ldap_get_attributes
1254
-	 * @param string $attribute the attribute values to look for
1255
-	 * @param array &$known new values will be appended here
1256
-	 * @return int, state on of the class constants LRESULT_PROCESSED_OK,
1257
-	 * LRESULT_PROCESSED_INVALID or LRESULT_PROCESSED_SKIP
1258
-	 */
1259
-	private function getAttributeValuesFromEntry($result, $attribute, &$known) {
1260
-		if(!is_array($result)
1261
-		   || !isset($result['count'])
1262
-		   || !$result['count'] > 0) {
1263
-			return self::LRESULT_PROCESSED_INVALID;
1264
-		}
1265
-
1266
-		// strtolower on all keys for proper comparison
1267
-		$result = \OCP\Util::mb_array_change_key_case($result);
1268
-		$attribute = strtolower($attribute);
1269
-		if(isset($result[$attribute])) {
1270
-			foreach($result[$attribute] as $key => $val) {
1271
-				if($key === 'count') {
1272
-					continue;
1273
-				}
1274
-				if(!in_array($val, $known)) {
1275
-					$known[] = $val;
1276
-				}
1277
-			}
1278
-			return self::LRESULT_PROCESSED_OK;
1279
-		} else {
1280
-			return self::LRESULT_PROCESSED_SKIP;
1281
-		}
1282
-	}
1283
-
1284
-	/**
1285
-	 * @return bool|mixed
1286
-	 */
1287
-	private function getConnection() {
1288
-		if(!is_null($this->cr)) {
1289
-			return $this->cr;
1290
-		}
1291
-
1292
-		$cr = $this->ldap->connect(
1293
-			$this->configuration->ldapHost,
1294
-			$this->configuration->ldapPort
1295
-		);
1296
-
1297
-		$this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3);
1298
-		$this->ldap->setOption($cr, LDAP_OPT_REFERRALS, 0);
1299
-		$this->ldap->setOption($cr, LDAP_OPT_NETWORK_TIMEOUT, self::LDAP_NW_TIMEOUT);
1300
-		if($this->configuration->ldapTLS === 1) {
1301
-			$this->ldap->startTls($cr);
1302
-		}
1303
-
1304
-		$lo = @$this->ldap->bind($cr,
1305
-								 $this->configuration->ldapAgentName,
1306
-								 $this->configuration->ldapAgentPassword);
1307
-		if($lo === true) {
1308
-			$this->$cr = $cr;
1309
-			return $cr;
1310
-		}
1311
-
1312
-		return false;
1313
-	}
1314
-
1315
-	/**
1316
-	 * @return array
1317
-	 */
1318
-	private function getDefaultLdapPortSettings() {
1319
-		static $settings = array(
1320
-								array('port' => 7636, 'tls' => false),
1321
-								array('port' =>  636, 'tls' => false),
1322
-								array('port' => 7389, 'tls' => true),
1323
-								array('port' =>  389, 'tls' => true),
1324
-								array('port' => 7389, 'tls' => false),
1325
-								array('port' =>  389, 'tls' => false),
1326
-						  );
1327
-		return $settings;
1328
-	}
1329
-
1330
-	/**
1331
-	 * @return array
1332
-	 */
1333
-	private function getPortSettingsToTry() {
1334
-		//389 ← LDAP / Unencrypted or StartTLS
1335
-		//636 ← LDAPS / SSL
1336
-		//7xxx ← UCS. need to be checked first, because both ports may be open
1337
-		$host = $this->configuration->ldapHost;
1338
-		$port = intval($this->configuration->ldapPort);
1339
-		$portSettings = array();
1340
-
1341
-		//In case the port is already provided, we will check this first
1342
-		if($port > 0) {
1343
-			$hostInfo = parse_url($host);
1344
-			if(!(is_array($hostInfo)
1345
-				&& isset($hostInfo['scheme'])
1346
-				&& stripos($hostInfo['scheme'], 'ldaps') !== false)) {
1347
-				$portSettings[] = array('port' => $port, 'tls' => true);
1348
-			}
1349
-			$portSettings[] =array('port' => $port, 'tls' => false);
1350
-		}
1351
-
1352
-		//default ports
1353
-		$portSettings = array_merge($portSettings,
1354
-		                            $this->getDefaultLdapPortSettings());
1355
-
1356
-		return $portSettings;
1357
-	}
40
+    /** @var \OCP\IL10N */
41
+    static protected $l;
42
+    protected $access;
43
+    protected $cr;
44
+    protected $configuration;
45
+    protected $result;
46
+    protected $resultCache = array();
47
+
48
+    const LRESULT_PROCESSED_OK = 2;
49
+    const LRESULT_PROCESSED_INVALID = 3;
50
+    const LRESULT_PROCESSED_SKIP = 4;
51
+
52
+    const LFILTER_LOGIN      = 2;
53
+    const LFILTER_USER_LIST  = 3;
54
+    const LFILTER_GROUP_LIST = 4;
55
+
56
+    const LFILTER_MODE_ASSISTED = 2;
57
+    const LFILTER_MODE_RAW = 1;
58
+
59
+    const LDAP_NW_TIMEOUT = 4;
60
+
61
+    /**
62
+     * Constructor
63
+     * @param Configuration $configuration an instance of Configuration
64
+     * @param ILDAPWrapper $ldap an instance of ILDAPWrapper
65
+     * @param Access $access
66
+     */
67
+    public function __construct(Configuration $configuration, ILDAPWrapper $ldap, Access $access) {
68
+        parent::__construct($ldap);
69
+        $this->configuration = $configuration;
70
+        if(is_null(Wizard::$l)) {
71
+            Wizard::$l = \OC::$server->getL10N('user_ldap');
72
+        }
73
+        $this->access = $access;
74
+        $this->result = new WizardResult();
75
+    }
76
+
77
+    public function  __destruct() {
78
+        if($this->result->hasChanges()) {
79
+            $this->configuration->saveConfiguration();
80
+        }
81
+    }
82
+
83
+    /**
84
+     * counts entries in the LDAP directory
85
+     *
86
+     * @param string $filter the LDAP search filter
87
+     * @param string $type a string being either 'users' or 'groups';
88
+     * @return bool|int
89
+     * @throws \Exception
90
+     */
91
+    public function countEntries($filter, $type) {
92
+        $reqs = array('ldapHost', 'ldapPort', 'ldapBase');
93
+        if($type === 'users') {
94
+            $reqs[] = 'ldapUserFilter';
95
+        }
96
+        if(!$this->checkRequirements($reqs)) {
97
+            throw new \Exception('Requirements not met', 400);
98
+        }
99
+
100
+        $attr = array('dn'); // default
101
+        $limit = 1001;
102
+        if($type === 'groups') {
103
+            $result =  $this->access->countGroups($filter, $attr, $limit);
104
+        } else if($type === 'users') {
105
+            $result = $this->access->countUsers($filter, $attr, $limit);
106
+        } else if ($type === 'objects') {
107
+            $result = $this->access->countObjects($limit);
108
+        } else {
109
+            throw new \Exception('internal error: invalid object type', 500);
110
+        }
111
+
112
+        return $result;
113
+    }
114
+
115
+    /**
116
+     * formats the return value of a count operation to the string to be
117
+     * inserted.
118
+     *
119
+     * @param bool|int $count
120
+     * @return int|string
121
+     */
122
+    private function formatCountResult($count) {
123
+        $formatted = ($count !== false) ? $count : 0;
124
+        if($formatted > 1000) {
125
+            $formatted = '> 1000';
126
+        }
127
+        return $formatted;
128
+    }
129
+
130
+    public function countGroups() {
131
+        $filter = $this->configuration->ldapGroupFilter;
132
+
133
+        if(empty($filter)) {
134
+            $output = self::$l->n('%s group found', '%s groups found', 0, array(0));
135
+            $this->result->addChange('ldap_group_count', $output);
136
+            return $this->result;
137
+        }
138
+
139
+        try {
140
+            $groupsTotal = $this->formatCountResult($this->countEntries($filter, 'groups'));
141
+        } catch (\Exception $e) {
142
+            //400 can be ignored, 500 is forwarded
143
+            if($e->getCode() === 500) {
144
+                throw $e;
145
+            }
146
+            return false;
147
+        }
148
+        $output = self::$l->n('%s group found', '%s groups found', $groupsTotal, array($groupsTotal));
149
+        $this->result->addChange('ldap_group_count', $output);
150
+        return $this->result;
151
+    }
152
+
153
+    /**
154
+     * @return WizardResult
155
+     * @throws \Exception
156
+     */
157
+    public function countUsers() {
158
+        $filter = $this->access->getFilterForUserCount();
159
+
160
+        $usersTotal = $this->formatCountResult($this->countEntries($filter, 'users'));
161
+        $output = self::$l->n('%s user found', '%s users found', $usersTotal, array($usersTotal));
162
+        $this->result->addChange('ldap_user_count', $output);
163
+        return $this->result;
164
+    }
165
+
166
+    /**
167
+     * counts any objects in the currently set base dn
168
+     *
169
+     * @return WizardResult
170
+     * @throws \Exception
171
+     */
172
+    public function countInBaseDN() {
173
+        // we don't need to provide a filter in this case
174
+        $total = $this->countEntries(null, 'objects');
175
+        if($total === false) {
176
+            throw new \Exception('invalid results received');
177
+        }
178
+        $this->result->addChange('ldap_test_base', $total);
179
+        return $this->result;
180
+    }
181
+
182
+    /**
183
+     * counts users with a specified attribute
184
+     * @param string $attr
185
+     * @param bool $existsCheck
186
+     * @return int|bool
187
+     */
188
+    public function countUsersWithAttribute($attr, $existsCheck = false) {
189
+        if(!$this->checkRequirements(array('ldapHost',
190
+                                            'ldapPort',
191
+                                            'ldapBase',
192
+                                            'ldapUserFilter',
193
+                                            ))) {
194
+            return  false;
195
+        }
196
+
197
+        $filter = $this->access->combineFilterWithAnd(array(
198
+            $this->configuration->ldapUserFilter,
199
+            $attr . '=*'
200
+        ));
201
+
202
+        $limit = ($existsCheck === false) ? null : 1;
203
+
204
+        return $this->access->countUsers($filter, array('dn'), $limit);
205
+    }
206
+
207
+    /**
208
+     * detects the display name attribute. If a setting is already present that
209
+     * returns at least one hit, the detection will be canceled.
210
+     * @return WizardResult|bool
211
+     * @throws \Exception
212
+     */
213
+    public function detectUserDisplayNameAttribute() {
214
+        if(!$this->checkRequirements(array('ldapHost',
215
+                                        'ldapPort',
216
+                                        'ldapBase',
217
+                                        'ldapUserFilter',
218
+                                        ))) {
219
+            return  false;
220
+        }
221
+
222
+        $attr = $this->configuration->ldapUserDisplayName;
223
+        if ($attr !== '' && $attr !== 'displayName') {
224
+            // most likely not the default value with upper case N,
225
+            // verify it still produces a result
226
+            $count = intval($this->countUsersWithAttribute($attr, true));
227
+            if($count > 0) {
228
+                //no change, but we sent it back to make sure the user interface
229
+                //is still correct, even if the ajax call was cancelled meanwhile
230
+                $this->result->addChange('ldap_display_name', $attr);
231
+                return $this->result;
232
+            }
233
+        }
234
+
235
+        // first attribute that has at least one result wins
236
+        $displayNameAttrs = array('displayname', 'cn');
237
+        foreach ($displayNameAttrs as $attr) {
238
+            $count = intval($this->countUsersWithAttribute($attr, true));
239
+
240
+            if($count > 0) {
241
+                $this->applyFind('ldap_display_name', $attr);
242
+                return $this->result;
243
+            }
244
+        };
245
+
246
+        throw new \Exception(self::$l->t('Could not detect user display name attribute. Please specify it yourself in advanced ldap settings.'));
247
+    }
248
+
249
+    /**
250
+     * detects the most often used email attribute for users applying to the
251
+     * user list filter. If a setting is already present that returns at least
252
+     * one hit, the detection will be canceled.
253
+     * @return WizardResult|bool
254
+     */
255
+    public function detectEmailAttribute() {
256
+        if(!$this->checkRequirements(array('ldapHost',
257
+                                            'ldapPort',
258
+                                            'ldapBase',
259
+                                            'ldapUserFilter',
260
+                                            ))) {
261
+            return  false;
262
+        }
263
+
264
+        $attr = $this->configuration->ldapEmailAttribute;
265
+        if ($attr !== '') {
266
+            $count = intval($this->countUsersWithAttribute($attr, true));
267
+            if($count > 0) {
268
+                return false;
269
+            }
270
+            $writeLog = true;
271
+        } else {
272
+            $writeLog = false;
273
+        }
274
+
275
+        $emailAttributes = array('mail', 'mailPrimaryAddress');
276
+        $winner = '';
277
+        $maxUsers = 0;
278
+        foreach($emailAttributes as $attr) {
279
+            $count = $this->countUsersWithAttribute($attr);
280
+            if($count > $maxUsers) {
281
+                $maxUsers = $count;
282
+                $winner = $attr;
283
+            }
284
+        }
285
+
286
+        if($winner !== '') {
287
+            $this->applyFind('ldap_email_attr', $winner);
288
+            if($writeLog) {
289
+                \OCP\Util::writeLog('user_ldap', 'The mail attribute has ' .
290
+                    'automatically been reset, because the original value ' .
291
+                    'did not return any results.', \OCP\Util::INFO);
292
+            }
293
+        }
294
+
295
+        return $this->result;
296
+    }
297
+
298
+    /**
299
+     * @return WizardResult
300
+     * @throws \Exception
301
+     */
302
+    public function determineAttributes() {
303
+        if(!$this->checkRequirements(array('ldapHost',
304
+                                            'ldapPort',
305
+                                            'ldapBase',
306
+                                            'ldapUserFilter',
307
+                                            ))) {
308
+            return  false;
309
+        }
310
+
311
+        $attributes = $this->getUserAttributes();
312
+
313
+        natcasesort($attributes);
314
+        $attributes = array_values($attributes);
315
+
316
+        $this->result->addOptions('ldap_loginfilter_attributes', $attributes);
317
+
318
+        $selected = $this->configuration->ldapLoginFilterAttributes;
319
+        if(is_array($selected) && !empty($selected)) {
320
+            $this->result->addChange('ldap_loginfilter_attributes', $selected);
321
+        }
322
+
323
+        return $this->result;
324
+    }
325
+
326
+    /**
327
+     * detects the available LDAP attributes
328
+     * @return array|false The instance's WizardResult instance
329
+     * @throws \Exception
330
+     */
331
+    private function getUserAttributes() {
332
+        if(!$this->checkRequirements(array('ldapHost',
333
+                                            'ldapPort',
334
+                                            'ldapBase',
335
+                                            'ldapUserFilter',
336
+                                            ))) {
337
+            return  false;
338
+        }
339
+        $cr = $this->getConnection();
340
+        if(!$cr) {
341
+            throw new \Exception('Could not connect to LDAP');
342
+        }
343
+
344
+        $base = $this->configuration->ldapBase[0];
345
+        $filter = $this->configuration->ldapUserFilter;
346
+        $rr = $this->ldap->search($cr, $base, $filter, array(), 1, 1);
347
+        if(!$this->ldap->isResource($rr)) {
348
+            return false;
349
+        }
350
+        $er = $this->ldap->firstEntry($cr, $rr);
351
+        $attributes = $this->ldap->getAttributes($cr, $er);
352
+        $pureAttributes = array();
353
+        for($i = 0; $i < $attributes['count']; $i++) {
354
+            $pureAttributes[] = $attributes[$i];
355
+        }
356
+
357
+        return $pureAttributes;
358
+    }
359
+
360
+    /**
361
+     * detects the available LDAP groups
362
+     * @return WizardResult|false the instance's WizardResult instance
363
+     */
364
+    public function determineGroupsForGroups() {
365
+        return $this->determineGroups('ldap_groupfilter_groups',
366
+                                        'ldapGroupFilterGroups',
367
+                                        false);
368
+    }
369
+
370
+    /**
371
+     * detects the available LDAP groups
372
+     * @return WizardResult|false the instance's WizardResult instance
373
+     */
374
+    public function determineGroupsForUsers() {
375
+        return $this->determineGroups('ldap_userfilter_groups',
376
+                                        'ldapUserFilterGroups');
377
+    }
378
+
379
+    /**
380
+     * detects the available LDAP groups
381
+     * @param string $dbKey
382
+     * @param string $confKey
383
+     * @param bool $testMemberOf
384
+     * @return WizardResult|false the instance's WizardResult instance
385
+     * @throws \Exception
386
+     */
387
+    private function determineGroups($dbKey, $confKey, $testMemberOf = true) {
388
+        if(!$this->checkRequirements(array('ldapHost',
389
+                                            'ldapPort',
390
+                                            'ldapBase',
391
+                                            ))) {
392
+            return  false;
393
+        }
394
+        $cr = $this->getConnection();
395
+        if(!$cr) {
396
+            throw new \Exception('Could not connect to LDAP');
397
+        }
398
+
399
+        $this->fetchGroups($dbKey, $confKey);
400
+
401
+        if($testMemberOf) {
402
+            $this->configuration->hasMemberOfFilterSupport = $this->testMemberOf();
403
+            $this->result->markChange();
404
+            if(!$this->configuration->hasMemberOfFilterSupport) {
405
+                throw new \Exception('memberOf is not supported by the server');
406
+            }
407
+        }
408
+
409
+        return $this->result;
410
+    }
411
+
412
+    /**
413
+     * fetches all groups from LDAP and adds them to the result object
414
+     *
415
+     * @param string $dbKey
416
+     * @param string $confKey
417
+     * @return array $groupEntries
418
+     * @throws \Exception
419
+     */
420
+    public function fetchGroups($dbKey, $confKey) {
421
+        $obclasses = array('posixGroup', 'group', 'zimbraDistributionList', 'groupOfNames');
422
+
423
+        $filterParts = array();
424
+        foreach($obclasses as $obclass) {
425
+            $filterParts[] = 'objectclass='.$obclass;
426
+        }
427
+        //we filter for everything
428
+        //- that looks like a group and
429
+        //- has the group display name set
430
+        $filter = $this->access->combineFilterWithOr($filterParts);
431
+        $filter = $this->access->combineFilterWithAnd(array($filter, 'cn=*'));
432
+
433
+        $groupNames = array();
434
+        $groupEntries = array();
435
+        $limit = 400;
436
+        $offset = 0;
437
+        do {
438
+            // we need to request dn additionally here, otherwise memberOf
439
+            // detection will fail later
440
+            $result = $this->access->searchGroups($filter, array('cn', 'dn'), $limit, $offset);
441
+            foreach($result as $item) {
442
+                if(!isset($item['cn']) && !is_array($item['cn']) && !isset($item['cn'][0])) {
443
+                    // just in case - no issue known
444
+                    continue;
445
+                }
446
+                $groupNames[] = $item['cn'][0];
447
+                $groupEntries[] = $item;
448
+            }
449
+            $offset += $limit;
450
+        } while ($this->access->hasMoreResults());
451
+
452
+        if(count($groupNames) > 0) {
453
+            natsort($groupNames);
454
+            $this->result->addOptions($dbKey, array_values($groupNames));
455
+        } else {
456
+            throw new \Exception(self::$l->t('Could not find the desired feature'));
457
+        }
458
+
459
+        $setFeatures = $this->configuration->$confKey;
460
+        if(is_array($setFeatures) && !empty($setFeatures)) {
461
+            //something is already configured? pre-select it.
462
+            $this->result->addChange($dbKey, $setFeatures);
463
+        }
464
+        return $groupEntries;
465
+    }
466
+
467
+    public function determineGroupMemberAssoc() {
468
+        if(!$this->checkRequirements(array('ldapHost',
469
+                                            'ldapPort',
470
+                                            'ldapGroupFilter',
471
+                                            ))) {
472
+            return  false;
473
+        }
474
+        $attribute = $this->detectGroupMemberAssoc();
475
+        if($attribute === false) {
476
+            return false;
477
+        }
478
+        $this->configuration->setConfiguration(array('ldapGroupMemberAssocAttr' => $attribute));
479
+        $this->result->addChange('ldap_group_member_assoc_attribute', $attribute);
480
+
481
+        return $this->result;
482
+    }
483
+
484
+    /**
485
+     * Detects the available object classes
486
+     * @return WizardResult|false the instance's WizardResult instance
487
+     * @throws \Exception
488
+     */
489
+    public function determineGroupObjectClasses() {
490
+        if(!$this->checkRequirements(array('ldapHost',
491
+                                            'ldapPort',
492
+                                            'ldapBase',
493
+                                            ))) {
494
+            return  false;
495
+        }
496
+        $cr = $this->getConnection();
497
+        if(!$cr) {
498
+            throw new \Exception('Could not connect to LDAP');
499
+        }
500
+
501
+        $obclasses = array('groupOfNames', 'groupOfUniqueNames', 'group', 'posixGroup', '*');
502
+        $this->determineFeature($obclasses,
503
+                                'objectclass',
504
+                                'ldap_groupfilter_objectclass',
505
+                                'ldapGroupFilterObjectclass',
506
+                                false);
507
+
508
+        return $this->result;
509
+    }
510
+
511
+    /**
512
+     * detects the available object classes
513
+     * @return WizardResult
514
+     * @throws \Exception
515
+     */
516
+    public function determineUserObjectClasses() {
517
+        if(!$this->checkRequirements(array('ldapHost',
518
+                                            'ldapPort',
519
+                                            'ldapBase',
520
+                                            ))) {
521
+            return  false;
522
+        }
523
+        $cr = $this->getConnection();
524
+        if(!$cr) {
525
+            throw new \Exception('Could not connect to LDAP');
526
+        }
527
+
528
+        $obclasses = array('inetOrgPerson', 'person', 'organizationalPerson',
529
+                            'user', 'posixAccount', '*');
530
+        $filter = $this->configuration->ldapUserFilter;
531
+        //if filter is empty, it is probably the first time the wizard is called
532
+        //then, apply suggestions.
533
+        $this->determineFeature($obclasses,
534
+                                'objectclass',
535
+                                'ldap_userfilter_objectclass',
536
+                                'ldapUserFilterObjectclass',
537
+                                empty($filter));
538
+
539
+        return $this->result;
540
+    }
541
+
542
+    /**
543
+     * @return WizardResult|false
544
+     * @throws \Exception
545
+     */
546
+    public function getGroupFilter() {
547
+        if(!$this->checkRequirements(array('ldapHost',
548
+                                            'ldapPort',
549
+                                            'ldapBase',
550
+                                            ))) {
551
+            return false;
552
+        }
553
+        //make sure the use display name is set
554
+        $displayName = $this->configuration->ldapGroupDisplayName;
555
+        if ($displayName === '') {
556
+            $d = $this->configuration->getDefaults();
557
+            $this->applyFind('ldap_group_display_name',
558
+                                $d['ldap_group_display_name']);
559
+        }
560
+        $filter = $this->composeLdapFilter(self::LFILTER_GROUP_LIST);
561
+
562
+        $this->applyFind('ldap_group_filter', $filter);
563
+        return $this->result;
564
+    }
565
+
566
+    /**
567
+     * @return WizardResult|false
568
+     * @throws \Exception
569
+     */
570
+    public function getUserListFilter() {
571
+        if(!$this->checkRequirements(array('ldapHost',
572
+                                            'ldapPort',
573
+                                            'ldapBase',
574
+                                            ))) {
575
+            return false;
576
+        }
577
+        //make sure the use display name is set
578
+        $displayName = $this->configuration->ldapUserDisplayName;
579
+        if ($displayName === '') {
580
+            $d = $this->configuration->getDefaults();
581
+            $this->applyFind('ldap_display_name', $d['ldap_display_name']);
582
+        }
583
+        $filter = $this->composeLdapFilter(self::LFILTER_USER_LIST);
584
+        if(!$filter) {
585
+            throw new \Exception('Cannot create filter');
586
+        }
587
+
588
+        $this->applyFind('ldap_userlist_filter', $filter);
589
+        return $this->result;
590
+    }
591
+
592
+    /**
593
+     * @return bool|WizardResult
594
+     * @throws \Exception
595
+     */
596
+    public function getUserLoginFilter() {
597
+        if(!$this->checkRequirements(array('ldapHost',
598
+                                            'ldapPort',
599
+                                            'ldapBase',
600
+                                            'ldapUserFilter',
601
+                                            ))) {
602
+            return false;
603
+        }
604
+
605
+        $filter = $this->composeLdapFilter(self::LFILTER_LOGIN);
606
+        if(!$filter) {
607
+            throw new \Exception('Cannot create filter');
608
+        }
609
+
610
+        $this->applyFind('ldap_login_filter', $filter);
611
+        return $this->result;
612
+    }
613
+
614
+    /**
615
+     * @return bool|WizardResult
616
+     * @param string $loginName
617
+     * @throws \Exception
618
+     */
619
+    public function testLoginName($loginName) {
620
+        if(!$this->checkRequirements(array('ldapHost',
621
+            'ldapPort',
622
+            'ldapBase',
623
+            'ldapLoginFilter',
624
+        ))) {
625
+            return false;
626
+        }
627
+
628
+        $cr = $this->access->connection->getConnectionResource();
629
+        if(!$this->ldap->isResource($cr)) {
630
+            throw new \Exception('connection error');
631
+        }
632
+
633
+        if(mb_strpos($this->access->connection->ldapLoginFilter, '%uid', 0, 'UTF-8')
634
+            === false) {
635
+            throw new \Exception('missing placeholder');
636
+        }
637
+
638
+        $users = $this->access->countUsersByLoginName($loginName);
639
+        if($this->ldap->errno($cr) !== 0) {
640
+            throw new \Exception($this->ldap->error($cr));
641
+        }
642
+        $filter = str_replace('%uid', $loginName, $this->access->connection->ldapLoginFilter);
643
+        $this->result->addChange('ldap_test_loginname', $users);
644
+        $this->result->addChange('ldap_test_effective_filter', $filter);
645
+        return $this->result;
646
+    }
647
+
648
+    /**
649
+     * Tries to determine the port, requires given Host, User DN and Password
650
+     * @return WizardResult|false WizardResult on success, false otherwise
651
+     * @throws \Exception
652
+     */
653
+    public function guessPortAndTLS() {
654
+        if(!$this->checkRequirements(array('ldapHost',
655
+                                            ))) {
656
+            return false;
657
+        }
658
+        $this->checkHost();
659
+        $portSettings = $this->getPortSettingsToTry();
660
+
661
+        if(!is_array($portSettings)) {
662
+            throw new \Exception(print_r($portSettings, true));
663
+        }
664
+
665
+        //proceed from the best configuration and return on first success
666
+        foreach($portSettings as $setting) {
667
+            $p = $setting['port'];
668
+            $t = $setting['tls'];
669
+            \OCP\Util::writeLog('user_ldap', 'Wiz: trying port '. $p . ', TLS '. $t, \OCP\Util::DEBUG);
670
+            //connectAndBind may throw Exception, it needs to be catched by the
671
+            //callee of this method
672
+
673
+            try {
674
+                $settingsFound = $this->connectAndBind($p, $t);
675
+            } catch (\Exception $e) {
676
+                // any reply other than -1 (= cannot connect) is already okay,
677
+                // because then we found the server
678
+                // unavailable startTLS returns -11
679
+                if($e->getCode() > 0) {
680
+                    $settingsFound = true;
681
+                } else {
682
+                    throw $e;
683
+                }
684
+            }
685
+
686
+            if ($settingsFound === true) {
687
+                $config = array(
688
+                    'ldapPort' => $p,
689
+                    'ldapTLS' => intval($t)
690
+                );
691
+                $this->configuration->setConfiguration($config);
692
+                \OCP\Util::writeLog('user_ldap', 'Wiz: detected Port ' . $p, \OCP\Util::DEBUG);
693
+                $this->result->addChange('ldap_port', $p);
694
+                return $this->result;
695
+            }
696
+        }
697
+
698
+        //custom port, undetected (we do not brute force)
699
+        return false;
700
+    }
701
+
702
+    /**
703
+     * tries to determine a base dn from User DN or LDAP Host
704
+     * @return WizardResult|false WizardResult on success, false otherwise
705
+     */
706
+    public function guessBaseDN() {
707
+        if(!$this->checkRequirements(array('ldapHost',
708
+                                            'ldapPort',
709
+                                            ))) {
710
+            return false;
711
+        }
712
+
713
+        //check whether a DN is given in the agent name (99.9% of all cases)
714
+        $base = null;
715
+        $i = stripos($this->configuration->ldapAgentName, 'dc=');
716
+        if($i !== false) {
717
+            $base = substr($this->configuration->ldapAgentName, $i);
718
+            if($this->testBaseDN($base)) {
719
+                $this->applyFind('ldap_base', $base);
720
+                return $this->result;
721
+            }
722
+        }
723
+
724
+        //this did not help :(
725
+        //Let's see whether we can parse the Host URL and convert the domain to
726
+        //a base DN
727
+        $helper = new Helper(\OC::$server->getConfig());
728
+        $domain = $helper->getDomainFromURL($this->configuration->ldapHost);
729
+        if(!$domain) {
730
+            return false;
731
+        }
732
+
733
+        $dparts = explode('.', $domain);
734
+        while(count($dparts) > 0) {
735
+            $base2 = 'dc=' . implode(',dc=', $dparts);
736
+            if ($base !== $base2 && $this->testBaseDN($base2)) {
737
+                $this->applyFind('ldap_base', $base2);
738
+                return $this->result;
739
+            }
740
+            array_shift($dparts);
741
+        }
742
+
743
+        return false;
744
+    }
745
+
746
+    /**
747
+     * sets the found value for the configuration key in the WizardResult
748
+     * as well as in the Configuration instance
749
+     * @param string $key the configuration key
750
+     * @param string $value the (detected) value
751
+     *
752
+     */
753
+    private function applyFind($key, $value) {
754
+        $this->result->addChange($key, $value);
755
+        $this->configuration->setConfiguration(array($key => $value));
756
+    }
757
+
758
+    /**
759
+     * Checks, whether a port was entered in the Host configuration
760
+     * field. In this case the port will be stripped off, but also stored as
761
+     * setting.
762
+     */
763
+    private function checkHost() {
764
+        $host = $this->configuration->ldapHost;
765
+        $hostInfo = parse_url($host);
766
+
767
+        //removes Port from Host
768
+        if(is_array($hostInfo) && isset($hostInfo['port'])) {
769
+            $port = $hostInfo['port'];
770
+            $host = str_replace(':'.$port, '', $host);
771
+            $this->applyFind('ldap_host', $host);
772
+            $this->applyFind('ldap_port', $port);
773
+        }
774
+    }
775
+
776
+    /**
777
+     * tries to detect the group member association attribute which is
778
+     * one of 'uniqueMember', 'memberUid', 'member'
779
+     * @return string|false, string with the attribute name, false on error
780
+     * @throws \Exception
781
+     */
782
+    private function detectGroupMemberAssoc() {
783
+        $possibleAttrs = array('uniqueMember', 'memberUid', 'member');
784
+        $filter = $this->configuration->ldapGroupFilter;
785
+        if(empty($filter)) {
786
+            return false;
787
+        }
788
+        $cr = $this->getConnection();
789
+        if(!$cr) {
790
+            throw new \Exception('Could not connect to LDAP');
791
+        }
792
+        $base = $this->configuration->ldapBase[0];
793
+        $rr = $this->ldap->search($cr, $base, $filter, $possibleAttrs, 0, 1000);
794
+        if(!$this->ldap->isResource($rr)) {
795
+            return false;
796
+        }
797
+        $er = $this->ldap->firstEntry($cr, $rr);
798
+        while(is_resource($er)) {
799
+            $this->ldap->getDN($cr, $er);
800
+            $attrs = $this->ldap->getAttributes($cr, $er);
801
+            $result = array();
802
+            $possibleAttrsCount = count($possibleAttrs);
803
+            for($i = 0; $i < $possibleAttrsCount; $i++) {
804
+                if(isset($attrs[$possibleAttrs[$i]])) {
805
+                    $result[$possibleAttrs[$i]] = $attrs[$possibleAttrs[$i]]['count'];
806
+                }
807
+            }
808
+            if(!empty($result)) {
809
+                natsort($result);
810
+                return key($result);
811
+            }
812
+
813
+            $er = $this->ldap->nextEntry($cr, $er);
814
+        }
815
+
816
+        return false;
817
+    }
818
+
819
+    /**
820
+     * Checks whether for a given BaseDN results will be returned
821
+     * @param string $base the BaseDN to test
822
+     * @return bool true on success, false otherwise
823
+     * @throws \Exception
824
+     */
825
+    private function testBaseDN($base) {
826
+        $cr = $this->getConnection();
827
+        if(!$cr) {
828
+            throw new \Exception('Could not connect to LDAP');
829
+        }
830
+
831
+        //base is there, let's validate it. If we search for anything, we should
832
+        //get a result set > 0 on a proper base
833
+        $rr = $this->ldap->search($cr, $base, 'objectClass=*', array('dn'), 0, 1);
834
+        if(!$this->ldap->isResource($rr)) {
835
+            $errorNo  = $this->ldap->errno($cr);
836
+            $errorMsg = $this->ldap->error($cr);
837
+            \OCP\Util::writeLog('user_ldap', 'Wiz: Could not search base '.$base.
838
+                            ' Error '.$errorNo.': '.$errorMsg, \OCP\Util::INFO);
839
+            return false;
840
+        }
841
+        $entries = $this->ldap->countEntries($cr, $rr);
842
+        return ($entries !== false) && ($entries > 0);
843
+    }
844
+
845
+    /**
846
+     * Checks whether the server supports memberOf in LDAP Filter.
847
+     * Note: at least in OpenLDAP, availability of memberOf is dependent on
848
+     * a configured objectClass. I.e. not necessarily for all available groups
849
+     * memberOf does work.
850
+     *
851
+     * @return bool true if it does, false otherwise
852
+     * @throws \Exception
853
+     */
854
+    private function testMemberOf() {
855
+        $cr = $this->getConnection();
856
+        if(!$cr) {
857
+            throw new \Exception('Could not connect to LDAP');
858
+        }
859
+        $result = $this->access->countUsers('memberOf=*', array('memberOf'), 1);
860
+        if(is_int($result) &&  $result > 0) {
861
+            return true;
862
+        }
863
+        return false;
864
+    }
865
+
866
+    /**
867
+     * creates an LDAP Filter from given configuration
868
+     * @param integer $filterType int, for which use case the filter shall be created
869
+     * can be any of self::LFILTER_USER_LIST, self::LFILTER_LOGIN or
870
+     * self::LFILTER_GROUP_LIST
871
+     * @return string|false string with the filter on success, false otherwise
872
+     * @throws \Exception
873
+     */
874
+    private function composeLdapFilter($filterType) {
875
+        $filter = '';
876
+        $parts = 0;
877
+        switch ($filterType) {
878
+            case self::LFILTER_USER_LIST:
879
+                $objcs = $this->configuration->ldapUserFilterObjectclass;
880
+                //glue objectclasses
881
+                if(is_array($objcs) && count($objcs) > 0) {
882
+                    $filter .= '(|';
883
+                    foreach($objcs as $objc) {
884
+                        $filter .= '(objectclass=' . $objc . ')';
885
+                    }
886
+                    $filter .= ')';
887
+                    $parts++;
888
+                }
889
+                //glue group memberships
890
+                if($this->configuration->hasMemberOfFilterSupport) {
891
+                    $cns = $this->configuration->ldapUserFilterGroups;
892
+                    if(is_array($cns) && count($cns) > 0) {
893
+                        $filter .= '(|';
894
+                        $cr = $this->getConnection();
895
+                        if(!$cr) {
896
+                            throw new \Exception('Could not connect to LDAP');
897
+                        }
898
+                        $base = $this->configuration->ldapBase[0];
899
+                        foreach($cns as $cn) {
900
+                            $rr = $this->ldap->search($cr, $base, 'cn=' . $cn, array('dn', 'primaryGroupToken'));
901
+                            if(!$this->ldap->isResource($rr)) {
902
+                                continue;
903
+                            }
904
+                            $er = $this->ldap->firstEntry($cr, $rr);
905
+                            $attrs = $this->ldap->getAttributes($cr, $er);
906
+                            $dn = $this->ldap->getDN($cr, $er);
907
+                            if ($dn == false || $dn === '') {
908
+                                continue;
909
+                            }
910
+                            $filterPart = '(memberof=' . $dn . ')';
911
+                            if(isset($attrs['primaryGroupToken'])) {
912
+                                $pgt = $attrs['primaryGroupToken'][0];
913
+                                $primaryFilterPart = '(primaryGroupID=' . $pgt .')';
914
+                                $filterPart = '(|' . $filterPart . $primaryFilterPart . ')';
915
+                            }
916
+                            $filter .= $filterPart;
917
+                        }
918
+                        $filter .= ')';
919
+                    }
920
+                    $parts++;
921
+                }
922
+                //wrap parts in AND condition
923
+                if($parts > 1) {
924
+                    $filter = '(&' . $filter . ')';
925
+                }
926
+                if ($filter === '') {
927
+                    $filter = '(objectclass=*)';
928
+                }
929
+                break;
930
+
931
+            case self::LFILTER_GROUP_LIST:
932
+                $objcs = $this->configuration->ldapGroupFilterObjectclass;
933
+                //glue objectclasses
934
+                if(is_array($objcs) && count($objcs) > 0) {
935
+                    $filter .= '(|';
936
+                    foreach($objcs as $objc) {
937
+                        $filter .= '(objectclass=' . $objc . ')';
938
+                    }
939
+                    $filter .= ')';
940
+                    $parts++;
941
+                }
942
+                //glue group memberships
943
+                $cns = $this->configuration->ldapGroupFilterGroups;
944
+                if(is_array($cns) && count($cns) > 0) {
945
+                    $filter .= '(|';
946
+                    foreach($cns as $cn) {
947
+                        $filter .= '(cn=' . $cn . ')';
948
+                    }
949
+                    $filter .= ')';
950
+                }
951
+                $parts++;
952
+                //wrap parts in AND condition
953
+                if($parts > 1) {
954
+                    $filter = '(&' . $filter . ')';
955
+                }
956
+                break;
957
+
958
+            case self::LFILTER_LOGIN:
959
+                $ulf = $this->configuration->ldapUserFilter;
960
+                $loginpart = '=%uid';
961
+                $filterUsername = '';
962
+                $userAttributes = $this->getUserAttributes();
963
+                $userAttributes = array_change_key_case(array_flip($userAttributes));
964
+                $parts = 0;
965
+
966
+                if($this->configuration->ldapLoginFilterUsername === '1') {
967
+                    $attr = '';
968
+                    if(isset($userAttributes['uid'])) {
969
+                        $attr = 'uid';
970
+                    } else if(isset($userAttributes['samaccountname'])) {
971
+                        $attr = 'samaccountname';
972
+                    } else if(isset($userAttributes['cn'])) {
973
+                        //fallback
974
+                        $attr = 'cn';
975
+                    }
976
+                    if ($attr !== '') {
977
+                        $filterUsername = '(' . $attr . $loginpart . ')';
978
+                        $parts++;
979
+                    }
980
+                }
981
+
982
+                $filterEmail = '';
983
+                if($this->configuration->ldapLoginFilterEmail === '1') {
984
+                    $filterEmail = '(|(mailPrimaryAddress=%uid)(mail=%uid))';
985
+                    $parts++;
986
+                }
987
+
988
+                $filterAttributes = '';
989
+                $attrsToFilter = $this->configuration->ldapLoginFilterAttributes;
990
+                if(is_array($attrsToFilter) && count($attrsToFilter) > 0) {
991
+                    $filterAttributes = '(|';
992
+                    foreach($attrsToFilter as $attribute) {
993
+                        $filterAttributes .= '(' . $attribute . $loginpart . ')';
994
+                    }
995
+                    $filterAttributes .= ')';
996
+                    $parts++;
997
+                }
998
+
999
+                $filterLogin = '';
1000
+                if($parts > 1) {
1001
+                    $filterLogin = '(|';
1002
+                }
1003
+                $filterLogin .= $filterUsername;
1004
+                $filterLogin .= $filterEmail;
1005
+                $filterLogin .= $filterAttributes;
1006
+                if($parts > 1) {
1007
+                    $filterLogin .= ')';
1008
+                }
1009
+
1010
+                $filter = '(&'.$ulf.$filterLogin.')';
1011
+                break;
1012
+        }
1013
+
1014
+        \OCP\Util::writeLog('user_ldap', 'Wiz: Final filter '.$filter, \OCP\Util::DEBUG);
1015
+
1016
+        return $filter;
1017
+    }
1018
+
1019
+    /**
1020
+     * Connects and Binds to an LDAP Server
1021
+     * @param int $port the port to connect with
1022
+     * @param bool $tls whether startTLS is to be used
1023
+     * @param bool $ncc
1024
+     * @return bool
1025
+     * @throws \Exception
1026
+     */
1027
+    private function connectAndBind($port = 389, $tls = false, $ncc = false) {
1028
+        if($ncc) {
1029
+            //No certificate check
1030
+            //FIXME: undo afterwards
1031
+            putenv('LDAPTLS_REQCERT=never');
1032
+        }
1033
+
1034
+        //connect, does not really trigger any server communication
1035
+        \OCP\Util::writeLog('user_ldap', 'Wiz: Checking Host Info ', \OCP\Util::DEBUG);
1036
+        $host = $this->configuration->ldapHost;
1037
+        $hostInfo = parse_url($host);
1038
+        if(!$hostInfo) {
1039
+            throw new \Exception(self::$l->t('Invalid Host'));
1040
+        }
1041
+        \OCP\Util::writeLog('user_ldap', 'Wiz: Attempting to connect ', \OCP\Util::DEBUG);
1042
+        $cr = $this->ldap->connect($host, $port);
1043
+        if(!is_resource($cr)) {
1044
+            throw new \Exception(self::$l->t('Invalid Host'));
1045
+        }
1046
+
1047
+        \OCP\Util::writeLog('user_ldap', 'Wiz: Setting LDAP Options ', \OCP\Util::DEBUG);
1048
+        //set LDAP options
1049
+        $this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3);
1050
+        $this->ldap->setOption($cr, LDAP_OPT_REFERRALS, 0);
1051
+        $this->ldap->setOption($cr, LDAP_OPT_NETWORK_TIMEOUT, self::LDAP_NW_TIMEOUT);
1052
+
1053
+        try {
1054
+            if($tls) {
1055
+                $isTlsWorking = @$this->ldap->startTls($cr);
1056
+                if(!$isTlsWorking) {
1057
+                    return false;
1058
+                }
1059
+            }
1060
+
1061
+            \OCP\Util::writeLog('user_ldap', 'Wiz: Attemping to Bind ', \OCP\Util::DEBUG);
1062
+            //interesting part: do the bind!
1063
+            $login = $this->ldap->bind($cr,
1064
+                $this->configuration->ldapAgentName,
1065
+                $this->configuration->ldapAgentPassword
1066
+            );
1067
+            $errNo = $this->ldap->errno($cr);
1068
+            $error = ldap_error($cr);
1069
+            $this->ldap->unbind($cr);
1070
+        } catch(ServerNotAvailableException $e) {
1071
+            return false;
1072
+        }
1073
+
1074
+        if($login === true) {
1075
+            $this->ldap->unbind($cr);
1076
+            if($ncc) {
1077
+                throw new \Exception('Certificate cannot be validated.');
1078
+            }
1079
+            \OCP\Util::writeLog('user_ldap', 'Wiz: Bind successful to Port '. $port . ' TLS ' . intval($tls), \OCP\Util::DEBUG);
1080
+            return true;
1081
+        }
1082
+
1083
+        if($errNo === -1 || ($errNo === 2 && $ncc)) {
1084
+            //host, port or TLS wrong
1085
+            return false;
1086
+        } else if ($errNo === 2) {
1087
+            return $this->connectAndBind($port, $tls, true);
1088
+        }
1089
+        throw new \Exception($error, $errNo);
1090
+    }
1091
+
1092
+    /**
1093
+     * checks whether a valid combination of agent and password has been
1094
+     * provided (either two values or nothing for anonymous connect)
1095
+     * @return bool, true if everything is fine, false otherwise
1096
+     */
1097
+    private function checkAgentRequirements() {
1098
+        $agent = $this->configuration->ldapAgentName;
1099
+        $pwd = $this->configuration->ldapAgentPassword;
1100
+
1101
+        return
1102
+            ($agent !== '' && $pwd !== '')
1103
+            ||  ($agent === '' && $pwd === '')
1104
+        ;
1105
+    }
1106
+
1107
+    /**
1108
+     * @param array $reqs
1109
+     * @return bool
1110
+     */
1111
+    private function checkRequirements($reqs) {
1112
+        $this->checkAgentRequirements();
1113
+        foreach($reqs as $option) {
1114
+            $value = $this->configuration->$option;
1115
+            if(empty($value)) {
1116
+                return false;
1117
+            }
1118
+        }
1119
+        return true;
1120
+    }
1121
+
1122
+    /**
1123
+     * does a cumulativeSearch on LDAP to get different values of a
1124
+     * specified attribute
1125
+     * @param string[] $filters array, the filters that shall be used in the search
1126
+     * @param string $attr the attribute of which a list of values shall be returned
1127
+     * @param int $dnReadLimit the amount of how many DNs should be analyzed.
1128
+     * The lower, the faster
1129
+     * @param string $maxF string. if not null, this variable will have the filter that
1130
+     * yields most result entries
1131
+     * @return array|false an array with the values on success, false otherwise
1132
+     */
1133
+    public function cumulativeSearchOnAttribute($filters, $attr, $dnReadLimit = 3, &$maxF = null) {
1134
+        $dnRead = array();
1135
+        $foundItems = array();
1136
+        $maxEntries = 0;
1137
+        if(!is_array($this->configuration->ldapBase)
1138
+           || !isset($this->configuration->ldapBase[0])) {
1139
+            return false;
1140
+        }
1141
+        $base = $this->configuration->ldapBase[0];
1142
+        $cr = $this->getConnection();
1143
+        if(!$this->ldap->isResource($cr)) {
1144
+            return false;
1145
+        }
1146
+        $lastFilter = null;
1147
+        if(isset($filters[count($filters)-1])) {
1148
+            $lastFilter = $filters[count($filters)-1];
1149
+        }
1150
+        foreach($filters as $filter) {
1151
+            if($lastFilter === $filter && count($foundItems) > 0) {
1152
+                //skip when the filter is a wildcard and results were found
1153
+                continue;
1154
+            }
1155
+            // 20k limit for performance and reason
1156
+            $rr = $this->ldap->search($cr, $base, $filter, array($attr), 0, 20000);
1157
+            if(!$this->ldap->isResource($rr)) {
1158
+                continue;
1159
+            }
1160
+            $entries = $this->ldap->countEntries($cr, $rr);
1161
+            $getEntryFunc = 'firstEntry';
1162
+            if(($entries !== false) && ($entries > 0)) {
1163
+                if(!is_null($maxF) && $entries > $maxEntries) {
1164
+                    $maxEntries = $entries;
1165
+                    $maxF = $filter;
1166
+                }
1167
+                $dnReadCount = 0;
1168
+                do {
1169
+                    $entry = $this->ldap->$getEntryFunc($cr, $rr);
1170
+                    $getEntryFunc = 'nextEntry';
1171
+                    if(!$this->ldap->isResource($entry)) {
1172
+                        continue 2;
1173
+                    }
1174
+                    $rr = $entry; //will be expected by nextEntry next round
1175
+                    $attributes = $this->ldap->getAttributes($cr, $entry);
1176
+                    $dn = $this->ldap->getDN($cr, $entry);
1177
+                    if($dn === false || in_array($dn, $dnRead)) {
1178
+                        continue;
1179
+                    }
1180
+                    $newItems = array();
1181
+                    $state = $this->getAttributeValuesFromEntry($attributes,
1182
+                                                                $attr,
1183
+                                                                $newItems);
1184
+                    $dnReadCount++;
1185
+                    $foundItems = array_merge($foundItems, $newItems);
1186
+                    $this->resultCache[$dn][$attr] = $newItems;
1187
+                    $dnRead[] = $dn;
1188
+                } while(($state === self::LRESULT_PROCESSED_SKIP
1189
+                        || $this->ldap->isResource($entry))
1190
+                        && ($dnReadLimit === 0 || $dnReadCount < $dnReadLimit));
1191
+            }
1192
+        }
1193
+
1194
+        return array_unique($foundItems);
1195
+    }
1196
+
1197
+    /**
1198
+     * determines if and which $attr are available on the LDAP server
1199
+     * @param string[] $objectclasses the objectclasses to use as search filter
1200
+     * @param string $attr the attribute to look for
1201
+     * @param string $dbkey the dbkey of the setting the feature is connected to
1202
+     * @param string $confkey the confkey counterpart for the $dbkey as used in the
1203
+     * Configuration class
1204
+     * @param bool $po whether the objectClass with most result entries
1205
+     * shall be pre-selected via the result
1206
+     * @return array|false list of found items.
1207
+     * @throws \Exception
1208
+     */
1209
+    private function determineFeature($objectclasses, $attr, $dbkey, $confkey, $po = false) {
1210
+        $cr = $this->getConnection();
1211
+        if(!$cr) {
1212
+            throw new \Exception('Could not connect to LDAP');
1213
+        }
1214
+        $p = 'objectclass=';
1215
+        foreach($objectclasses as $key => $value) {
1216
+            $objectclasses[$key] = $p.$value;
1217
+        }
1218
+        $maxEntryObjC = '';
1219
+
1220
+        //how deep to dig?
1221
+        //When looking for objectclasses, testing few entries is sufficient,
1222
+        $dig = 3;
1223
+
1224
+        $availableFeatures =
1225
+            $this->cumulativeSearchOnAttribute($objectclasses, $attr,
1226
+                                                $dig, $maxEntryObjC);
1227
+        if(is_array($availableFeatures)
1228
+           && count($availableFeatures) > 0) {
1229
+            natcasesort($availableFeatures);
1230
+            //natcasesort keeps indices, but we must get rid of them for proper
1231
+            //sorting in the web UI. Therefore: array_values
1232
+            $this->result->addOptions($dbkey, array_values($availableFeatures));
1233
+        } else {
1234
+            throw new \Exception(self::$l->t('Could not find the desired feature'));
1235
+        }
1236
+
1237
+        $setFeatures = $this->configuration->$confkey;
1238
+        if(is_array($setFeatures) && !empty($setFeatures)) {
1239
+            //something is already configured? pre-select it.
1240
+            $this->result->addChange($dbkey, $setFeatures);
1241
+        } else if ($po && $maxEntryObjC !== '') {
1242
+            //pre-select objectclass with most result entries
1243
+            $maxEntryObjC = str_replace($p, '', $maxEntryObjC);
1244
+            $this->applyFind($dbkey, $maxEntryObjC);
1245
+            $this->result->addChange($dbkey, $maxEntryObjC);
1246
+        }
1247
+
1248
+        return $availableFeatures;
1249
+    }
1250
+
1251
+    /**
1252
+     * appends a list of values fr
1253
+     * @param resource $result the return value from ldap_get_attributes
1254
+     * @param string $attribute the attribute values to look for
1255
+     * @param array &$known new values will be appended here
1256
+     * @return int, state on of the class constants LRESULT_PROCESSED_OK,
1257
+     * LRESULT_PROCESSED_INVALID or LRESULT_PROCESSED_SKIP
1258
+     */
1259
+    private function getAttributeValuesFromEntry($result, $attribute, &$known) {
1260
+        if(!is_array($result)
1261
+           || !isset($result['count'])
1262
+           || !$result['count'] > 0) {
1263
+            return self::LRESULT_PROCESSED_INVALID;
1264
+        }
1265
+
1266
+        // strtolower on all keys for proper comparison
1267
+        $result = \OCP\Util::mb_array_change_key_case($result);
1268
+        $attribute = strtolower($attribute);
1269
+        if(isset($result[$attribute])) {
1270
+            foreach($result[$attribute] as $key => $val) {
1271
+                if($key === 'count') {
1272
+                    continue;
1273
+                }
1274
+                if(!in_array($val, $known)) {
1275
+                    $known[] = $val;
1276
+                }
1277
+            }
1278
+            return self::LRESULT_PROCESSED_OK;
1279
+        } else {
1280
+            return self::LRESULT_PROCESSED_SKIP;
1281
+        }
1282
+    }
1283
+
1284
+    /**
1285
+     * @return bool|mixed
1286
+     */
1287
+    private function getConnection() {
1288
+        if(!is_null($this->cr)) {
1289
+            return $this->cr;
1290
+        }
1291
+
1292
+        $cr = $this->ldap->connect(
1293
+            $this->configuration->ldapHost,
1294
+            $this->configuration->ldapPort
1295
+        );
1296
+
1297
+        $this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3);
1298
+        $this->ldap->setOption($cr, LDAP_OPT_REFERRALS, 0);
1299
+        $this->ldap->setOption($cr, LDAP_OPT_NETWORK_TIMEOUT, self::LDAP_NW_TIMEOUT);
1300
+        if($this->configuration->ldapTLS === 1) {
1301
+            $this->ldap->startTls($cr);
1302
+        }
1303
+
1304
+        $lo = @$this->ldap->bind($cr,
1305
+                                    $this->configuration->ldapAgentName,
1306
+                                    $this->configuration->ldapAgentPassword);
1307
+        if($lo === true) {
1308
+            $this->$cr = $cr;
1309
+            return $cr;
1310
+        }
1311
+
1312
+        return false;
1313
+    }
1314
+
1315
+    /**
1316
+     * @return array
1317
+     */
1318
+    private function getDefaultLdapPortSettings() {
1319
+        static $settings = array(
1320
+                                array('port' => 7636, 'tls' => false),
1321
+                                array('port' =>  636, 'tls' => false),
1322
+                                array('port' => 7389, 'tls' => true),
1323
+                                array('port' =>  389, 'tls' => true),
1324
+                                array('port' => 7389, 'tls' => false),
1325
+                                array('port' =>  389, 'tls' => false),
1326
+                            );
1327
+        return $settings;
1328
+    }
1329
+
1330
+    /**
1331
+     * @return array
1332
+     */
1333
+    private function getPortSettingsToTry() {
1334
+        //389 ← LDAP / Unencrypted or StartTLS
1335
+        //636 ← LDAPS / SSL
1336
+        //7xxx ← UCS. need to be checked first, because both ports may be open
1337
+        $host = $this->configuration->ldapHost;
1338
+        $port = intval($this->configuration->ldapPort);
1339
+        $portSettings = array();
1340
+
1341
+        //In case the port is already provided, we will check this first
1342
+        if($port > 0) {
1343
+            $hostInfo = parse_url($host);
1344
+            if(!(is_array($hostInfo)
1345
+                && isset($hostInfo['scheme'])
1346
+                && stripos($hostInfo['scheme'], 'ldaps') !== false)) {
1347
+                $portSettings[] = array('port' => $port, 'tls' => true);
1348
+            }
1349
+            $portSettings[] =array('port' => $port, 'tls' => false);
1350
+        }
1351
+
1352
+        //default ports
1353
+        $portSettings = array_merge($portSettings,
1354
+                                    $this->getDefaultLdapPortSettings());
1355
+
1356
+        return $portSettings;
1357
+    }
1358 1358
 
1359 1359
 
1360 1360
 }
Please login to merge, or discard this patch.
Spacing   +151 added lines, -151 removed lines patch added patch discarded remove patch
@@ -67,7 +67,7 @@  discard block
 block discarded – undo
67 67
 	public function __construct(Configuration $configuration, ILDAPWrapper $ldap, Access $access) {
68 68
 		parent::__construct($ldap);
69 69
 		$this->configuration = $configuration;
70
-		if(is_null(Wizard::$l)) {
70
+		if (is_null(Wizard::$l)) {
71 71
 			Wizard::$l = \OC::$server->getL10N('user_ldap');
72 72
 		}
73 73
 		$this->access = $access;
@@ -75,7 +75,7 @@  discard block
 block discarded – undo
75 75
 	}
76 76
 
77 77
 	public function  __destruct() {
78
-		if($this->result->hasChanges()) {
78
+		if ($this->result->hasChanges()) {
79 79
 			$this->configuration->saveConfiguration();
80 80
 		}
81 81
 	}
@@ -90,18 +90,18 @@  discard block
 block discarded – undo
90 90
 	 */
91 91
 	public function countEntries($filter, $type) {
92 92
 		$reqs = array('ldapHost', 'ldapPort', 'ldapBase');
93
-		if($type === 'users') {
93
+		if ($type === 'users') {
94 94
 			$reqs[] = 'ldapUserFilter';
95 95
 		}
96
-		if(!$this->checkRequirements($reqs)) {
96
+		if (!$this->checkRequirements($reqs)) {
97 97
 			throw new \Exception('Requirements not met', 400);
98 98
 		}
99 99
 
100 100
 		$attr = array('dn'); // default
101 101
 		$limit = 1001;
102
-		if($type === 'groups') {
103
-			$result =  $this->access->countGroups($filter, $attr, $limit);
104
-		} else if($type === 'users') {
102
+		if ($type === 'groups') {
103
+			$result = $this->access->countGroups($filter, $attr, $limit);
104
+		} else if ($type === 'users') {
105 105
 			$result = $this->access->countUsers($filter, $attr, $limit);
106 106
 		} else if ($type === 'objects') {
107 107
 			$result = $this->access->countObjects($limit);
@@ -121,7 +121,7 @@  discard block
 block discarded – undo
121 121
 	 */
122 122
 	private function formatCountResult($count) {
123 123
 		$formatted = ($count !== false) ? $count : 0;
124
-		if($formatted > 1000) {
124
+		if ($formatted > 1000) {
125 125
 			$formatted = '> 1000';
126 126
 		}
127 127
 		return $formatted;
@@ -130,7 +130,7 @@  discard block
 block discarded – undo
130 130
 	public function countGroups() {
131 131
 		$filter = $this->configuration->ldapGroupFilter;
132 132
 
133
-		if(empty($filter)) {
133
+		if (empty($filter)) {
134 134
 			$output = self::$l->n('%s group found', '%s groups found', 0, array(0));
135 135
 			$this->result->addChange('ldap_group_count', $output);
136 136
 			return $this->result;
@@ -140,7 +140,7 @@  discard block
 block discarded – undo
140 140
 			$groupsTotal = $this->formatCountResult($this->countEntries($filter, 'groups'));
141 141
 		} catch (\Exception $e) {
142 142
 			//400 can be ignored, 500 is forwarded
143
-			if($e->getCode() === 500) {
143
+			if ($e->getCode() === 500) {
144 144
 				throw $e;
145 145
 			}
146 146
 			return false;
@@ -172,7 +172,7 @@  discard block
 block discarded – undo
172 172
 	public function countInBaseDN() {
173 173
 		// we don't need to provide a filter in this case
174 174
 		$total = $this->countEntries(null, 'objects');
175
-		if($total === false) {
175
+		if ($total === false) {
176 176
 			throw new \Exception('invalid results received');
177 177
 		}
178 178
 		$this->result->addChange('ldap_test_base', $total);
@@ -186,7 +186,7 @@  discard block
 block discarded – undo
186 186
 	 * @return int|bool
187 187
 	 */
188 188
 	public function countUsersWithAttribute($attr, $existsCheck = false) {
189
-		if(!$this->checkRequirements(array('ldapHost',
189
+		if (!$this->checkRequirements(array('ldapHost',
190 190
 										   'ldapPort',
191 191
 										   'ldapBase',
192 192
 										   'ldapUserFilter',
@@ -196,7 +196,7 @@  discard block
 block discarded – undo
196 196
 
197 197
 		$filter = $this->access->combineFilterWithAnd(array(
198 198
 			$this->configuration->ldapUserFilter,
199
-			$attr . '=*'
199
+			$attr.'=*'
200 200
 		));
201 201
 
202 202
 		$limit = ($existsCheck === false) ? null : 1;
@@ -211,7 +211,7 @@  discard block
 block discarded – undo
211 211
 	 * @throws \Exception
212 212
 	 */
213 213
 	public function detectUserDisplayNameAttribute() {
214
-		if(!$this->checkRequirements(array('ldapHost',
214
+		if (!$this->checkRequirements(array('ldapHost',
215 215
 										'ldapPort',
216 216
 										'ldapBase',
217 217
 										'ldapUserFilter',
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
 			// most likely not the default value with upper case N,
225 225
 			// verify it still produces a result
226 226
 			$count = intval($this->countUsersWithAttribute($attr, true));
227
-			if($count > 0) {
227
+			if ($count > 0) {
228 228
 				//no change, but we sent it back to make sure the user interface
229 229
 				//is still correct, even if the ajax call was cancelled meanwhile
230 230
 				$this->result->addChange('ldap_display_name', $attr);
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
 		foreach ($displayNameAttrs as $attr) {
238 238
 			$count = intval($this->countUsersWithAttribute($attr, true));
239 239
 
240
-			if($count > 0) {
240
+			if ($count > 0) {
241 241
 				$this->applyFind('ldap_display_name', $attr);
242 242
 				return $this->result;
243 243
 			}
@@ -253,7 +253,7 @@  discard block
 block discarded – undo
253 253
 	 * @return WizardResult|bool
254 254
 	 */
255 255
 	public function detectEmailAttribute() {
256
-		if(!$this->checkRequirements(array('ldapHost',
256
+		if (!$this->checkRequirements(array('ldapHost',
257 257
 										   'ldapPort',
258 258
 										   'ldapBase',
259 259
 										   'ldapUserFilter',
@@ -264,7 +264,7 @@  discard block
 block discarded – undo
264 264
 		$attr = $this->configuration->ldapEmailAttribute;
265 265
 		if ($attr !== '') {
266 266
 			$count = intval($this->countUsersWithAttribute($attr, true));
267
-			if($count > 0) {
267
+			if ($count > 0) {
268 268
 				return false;
269 269
 			}
270 270
 			$writeLog = true;
@@ -275,19 +275,19 @@  discard block
 block discarded – undo
275 275
 		$emailAttributes = array('mail', 'mailPrimaryAddress');
276 276
 		$winner = '';
277 277
 		$maxUsers = 0;
278
-		foreach($emailAttributes as $attr) {
278
+		foreach ($emailAttributes as $attr) {
279 279
 			$count = $this->countUsersWithAttribute($attr);
280
-			if($count > $maxUsers) {
280
+			if ($count > $maxUsers) {
281 281
 				$maxUsers = $count;
282 282
 				$winner = $attr;
283 283
 			}
284 284
 		}
285 285
 
286
-		if($winner !== '') {
286
+		if ($winner !== '') {
287 287
 			$this->applyFind('ldap_email_attr', $winner);
288
-			if($writeLog) {
289
-				\OCP\Util::writeLog('user_ldap', 'The mail attribute has ' .
290
-					'automatically been reset, because the original value ' .
288
+			if ($writeLog) {
289
+				\OCP\Util::writeLog('user_ldap', 'The mail attribute has '.
290
+					'automatically been reset, because the original value '.
291 291
 					'did not return any results.', \OCP\Util::INFO);
292 292
 			}
293 293
 		}
@@ -300,7 +300,7 @@  discard block
 block discarded – undo
300 300
 	 * @throws \Exception
301 301
 	 */
302 302
 	public function determineAttributes() {
303
-		if(!$this->checkRequirements(array('ldapHost',
303
+		if (!$this->checkRequirements(array('ldapHost',
304 304
 										   'ldapPort',
305 305
 										   'ldapBase',
306 306
 										   'ldapUserFilter',
@@ -316,7 +316,7 @@  discard block
 block discarded – undo
316 316
 		$this->result->addOptions('ldap_loginfilter_attributes', $attributes);
317 317
 
318 318
 		$selected = $this->configuration->ldapLoginFilterAttributes;
319
-		if(is_array($selected) && !empty($selected)) {
319
+		if (is_array($selected) && !empty($selected)) {
320 320
 			$this->result->addChange('ldap_loginfilter_attributes', $selected);
321 321
 		}
322 322
 
@@ -329,7 +329,7 @@  discard block
 block discarded – undo
329 329
 	 * @throws \Exception
330 330
 	 */
331 331
 	private function getUserAttributes() {
332
-		if(!$this->checkRequirements(array('ldapHost',
332
+		if (!$this->checkRequirements(array('ldapHost',
333 333
 										   'ldapPort',
334 334
 										   'ldapBase',
335 335
 										   'ldapUserFilter',
@@ -337,20 +337,20 @@  discard block
 block discarded – undo
337 337
 			return  false;
338 338
 		}
339 339
 		$cr = $this->getConnection();
340
-		if(!$cr) {
340
+		if (!$cr) {
341 341
 			throw new \Exception('Could not connect to LDAP');
342 342
 		}
343 343
 
344 344
 		$base = $this->configuration->ldapBase[0];
345 345
 		$filter = $this->configuration->ldapUserFilter;
346 346
 		$rr = $this->ldap->search($cr, $base, $filter, array(), 1, 1);
347
-		if(!$this->ldap->isResource($rr)) {
347
+		if (!$this->ldap->isResource($rr)) {
348 348
 			return false;
349 349
 		}
350 350
 		$er = $this->ldap->firstEntry($cr, $rr);
351 351
 		$attributes = $this->ldap->getAttributes($cr, $er);
352 352
 		$pureAttributes = array();
353
-		for($i = 0; $i < $attributes['count']; $i++) {
353
+		for ($i = 0; $i < $attributes['count']; $i++) {
354 354
 			$pureAttributes[] = $attributes[$i];
355 355
 		}
356 356
 
@@ -385,23 +385,23 @@  discard block
 block discarded – undo
385 385
 	 * @throws \Exception
386 386
 	 */
387 387
 	private function determineGroups($dbKey, $confKey, $testMemberOf = true) {
388
-		if(!$this->checkRequirements(array('ldapHost',
388
+		if (!$this->checkRequirements(array('ldapHost',
389 389
 										   'ldapPort',
390 390
 										   'ldapBase',
391 391
 										   ))) {
392 392
 			return  false;
393 393
 		}
394 394
 		$cr = $this->getConnection();
395
-		if(!$cr) {
395
+		if (!$cr) {
396 396
 			throw new \Exception('Could not connect to LDAP');
397 397
 		}
398 398
 
399 399
 		$this->fetchGroups($dbKey, $confKey);
400 400
 
401
-		if($testMemberOf) {
401
+		if ($testMemberOf) {
402 402
 			$this->configuration->hasMemberOfFilterSupport = $this->testMemberOf();
403 403
 			$this->result->markChange();
404
-			if(!$this->configuration->hasMemberOfFilterSupport) {
404
+			if (!$this->configuration->hasMemberOfFilterSupport) {
405 405
 				throw new \Exception('memberOf is not supported by the server');
406 406
 			}
407 407
 		}
@@ -421,7 +421,7 @@  discard block
 block discarded – undo
421 421
 		$obclasses = array('posixGroup', 'group', 'zimbraDistributionList', 'groupOfNames');
422 422
 
423 423
 		$filterParts = array();
424
-		foreach($obclasses as $obclass) {
424
+		foreach ($obclasses as $obclass) {
425 425
 			$filterParts[] = 'objectclass='.$obclass;
426 426
 		}
427 427
 		//we filter for everything
@@ -438,8 +438,8 @@  discard block
 block discarded – undo
438 438
 			// we need to request dn additionally here, otherwise memberOf
439 439
 			// detection will fail later
440 440
 			$result = $this->access->searchGroups($filter, array('cn', 'dn'), $limit, $offset);
441
-			foreach($result as $item) {
442
-				if(!isset($item['cn']) && !is_array($item['cn']) && !isset($item['cn'][0])) {
441
+			foreach ($result as $item) {
442
+				if (!isset($item['cn']) && !is_array($item['cn']) && !isset($item['cn'][0])) {
443 443
 					// just in case - no issue known
444 444
 					continue;
445 445
 				}
@@ -449,7 +449,7 @@  discard block
 block discarded – undo
449 449
 			$offset += $limit;
450 450
 		} while ($this->access->hasMoreResults());
451 451
 
452
-		if(count($groupNames) > 0) {
452
+		if (count($groupNames) > 0) {
453 453
 			natsort($groupNames);
454 454
 			$this->result->addOptions($dbKey, array_values($groupNames));
455 455
 		} else {
@@ -457,7 +457,7 @@  discard block
 block discarded – undo
457 457
 		}
458 458
 
459 459
 		$setFeatures = $this->configuration->$confKey;
460
-		if(is_array($setFeatures) && !empty($setFeatures)) {
460
+		if (is_array($setFeatures) && !empty($setFeatures)) {
461 461
 			//something is already configured? pre-select it.
462 462
 			$this->result->addChange($dbKey, $setFeatures);
463 463
 		}
@@ -465,14 +465,14 @@  discard block
 block discarded – undo
465 465
 	}
466 466
 
467 467
 	public function determineGroupMemberAssoc() {
468
-		if(!$this->checkRequirements(array('ldapHost',
468
+		if (!$this->checkRequirements(array('ldapHost',
469 469
 										   'ldapPort',
470 470
 										   'ldapGroupFilter',
471 471
 										   ))) {
472 472
 			return  false;
473 473
 		}
474 474
 		$attribute = $this->detectGroupMemberAssoc();
475
-		if($attribute === false) {
475
+		if ($attribute === false) {
476 476
 			return false;
477 477
 		}
478 478
 		$this->configuration->setConfiguration(array('ldapGroupMemberAssocAttr' => $attribute));
@@ -487,14 +487,14 @@  discard block
 block discarded – undo
487 487
 	 * @throws \Exception
488 488
 	 */
489 489
 	public function determineGroupObjectClasses() {
490
-		if(!$this->checkRequirements(array('ldapHost',
490
+		if (!$this->checkRequirements(array('ldapHost',
491 491
 										   'ldapPort',
492 492
 										   'ldapBase',
493 493
 										   ))) {
494 494
 			return  false;
495 495
 		}
496 496
 		$cr = $this->getConnection();
497
-		if(!$cr) {
497
+		if (!$cr) {
498 498
 			throw new \Exception('Could not connect to LDAP');
499 499
 		}
500 500
 
@@ -514,14 +514,14 @@  discard block
 block discarded – undo
514 514
 	 * @throws \Exception
515 515
 	 */
516 516
 	public function determineUserObjectClasses() {
517
-		if(!$this->checkRequirements(array('ldapHost',
517
+		if (!$this->checkRequirements(array('ldapHost',
518 518
 										   'ldapPort',
519 519
 										   'ldapBase',
520 520
 										   ))) {
521 521
 			return  false;
522 522
 		}
523 523
 		$cr = $this->getConnection();
524
-		if(!$cr) {
524
+		if (!$cr) {
525 525
 			throw new \Exception('Could not connect to LDAP');
526 526
 		}
527 527
 
@@ -544,7 +544,7 @@  discard block
 block discarded – undo
544 544
 	 * @throws \Exception
545 545
 	 */
546 546
 	public function getGroupFilter() {
547
-		if(!$this->checkRequirements(array('ldapHost',
547
+		if (!$this->checkRequirements(array('ldapHost',
548 548
 										   'ldapPort',
549 549
 										   'ldapBase',
550 550
 										   ))) {
@@ -568,7 +568,7 @@  discard block
 block discarded – undo
568 568
 	 * @throws \Exception
569 569
 	 */
570 570
 	public function getUserListFilter() {
571
-		if(!$this->checkRequirements(array('ldapHost',
571
+		if (!$this->checkRequirements(array('ldapHost',
572 572
 										   'ldapPort',
573 573
 										   'ldapBase',
574 574
 										   ))) {
@@ -581,7 +581,7 @@  discard block
 block discarded – undo
581 581
 			$this->applyFind('ldap_display_name', $d['ldap_display_name']);
582 582
 		}
583 583
 		$filter = $this->composeLdapFilter(self::LFILTER_USER_LIST);
584
-		if(!$filter) {
584
+		if (!$filter) {
585 585
 			throw new \Exception('Cannot create filter');
586 586
 		}
587 587
 
@@ -594,7 +594,7 @@  discard block
 block discarded – undo
594 594
 	 * @throws \Exception
595 595
 	 */
596 596
 	public function getUserLoginFilter() {
597
-		if(!$this->checkRequirements(array('ldapHost',
597
+		if (!$this->checkRequirements(array('ldapHost',
598 598
 										   'ldapPort',
599 599
 										   'ldapBase',
600 600
 										   'ldapUserFilter',
@@ -603,7 +603,7 @@  discard block
 block discarded – undo
603 603
 		}
604 604
 
605 605
 		$filter = $this->composeLdapFilter(self::LFILTER_LOGIN);
606
-		if(!$filter) {
606
+		if (!$filter) {
607 607
 			throw new \Exception('Cannot create filter');
608 608
 		}
609 609
 
@@ -617,7 +617,7 @@  discard block
 block discarded – undo
617 617
 	 * @throws \Exception
618 618
 	 */
619 619
 	public function testLoginName($loginName) {
620
-		if(!$this->checkRequirements(array('ldapHost',
620
+		if (!$this->checkRequirements(array('ldapHost',
621 621
 			'ldapPort',
622 622
 			'ldapBase',
623 623
 			'ldapLoginFilter',
@@ -626,17 +626,17 @@  discard block
 block discarded – undo
626 626
 		}
627 627
 
628 628
 		$cr = $this->access->connection->getConnectionResource();
629
-		if(!$this->ldap->isResource($cr)) {
629
+		if (!$this->ldap->isResource($cr)) {
630 630
 			throw new \Exception('connection error');
631 631
 		}
632 632
 
633
-		if(mb_strpos($this->access->connection->ldapLoginFilter, '%uid', 0, 'UTF-8')
633
+		if (mb_strpos($this->access->connection->ldapLoginFilter, '%uid', 0, 'UTF-8')
634 634
 			=== false) {
635 635
 			throw new \Exception('missing placeholder');
636 636
 		}
637 637
 
638 638
 		$users = $this->access->countUsersByLoginName($loginName);
639
-		if($this->ldap->errno($cr) !== 0) {
639
+		if ($this->ldap->errno($cr) !== 0) {
640 640
 			throw new \Exception($this->ldap->error($cr));
641 641
 		}
642 642
 		$filter = str_replace('%uid', $loginName, $this->access->connection->ldapLoginFilter);
@@ -651,22 +651,22 @@  discard block
 block discarded – undo
651 651
 	 * @throws \Exception
652 652
 	 */
653 653
 	public function guessPortAndTLS() {
654
-		if(!$this->checkRequirements(array('ldapHost',
654
+		if (!$this->checkRequirements(array('ldapHost',
655 655
 										   ))) {
656 656
 			return false;
657 657
 		}
658 658
 		$this->checkHost();
659 659
 		$portSettings = $this->getPortSettingsToTry();
660 660
 
661
-		if(!is_array($portSettings)) {
661
+		if (!is_array($portSettings)) {
662 662
 			throw new \Exception(print_r($portSettings, true));
663 663
 		}
664 664
 
665 665
 		//proceed from the best configuration and return on first success
666
-		foreach($portSettings as $setting) {
666
+		foreach ($portSettings as $setting) {
667 667
 			$p = $setting['port'];
668 668
 			$t = $setting['tls'];
669
-			\OCP\Util::writeLog('user_ldap', 'Wiz: trying port '. $p . ', TLS '. $t, \OCP\Util::DEBUG);
669
+			\OCP\Util::writeLog('user_ldap', 'Wiz: trying port '.$p.', TLS '.$t, \OCP\Util::DEBUG);
670 670
 			//connectAndBind may throw Exception, it needs to be catched by the
671 671
 			//callee of this method
672 672
 
@@ -676,7 +676,7 @@  discard block
 block discarded – undo
676 676
 				// any reply other than -1 (= cannot connect) is already okay,
677 677
 				// because then we found the server
678 678
 				// unavailable startTLS returns -11
679
-				if($e->getCode() > 0) {
679
+				if ($e->getCode() > 0) {
680 680
 					$settingsFound = true;
681 681
 				} else {
682 682
 					throw $e;
@@ -689,7 +689,7 @@  discard block
 block discarded – undo
689 689
 					'ldapTLS' => intval($t)
690 690
 				);
691 691
 				$this->configuration->setConfiguration($config);
692
-				\OCP\Util::writeLog('user_ldap', 'Wiz: detected Port ' . $p, \OCP\Util::DEBUG);
692
+				\OCP\Util::writeLog('user_ldap', 'Wiz: detected Port '.$p, \OCP\Util::DEBUG);
693 693
 				$this->result->addChange('ldap_port', $p);
694 694
 				return $this->result;
695 695
 			}
@@ -704,7 +704,7 @@  discard block
 block discarded – undo
704 704
 	 * @return WizardResult|false WizardResult on success, false otherwise
705 705
 	 */
706 706
 	public function guessBaseDN() {
707
-		if(!$this->checkRequirements(array('ldapHost',
707
+		if (!$this->checkRequirements(array('ldapHost',
708 708
 										   'ldapPort',
709 709
 										   ))) {
710 710
 			return false;
@@ -713,9 +713,9 @@  discard block
 block discarded – undo
713 713
 		//check whether a DN is given in the agent name (99.9% of all cases)
714 714
 		$base = null;
715 715
 		$i = stripos($this->configuration->ldapAgentName, 'dc=');
716
-		if($i !== false) {
716
+		if ($i !== false) {
717 717
 			$base = substr($this->configuration->ldapAgentName, $i);
718
-			if($this->testBaseDN($base)) {
718
+			if ($this->testBaseDN($base)) {
719 719
 				$this->applyFind('ldap_base', $base);
720 720
 				return $this->result;
721 721
 			}
@@ -726,13 +726,13 @@  discard block
 block discarded – undo
726 726
 		//a base DN
727 727
 		$helper = new Helper(\OC::$server->getConfig());
728 728
 		$domain = $helper->getDomainFromURL($this->configuration->ldapHost);
729
-		if(!$domain) {
729
+		if (!$domain) {
730 730
 			return false;
731 731
 		}
732 732
 
733 733
 		$dparts = explode('.', $domain);
734
-		while(count($dparts) > 0) {
735
-			$base2 = 'dc=' . implode(',dc=', $dparts);
734
+		while (count($dparts) > 0) {
735
+			$base2 = 'dc='.implode(',dc=', $dparts);
736 736
 			if ($base !== $base2 && $this->testBaseDN($base2)) {
737 737
 				$this->applyFind('ldap_base', $base2);
738 738
 				return $this->result;
@@ -765,7 +765,7 @@  discard block
 block discarded – undo
765 765
 		$hostInfo = parse_url($host);
766 766
 
767 767
 		//removes Port from Host
768
-		if(is_array($hostInfo) && isset($hostInfo['port'])) {
768
+		if (is_array($hostInfo) && isset($hostInfo['port'])) {
769 769
 			$port = $hostInfo['port'];
770 770
 			$host = str_replace(':'.$port, '', $host);
771 771
 			$this->applyFind('ldap_host', $host);
@@ -782,30 +782,30 @@  discard block
 block discarded – undo
782 782
 	private function detectGroupMemberAssoc() {
783 783
 		$possibleAttrs = array('uniqueMember', 'memberUid', 'member');
784 784
 		$filter = $this->configuration->ldapGroupFilter;
785
-		if(empty($filter)) {
785
+		if (empty($filter)) {
786 786
 			return false;
787 787
 		}
788 788
 		$cr = $this->getConnection();
789
-		if(!$cr) {
789
+		if (!$cr) {
790 790
 			throw new \Exception('Could not connect to LDAP');
791 791
 		}
792 792
 		$base = $this->configuration->ldapBase[0];
793 793
 		$rr = $this->ldap->search($cr, $base, $filter, $possibleAttrs, 0, 1000);
794
-		if(!$this->ldap->isResource($rr)) {
794
+		if (!$this->ldap->isResource($rr)) {
795 795
 			return false;
796 796
 		}
797 797
 		$er = $this->ldap->firstEntry($cr, $rr);
798
-		while(is_resource($er)) {
798
+		while (is_resource($er)) {
799 799
 			$this->ldap->getDN($cr, $er);
800 800
 			$attrs = $this->ldap->getAttributes($cr, $er);
801 801
 			$result = array();
802 802
 			$possibleAttrsCount = count($possibleAttrs);
803
-			for($i = 0; $i < $possibleAttrsCount; $i++) {
804
-				if(isset($attrs[$possibleAttrs[$i]])) {
803
+			for ($i = 0; $i < $possibleAttrsCount; $i++) {
804
+				if (isset($attrs[$possibleAttrs[$i]])) {
805 805
 					$result[$possibleAttrs[$i]] = $attrs[$possibleAttrs[$i]]['count'];
806 806
 				}
807 807
 			}
808
-			if(!empty($result)) {
808
+			if (!empty($result)) {
809 809
 				natsort($result);
810 810
 				return key($result);
811 811
 			}
@@ -824,14 +824,14 @@  discard block
 block discarded – undo
824 824
 	 */
825 825
 	private function testBaseDN($base) {
826 826
 		$cr = $this->getConnection();
827
-		if(!$cr) {
827
+		if (!$cr) {
828 828
 			throw new \Exception('Could not connect to LDAP');
829 829
 		}
830 830
 
831 831
 		//base is there, let's validate it. If we search for anything, we should
832 832
 		//get a result set > 0 on a proper base
833 833
 		$rr = $this->ldap->search($cr, $base, 'objectClass=*', array('dn'), 0, 1);
834
-		if(!$this->ldap->isResource($rr)) {
834
+		if (!$this->ldap->isResource($rr)) {
835 835
 			$errorNo  = $this->ldap->errno($cr);
836 836
 			$errorMsg = $this->ldap->error($cr);
837 837
 			\OCP\Util::writeLog('user_ldap', 'Wiz: Could not search base '.$base.
@@ -853,11 +853,11 @@  discard block
 block discarded – undo
853 853
 	 */
854 854
 	private function testMemberOf() {
855 855
 		$cr = $this->getConnection();
856
-		if(!$cr) {
856
+		if (!$cr) {
857 857
 			throw new \Exception('Could not connect to LDAP');
858 858
 		}
859 859
 		$result = $this->access->countUsers('memberOf=*', array('memberOf'), 1);
860
-		if(is_int($result) &&  $result > 0) {
860
+		if (is_int($result) && $result > 0) {
861 861
 			return true;
862 862
 		}
863 863
 		return false;
@@ -878,27 +878,27 @@  discard block
 block discarded – undo
878 878
 			case self::LFILTER_USER_LIST:
879 879
 				$objcs = $this->configuration->ldapUserFilterObjectclass;
880 880
 				//glue objectclasses
881
-				if(is_array($objcs) && count($objcs) > 0) {
881
+				if (is_array($objcs) && count($objcs) > 0) {
882 882
 					$filter .= '(|';
883
-					foreach($objcs as $objc) {
884
-						$filter .= '(objectclass=' . $objc . ')';
883
+					foreach ($objcs as $objc) {
884
+						$filter .= '(objectclass='.$objc.')';
885 885
 					}
886 886
 					$filter .= ')';
887 887
 					$parts++;
888 888
 				}
889 889
 				//glue group memberships
890
-				if($this->configuration->hasMemberOfFilterSupport) {
890
+				if ($this->configuration->hasMemberOfFilterSupport) {
891 891
 					$cns = $this->configuration->ldapUserFilterGroups;
892
-					if(is_array($cns) && count($cns) > 0) {
892
+					if (is_array($cns) && count($cns) > 0) {
893 893
 						$filter .= '(|';
894 894
 						$cr = $this->getConnection();
895
-						if(!$cr) {
895
+						if (!$cr) {
896 896
 							throw new \Exception('Could not connect to LDAP');
897 897
 						}
898 898
 						$base = $this->configuration->ldapBase[0];
899
-						foreach($cns as $cn) {
900
-							$rr = $this->ldap->search($cr, $base, 'cn=' . $cn, array('dn', 'primaryGroupToken'));
901
-							if(!$this->ldap->isResource($rr)) {
899
+						foreach ($cns as $cn) {
900
+							$rr = $this->ldap->search($cr, $base, 'cn='.$cn, array('dn', 'primaryGroupToken'));
901
+							if (!$this->ldap->isResource($rr)) {
902 902
 								continue;
903 903
 							}
904 904
 							$er = $this->ldap->firstEntry($cr, $rr);
@@ -907,11 +907,11 @@  discard block
 block discarded – undo
907 907
 							if ($dn == false || $dn === '') {
908 908
 								continue;
909 909
 							}
910
-							$filterPart = '(memberof=' . $dn . ')';
911
-							if(isset($attrs['primaryGroupToken'])) {
910
+							$filterPart = '(memberof='.$dn.')';
911
+							if (isset($attrs['primaryGroupToken'])) {
912 912
 								$pgt = $attrs['primaryGroupToken'][0];
913
-								$primaryFilterPart = '(primaryGroupID=' . $pgt .')';
914
-								$filterPart = '(|' . $filterPart . $primaryFilterPart . ')';
913
+								$primaryFilterPart = '(primaryGroupID='.$pgt.')';
914
+								$filterPart = '(|'.$filterPart.$primaryFilterPart.')';
915 915
 							}
916 916
 							$filter .= $filterPart;
917 917
 						}
@@ -920,8 +920,8 @@  discard block
 block discarded – undo
920 920
 					$parts++;
921 921
 				}
922 922
 				//wrap parts in AND condition
923
-				if($parts > 1) {
924
-					$filter = '(&' . $filter . ')';
923
+				if ($parts > 1) {
924
+					$filter = '(&'.$filter.')';
925 925
 				}
926 926
 				if ($filter === '') {
927 927
 					$filter = '(objectclass=*)';
@@ -931,27 +931,27 @@  discard block
 block discarded – undo
931 931
 			case self::LFILTER_GROUP_LIST:
932 932
 				$objcs = $this->configuration->ldapGroupFilterObjectclass;
933 933
 				//glue objectclasses
934
-				if(is_array($objcs) && count($objcs) > 0) {
934
+				if (is_array($objcs) && count($objcs) > 0) {
935 935
 					$filter .= '(|';
936
-					foreach($objcs as $objc) {
937
-						$filter .= '(objectclass=' . $objc . ')';
936
+					foreach ($objcs as $objc) {
937
+						$filter .= '(objectclass='.$objc.')';
938 938
 					}
939 939
 					$filter .= ')';
940 940
 					$parts++;
941 941
 				}
942 942
 				//glue group memberships
943 943
 				$cns = $this->configuration->ldapGroupFilterGroups;
944
-				if(is_array($cns) && count($cns) > 0) {
944
+				if (is_array($cns) && count($cns) > 0) {
945 945
 					$filter .= '(|';
946
-					foreach($cns as $cn) {
947
-						$filter .= '(cn=' . $cn . ')';
946
+					foreach ($cns as $cn) {
947
+						$filter .= '(cn='.$cn.')';
948 948
 					}
949 949
 					$filter .= ')';
950 950
 				}
951 951
 				$parts++;
952 952
 				//wrap parts in AND condition
953
-				if($parts > 1) {
954
-					$filter = '(&' . $filter . ')';
953
+				if ($parts > 1) {
954
+					$filter = '(&'.$filter.')';
955 955
 				}
956 956
 				break;
957 957
 
@@ -963,47 +963,47 @@  discard block
 block discarded – undo
963 963
 				$userAttributes = array_change_key_case(array_flip($userAttributes));
964 964
 				$parts = 0;
965 965
 
966
-				if($this->configuration->ldapLoginFilterUsername === '1') {
966
+				if ($this->configuration->ldapLoginFilterUsername === '1') {
967 967
 					$attr = '';
968
-					if(isset($userAttributes['uid'])) {
968
+					if (isset($userAttributes['uid'])) {
969 969
 						$attr = 'uid';
970
-					} else if(isset($userAttributes['samaccountname'])) {
970
+					} else if (isset($userAttributes['samaccountname'])) {
971 971
 						$attr = 'samaccountname';
972
-					} else if(isset($userAttributes['cn'])) {
972
+					} else if (isset($userAttributes['cn'])) {
973 973
 						//fallback
974 974
 						$attr = 'cn';
975 975
 					}
976 976
 					if ($attr !== '') {
977
-						$filterUsername = '(' . $attr . $loginpart . ')';
977
+						$filterUsername = '('.$attr.$loginpart.')';
978 978
 						$parts++;
979 979
 					}
980 980
 				}
981 981
 
982 982
 				$filterEmail = '';
983
-				if($this->configuration->ldapLoginFilterEmail === '1') {
983
+				if ($this->configuration->ldapLoginFilterEmail === '1') {
984 984
 					$filterEmail = '(|(mailPrimaryAddress=%uid)(mail=%uid))';
985 985
 					$parts++;
986 986
 				}
987 987
 
988 988
 				$filterAttributes = '';
989 989
 				$attrsToFilter = $this->configuration->ldapLoginFilterAttributes;
990
-				if(is_array($attrsToFilter) && count($attrsToFilter) > 0) {
990
+				if (is_array($attrsToFilter) && count($attrsToFilter) > 0) {
991 991
 					$filterAttributes = '(|';
992
-					foreach($attrsToFilter as $attribute) {
993
-						$filterAttributes .= '(' . $attribute . $loginpart . ')';
992
+					foreach ($attrsToFilter as $attribute) {
993
+						$filterAttributes .= '('.$attribute.$loginpart.')';
994 994
 					}
995 995
 					$filterAttributes .= ')';
996 996
 					$parts++;
997 997
 				}
998 998
 
999 999
 				$filterLogin = '';
1000
-				if($parts > 1) {
1000
+				if ($parts > 1) {
1001 1001
 					$filterLogin = '(|';
1002 1002
 				}
1003 1003
 				$filterLogin .= $filterUsername;
1004 1004
 				$filterLogin .= $filterEmail;
1005 1005
 				$filterLogin .= $filterAttributes;
1006
-				if($parts > 1) {
1006
+				if ($parts > 1) {
1007 1007
 					$filterLogin .= ')';
1008 1008
 				}
1009 1009
 
@@ -1025,7 +1025,7 @@  discard block
 block discarded – undo
1025 1025
 	 * @throws \Exception
1026 1026
 	 */
1027 1027
 	private function connectAndBind($port = 389, $tls = false, $ncc = false) {
1028
-		if($ncc) {
1028
+		if ($ncc) {
1029 1029
 			//No certificate check
1030 1030
 			//FIXME: undo afterwards
1031 1031
 			putenv('LDAPTLS_REQCERT=never');
@@ -1035,12 +1035,12 @@  discard block
 block discarded – undo
1035 1035
 		\OCP\Util::writeLog('user_ldap', 'Wiz: Checking Host Info ', \OCP\Util::DEBUG);
1036 1036
 		$host = $this->configuration->ldapHost;
1037 1037
 		$hostInfo = parse_url($host);
1038
-		if(!$hostInfo) {
1038
+		if (!$hostInfo) {
1039 1039
 			throw new \Exception(self::$l->t('Invalid Host'));
1040 1040
 		}
1041 1041
 		\OCP\Util::writeLog('user_ldap', 'Wiz: Attempting to connect ', \OCP\Util::DEBUG);
1042 1042
 		$cr = $this->ldap->connect($host, $port);
1043
-		if(!is_resource($cr)) {
1043
+		if (!is_resource($cr)) {
1044 1044
 			throw new \Exception(self::$l->t('Invalid Host'));
1045 1045
 		}
1046 1046
 
@@ -1051,9 +1051,9 @@  discard block
 block discarded – undo
1051 1051
 		$this->ldap->setOption($cr, LDAP_OPT_NETWORK_TIMEOUT, self::LDAP_NW_TIMEOUT);
1052 1052
 
1053 1053
 		try {
1054
-			if($tls) {
1054
+			if ($tls) {
1055 1055
 				$isTlsWorking = @$this->ldap->startTls($cr);
1056
-				if(!$isTlsWorking) {
1056
+				if (!$isTlsWorking) {
1057 1057
 					return false;
1058 1058
 				}
1059 1059
 			}
@@ -1067,20 +1067,20 @@  discard block
 block discarded – undo
1067 1067
 			$errNo = $this->ldap->errno($cr);
1068 1068
 			$error = ldap_error($cr);
1069 1069
 			$this->ldap->unbind($cr);
1070
-		} catch(ServerNotAvailableException $e) {
1070
+		} catch (ServerNotAvailableException $e) {
1071 1071
 			return false;
1072 1072
 		}
1073 1073
 
1074
-		if($login === true) {
1074
+		if ($login === true) {
1075 1075
 			$this->ldap->unbind($cr);
1076
-			if($ncc) {
1076
+			if ($ncc) {
1077 1077
 				throw new \Exception('Certificate cannot be validated.');
1078 1078
 			}
1079
-			\OCP\Util::writeLog('user_ldap', 'Wiz: Bind successful to Port '. $port . ' TLS ' . intval($tls), \OCP\Util::DEBUG);
1079
+			\OCP\Util::writeLog('user_ldap', 'Wiz: Bind successful to Port '.$port.' TLS '.intval($tls), \OCP\Util::DEBUG);
1080 1080
 			return true;
1081 1081
 		}
1082 1082
 
1083
-		if($errNo === -1 || ($errNo === 2 && $ncc)) {
1083
+		if ($errNo === -1 || ($errNo === 2 && $ncc)) {
1084 1084
 			//host, port or TLS wrong
1085 1085
 			return false;
1086 1086
 		} else if ($errNo === 2) {
@@ -1110,9 +1110,9 @@  discard block
 block discarded – undo
1110 1110
 	 */
1111 1111
 	private function checkRequirements($reqs) {
1112 1112
 		$this->checkAgentRequirements();
1113
-		foreach($reqs as $option) {
1113
+		foreach ($reqs as $option) {
1114 1114
 			$value = $this->configuration->$option;
1115
-			if(empty($value)) {
1115
+			if (empty($value)) {
1116 1116
 				return false;
1117 1117
 			}
1118 1118
 		}
@@ -1134,33 +1134,33 @@  discard block
 block discarded – undo
1134 1134
 		$dnRead = array();
1135 1135
 		$foundItems = array();
1136 1136
 		$maxEntries = 0;
1137
-		if(!is_array($this->configuration->ldapBase)
1137
+		if (!is_array($this->configuration->ldapBase)
1138 1138
 		   || !isset($this->configuration->ldapBase[0])) {
1139 1139
 			return false;
1140 1140
 		}
1141 1141
 		$base = $this->configuration->ldapBase[0];
1142 1142
 		$cr = $this->getConnection();
1143
-		if(!$this->ldap->isResource($cr)) {
1143
+		if (!$this->ldap->isResource($cr)) {
1144 1144
 			return false;
1145 1145
 		}
1146 1146
 		$lastFilter = null;
1147
-		if(isset($filters[count($filters)-1])) {
1148
-			$lastFilter = $filters[count($filters)-1];
1147
+		if (isset($filters[count($filters) - 1])) {
1148
+			$lastFilter = $filters[count($filters) - 1];
1149 1149
 		}
1150
-		foreach($filters as $filter) {
1151
-			if($lastFilter === $filter && count($foundItems) > 0) {
1150
+		foreach ($filters as $filter) {
1151
+			if ($lastFilter === $filter && count($foundItems) > 0) {
1152 1152
 				//skip when the filter is a wildcard and results were found
1153 1153
 				continue;
1154 1154
 			}
1155 1155
 			// 20k limit for performance and reason
1156 1156
 			$rr = $this->ldap->search($cr, $base, $filter, array($attr), 0, 20000);
1157
-			if(!$this->ldap->isResource($rr)) {
1157
+			if (!$this->ldap->isResource($rr)) {
1158 1158
 				continue;
1159 1159
 			}
1160 1160
 			$entries = $this->ldap->countEntries($cr, $rr);
1161 1161
 			$getEntryFunc = 'firstEntry';
1162
-			if(($entries !== false) && ($entries > 0)) {
1163
-				if(!is_null($maxF) && $entries > $maxEntries) {
1162
+			if (($entries !== false) && ($entries > 0)) {
1163
+				if (!is_null($maxF) && $entries > $maxEntries) {
1164 1164
 					$maxEntries = $entries;
1165 1165
 					$maxF = $filter;
1166 1166
 				}
@@ -1168,13 +1168,13 @@  discard block
 block discarded – undo
1168 1168
 				do {
1169 1169
 					$entry = $this->ldap->$getEntryFunc($cr, $rr);
1170 1170
 					$getEntryFunc = 'nextEntry';
1171
-					if(!$this->ldap->isResource($entry)) {
1171
+					if (!$this->ldap->isResource($entry)) {
1172 1172
 						continue 2;
1173 1173
 					}
1174 1174
 					$rr = $entry; //will be expected by nextEntry next round
1175 1175
 					$attributes = $this->ldap->getAttributes($cr, $entry);
1176 1176
 					$dn = $this->ldap->getDN($cr, $entry);
1177
-					if($dn === false || in_array($dn, $dnRead)) {
1177
+					if ($dn === false || in_array($dn, $dnRead)) {
1178 1178
 						continue;
1179 1179
 					}
1180 1180
 					$newItems = array();
@@ -1185,7 +1185,7 @@  discard block
 block discarded – undo
1185 1185
 					$foundItems = array_merge($foundItems, $newItems);
1186 1186
 					$this->resultCache[$dn][$attr] = $newItems;
1187 1187
 					$dnRead[] = $dn;
1188
-				} while(($state === self::LRESULT_PROCESSED_SKIP
1188
+				} while (($state === self::LRESULT_PROCESSED_SKIP
1189 1189
 						|| $this->ldap->isResource($entry))
1190 1190
 						&& ($dnReadLimit === 0 || $dnReadCount < $dnReadLimit));
1191 1191
 			}
@@ -1208,11 +1208,11 @@  discard block
 block discarded – undo
1208 1208
 	 */
1209 1209
 	private function determineFeature($objectclasses, $attr, $dbkey, $confkey, $po = false) {
1210 1210
 		$cr = $this->getConnection();
1211
-		if(!$cr) {
1211
+		if (!$cr) {
1212 1212
 			throw new \Exception('Could not connect to LDAP');
1213 1213
 		}
1214 1214
 		$p = 'objectclass=';
1215
-		foreach($objectclasses as $key => $value) {
1215
+		foreach ($objectclasses as $key => $value) {
1216 1216
 			$objectclasses[$key] = $p.$value;
1217 1217
 		}
1218 1218
 		$maxEntryObjC = '';
@@ -1224,7 +1224,7 @@  discard block
 block discarded – undo
1224 1224
 		$availableFeatures =
1225 1225
 			$this->cumulativeSearchOnAttribute($objectclasses, $attr,
1226 1226
 											   $dig, $maxEntryObjC);
1227
-		if(is_array($availableFeatures)
1227
+		if (is_array($availableFeatures)
1228 1228
 		   && count($availableFeatures) > 0) {
1229 1229
 			natcasesort($availableFeatures);
1230 1230
 			//natcasesort keeps indices, but we must get rid of them for proper
@@ -1235,7 +1235,7 @@  discard block
 block discarded – undo
1235 1235
 		}
1236 1236
 
1237 1237
 		$setFeatures = $this->configuration->$confkey;
1238
-		if(is_array($setFeatures) && !empty($setFeatures)) {
1238
+		if (is_array($setFeatures) && !empty($setFeatures)) {
1239 1239
 			//something is already configured? pre-select it.
1240 1240
 			$this->result->addChange($dbkey, $setFeatures);
1241 1241
 		} else if ($po && $maxEntryObjC !== '') {
@@ -1257,7 +1257,7 @@  discard block
 block discarded – undo
1257 1257
 	 * LRESULT_PROCESSED_INVALID or LRESULT_PROCESSED_SKIP
1258 1258
 	 */
1259 1259
 	private function getAttributeValuesFromEntry($result, $attribute, &$known) {
1260
-		if(!is_array($result)
1260
+		if (!is_array($result)
1261 1261
 		   || !isset($result['count'])
1262 1262
 		   || !$result['count'] > 0) {
1263 1263
 			return self::LRESULT_PROCESSED_INVALID;
@@ -1266,12 +1266,12 @@  discard block
 block discarded – undo
1266 1266
 		// strtolower on all keys for proper comparison
1267 1267
 		$result = \OCP\Util::mb_array_change_key_case($result);
1268 1268
 		$attribute = strtolower($attribute);
1269
-		if(isset($result[$attribute])) {
1270
-			foreach($result[$attribute] as $key => $val) {
1271
-				if($key === 'count') {
1269
+		if (isset($result[$attribute])) {
1270
+			foreach ($result[$attribute] as $key => $val) {
1271
+				if ($key === 'count') {
1272 1272
 					continue;
1273 1273
 				}
1274
-				if(!in_array($val, $known)) {
1274
+				if (!in_array($val, $known)) {
1275 1275
 					$known[] = $val;
1276 1276
 				}
1277 1277
 			}
@@ -1285,7 +1285,7 @@  discard block
 block discarded – undo
1285 1285
 	 * @return bool|mixed
1286 1286
 	 */
1287 1287
 	private function getConnection() {
1288
-		if(!is_null($this->cr)) {
1288
+		if (!is_null($this->cr)) {
1289 1289
 			return $this->cr;
1290 1290
 		}
1291 1291
 
@@ -1297,14 +1297,14 @@  discard block
 block discarded – undo
1297 1297
 		$this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3);
1298 1298
 		$this->ldap->setOption($cr, LDAP_OPT_REFERRALS, 0);
1299 1299
 		$this->ldap->setOption($cr, LDAP_OPT_NETWORK_TIMEOUT, self::LDAP_NW_TIMEOUT);
1300
-		if($this->configuration->ldapTLS === 1) {
1300
+		if ($this->configuration->ldapTLS === 1) {
1301 1301
 			$this->ldap->startTls($cr);
1302 1302
 		}
1303 1303
 
1304 1304
 		$lo = @$this->ldap->bind($cr,
1305 1305
 								 $this->configuration->ldapAgentName,
1306 1306
 								 $this->configuration->ldapAgentPassword);
1307
-		if($lo === true) {
1307
+		if ($lo === true) {
1308 1308
 			$this->$cr = $cr;
1309 1309
 			return $cr;
1310 1310
 		}
@@ -1339,14 +1339,14 @@  discard block
 block discarded – undo
1339 1339
 		$portSettings = array();
1340 1340
 
1341 1341
 		//In case the port is already provided, we will check this first
1342
-		if($port > 0) {
1342
+		if ($port > 0) {
1343 1343
 			$hostInfo = parse_url($host);
1344
-			if(!(is_array($hostInfo)
1344
+			if (!(is_array($hostInfo)
1345 1345
 				&& isset($hostInfo['scheme'])
1346 1346
 				&& stripos($hostInfo['scheme'], 'ldaps') !== false)) {
1347 1347
 				$portSettings[] = array('port' => $port, 'tls' => true);
1348 1348
 			}
1349
-			$portSettings[] =array('port' => $port, 'tls' => false);
1349
+			$portSettings[] = array('port' => $port, 'tls' => false);
1350 1350
 		}
1351 1351
 
1352 1352
 		//default ports
Please login to merge, or discard this patch.
lib/private/legacy/db.php 3 patches
Doc Comments   -1 removed lines patch added patch discarded remove patch
@@ -151,7 +151,6 @@
 block discarded – undo
151 151
 	/**
152 152
 	 * saves database schema to xml file
153 153
 	 * @param string $file name of file
154
-	 * @param int $mode
155 154
 	 * @return bool
156 155
 	 *
157 156
 	 * TODO: write more documentation
Please login to merge, or discard this patch.
Indentation   +194 added lines, -194 removed lines patch added patch discarded remove patch
@@ -33,210 +33,210 @@
 block discarded – undo
33 33
  */
34 34
 class OC_DB {
35 35
 
36
-	/**
37
-	 * get MDB2 schema manager
38
-	 *
39
-	 * @return \OC\DB\MDB2SchemaManager
40
-	 */
41
-	private static function getMDB2SchemaManager() {
42
-		return new \OC\DB\MDB2SchemaManager(\OC::$server->getDatabaseConnection());
43
-	}
36
+    /**
37
+     * get MDB2 schema manager
38
+     *
39
+     * @return \OC\DB\MDB2SchemaManager
40
+     */
41
+    private static function getMDB2SchemaManager() {
42
+        return new \OC\DB\MDB2SchemaManager(\OC::$server->getDatabaseConnection());
43
+    }
44 44
 
45
-	/**
46
-	 * Prepare a SQL query
47
-	 * @param string $query Query string
48
-	 * @param int $limit
49
-	 * @param int $offset
50
-	 * @param bool $isManipulation
51
-	 * @throws \OC\DatabaseException
52
-	 * @return OC_DB_StatementWrapper prepared SQL query
53
-	 *
54
-	 * SQL query via Doctrine prepare(), needs to be execute()'d!
55
-	 */
56
-	static public function prepare( $query , $limit = null, $offset = null, $isManipulation = null) {
57
-		$connection = \OC::$server->getDatabaseConnection();
45
+    /**
46
+     * Prepare a SQL query
47
+     * @param string $query Query string
48
+     * @param int $limit
49
+     * @param int $offset
50
+     * @param bool $isManipulation
51
+     * @throws \OC\DatabaseException
52
+     * @return OC_DB_StatementWrapper prepared SQL query
53
+     *
54
+     * SQL query via Doctrine prepare(), needs to be execute()'d!
55
+     */
56
+    static public function prepare( $query , $limit = null, $offset = null, $isManipulation = null) {
57
+        $connection = \OC::$server->getDatabaseConnection();
58 58
 
59
-		if ($isManipulation === null) {
60
-			//try to guess, so we return the number of rows on manipulations
61
-			$isManipulation = self::isManipulation($query);
62
-		}
59
+        if ($isManipulation === null) {
60
+            //try to guess, so we return the number of rows on manipulations
61
+            $isManipulation = self::isManipulation($query);
62
+        }
63 63
 
64
-		// return the result
65
-		try {
66
-			$result =$connection->prepare($query, $limit, $offset);
67
-		} catch (\Doctrine\DBAL\DBALException $e) {
68
-			throw new \OC\DatabaseException($e->getMessage(), $query);
69
-		}
70
-		// differentiate between query and manipulation
71
-		$result = new OC_DB_StatementWrapper($result, $isManipulation);
72
-		return $result;
73
-	}
64
+        // return the result
65
+        try {
66
+            $result =$connection->prepare($query, $limit, $offset);
67
+        } catch (\Doctrine\DBAL\DBALException $e) {
68
+            throw new \OC\DatabaseException($e->getMessage(), $query);
69
+        }
70
+        // differentiate between query and manipulation
71
+        $result = new OC_DB_StatementWrapper($result, $isManipulation);
72
+        return $result;
73
+    }
74 74
 
75
-	/**
76
-	 * tries to guess the type of statement based on the first 10 characters
77
-	 * the current check allows some whitespace but does not work with IF EXISTS or other more complex statements
78
-	 *
79
-	 * @param string $sql
80
-	 * @return bool
81
-	 */
82
-	static public function isManipulation( $sql ) {
83
-		$selectOccurrence = stripos($sql, 'SELECT');
84
-		if ($selectOccurrence !== false && $selectOccurrence < 10) {
85
-			return false;
86
-		}
87
-		$insertOccurrence = stripos($sql, 'INSERT');
88
-		if ($insertOccurrence !== false && $insertOccurrence < 10) {
89
-			return true;
90
-		}
91
-		$updateOccurrence = stripos($sql, 'UPDATE');
92
-		if ($updateOccurrence !== false && $updateOccurrence < 10) {
93
-			return true;
94
-		}
95
-		$deleteOccurrence = stripos($sql, 'DELETE');
96
-		if ($deleteOccurrence !== false && $deleteOccurrence < 10) {
97
-			return true;
98
-		}
99
-		return false;
100
-	}
75
+    /**
76
+     * tries to guess the type of statement based on the first 10 characters
77
+     * the current check allows some whitespace but does not work with IF EXISTS or other more complex statements
78
+     *
79
+     * @param string $sql
80
+     * @return bool
81
+     */
82
+    static public function isManipulation( $sql ) {
83
+        $selectOccurrence = stripos($sql, 'SELECT');
84
+        if ($selectOccurrence !== false && $selectOccurrence < 10) {
85
+            return false;
86
+        }
87
+        $insertOccurrence = stripos($sql, 'INSERT');
88
+        if ($insertOccurrence !== false && $insertOccurrence < 10) {
89
+            return true;
90
+        }
91
+        $updateOccurrence = stripos($sql, 'UPDATE');
92
+        if ($updateOccurrence !== false && $updateOccurrence < 10) {
93
+            return true;
94
+        }
95
+        $deleteOccurrence = stripos($sql, 'DELETE');
96
+        if ($deleteOccurrence !== false && $deleteOccurrence < 10) {
97
+            return true;
98
+        }
99
+        return false;
100
+    }
101 101
 
102
-	/**
103
-	 * execute a prepared statement, on error write log and throw exception
104
-	 * @param mixed $stmt OC_DB_StatementWrapper,
105
-	 *					  an array with 'sql' and optionally 'limit' and 'offset' keys
106
-	 *					.. or a simple sql query string
107
-	 * @param array $parameters
108
-	 * @return OC_DB_StatementWrapper
109
-	 * @throws \OC\DatabaseException
110
-	 */
111
-	static public function executeAudited( $stmt, array $parameters = null) {
112
-		if (is_string($stmt)) {
113
-			// convert to an array with 'sql'
114
-			if (stripos($stmt, 'LIMIT') !== false) { //OFFSET requires LIMIT, so we only need to check for LIMIT
115
-				// TODO try to convert LIMIT OFFSET notation to parameters
116
-				$message = 'LIMIT and OFFSET are forbidden for portability reasons,'
117
-						 . ' pass an array with \'limit\' and \'offset\' instead';
118
-				throw new \OC\DatabaseException($message);
119
-			}
120
-			$stmt = array('sql' => $stmt, 'limit' => null, 'offset' => null);
121
-		}
122
-		if (is_array($stmt)) {
123
-			// convert to prepared statement
124
-			if ( ! array_key_exists('sql', $stmt) ) {
125
-				$message = 'statement array must at least contain key \'sql\'';
126
-				throw new \OC\DatabaseException($message);
127
-			}
128
-			if ( ! array_key_exists('limit', $stmt) ) {
129
-				$stmt['limit'] = null;
130
-			}
131
-			if ( ! array_key_exists('limit', $stmt) ) {
132
-				$stmt['offset'] = null;
133
-			}
134
-			$stmt = self::prepare($stmt['sql'], $stmt['limit'], $stmt['offset']);
135
-		}
136
-		self::raiseExceptionOnError($stmt, 'Could not prepare statement');
137
-		if ($stmt instanceof OC_DB_StatementWrapper) {
138
-			$result = $stmt->execute($parameters);
139
-			self::raiseExceptionOnError($result, 'Could not execute statement');
140
-		} else {
141
-			if (is_object($stmt)) {
142
-				$message = 'Expected a prepared statement or array got ' . get_class($stmt);
143
-			} else {
144
-				$message = 'Expected a prepared statement or array got ' . gettype($stmt);
145
-			}
146
-			throw new \OC\DatabaseException($message);
147
-		}
148
-		return $result;
149
-	}
102
+    /**
103
+     * execute a prepared statement, on error write log and throw exception
104
+     * @param mixed $stmt OC_DB_StatementWrapper,
105
+     *					  an array with 'sql' and optionally 'limit' and 'offset' keys
106
+     *					.. or a simple sql query string
107
+     * @param array $parameters
108
+     * @return OC_DB_StatementWrapper
109
+     * @throws \OC\DatabaseException
110
+     */
111
+    static public function executeAudited( $stmt, array $parameters = null) {
112
+        if (is_string($stmt)) {
113
+            // convert to an array with 'sql'
114
+            if (stripos($stmt, 'LIMIT') !== false) { //OFFSET requires LIMIT, so we only need to check for LIMIT
115
+                // TODO try to convert LIMIT OFFSET notation to parameters
116
+                $message = 'LIMIT and OFFSET are forbidden for portability reasons,'
117
+                            . ' pass an array with \'limit\' and \'offset\' instead';
118
+                throw new \OC\DatabaseException($message);
119
+            }
120
+            $stmt = array('sql' => $stmt, 'limit' => null, 'offset' => null);
121
+        }
122
+        if (is_array($stmt)) {
123
+            // convert to prepared statement
124
+            if ( ! array_key_exists('sql', $stmt) ) {
125
+                $message = 'statement array must at least contain key \'sql\'';
126
+                throw new \OC\DatabaseException($message);
127
+            }
128
+            if ( ! array_key_exists('limit', $stmt) ) {
129
+                $stmt['limit'] = null;
130
+            }
131
+            if ( ! array_key_exists('limit', $stmt) ) {
132
+                $stmt['offset'] = null;
133
+            }
134
+            $stmt = self::prepare($stmt['sql'], $stmt['limit'], $stmt['offset']);
135
+        }
136
+        self::raiseExceptionOnError($stmt, 'Could not prepare statement');
137
+        if ($stmt instanceof OC_DB_StatementWrapper) {
138
+            $result = $stmt->execute($parameters);
139
+            self::raiseExceptionOnError($result, 'Could not execute statement');
140
+        } else {
141
+            if (is_object($stmt)) {
142
+                $message = 'Expected a prepared statement or array got ' . get_class($stmt);
143
+            } else {
144
+                $message = 'Expected a prepared statement or array got ' . gettype($stmt);
145
+            }
146
+            throw new \OC\DatabaseException($message);
147
+        }
148
+        return $result;
149
+    }
150 150
 
151
-	/**
152
-	 * saves database schema to xml file
153
-	 * @param string $file name of file
154
-	 * @param int $mode
155
-	 * @return bool
156
-	 *
157
-	 * TODO: write more documentation
158
-	 */
159
-	public static function getDbStructure($file) {
160
-		$schemaManager = self::getMDB2SchemaManager();
161
-		return $schemaManager->getDbStructure($file);
162
-	}
151
+    /**
152
+     * saves database schema to xml file
153
+     * @param string $file name of file
154
+     * @param int $mode
155
+     * @return bool
156
+     *
157
+     * TODO: write more documentation
158
+     */
159
+    public static function getDbStructure($file) {
160
+        $schemaManager = self::getMDB2SchemaManager();
161
+        return $schemaManager->getDbStructure($file);
162
+    }
163 163
 
164
-	/**
165
-	 * Creates tables from XML file
166
-	 * @param string $file file to read structure from
167
-	 * @return bool
168
-	 *
169
-	 * TODO: write more documentation
170
-	 */
171
-	public static function createDbFromStructure( $file ) {
172
-		$schemaManager = self::getMDB2SchemaManager();
173
-		$result = $schemaManager->createDbFromStructure($file);
174
-		return $result;
175
-	}
164
+    /**
165
+     * Creates tables from XML file
166
+     * @param string $file file to read structure from
167
+     * @return bool
168
+     *
169
+     * TODO: write more documentation
170
+     */
171
+    public static function createDbFromStructure( $file ) {
172
+        $schemaManager = self::getMDB2SchemaManager();
173
+        $result = $schemaManager->createDbFromStructure($file);
174
+        return $result;
175
+    }
176 176
 
177
-	/**
178
-	 * update the database schema
179
-	 * @param string $file file to read structure from
180
-	 * @throws Exception
181
-	 * @return string|boolean
182
-	 */
183
-	public static function updateDbFromStructure($file) {
184
-		$schemaManager = self::getMDB2SchemaManager();
185
-		try {
186
-			$result = $schemaManager->updateDbFromStructure($file);
187
-		} catch (Exception $e) {
188
-			\OCP\Util::writeLog('core', 'Failed to update database structure ('.$e.')', \OCP\Util::FATAL);
189
-			throw $e;
190
-		}
191
-		return $result;
192
-	}
177
+    /**
178
+     * update the database schema
179
+     * @param string $file file to read structure from
180
+     * @throws Exception
181
+     * @return string|boolean
182
+     */
183
+    public static function updateDbFromStructure($file) {
184
+        $schemaManager = self::getMDB2SchemaManager();
185
+        try {
186
+            $result = $schemaManager->updateDbFromStructure($file);
187
+        } catch (Exception $e) {
188
+            \OCP\Util::writeLog('core', 'Failed to update database structure ('.$e.')', \OCP\Util::FATAL);
189
+            throw $e;
190
+        }
191
+        return $result;
192
+    }
193 193
 
194
-	/**
195
-	 * remove all tables defined in a database structure xml file
196
-	 * @param string $file the xml file describing the tables
197
-	 */
198
-	public static function removeDBStructure($file) {
199
-		$schemaManager = self::getMDB2SchemaManager();
200
-		$schemaManager->removeDBStructure($file);
201
-	}
194
+    /**
195
+     * remove all tables defined in a database structure xml file
196
+     * @param string $file the xml file describing the tables
197
+     */
198
+    public static function removeDBStructure($file) {
199
+        $schemaManager = self::getMDB2SchemaManager();
200
+        $schemaManager->removeDBStructure($file);
201
+    }
202 202
 
203
-	/**
204
-	 * check if a result is an error and throws an exception, works with \Doctrine\DBAL\DBALException
205
-	 * @param mixed $result
206
-	 * @param string $message
207
-	 * @return void
208
-	 * @throws \OC\DatabaseException
209
-	 */
210
-	public static function raiseExceptionOnError($result, $message = null) {
211
-		if($result === false) {
212
-			if ($message === null) {
213
-				$message = self::getErrorMessage();
214
-			} else {
215
-				$message .= ', Root cause:' . self::getErrorMessage();
216
-			}
217
-			throw new \OC\DatabaseException($message, \OC::$server->getDatabaseConnection()->errorCode());
218
-		}
219
-	}
203
+    /**
204
+     * check if a result is an error and throws an exception, works with \Doctrine\DBAL\DBALException
205
+     * @param mixed $result
206
+     * @param string $message
207
+     * @return void
208
+     * @throws \OC\DatabaseException
209
+     */
210
+    public static function raiseExceptionOnError($result, $message = null) {
211
+        if($result === false) {
212
+            if ($message === null) {
213
+                $message = self::getErrorMessage();
214
+            } else {
215
+                $message .= ', Root cause:' . self::getErrorMessage();
216
+            }
217
+            throw new \OC\DatabaseException($message, \OC::$server->getDatabaseConnection()->errorCode());
218
+        }
219
+    }
220 220
 
221
-	/**
222
-	 * returns the error code and message as a string for logging
223
-	 * works with DoctrineException
224
-	 * @return string
225
-	 */
226
-	public static function getErrorMessage() {
227
-		$connection = \OC::$server->getDatabaseConnection();
228
-		return $connection->getError();
229
-	}
221
+    /**
222
+     * returns the error code and message as a string for logging
223
+     * works with DoctrineException
224
+     * @return string
225
+     */
226
+    public static function getErrorMessage() {
227
+        $connection = \OC::$server->getDatabaseConnection();
228
+        return $connection->getError();
229
+    }
230 230
 
231
-	/**
232
-	 * Checks if a table exists in the database - the database prefix will be prepended
233
-	 *
234
-	 * @param string $table
235
-	 * @return bool
236
-	 * @throws \OC\DatabaseException
237
-	 */
238
-	public static function tableExists($table) {
239
-		$connection = \OC::$server->getDatabaseConnection();
240
-		return $connection->tableExists($table);
241
-	}
231
+    /**
232
+     * Checks if a table exists in the database - the database prefix will be prepended
233
+     *
234
+     * @param string $table
235
+     * @return bool
236
+     * @throws \OC\DatabaseException
237
+     */
238
+    public static function tableExists($table) {
239
+        $connection = \OC::$server->getDatabaseConnection();
240
+        return $connection->tableExists($table);
241
+    }
242 242
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -53,7 +53,7 @@  discard block
 block discarded – undo
53 53
 	 *
54 54
 	 * SQL query via Doctrine prepare(), needs to be execute()'d!
55 55
 	 */
56
-	static public function prepare( $query , $limit = null, $offset = null, $isManipulation = null) {
56
+	static public function prepare($query, $limit = null, $offset = null, $isManipulation = null) {
57 57
 		$connection = \OC::$server->getDatabaseConnection();
58 58
 
59 59
 		if ($isManipulation === null) {
@@ -63,7 +63,7 @@  discard block
 block discarded – undo
63 63
 
64 64
 		// return the result
65 65
 		try {
66
-			$result =$connection->prepare($query, $limit, $offset);
66
+			$result = $connection->prepare($query, $limit, $offset);
67 67
 		} catch (\Doctrine\DBAL\DBALException $e) {
68 68
 			throw new \OC\DatabaseException($e->getMessage(), $query);
69 69
 		}
@@ -79,7 +79,7 @@  discard block
 block discarded – undo
79 79
 	 * @param string $sql
80 80
 	 * @return bool
81 81
 	 */
82
-	static public function isManipulation( $sql ) {
82
+	static public function isManipulation($sql) {
83 83
 		$selectOccurrence = stripos($sql, 'SELECT');
84 84
 		if ($selectOccurrence !== false && $selectOccurrence < 10) {
85 85
 			return false;
@@ -108,7 +108,7 @@  discard block
 block discarded – undo
108 108
 	 * @return OC_DB_StatementWrapper
109 109
 	 * @throws \OC\DatabaseException
110 110
 	 */
111
-	static public function executeAudited( $stmt, array $parameters = null) {
111
+	static public function executeAudited($stmt, array $parameters = null) {
112 112
 		if (is_string($stmt)) {
113 113
 			// convert to an array with 'sql'
114 114
 			if (stripos($stmt, 'LIMIT') !== false) { //OFFSET requires LIMIT, so we only need to check for LIMIT
@@ -121,14 +121,14 @@  discard block
 block discarded – undo
121 121
 		}
122 122
 		if (is_array($stmt)) {
123 123
 			// convert to prepared statement
124
-			if ( ! array_key_exists('sql', $stmt) ) {
124
+			if (!array_key_exists('sql', $stmt)) {
125 125
 				$message = 'statement array must at least contain key \'sql\'';
126 126
 				throw new \OC\DatabaseException($message);
127 127
 			}
128
-			if ( ! array_key_exists('limit', $stmt) ) {
128
+			if (!array_key_exists('limit', $stmt)) {
129 129
 				$stmt['limit'] = null;
130 130
 			}
131
-			if ( ! array_key_exists('limit', $stmt) ) {
131
+			if (!array_key_exists('limit', $stmt)) {
132 132
 				$stmt['offset'] = null;
133 133
 			}
134 134
 			$stmt = self::prepare($stmt['sql'], $stmt['limit'], $stmt['offset']);
@@ -139,9 +139,9 @@  discard block
 block discarded – undo
139 139
 			self::raiseExceptionOnError($result, 'Could not execute statement');
140 140
 		} else {
141 141
 			if (is_object($stmt)) {
142
-				$message = 'Expected a prepared statement or array got ' . get_class($stmt);
142
+				$message = 'Expected a prepared statement or array got '.get_class($stmt);
143 143
 			} else {
144
-				$message = 'Expected a prepared statement or array got ' . gettype($stmt);
144
+				$message = 'Expected a prepared statement or array got '.gettype($stmt);
145 145
 			}
146 146
 			throw new \OC\DatabaseException($message);
147 147
 		}
@@ -168,7 +168,7 @@  discard block
 block discarded – undo
168 168
 	 *
169 169
 	 * TODO: write more documentation
170 170
 	 */
171
-	public static function createDbFromStructure( $file ) {
171
+	public static function createDbFromStructure($file) {
172 172
 		$schemaManager = self::getMDB2SchemaManager();
173 173
 		$result = $schemaManager->createDbFromStructure($file);
174 174
 		return $result;
@@ -208,11 +208,11 @@  discard block
 block discarded – undo
208 208
 	 * @throws \OC\DatabaseException
209 209
 	 */
210 210
 	public static function raiseExceptionOnError($result, $message = null) {
211
-		if($result === false) {
211
+		if ($result === false) {
212 212
 			if ($message === null) {
213 213
 				$message = self::getErrorMessage();
214 214
 			} else {
215
-				$message .= ', Root cause:' . self::getErrorMessage();
215
+				$message .= ', Root cause:'.self::getErrorMessage();
216 216
 			}
217 217
 			throw new \OC\DatabaseException($message, \OC::$server->getDatabaseConnection()->errorCode());
218 218
 		}
Please login to merge, or discard this patch.
lib/private/legacy/files.php 4 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -334,7 +334,7 @@
 block discarded – undo
334 334
 	 *
335 335
 	 * @param int $size file size in bytes
336 336
 	 * @param array $files override '.htaccess' and '.user.ini' locations
337
-	 * @return bool false on failure, size on success
337
+	 * @return integer false on failure, size on success
338 338
 	 */
339 339
 	public static function setUploadLimit($size, $files = []) {
340 340
 		//don't allow user to break his config
Please login to merge, or discard this patch.
Spacing   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -115,7 +115,7 @@  discard block
 block discarded – undo
115 115
 			}
116 116
 
117 117
 			if (!is_array($files)) {
118
-				$filename = $dir . '/' . $files;
118
+				$filename = $dir.'/'.$files;
119 119
 				if (!$view->is_dir($filename)) {
120 120
 					self::getSingleFile($view, $dir, $files, is_null($params) ? array() : $params);
121 121
 					return;
@@ -130,9 +130,9 @@  discard block
 block discarded – undo
130 130
 					$name = $basename;
131 131
 				}
132 132
 
133
-				$filename = $dir . '/' . $name;
133
+				$filename = $dir.'/'.$name;
134 134
 			} else {
135
-				$filename = $dir . '/' . $files;
135
+				$filename = $dir.'/'.$files;
136 136
 				$getType = self::ZIP_DIR;
137 137
 				// downloading root ?
138 138
 				if ($files !== '') {
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
 			ignore_user_abort(true);
152 152
 			if ($getType === self::ZIP_FILES) {
153 153
 				foreach ($files as $file) {
154
-					$file = $dir . '/' . $file;
154
+					$file = $dir.'/'.$file;
155 155
 					if (\OC\Files\Filesystem::is_file($file)) {
156 156
 						$fileSize = \OC\Files\Filesystem::filesize($file);
157 157
 						$fileTime = \OC\Files\Filesystem::filemtime($file);
@@ -163,7 +163,7 @@  discard block
 block discarded – undo
163 163
 					}
164 164
 				}
165 165
 			} elseif ($getType === self::ZIP_DIR) {
166
-				$file = $dir . '/' . $files;
166
+				$file = $dir.'/'.$files;
167 167
 				$streamer->addDirRecursive($file);
168 168
 			}
169 169
 			$streamer->finalize();
@@ -195,7 +195,7 @@  discard block
 block discarded – undo
195 195
 	 * @return array $rangeArray ('from'=>int,'to'=>int), ...
196 196
 	 */
197 197
 	private static function parseHttpRangeHeader($rangeHeaderPos, $fileSize) {
198
-		$rArray=explode(',', $rangeHeaderPos);
198
+		$rArray = explode(',', $rangeHeaderPos);
199 199
 		$minOffset = 0;
200 200
 		$ind = 0;
201 201
 
@@ -207,7 +207,7 @@  discard block
 block discarded – undo
207 207
 				if ($ranges[0] < $minOffset) { // case: bytes=500-700,601-999
208 208
 					$ranges[0] = $minOffset;
209 209
 				}
210
-				if ($ind > 0 && $rangeArray[$ind-1]['to']+1 == $ranges[0]) { // case: bytes=500-600,601-999
210
+				if ($ind > 0 && $rangeArray[$ind - 1]['to'] + 1 == $ranges[0]) { // case: bytes=500-600,601-999
211 211
 					$ind--;
212 212
 					$ranges[0] = $rangeArray[$ind]['from'];
213 213
 				}
@@ -216,9 +216,9 @@  discard block
 block discarded – undo
216 216
 			if (is_numeric($ranges[0]) && is_numeric($ranges[1]) && $ranges[0] < $fileSize && $ranges[0] <= $ranges[1]) {
217 217
 				// case: x-x
218 218
 				if ($ranges[1] >= $fileSize) {
219
-					$ranges[1] = $fileSize-1;
219
+					$ranges[1] = $fileSize - 1;
220 220
 				}
221
-				$rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $ranges[1], 'size' => $fileSize );
221
+				$rangeArray[$ind++] = array('from' => $ranges[0], 'to' => $ranges[1], 'size' => $fileSize);
222 222
 				$minOffset = $ranges[1] + 1;
223 223
 				if ($minOffset >= $fileSize) {
224 224
 					break;
@@ -226,7 +226,7 @@  discard block
 block discarded – undo
226 226
 			}
227 227
 			elseif (is_numeric($ranges[0]) && $ranges[0] < $fileSize) {
228 228
 				// case: x-
229
-				$rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $fileSize-1, 'size' => $fileSize );
229
+				$rangeArray[$ind++] = array('from' => $ranges[0], 'to' => $fileSize - 1, 'size' => $fileSize);
230 230
 				break;
231 231
 			}
232 232
 			elseif (is_numeric($ranges[1])) {
@@ -234,7 +234,7 @@  discard block
 block discarded – undo
234 234
 				if ($ranges[1] > $fileSize) {
235 235
 					$ranges[1] = $fileSize;
236 236
 				}
237
-				$rangeArray[$ind++] = array( 'from' => $fileSize-$ranges[1], 'to' => $fileSize-1, 'size' => $fileSize );
237
+				$rangeArray[$ind++] = array('from' => $fileSize - $ranges[1], 'to' => $fileSize - 1, 'size' => $fileSize);
238 238
 				break;
239 239
 			}
240 240
 		}
@@ -248,7 +248,7 @@  discard block
 block discarded – undo
248 248
 	 * @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header
249 249
 	 */
250 250
 	private static function getSingleFile($view, $dir, $name, $params) {
251
-		$filename = $dir . '/' . $name;
251
+		$filename = $dir.'/'.$name;
252 252
 		OC_Util::obEnd();
253 253
 		$view->lockFile($filename, ILockingProvider::LOCK_SHARED);
254 254
 		
@@ -314,17 +314,17 @@  discard block
 block discarded – undo
314 314
 	 */
315 315
 	public static function lockFiles($view, $dir, $files) {
316 316
 		if (!is_array($files)) {
317
-			$file = $dir . '/' . $files;
317
+			$file = $dir.'/'.$files;
318 318
 			$files = [$file];
319 319
 		}
320 320
 		foreach ($files as $file) {
321
-			$file = $dir . '/' . $file;
321
+			$file = $dir.'/'.$file;
322 322
 			$view->lockFile($file, ILockingProvider::LOCK_SHARED);
323 323
 			if ($view->is_dir($file)) {
324 324
 				$contents = $view->getDirectoryContent($file);
325 325
 				$contents = array_map(function($fileInfo) use ($file) {
326 326
 					/** @var \OCP\Files\FileInfo $fileInfo */
327
-					return $file . '/' . $fileInfo->getName();
327
+					return $file.'/'.$fileInfo->getName();
328 328
 				}, $contents);
329 329
 				self::lockFiles($view, $dir, $contents);
330 330
 			}
@@ -353,8 +353,8 @@  discard block
 block discarded – undo
353 353
 
354 354
 		// default locations if not overridden by $files
355 355
 		$files = array_merge([
356
-			'.htaccess' => OC::$SERVERROOT . '/.htaccess',
357
-			'.user.ini' => OC::$SERVERROOT . '/.user.ini'
356
+			'.htaccess' => OC::$SERVERROOT.'/.htaccess',
357
+			'.user.ini' => OC::$SERVERROOT.'/.user.ini'
358 358
 		], $files);
359 359
 
360 360
 		$updateFiles = [
@@ -375,7 +375,7 @@  discard block
 block discarded – undo
375 375
 			$handle = @fopen($filename, 'r+');
376 376
 			if (!$handle) {
377 377
 				\OCP\Util::writeLog('files',
378
-					'Can\'t write upload limit to ' . $filename . '. Please check the file permissions',
378
+					'Can\'t write upload limit to '.$filename.'. Please check the file permissions',
379 379
 					\OCP\Util::WARN);
380 380
 				$success = false;
381 381
 				continue; // try to update as many files as possible
@@ -395,7 +395,7 @@  discard block
 block discarded – undo
395 395
 					$content = $newContent;
396 396
 				}
397 397
 				if ($hasReplaced === 0) {
398
-					$content .= "\n" . $setting;
398
+					$content .= "\n".$setting;
399 399
 				}
400 400
 			}
401 401
 
@@ -426,12 +426,12 @@  discard block
 block discarded – undo
426 426
 		}
427 427
 		if ($getType === self::ZIP_FILES) {
428 428
 			foreach ($files as $file) {
429
-				$file = $dir . '/' . $file;
429
+				$file = $dir.'/'.$file;
430 430
 				$view->unlockFile($file, ILockingProvider::LOCK_SHARED);
431 431
 			}
432 432
 		}
433 433
 		if ($getType === self::ZIP_DIR) {
434
-			$file = $dir . '/' . $files;
434
+			$file = $dir.'/'.$files;
435 435
 			$view->unlockFile($file, ILockingProvider::LOCK_SHARED);
436 436
 		}
437 437
 	}
Please login to merge, or discard this patch.
Braces   +6 added lines, -12 removed lines patch added patch discarded remove patch
@@ -83,13 +83,11 @@  discard block
 block discarded – undo
83 83
 			    if (count($rangeArray) > 1) {
84 84
 				$type = 'multipart/byteranges; boundary='.self::getBoundary();
85 85
 				// no Content-Length header here
86
-			    }
87
-			    else {
86
+			    } else {
88 87
 				header(sprintf('Content-Range: bytes %d-%d/%d', $rangeArray[0]['from'], $rangeArray[0]['to'], $fileSize), true);
89 88
 				OC_Response::setContentLengthHeader($rangeArray[0]['to'] - $rangeArray[0]['from'] + 1);
90 89
 			    }
91
-			}
92
-			else {
90
+			} else {
93 91
 			    OC_Response::setContentLengthHeader($fileSize);
94 92
 			}
95 93
 		}
@@ -223,13 +221,11 @@  discard block
 block discarded – undo
223 221
 				if ($minOffset >= $fileSize) {
224 222
 					break;
225 223
 				}
226
-			}
227
-			elseif (is_numeric($ranges[0]) && $ranges[0] < $fileSize) {
224
+			} elseif (is_numeric($ranges[0]) && $ranges[0] < $fileSize) {
228 225
 				// case: x-
229 226
 				$rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $fileSize-1, 'size' => $fileSize );
230 227
 				break;
231
-			}
232
-			elseif (is_numeric($ranges[1])) {
228
+			} elseif (is_numeric($ranges[1])) {
233 229
 				// case: -x
234 230
 				if ($ranges[1] > $fileSize) {
235 231
 					$ranges[1] = $fileSize;
@@ -277,8 +273,7 @@  discard block
 block discarded – undo
277 273
 			try {
278 274
 			    if (count($rangeArray) == 1) {
279 275
 				$view->readfilePart($filename, $rangeArray[0]['from'], $rangeArray[0]['to']);
280
-			    }
281
-			    else {
276
+			    } else {
282 277
 				// check if file is seekable (if not throw UnseekableException)
283 278
 				// we have to check it before body contents
284 279
 				$view->readfilePart($filename, $rangeArray[0]['size'], $rangeArray[0]['size']);
@@ -301,8 +296,7 @@  discard block
 block discarded – undo
301 296
 			    self::sendHeaders($filename, $name, array());
302 297
 			    $view->readfile($filename);
303 298
 			}
304
-		}
305
-		else {
299
+		} else {
306 300
 		    $view->readfile($filename);
307 301
 		}
308 302
 	}
Please login to merge, or discard this patch.
Indentation   +388 added lines, -388 removed lines patch added patch discarded remove patch
@@ -46,396 +46,396 @@
 block discarded – undo
46 46
  *
47 47
  */
48 48
 class OC_Files {
49
-	const FILE = 1;
50
-	const ZIP_FILES = 2;
51
-	const ZIP_DIR = 3;
52
-
53
-	const UPLOAD_MIN_LIMIT_BYTES = 1048576; // 1 MiB
54
-
55
-
56
-	private static $multipartBoundary = '';
57
-
58
-	/**
59
-	 * @return string
60
-	 */
61
-	private static function getBoundary() {
62
-		if (empty(self::$multipartBoundary)) {
63
-			self::$multipartBoundary = md5(mt_rand());
64
-		}
65
-		return self::$multipartBoundary;
66
-	}
67
-
68
-	/**
69
-	 * @param string $filename
70
-	 * @param string $name
71
-	 * @param array $rangeArray ('from'=>int,'to'=>int), ...
72
-	 */
73
-	private static function sendHeaders($filename, $name, array $rangeArray) {
74
-		OC_Response::setContentDispositionHeader($name, 'attachment');
75
-		header('Content-Transfer-Encoding: binary', true);
76
-		OC_Response::disableCaching();
77
-		$fileSize = \OC\Files\Filesystem::filesize($filename);
78
-		$type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename));
79
-		if ($fileSize > -1) {
80
-			if (!empty($rangeArray)) {
81
-			    header('HTTP/1.1 206 Partial Content', true);
82
-			    header('Accept-Ranges: bytes', true);
83
-			    if (count($rangeArray) > 1) {
84
-				$type = 'multipart/byteranges; boundary='.self::getBoundary();
85
-				// no Content-Length header here
86
-			    }
87
-			    else {
88
-				header(sprintf('Content-Range: bytes %d-%d/%d', $rangeArray[0]['from'], $rangeArray[0]['to'], $fileSize), true);
89
-				OC_Response::setContentLengthHeader($rangeArray[0]['to'] - $rangeArray[0]['from'] + 1);
90
-			    }
91
-			}
92
-			else {
93
-			    OC_Response::setContentLengthHeader($fileSize);
94
-			}
95
-		}
96
-		header('Content-Type: '.$type, true);
97
-	}
98
-
99
-	/**
100
-	 * return the content of a file or return a zip file containing multiple files
101
-	 *
102
-	 * @param string $dir
103
-	 * @param string $files ; separated list of files to download
104
-	 * @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header
105
-	 */
106
-	public static function get($dir, $files, $params = null) {
107
-
108
-		$view = \OC\Files\Filesystem::getView();
109
-		$getType = self::FILE;
110
-		$filename = $dir;
111
-		try {
112
-
113
-			if (is_array($files) && count($files) === 1) {
114
-				$files = $files[0];
115
-			}
116
-
117
-			if (!is_array($files)) {
118
-				$filename = $dir . '/' . $files;
119
-				if (!$view->is_dir($filename)) {
120
-					self::getSingleFile($view, $dir, $files, is_null($params) ? array() : $params);
121
-					return;
122
-				}
123
-			}
124
-
125
-			$name = 'download';
126
-			if (is_array($files)) {
127
-				$getType = self::ZIP_FILES;
128
-				$basename = basename($dir);
129
-				if ($basename) {
130
-					$name = $basename;
131
-				}
132
-
133
-				$filename = $dir . '/' . $name;
134
-			} else {
135
-				$filename = $dir . '/' . $files;
136
-				$getType = self::ZIP_DIR;
137
-				// downloading root ?
138
-				if ($files !== '') {
139
-					$name = $files;
140
-				}
141
-			}
142
-
143
-			$streamer = new Streamer();
144
-			OC_Util::obEnd();
145
-
146
-			self::lockFiles($view, $dir, $files);
147
-
148
-			$streamer->sendHeaders($name);
149
-			$executionTime = intval(OC::$server->getIniWrapper()->getNumeric('max_execution_time'));
150
-			if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
151
-				@set_time_limit(0);
152
-			}
153
-			ignore_user_abort(true);
154
-			if ($getType === self::ZIP_FILES) {
155
-				foreach ($files as $file) {
156
-					$file = $dir . '/' . $file;
157
-					if (\OC\Files\Filesystem::is_file($file)) {
158
-						$fileSize = \OC\Files\Filesystem::filesize($file);
159
-						$fileTime = \OC\Files\Filesystem::filemtime($file);
160
-						$fh = \OC\Files\Filesystem::fopen($file, 'r');
161
-						$streamer->addFileFromStream($fh, basename($file), $fileSize, $fileTime);
162
-						fclose($fh);
163
-					} elseif (\OC\Files\Filesystem::is_dir($file)) {
164
-						$streamer->addDirRecursive($file);
165
-					}
166
-				}
167
-			} elseif ($getType === self::ZIP_DIR) {
168
-				$file = $dir . '/' . $files;
169
-				$streamer->addDirRecursive($file);
170
-			}
171
-			$streamer->finalize();
172
-			set_time_limit($executionTime);
173
-			self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
174
-		} catch (\OCP\Lock\LockedException $ex) {
175
-			self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
176
-			OC::$server->getLogger()->logException($ex);
177
-			$l = \OC::$server->getL10N('core');
178
-			$hint = method_exists($ex, 'getHint') ? $ex->getHint() : '';
179
-			\OC_Template::printErrorPage($l->t('File is currently busy, please try again later'), $hint);
180
-		} catch (\OCP\Files\ForbiddenException $ex) {
181
-			self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
182
-			OC::$server->getLogger()->logException($ex);
183
-			$l = \OC::$server->getL10N('core');
184
-			\OC_Template::printErrorPage($l->t('Can\'t read file'), $ex->getMessage());
185
-		} catch (\Exception $ex) {
186
-			self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
187
-			OC::$server->getLogger()->logException($ex);
188
-			$l = \OC::$server->getL10N('core');
189
-			$hint = method_exists($ex, 'getHint') ? $ex->getHint() : '';
190
-			\OC_Template::printErrorPage($l->t('Can\'t read file'), $hint);
191
-		}
192
-	}
193
-
194
-	/**
195
-	 * @param string $rangeHeaderPos
196
-	 * @param int $fileSize
197
-	 * @return array $rangeArray ('from'=>int,'to'=>int), ...
198
-	 */
199
-	private static function parseHttpRangeHeader($rangeHeaderPos, $fileSize) {
200
-		$rArray=explode(',', $rangeHeaderPos);
201
-		$minOffset = 0;
202
-		$ind = 0;
203
-
204
-		$rangeArray = array();
205
-
206
-		foreach ($rArray as $value) {
207
-			$ranges = explode('-', $value);
208
-			if (is_numeric($ranges[0])) {
209
-				if ($ranges[0] < $minOffset) { // case: bytes=500-700,601-999
210
-					$ranges[0] = $minOffset;
211
-				}
212
-				if ($ind > 0 && $rangeArray[$ind-1]['to']+1 == $ranges[0]) { // case: bytes=500-600,601-999
213
-					$ind--;
214
-					$ranges[0] = $rangeArray[$ind]['from'];
215
-				}
216
-			}
217
-
218
-			if (is_numeric($ranges[0]) && is_numeric($ranges[1]) && $ranges[0] < $fileSize && $ranges[0] <= $ranges[1]) {
219
-				// case: x-x
220
-				if ($ranges[1] >= $fileSize) {
221
-					$ranges[1] = $fileSize-1;
222
-				}
223
-				$rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $ranges[1], 'size' => $fileSize );
224
-				$minOffset = $ranges[1] + 1;
225
-				if ($minOffset >= $fileSize) {
226
-					break;
227
-				}
228
-			}
229
-			elseif (is_numeric($ranges[0]) && $ranges[0] < $fileSize) {
230
-				// case: x-
231
-				$rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $fileSize-1, 'size' => $fileSize );
232
-				break;
233
-			}
234
-			elseif (is_numeric($ranges[1])) {
235
-				// case: -x
236
-				if ($ranges[1] > $fileSize) {
237
-					$ranges[1] = $fileSize;
238
-				}
239
-				$rangeArray[$ind++] = array( 'from' => $fileSize-$ranges[1], 'to' => $fileSize-1, 'size' => $fileSize );
240
-				break;
241
-			}
242
-		}
243
-		return $rangeArray;
244
-	}
245
-
246
-	/**
247
-	 * @param View $view
248
-	 * @param string $name
249
-	 * @param string $dir
250
-	 * @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header
251
-	 */
252
-	private static function getSingleFile($view, $dir, $name, $params) {
253
-		$filename = $dir . '/' . $name;
254
-		OC_Util::obEnd();
255
-		$view->lockFile($filename, ILockingProvider::LOCK_SHARED);
49
+    const FILE = 1;
50
+    const ZIP_FILES = 2;
51
+    const ZIP_DIR = 3;
52
+
53
+    const UPLOAD_MIN_LIMIT_BYTES = 1048576; // 1 MiB
54
+
55
+
56
+    private static $multipartBoundary = '';
57
+
58
+    /**
59
+     * @return string
60
+     */
61
+    private static function getBoundary() {
62
+        if (empty(self::$multipartBoundary)) {
63
+            self::$multipartBoundary = md5(mt_rand());
64
+        }
65
+        return self::$multipartBoundary;
66
+    }
67
+
68
+    /**
69
+     * @param string $filename
70
+     * @param string $name
71
+     * @param array $rangeArray ('from'=>int,'to'=>int), ...
72
+     */
73
+    private static function sendHeaders($filename, $name, array $rangeArray) {
74
+        OC_Response::setContentDispositionHeader($name, 'attachment');
75
+        header('Content-Transfer-Encoding: binary', true);
76
+        OC_Response::disableCaching();
77
+        $fileSize = \OC\Files\Filesystem::filesize($filename);
78
+        $type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename));
79
+        if ($fileSize > -1) {
80
+            if (!empty($rangeArray)) {
81
+                header('HTTP/1.1 206 Partial Content', true);
82
+                header('Accept-Ranges: bytes', true);
83
+                if (count($rangeArray) > 1) {
84
+                $type = 'multipart/byteranges; boundary='.self::getBoundary();
85
+                // no Content-Length header here
86
+                }
87
+                else {
88
+                header(sprintf('Content-Range: bytes %d-%d/%d', $rangeArray[0]['from'], $rangeArray[0]['to'], $fileSize), true);
89
+                OC_Response::setContentLengthHeader($rangeArray[0]['to'] - $rangeArray[0]['from'] + 1);
90
+                }
91
+            }
92
+            else {
93
+                OC_Response::setContentLengthHeader($fileSize);
94
+            }
95
+        }
96
+        header('Content-Type: '.$type, true);
97
+    }
98
+
99
+    /**
100
+     * return the content of a file or return a zip file containing multiple files
101
+     *
102
+     * @param string $dir
103
+     * @param string $files ; separated list of files to download
104
+     * @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header
105
+     */
106
+    public static function get($dir, $files, $params = null) {
107
+
108
+        $view = \OC\Files\Filesystem::getView();
109
+        $getType = self::FILE;
110
+        $filename = $dir;
111
+        try {
112
+
113
+            if (is_array($files) && count($files) === 1) {
114
+                $files = $files[0];
115
+            }
116
+
117
+            if (!is_array($files)) {
118
+                $filename = $dir . '/' . $files;
119
+                if (!$view->is_dir($filename)) {
120
+                    self::getSingleFile($view, $dir, $files, is_null($params) ? array() : $params);
121
+                    return;
122
+                }
123
+            }
124
+
125
+            $name = 'download';
126
+            if (is_array($files)) {
127
+                $getType = self::ZIP_FILES;
128
+                $basename = basename($dir);
129
+                if ($basename) {
130
+                    $name = $basename;
131
+                }
132
+
133
+                $filename = $dir . '/' . $name;
134
+            } else {
135
+                $filename = $dir . '/' . $files;
136
+                $getType = self::ZIP_DIR;
137
+                // downloading root ?
138
+                if ($files !== '') {
139
+                    $name = $files;
140
+                }
141
+            }
142
+
143
+            $streamer = new Streamer();
144
+            OC_Util::obEnd();
145
+
146
+            self::lockFiles($view, $dir, $files);
147
+
148
+            $streamer->sendHeaders($name);
149
+            $executionTime = intval(OC::$server->getIniWrapper()->getNumeric('max_execution_time'));
150
+            if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
151
+                @set_time_limit(0);
152
+            }
153
+            ignore_user_abort(true);
154
+            if ($getType === self::ZIP_FILES) {
155
+                foreach ($files as $file) {
156
+                    $file = $dir . '/' . $file;
157
+                    if (\OC\Files\Filesystem::is_file($file)) {
158
+                        $fileSize = \OC\Files\Filesystem::filesize($file);
159
+                        $fileTime = \OC\Files\Filesystem::filemtime($file);
160
+                        $fh = \OC\Files\Filesystem::fopen($file, 'r');
161
+                        $streamer->addFileFromStream($fh, basename($file), $fileSize, $fileTime);
162
+                        fclose($fh);
163
+                    } elseif (\OC\Files\Filesystem::is_dir($file)) {
164
+                        $streamer->addDirRecursive($file);
165
+                    }
166
+                }
167
+            } elseif ($getType === self::ZIP_DIR) {
168
+                $file = $dir . '/' . $files;
169
+                $streamer->addDirRecursive($file);
170
+            }
171
+            $streamer->finalize();
172
+            set_time_limit($executionTime);
173
+            self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
174
+        } catch (\OCP\Lock\LockedException $ex) {
175
+            self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
176
+            OC::$server->getLogger()->logException($ex);
177
+            $l = \OC::$server->getL10N('core');
178
+            $hint = method_exists($ex, 'getHint') ? $ex->getHint() : '';
179
+            \OC_Template::printErrorPage($l->t('File is currently busy, please try again later'), $hint);
180
+        } catch (\OCP\Files\ForbiddenException $ex) {
181
+            self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
182
+            OC::$server->getLogger()->logException($ex);
183
+            $l = \OC::$server->getL10N('core');
184
+            \OC_Template::printErrorPage($l->t('Can\'t read file'), $ex->getMessage());
185
+        } catch (\Exception $ex) {
186
+            self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
187
+            OC::$server->getLogger()->logException($ex);
188
+            $l = \OC::$server->getL10N('core');
189
+            $hint = method_exists($ex, 'getHint') ? $ex->getHint() : '';
190
+            \OC_Template::printErrorPage($l->t('Can\'t read file'), $hint);
191
+        }
192
+    }
193
+
194
+    /**
195
+     * @param string $rangeHeaderPos
196
+     * @param int $fileSize
197
+     * @return array $rangeArray ('from'=>int,'to'=>int), ...
198
+     */
199
+    private static function parseHttpRangeHeader($rangeHeaderPos, $fileSize) {
200
+        $rArray=explode(',', $rangeHeaderPos);
201
+        $minOffset = 0;
202
+        $ind = 0;
203
+
204
+        $rangeArray = array();
205
+
206
+        foreach ($rArray as $value) {
207
+            $ranges = explode('-', $value);
208
+            if (is_numeric($ranges[0])) {
209
+                if ($ranges[0] < $minOffset) { // case: bytes=500-700,601-999
210
+                    $ranges[0] = $minOffset;
211
+                }
212
+                if ($ind > 0 && $rangeArray[$ind-1]['to']+1 == $ranges[0]) { // case: bytes=500-600,601-999
213
+                    $ind--;
214
+                    $ranges[0] = $rangeArray[$ind]['from'];
215
+                }
216
+            }
217
+
218
+            if (is_numeric($ranges[0]) && is_numeric($ranges[1]) && $ranges[0] < $fileSize && $ranges[0] <= $ranges[1]) {
219
+                // case: x-x
220
+                if ($ranges[1] >= $fileSize) {
221
+                    $ranges[1] = $fileSize-1;
222
+                }
223
+                $rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $ranges[1], 'size' => $fileSize );
224
+                $minOffset = $ranges[1] + 1;
225
+                if ($minOffset >= $fileSize) {
226
+                    break;
227
+                }
228
+            }
229
+            elseif (is_numeric($ranges[0]) && $ranges[0] < $fileSize) {
230
+                // case: x-
231
+                $rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $fileSize-1, 'size' => $fileSize );
232
+                break;
233
+            }
234
+            elseif (is_numeric($ranges[1])) {
235
+                // case: -x
236
+                if ($ranges[1] > $fileSize) {
237
+                    $ranges[1] = $fileSize;
238
+                }
239
+                $rangeArray[$ind++] = array( 'from' => $fileSize-$ranges[1], 'to' => $fileSize-1, 'size' => $fileSize );
240
+                break;
241
+            }
242
+        }
243
+        return $rangeArray;
244
+    }
245
+
246
+    /**
247
+     * @param View $view
248
+     * @param string $name
249
+     * @param string $dir
250
+     * @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header
251
+     */
252
+    private static function getSingleFile($view, $dir, $name, $params) {
253
+        $filename = $dir . '/' . $name;
254
+        OC_Util::obEnd();
255
+        $view->lockFile($filename, ILockingProvider::LOCK_SHARED);
256 256
 		
257
-		$rangeArray = array();
257
+        $rangeArray = array();
258 258
 
259
-		if (isset($params['range']) && substr($params['range'], 0, 6) === 'bytes=') {
260
-			$rangeArray = self::parseHttpRangeHeader(substr($params['range'], 6), 
261
-								 \OC\Files\Filesystem::filesize($filename));
262
-		}
259
+        if (isset($params['range']) && substr($params['range'], 0, 6) === 'bytes=') {
260
+            $rangeArray = self::parseHttpRangeHeader(substr($params['range'], 6), 
261
+                                    \OC\Files\Filesystem::filesize($filename));
262
+        }
263 263
 		
264
-		if (\OC\Files\Filesystem::isReadable($filename)) {
265
-			self::sendHeaders($filename, $name, $rangeArray);
266
-		} elseif (!\OC\Files\Filesystem::file_exists($filename)) {
267
-			header("HTTP/1.1 404 Not Found");
268
-			$tmpl = new OC_Template('', '404', 'guest');
269
-			$tmpl->printPage();
270
-			exit();
271
-		} else {
272
-			header("HTTP/1.1 403 Forbidden");
273
-			die('403 Forbidden');
274
-		}
275
-		if (isset($params['head']) && $params['head']) {
276
-			return;
277
-		}
278
-		if (!empty($rangeArray)) {
279
-			try {
280
-			    if (count($rangeArray) == 1) {
281
-				$view->readfilePart($filename, $rangeArray[0]['from'], $rangeArray[0]['to']);
282
-			    }
283
-			    else {
284
-				// check if file is seekable (if not throw UnseekableException)
285
-				// we have to check it before body contents
286
-				$view->readfilePart($filename, $rangeArray[0]['size'], $rangeArray[0]['size']);
287
-
288
-				$type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename));
289
-
290
-				foreach ($rangeArray as $range) {
291
-				    echo "\r\n--".self::getBoundary()."\r\n".
292
-				         "Content-type: ".$type."\r\n".
293
-				         "Content-range: bytes ".$range['from']."-".$range['to']."/".$range['size']."\r\n\r\n";
294
-				    $view->readfilePart($filename, $range['from'], $range['to']);
295
-				}
296
-				echo "\r\n--".self::getBoundary()."--\r\n";
297
-			    }
298
-			} catch (\OCP\Files\UnseekableException $ex) {
299
-			    // file is unseekable
300
-			    header_remove('Accept-Ranges');
301
-			    header_remove('Content-Range');
302
-			    header("HTTP/1.1 200 OK");
303
-			    self::sendHeaders($filename, $name, array());
304
-			    $view->readfile($filename);
305
-			}
306
-		}
307
-		else {
308
-		    $view->readfile($filename);
309
-		}
310
-	}
311
-
312
-	/**
313
-	 * @param View $view
314
-	 * @param string $dir
315
-	 * @param string[]|string $files
316
-	 */
317
-	public static function lockFiles($view, $dir, $files) {
318
-		if (!is_array($files)) {
319
-			$file = $dir . '/' . $files;
320
-			$files = [$file];
321
-		}
322
-		foreach ($files as $file) {
323
-			$file = $dir . '/' . $file;
324
-			$view->lockFile($file, ILockingProvider::LOCK_SHARED);
325
-			if ($view->is_dir($file)) {
326
-				$contents = $view->getDirectoryContent($file);
327
-				$contents = array_map(function($fileInfo) use ($file) {
328
-					/** @var \OCP\Files\FileInfo $fileInfo */
329
-					return $file . '/' . $fileInfo->getName();
330
-				}, $contents);
331
-				self::lockFiles($view, $dir, $contents);
332
-			}
333
-		}
334
-	}
335
-
336
-	/**
337
-	 * set the maximum upload size limit for apache hosts using .htaccess
338
-	 *
339
-	 * @param int $size file size in bytes
340
-	 * @param array $files override '.htaccess' and '.user.ini' locations
341
-	 * @return bool false on failure, size on success
342
-	 */
343
-	public static function setUploadLimit($size, $files = []) {
344
-		//don't allow user to break his config
345
-		$size = intval($size);
346
-		if ($size < self::UPLOAD_MIN_LIMIT_BYTES) {
347
-			return false;
348
-		}
349
-		$size = OC_Helper::phpFileSize($size);
350
-
351
-		$phpValueKeys = array(
352
-			'upload_max_filesize',
353
-			'post_max_size'
354
-		);
355
-
356
-		// default locations if not overridden by $files
357
-		$files = array_merge([
358
-			'.htaccess' => OC::$SERVERROOT . '/.htaccess',
359
-			'.user.ini' => OC::$SERVERROOT . '/.user.ini'
360
-		], $files);
361
-
362
-		$updateFiles = [
363
-			$files['.htaccess'] => [
364
-				'pattern' => '/php_value %1$s (\S)*/',
365
-				'setting' => 'php_value %1$s %2$s'
366
-			],
367
-			$files['.user.ini'] => [
368
-				'pattern' => '/%1$s=(\S)*/',
369
-				'setting' => '%1$s=%2$s'
370
-			]
371
-		];
372
-
373
-		$success = true;
374
-
375
-		foreach ($updateFiles as $filename => $patternMap) {
376
-			// suppress warnings from fopen()
377
-			$handle = @fopen($filename, 'r+');
378
-			if (!$handle) {
379
-				\OCP\Util::writeLog('files',
380
-					'Can\'t write upload limit to ' . $filename . '. Please check the file permissions',
381
-					\OCP\Util::WARN);
382
-				$success = false;
383
-				continue; // try to update as many files as possible
384
-			}
385
-
386
-			$content = '';
387
-			while (!feof($handle)) {
388
-				$content .= fread($handle, 1000);
389
-			}
390
-
391
-			foreach ($phpValueKeys as $key) {
392
-				$pattern = vsprintf($patternMap['pattern'], [$key]);
393
-				$setting = vsprintf($patternMap['setting'], [$key, $size]);
394
-				$hasReplaced = 0;
395
-				$newContent = preg_replace($pattern, $setting, $content, 2, $hasReplaced);
396
-				if ($newContent !== null) {
397
-					$content = $newContent;
398
-				}
399
-				if ($hasReplaced === 0) {
400
-					$content .= "\n" . $setting;
401
-				}
402
-			}
403
-
404
-			// write file back
405
-			ftruncate($handle, 0);
406
-			rewind($handle);
407
-			fwrite($handle, $content);
408
-
409
-			fclose($handle);
410
-		}
411
-
412
-		if ($success) {
413
-			return OC_Helper::computerFileSize($size);
414
-		}
415
-		return false;
416
-	}
417
-
418
-	/**
419
-	 * @param string $dir
420
-	 * @param $files
421
-	 * @param integer $getType
422
-	 * @param View $view
423
-	 * @param string $filename
424
-	 */
425
-	private static function unlockAllTheFiles($dir, $files, $getType, $view, $filename) {
426
-		if ($getType === self::FILE) {
427
-			$view->unlockFile($filename, ILockingProvider::LOCK_SHARED);
428
-		}
429
-		if ($getType === self::ZIP_FILES) {
430
-			foreach ($files as $file) {
431
-				$file = $dir . '/' . $file;
432
-				$view->unlockFile($file, ILockingProvider::LOCK_SHARED);
433
-			}
434
-		}
435
-		if ($getType === self::ZIP_DIR) {
436
-			$file = $dir . '/' . $files;
437
-			$view->unlockFile($file, ILockingProvider::LOCK_SHARED);
438
-		}
439
-	}
264
+        if (\OC\Files\Filesystem::isReadable($filename)) {
265
+            self::sendHeaders($filename, $name, $rangeArray);
266
+        } elseif (!\OC\Files\Filesystem::file_exists($filename)) {
267
+            header("HTTP/1.1 404 Not Found");
268
+            $tmpl = new OC_Template('', '404', 'guest');
269
+            $tmpl->printPage();
270
+            exit();
271
+        } else {
272
+            header("HTTP/1.1 403 Forbidden");
273
+            die('403 Forbidden');
274
+        }
275
+        if (isset($params['head']) && $params['head']) {
276
+            return;
277
+        }
278
+        if (!empty($rangeArray)) {
279
+            try {
280
+                if (count($rangeArray) == 1) {
281
+                $view->readfilePart($filename, $rangeArray[0]['from'], $rangeArray[0]['to']);
282
+                }
283
+                else {
284
+                // check if file is seekable (if not throw UnseekableException)
285
+                // we have to check it before body contents
286
+                $view->readfilePart($filename, $rangeArray[0]['size'], $rangeArray[0]['size']);
287
+
288
+                $type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename));
289
+
290
+                foreach ($rangeArray as $range) {
291
+                    echo "\r\n--".self::getBoundary()."\r\n".
292
+                            "Content-type: ".$type."\r\n".
293
+                            "Content-range: bytes ".$range['from']."-".$range['to']."/".$range['size']."\r\n\r\n";
294
+                    $view->readfilePart($filename, $range['from'], $range['to']);
295
+                }
296
+                echo "\r\n--".self::getBoundary()."--\r\n";
297
+                }
298
+            } catch (\OCP\Files\UnseekableException $ex) {
299
+                // file is unseekable
300
+                header_remove('Accept-Ranges');
301
+                header_remove('Content-Range');
302
+                header("HTTP/1.1 200 OK");
303
+                self::sendHeaders($filename, $name, array());
304
+                $view->readfile($filename);
305
+            }
306
+        }
307
+        else {
308
+            $view->readfile($filename);
309
+        }
310
+    }
311
+
312
+    /**
313
+     * @param View $view
314
+     * @param string $dir
315
+     * @param string[]|string $files
316
+     */
317
+    public static function lockFiles($view, $dir, $files) {
318
+        if (!is_array($files)) {
319
+            $file = $dir . '/' . $files;
320
+            $files = [$file];
321
+        }
322
+        foreach ($files as $file) {
323
+            $file = $dir . '/' . $file;
324
+            $view->lockFile($file, ILockingProvider::LOCK_SHARED);
325
+            if ($view->is_dir($file)) {
326
+                $contents = $view->getDirectoryContent($file);
327
+                $contents = array_map(function($fileInfo) use ($file) {
328
+                    /** @var \OCP\Files\FileInfo $fileInfo */
329
+                    return $file . '/' . $fileInfo->getName();
330
+                }, $contents);
331
+                self::lockFiles($view, $dir, $contents);
332
+            }
333
+        }
334
+    }
335
+
336
+    /**
337
+     * set the maximum upload size limit for apache hosts using .htaccess
338
+     *
339
+     * @param int $size file size in bytes
340
+     * @param array $files override '.htaccess' and '.user.ini' locations
341
+     * @return bool false on failure, size on success
342
+     */
343
+    public static function setUploadLimit($size, $files = []) {
344
+        //don't allow user to break his config
345
+        $size = intval($size);
346
+        if ($size < self::UPLOAD_MIN_LIMIT_BYTES) {
347
+            return false;
348
+        }
349
+        $size = OC_Helper::phpFileSize($size);
350
+
351
+        $phpValueKeys = array(
352
+            'upload_max_filesize',
353
+            'post_max_size'
354
+        );
355
+
356
+        // default locations if not overridden by $files
357
+        $files = array_merge([
358
+            '.htaccess' => OC::$SERVERROOT . '/.htaccess',
359
+            '.user.ini' => OC::$SERVERROOT . '/.user.ini'
360
+        ], $files);
361
+
362
+        $updateFiles = [
363
+            $files['.htaccess'] => [
364
+                'pattern' => '/php_value %1$s (\S)*/',
365
+                'setting' => 'php_value %1$s %2$s'
366
+            ],
367
+            $files['.user.ini'] => [
368
+                'pattern' => '/%1$s=(\S)*/',
369
+                'setting' => '%1$s=%2$s'
370
+            ]
371
+        ];
372
+
373
+        $success = true;
374
+
375
+        foreach ($updateFiles as $filename => $patternMap) {
376
+            // suppress warnings from fopen()
377
+            $handle = @fopen($filename, 'r+');
378
+            if (!$handle) {
379
+                \OCP\Util::writeLog('files',
380
+                    'Can\'t write upload limit to ' . $filename . '. Please check the file permissions',
381
+                    \OCP\Util::WARN);
382
+                $success = false;
383
+                continue; // try to update as many files as possible
384
+            }
385
+
386
+            $content = '';
387
+            while (!feof($handle)) {
388
+                $content .= fread($handle, 1000);
389
+            }
390
+
391
+            foreach ($phpValueKeys as $key) {
392
+                $pattern = vsprintf($patternMap['pattern'], [$key]);
393
+                $setting = vsprintf($patternMap['setting'], [$key, $size]);
394
+                $hasReplaced = 0;
395
+                $newContent = preg_replace($pattern, $setting, $content, 2, $hasReplaced);
396
+                if ($newContent !== null) {
397
+                    $content = $newContent;
398
+                }
399
+                if ($hasReplaced === 0) {
400
+                    $content .= "\n" . $setting;
401
+                }
402
+            }
403
+
404
+            // write file back
405
+            ftruncate($handle, 0);
406
+            rewind($handle);
407
+            fwrite($handle, $content);
408
+
409
+            fclose($handle);
410
+        }
411
+
412
+        if ($success) {
413
+            return OC_Helper::computerFileSize($size);
414
+        }
415
+        return false;
416
+    }
417
+
418
+    /**
419
+     * @param string $dir
420
+     * @param $files
421
+     * @param integer $getType
422
+     * @param View $view
423
+     * @param string $filename
424
+     */
425
+    private static function unlockAllTheFiles($dir, $files, $getType, $view, $filename) {
426
+        if ($getType === self::FILE) {
427
+            $view->unlockFile($filename, ILockingProvider::LOCK_SHARED);
428
+        }
429
+        if ($getType === self::ZIP_FILES) {
430
+            foreach ($files as $file) {
431
+                $file = $dir . '/' . $file;
432
+                $view->unlockFile($file, ILockingProvider::LOCK_SHARED);
433
+            }
434
+        }
435
+        if ($getType === self::ZIP_DIR) {
436
+            $file = $dir . '/' . $files;
437
+            $view->unlockFile($file, ILockingProvider::LOCK_SHARED);
438
+        }
439
+    }
440 440
 
441 441
 }
Please login to merge, or discard this patch.
settings/Controller/CertificateController.php 2 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -72,7 +72,7 @@  discard block
 block discarded – undo
72 72
 	 *
73 73
 	 * @NoAdminRequired
74 74
 	 * @NoSubadminRequired
75
-	 * @return array
75
+	 * @return DataResponse
76 76
 	 */
77 77
 	public function addPersonalRootCertificate() {
78 78
 		return $this->addCertificate($this->userCertificateManager);
@@ -160,7 +160,7 @@  discard block
 block discarded – undo
160 160
 	/**
161 161
 	 * Add a new personal root certificate to the system's trust store
162 162
 	 *
163
-	 * @return array
163
+	 * @return DataResponse
164 164
 	 */
165 165
 	public function addSystemRootCertificate() {
166 166
 		return $this->addCertificate($this->systemCertificateManager);
Please login to merge, or discard this patch.
Indentation   +140 added lines, -140 removed lines patch added patch discarded remove patch
@@ -37,144 +37,144 @@
 block discarded – undo
37 37
  * @package OC\Settings\Controller
38 38
  */
39 39
 class CertificateController extends Controller {
40
-	/** @var ICertificateManager */
41
-	private $userCertificateManager;
42
-	/** @var ICertificateManager  */
43
-	private $systemCertificateManager;
44
-	/** @var IL10N */
45
-	private $l10n;
46
-	/** @var IAppManager */
47
-	private $appManager;
48
-
49
-	/**
50
-	 * @param string $appName
51
-	 * @param IRequest $request
52
-	 * @param ICertificateManager $userCertificateManager
53
-	 * @param ICertificateManager $systemCertificateManager
54
-	 * @param IL10N $l10n
55
-	 * @param IAppManager $appManager
56
-	 */
57
-	public function __construct($appName,
58
-								IRequest $request,
59
-								ICertificateManager $userCertificateManager,
60
-								ICertificateManager $systemCertificateManager,
61
-								IL10N $l10n,
62
-								IAppManager $appManager) {
63
-		parent::__construct($appName, $request);
64
-		$this->userCertificateManager = $userCertificateManager;
65
-		$this->systemCertificateManager = $systemCertificateManager;
66
-		$this->l10n = $l10n;
67
-		$this->appManager = $appManager;
68
-	}
69
-
70
-	/**
71
-	 * Add a new personal root certificate to the users' trust store
72
-	 *
73
-	 * @NoAdminRequired
74
-	 * @NoSubadminRequired
75
-	 * @return array
76
-	 */
77
-	public function addPersonalRootCertificate() {
78
-		return $this->addCertificate($this->userCertificateManager);
79
-	}
80
-
81
-	/**
82
-	 * Add a new root certificate to a trust store
83
-	 *
84
-	 * @param ICertificateManager $certificateManager
85
-	 * @return DataResponse
86
-	 */
87
-	private function addCertificate(ICertificateManager $certificateManager) {
88
-		$headers = [];
89
-
90
-		if ($this->isCertificateImportAllowed() === false) {
91
-			return new DataResponse(['message' => 'Individual certificate management disabled'], Http::STATUS_FORBIDDEN, $headers);
92
-		}
93
-
94
-		$file = $this->request->getUploadedFile('rootcert_import');
95
-		if (empty($file)) {
96
-			return new DataResponse(['message' => 'No file uploaded'], Http::STATUS_UNPROCESSABLE_ENTITY, $headers);
97
-		}
98
-
99
-		try {
100
-			$certificate = $certificateManager->addCertificate(file_get_contents($file['tmp_name']), $file['name']);
101
-			return new DataResponse(
102
-				[
103
-					'name' => $certificate->getName(),
104
-					'commonName' => $certificate->getCommonName(),
105
-					'organization' => $certificate->getOrganization(),
106
-					'validFrom' => $certificate->getIssueDate()->getTimestamp(),
107
-					'validTill' => $certificate->getExpireDate()->getTimestamp(),
108
-					'validFromString' => $this->l10n->l('date', $certificate->getIssueDate()),
109
-					'validTillString' => $this->l10n->l('date', $certificate->getExpireDate()),
110
-					'issuer' => $certificate->getIssuerName(),
111
-					'issuerOrganization' => $certificate->getIssuerOrganization(),
112
-				],
113
-				Http::STATUS_OK,
114
-				$headers
115
-			);
116
-		} catch (\Exception $e) {
117
-			return new DataResponse('An error occurred.', Http::STATUS_UNPROCESSABLE_ENTITY, $headers);
118
-		}
119
-	}
120
-
121
-	/**
122
-	 * Removes a personal root certificate from the users' trust store
123
-	 *
124
-	 * @NoAdminRequired
125
-	 * @NoSubadminRequired
126
-	 * @param string $certificateIdentifier
127
-	 * @return DataResponse
128
-	 */
129
-	public function removePersonalRootCertificate($certificateIdentifier) {
130
-
131
-		if ($this->isCertificateImportAllowed() === false) {
132
-			return new DataResponse('Individual certificate management disabled', Http::STATUS_FORBIDDEN);
133
-		}
134
-
135
-		$this->userCertificateManager->removeCertificate($certificateIdentifier);
136
-		return new DataResponse();
137
-	}
138
-
139
-	/**
140
-	 * check if certificate import is allowed
141
-	 *
142
-	 * @return bool
143
-	 */
144
-	protected function isCertificateImportAllowed() {
145
-		$externalStorageEnabled = $this->appManager->isEnabledForUser('files_external');
146
-		if ($externalStorageEnabled) {
147
-			/** @var \OCA\Files_External\Service\BackendService $backendService */
148
-			$backendService = \OC_Mount_Config::$app->getContainer()->query('\OCA\Files_External\Service\BackendService');
149
-			if ($backendService->isUserMountingAllowed()) {
150
-				return true;
151
-			}
152
-		}
153
-		return false;
154
-	}
155
-
156
-	/**
157
-	 * Add a new personal root certificate to the system's trust store
158
-	 *
159
-	 * @return array
160
-	 */
161
-	public function addSystemRootCertificate() {
162
-		return $this->addCertificate($this->systemCertificateManager);
163
-	}
164
-
165
-	/**
166
-	 * Removes a personal root certificate from the users' trust store
167
-	 *
168
-	 * @param string $certificateIdentifier
169
-	 * @return DataResponse
170
-	 */
171
-	public function removeSystemRootCertificate($certificateIdentifier) {
172
-
173
-		if ($this->isCertificateImportAllowed() === false) {
174
-			return new DataResponse('Individual certificate management disabled', Http::STATUS_FORBIDDEN);
175
-		}
176
-
177
-		$this->systemCertificateManager->removeCertificate($certificateIdentifier);
178
-		return new DataResponse();
179
-	}
40
+    /** @var ICertificateManager */
41
+    private $userCertificateManager;
42
+    /** @var ICertificateManager  */
43
+    private $systemCertificateManager;
44
+    /** @var IL10N */
45
+    private $l10n;
46
+    /** @var IAppManager */
47
+    private $appManager;
48
+
49
+    /**
50
+     * @param string $appName
51
+     * @param IRequest $request
52
+     * @param ICertificateManager $userCertificateManager
53
+     * @param ICertificateManager $systemCertificateManager
54
+     * @param IL10N $l10n
55
+     * @param IAppManager $appManager
56
+     */
57
+    public function __construct($appName,
58
+                                IRequest $request,
59
+                                ICertificateManager $userCertificateManager,
60
+                                ICertificateManager $systemCertificateManager,
61
+                                IL10N $l10n,
62
+                                IAppManager $appManager) {
63
+        parent::__construct($appName, $request);
64
+        $this->userCertificateManager = $userCertificateManager;
65
+        $this->systemCertificateManager = $systemCertificateManager;
66
+        $this->l10n = $l10n;
67
+        $this->appManager = $appManager;
68
+    }
69
+
70
+    /**
71
+     * Add a new personal root certificate to the users' trust store
72
+     *
73
+     * @NoAdminRequired
74
+     * @NoSubadminRequired
75
+     * @return array
76
+     */
77
+    public function addPersonalRootCertificate() {
78
+        return $this->addCertificate($this->userCertificateManager);
79
+    }
80
+
81
+    /**
82
+     * Add a new root certificate to a trust store
83
+     *
84
+     * @param ICertificateManager $certificateManager
85
+     * @return DataResponse
86
+     */
87
+    private function addCertificate(ICertificateManager $certificateManager) {
88
+        $headers = [];
89
+
90
+        if ($this->isCertificateImportAllowed() === false) {
91
+            return new DataResponse(['message' => 'Individual certificate management disabled'], Http::STATUS_FORBIDDEN, $headers);
92
+        }
93
+
94
+        $file = $this->request->getUploadedFile('rootcert_import');
95
+        if (empty($file)) {
96
+            return new DataResponse(['message' => 'No file uploaded'], Http::STATUS_UNPROCESSABLE_ENTITY, $headers);
97
+        }
98
+
99
+        try {
100
+            $certificate = $certificateManager->addCertificate(file_get_contents($file['tmp_name']), $file['name']);
101
+            return new DataResponse(
102
+                [
103
+                    'name' => $certificate->getName(),
104
+                    'commonName' => $certificate->getCommonName(),
105
+                    'organization' => $certificate->getOrganization(),
106
+                    'validFrom' => $certificate->getIssueDate()->getTimestamp(),
107
+                    'validTill' => $certificate->getExpireDate()->getTimestamp(),
108
+                    'validFromString' => $this->l10n->l('date', $certificate->getIssueDate()),
109
+                    'validTillString' => $this->l10n->l('date', $certificate->getExpireDate()),
110
+                    'issuer' => $certificate->getIssuerName(),
111
+                    'issuerOrganization' => $certificate->getIssuerOrganization(),
112
+                ],
113
+                Http::STATUS_OK,
114
+                $headers
115
+            );
116
+        } catch (\Exception $e) {
117
+            return new DataResponse('An error occurred.', Http::STATUS_UNPROCESSABLE_ENTITY, $headers);
118
+        }
119
+    }
120
+
121
+    /**
122
+     * Removes a personal root certificate from the users' trust store
123
+     *
124
+     * @NoAdminRequired
125
+     * @NoSubadminRequired
126
+     * @param string $certificateIdentifier
127
+     * @return DataResponse
128
+     */
129
+    public function removePersonalRootCertificate($certificateIdentifier) {
130
+
131
+        if ($this->isCertificateImportAllowed() === false) {
132
+            return new DataResponse('Individual certificate management disabled', Http::STATUS_FORBIDDEN);
133
+        }
134
+
135
+        $this->userCertificateManager->removeCertificate($certificateIdentifier);
136
+        return new DataResponse();
137
+    }
138
+
139
+    /**
140
+     * check if certificate import is allowed
141
+     *
142
+     * @return bool
143
+     */
144
+    protected function isCertificateImportAllowed() {
145
+        $externalStorageEnabled = $this->appManager->isEnabledForUser('files_external');
146
+        if ($externalStorageEnabled) {
147
+            /** @var \OCA\Files_External\Service\BackendService $backendService */
148
+            $backendService = \OC_Mount_Config::$app->getContainer()->query('\OCA\Files_External\Service\BackendService');
149
+            if ($backendService->isUserMountingAllowed()) {
150
+                return true;
151
+            }
152
+        }
153
+        return false;
154
+    }
155
+
156
+    /**
157
+     * Add a new personal root certificate to the system's trust store
158
+     *
159
+     * @return array
160
+     */
161
+    public function addSystemRootCertificate() {
162
+        return $this->addCertificate($this->systemCertificateManager);
163
+    }
164
+
165
+    /**
166
+     * Removes a personal root certificate from the users' trust store
167
+     *
168
+     * @param string $certificateIdentifier
169
+     * @return DataResponse
170
+     */
171
+    public function removeSystemRootCertificate($certificateIdentifier) {
172
+
173
+        if ($this->isCertificateImportAllowed() === false) {
174
+            return new DataResponse('Individual certificate management disabled', Http::STATUS_FORBIDDEN);
175
+        }
176
+
177
+        $this->systemCertificateManager->removeCertificate($certificateIdentifier);
178
+        return new DataResponse();
179
+    }
180 180
 }
Please login to merge, or discard this patch.
core/Controller/LostController.php 4 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -132,7 +132,7 @@
 block discarded – undo
132 132
 	}
133 133
 
134 134
 	/**
135
-	 * @param $message
135
+	 * @param string $message
136 136
 	 * @param array $additional
137 137
 	 * @return array
138 138
 	 */
Please login to merge, or discard this patch.
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -30,7 +30,6 @@
 block discarded – undo
30 30
 
31 31
 namespace OC\Core\Controller;
32 32
 
33
-use OCA\Encryption\Exceptions\PrivateKeyMissingException;
34 33
 use \OCP\AppFramework\Controller;
35 34
 use \OCP\AppFramework\Http\TemplateResponse;
36 35
 use OCP\AppFramework\Utility\ITimeFactory;
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -158,7 +158,7 @@  discard block
 block discarded – undo
158 158
 	 */
159 159
 	protected function checkPasswordResetToken($token, $userId) {
160 160
 		$user = $this->userManager->get($userId);
161
-		if($user === null) {
161
+		if ($user === null) {
162 162
 			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
163 163
 		}
164 164
 
@@ -171,11 +171,11 @@  discard block
 block discarded – undo
171 171
 		}
172 172
 
173 173
 		$splittedToken = explode(':', $decryptedToken);
174
-		if(count($splittedToken) !== 2) {
174
+		if (count($splittedToken) !== 2) {
175 175
 			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
176 176
 		}
177 177
 
178
-		if ($splittedToken[0] < ($this->timeFactory->getTime() - 60*60*12) ||
178
+		if ($splittedToken[0] < ($this->timeFactory->getTime() - 60 * 60 * 12) ||
179 179
 			$user->getLastLogin() > $splittedToken[0]) {
180 180
 			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is expired'));
181 181
 		}
@@ -190,7 +190,7 @@  discard block
 block discarded – undo
190 190
 	 * @param array $additional
191 191
 	 * @return array
192 192
 	 */
193
-	private function error($message, array $additional=array()) {
193
+	private function error($message, array $additional = array()) {
194 194
 		return array_merge(array('status' => 'error', 'msg' => $message), $additional);
195 195
 	}
196 196
 
@@ -208,11 +208,11 @@  discard block
 block discarded – undo
208 208
 	 * @param string $user
209 209
 	 * @return array
210 210
 	 */
211
-	public function email($user){
211
+	public function email($user) {
212 212
 		// FIXME: use HTTP error codes
213 213
 		try {
214 214
 			$this->sendEmail($user);
215
-		} catch (\Exception $e){
215
+		} catch (\Exception $e) {
216 216
 			return $this->error($e->getMessage());
217 217
 		}
218 218
 
@@ -246,7 +246,7 @@  discard block
 block discarded – undo
246 246
 
247 247
 			$this->config->deleteUserValue($userId, 'core', 'lostpassword');
248 248
 			@\OC_User::unsetMagicInCookie();
249
-		} catch (\Exception $e){
249
+		} catch (\Exception $e) {
250 250
 			return $this->error($e->getMessage());
251 251
 		}
252 252
 
@@ -277,8 +277,8 @@  discard block
 block discarded – undo
277 277
 			ISecureRandom::CHAR_LOWER.
278 278
 			ISecureRandom::CHAR_UPPER
279 279
 		);
280
-		$tokenValue = $this->timeFactory->getTime() .':'. $token;
281
-		$encryptedValue = $this->crypto->encrypt($tokenValue, $email . $this->config->getSystemValue('secret'));
280
+		$tokenValue = $this->timeFactory->getTime().':'.$token;
281
+		$encryptedValue = $this->crypto->encrypt($tokenValue, $email.$this->config->getSystemValue('secret'));
282 282
 		$this->config->setUserValue($user->getUID(), 'core', 'lostpassword', $encryptedValue);
283 283
 
284 284
 		$link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $user->getUID(), 'token' => $token));
Please login to merge, or discard this patch.
Indentation   +278 added lines, -278 removed lines patch added patch discarded remove patch
@@ -55,282 +55,282 @@
 block discarded – undo
55 55
  */
56 56
 class LostController extends Controller {
57 57
 
58
-	/** @var IURLGenerator */
59
-	protected $urlGenerator;
60
-	/** @var IUserManager */
61
-	protected $userManager;
62
-	/** @var Defaults */
63
-	protected $defaults;
64
-	/** @var IL10N */
65
-	protected $l10n;
66
-	/** @var string */
67
-	protected $from;
68
-	/** @var IManager */
69
-	protected $encryptionManager;
70
-	/** @var IConfig */
71
-	protected $config;
72
-	/** @var ISecureRandom */
73
-	protected $secureRandom;
74
-	/** @var IMailer */
75
-	protected $mailer;
76
-	/** @var ITimeFactory */
77
-	protected $timeFactory;
78
-	/** @var ICrypto */
79
-	protected $crypto;
80
-
81
-	/**
82
-	 * @param string $appName
83
-	 * @param IRequest $request
84
-	 * @param IURLGenerator $urlGenerator
85
-	 * @param IUserManager $userManager
86
-	 * @param Defaults $defaults
87
-	 * @param IL10N $l10n
88
-	 * @param IConfig $config
89
-	 * @param ISecureRandom $secureRandom
90
-	 * @param string $defaultMailAddress
91
-	 * @param IManager $encryptionManager
92
-	 * @param IMailer $mailer
93
-	 * @param ITimeFactory $timeFactory
94
-	 * @param ICrypto $crypto
95
-	 */
96
-	public function __construct($appName,
97
-								IRequest $request,
98
-								IURLGenerator $urlGenerator,
99
-								IUserManager $userManager,
100
-								Defaults $defaults,
101
-								IL10N $l10n,
102
-								IConfig $config,
103
-								ISecureRandom $secureRandom,
104
-								$defaultMailAddress,
105
-								IManager $encryptionManager,
106
-								IMailer $mailer,
107
-								ITimeFactory $timeFactory,
108
-								ICrypto $crypto) {
109
-		parent::__construct($appName, $request);
110
-		$this->urlGenerator = $urlGenerator;
111
-		$this->userManager = $userManager;
112
-		$this->defaults = $defaults;
113
-		$this->l10n = $l10n;
114
-		$this->secureRandom = $secureRandom;
115
-		$this->from = $defaultMailAddress;
116
-		$this->encryptionManager = $encryptionManager;
117
-		$this->config = $config;
118
-		$this->mailer = $mailer;
119
-		$this->timeFactory = $timeFactory;
120
-		$this->crypto = $crypto;
121
-	}
122
-
123
-	/**
124
-	 * Someone wants to reset their password:
125
-	 *
126
-	 * @PublicPage
127
-	 * @NoCSRFRequired
128
-	 *
129
-	 * @param string $token
130
-	 * @param string $userId
131
-	 * @return TemplateResponse
132
-	 */
133
-	public function resetform($token, $userId) {
134
-		try {
135
-			$this->checkPasswordResetToken($token, $userId);
136
-		} catch (\Exception $e) {
137
-			return new TemplateResponse(
138
-				'core', 'error', [
139
-					"errors" => array(array("error" => $e->getMessage()))
140
-				],
141
-				'guest'
142
-			);
143
-		}
144
-
145
-		return new TemplateResponse(
146
-			'core',
147
-			'lostpassword/resetpassword',
148
-			array(
149
-				'link' => $this->urlGenerator->linkToRouteAbsolute('core.lost.setPassword', array('userId' => $userId, 'token' => $token)),
150
-			),
151
-			'guest'
152
-		);
153
-	}
154
-
155
-	/**
156
-	 * @param string $token
157
-	 * @param string $userId
158
-	 * @throws \Exception
159
-	 */
160
-	protected function checkPasswordResetToken($token, $userId) {
161
-		$user = $this->userManager->get($userId);
162
-		if($user === null) {
163
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
164
-		}
165
-
166
-		try {
167
-			$encryptedToken = $this->config->getUserValue($userId, 'core', 'lostpassword', null);
168
-			$mailAddress = !is_null($user->getEMailAddress()) ? $user->getEMailAddress() : '';
169
-			$decryptedToken = $this->crypto->decrypt($encryptedToken, $mailAddress.$this->config->getSystemValue('secret'));
170
-		} catch (\Exception $e) {
171
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
172
-		}
173
-
174
-		$splittedToken = explode(':', $decryptedToken);
175
-		if(count($splittedToken) !== 2) {
176
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
177
-		}
178
-
179
-		if ($splittedToken[0] < ($this->timeFactory->getTime() - 60*60*12) ||
180
-			$user->getLastLogin() > $splittedToken[0]) {
181
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is expired'));
182
-		}
183
-
184
-		if (!hash_equals($splittedToken[1], $token)) {
185
-			throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
186
-		}
187
-	}
188
-
189
-	/**
190
-	 * @param $message
191
-	 * @param array $additional
192
-	 * @return array
193
-	 */
194
-	private function error($message, array $additional=array()) {
195
-		return array_merge(array('status' => 'error', 'msg' => $message), $additional);
196
-	}
197
-
198
-	/**
199
-	 * @return array
200
-	 */
201
-	private function success() {
202
-		return array('status'=>'success');
203
-	}
204
-
205
-	/**
206
-	 * @PublicPage
207
-	 * @BruteForceProtection(action=passwordResetEmail)
208
-	 *
209
-	 * @param string $user
210
-	 * @return array
211
-	 */
212
-	public function email($user){
213
-		// FIXME: use HTTP error codes
214
-		try {
215
-			$this->sendEmail($user);
216
-		} catch (\Exception $e){
217
-			return $this->error($e->getMessage());
218
-		}
219
-
220
-		return $this->success();
221
-	}
222
-
223
-	/**
224
-	 * @PublicPage
225
-	 * @param string $token
226
-	 * @param string $userId
227
-	 * @param string $password
228
-	 * @param boolean $proceed
229
-	 * @return array
230
-	 */
231
-	public function setPassword($token, $userId, $password, $proceed) {
232
-		if ($this->encryptionManager->isEnabled() && !$proceed) {
233
-			return $this->error('', array('encryption' => true));
234
-		}
235
-
236
-		try {
237
-			$this->checkPasswordResetToken($token, $userId);
238
-			$user = $this->userManager->get($userId);
239
-
240
-			\OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'pre_passwordReset', array('uid' => $userId, 'password' => $password));
241
-
242
-			if (!$user->setPassword($password)) {
243
-				throw new \Exception();
244
-			}
245
-
246
-			\OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'post_passwordReset', array('uid' => $userId, 'password' => $password));
247
-
248
-			$this->config->deleteUserValue($userId, 'core', 'lostpassword');
249
-			@\OC_User::unsetMagicInCookie();
250
-		} catch (\Exception $e){
251
-			return $this->error($e->getMessage());
252
-		}
253
-
254
-		return $this->success();
255
-	}
256
-
257
-	/**
258
-	 * @param string $input
259
-	 * @throws \Exception
260
-	 */
261
-	protected function sendEmail($input) {
262
-		$user = $this->findUserByIdOrMail($input);
263
-		$email = $user->getEMailAddress();
264
-
265
-		if (empty($email)) {
266
-			throw new \Exception(
267
-				$this->l10n->t('Could not send reset email because there is no email address for this username. Please contact your administrator.')
268
-			);
269
-		}
270
-
271
-		// Generate the token. It is stored encrypted in the database with the
272
-		// secret being the users' email address appended with the system secret.
273
-		// This makes the token automatically invalidate once the user changes
274
-		// their email address.
275
-		$token = $this->secureRandom->generate(
276
-			21,
277
-			ISecureRandom::CHAR_DIGITS.
278
-			ISecureRandom::CHAR_LOWER.
279
-			ISecureRandom::CHAR_UPPER
280
-		);
281
-		$tokenValue = $this->timeFactory->getTime() .':'. $token;
282
-		$encryptedValue = $this->crypto->encrypt($tokenValue, $email . $this->config->getSystemValue('secret'));
283
-		$this->config->setUserValue($user->getUID(), 'core', 'lostpassword', $encryptedValue);
284
-
285
-		$link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $user->getUID(), 'token' => $token));
286
-
287
-		$emailTemplate = $this->mailer->createEMailTemplate();
288
-
289
-		$emailTemplate->addHeader();
290
-		$emailTemplate->addHeading($this->l10n->t('Password reset'));
291
-
292
-		$emailTemplate->addBodyText(
293
-			$this->l10n->t('Click the following button to reset your password. If you have not requested the password reset, then ignore this email.'),
294
-			$this->l10n->t('Click the following link to reset your password. If you have not requested the password reset, then ignore this email.')
295
-		);
296
-
297
-		$emailTemplate->addBodyButton(
298
-			$this->l10n->t('Reset your password'),
299
-			$link,
300
-			false
301
-		);
302
-		$emailTemplate->addFooter();
303
-
304
-		try {
305
-			$message = $this->mailer->createMessage();
306
-			$message->setTo([$email => $user->getUID()]);
307
-			$message->setSubject($this->l10n->t('%s password reset', [$this->defaults->getName()]));
308
-			$message->setPlainBody($emailTemplate->renderText());
309
-			$message->setHtmlBody($emailTemplate->renderHTML());
310
-			$message->setFrom([$this->from => $this->defaults->getName()]);
311
-			$this->mailer->send($message);
312
-		} catch (\Exception $e) {
313
-			throw new \Exception($this->l10n->t(
314
-				'Couldn\'t send reset email. Please contact your administrator.'
315
-			));
316
-		}
317
-	}
318
-
319
-	/**
320
-	 * @param string $input
321
-	 * @return IUser
322
-	 * @throws \Exception
323
-	 */
324
-	protected function findUserByIdOrMail($input) {
325
-		$user = $this->userManager->get($input);
326
-		if ($user instanceof IUser) {
327
-			return $user;
328
-		}
329
-		$users = $this->userManager->getByEmail($input);
330
-		if (count($users) === 1) {
331
-			return $users[0];
332
-		}
333
-
334
-		throw new \InvalidArgumentException($this->l10n->t('Couldn\'t send reset email. Please make sure your username is correct.'));
335
-	}
58
+    /** @var IURLGenerator */
59
+    protected $urlGenerator;
60
+    /** @var IUserManager */
61
+    protected $userManager;
62
+    /** @var Defaults */
63
+    protected $defaults;
64
+    /** @var IL10N */
65
+    protected $l10n;
66
+    /** @var string */
67
+    protected $from;
68
+    /** @var IManager */
69
+    protected $encryptionManager;
70
+    /** @var IConfig */
71
+    protected $config;
72
+    /** @var ISecureRandom */
73
+    protected $secureRandom;
74
+    /** @var IMailer */
75
+    protected $mailer;
76
+    /** @var ITimeFactory */
77
+    protected $timeFactory;
78
+    /** @var ICrypto */
79
+    protected $crypto;
80
+
81
+    /**
82
+     * @param string $appName
83
+     * @param IRequest $request
84
+     * @param IURLGenerator $urlGenerator
85
+     * @param IUserManager $userManager
86
+     * @param Defaults $defaults
87
+     * @param IL10N $l10n
88
+     * @param IConfig $config
89
+     * @param ISecureRandom $secureRandom
90
+     * @param string $defaultMailAddress
91
+     * @param IManager $encryptionManager
92
+     * @param IMailer $mailer
93
+     * @param ITimeFactory $timeFactory
94
+     * @param ICrypto $crypto
95
+     */
96
+    public function __construct($appName,
97
+                                IRequest $request,
98
+                                IURLGenerator $urlGenerator,
99
+                                IUserManager $userManager,
100
+                                Defaults $defaults,
101
+                                IL10N $l10n,
102
+                                IConfig $config,
103
+                                ISecureRandom $secureRandom,
104
+                                $defaultMailAddress,
105
+                                IManager $encryptionManager,
106
+                                IMailer $mailer,
107
+                                ITimeFactory $timeFactory,
108
+                                ICrypto $crypto) {
109
+        parent::__construct($appName, $request);
110
+        $this->urlGenerator = $urlGenerator;
111
+        $this->userManager = $userManager;
112
+        $this->defaults = $defaults;
113
+        $this->l10n = $l10n;
114
+        $this->secureRandom = $secureRandom;
115
+        $this->from = $defaultMailAddress;
116
+        $this->encryptionManager = $encryptionManager;
117
+        $this->config = $config;
118
+        $this->mailer = $mailer;
119
+        $this->timeFactory = $timeFactory;
120
+        $this->crypto = $crypto;
121
+    }
122
+
123
+    /**
124
+     * Someone wants to reset their password:
125
+     *
126
+     * @PublicPage
127
+     * @NoCSRFRequired
128
+     *
129
+     * @param string $token
130
+     * @param string $userId
131
+     * @return TemplateResponse
132
+     */
133
+    public function resetform($token, $userId) {
134
+        try {
135
+            $this->checkPasswordResetToken($token, $userId);
136
+        } catch (\Exception $e) {
137
+            return new TemplateResponse(
138
+                'core', 'error', [
139
+                    "errors" => array(array("error" => $e->getMessage()))
140
+                ],
141
+                'guest'
142
+            );
143
+        }
144
+
145
+        return new TemplateResponse(
146
+            'core',
147
+            'lostpassword/resetpassword',
148
+            array(
149
+                'link' => $this->urlGenerator->linkToRouteAbsolute('core.lost.setPassword', array('userId' => $userId, 'token' => $token)),
150
+            ),
151
+            'guest'
152
+        );
153
+    }
154
+
155
+    /**
156
+     * @param string $token
157
+     * @param string $userId
158
+     * @throws \Exception
159
+     */
160
+    protected function checkPasswordResetToken($token, $userId) {
161
+        $user = $this->userManager->get($userId);
162
+        if($user === null) {
163
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
164
+        }
165
+
166
+        try {
167
+            $encryptedToken = $this->config->getUserValue($userId, 'core', 'lostpassword', null);
168
+            $mailAddress = !is_null($user->getEMailAddress()) ? $user->getEMailAddress() : '';
169
+            $decryptedToken = $this->crypto->decrypt($encryptedToken, $mailAddress.$this->config->getSystemValue('secret'));
170
+        } catch (\Exception $e) {
171
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
172
+        }
173
+
174
+        $splittedToken = explode(':', $decryptedToken);
175
+        if(count($splittedToken) !== 2) {
176
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
177
+        }
178
+
179
+        if ($splittedToken[0] < ($this->timeFactory->getTime() - 60*60*12) ||
180
+            $user->getLastLogin() > $splittedToken[0]) {
181
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is expired'));
182
+        }
183
+
184
+        if (!hash_equals($splittedToken[1], $token)) {
185
+            throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
186
+        }
187
+    }
188
+
189
+    /**
190
+     * @param $message
191
+     * @param array $additional
192
+     * @return array
193
+     */
194
+    private function error($message, array $additional=array()) {
195
+        return array_merge(array('status' => 'error', 'msg' => $message), $additional);
196
+    }
197
+
198
+    /**
199
+     * @return array
200
+     */
201
+    private function success() {
202
+        return array('status'=>'success');
203
+    }
204
+
205
+    /**
206
+     * @PublicPage
207
+     * @BruteForceProtection(action=passwordResetEmail)
208
+     *
209
+     * @param string $user
210
+     * @return array
211
+     */
212
+    public function email($user){
213
+        // FIXME: use HTTP error codes
214
+        try {
215
+            $this->sendEmail($user);
216
+        } catch (\Exception $e){
217
+            return $this->error($e->getMessage());
218
+        }
219
+
220
+        return $this->success();
221
+    }
222
+
223
+    /**
224
+     * @PublicPage
225
+     * @param string $token
226
+     * @param string $userId
227
+     * @param string $password
228
+     * @param boolean $proceed
229
+     * @return array
230
+     */
231
+    public function setPassword($token, $userId, $password, $proceed) {
232
+        if ($this->encryptionManager->isEnabled() && !$proceed) {
233
+            return $this->error('', array('encryption' => true));
234
+        }
235
+
236
+        try {
237
+            $this->checkPasswordResetToken($token, $userId);
238
+            $user = $this->userManager->get($userId);
239
+
240
+            \OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'pre_passwordReset', array('uid' => $userId, 'password' => $password));
241
+
242
+            if (!$user->setPassword($password)) {
243
+                throw new \Exception();
244
+            }
245
+
246
+            \OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'post_passwordReset', array('uid' => $userId, 'password' => $password));
247
+
248
+            $this->config->deleteUserValue($userId, 'core', 'lostpassword');
249
+            @\OC_User::unsetMagicInCookie();
250
+        } catch (\Exception $e){
251
+            return $this->error($e->getMessage());
252
+        }
253
+
254
+        return $this->success();
255
+    }
256
+
257
+    /**
258
+     * @param string $input
259
+     * @throws \Exception
260
+     */
261
+    protected function sendEmail($input) {
262
+        $user = $this->findUserByIdOrMail($input);
263
+        $email = $user->getEMailAddress();
264
+
265
+        if (empty($email)) {
266
+            throw new \Exception(
267
+                $this->l10n->t('Could not send reset email because there is no email address for this username. Please contact your administrator.')
268
+            );
269
+        }
270
+
271
+        // Generate the token. It is stored encrypted in the database with the
272
+        // secret being the users' email address appended with the system secret.
273
+        // This makes the token automatically invalidate once the user changes
274
+        // their email address.
275
+        $token = $this->secureRandom->generate(
276
+            21,
277
+            ISecureRandom::CHAR_DIGITS.
278
+            ISecureRandom::CHAR_LOWER.
279
+            ISecureRandom::CHAR_UPPER
280
+        );
281
+        $tokenValue = $this->timeFactory->getTime() .':'. $token;
282
+        $encryptedValue = $this->crypto->encrypt($tokenValue, $email . $this->config->getSystemValue('secret'));
283
+        $this->config->setUserValue($user->getUID(), 'core', 'lostpassword', $encryptedValue);
284
+
285
+        $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $user->getUID(), 'token' => $token));
286
+
287
+        $emailTemplate = $this->mailer->createEMailTemplate();
288
+
289
+        $emailTemplate->addHeader();
290
+        $emailTemplate->addHeading($this->l10n->t('Password reset'));
291
+
292
+        $emailTemplate->addBodyText(
293
+            $this->l10n->t('Click the following button to reset your password. If you have not requested the password reset, then ignore this email.'),
294
+            $this->l10n->t('Click the following link to reset your password. If you have not requested the password reset, then ignore this email.')
295
+        );
296
+
297
+        $emailTemplate->addBodyButton(
298
+            $this->l10n->t('Reset your password'),
299
+            $link,
300
+            false
301
+        );
302
+        $emailTemplate->addFooter();
303
+
304
+        try {
305
+            $message = $this->mailer->createMessage();
306
+            $message->setTo([$email => $user->getUID()]);
307
+            $message->setSubject($this->l10n->t('%s password reset', [$this->defaults->getName()]));
308
+            $message->setPlainBody($emailTemplate->renderText());
309
+            $message->setHtmlBody($emailTemplate->renderHTML());
310
+            $message->setFrom([$this->from => $this->defaults->getName()]);
311
+            $this->mailer->send($message);
312
+        } catch (\Exception $e) {
313
+            throw new \Exception($this->l10n->t(
314
+                'Couldn\'t send reset email. Please contact your administrator.'
315
+            ));
316
+        }
317
+    }
318
+
319
+    /**
320
+     * @param string $input
321
+     * @return IUser
322
+     * @throws \Exception
323
+     */
324
+    protected function findUserByIdOrMail($input) {
325
+        $user = $this->userManager->get($input);
326
+        if ($user instanceof IUser) {
327
+            return $user;
328
+        }
329
+        $users = $this->userManager->getByEmail($input);
330
+        if (count($users) === 1) {
331
+            return $users[0];
332
+        }
333
+
334
+        throw new \InvalidArgumentException($this->l10n->t('Couldn\'t send reset email. Please make sure your username is correct.'));
335
+    }
336 336
 }
Please login to merge, or discard this patch.
apps/theming/lib/Util.php 3 patches
Doc Comments   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -52,7 +52,7 @@  discard block
 block discarded – undo
52 52
 	/**
53 53
 	 * get color for on-page elements:
54 54
 	 * theme color by default, grey if theme color is to bright
55
-	 * @param $color
55
+	 * @param string $color
56 56
 	 * @return string
57 57
 	 */
58 58
 	public function elementColor($color) {
@@ -83,7 +83,7 @@  discard block
 block discarded – undo
83 83
 	}
84 84
 
85 85
 	/**
86
-	 * @param $color
86
+	 * @param string $color
87 87
 	 * @return string base64 encoded radio button svg
88 88
 	 */
89 89
 	public function generateRadioButton($color) {
@@ -152,8 +152,8 @@  discard block
 block discarded – undo
152 152
 	/**
153 153
 	 * replace default color with a custom one
154 154
 	 *
155
-	 * @param $svg string content of a svg file
156
-	 * @param $color string color to match
155
+	 * @param string $svg string content of a svg file
156
+	 * @param string $color string color to match
157 157
 	 * @return string
158 158
 	 */
159 159
 	public function colorizeSvg($svg, $color) {
Please login to merge, or discard this patch.
Indentation   +159 added lines, -159 removed lines patch added patch discarded remove patch
@@ -30,164 +30,164 @@
 block discarded – undo
30 30
 
31 31
 class Util {
32 32
 
33
-	/** @var IConfig */
34
-	private $config;
35
-
36
-	/** @var IRootFolder */
37
-	private $rootFolder;
38
-
39
-	/** @var IAppManager */
40
-	private $appManager;
41
-
42
-	/**
43
-	 * Util constructor.
44
-	 *
45
-	 * @param IConfig $config
46
-	 * @param IRootFolder $rootFolder
47
-	 * @param IAppManager $appManager
48
-	 */
49
-	public function __construct(IConfig $config, IRootFolder $rootFolder, IAppManager $appManager) {
50
-		$this->config = $config;
51
-		$this->rootFolder = $rootFolder;
52
-		$this->appManager = $appManager;
53
-	}
54
-
55
-	/**
56
-	 * @param string $color rgb color value
57
-	 * @return bool
58
-	 */
59
-	public function invertTextColor($color) {
60
-		$l = $this->calculateLuminance($color);
61
-		if($l>0.5) {
62
-			return true;
63
-		} else {
64
-			return false;
65
-		}
66
-	}
67
-
68
-	/**
69
-	 * get color for on-page elements:
70
-	 * theme color by default, grey if theme color is to bright
71
-	 * @param $color
72
-	 * @return string
73
-	 */
74
-	public function elementColor($color) {
75
-		$l = $this->calculateLuminance($color);
76
-		if($l>0.8) {
77
-			return '#555555';
78
-		} else {
79
-			return $color;
80
-		}
81
-	}
82
-
83
-	/**
84
-	 * @param string $color rgb color value
85
-	 * @return float
86
-	 */
87
-	public function calculateLuminance($color) {
88
-		$hex = preg_replace("/[^0-9A-Fa-f]/", '', $color);
89
-		if (strlen($hex) === 3) {
90
-			$hex = $hex{0} . $hex{0} . $hex{1} . $hex{1} . $hex{2} . $hex{2};
91
-		}
92
-		if (strlen($hex) !== 6) {
93
-			return 0;
94
-		}
95
-		$r = hexdec(substr($hex, 0, 2));
96
-		$g = hexdec(substr($hex, 2, 2));
97
-		$b = hexdec(substr($hex, 4, 2));
98
-		return (0.299 * $r + 0.587 * $g + 0.114 * $b)/255;
99
-	}
100
-
101
-	/**
102
-	 * @param $color
103
-	 * @return string base64 encoded radio button svg
104
-	 */
105
-	public function generateRadioButton($color) {
106
-		$radioButtonIcon = '<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">' .
107
-			'<path d="M8 1a7 7 0 0 0-7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0-7-7zm0 1a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6zm0 2a4 4 0 1 0 0 8 4 4 0 0 0 0-8z" fill="'.$color.'"/></svg>';
108
-		return base64_encode($radioButtonIcon);
109
-	}
110
-
111
-
112
-	/**
113
-	 * @param $app string app name
114
-	 * @return string path to app icon / logo
115
-	 */
116
-	public function getAppIcon($app) {
117
-		$app = str_replace(array('\0', '/', '\\', '..'), '', $app);
118
-		try {
119
-			$appPath = $this->appManager->getAppPath($app);
120
-			$icon = $appPath . '/img/' . $app . '.svg';
121
-			if (file_exists($icon)) {
122
-				return $icon;
123
-			}
124
-			$icon = $appPath . '/img/app.svg';
125
-			if (file_exists($icon)) {
126
-				return $icon;
127
-			}
128
-		} catch (AppPathNotFoundException $e) {}
129
-
130
-		if($this->config->getAppValue('theming', 'logoMime', '') !== '' && $this->rootFolder->nodeExists('/themedinstancelogo')) {
131
-			return $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/themedinstancelogo';
132
-		}
133
-		return \OC::$SERVERROOT . '/core/img/logo.svg';
134
-	}
135
-
136
-	/**
137
-	 * @param $app string app name
138
-	 * @param $image string relative path to image in app folder
139
-	 * @return string|false absolute path to image
140
-	 */
141
-	public function getAppImage($app, $image) {
142
-		$app = str_replace(array('\0', '/', '\\', '..'), '', $app);
143
-		$image = str_replace(array('\0', '\\', '..'), '', $image);
144
-		if ($app === "core") {
145
-			$icon = \OC::$SERVERROOT . '/core/img/' . $image;
146
-			if (file_exists($icon)) {
147
-				return $icon;
148
-			}
149
-		}
150
-
151
-		try {
152
-			$appPath = $this->appManager->getAppPath($app);
153
-		} catch (AppPathNotFoundException $e) {
154
-			return false;
155
-		}
156
-
157
-		$icon = $appPath . '/img/' . $image;
158
-		if (file_exists($icon)) {
159
-			return $icon;
160
-		}
161
-		$icon = $appPath . '/img/' . $image . '.svg';
162
-		if (file_exists($icon)) {
163
-			return $icon;
164
-		}
165
-		$icon = $appPath . '/img/' . $image . '.png';
166
-		if (file_exists($icon)) {
167
-			return $icon;
168
-		}
169
-		$icon = $appPath . '/img/' . $image . '.gif';
170
-		if (file_exists($icon)) {
171
-			return $icon;
172
-		}
173
-		$icon = $appPath . '/img/' . $image . '.jpg';
174
-		if (file_exists($icon)) {
175
-			return $icon;
176
-		}
177
-
178
-		return false;
179
-	}
180
-
181
-	/**
182
-	 * replace default color with a custom one
183
-	 *
184
-	 * @param $svg string content of a svg file
185
-	 * @param $color string color to match
186
-	 * @return string
187
-	 */
188
-	public function colorizeSvg($svg, $color) {
189
-		$svg = preg_replace('/#0082c9/i', $color, $svg);
190
-		return $svg;
191
-	}
33
+    /** @var IConfig */
34
+    private $config;
35
+
36
+    /** @var IRootFolder */
37
+    private $rootFolder;
38
+
39
+    /** @var IAppManager */
40
+    private $appManager;
41
+
42
+    /**
43
+     * Util constructor.
44
+     *
45
+     * @param IConfig $config
46
+     * @param IRootFolder $rootFolder
47
+     * @param IAppManager $appManager
48
+     */
49
+    public function __construct(IConfig $config, IRootFolder $rootFolder, IAppManager $appManager) {
50
+        $this->config = $config;
51
+        $this->rootFolder = $rootFolder;
52
+        $this->appManager = $appManager;
53
+    }
54
+
55
+    /**
56
+     * @param string $color rgb color value
57
+     * @return bool
58
+     */
59
+    public function invertTextColor($color) {
60
+        $l = $this->calculateLuminance($color);
61
+        if($l>0.5) {
62
+            return true;
63
+        } else {
64
+            return false;
65
+        }
66
+    }
67
+
68
+    /**
69
+     * get color for on-page elements:
70
+     * theme color by default, grey if theme color is to bright
71
+     * @param $color
72
+     * @return string
73
+     */
74
+    public function elementColor($color) {
75
+        $l = $this->calculateLuminance($color);
76
+        if($l>0.8) {
77
+            return '#555555';
78
+        } else {
79
+            return $color;
80
+        }
81
+    }
82
+
83
+    /**
84
+     * @param string $color rgb color value
85
+     * @return float
86
+     */
87
+    public function calculateLuminance($color) {
88
+        $hex = preg_replace("/[^0-9A-Fa-f]/", '', $color);
89
+        if (strlen($hex) === 3) {
90
+            $hex = $hex{0} . $hex{0} . $hex{1} . $hex{1} . $hex{2} . $hex{2};
91
+        }
92
+        if (strlen($hex) !== 6) {
93
+            return 0;
94
+        }
95
+        $r = hexdec(substr($hex, 0, 2));
96
+        $g = hexdec(substr($hex, 2, 2));
97
+        $b = hexdec(substr($hex, 4, 2));
98
+        return (0.299 * $r + 0.587 * $g + 0.114 * $b)/255;
99
+    }
100
+
101
+    /**
102
+     * @param $color
103
+     * @return string base64 encoded radio button svg
104
+     */
105
+    public function generateRadioButton($color) {
106
+        $radioButtonIcon = '<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">' .
107
+            '<path d="M8 1a7 7 0 0 0-7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0-7-7zm0 1a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6zm0 2a4 4 0 1 0 0 8 4 4 0 0 0 0-8z" fill="'.$color.'"/></svg>';
108
+        return base64_encode($radioButtonIcon);
109
+    }
110
+
111
+
112
+    /**
113
+     * @param $app string app name
114
+     * @return string path to app icon / logo
115
+     */
116
+    public function getAppIcon($app) {
117
+        $app = str_replace(array('\0', '/', '\\', '..'), '', $app);
118
+        try {
119
+            $appPath = $this->appManager->getAppPath($app);
120
+            $icon = $appPath . '/img/' . $app . '.svg';
121
+            if (file_exists($icon)) {
122
+                return $icon;
123
+            }
124
+            $icon = $appPath . '/img/app.svg';
125
+            if (file_exists($icon)) {
126
+                return $icon;
127
+            }
128
+        } catch (AppPathNotFoundException $e) {}
129
+
130
+        if($this->config->getAppValue('theming', 'logoMime', '') !== '' && $this->rootFolder->nodeExists('/themedinstancelogo')) {
131
+            return $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/themedinstancelogo';
132
+        }
133
+        return \OC::$SERVERROOT . '/core/img/logo.svg';
134
+    }
135
+
136
+    /**
137
+     * @param $app string app name
138
+     * @param $image string relative path to image in app folder
139
+     * @return string|false absolute path to image
140
+     */
141
+    public function getAppImage($app, $image) {
142
+        $app = str_replace(array('\0', '/', '\\', '..'), '', $app);
143
+        $image = str_replace(array('\0', '\\', '..'), '', $image);
144
+        if ($app === "core") {
145
+            $icon = \OC::$SERVERROOT . '/core/img/' . $image;
146
+            if (file_exists($icon)) {
147
+                return $icon;
148
+            }
149
+        }
150
+
151
+        try {
152
+            $appPath = $this->appManager->getAppPath($app);
153
+        } catch (AppPathNotFoundException $e) {
154
+            return false;
155
+        }
156
+
157
+        $icon = $appPath . '/img/' . $image;
158
+        if (file_exists($icon)) {
159
+            return $icon;
160
+        }
161
+        $icon = $appPath . '/img/' . $image . '.svg';
162
+        if (file_exists($icon)) {
163
+            return $icon;
164
+        }
165
+        $icon = $appPath . '/img/' . $image . '.png';
166
+        if (file_exists($icon)) {
167
+            return $icon;
168
+        }
169
+        $icon = $appPath . '/img/' . $image . '.gif';
170
+        if (file_exists($icon)) {
171
+            return $icon;
172
+        }
173
+        $icon = $appPath . '/img/' . $image . '.jpg';
174
+        if (file_exists($icon)) {
175
+            return $icon;
176
+        }
177
+
178
+        return false;
179
+    }
180
+
181
+    /**
182
+     * replace default color with a custom one
183
+     *
184
+     * @param $svg string content of a svg file
185
+     * @param $color string color to match
186
+     * @return string
187
+     */
188
+    public function colorizeSvg($svg, $color) {
189
+        $svg = preg_replace('/#0082c9/i', $color, $svg);
190
+        return $svg;
191
+    }
192 192
 
193 193
 }
Please login to merge, or discard this patch.
Spacing   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -58,7 +58,7 @@  discard block
 block discarded – undo
58 58
 	 */
59 59
 	public function invertTextColor($color) {
60 60
 		$l = $this->calculateLuminance($color);
61
-		if($l>0.5) {
61
+		if ($l > 0.5) {
62 62
 			return true;
63 63
 		} else {
64 64
 			return false;
@@ -73,7 +73,7 @@  discard block
 block discarded – undo
73 73
 	 */
74 74
 	public function elementColor($color) {
75 75
 		$l = $this->calculateLuminance($color);
76
-		if($l>0.8) {
76
+		if ($l > 0.8) {
77 77
 			return '#555555';
78 78
 		} else {
79 79
 			return $color;
@@ -87,7 +87,7 @@  discard block
 block discarded – undo
87 87
 	public function calculateLuminance($color) {
88 88
 		$hex = preg_replace("/[^0-9A-Fa-f]/", '', $color);
89 89
 		if (strlen($hex) === 3) {
90
-			$hex = $hex{0} . $hex{0} . $hex{1} . $hex{1} . $hex{2} . $hex{2};
90
+			$hex = $hex{0}.$hex{0}.$hex{1}.$hex{1}.$hex{2}.$hex{2};
91 91
 		}
92 92
 		if (strlen($hex) !== 6) {
93 93
 			return 0;
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
 		$r = hexdec(substr($hex, 0, 2));
96 96
 		$g = hexdec(substr($hex, 2, 2));
97 97
 		$b = hexdec(substr($hex, 4, 2));
98
-		return (0.299 * $r + 0.587 * $g + 0.114 * $b)/255;
98
+		return (0.299 * $r + 0.587 * $g + 0.114 * $b) / 255;
99 99
 	}
100 100
 
101 101
 	/**
@@ -103,7 +103,7 @@  discard block
 block discarded – undo
103 103
 	 * @return string base64 encoded radio button svg
104 104
 	 */
105 105
 	public function generateRadioButton($color) {
106
-		$radioButtonIcon = '<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">' .
106
+		$radioButtonIcon = '<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">'.
107 107
 			'<path d="M8 1a7 7 0 0 0-7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0-7-7zm0 1a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6zm0 2a4 4 0 1 0 0 8 4 4 0 0 0 0-8z" fill="'.$color.'"/></svg>';
108 108
 		return base64_encode($radioButtonIcon);
109 109
 	}
@@ -117,20 +117,20 @@  discard block
 block discarded – undo
117 117
 		$app = str_replace(array('\0', '/', '\\', '..'), '', $app);
118 118
 		try {
119 119
 			$appPath = $this->appManager->getAppPath($app);
120
-			$icon = $appPath . '/img/' . $app . '.svg';
120
+			$icon = $appPath.'/img/'.$app.'.svg';
121 121
 			if (file_exists($icon)) {
122 122
 				return $icon;
123 123
 			}
124
-			$icon = $appPath . '/img/app.svg';
124
+			$icon = $appPath.'/img/app.svg';
125 125
 			if (file_exists($icon)) {
126 126
 				return $icon;
127 127
 			}
128 128
 		} catch (AppPathNotFoundException $e) {}
129 129
 
130
-		if($this->config->getAppValue('theming', 'logoMime', '') !== '' && $this->rootFolder->nodeExists('/themedinstancelogo')) {
131
-			return $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/themedinstancelogo';
130
+		if ($this->config->getAppValue('theming', 'logoMime', '') !== '' && $this->rootFolder->nodeExists('/themedinstancelogo')) {
131
+			return $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data').'/themedinstancelogo';
132 132
 		}
133
-		return \OC::$SERVERROOT . '/core/img/logo.svg';
133
+		return \OC::$SERVERROOT.'/core/img/logo.svg';
134 134
 	}
135 135
 
136 136
 	/**
@@ -142,7 +142,7 @@  discard block
 block discarded – undo
142 142
 		$app = str_replace(array('\0', '/', '\\', '..'), '', $app);
143 143
 		$image = str_replace(array('\0', '\\', '..'), '', $image);
144 144
 		if ($app === "core") {
145
-			$icon = \OC::$SERVERROOT . '/core/img/' . $image;
145
+			$icon = \OC::$SERVERROOT.'/core/img/'.$image;
146 146
 			if (file_exists($icon)) {
147 147
 				return $icon;
148 148
 			}
@@ -154,23 +154,23 @@  discard block
 block discarded – undo
154 154
 			return false;
155 155
 		}
156 156
 
157
-		$icon = $appPath . '/img/' . $image;
157
+		$icon = $appPath.'/img/'.$image;
158 158
 		if (file_exists($icon)) {
159 159
 			return $icon;
160 160
 		}
161
-		$icon = $appPath . '/img/' . $image . '.svg';
161
+		$icon = $appPath.'/img/'.$image.'.svg';
162 162
 		if (file_exists($icon)) {
163 163
 			return $icon;
164 164
 		}
165
-		$icon = $appPath . '/img/' . $image . '.png';
165
+		$icon = $appPath.'/img/'.$image.'.png';
166 166
 		if (file_exists($icon)) {
167 167
 			return $icon;
168 168
 		}
169
-		$icon = $appPath . '/img/' . $image . '.gif';
169
+		$icon = $appPath.'/img/'.$image.'.gif';
170 170
 		if (file_exists($icon)) {
171 171
 			return $icon;
172 172
 		}
173
-		$icon = $appPath . '/img/' . $image . '.jpg';
173
+		$icon = $appPath.'/img/'.$image.'.jpg';
174 174
 		if (file_exists($icon)) {
175 175
 			return $icon;
176 176
 		}
Please login to merge, or discard this patch.
apps/files_external/lib/Service/DBConfigService.php 3 patches
Doc Comments   +16 added lines patch added patch discarded remove patch
@@ -89,6 +89,9 @@  discard block
 block discarded – undo
89 89
 		return $this->getMountsFromQuery($query);
90 90
 	}
91 91
 
92
+	/**
93
+	 * @param string $userId
94
+	 */
92 95
 	public function getMountsForUser($userId, $groupIds) {
93 96
 		$builder = $this->connection->getQueryBuilder();
94 97
 		$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
@@ -125,6 +128,10 @@  discard block
 block discarded – undo
125 128
 		return $this->getMountsFromQuery($query);
126 129
 	}
127 130
 
131
+	/**
132
+	 * @param integer $type
133
+	 * @param string|null $value
134
+	 */
128 135
 	protected function getForQuery(IQueryBuilder $builder, $type, $value) {
129 136
 		$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
130 137
 			->from('external_mounts', 'm')
@@ -332,6 +339,9 @@  discard block
 block discarded – undo
332 339
 		}
333 340
 	}
334 341
 
342
+	/**
343
+	 * @param integer $mountId
344
+	 */
335 345
 	public function addApplicable($mountId, $type, $value) {
336 346
 		$this->connection->insertIfNotExist('*PREFIX*external_applicable', [
337 347
 			'mount_id' => $mountId,
@@ -340,6 +350,9 @@  discard block
 block discarded – undo
340 350
 		], ['mount_id', 'type', 'value']);
341 351
 	}
342 352
 
353
+	/**
354
+	 * @param integer $mountId
355
+	 */
343 356
 	public function removeApplicable($mountId, $type, $value) {
344 357
 		$builder = $this->connection->getQueryBuilder();
345 358
 		$query = $builder->delete('external_applicable')
@@ -473,6 +486,9 @@  discard block
 block discarded – undo
473 486
 		return array_combine($keys, $values);
474 487
 	}
475 488
 
489
+	/**
490
+	 * @param string $value
491
+	 */
476 492
 	private function encryptValue($value) {
477 493
 		return $this->crypto->encrypt($value);
478 494
 	}
Please login to merge, or discard this patch.
Indentation   +452 added lines, -452 removed lines patch added patch discarded remove patch
@@ -32,456 +32,456 @@
 block discarded – undo
32 32
  * Stores the mount config in the database
33 33
  */
34 34
 class DBConfigService {
35
-	const MOUNT_TYPE_ADMIN = 1;
36
-	const MOUNT_TYPE_PERSONAl = 2;
37
-
38
-	const APPLICABLE_TYPE_GLOBAL = 1;
39
-	const APPLICABLE_TYPE_GROUP = 2;
40
-	const APPLICABLE_TYPE_USER = 3;
41
-
42
-	/**
43
-	 * @var IDBConnection
44
-	 */
45
-	private $connection;
46
-
47
-	/**
48
-	 * @var ICrypto
49
-	 */
50
-	private $crypto;
51
-
52
-	/**
53
-	 * DBConfigService constructor.
54
-	 *
55
-	 * @param IDBConnection $connection
56
-	 * @param ICrypto $crypto
57
-	 */
58
-	public function __construct(IDBConnection $connection, ICrypto $crypto) {
59
-		$this->connection = $connection;
60
-		$this->crypto = $crypto;
61
-	}
62
-
63
-	/**
64
-	 * @param int $mountId
65
-	 * @return array
66
-	 */
67
-	public function getMountById($mountId) {
68
-		$builder = $this->connection->getQueryBuilder();
69
-		$query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
70
-			->from('external_mounts', 'm')
71
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
72
-		$mounts = $this->getMountsFromQuery($query);
73
-		if (count($mounts) > 0) {
74
-			return $mounts[0];
75
-		} else {
76
-			return null;
77
-		}
78
-	}
79
-
80
-	/**
81
-	 * Get all configured mounts
82
-	 *
83
-	 * @return array
84
-	 */
85
-	public function getAllMounts() {
86
-		$builder = $this->connection->getQueryBuilder();
87
-		$query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
88
-			->from('external_mounts');
89
-		return $this->getMountsFromQuery($query);
90
-	}
91
-
92
-	public function getMountsForUser($userId, $groupIds) {
93
-		$builder = $this->connection->getQueryBuilder();
94
-		$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
95
-			->from('external_mounts', 'm')
96
-			->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
97
-			->where($builder->expr()->orX(
98
-				$builder->expr()->andX( // global mounts
99
-					$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GLOBAL, IQueryBuilder::PARAM_INT)),
100
-					$builder->expr()->isNull('a.value')
101
-				),
102
-				$builder->expr()->andX( // mounts for user
103
-					$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_USER, IQueryBuilder::PARAM_INT)),
104
-					$builder->expr()->eq('a.value', $builder->createNamedParameter($userId))
105
-				),
106
-				$builder->expr()->andX( // mounts for group
107
-					$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GROUP, IQueryBuilder::PARAM_INT)),
108
-					$builder->expr()->in('a.value', $builder->createNamedParameter($groupIds, IQueryBuilder::PARAM_INT_ARRAY))
109
-				)
110
-			));
111
-
112
-		return $this->getMountsFromQuery($query);
113
-	}
114
-
115
-	/**
116
-	 * Get admin defined mounts
117
-	 *
118
-	 * @return array
119
-	 */
120
-	public function getAdminMounts() {
121
-		$builder = $this->connection->getQueryBuilder();
122
-		$query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
123
-			->from('external_mounts')
124
-			->where($builder->expr()->eq('type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
125
-		return $this->getMountsFromQuery($query);
126
-	}
127
-
128
-	protected function getForQuery(IQueryBuilder $builder, $type, $value) {
129
-		$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
130
-			->from('external_mounts', 'm')
131
-			->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
132
-			->where($builder->expr()->eq('a.type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
133
-
134
-		if (is_null($value)) {
135
-			$query = $query->andWhere($builder->expr()->isNull('a.value'));
136
-		} else {
137
-			$query = $query->andWhere($builder->expr()->eq('a.value', $builder->createNamedParameter($value)));
138
-		}
139
-
140
-		return $query;
141
-	}
142
-
143
-	/**
144
-	 * Get mounts by applicable
145
-	 *
146
-	 * @param int $type any of the self::APPLICABLE_TYPE_ constants
147
-	 * @param string|null $value user_id, group_id or null for global mounts
148
-	 * @return array
149
-	 */
150
-	public function getMountsFor($type, $value) {
151
-		$builder = $this->connection->getQueryBuilder();
152
-		$query = $this->getForQuery($builder, $type, $value);
153
-
154
-		return $this->getMountsFromQuery($query);
155
-	}
156
-
157
-	/**
158
-	 * Get admin defined mounts by applicable
159
-	 *
160
-	 * @param int $type any of the self::APPLICABLE_TYPE_ constants
161
-	 * @param string|null $value user_id, group_id or null for global mounts
162
-	 * @return array
163
-	 */
164
-	public function getAdminMountsFor($type, $value) {
165
-		$builder = $this->connection->getQueryBuilder();
166
-		$query = $this->getForQuery($builder, $type, $value);
167
-		$query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
168
-
169
-		return $this->getMountsFromQuery($query);
170
-	}
171
-
172
-	/**
173
-	 * Get admin defined mounts for multiple applicable
174
-	 *
175
-	 * @param int $type any of the self::APPLICABLE_TYPE_ constants
176
-	 * @param string[] $values user_ids or group_ids
177
-	 * @return array
178
-	 */
179
-	public function getAdminMountsForMultiple($type, array $values) {
180
-		$builder = $this->connection->getQueryBuilder();
181
-		$params = array_map(function ($value) use ($builder) {
182
-			return $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR);
183
-		}, $values);
184
-
185
-		$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
186
-			->from('external_mounts', 'm')
187
-			->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
188
-			->where($builder->expr()->eq('a.type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)))
189
-			->andWhere($builder->expr()->in('a.value', $params));
190
-		$query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
191
-
192
-		return $this->getMountsFromQuery($query);
193
-	}
194
-
195
-	/**
196
-	 * Get user defined mounts by applicable
197
-	 *
198
-	 * @param int $type any of the self::APPLICABLE_TYPE_ constants
199
-	 * @param string|null $value user_id, group_id or null for global mounts
200
-	 * @return array
201
-	 */
202
-	public function getUserMountsFor($type, $value) {
203
-		$builder = $this->connection->getQueryBuilder();
204
-		$query = $this->getForQuery($builder, $type, $value);
205
-		$query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_PERSONAl, IQueryBuilder::PARAM_INT)));
206
-
207
-		return $this->getMountsFromQuery($query);
208
-	}
209
-
210
-	/**
211
-	 * Add a mount to the database
212
-	 *
213
-	 * @param string $mountPoint
214
-	 * @param string $storageBackend
215
-	 * @param string $authBackend
216
-	 * @param int $priority
217
-	 * @param int $type self::MOUNT_TYPE_ADMIN or self::MOUNT_TYPE_PERSONAL
218
-	 * @return int the id of the new mount
219
-	 */
220
-	public function addMount($mountPoint, $storageBackend, $authBackend, $priority, $type) {
221
-		if (!$priority) {
222
-			$priority = 100;
223
-		}
224
-		$builder = $this->connection->getQueryBuilder();
225
-		$query = $builder->insert('external_mounts')
226
-			->values([
227
-				'mount_point' => $builder->createNamedParameter($mountPoint, IQueryBuilder::PARAM_STR),
228
-				'storage_backend' => $builder->createNamedParameter($storageBackend, IQueryBuilder::PARAM_STR),
229
-				'auth_backend' => $builder->createNamedParameter($authBackend, IQueryBuilder::PARAM_STR),
230
-				'priority' => $builder->createNamedParameter($priority, IQueryBuilder::PARAM_INT),
231
-				'type' => $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)
232
-			]);
233
-		$query->execute();
234
-		return (int)$this->connection->lastInsertId('*PREFIX*external_mounts');
235
-	}
236
-
237
-	/**
238
-	 * Remove a mount from the database
239
-	 *
240
-	 * @param int $mountId
241
-	 */
242
-	public function removeMount($mountId) {
243
-		$builder = $this->connection->getQueryBuilder();
244
-		$query = $builder->delete('external_mounts')
245
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
246
-		$query->execute();
247
-
248
-		$query = $builder->delete('external_applicable')
249
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
250
-		$query->execute();
251
-
252
-		$query = $builder->delete('external_config')
253
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
254
-		$query->execute();
255
-
256
-		$query = $builder->delete('external_options')
257
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
258
-		$query->execute();
259
-	}
260
-
261
-	/**
262
-	 * @param int $mountId
263
-	 * @param string $newMountPoint
264
-	 */
265
-	public function setMountPoint($mountId, $newMountPoint) {
266
-		$builder = $this->connection->getQueryBuilder();
267
-
268
-		$query = $builder->update('external_mounts')
269
-			->set('mount_point', $builder->createNamedParameter($newMountPoint))
270
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
271
-
272
-		$query->execute();
273
-	}
274
-
275
-	/**
276
-	 * @param int $mountId
277
-	 * @param string $newAuthBackend
278
-	 */
279
-	public function setAuthBackend($mountId, $newAuthBackend) {
280
-		$builder = $this->connection->getQueryBuilder();
281
-
282
-		$query = $builder->update('external_mounts')
283
-			->set('auth_backend', $builder->createNamedParameter($newAuthBackend))
284
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
285
-
286
-		$query->execute();
287
-	}
288
-
289
-	/**
290
-	 * @param int $mountId
291
-	 * @param string $key
292
-	 * @param string $value
293
-	 */
294
-	public function setConfig($mountId, $key, $value) {
295
-		if ($key === 'password') {
296
-			$value = $this->encryptValue($value);
297
-		}
298
-		$count = $this->connection->insertIfNotExist('*PREFIX*external_config', [
299
-			'mount_id' => $mountId,
300
-			'key' => $key,
301
-			'value' => $value
302
-		], ['mount_id', 'key']);
303
-		if ($count === 0) {
304
-			$builder = $this->connection->getQueryBuilder();
305
-			$query = $builder->update('external_config')
306
-				->set('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR))
307
-				->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
308
-				->andWhere($builder->expr()->eq('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR)));
309
-			$query->execute();
310
-		}
311
-	}
312
-
313
-	/**
314
-	 * @param int $mountId
315
-	 * @param string $key
316
-	 * @param string $value
317
-	 */
318
-	public function setOption($mountId, $key, $value) {
319
-
320
-		$count = $this->connection->insertIfNotExist('*PREFIX*external_options', [
321
-			'mount_id' => $mountId,
322
-			'key' => $key,
323
-			'value' => json_encode($value)
324
-		], ['mount_id', 'key']);
325
-		if ($count === 0) {
326
-			$builder = $this->connection->getQueryBuilder();
327
-			$query = $builder->update('external_options')
328
-				->set('value', $builder->createNamedParameter(json_encode($value), IQueryBuilder::PARAM_STR))
329
-				->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
330
-				->andWhere($builder->expr()->eq('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR)));
331
-			$query->execute();
332
-		}
333
-	}
334
-
335
-	public function addApplicable($mountId, $type, $value) {
336
-		$this->connection->insertIfNotExist('*PREFIX*external_applicable', [
337
-			'mount_id' => $mountId,
338
-			'type' => $type,
339
-			'value' => $value
340
-		], ['mount_id', 'type', 'value']);
341
-	}
342
-
343
-	public function removeApplicable($mountId, $type, $value) {
344
-		$builder = $this->connection->getQueryBuilder();
345
-		$query = $builder->delete('external_applicable')
346
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
347
-			->andWhere($builder->expr()->eq('type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
348
-
349
-		if (is_null($value)) {
350
-			$query = $query->andWhere($builder->expr()->isNull('value'));
351
-		} else {
352
-			$query = $query->andWhere($builder->expr()->eq('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR)));
353
-		}
354
-
355
-		$query->execute();
356
-	}
357
-
358
-	private function getMountsFromQuery(IQueryBuilder $query) {
359
-		$result = $query->execute();
360
-		$mounts = $result->fetchAll();
361
-		$uniqueMounts = [];
362
-		foreach ($mounts as $mount) {
363
-			$id = $mount['mount_id'];
364
-			if (!isset($uniqueMounts[$id])) {
365
-				$uniqueMounts[$id] = $mount;
366
-			}
367
-		}
368
-		$uniqueMounts = array_values($uniqueMounts);
369
-
370
-		$mountIds = array_map(function ($mount) {
371
-			return $mount['mount_id'];
372
-		}, $uniqueMounts);
373
-		$mountIds = array_values(array_unique($mountIds));
374
-
375
-		$applicable = $this->getApplicableForMounts($mountIds);
376
-		$config = $this->getConfigForMounts($mountIds);
377
-		$options = $this->getOptionsForMounts($mountIds);
378
-
379
-		return array_map(function ($mount, $applicable, $config, $options) {
380
-			$mount['type'] = (int)$mount['type'];
381
-			$mount['priority'] = (int)$mount['priority'];
382
-			$mount['applicable'] = $applicable;
383
-			$mount['config'] = $config;
384
-			$mount['options'] = $options;
385
-			return $mount;
386
-		}, $uniqueMounts, $applicable, $config, $options);
387
-	}
388
-
389
-	/**
390
-	 * Get mount options from a table grouped by mount id
391
-	 *
392
-	 * @param string $table
393
-	 * @param string[] $fields
394
-	 * @param int[] $mountIds
395
-	 * @return array [$mountId => [['field1' => $value1, ...], ...], ...]
396
-	 */
397
-	private function selectForMounts($table, array $fields, array $mountIds) {
398
-		if (count($mountIds) === 0) {
399
-			return [];
400
-		}
401
-		$builder = $this->connection->getQueryBuilder();
402
-		$fields[] = 'mount_id';
403
-		$placeHolders = array_map(function ($id) use ($builder) {
404
-			return $builder->createPositionalParameter($id, IQueryBuilder::PARAM_INT);
405
-		}, $mountIds);
406
-		$query = $builder->select($fields)
407
-			->from($table)
408
-			->where($builder->expr()->in('mount_id', $placeHolders));
409
-		$rows = $query->execute()->fetchAll();
410
-
411
-		$result = [];
412
-		foreach ($mountIds as $mountId) {
413
-			$result[$mountId] = [];
414
-		}
415
-		foreach ($rows as $row) {
416
-			if (isset($row['type'])) {
417
-				$row['type'] = (int)$row['type'];
418
-			}
419
-			$result[$row['mount_id']][] = $row;
420
-		}
421
-		return $result;
422
-	}
423
-
424
-	/**
425
-	 * @param int[] $mountIds
426
-	 * @return array [$id => [['type' => $type, 'value' => $value], ...], ...]
427
-	 */
428
-	public function getApplicableForMounts($mountIds) {
429
-		return $this->selectForMounts('external_applicable', ['type', 'value'], $mountIds);
430
-	}
431
-
432
-	/**
433
-	 * @param int[] $mountIds
434
-	 * @return array [$id => ['key1' => $value1, ...], ...]
435
-	 */
436
-	public function getConfigForMounts($mountIds) {
437
-		$mountConfigs = $this->selectForMounts('external_config', ['key', 'value'], $mountIds);
438
-		return array_map([$this, 'createKeyValueMap'], $mountConfigs);
439
-	}
440
-
441
-	/**
442
-	 * @param int[] $mountIds
443
-	 * @return array [$id => ['key1' => $value1, ...], ...]
444
-	 */
445
-	public function getOptionsForMounts($mountIds) {
446
-		$mountOptions = $this->selectForMounts('external_options', ['key', 'value'], $mountIds);
447
-		$optionsMap = array_map([$this, 'createKeyValueMap'], $mountOptions);
448
-		return array_map(function (array $options) {
449
-			return array_map(function ($option) {
450
-				return json_decode($option);
451
-			}, $options);
452
-		}, $optionsMap);
453
-	}
454
-
455
-	/**
456
-	 * @param array $keyValuePairs [['key'=>$key, 'value=>$value], ...]
457
-	 * @return array ['key1' => $value1, ...]
458
-	 */
459
-	private function createKeyValueMap(array $keyValuePairs) {
460
-		$decryptedPairts = array_map(function ($pair) {
461
-			if ($pair['key'] === 'password') {
462
-				$pair['value'] = $this->decryptValue($pair['value']);
463
-			}
464
-			return $pair;
465
-		}, $keyValuePairs);
466
-		$keys = array_map(function ($pair) {
467
-			return $pair['key'];
468
-		}, $decryptedPairts);
469
-		$values = array_map(function ($pair) {
470
-			return $pair['value'];
471
-		}, $decryptedPairts);
472
-
473
-		return array_combine($keys, $values);
474
-	}
475
-
476
-	private function encryptValue($value) {
477
-		return $this->crypto->encrypt($value);
478
-	}
479
-
480
-	private function decryptValue($value) {
481
-		try {
482
-			return $this->crypto->decrypt($value);
483
-		} catch (\Exception $e) {
484
-			return $value;
485
-		}
486
-	}
35
+    const MOUNT_TYPE_ADMIN = 1;
36
+    const MOUNT_TYPE_PERSONAl = 2;
37
+
38
+    const APPLICABLE_TYPE_GLOBAL = 1;
39
+    const APPLICABLE_TYPE_GROUP = 2;
40
+    const APPLICABLE_TYPE_USER = 3;
41
+
42
+    /**
43
+     * @var IDBConnection
44
+     */
45
+    private $connection;
46
+
47
+    /**
48
+     * @var ICrypto
49
+     */
50
+    private $crypto;
51
+
52
+    /**
53
+     * DBConfigService constructor.
54
+     *
55
+     * @param IDBConnection $connection
56
+     * @param ICrypto $crypto
57
+     */
58
+    public function __construct(IDBConnection $connection, ICrypto $crypto) {
59
+        $this->connection = $connection;
60
+        $this->crypto = $crypto;
61
+    }
62
+
63
+    /**
64
+     * @param int $mountId
65
+     * @return array
66
+     */
67
+    public function getMountById($mountId) {
68
+        $builder = $this->connection->getQueryBuilder();
69
+        $query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
70
+            ->from('external_mounts', 'm')
71
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
72
+        $mounts = $this->getMountsFromQuery($query);
73
+        if (count($mounts) > 0) {
74
+            return $mounts[0];
75
+        } else {
76
+            return null;
77
+        }
78
+    }
79
+
80
+    /**
81
+     * Get all configured mounts
82
+     *
83
+     * @return array
84
+     */
85
+    public function getAllMounts() {
86
+        $builder = $this->connection->getQueryBuilder();
87
+        $query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
88
+            ->from('external_mounts');
89
+        return $this->getMountsFromQuery($query);
90
+    }
91
+
92
+    public function getMountsForUser($userId, $groupIds) {
93
+        $builder = $this->connection->getQueryBuilder();
94
+        $query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
95
+            ->from('external_mounts', 'm')
96
+            ->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
97
+            ->where($builder->expr()->orX(
98
+                $builder->expr()->andX( // global mounts
99
+                    $builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GLOBAL, IQueryBuilder::PARAM_INT)),
100
+                    $builder->expr()->isNull('a.value')
101
+                ),
102
+                $builder->expr()->andX( // mounts for user
103
+                    $builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_USER, IQueryBuilder::PARAM_INT)),
104
+                    $builder->expr()->eq('a.value', $builder->createNamedParameter($userId))
105
+                ),
106
+                $builder->expr()->andX( // mounts for group
107
+                    $builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GROUP, IQueryBuilder::PARAM_INT)),
108
+                    $builder->expr()->in('a.value', $builder->createNamedParameter($groupIds, IQueryBuilder::PARAM_INT_ARRAY))
109
+                )
110
+            ));
111
+
112
+        return $this->getMountsFromQuery($query);
113
+    }
114
+
115
+    /**
116
+     * Get admin defined mounts
117
+     *
118
+     * @return array
119
+     */
120
+    public function getAdminMounts() {
121
+        $builder = $this->connection->getQueryBuilder();
122
+        $query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
123
+            ->from('external_mounts')
124
+            ->where($builder->expr()->eq('type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
125
+        return $this->getMountsFromQuery($query);
126
+    }
127
+
128
+    protected function getForQuery(IQueryBuilder $builder, $type, $value) {
129
+        $query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
130
+            ->from('external_mounts', 'm')
131
+            ->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
132
+            ->where($builder->expr()->eq('a.type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
133
+
134
+        if (is_null($value)) {
135
+            $query = $query->andWhere($builder->expr()->isNull('a.value'));
136
+        } else {
137
+            $query = $query->andWhere($builder->expr()->eq('a.value', $builder->createNamedParameter($value)));
138
+        }
139
+
140
+        return $query;
141
+    }
142
+
143
+    /**
144
+     * Get mounts by applicable
145
+     *
146
+     * @param int $type any of the self::APPLICABLE_TYPE_ constants
147
+     * @param string|null $value user_id, group_id or null for global mounts
148
+     * @return array
149
+     */
150
+    public function getMountsFor($type, $value) {
151
+        $builder = $this->connection->getQueryBuilder();
152
+        $query = $this->getForQuery($builder, $type, $value);
153
+
154
+        return $this->getMountsFromQuery($query);
155
+    }
156
+
157
+    /**
158
+     * Get admin defined mounts by applicable
159
+     *
160
+     * @param int $type any of the self::APPLICABLE_TYPE_ constants
161
+     * @param string|null $value user_id, group_id or null for global mounts
162
+     * @return array
163
+     */
164
+    public function getAdminMountsFor($type, $value) {
165
+        $builder = $this->connection->getQueryBuilder();
166
+        $query = $this->getForQuery($builder, $type, $value);
167
+        $query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
168
+
169
+        return $this->getMountsFromQuery($query);
170
+    }
171
+
172
+    /**
173
+     * Get admin defined mounts for multiple applicable
174
+     *
175
+     * @param int $type any of the self::APPLICABLE_TYPE_ constants
176
+     * @param string[] $values user_ids or group_ids
177
+     * @return array
178
+     */
179
+    public function getAdminMountsForMultiple($type, array $values) {
180
+        $builder = $this->connection->getQueryBuilder();
181
+        $params = array_map(function ($value) use ($builder) {
182
+            return $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR);
183
+        }, $values);
184
+
185
+        $query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
186
+            ->from('external_mounts', 'm')
187
+            ->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
188
+            ->where($builder->expr()->eq('a.type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)))
189
+            ->andWhere($builder->expr()->in('a.value', $params));
190
+        $query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
191
+
192
+        return $this->getMountsFromQuery($query);
193
+    }
194
+
195
+    /**
196
+     * Get user defined mounts by applicable
197
+     *
198
+     * @param int $type any of the self::APPLICABLE_TYPE_ constants
199
+     * @param string|null $value user_id, group_id or null for global mounts
200
+     * @return array
201
+     */
202
+    public function getUserMountsFor($type, $value) {
203
+        $builder = $this->connection->getQueryBuilder();
204
+        $query = $this->getForQuery($builder, $type, $value);
205
+        $query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_PERSONAl, IQueryBuilder::PARAM_INT)));
206
+
207
+        return $this->getMountsFromQuery($query);
208
+    }
209
+
210
+    /**
211
+     * Add a mount to the database
212
+     *
213
+     * @param string $mountPoint
214
+     * @param string $storageBackend
215
+     * @param string $authBackend
216
+     * @param int $priority
217
+     * @param int $type self::MOUNT_TYPE_ADMIN or self::MOUNT_TYPE_PERSONAL
218
+     * @return int the id of the new mount
219
+     */
220
+    public function addMount($mountPoint, $storageBackend, $authBackend, $priority, $type) {
221
+        if (!$priority) {
222
+            $priority = 100;
223
+        }
224
+        $builder = $this->connection->getQueryBuilder();
225
+        $query = $builder->insert('external_mounts')
226
+            ->values([
227
+                'mount_point' => $builder->createNamedParameter($mountPoint, IQueryBuilder::PARAM_STR),
228
+                'storage_backend' => $builder->createNamedParameter($storageBackend, IQueryBuilder::PARAM_STR),
229
+                'auth_backend' => $builder->createNamedParameter($authBackend, IQueryBuilder::PARAM_STR),
230
+                'priority' => $builder->createNamedParameter($priority, IQueryBuilder::PARAM_INT),
231
+                'type' => $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)
232
+            ]);
233
+        $query->execute();
234
+        return (int)$this->connection->lastInsertId('*PREFIX*external_mounts');
235
+    }
236
+
237
+    /**
238
+     * Remove a mount from the database
239
+     *
240
+     * @param int $mountId
241
+     */
242
+    public function removeMount($mountId) {
243
+        $builder = $this->connection->getQueryBuilder();
244
+        $query = $builder->delete('external_mounts')
245
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
246
+        $query->execute();
247
+
248
+        $query = $builder->delete('external_applicable')
249
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
250
+        $query->execute();
251
+
252
+        $query = $builder->delete('external_config')
253
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
254
+        $query->execute();
255
+
256
+        $query = $builder->delete('external_options')
257
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
258
+        $query->execute();
259
+    }
260
+
261
+    /**
262
+     * @param int $mountId
263
+     * @param string $newMountPoint
264
+     */
265
+    public function setMountPoint($mountId, $newMountPoint) {
266
+        $builder = $this->connection->getQueryBuilder();
267
+
268
+        $query = $builder->update('external_mounts')
269
+            ->set('mount_point', $builder->createNamedParameter($newMountPoint))
270
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
271
+
272
+        $query->execute();
273
+    }
274
+
275
+    /**
276
+     * @param int $mountId
277
+     * @param string $newAuthBackend
278
+     */
279
+    public function setAuthBackend($mountId, $newAuthBackend) {
280
+        $builder = $this->connection->getQueryBuilder();
281
+
282
+        $query = $builder->update('external_mounts')
283
+            ->set('auth_backend', $builder->createNamedParameter($newAuthBackend))
284
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
285
+
286
+        $query->execute();
287
+    }
288
+
289
+    /**
290
+     * @param int $mountId
291
+     * @param string $key
292
+     * @param string $value
293
+     */
294
+    public function setConfig($mountId, $key, $value) {
295
+        if ($key === 'password') {
296
+            $value = $this->encryptValue($value);
297
+        }
298
+        $count = $this->connection->insertIfNotExist('*PREFIX*external_config', [
299
+            'mount_id' => $mountId,
300
+            'key' => $key,
301
+            'value' => $value
302
+        ], ['mount_id', 'key']);
303
+        if ($count === 0) {
304
+            $builder = $this->connection->getQueryBuilder();
305
+            $query = $builder->update('external_config')
306
+                ->set('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR))
307
+                ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
308
+                ->andWhere($builder->expr()->eq('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR)));
309
+            $query->execute();
310
+        }
311
+    }
312
+
313
+    /**
314
+     * @param int $mountId
315
+     * @param string $key
316
+     * @param string $value
317
+     */
318
+    public function setOption($mountId, $key, $value) {
319
+
320
+        $count = $this->connection->insertIfNotExist('*PREFIX*external_options', [
321
+            'mount_id' => $mountId,
322
+            'key' => $key,
323
+            'value' => json_encode($value)
324
+        ], ['mount_id', 'key']);
325
+        if ($count === 0) {
326
+            $builder = $this->connection->getQueryBuilder();
327
+            $query = $builder->update('external_options')
328
+                ->set('value', $builder->createNamedParameter(json_encode($value), IQueryBuilder::PARAM_STR))
329
+                ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
330
+                ->andWhere($builder->expr()->eq('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR)));
331
+            $query->execute();
332
+        }
333
+    }
334
+
335
+    public function addApplicable($mountId, $type, $value) {
336
+        $this->connection->insertIfNotExist('*PREFIX*external_applicable', [
337
+            'mount_id' => $mountId,
338
+            'type' => $type,
339
+            'value' => $value
340
+        ], ['mount_id', 'type', 'value']);
341
+    }
342
+
343
+    public function removeApplicable($mountId, $type, $value) {
344
+        $builder = $this->connection->getQueryBuilder();
345
+        $query = $builder->delete('external_applicable')
346
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
347
+            ->andWhere($builder->expr()->eq('type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
348
+
349
+        if (is_null($value)) {
350
+            $query = $query->andWhere($builder->expr()->isNull('value'));
351
+        } else {
352
+            $query = $query->andWhere($builder->expr()->eq('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR)));
353
+        }
354
+
355
+        $query->execute();
356
+    }
357
+
358
+    private function getMountsFromQuery(IQueryBuilder $query) {
359
+        $result = $query->execute();
360
+        $mounts = $result->fetchAll();
361
+        $uniqueMounts = [];
362
+        foreach ($mounts as $mount) {
363
+            $id = $mount['mount_id'];
364
+            if (!isset($uniqueMounts[$id])) {
365
+                $uniqueMounts[$id] = $mount;
366
+            }
367
+        }
368
+        $uniqueMounts = array_values($uniqueMounts);
369
+
370
+        $mountIds = array_map(function ($mount) {
371
+            return $mount['mount_id'];
372
+        }, $uniqueMounts);
373
+        $mountIds = array_values(array_unique($mountIds));
374
+
375
+        $applicable = $this->getApplicableForMounts($mountIds);
376
+        $config = $this->getConfigForMounts($mountIds);
377
+        $options = $this->getOptionsForMounts($mountIds);
378
+
379
+        return array_map(function ($mount, $applicable, $config, $options) {
380
+            $mount['type'] = (int)$mount['type'];
381
+            $mount['priority'] = (int)$mount['priority'];
382
+            $mount['applicable'] = $applicable;
383
+            $mount['config'] = $config;
384
+            $mount['options'] = $options;
385
+            return $mount;
386
+        }, $uniqueMounts, $applicable, $config, $options);
387
+    }
388
+
389
+    /**
390
+     * Get mount options from a table grouped by mount id
391
+     *
392
+     * @param string $table
393
+     * @param string[] $fields
394
+     * @param int[] $mountIds
395
+     * @return array [$mountId => [['field1' => $value1, ...], ...], ...]
396
+     */
397
+    private function selectForMounts($table, array $fields, array $mountIds) {
398
+        if (count($mountIds) === 0) {
399
+            return [];
400
+        }
401
+        $builder = $this->connection->getQueryBuilder();
402
+        $fields[] = 'mount_id';
403
+        $placeHolders = array_map(function ($id) use ($builder) {
404
+            return $builder->createPositionalParameter($id, IQueryBuilder::PARAM_INT);
405
+        }, $mountIds);
406
+        $query = $builder->select($fields)
407
+            ->from($table)
408
+            ->where($builder->expr()->in('mount_id', $placeHolders));
409
+        $rows = $query->execute()->fetchAll();
410
+
411
+        $result = [];
412
+        foreach ($mountIds as $mountId) {
413
+            $result[$mountId] = [];
414
+        }
415
+        foreach ($rows as $row) {
416
+            if (isset($row['type'])) {
417
+                $row['type'] = (int)$row['type'];
418
+            }
419
+            $result[$row['mount_id']][] = $row;
420
+        }
421
+        return $result;
422
+    }
423
+
424
+    /**
425
+     * @param int[] $mountIds
426
+     * @return array [$id => [['type' => $type, 'value' => $value], ...], ...]
427
+     */
428
+    public function getApplicableForMounts($mountIds) {
429
+        return $this->selectForMounts('external_applicable', ['type', 'value'], $mountIds);
430
+    }
431
+
432
+    /**
433
+     * @param int[] $mountIds
434
+     * @return array [$id => ['key1' => $value1, ...], ...]
435
+     */
436
+    public function getConfigForMounts($mountIds) {
437
+        $mountConfigs = $this->selectForMounts('external_config', ['key', 'value'], $mountIds);
438
+        return array_map([$this, 'createKeyValueMap'], $mountConfigs);
439
+    }
440
+
441
+    /**
442
+     * @param int[] $mountIds
443
+     * @return array [$id => ['key1' => $value1, ...], ...]
444
+     */
445
+    public function getOptionsForMounts($mountIds) {
446
+        $mountOptions = $this->selectForMounts('external_options', ['key', 'value'], $mountIds);
447
+        $optionsMap = array_map([$this, 'createKeyValueMap'], $mountOptions);
448
+        return array_map(function (array $options) {
449
+            return array_map(function ($option) {
450
+                return json_decode($option);
451
+            }, $options);
452
+        }, $optionsMap);
453
+    }
454
+
455
+    /**
456
+     * @param array $keyValuePairs [['key'=>$key, 'value=>$value], ...]
457
+     * @return array ['key1' => $value1, ...]
458
+     */
459
+    private function createKeyValueMap(array $keyValuePairs) {
460
+        $decryptedPairts = array_map(function ($pair) {
461
+            if ($pair['key'] === 'password') {
462
+                $pair['value'] = $this->decryptValue($pair['value']);
463
+            }
464
+            return $pair;
465
+        }, $keyValuePairs);
466
+        $keys = array_map(function ($pair) {
467
+            return $pair['key'];
468
+        }, $decryptedPairts);
469
+        $values = array_map(function ($pair) {
470
+            return $pair['value'];
471
+        }, $decryptedPairts);
472
+
473
+        return array_combine($keys, $values);
474
+    }
475
+
476
+    private function encryptValue($value) {
477
+        return $this->crypto->encrypt($value);
478
+    }
479
+
480
+    private function decryptValue($value) {
481
+        try {
482
+            return $this->crypto->decrypt($value);
483
+        } catch (\Exception $e) {
484
+            return $value;
485
+        }
486
+    }
487 487
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -178,7 +178,7 @@  discard block
 block discarded – undo
178 178
 	 */
179 179
 	public function getAdminMountsForMultiple($type, array $values) {
180 180
 		$builder = $this->connection->getQueryBuilder();
181
-		$params = array_map(function ($value) use ($builder) {
181
+		$params = array_map(function($value) use ($builder) {
182 182
 			return $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR);
183 183
 		}, $values);
184 184
 
@@ -231,7 +231,7 @@  discard block
 block discarded – undo
231 231
 				'type' => $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)
232 232
 			]);
233 233
 		$query->execute();
234
-		return (int)$this->connection->lastInsertId('*PREFIX*external_mounts');
234
+		return (int) $this->connection->lastInsertId('*PREFIX*external_mounts');
235 235
 	}
236 236
 
237 237
 	/**
@@ -367,7 +367,7 @@  discard block
 block discarded – undo
367 367
 		}
368 368
 		$uniqueMounts = array_values($uniqueMounts);
369 369
 
370
-		$mountIds = array_map(function ($mount) {
370
+		$mountIds = array_map(function($mount) {
371 371
 			return $mount['mount_id'];
372 372
 		}, $uniqueMounts);
373 373
 		$mountIds = array_values(array_unique($mountIds));
@@ -376,9 +376,9 @@  discard block
 block discarded – undo
376 376
 		$config = $this->getConfigForMounts($mountIds);
377 377
 		$options = $this->getOptionsForMounts($mountIds);
378 378
 
379
-		return array_map(function ($mount, $applicable, $config, $options) {
380
-			$mount['type'] = (int)$mount['type'];
381
-			$mount['priority'] = (int)$mount['priority'];
379
+		return array_map(function($mount, $applicable, $config, $options) {
380
+			$mount['type'] = (int) $mount['type'];
381
+			$mount['priority'] = (int) $mount['priority'];
382 382
 			$mount['applicable'] = $applicable;
383 383
 			$mount['config'] = $config;
384 384
 			$mount['options'] = $options;
@@ -400,7 +400,7 @@  discard block
 block discarded – undo
400 400
 		}
401 401
 		$builder = $this->connection->getQueryBuilder();
402 402
 		$fields[] = 'mount_id';
403
-		$placeHolders = array_map(function ($id) use ($builder) {
403
+		$placeHolders = array_map(function($id) use ($builder) {
404 404
 			return $builder->createPositionalParameter($id, IQueryBuilder::PARAM_INT);
405 405
 		}, $mountIds);
406 406
 		$query = $builder->select($fields)
@@ -414,7 +414,7 @@  discard block
 block discarded – undo
414 414
 		}
415 415
 		foreach ($rows as $row) {
416 416
 			if (isset($row['type'])) {
417
-				$row['type'] = (int)$row['type'];
417
+				$row['type'] = (int) $row['type'];
418 418
 			}
419 419
 			$result[$row['mount_id']][] = $row;
420 420
 		}
@@ -445,8 +445,8 @@  discard block
 block discarded – undo
445 445
 	public function getOptionsForMounts($mountIds) {
446 446
 		$mountOptions = $this->selectForMounts('external_options', ['key', 'value'], $mountIds);
447 447
 		$optionsMap = array_map([$this, 'createKeyValueMap'], $mountOptions);
448
-		return array_map(function (array $options) {
449
-			return array_map(function ($option) {
448
+		return array_map(function(array $options) {
449
+			return array_map(function($option) {
450 450
 				return json_decode($option);
451 451
 			}, $options);
452 452
 		}, $optionsMap);
@@ -457,16 +457,16 @@  discard block
 block discarded – undo
457 457
 	 * @return array ['key1' => $value1, ...]
458 458
 	 */
459 459
 	private function createKeyValueMap(array $keyValuePairs) {
460
-		$decryptedPairts = array_map(function ($pair) {
460
+		$decryptedPairts = array_map(function($pair) {
461 461
 			if ($pair['key'] === 'password') {
462 462
 				$pair['value'] = $this->decryptValue($pair['value']);
463 463
 			}
464 464
 			return $pair;
465 465
 		}, $keyValuePairs);
466
-		$keys = array_map(function ($pair) {
466
+		$keys = array_map(function($pair) {
467 467
 			return $pair['key'];
468 468
 		}, $decryptedPairts);
469
-		$values = array_map(function ($pair) {
469
+		$values = array_map(function($pair) {
470 470
 			return $pair['value'];
471 471
 		}, $decryptedPairts);
472 472
 
Please login to merge, or discard this patch.
apps/federation/lib/AppInfo/Application.php 3 patches
Unused Use Statements   -3 removed lines patch added patch discarded remove patch
@@ -24,16 +24,13 @@
 block discarded – undo
24 24
 
25 25
 namespace OCA\Federation\AppInfo;
26 26
 
27
-use OCA\Federation\API\OCSAuthAPI;
28 27
 use OCA\Federation\Controller\SettingsController;
29 28
 use OCA\Federation\DAV\FedAuth;
30 29
 use OCA\Federation\DbHandler;
31 30
 use OCA\Federation\Hooks;
32 31
 use OCA\Federation\Middleware\AddServerMiddleware;
33 32
 use OCA\Federation\SyncFederationAddressBooks;
34
-use OCA\Federation\SyncJob;
35 33
 use OCA\Federation\TrustedServers;
36
-use OCP\API;
37 34
 use OCP\App;
38 35
 use OCP\AppFramework\IAppContainer;
39 36
 use OCP\SabrePluginEvent;
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -82,7 +82,7 @@
 block discarded – undo
82 82
 			);
83 83
 		});
84 84
 
85
-		$container->registerService('SettingsController', function (IAppContainer $c) {
85
+		$container->registerService('SettingsController', function(IAppContainer $c) {
86 86
 			$server = $c->getServer();
87 87
 			return new SettingsController(
88 88
 				$c->getAppName(),
Please login to merge, or discard this patch.
Indentation   +96 added lines, -96 removed lines patch added patch discarded remove patch
@@ -42,101 +42,101 @@
 block discarded – undo
42 42
 
43 43
 class Application extends \OCP\AppFramework\App {
44 44
 
45
-	/**
46
-	 * @param array $urlParams
47
-	 */
48
-	public function __construct($urlParams = array()) {
49
-		parent::__construct('federation', $urlParams);
50
-		$this->registerService();
51
-		$this->registerMiddleware();
52
-	}
53
-
54
-	private function registerService() {
55
-		$container = $this->getContainer();
56
-
57
-		$container->registerService('addServerMiddleware', function(IAppContainer $c) {
58
-			return new AddServerMiddleware(
59
-				$c->getAppName(),
60
-				\OC::$server->getL10N($c->getAppName()),
61
-				\OC::$server->getLogger()
62
-			);
63
-		});
64
-
65
-		$container->registerService('DbHandler', function(IAppContainer $c) {
66
-			return new DbHandler(
67
-				\OC::$server->getDatabaseConnection(),
68
-				\OC::$server->getL10N($c->getAppName())
69
-			);
70
-		});
71
-
72
-		$container->registerService('TrustedServers', function(IAppContainer $c) {
73
-			$server = $c->getServer();
74
-			return new TrustedServers(
75
-				$c->query('DbHandler'),
76
-				$server->getHTTPClientService(),
77
-				$server->getLogger(),
78
-				$server->getJobList(),
79
-				$server->getSecureRandom(),
80
-				$server->getConfig(),
81
-				$server->getEventDispatcher()
82
-			);
83
-		});
84
-
85
-		$container->registerService('SettingsController', function (IAppContainer $c) {
86
-			$server = $c->getServer();
87
-			return new SettingsController(
88
-				$c->getAppName(),
89
-				$server->getRequest(),
90
-				$server->getL10N($c->getAppName()),
91
-				$c->query('TrustedServers')
92
-			);
93
-		});
94
-
95
-	}
96
-
97
-	private function registerMiddleware() {
98
-		$container = $this->getContainer();
99
-		$container->registerMiddleware('addServerMiddleware');
100
-	}
101
-
102
-	/**
103
-	 * listen to federated_share_added hooks to auto-add new servers to the
104
-	 * list of trusted servers.
105
-	 */
106
-	public function registerHooks() {
107
-
108
-		$container = $this->getContainer();
109
-		$hooksManager = new Hooks($container->query('TrustedServers'));
110
-
111
-		Util::connectHook(
112
-				'OCP\Share',
113
-				'federated_share_added',
114
-				$hooksManager,
115
-				'addServerHook'
116
-		);
117
-
118
-		$dispatcher = $this->getContainer()->getServer()->getEventDispatcher();
119
-		$dispatcher->addListener('OCA\DAV\Connector\Sabre::authInit', function($event) use($container) {
120
-			if ($event instanceof SabrePluginEvent) {
121
-				$authPlugin = $event->getServer()->getPlugin('auth');
122
-				if ($authPlugin instanceof Plugin) {
123
-					$h = new DbHandler($container->getServer()->getDatabaseConnection(),
124
-							$container->getServer()->getL10N('federation')
125
-					);
126
-					$authPlugin->addBackend(new FedAuth($h));
127
-				}
128
-			}
129
-		});
130
-	}
131
-
132
-	/**
133
-	 * @return SyncFederationAddressBooks
134
-	 */
135
-	public function getSyncService() {
136
-		$syncService = \OC::$server->query('CardDAVSyncService');
137
-		$dbHandler = $this->getContainer()->query('DbHandler');
138
-		$discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
139
-		return new SyncFederationAddressBooks($dbHandler, $syncService, $discoveryService);
140
-	}
45
+    /**
46
+     * @param array $urlParams
47
+     */
48
+    public function __construct($urlParams = array()) {
49
+        parent::__construct('federation', $urlParams);
50
+        $this->registerService();
51
+        $this->registerMiddleware();
52
+    }
53
+
54
+    private function registerService() {
55
+        $container = $this->getContainer();
56
+
57
+        $container->registerService('addServerMiddleware', function(IAppContainer $c) {
58
+            return new AddServerMiddleware(
59
+                $c->getAppName(),
60
+                \OC::$server->getL10N($c->getAppName()),
61
+                \OC::$server->getLogger()
62
+            );
63
+        });
64
+
65
+        $container->registerService('DbHandler', function(IAppContainer $c) {
66
+            return new DbHandler(
67
+                \OC::$server->getDatabaseConnection(),
68
+                \OC::$server->getL10N($c->getAppName())
69
+            );
70
+        });
71
+
72
+        $container->registerService('TrustedServers', function(IAppContainer $c) {
73
+            $server = $c->getServer();
74
+            return new TrustedServers(
75
+                $c->query('DbHandler'),
76
+                $server->getHTTPClientService(),
77
+                $server->getLogger(),
78
+                $server->getJobList(),
79
+                $server->getSecureRandom(),
80
+                $server->getConfig(),
81
+                $server->getEventDispatcher()
82
+            );
83
+        });
84
+
85
+        $container->registerService('SettingsController', function (IAppContainer $c) {
86
+            $server = $c->getServer();
87
+            return new SettingsController(
88
+                $c->getAppName(),
89
+                $server->getRequest(),
90
+                $server->getL10N($c->getAppName()),
91
+                $c->query('TrustedServers')
92
+            );
93
+        });
94
+
95
+    }
96
+
97
+    private function registerMiddleware() {
98
+        $container = $this->getContainer();
99
+        $container->registerMiddleware('addServerMiddleware');
100
+    }
101
+
102
+    /**
103
+     * listen to federated_share_added hooks to auto-add new servers to the
104
+     * list of trusted servers.
105
+     */
106
+    public function registerHooks() {
107
+
108
+        $container = $this->getContainer();
109
+        $hooksManager = new Hooks($container->query('TrustedServers'));
110
+
111
+        Util::connectHook(
112
+                'OCP\Share',
113
+                'federated_share_added',
114
+                $hooksManager,
115
+                'addServerHook'
116
+        );
117
+
118
+        $dispatcher = $this->getContainer()->getServer()->getEventDispatcher();
119
+        $dispatcher->addListener('OCA\DAV\Connector\Sabre::authInit', function($event) use($container) {
120
+            if ($event instanceof SabrePluginEvent) {
121
+                $authPlugin = $event->getServer()->getPlugin('auth');
122
+                if ($authPlugin instanceof Plugin) {
123
+                    $h = new DbHandler($container->getServer()->getDatabaseConnection(),
124
+                            $container->getServer()->getL10N('federation')
125
+                    );
126
+                    $authPlugin->addBackend(new FedAuth($h));
127
+                }
128
+            }
129
+        });
130
+    }
131
+
132
+    /**
133
+     * @return SyncFederationAddressBooks
134
+     */
135
+    public function getSyncService() {
136
+        $syncService = \OC::$server->query('CardDAVSyncService');
137
+        $dbHandler = $this->getContainer()->query('DbHandler');
138
+        $discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
139
+        return new SyncFederationAddressBooks($dbHandler, $syncService, $discoveryService);
140
+    }
141 141
 
142 142
 }
Please login to merge, or discard this patch.
lib/private/AppFramework/OCS/BaseResponse.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -24,7 +24,7 @@
 block discarded – undo
24 24
 	/**
25 25
 	 * BaseResponse constructor.
26 26
 	 *
27
-	 * @param DataResponse|null $dataResponse
27
+	 * @param DataResponse $dataResponse
28 28
 	 * @param string $format
29 29
 	 * @param string|null $statusMessage
30 30
 	 * @param int|null $itemsCount
Please login to merge, or discard this patch.
Indentation   +56 added lines, -56 removed lines patch added patch discarded remove patch
@@ -27,70 +27,70 @@
 block discarded – undo
27 27
 use OCP\AppFramework\Http\Response;
28 28
 
29 29
 abstract class BaseResponse extends Response   {
30
-	/** @var array */
31
-	protected $data;
30
+    /** @var array */
31
+    protected $data;
32 32
 
33
-	/** @var string */
34
-	protected $format;
33
+    /** @var string */
34
+    protected $format;
35 35
 
36
-	/** @var string */
37
-	protected $statusMessage;
36
+    /** @var string */
37
+    protected $statusMessage;
38 38
 
39
-	/** @var int */
40
-	protected $itemsCount;
39
+    /** @var int */
40
+    protected $itemsCount;
41 41
 
42
-	/** @var int */
43
-	protected $itemsPerPage;
42
+    /** @var int */
43
+    protected $itemsPerPage;
44 44
 
45
-	/**
46
-	 * BaseResponse constructor.
47
-	 *
48
-	 * @param DataResponse|null $dataResponse
49
-	 * @param string $format
50
-	 * @param string|null $statusMessage
51
-	 * @param int|null $itemsCount
52
-	 * @param int|null $itemsPerPage
53
-	 */
54
-	public function __construct(DataResponse $dataResponse,
55
-								$format = 'xml',
56
-								$statusMessage = null,
57
-								$itemsCount = null,
58
-								$itemsPerPage = null) {
59
-		$this->format = $format;
60
-		$this->statusMessage = $statusMessage;
61
-		$this->itemsCount = $itemsCount;
62
-		$this->itemsPerPage = $itemsPerPage;
45
+    /**
46
+     * BaseResponse constructor.
47
+     *
48
+     * @param DataResponse|null $dataResponse
49
+     * @param string $format
50
+     * @param string|null $statusMessage
51
+     * @param int|null $itemsCount
52
+     * @param int|null $itemsPerPage
53
+     */
54
+    public function __construct(DataResponse $dataResponse,
55
+                                $format = 'xml',
56
+                                $statusMessage = null,
57
+                                $itemsCount = null,
58
+                                $itemsPerPage = null) {
59
+        $this->format = $format;
60
+        $this->statusMessage = $statusMessage;
61
+        $this->itemsCount = $itemsCount;
62
+        $this->itemsPerPage = $itemsPerPage;
63 63
 
64
-		$this->data = $dataResponse->getData();
64
+        $this->data = $dataResponse->getData();
65 65
 
66
-		$this->setHeaders($dataResponse->getHeaders());
67
-		$this->setStatus($dataResponse->getStatus());
68
-		$this->setETag($dataResponse->getETag());
69
-		$this->setLastModified($dataResponse->getLastModified());
70
-		$this->setCookies($dataResponse->getCookies());
71
-		$this->setContentSecurityPolicy(new EmptyContentSecurityPolicy());
66
+        $this->setHeaders($dataResponse->getHeaders());
67
+        $this->setStatus($dataResponse->getStatus());
68
+        $this->setETag($dataResponse->getETag());
69
+        $this->setLastModified($dataResponse->getLastModified());
70
+        $this->setCookies($dataResponse->getCookies());
71
+        $this->setContentSecurityPolicy(new EmptyContentSecurityPolicy());
72 72
 
73
-		if ($format === 'json') {
74
-			$this->addHeader(
75
-				'Content-Type', 'application/json; charset=utf-8'
76
-			);
77
-		} else {
78
-			$this->addHeader(
79
-				'Content-Type', 'application/xml; charset=utf-8'
80
-			);
81
-		}
82
-	}
73
+        if ($format === 'json') {
74
+            $this->addHeader(
75
+                'Content-Type', 'application/json; charset=utf-8'
76
+            );
77
+        } else {
78
+            $this->addHeader(
79
+                'Content-Type', 'application/xml; charset=utf-8'
80
+            );
81
+        }
82
+    }
83 83
 
84
-	/**
85
-	 * @param string[] $meta
86
-	 * @return string
87
-	 */
88
-	protected function renderResult($meta) {
89
-		// TODO rewrite functions
90
-		return \OC_API::renderResult($this->format, $meta, $this->data);
91
-	}
84
+    /**
85
+     * @param string[] $meta
86
+     * @return string
87
+     */
88
+    protected function renderResult($meta) {
89
+        // TODO rewrite functions
90
+        return \OC_API::renderResult($this->format, $meta, $this->data);
91
+    }
92 92
 
93
-	public function getOCSStatus() {
94
-		return parent::getStatus();
95
-	}
93
+    public function getOCSStatus() {
94
+        return parent::getStatus();
95
+    }
96 96
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -26,7 +26,7 @@
 block discarded – undo
26 26
 use OCP\AppFramework\Http\EmptyContentSecurityPolicy;
27 27
 use OCP\AppFramework\Http\Response;
28 28
 
29
-abstract class BaseResponse extends Response   {
29
+abstract class BaseResponse extends Response {
30 30
 	/** @var array */
31 31
 	protected $data;
32 32
 
Please login to merge, or discard this patch.