Completed
Push — master ( 5ca5eb...afb5d4 )
by Lukas
16:52
created
apps/provisioning_api/lib/Controller/UsersController.php 1 patch
Indentation   +773 added lines, -773 removed lines patch added patch discarded remove patch
@@ -51,777 +51,777 @@
 block discarded – undo
51 51
 
52 52
 class UsersController extends OCSController {
53 53
 
54
-	/** @var IUserManager */
55
-	private $userManager;
56
-	/** @var IConfig */
57
-	private $config;
58
-	/** @var IGroupManager|\OC\Group\Manager */ // FIXME Requires a method that is not on the interface
59
-	private $groupManager;
60
-	/** @var IUserSession */
61
-	private $userSession;
62
-	/** @var AccountManager */
63
-	private $accountManager;
64
-	/** @var ILogger */
65
-	private $logger;
66
-	/** @var string */
67
-	private $fromMailAddress;
68
-	/** @var IURLGenerator */
69
-	private $urlGenerator;
70
-	/** @var IMailer */
71
-	private $mailer;
72
-	/** @var Defaults */
73
-	private $defaults;
74
-	/** @var IFactory */
75
-	private $l10nFactory;
76
-	/** @var NewUserMailHelper */
77
-	private $newUserMailHelper;
78
-
79
-	/**
80
-	 * @param string $appName
81
-	 * @param IRequest $request
82
-	 * @param IUserManager $userManager
83
-	 * @param IConfig $config
84
-	 * @param IGroupManager $groupManager
85
-	 * @param IUserSession $userSession
86
-	 * @param AccountManager $accountManager
87
-	 * @param ILogger $logger
88
-	 * @param string $fromMailAddress
89
-	 * @param IURLGenerator $urlGenerator
90
-	 * @param IMailer $mailer
91
-	 * @param Defaults $defaults
92
-	 * @param IFactory $l10nFactory
93
-	 * @param NewUserMailHelper $newUserMailHelper
94
-	 */
95
-	public function __construct($appName,
96
-								IRequest $request,
97
-								IUserManager $userManager,
98
-								IConfig $config,
99
-								IGroupManager $groupManager,
100
-								IUserSession $userSession,
101
-								AccountManager $accountManager,
102
-								ILogger $logger,
103
-								$fromMailAddress,
104
-								IURLGenerator $urlGenerator,
105
-								IMailer $mailer,
106
-								Defaults $defaults,
107
-								IFactory $l10nFactory,
108
-								NewUserMailHelper $newUserMailHelper) {
109
-		parent::__construct($appName, $request);
110
-
111
-		$this->userManager = $userManager;
112
-		$this->config = $config;
113
-		$this->groupManager = $groupManager;
114
-		$this->userSession = $userSession;
115
-		$this->accountManager = $accountManager;
116
-		$this->logger = $logger;
117
-		$this->fromMailAddress = $fromMailAddress;
118
-		$this->urlGenerator = $urlGenerator;
119
-		$this->mailer = $mailer;
120
-		$this->defaults = $defaults;
121
-		$this->l10nFactory = $l10nFactory;
122
-		$this->newUserMailHelper = $newUserMailHelper;
123
-	}
124
-
125
-	/**
126
-	 * @NoAdminRequired
127
-	 *
128
-	 * returns a list of users
129
-	 *
130
-	 * @param string $search
131
-	 * @param int $limit
132
-	 * @param int $offset
133
-	 * @return DataResponse
134
-	 */
135
-	public function getUsers($search = '', $limit = null, $offset = null) {
136
-		$user = $this->userSession->getUser();
137
-		$users = [];
138
-
139
-		// Admin? Or SubAdmin?
140
-		$uid = $user->getUID();
141
-		$subAdminManager = $this->groupManager->getSubAdmin();
142
-		if($this->groupManager->isAdmin($uid)){
143
-			$users = $this->userManager->search($search, $limit, $offset);
144
-		} else if ($subAdminManager->isSubAdmin($user)) {
145
-			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
146
-			foreach ($subAdminOfGroups as $key => $group) {
147
-				$subAdminOfGroups[$key] = $group->getGID();
148
-			}
149
-
150
-			if($offset === null) {
151
-				$offset = 0;
152
-			}
153
-
154
-			$users = [];
155
-			foreach ($subAdminOfGroups as $group) {
156
-				$users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search));
157
-			}
158
-
159
-			$users = array_slice($users, $offset, $limit);
160
-		}
161
-
162
-		$users = array_keys($users);
163
-
164
-		return new DataResponse([
165
-			'users' => $users
166
-		]);
167
-	}
168
-
169
-	/**
170
-	 * @PasswordConfirmationRequired
171
-	 * @NoAdminRequired
172
-	 *
173
-	 * @param string $userid
174
-	 * @param string $password
175
-	 * @param array $groups
176
-	 * @return DataResponse
177
-	 * @throws OCSException
178
-	 */
179
-	public function addUser($userid, $password, $groups = null) {
180
-		$user = $this->userSession->getUser();
181
-		$isAdmin = $this->groupManager->isAdmin($user->getUID());
182
-		$subAdminManager = $this->groupManager->getSubAdmin();
183
-
184
-		if($this->userManager->userExists($userid)) {
185
-			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
186
-			throw new OCSException('User already exists', 102);
187
-		}
188
-
189
-		if(is_array($groups)) {
190
-			foreach ($groups as $group) {
191
-				if(!$this->groupManager->groupExists($group)) {
192
-					throw new OCSException('group '.$group.' does not exist', 104);
193
-				}
194
-				if(!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) {
195
-					throw new OCSException('insufficient privileges for group '. $group, 105);
196
-				}
197
-			}
198
-		} else {
199
-			if(!$isAdmin) {
200
-				throw new OCSException('no group specified (required for subadmins)', 106);
201
-			}
202
-		}
203
-
204
-		try {
205
-			$newUser = $this->userManager->createUser($userid, $password);
206
-			$this->logger->info('Successful addUser call with userid: '.$userid, ['app' => 'ocs_api']);
207
-
208
-			if (is_array($groups)) {
209
-				foreach ($groups as $group) {
210
-					$this->groupManager->get($group)->addUser($newUser);
211
-					$this->logger->info('Added userid '.$userid.' to group '.$group, ['app' => 'ocs_api']);
212
-				}
213
-			}
214
-			return new DataResponse();
215
-		} catch (\Exception $e) {
216
-			$this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
217
-			throw new OCSException('Bad request', 101);
218
-		}
219
-	}
220
-
221
-	/**
222
-	 * @NoAdminRequired
223
-	 * @NoSubAdminRequired
224
-	 *
225
-	 * gets user info
226
-	 *
227
-	 * @param string $userId
228
-	 * @return DataResponse
229
-	 * @throws OCSException
230
-	 */
231
-	public function getUser($userId) {
232
-		$data = $this->getUserData($userId);
233
-		return new DataResponse($data);
234
-	}
235
-
236
-	/**
237
-	 * @NoAdminRequired
238
-	 * @NoSubAdminRequired
239
-	 *
240
-	 * gets user info from the currently logged in user
241
-	 *
242
-	 * @return DataResponse
243
-	 * @throws OCSException
244
-	 */
245
-	public function getCurrentUser() {
246
-		$user = $this->userSession->getUser();
247
-		if ($user) {
248
-			$data =  $this->getUserData($user->getUID());
249
-			// rename "displayname" to "display-name" only for this call to keep
250
-			// the API stable.
251
-			$data['display-name'] = $data['displayname'];
252
-			unset($data['displayname']);
253
-			return new DataResponse($data);
254
-
255
-		}
256
-
257
-		throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
258
-	}
259
-
260
-	/**
261
-	 * creates a array with all user data
262
-	 *
263
-	 * @param $userId
264
-	 * @return array
265
-	 * @throws OCSException
266
-	 */
267
-	protected function getUserData($userId) {
268
-		$currentLoggedInUser = $this->userSession->getUser();
269
-
270
-		$data = [];
271
-
272
-		// Check if the target user exists
273
-		$targetUserObject = $this->userManager->get($userId);
274
-		if($targetUserObject === null) {
275
-			throw new OCSException('The requested user could not be found', \OCP\API::RESPOND_NOT_FOUND);
276
-		}
277
-
278
-		// Admin? Or SubAdmin?
279
-		if($this->groupManager->isAdmin($currentLoggedInUser->getUID())
280
-			|| $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) {
281
-			$data['enabled'] = $this->config->getUserValue($userId, 'core', 'enabled', 'true');
282
-		} else {
283
-			// Check they are looking up themselves
284
-			if($currentLoggedInUser->getUID() !== $userId) {
285
-				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
286
-			}
287
-		}
288
-
289
-		$userAccount = $this->accountManager->getUser($targetUserObject);
290
-		$groups = $this->groupManager->getUserGroups($targetUserObject);
291
-		$gids = [];
292
-		foreach ($groups as $group) {
293
-			$gids[] = $group->getDisplayName();
294
-		}
295
-
296
-		// Find the data
297
-		$data['id'] = $targetUserObject->getUID();
298
-		$data['quota'] = $this->fillStorageInfo($userId);
299
-		$data[AccountManager::PROPERTY_EMAIL] = $targetUserObject->getEMailAddress();
300
-		$data[AccountManager::PROPERTY_DISPLAYNAME] = $targetUserObject->getDisplayName();
301
-		$data[AccountManager::PROPERTY_PHONE] = $userAccount[AccountManager::PROPERTY_PHONE]['value'];
302
-		$data[AccountManager::PROPERTY_ADDRESS] = $userAccount[AccountManager::PROPERTY_ADDRESS]['value'];
303
-		$data[AccountManager::PROPERTY_WEBSITE] = $userAccount[AccountManager::PROPERTY_WEBSITE]['value'];
304
-		$data[AccountManager::PROPERTY_TWITTER] = $userAccount[AccountManager::PROPERTY_TWITTER]['value'];
305
-		$data['groups'] = $gids;
306
-
307
-		return $data;
308
-	}
309
-
310
-	/**
311
-	 * @NoAdminRequired
312
-	 * @NoSubAdminRequired
313
-	 * @PasswordConfirmationRequired
314
-	 *
315
-	 * edit users
316
-	 *
317
-	 * @param string $userId
318
-	 * @param string $key
319
-	 * @param string $value
320
-	 * @return DataResponse
321
-	 * @throws OCSException
322
-	 * @throws OCSForbiddenException
323
-	 */
324
-	public function editUser($userId, $key, $value) {
325
-		$currentLoggedInUser = $this->userSession->getUser();
326
-
327
-		$targetUser = $this->userManager->get($userId);
328
-		if($targetUser === null) {
329
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
330
-		}
331
-
332
-		$permittedFields = [];
333
-		if($userId === $currentLoggedInUser->getUID()) {
334
-			// Editing self (display, email)
335
-			$permittedFields[] = 'display';
336
-			$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
337
-			$permittedFields[] = AccountManager::PROPERTY_EMAIL;
338
-			$permittedFields[] = 'password';
339
-			$permittedFields[] = AccountManager::PROPERTY_PHONE;
340
-			$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
341
-			$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
342
-			$permittedFields[] = AccountManager::PROPERTY_TWITTER;
343
-			// If admin they can edit their own quota
344
-			if($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
345
-				$permittedFields[] = 'quota';
346
-			}
347
-		} else {
348
-			// Check if admin / subadmin
349
-			$subAdminManager = $this->groupManager->getSubAdmin();
350
-			if($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
351
-			|| $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
352
-				// They have permissions over the user
353
-				$permittedFields[] = 'display';
354
-				$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
355
-				$permittedFields[] = AccountManager::PROPERTY_EMAIL;
356
-				$permittedFields[] = 'password';
357
-				$permittedFields[] = AccountManager::PROPERTY_PHONE;
358
-				$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
359
-				$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
360
-				$permittedFields[] = AccountManager::PROPERTY_TWITTER;
361
-				$permittedFields[] = 'quota';
362
-			} else {
363
-				// No rights
364
-				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
365
-			}
366
-		}
367
-		// Check if permitted to edit this field
368
-		if(!in_array($key, $permittedFields)) {
369
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
370
-		}
371
-		// Process the edit
372
-		switch($key) {
373
-			case 'display':
374
-			case AccountManager::PROPERTY_DISPLAYNAME:
375
-				$targetUser->setDisplayName($value);
376
-				break;
377
-			case 'quota':
378
-				$quota = $value;
379
-				if($quota !== 'none' && $quota !== 'default') {
380
-					if (is_numeric($quota)) {
381
-						$quota = (float) $quota;
382
-					} else {
383
-						$quota = \OCP\Util::computerFileSize($quota);
384
-					}
385
-					if ($quota === false) {
386
-						throw new OCSException('Invalid quota value '.$value, 103);
387
-					}
388
-					if($quota === 0) {
389
-						$quota = 'default';
390
-					}else if($quota === -1) {
391
-						$quota = 'none';
392
-					} else {
393
-						$quota = \OCP\Util::humanFileSize($quota);
394
-					}
395
-				}
396
-				$targetUser->setQuota($quota);
397
-				break;
398
-			case 'password':
399
-				$targetUser->setPassword($value);
400
-				break;
401
-			case AccountManager::PROPERTY_EMAIL:
402
-				if(filter_var($value, FILTER_VALIDATE_EMAIL)) {
403
-					$targetUser->setEMailAddress($value);
404
-				} else {
405
-					throw new OCSException('', 102);
406
-				}
407
-				break;
408
-			case AccountManager::PROPERTY_PHONE:
409
-			case AccountManager::PROPERTY_ADDRESS:
410
-			case AccountManager::PROPERTY_WEBSITE:
411
-			case AccountManager::PROPERTY_TWITTER:
412
-				$userAccount = $this->accountManager->getUser($targetUser);
413
-				if ($userAccount[$key]['value'] !== $value) {
414
-					$userAccount[$key]['value'] = $value;
415
-					$this->accountManager->updateUser($targetUser, $userAccount);
416
-				}
417
-				break;
418
-			default:
419
-				throw new OCSException('', 103);
420
-		}
421
-		return new DataResponse();
422
-	}
423
-
424
-	/**
425
-	 * @PasswordConfirmationRequired
426
-	 * @NoAdminRequired
427
-	 *
428
-	 * @param string $userId
429
-	 * @return DataResponse
430
-	 * @throws OCSException
431
-	 * @throws OCSForbiddenException
432
-	 */
433
-	public function deleteUser($userId) {
434
-		$currentLoggedInUser = $this->userSession->getUser();
435
-
436
-		$targetUser = $this->userManager->get($userId);
437
-
438
-		if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
439
-			throw new OCSException('', 101);
440
-		}
441
-
442
-		// If not permitted
443
-		$subAdminManager = $this->groupManager->getSubAdmin();
444
-		if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
445
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
446
-		}
447
-
448
-		// Go ahead with the delete
449
-		if($targetUser->delete()) {
450
-			return new DataResponse();
451
-		} else {
452
-			throw new OCSException('', 101);
453
-		}
454
-	}
455
-
456
-	/**
457
-	 * @PasswordConfirmationRequired
458
-	 * @NoAdminRequired
459
-	 *
460
-	 * @param string $userId
461
-	 * @return DataResponse
462
-	 * @throws OCSException
463
-	 * @throws OCSForbiddenException
464
-	 */
465
-	public function disableUser($userId) {
466
-		return $this->setEnabled($userId, false);
467
-	}
468
-
469
-	/**
470
-	 * @PasswordConfirmationRequired
471
-	 * @NoAdminRequired
472
-	 *
473
-	 * @param string $userId
474
-	 * @return DataResponse
475
-	 * @throws OCSException
476
-	 * @throws OCSForbiddenException
477
-	 */
478
-	public function enableUser($userId) {
479
-		return $this->setEnabled($userId, true);
480
-	}
481
-
482
-	/**
483
-	 * @param string $userId
484
-	 * @param bool $value
485
-	 * @return DataResponse
486
-	 * @throws OCSException
487
-	 * @throws OCSForbiddenException
488
-	 */
489
-	private function setEnabled($userId, $value) {
490
-		$currentLoggedInUser = $this->userSession->getUser();
491
-
492
-		$targetUser = $this->userManager->get($userId);
493
-		if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
494
-			throw new OCSException('', 101);
495
-		}
496
-
497
-		// If not permitted
498
-		$subAdminManager = $this->groupManager->getSubAdmin();
499
-		if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
500
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
501
-		}
502
-
503
-		// enable/disable the user now
504
-		$targetUser->setEnabled($value);
505
-		return new DataResponse();
506
-	}
507
-
508
-	/**
509
-	 * @NoAdminRequired
510
-	 * @NoSubAdminRequired
511
-	 *
512
-	 * @param string $userId
513
-	 * @return DataResponse
514
-	 * @throws OCSException
515
-	 */
516
-	public function getUsersGroups($userId) {
517
-		$loggedInUser = $this->userSession->getUser();
518
-
519
-		$targetUser = $this->userManager->get($userId);
520
-		if($targetUser === null) {
521
-			throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
522
-		}
523
-
524
-		if($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
525
-			// Self lookup or admin lookup
526
-			return new DataResponse([
527
-				'groups' => $this->groupManager->getUserGroupIds($targetUser)
528
-			]);
529
-		} else {
530
-			$subAdminManager = $this->groupManager->getSubAdmin();
531
-
532
-			// Looking up someone else
533
-			if($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
534
-				// Return the group that the method caller is subadmin of for the user in question
535
-				/** @var IGroup[] $getSubAdminsGroups */
536
-				$getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
537
-				foreach ($getSubAdminsGroups as $key => $group) {
538
-					$getSubAdminsGroups[$key] = $group->getGID();
539
-				}
540
-				$groups = array_intersect(
541
-					$getSubAdminsGroups,
542
-					$this->groupManager->getUserGroupIds($targetUser)
543
-				);
544
-				return new DataResponse(['groups' => $groups]);
545
-			} else {
546
-				// Not permitted
547
-				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
548
-			}
549
-		}
550
-
551
-	}
552
-
553
-	/**
554
-	 * @PasswordConfirmationRequired
555
-	 * @NoAdminRequired
556
-	 *
557
-	 * @param string $userId
558
-	 * @param string $groupid
559
-	 * @return DataResponse
560
-	 * @throws OCSException
561
-	 */
562
-	public function addToGroup($userId, $groupid = '') {
563
-		if($groupid === '') {
564
-			throw new OCSException('', 101);
565
-		}
566
-
567
-		$group = $this->groupManager->get($groupid);
568
-		$targetUser = $this->userManager->get($userId);
569
-		if($group === null) {
570
-			throw new OCSException('', 102);
571
-		}
572
-		if($targetUser === null) {
573
-			throw new OCSException('', 103);
574
-		}
575
-
576
-		// If they're not an admin, check they are a subadmin of the group in question
577
-		$loggedInUser = $this->userSession->getUser();
578
-		$subAdminManager = $this->groupManager->getSubAdmin();
579
-		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
580
-			throw new OCSException('', 104);
581
-		}
582
-
583
-		// Add user to group
584
-		$group->addUser($targetUser);
585
-		return new DataResponse();
586
-	}
587
-
588
-	/**
589
-	 * @PasswordConfirmationRequired
590
-	 * @NoAdminRequired
591
-	 *
592
-	 * @param string $userId
593
-	 * @param string $groupid
594
-	 * @return DataResponse
595
-	 * @throws OCSException
596
-	 */
597
-	public function removeFromGroup($userId, $groupid) {
598
-		$loggedInUser = $this->userSession->getUser();
599
-
600
-		if($groupid === null) {
601
-			throw new OCSException('', 101);
602
-		}
603
-
604
-		$group = $this->groupManager->get($groupid);
605
-		if($group === null) {
606
-			throw new OCSException('', 102);
607
-		}
608
-
609
-		$targetUser = $this->userManager->get($userId);
610
-		if($targetUser === null) {
611
-			throw new OCSException('', 103);
612
-		}
613
-
614
-		// If they're not an admin, check they are a subadmin of the group in question
615
-		$subAdminManager = $this->groupManager->getSubAdmin();
616
-		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
617
-			throw new OCSException('', 104);
618
-		}
619
-
620
-		// Check they aren't removing themselves from 'admin' or their 'subadmin; group
621
-		if ($userId === $loggedInUser->getUID()) {
622
-			if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
623
-				if ($group->getGID() === 'admin') {
624
-					throw new OCSException('Cannot remove yourself from the admin group', 105);
625
-				}
626
-			} else {
627
-				// Not an admin, so the user must be a subadmin of this group, but that is not allowed.
628
-				throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
629
-			}
630
-
631
-		} else if (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
632
-			/** @var IGroup[] $subAdminGroups */
633
-			$subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
634
-			$subAdminGroups = array_map(function (IGroup $subAdminGroup) {
635
-				return $subAdminGroup->getGID();
636
-			}, $subAdminGroups);
637
-			$userGroups = $this->groupManager->getUserGroupIds($targetUser);
638
-			$userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
639
-
640
-			if (count($userSubAdminGroups) <= 1) {
641
-				// Subadmin must not be able to remove a user from all their subadmin groups.
642
-				throw new OCSException('Cannot remove user from this group as this is the only remaining group you are a SubAdmin of', 105);
643
-			}
644
-		}
645
-
646
-		// Remove user from group
647
-		$group->removeUser($targetUser);
648
-		return new DataResponse();
649
-	}
650
-
651
-	/**
652
-	 * Creates a subadmin
653
-	 *
654
-	 * @PasswordConfirmationRequired
655
-	 *
656
-	 * @param string $userId
657
-	 * @param string $groupid
658
-	 * @return DataResponse
659
-	 * @throws OCSException
660
-	 */
661
-	public function addSubAdmin($userId, $groupid) {
662
-		$group = $this->groupManager->get($groupid);
663
-		$user = $this->userManager->get($userId);
664
-
665
-		// Check if the user exists
666
-		if($user === null) {
667
-			throw new OCSException('User does not exist', 101);
668
-		}
669
-		// Check if group exists
670
-		if($group === null) {
671
-			throw new OCSException('Group:'.$groupid.' does not exist',  102);
672
-		}
673
-		// Check if trying to make subadmin of admin group
674
-		if(strtolower($groupid) === 'admin') {
675
-			throw new OCSException('Cannot create subadmins for admin group', 103);
676
-		}
677
-
678
-		$subAdminManager = $this->groupManager->getSubAdmin();
679
-
680
-		// We cannot be subadmin twice
681
-		if ($subAdminManager->isSubAdminofGroup($user, $group)) {
682
-			return new DataResponse();
683
-		}
684
-		// Go
685
-		if($subAdminManager->createSubAdmin($user, $group)) {
686
-			return new DataResponse();
687
-		} else {
688
-			throw new OCSException('Unknown error occurred', 103);
689
-		}
690
-	}
691
-
692
-	/**
693
-	 * Removes a subadmin from a group
694
-	 *
695
-	 * @PasswordConfirmationRequired
696
-	 *
697
-	 * @param string $userId
698
-	 * @param string $groupid
699
-	 * @return DataResponse
700
-	 * @throws OCSException
701
-	 */
702
-	public function removeSubAdmin($userId, $groupid) {
703
-		$group = $this->groupManager->get($groupid);
704
-		$user = $this->userManager->get($userId);
705
-		$subAdminManager = $this->groupManager->getSubAdmin();
706
-
707
-		// Check if the user exists
708
-		if($user === null) {
709
-			throw new OCSException('User does not exist', 101);
710
-		}
711
-		// Check if the group exists
712
-		if($group === null) {
713
-			throw new OCSException('Group does not exist', 101);
714
-		}
715
-		// Check if they are a subadmin of this said group
716
-		if(!$subAdminManager->isSubAdminofGroup($user, $group)) {
717
-			throw new OCSException('User is not a subadmin of this group', 102);
718
-		}
719
-
720
-		// Go
721
-		if($subAdminManager->deleteSubAdmin($user, $group)) {
722
-			return new DataResponse();
723
-		} else {
724
-			throw new OCSException('Unknown error occurred', 103);
725
-		}
726
-	}
727
-
728
-	/**
729
-	 * Get the groups a user is a subadmin of
730
-	 *
731
-	 * @param string $userId
732
-	 * @return DataResponse
733
-	 * @throws OCSException
734
-	 */
735
-	public function getUserSubAdminGroups($userId) {
736
-		$user = $this->userManager->get($userId);
737
-		// Check if the user exists
738
-		if($user === null) {
739
-			throw new OCSException('User does not exist', 101);
740
-		}
741
-
742
-		// Get the subadmin groups
743
-		$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user);
744
-		foreach ($groups as $key => $group) {
745
-			$groups[$key] = $group->getGID();
746
-		}
747
-
748
-		if(!$groups) {
749
-			throw new OCSException('Unknown error occurred', 102);
750
-		} else {
751
-			return new DataResponse($groups);
752
-		}
753
-	}
754
-
755
-	/**
756
-	 * @param string $userId
757
-	 * @return array
758
-	 * @throws \OCP\Files\NotFoundException
759
-	 */
760
-	protected function fillStorageInfo($userId) {
761
-		try {
762
-			\OC_Util::tearDownFS();
763
-			\OC_Util::setupFS($userId);
764
-			$storage = OC_Helper::getStorageInfo('/');
765
-			$data = [
766
-				'free' => $storage['free'],
767
-				'used' => $storage['used'],
768
-				'total' => $storage['total'],
769
-				'relative' => $storage['relative'],
770
-				'quota' => $storage['quota'],
771
-			];
772
-		} catch (NotFoundException $ex) {
773
-			$data = [];
774
-		}
775
-		return $data;
776
-	}
777
-
778
-	/**
779
-	 * @NoAdminRequired
780
-	 * @PasswordConfirmationRequired
781
-	 *
782
-	 * resend welcome message
783
-	 *
784
-	 * @param string $userId
785
-	 * @return DataResponse
786
-	 * @throws OCSException
787
-	 */
788
-	public function resendWelcomeMessage($userId) {
789
-		$currentLoggedInUser = $this->userSession->getUser();
790
-
791
-		$targetUser = $this->userManager->get($userId);
792
-		if($targetUser === null) {
793
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
794
-		}
795
-
796
-		// Check if admin / subadmin
797
-		$subAdminManager = $this->groupManager->getSubAdmin();
798
-		if(!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
799
-			&& !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
800
-			// No rights
801
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
802
-		}
803
-
804
-		$email = $targetUser->getEMailAddress();
805
-		if ($email === '' || $email === null) {
806
-			throw new OCSException('Email address not available', 101);
807
-		}
808
-		$username = $targetUser->getUID();
809
-		$lang = $this->config->getUserValue($username, 'core', 'lang', 'en');
810
-		if (!$this->l10nFactory->languageExists('settings', $lang)) {
811
-			$lang = 'en';
812
-		}
813
-
814
-		$l10n = $this->l10nFactory->get('settings', $lang);
815
-
816
-		try {
817
-			$this->newUserMailHelper->setL10N($l10n);
818
-			$emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
819
-			$this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
820
-		} catch(\Exception $e) {
821
-			$this->logger->error("Can't send new user mail to $email: " . $e->getMessage(), array('app' => 'settings'));
822
-			throw new OCSException('Sending email failed', 102);
823
-		}
824
-
825
-		return new DataResponse();
826
-	}
54
+    /** @var IUserManager */
55
+    private $userManager;
56
+    /** @var IConfig */
57
+    private $config;
58
+    /** @var IGroupManager|\OC\Group\Manager */ // FIXME Requires a method that is not on the interface
59
+    private $groupManager;
60
+    /** @var IUserSession */
61
+    private $userSession;
62
+    /** @var AccountManager */
63
+    private $accountManager;
64
+    /** @var ILogger */
65
+    private $logger;
66
+    /** @var string */
67
+    private $fromMailAddress;
68
+    /** @var IURLGenerator */
69
+    private $urlGenerator;
70
+    /** @var IMailer */
71
+    private $mailer;
72
+    /** @var Defaults */
73
+    private $defaults;
74
+    /** @var IFactory */
75
+    private $l10nFactory;
76
+    /** @var NewUserMailHelper */
77
+    private $newUserMailHelper;
78
+
79
+    /**
80
+     * @param string $appName
81
+     * @param IRequest $request
82
+     * @param IUserManager $userManager
83
+     * @param IConfig $config
84
+     * @param IGroupManager $groupManager
85
+     * @param IUserSession $userSession
86
+     * @param AccountManager $accountManager
87
+     * @param ILogger $logger
88
+     * @param string $fromMailAddress
89
+     * @param IURLGenerator $urlGenerator
90
+     * @param IMailer $mailer
91
+     * @param Defaults $defaults
92
+     * @param IFactory $l10nFactory
93
+     * @param NewUserMailHelper $newUserMailHelper
94
+     */
95
+    public function __construct($appName,
96
+                                IRequest $request,
97
+                                IUserManager $userManager,
98
+                                IConfig $config,
99
+                                IGroupManager $groupManager,
100
+                                IUserSession $userSession,
101
+                                AccountManager $accountManager,
102
+                                ILogger $logger,
103
+                                $fromMailAddress,
104
+                                IURLGenerator $urlGenerator,
105
+                                IMailer $mailer,
106
+                                Defaults $defaults,
107
+                                IFactory $l10nFactory,
108
+                                NewUserMailHelper $newUserMailHelper) {
109
+        parent::__construct($appName, $request);
110
+
111
+        $this->userManager = $userManager;
112
+        $this->config = $config;
113
+        $this->groupManager = $groupManager;
114
+        $this->userSession = $userSession;
115
+        $this->accountManager = $accountManager;
116
+        $this->logger = $logger;
117
+        $this->fromMailAddress = $fromMailAddress;
118
+        $this->urlGenerator = $urlGenerator;
119
+        $this->mailer = $mailer;
120
+        $this->defaults = $defaults;
121
+        $this->l10nFactory = $l10nFactory;
122
+        $this->newUserMailHelper = $newUserMailHelper;
123
+    }
124
+
125
+    /**
126
+     * @NoAdminRequired
127
+     *
128
+     * returns a list of users
129
+     *
130
+     * @param string $search
131
+     * @param int $limit
132
+     * @param int $offset
133
+     * @return DataResponse
134
+     */
135
+    public function getUsers($search = '', $limit = null, $offset = null) {
136
+        $user = $this->userSession->getUser();
137
+        $users = [];
138
+
139
+        // Admin? Or SubAdmin?
140
+        $uid = $user->getUID();
141
+        $subAdminManager = $this->groupManager->getSubAdmin();
142
+        if($this->groupManager->isAdmin($uid)){
143
+            $users = $this->userManager->search($search, $limit, $offset);
144
+        } else if ($subAdminManager->isSubAdmin($user)) {
145
+            $subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
146
+            foreach ($subAdminOfGroups as $key => $group) {
147
+                $subAdminOfGroups[$key] = $group->getGID();
148
+            }
149
+
150
+            if($offset === null) {
151
+                $offset = 0;
152
+            }
153
+
154
+            $users = [];
155
+            foreach ($subAdminOfGroups as $group) {
156
+                $users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search));
157
+            }
158
+
159
+            $users = array_slice($users, $offset, $limit);
160
+        }
161
+
162
+        $users = array_keys($users);
163
+
164
+        return new DataResponse([
165
+            'users' => $users
166
+        ]);
167
+    }
168
+
169
+    /**
170
+     * @PasswordConfirmationRequired
171
+     * @NoAdminRequired
172
+     *
173
+     * @param string $userid
174
+     * @param string $password
175
+     * @param array $groups
176
+     * @return DataResponse
177
+     * @throws OCSException
178
+     */
179
+    public function addUser($userid, $password, $groups = null) {
180
+        $user = $this->userSession->getUser();
181
+        $isAdmin = $this->groupManager->isAdmin($user->getUID());
182
+        $subAdminManager = $this->groupManager->getSubAdmin();
183
+
184
+        if($this->userManager->userExists($userid)) {
185
+            $this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
186
+            throw new OCSException('User already exists', 102);
187
+        }
188
+
189
+        if(is_array($groups)) {
190
+            foreach ($groups as $group) {
191
+                if(!$this->groupManager->groupExists($group)) {
192
+                    throw new OCSException('group '.$group.' does not exist', 104);
193
+                }
194
+                if(!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) {
195
+                    throw new OCSException('insufficient privileges for group '. $group, 105);
196
+                }
197
+            }
198
+        } else {
199
+            if(!$isAdmin) {
200
+                throw new OCSException('no group specified (required for subadmins)', 106);
201
+            }
202
+        }
203
+
204
+        try {
205
+            $newUser = $this->userManager->createUser($userid, $password);
206
+            $this->logger->info('Successful addUser call with userid: '.$userid, ['app' => 'ocs_api']);
207
+
208
+            if (is_array($groups)) {
209
+                foreach ($groups as $group) {
210
+                    $this->groupManager->get($group)->addUser($newUser);
211
+                    $this->logger->info('Added userid '.$userid.' to group '.$group, ['app' => 'ocs_api']);
212
+                }
213
+            }
214
+            return new DataResponse();
215
+        } catch (\Exception $e) {
216
+            $this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
217
+            throw new OCSException('Bad request', 101);
218
+        }
219
+    }
220
+
221
+    /**
222
+     * @NoAdminRequired
223
+     * @NoSubAdminRequired
224
+     *
225
+     * gets user info
226
+     *
227
+     * @param string $userId
228
+     * @return DataResponse
229
+     * @throws OCSException
230
+     */
231
+    public function getUser($userId) {
232
+        $data = $this->getUserData($userId);
233
+        return new DataResponse($data);
234
+    }
235
+
236
+    /**
237
+     * @NoAdminRequired
238
+     * @NoSubAdminRequired
239
+     *
240
+     * gets user info from the currently logged in user
241
+     *
242
+     * @return DataResponse
243
+     * @throws OCSException
244
+     */
245
+    public function getCurrentUser() {
246
+        $user = $this->userSession->getUser();
247
+        if ($user) {
248
+            $data =  $this->getUserData($user->getUID());
249
+            // rename "displayname" to "display-name" only for this call to keep
250
+            // the API stable.
251
+            $data['display-name'] = $data['displayname'];
252
+            unset($data['displayname']);
253
+            return new DataResponse($data);
254
+
255
+        }
256
+
257
+        throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
258
+    }
259
+
260
+    /**
261
+     * creates a array with all user data
262
+     *
263
+     * @param $userId
264
+     * @return array
265
+     * @throws OCSException
266
+     */
267
+    protected function getUserData($userId) {
268
+        $currentLoggedInUser = $this->userSession->getUser();
269
+
270
+        $data = [];
271
+
272
+        // Check if the target user exists
273
+        $targetUserObject = $this->userManager->get($userId);
274
+        if($targetUserObject === null) {
275
+            throw new OCSException('The requested user could not be found', \OCP\API::RESPOND_NOT_FOUND);
276
+        }
277
+
278
+        // Admin? Or SubAdmin?
279
+        if($this->groupManager->isAdmin($currentLoggedInUser->getUID())
280
+            || $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) {
281
+            $data['enabled'] = $this->config->getUserValue($userId, 'core', 'enabled', 'true');
282
+        } else {
283
+            // Check they are looking up themselves
284
+            if($currentLoggedInUser->getUID() !== $userId) {
285
+                throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
286
+            }
287
+        }
288
+
289
+        $userAccount = $this->accountManager->getUser($targetUserObject);
290
+        $groups = $this->groupManager->getUserGroups($targetUserObject);
291
+        $gids = [];
292
+        foreach ($groups as $group) {
293
+            $gids[] = $group->getDisplayName();
294
+        }
295
+
296
+        // Find the data
297
+        $data['id'] = $targetUserObject->getUID();
298
+        $data['quota'] = $this->fillStorageInfo($userId);
299
+        $data[AccountManager::PROPERTY_EMAIL] = $targetUserObject->getEMailAddress();
300
+        $data[AccountManager::PROPERTY_DISPLAYNAME] = $targetUserObject->getDisplayName();
301
+        $data[AccountManager::PROPERTY_PHONE] = $userAccount[AccountManager::PROPERTY_PHONE]['value'];
302
+        $data[AccountManager::PROPERTY_ADDRESS] = $userAccount[AccountManager::PROPERTY_ADDRESS]['value'];
303
+        $data[AccountManager::PROPERTY_WEBSITE] = $userAccount[AccountManager::PROPERTY_WEBSITE]['value'];
304
+        $data[AccountManager::PROPERTY_TWITTER] = $userAccount[AccountManager::PROPERTY_TWITTER]['value'];
305
+        $data['groups'] = $gids;
306
+
307
+        return $data;
308
+    }
309
+
310
+    /**
311
+     * @NoAdminRequired
312
+     * @NoSubAdminRequired
313
+     * @PasswordConfirmationRequired
314
+     *
315
+     * edit users
316
+     *
317
+     * @param string $userId
318
+     * @param string $key
319
+     * @param string $value
320
+     * @return DataResponse
321
+     * @throws OCSException
322
+     * @throws OCSForbiddenException
323
+     */
324
+    public function editUser($userId, $key, $value) {
325
+        $currentLoggedInUser = $this->userSession->getUser();
326
+
327
+        $targetUser = $this->userManager->get($userId);
328
+        if($targetUser === null) {
329
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
330
+        }
331
+
332
+        $permittedFields = [];
333
+        if($userId === $currentLoggedInUser->getUID()) {
334
+            // Editing self (display, email)
335
+            $permittedFields[] = 'display';
336
+            $permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
337
+            $permittedFields[] = AccountManager::PROPERTY_EMAIL;
338
+            $permittedFields[] = 'password';
339
+            $permittedFields[] = AccountManager::PROPERTY_PHONE;
340
+            $permittedFields[] = AccountManager::PROPERTY_ADDRESS;
341
+            $permittedFields[] = AccountManager::PROPERTY_WEBSITE;
342
+            $permittedFields[] = AccountManager::PROPERTY_TWITTER;
343
+            // If admin they can edit their own quota
344
+            if($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
345
+                $permittedFields[] = 'quota';
346
+            }
347
+        } else {
348
+            // Check if admin / subadmin
349
+            $subAdminManager = $this->groupManager->getSubAdmin();
350
+            if($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
351
+            || $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
352
+                // They have permissions over the user
353
+                $permittedFields[] = 'display';
354
+                $permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
355
+                $permittedFields[] = AccountManager::PROPERTY_EMAIL;
356
+                $permittedFields[] = 'password';
357
+                $permittedFields[] = AccountManager::PROPERTY_PHONE;
358
+                $permittedFields[] = AccountManager::PROPERTY_ADDRESS;
359
+                $permittedFields[] = AccountManager::PROPERTY_WEBSITE;
360
+                $permittedFields[] = AccountManager::PROPERTY_TWITTER;
361
+                $permittedFields[] = 'quota';
362
+            } else {
363
+                // No rights
364
+                throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
365
+            }
366
+        }
367
+        // Check if permitted to edit this field
368
+        if(!in_array($key, $permittedFields)) {
369
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
370
+        }
371
+        // Process the edit
372
+        switch($key) {
373
+            case 'display':
374
+            case AccountManager::PROPERTY_DISPLAYNAME:
375
+                $targetUser->setDisplayName($value);
376
+                break;
377
+            case 'quota':
378
+                $quota = $value;
379
+                if($quota !== 'none' && $quota !== 'default') {
380
+                    if (is_numeric($quota)) {
381
+                        $quota = (float) $quota;
382
+                    } else {
383
+                        $quota = \OCP\Util::computerFileSize($quota);
384
+                    }
385
+                    if ($quota === false) {
386
+                        throw new OCSException('Invalid quota value '.$value, 103);
387
+                    }
388
+                    if($quota === 0) {
389
+                        $quota = 'default';
390
+                    }else if($quota === -1) {
391
+                        $quota = 'none';
392
+                    } else {
393
+                        $quota = \OCP\Util::humanFileSize($quota);
394
+                    }
395
+                }
396
+                $targetUser->setQuota($quota);
397
+                break;
398
+            case 'password':
399
+                $targetUser->setPassword($value);
400
+                break;
401
+            case AccountManager::PROPERTY_EMAIL:
402
+                if(filter_var($value, FILTER_VALIDATE_EMAIL)) {
403
+                    $targetUser->setEMailAddress($value);
404
+                } else {
405
+                    throw new OCSException('', 102);
406
+                }
407
+                break;
408
+            case AccountManager::PROPERTY_PHONE:
409
+            case AccountManager::PROPERTY_ADDRESS:
410
+            case AccountManager::PROPERTY_WEBSITE:
411
+            case AccountManager::PROPERTY_TWITTER:
412
+                $userAccount = $this->accountManager->getUser($targetUser);
413
+                if ($userAccount[$key]['value'] !== $value) {
414
+                    $userAccount[$key]['value'] = $value;
415
+                    $this->accountManager->updateUser($targetUser, $userAccount);
416
+                }
417
+                break;
418
+            default:
419
+                throw new OCSException('', 103);
420
+        }
421
+        return new DataResponse();
422
+    }
423
+
424
+    /**
425
+     * @PasswordConfirmationRequired
426
+     * @NoAdminRequired
427
+     *
428
+     * @param string $userId
429
+     * @return DataResponse
430
+     * @throws OCSException
431
+     * @throws OCSForbiddenException
432
+     */
433
+    public function deleteUser($userId) {
434
+        $currentLoggedInUser = $this->userSession->getUser();
435
+
436
+        $targetUser = $this->userManager->get($userId);
437
+
438
+        if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
439
+            throw new OCSException('', 101);
440
+        }
441
+
442
+        // If not permitted
443
+        $subAdminManager = $this->groupManager->getSubAdmin();
444
+        if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
445
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
446
+        }
447
+
448
+        // Go ahead with the delete
449
+        if($targetUser->delete()) {
450
+            return new DataResponse();
451
+        } else {
452
+            throw new OCSException('', 101);
453
+        }
454
+    }
455
+
456
+    /**
457
+     * @PasswordConfirmationRequired
458
+     * @NoAdminRequired
459
+     *
460
+     * @param string $userId
461
+     * @return DataResponse
462
+     * @throws OCSException
463
+     * @throws OCSForbiddenException
464
+     */
465
+    public function disableUser($userId) {
466
+        return $this->setEnabled($userId, false);
467
+    }
468
+
469
+    /**
470
+     * @PasswordConfirmationRequired
471
+     * @NoAdminRequired
472
+     *
473
+     * @param string $userId
474
+     * @return DataResponse
475
+     * @throws OCSException
476
+     * @throws OCSForbiddenException
477
+     */
478
+    public function enableUser($userId) {
479
+        return $this->setEnabled($userId, true);
480
+    }
481
+
482
+    /**
483
+     * @param string $userId
484
+     * @param bool $value
485
+     * @return DataResponse
486
+     * @throws OCSException
487
+     * @throws OCSForbiddenException
488
+     */
489
+    private function setEnabled($userId, $value) {
490
+        $currentLoggedInUser = $this->userSession->getUser();
491
+
492
+        $targetUser = $this->userManager->get($userId);
493
+        if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
494
+            throw new OCSException('', 101);
495
+        }
496
+
497
+        // If not permitted
498
+        $subAdminManager = $this->groupManager->getSubAdmin();
499
+        if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
500
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
501
+        }
502
+
503
+        // enable/disable the user now
504
+        $targetUser->setEnabled($value);
505
+        return new DataResponse();
506
+    }
507
+
508
+    /**
509
+     * @NoAdminRequired
510
+     * @NoSubAdminRequired
511
+     *
512
+     * @param string $userId
513
+     * @return DataResponse
514
+     * @throws OCSException
515
+     */
516
+    public function getUsersGroups($userId) {
517
+        $loggedInUser = $this->userSession->getUser();
518
+
519
+        $targetUser = $this->userManager->get($userId);
520
+        if($targetUser === null) {
521
+            throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
522
+        }
523
+
524
+        if($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
525
+            // Self lookup or admin lookup
526
+            return new DataResponse([
527
+                'groups' => $this->groupManager->getUserGroupIds($targetUser)
528
+            ]);
529
+        } else {
530
+            $subAdminManager = $this->groupManager->getSubAdmin();
531
+
532
+            // Looking up someone else
533
+            if($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
534
+                // Return the group that the method caller is subadmin of for the user in question
535
+                /** @var IGroup[] $getSubAdminsGroups */
536
+                $getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
537
+                foreach ($getSubAdminsGroups as $key => $group) {
538
+                    $getSubAdminsGroups[$key] = $group->getGID();
539
+                }
540
+                $groups = array_intersect(
541
+                    $getSubAdminsGroups,
542
+                    $this->groupManager->getUserGroupIds($targetUser)
543
+                );
544
+                return new DataResponse(['groups' => $groups]);
545
+            } else {
546
+                // Not permitted
547
+                throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
548
+            }
549
+        }
550
+
551
+    }
552
+
553
+    /**
554
+     * @PasswordConfirmationRequired
555
+     * @NoAdminRequired
556
+     *
557
+     * @param string $userId
558
+     * @param string $groupid
559
+     * @return DataResponse
560
+     * @throws OCSException
561
+     */
562
+    public function addToGroup($userId, $groupid = '') {
563
+        if($groupid === '') {
564
+            throw new OCSException('', 101);
565
+        }
566
+
567
+        $group = $this->groupManager->get($groupid);
568
+        $targetUser = $this->userManager->get($userId);
569
+        if($group === null) {
570
+            throw new OCSException('', 102);
571
+        }
572
+        if($targetUser === null) {
573
+            throw new OCSException('', 103);
574
+        }
575
+
576
+        // If they're not an admin, check they are a subadmin of the group in question
577
+        $loggedInUser = $this->userSession->getUser();
578
+        $subAdminManager = $this->groupManager->getSubAdmin();
579
+        if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
580
+            throw new OCSException('', 104);
581
+        }
582
+
583
+        // Add user to group
584
+        $group->addUser($targetUser);
585
+        return new DataResponse();
586
+    }
587
+
588
+    /**
589
+     * @PasswordConfirmationRequired
590
+     * @NoAdminRequired
591
+     *
592
+     * @param string $userId
593
+     * @param string $groupid
594
+     * @return DataResponse
595
+     * @throws OCSException
596
+     */
597
+    public function removeFromGroup($userId, $groupid) {
598
+        $loggedInUser = $this->userSession->getUser();
599
+
600
+        if($groupid === null) {
601
+            throw new OCSException('', 101);
602
+        }
603
+
604
+        $group = $this->groupManager->get($groupid);
605
+        if($group === null) {
606
+            throw new OCSException('', 102);
607
+        }
608
+
609
+        $targetUser = $this->userManager->get($userId);
610
+        if($targetUser === null) {
611
+            throw new OCSException('', 103);
612
+        }
613
+
614
+        // If they're not an admin, check they are a subadmin of the group in question
615
+        $subAdminManager = $this->groupManager->getSubAdmin();
616
+        if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
617
+            throw new OCSException('', 104);
618
+        }
619
+
620
+        // Check they aren't removing themselves from 'admin' or their 'subadmin; group
621
+        if ($userId === $loggedInUser->getUID()) {
622
+            if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
623
+                if ($group->getGID() === 'admin') {
624
+                    throw new OCSException('Cannot remove yourself from the admin group', 105);
625
+                }
626
+            } else {
627
+                // Not an admin, so the user must be a subadmin of this group, but that is not allowed.
628
+                throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
629
+            }
630
+
631
+        } else if (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
632
+            /** @var IGroup[] $subAdminGroups */
633
+            $subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
634
+            $subAdminGroups = array_map(function (IGroup $subAdminGroup) {
635
+                return $subAdminGroup->getGID();
636
+            }, $subAdminGroups);
637
+            $userGroups = $this->groupManager->getUserGroupIds($targetUser);
638
+            $userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
639
+
640
+            if (count($userSubAdminGroups) <= 1) {
641
+                // Subadmin must not be able to remove a user from all their subadmin groups.
642
+                throw new OCSException('Cannot remove user from this group as this is the only remaining group you are a SubAdmin of', 105);
643
+            }
644
+        }
645
+
646
+        // Remove user from group
647
+        $group->removeUser($targetUser);
648
+        return new DataResponse();
649
+    }
650
+
651
+    /**
652
+     * Creates a subadmin
653
+     *
654
+     * @PasswordConfirmationRequired
655
+     *
656
+     * @param string $userId
657
+     * @param string $groupid
658
+     * @return DataResponse
659
+     * @throws OCSException
660
+     */
661
+    public function addSubAdmin($userId, $groupid) {
662
+        $group = $this->groupManager->get($groupid);
663
+        $user = $this->userManager->get($userId);
664
+
665
+        // Check if the user exists
666
+        if($user === null) {
667
+            throw new OCSException('User does not exist', 101);
668
+        }
669
+        // Check if group exists
670
+        if($group === null) {
671
+            throw new OCSException('Group:'.$groupid.' does not exist',  102);
672
+        }
673
+        // Check if trying to make subadmin of admin group
674
+        if(strtolower($groupid) === 'admin') {
675
+            throw new OCSException('Cannot create subadmins for admin group', 103);
676
+        }
677
+
678
+        $subAdminManager = $this->groupManager->getSubAdmin();
679
+
680
+        // We cannot be subadmin twice
681
+        if ($subAdminManager->isSubAdminofGroup($user, $group)) {
682
+            return new DataResponse();
683
+        }
684
+        // Go
685
+        if($subAdminManager->createSubAdmin($user, $group)) {
686
+            return new DataResponse();
687
+        } else {
688
+            throw new OCSException('Unknown error occurred', 103);
689
+        }
690
+    }
691
+
692
+    /**
693
+     * Removes a subadmin from a group
694
+     *
695
+     * @PasswordConfirmationRequired
696
+     *
697
+     * @param string $userId
698
+     * @param string $groupid
699
+     * @return DataResponse
700
+     * @throws OCSException
701
+     */
702
+    public function removeSubAdmin($userId, $groupid) {
703
+        $group = $this->groupManager->get($groupid);
704
+        $user = $this->userManager->get($userId);
705
+        $subAdminManager = $this->groupManager->getSubAdmin();
706
+
707
+        // Check if the user exists
708
+        if($user === null) {
709
+            throw new OCSException('User does not exist', 101);
710
+        }
711
+        // Check if the group exists
712
+        if($group === null) {
713
+            throw new OCSException('Group does not exist', 101);
714
+        }
715
+        // Check if they are a subadmin of this said group
716
+        if(!$subAdminManager->isSubAdminofGroup($user, $group)) {
717
+            throw new OCSException('User is not a subadmin of this group', 102);
718
+        }
719
+
720
+        // Go
721
+        if($subAdminManager->deleteSubAdmin($user, $group)) {
722
+            return new DataResponse();
723
+        } else {
724
+            throw new OCSException('Unknown error occurred', 103);
725
+        }
726
+    }
727
+
728
+    /**
729
+     * Get the groups a user is a subadmin of
730
+     *
731
+     * @param string $userId
732
+     * @return DataResponse
733
+     * @throws OCSException
734
+     */
735
+    public function getUserSubAdminGroups($userId) {
736
+        $user = $this->userManager->get($userId);
737
+        // Check if the user exists
738
+        if($user === null) {
739
+            throw new OCSException('User does not exist', 101);
740
+        }
741
+
742
+        // Get the subadmin groups
743
+        $groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user);
744
+        foreach ($groups as $key => $group) {
745
+            $groups[$key] = $group->getGID();
746
+        }
747
+
748
+        if(!$groups) {
749
+            throw new OCSException('Unknown error occurred', 102);
750
+        } else {
751
+            return new DataResponse($groups);
752
+        }
753
+    }
754
+
755
+    /**
756
+     * @param string $userId
757
+     * @return array
758
+     * @throws \OCP\Files\NotFoundException
759
+     */
760
+    protected function fillStorageInfo($userId) {
761
+        try {
762
+            \OC_Util::tearDownFS();
763
+            \OC_Util::setupFS($userId);
764
+            $storage = OC_Helper::getStorageInfo('/');
765
+            $data = [
766
+                'free' => $storage['free'],
767
+                'used' => $storage['used'],
768
+                'total' => $storage['total'],
769
+                'relative' => $storage['relative'],
770
+                'quota' => $storage['quota'],
771
+            ];
772
+        } catch (NotFoundException $ex) {
773
+            $data = [];
774
+        }
775
+        return $data;
776
+    }
777
+
778
+    /**
779
+     * @NoAdminRequired
780
+     * @PasswordConfirmationRequired
781
+     *
782
+     * resend welcome message
783
+     *
784
+     * @param string $userId
785
+     * @return DataResponse
786
+     * @throws OCSException
787
+     */
788
+    public function resendWelcomeMessage($userId) {
789
+        $currentLoggedInUser = $this->userSession->getUser();
790
+
791
+        $targetUser = $this->userManager->get($userId);
792
+        if($targetUser === null) {
793
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
794
+        }
795
+
796
+        // Check if admin / subadmin
797
+        $subAdminManager = $this->groupManager->getSubAdmin();
798
+        if(!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
799
+            && !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
800
+            // No rights
801
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
802
+        }
803
+
804
+        $email = $targetUser->getEMailAddress();
805
+        if ($email === '' || $email === null) {
806
+            throw new OCSException('Email address not available', 101);
807
+        }
808
+        $username = $targetUser->getUID();
809
+        $lang = $this->config->getUserValue($username, 'core', 'lang', 'en');
810
+        if (!$this->l10nFactory->languageExists('settings', $lang)) {
811
+            $lang = 'en';
812
+        }
813
+
814
+        $l10n = $this->l10nFactory->get('settings', $lang);
815
+
816
+        try {
817
+            $this->newUserMailHelper->setL10N($l10n);
818
+            $emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
819
+            $this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
820
+        } catch(\Exception $e) {
821
+            $this->logger->error("Can't send new user mail to $email: " . $e->getMessage(), array('app' => 'settings'));
822
+            throw new OCSException('Sending email failed', 102);
823
+        }
824
+
825
+        return new DataResponse();
826
+    }
827 827
 }
Please login to merge, or discard this patch.
settings/Mailer/NewUserMailHelper.php 1 patch
Indentation   +123 added lines, -123 removed lines patch added patch discarded remove patch
@@ -34,133 +34,133 @@
 block discarded – undo
34 34
 use OCP\Security\ISecureRandom;
35 35
 
36 36
 class NewUserMailHelper {
37
-	/** @var Defaults */
38
-	private $themingDefaults;
39
-	/** @var IURLGenerator */
40
-	private $urlGenerator;
41
-	/** @var IL10N */
42
-	private $l10n;
43
-	/** @var IMailer */
44
-	private $mailer;
45
-	/** @var ISecureRandom */
46
-	private $secureRandom;
47
-	/** @var ITimeFactory */
48
-	private $timeFactory;
49
-	/** @var IConfig */
50
-	private $config;
51
-	/** @var ICrypto */
52
-	private $crypto;
53
-	/** @var string */
54
-	private $fromAddress;
37
+    /** @var Defaults */
38
+    private $themingDefaults;
39
+    /** @var IURLGenerator */
40
+    private $urlGenerator;
41
+    /** @var IL10N */
42
+    private $l10n;
43
+    /** @var IMailer */
44
+    private $mailer;
45
+    /** @var ISecureRandom */
46
+    private $secureRandom;
47
+    /** @var ITimeFactory */
48
+    private $timeFactory;
49
+    /** @var IConfig */
50
+    private $config;
51
+    /** @var ICrypto */
52
+    private $crypto;
53
+    /** @var string */
54
+    private $fromAddress;
55 55
 
56
-	/**
57
-	 * @param Defaults $themingDefaults
58
-	 * @param IURLGenerator $urlGenerator
59
-	 * @param IL10N $l10n
60
-	 * @param IMailer $mailer
61
-	 * @param ISecureRandom $secureRandom
62
-	 * @param ITimeFactory $timeFactory
63
-	 * @param IConfig $config
64
-	 * @param ICrypto $crypto
65
-	 * @param string $fromAddress
66
-	 */
67
-	public function __construct(Defaults $themingDefaults,
68
-								IURLGenerator $urlGenerator,
69
-								IL10N $l10n,
70
-								IMailer $mailer,
71
-								ISecureRandom $secureRandom,
72
-								ITimeFactory $timeFactory,
73
-								IConfig $config,
74
-								ICrypto $crypto,
75
-								$fromAddress) {
76
-		$this->themingDefaults = $themingDefaults;
77
-		$this->urlGenerator = $urlGenerator;
78
-		$this->l10n = $l10n;
79
-		$this->mailer = $mailer;
80
-		$this->secureRandom = $secureRandom;
81
-		$this->timeFactory = $timeFactory;
82
-		$this->config = $config;
83
-		$this->crypto = $crypto;
84
-		$this->fromAddress = $fromAddress;
85
-	}
56
+    /**
57
+     * @param Defaults $themingDefaults
58
+     * @param IURLGenerator $urlGenerator
59
+     * @param IL10N $l10n
60
+     * @param IMailer $mailer
61
+     * @param ISecureRandom $secureRandom
62
+     * @param ITimeFactory $timeFactory
63
+     * @param IConfig $config
64
+     * @param ICrypto $crypto
65
+     * @param string $fromAddress
66
+     */
67
+    public function __construct(Defaults $themingDefaults,
68
+                                IURLGenerator $urlGenerator,
69
+                                IL10N $l10n,
70
+                                IMailer $mailer,
71
+                                ISecureRandom $secureRandom,
72
+                                ITimeFactory $timeFactory,
73
+                                IConfig $config,
74
+                                ICrypto $crypto,
75
+                                $fromAddress) {
76
+        $this->themingDefaults = $themingDefaults;
77
+        $this->urlGenerator = $urlGenerator;
78
+        $this->l10n = $l10n;
79
+        $this->mailer = $mailer;
80
+        $this->secureRandom = $secureRandom;
81
+        $this->timeFactory = $timeFactory;
82
+        $this->config = $config;
83
+        $this->crypto = $crypto;
84
+        $this->fromAddress = $fromAddress;
85
+    }
86 86
 
87
-	/**
88
-	 * Set the IL10N object
89
-	 *
90
-	 * @param IL10N $l10n
91
-	 */
92
-	public function setL10N(IL10N $l10n) {
93
-		$this->l10n = $l10n;
94
-	}
87
+    /**
88
+     * Set the IL10N object
89
+     *
90
+     * @param IL10N $l10n
91
+     */
92
+    public function setL10N(IL10N $l10n) {
93
+        $this->l10n = $l10n;
94
+    }
95 95
 
96
-	/**
97
-	 * @param IUser $user
98
-	 * @param bool $generatePasswordResetToken
99
-	 * @return EMailTemplate
100
-	 */
101
-	public function generateTemplate(IUser $user, $generatePasswordResetToken = false) {
102
-		if ($generatePasswordResetToken) {
103
-			$token = $this->secureRandom->generate(
104
-				21,
105
-				ISecureRandom::CHAR_DIGITS .
106
-				ISecureRandom::CHAR_LOWER .
107
-				ISecureRandom::CHAR_UPPER
108
-			);
109
-			$tokenValue = $this->timeFactory->getTime() . ':' . $token;
110
-			$mailAddress = (null !== $user->getEMailAddress()) ? $user->getEMailAddress() : '';
111
-			$encryptedValue = $this->crypto->encrypt($tokenValue, $mailAddress . $this->config->getSystemValue('secret'));
112
-			$this->config->setUserValue($user->getUID(), 'core', 'lostpassword', $encryptedValue);
113
-			$link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', ['userId' => $user->getUID(), 'token' => $token]);
114
-		} else {
115
-			$link = $this->urlGenerator->getAbsoluteURL('/');
116
-		}
96
+    /**
97
+     * @param IUser $user
98
+     * @param bool $generatePasswordResetToken
99
+     * @return EMailTemplate
100
+     */
101
+    public function generateTemplate(IUser $user, $generatePasswordResetToken = false) {
102
+        if ($generatePasswordResetToken) {
103
+            $token = $this->secureRandom->generate(
104
+                21,
105
+                ISecureRandom::CHAR_DIGITS .
106
+                ISecureRandom::CHAR_LOWER .
107
+                ISecureRandom::CHAR_UPPER
108
+            );
109
+            $tokenValue = $this->timeFactory->getTime() . ':' . $token;
110
+            $mailAddress = (null !== $user->getEMailAddress()) ? $user->getEMailAddress() : '';
111
+            $encryptedValue = $this->crypto->encrypt($tokenValue, $mailAddress . $this->config->getSystemValue('secret'));
112
+            $this->config->setUserValue($user->getUID(), 'core', 'lostpassword', $encryptedValue);
113
+            $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', ['userId' => $user->getUID(), 'token' => $token]);
114
+        } else {
115
+            $link = $this->urlGenerator->getAbsoluteURL('/');
116
+        }
117 117
 
118
-		$emailTemplate = new EMailTemplate(
119
-			$this->themingDefaults,
120
-			$this->urlGenerator,
121
-			$this->l10n
122
-		);
123
-		$emailTemplate->addHeader();
124
-		$displayName = $user->getDisplayName();
125
-		$userName = $user->getUID();
126
-		if ($displayName === $userName) {
127
-			$emailTemplate->addHeading($this->l10n->t('Welcome aboard'));
128
-		} else {
129
-			$emailTemplate->addHeading($this->l10n->t('Welcome aboard %s', [$displayName]));
130
-		}
131
-		$emailTemplate->addBodyText($this->l10n->t('You have now an %s account, you can add, protect, and share your data.', [$this->themingDefaults->getName()]));
132
-		$emailTemplate->addBodyText($this->l10n->t('Your username is: %s', [$userName]));
133
-		if ($generatePasswordResetToken) {
134
-			$leftButtonText = $this->l10n->t('Set your password');
135
-		} else {
136
-			$leftButtonText = $this->l10n->t('Go to %s', [$this->themingDefaults->getName()]);
137
-		}
138
-		$emailTemplate->addBodyButtonGroup(
139
-			$leftButtonText,
140
-			$link,
141
-			$this->l10n->t('Install Client'),
142
-			'https://nextcloud.com/install/#install-clients'
143
-		);
144
-		$emailTemplate->addFooter();
118
+        $emailTemplate = new EMailTemplate(
119
+            $this->themingDefaults,
120
+            $this->urlGenerator,
121
+            $this->l10n
122
+        );
123
+        $emailTemplate->addHeader();
124
+        $displayName = $user->getDisplayName();
125
+        $userName = $user->getUID();
126
+        if ($displayName === $userName) {
127
+            $emailTemplate->addHeading($this->l10n->t('Welcome aboard'));
128
+        } else {
129
+            $emailTemplate->addHeading($this->l10n->t('Welcome aboard %s', [$displayName]));
130
+        }
131
+        $emailTemplate->addBodyText($this->l10n->t('You have now an %s account, you can add, protect, and share your data.', [$this->themingDefaults->getName()]));
132
+        $emailTemplate->addBodyText($this->l10n->t('Your username is: %s', [$userName]));
133
+        if ($generatePasswordResetToken) {
134
+            $leftButtonText = $this->l10n->t('Set your password');
135
+        } else {
136
+            $leftButtonText = $this->l10n->t('Go to %s', [$this->themingDefaults->getName()]);
137
+        }
138
+        $emailTemplate->addBodyButtonGroup(
139
+            $leftButtonText,
140
+            $link,
141
+            $this->l10n->t('Install Client'),
142
+            'https://nextcloud.com/install/#install-clients'
143
+        );
144
+        $emailTemplate->addFooter();
145 145
 
146
-		return $emailTemplate;
147
-	}
146
+        return $emailTemplate;
147
+    }
148 148
 
149
-	/**
150
-	 * Sends a welcome mail to $user
151
-	 *
152
-	 * @param IUser $user
153
-	 * @param IEmailTemplate $emailTemplate
154
-	 * @throws \Exception If mail could not be sent
155
-	 */
156
-	public function sendMail(IUser $user,
157
-							 IEMailTemplate $emailTemplate) {
158
-		$message = $this->mailer->createMessage();
159
-		$message->setTo([$user->getEMailAddress() => $user->getDisplayName()]);
160
-		$message->setSubject($this->l10n->t('Your %s account was created', [$this->themingDefaults->getName()]));
161
-		$message->setHtmlBody($emailTemplate->renderHTML());
162
-		$message->setPlainBody($emailTemplate->renderText());
163
-		$message->setFrom([$this->fromAddress => $this->themingDefaults->getName()]);
164
-		$this->mailer->send($message);
165
-	}
149
+    /**
150
+     * Sends a welcome mail to $user
151
+     *
152
+     * @param IUser $user
153
+     * @param IEmailTemplate $emailTemplate
154
+     * @throws \Exception If mail could not be sent
155
+     */
156
+    public function sendMail(IUser $user,
157
+                                IEMailTemplate $emailTemplate) {
158
+        $message = $this->mailer->createMessage();
159
+        $message->setTo([$user->getEMailAddress() => $user->getDisplayName()]);
160
+        $message->setSubject($this->l10n->t('Your %s account was created', [$this->themingDefaults->getName()]));
161
+        $message->setHtmlBody($emailTemplate->renderHTML());
162
+        $message->setPlainBody($emailTemplate->renderText());
163
+        $message->setFrom([$this->fromAddress => $this->themingDefaults->getName()]);
164
+        $this->mailer->send($message);
165
+    }
166 166
 }
Please login to merge, or discard this patch.
core/templates/404.php 2 patches
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -4,11 +4,11 @@
 block discarded – undo
4 4
 /** @var $theme OCP\Defaults */
5 5
 // @codeCoverageIgnoreStart
6 6
 if(!isset($_)) {//also provide standalone error page
7
-	require_once '../../lib/base.php';
7
+    require_once '../../lib/base.php';
8 8
 	
9
-	$tmpl = new OC_Template( '', '404', 'guest' );
10
-	$tmpl->printPage();
11
-	exit;
9
+    $tmpl = new OC_Template( '', '404', 'guest' );
10
+    $tmpl->printPage();
11
+    exit;
12 12
 }
13 13
 // @codeCoverageIgnoreEnd
14 14
 ?>
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -3,10 +3,10 @@
 block discarded – undo
3 3
 /** @var $l \OCP\IL10N */
4 4
 /** @var $theme OCP\Defaults */
5 5
 // @codeCoverageIgnoreStart
6
-if(!isset($_)) {//also provide standalone error page
6
+if (!isset($_)) {//also provide standalone error page
7 7
 	require_once '../../lib/base.php';
8 8
 	
9
-	$tmpl = new OC_Template( '', '404', 'guest' );
9
+	$tmpl = new OC_Template('', '404', 'guest');
10 10
 	$tmpl->printPage();
11 11
 	exit;
12 12
 }
Please login to merge, or discard this patch.
lib/public/Defaults.php 1 patch
Indentation   +171 added lines, -171 removed lines patch added patch discarded remove patch
@@ -40,175 +40,175 @@
 block discarded – undo
40 40
  */
41 41
 class Defaults {
42 42
 
43
-	/**
44
-	 * \OC_Defaults instance to retrieve the defaults
45
-	 * @since 6.0.0
46
-	 */
47
-	private $defaults;
48
-
49
-	/**
50
-	 * creates a \OC_Defaults instance which is used in all methods to retrieve the
51
-	 * actual defaults
52
-	 * @since 6.0.0
53
-	 */
54
-	function __construct(\OC_Defaults $defaults = null) {
55
-		if ($defaults === null) {
56
-			$defaults = \OC::$server->getThemingDefaults();
57
-		}
58
-		$this->defaults = $defaults;
59
-	}
60
-
61
-	/**
62
-	 * get base URL for the organisation behind your ownCloud instance
63
-	 * @return string
64
-	 * @since 6.0.0
65
-	 */
66
-	public function getBaseUrl() {
67
-		return $this->defaults->getBaseUrl();
68
-	}
69
-
70
-	/**
71
-	 * link to the desktop sync client
72
-	 * @return string
73
-	 * @since 6.0.0
74
-	 */
75
-	public function getSyncClientUrl() {
76
-		return $this->defaults->getSyncClientUrl();
77
-	}
78
-
79
-	/**
80
-	 * link to the iOS client
81
-	 * @return string
82
-	 * @since 8.0.0
83
-	 */
84
-	public function getiOSClientUrl() {
85
-		return $this->defaults->getiOSClientUrl();
86
-	}
87
-
88
-	/**
89
-	 * link to the Android client
90
-	 * @return string
91
-	 * @since 8.0.0
92
-	 */
93
-	public function getAndroidClientUrl() {
94
-		return $this->defaults->getAndroidClientUrl();
95
-	}
96
-
97
-	/**
98
-	 * base URL to the documentation of your ownCloud instance
99
-	 * @return string
100
-	 * @since 6.0.0
101
-	 */
102
-	public function getDocBaseUrl() {
103
-		return $this->defaults->getDocBaseUrl();
104
-	}
105
-
106
-	/**
107
-	 * name of your ownCloud instance
108
-	 * @return string
109
-	 * @since 6.0.0
110
-	 */
111
-	public function getName() {
112
-		return $this->defaults->getName();
113
-	}
114
-
115
-	/**
116
-	 * name of your ownCloud instance containing HTML styles
117
-	 * @return string
118
-	 * @since 8.0.0
119
-	 */
120
-	public function getHTMLName() {
121
-		return $this->defaults->getHTMLName();
122
-	}
123
-
124
-	/**
125
-	 * Entity behind your onwCloud instance
126
-	 * @return string
127
-	 * @since 6.0.0
128
-	 */
129
-	public function getEntity() {
130
-		return $this->defaults->getEntity();
131
-	}
132
-
133
-	/**
134
-	 * ownCloud slogan
135
-	 * @return string
136
-	 * @since 6.0.0
137
-	 */
138
-	public function getSlogan() {
139
-		return $this->defaults->getSlogan();
140
-	}
141
-
142
-	/**
143
-	 * logo claim
144
-	 * @return string
145
-	 * @since 6.0.0
146
-	 */
147
-	public function getLogoClaim() {
148
-		return $this->defaults->getLogoClaim();
149
-	}
150
-
151
-	/**
152
-	 * footer, short version
153
-	 * @return string
154
-	 * @since 6.0.0
155
-	 */
156
-	public function getShortFooter() {
157
-		return $this->defaults->getShortFooter();
158
-	}
159
-
160
-	/**
161
-	 * footer, long version
162
-	 * @return string
163
-	 * @since 6.0.0
164
-	 */
165
-	public function getLongFooter() {
166
-		return $this->defaults->getLongFooter();
167
-	}
168
-
169
-	/**
170
-	 * Returns the AppId for the App Store for the iOS Client
171
-	 * @return string AppId
172
-	 * @since 8.0.0
173
-	 */
174
-	public function getiTunesAppId() {
175
-		return $this->defaults->getiTunesAppId();
176
-	}
177
-
178
-	/**
179
-	 * Themed logo url
180
-	 *
181
-	 * @return string
182
-	 * @since 12.0.0
183
-	 */
184
-	public function getLogo() {
185
-		return $this->defaults->getLogo();
186
-	}
187
-
188
-	/**
189
-	 * Returns primary color
190
-	 * @return string
191
-	 * @since 12.0.0
192
-	 */
193
-	public function getColorPrimary() {
194
-		return $this->defaults->getColorPrimary();
195
-	}
196
-
197
-	/**
198
-	 * @param string $key
199
-	 * @return string URL to doc with key
200
-	 * @since 12.0.0
201
-	 */
202
-	public function buildDocLinkToKey($key) {
203
-		return $this->defaults->buildDocLinkToKey($key);
204
-	}
205
-
206
-	/**
207
-	 * Returns the title
208
-	 * @return string title
209
-	 * @since 12.0.0
210
-	 */
211
-	public function getTitle() {
212
-		return $this->defaults->getTitle();
213
-	}
43
+    /**
44
+     * \OC_Defaults instance to retrieve the defaults
45
+     * @since 6.0.0
46
+     */
47
+    private $defaults;
48
+
49
+    /**
50
+     * creates a \OC_Defaults instance which is used in all methods to retrieve the
51
+     * actual defaults
52
+     * @since 6.0.0
53
+     */
54
+    function __construct(\OC_Defaults $defaults = null) {
55
+        if ($defaults === null) {
56
+            $defaults = \OC::$server->getThemingDefaults();
57
+        }
58
+        $this->defaults = $defaults;
59
+    }
60
+
61
+    /**
62
+     * get base URL for the organisation behind your ownCloud instance
63
+     * @return string
64
+     * @since 6.0.0
65
+     */
66
+    public function getBaseUrl() {
67
+        return $this->defaults->getBaseUrl();
68
+    }
69
+
70
+    /**
71
+     * link to the desktop sync client
72
+     * @return string
73
+     * @since 6.0.0
74
+     */
75
+    public function getSyncClientUrl() {
76
+        return $this->defaults->getSyncClientUrl();
77
+    }
78
+
79
+    /**
80
+     * link to the iOS client
81
+     * @return string
82
+     * @since 8.0.0
83
+     */
84
+    public function getiOSClientUrl() {
85
+        return $this->defaults->getiOSClientUrl();
86
+    }
87
+
88
+    /**
89
+     * link to the Android client
90
+     * @return string
91
+     * @since 8.0.0
92
+     */
93
+    public function getAndroidClientUrl() {
94
+        return $this->defaults->getAndroidClientUrl();
95
+    }
96
+
97
+    /**
98
+     * base URL to the documentation of your ownCloud instance
99
+     * @return string
100
+     * @since 6.0.0
101
+     */
102
+    public function getDocBaseUrl() {
103
+        return $this->defaults->getDocBaseUrl();
104
+    }
105
+
106
+    /**
107
+     * name of your ownCloud instance
108
+     * @return string
109
+     * @since 6.0.0
110
+     */
111
+    public function getName() {
112
+        return $this->defaults->getName();
113
+    }
114
+
115
+    /**
116
+     * name of your ownCloud instance containing HTML styles
117
+     * @return string
118
+     * @since 8.0.0
119
+     */
120
+    public function getHTMLName() {
121
+        return $this->defaults->getHTMLName();
122
+    }
123
+
124
+    /**
125
+     * Entity behind your onwCloud instance
126
+     * @return string
127
+     * @since 6.0.0
128
+     */
129
+    public function getEntity() {
130
+        return $this->defaults->getEntity();
131
+    }
132
+
133
+    /**
134
+     * ownCloud slogan
135
+     * @return string
136
+     * @since 6.0.0
137
+     */
138
+    public function getSlogan() {
139
+        return $this->defaults->getSlogan();
140
+    }
141
+
142
+    /**
143
+     * logo claim
144
+     * @return string
145
+     * @since 6.0.0
146
+     */
147
+    public function getLogoClaim() {
148
+        return $this->defaults->getLogoClaim();
149
+    }
150
+
151
+    /**
152
+     * footer, short version
153
+     * @return string
154
+     * @since 6.0.0
155
+     */
156
+    public function getShortFooter() {
157
+        return $this->defaults->getShortFooter();
158
+    }
159
+
160
+    /**
161
+     * footer, long version
162
+     * @return string
163
+     * @since 6.0.0
164
+     */
165
+    public function getLongFooter() {
166
+        return $this->defaults->getLongFooter();
167
+    }
168
+
169
+    /**
170
+     * Returns the AppId for the App Store for the iOS Client
171
+     * @return string AppId
172
+     * @since 8.0.0
173
+     */
174
+    public function getiTunesAppId() {
175
+        return $this->defaults->getiTunesAppId();
176
+    }
177
+
178
+    /**
179
+     * Themed logo url
180
+     *
181
+     * @return string
182
+     * @since 12.0.0
183
+     */
184
+    public function getLogo() {
185
+        return $this->defaults->getLogo();
186
+    }
187
+
188
+    /**
189
+     * Returns primary color
190
+     * @return string
191
+     * @since 12.0.0
192
+     */
193
+    public function getColorPrimary() {
194
+        return $this->defaults->getColorPrimary();
195
+    }
196
+
197
+    /**
198
+     * @param string $key
199
+     * @return string URL to doc with key
200
+     * @since 12.0.0
201
+     */
202
+    public function buildDocLinkToKey($key) {
203
+        return $this->defaults->buildDocLinkToKey($key);
204
+    }
205
+
206
+    /**
207
+     * Returns the title
208
+     * @return string title
209
+     * @since 12.0.0
210
+     */
211
+    public function getTitle() {
212
+        return $this->defaults->getTitle();
213
+    }
214 214
 }
Please login to merge, or discard this patch.
lib/base.php 1 patch
Indentation   +988 added lines, -988 removed lines patch added patch discarded remove patch
@@ -59,994 +59,994 @@
 block discarded – undo
59 59
  * OC_autoload!
60 60
  */
61 61
 class OC {
62
-	/**
63
-	 * Associative array for autoloading. classname => filename
64
-	 */
65
-	public static $CLASSPATH = array();
66
-	/**
67
-	 * The installation path for Nextcloud  on the server (e.g. /srv/http/nextcloud)
68
-	 */
69
-	public static $SERVERROOT = '';
70
-	/**
71
-	 * the current request path relative to the Nextcloud root (e.g. files/index.php)
72
-	 */
73
-	private static $SUBURI = '';
74
-	/**
75
-	 * the Nextcloud root path for http requests (e.g. nextcloud/)
76
-	 */
77
-	public static $WEBROOT = '';
78
-	/**
79
-	 * The installation path array of the apps folder on the server (e.g. /srv/http/nextcloud) 'path' and
80
-	 * web path in 'url'
81
-	 */
82
-	public static $APPSROOTS = array();
83
-
84
-	/**
85
-	 * @var string
86
-	 */
87
-	public static $configDir;
88
-
89
-	/**
90
-	 * requested app
91
-	 */
92
-	public static $REQUESTEDAPP = '';
93
-
94
-	/**
95
-	 * check if Nextcloud runs in cli mode
96
-	 */
97
-	public static $CLI = false;
98
-
99
-	/**
100
-	 * @var \OC\Autoloader $loader
101
-	 */
102
-	public static $loader = null;
103
-
104
-	/** @var \Composer\Autoload\ClassLoader $composerAutoloader */
105
-	public static $composerAutoloader = null;
106
-
107
-	/**
108
-	 * @var \OC\Server
109
-	 */
110
-	public static $server = null;
111
-
112
-	/**
113
-	 * @var \OC\Config
114
-	 */
115
-	private static $config = null;
116
-
117
-	/**
118
-	 * @throws \RuntimeException when the 3rdparty directory is missing or
119
-	 * the app path list is empty or contains an invalid path
120
-	 */
121
-	public static function initPaths() {
122
-		if(defined('PHPUNIT_CONFIG_DIR')) {
123
-			self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/';
124
-		} elseif(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) {
125
-			self::$configDir = OC::$SERVERROOT . '/tests/config/';
126
-		} elseif($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
127
-			self::$configDir = rtrim($dir, '/') . '/';
128
-		} else {
129
-			self::$configDir = OC::$SERVERROOT . '/config/';
130
-		}
131
-		self::$config = new \OC\Config(self::$configDir);
132
-
133
-		OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
134
-		/**
135
-		 * FIXME: The following lines are required because we can't yet instantiiate
136
-		 *        \OC::$server->getRequest() since \OC::$server does not yet exist.
137
-		 */
138
-		$params = [
139
-			'server' => [
140
-				'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'],
141
-				'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'],
142
-			],
143
-		];
144
-		$fakeRequest = new \OC\AppFramework\Http\Request($params, null, new \OC\AllConfig(new \OC\SystemConfig(self::$config)));
145
-		$scriptName = $fakeRequest->getScriptName();
146
-		if (substr($scriptName, -1) == '/') {
147
-			$scriptName .= 'index.php';
148
-			//make sure suburi follows the same rules as scriptName
149
-			if (substr(OC::$SUBURI, -9) != 'index.php') {
150
-				if (substr(OC::$SUBURI, -1) != '/') {
151
-					OC::$SUBURI = OC::$SUBURI . '/';
152
-				}
153
-				OC::$SUBURI = OC::$SUBURI . 'index.php';
154
-			}
155
-		}
156
-
157
-
158
-		if (OC::$CLI) {
159
-			OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
160
-		} else {
161
-			if (substr($scriptName, 0 - strlen(OC::$SUBURI)) === OC::$SUBURI) {
162
-				OC::$WEBROOT = substr($scriptName, 0, 0 - strlen(OC::$SUBURI));
163
-
164
-				if (OC::$WEBROOT != '' && OC::$WEBROOT[0] !== '/') {
165
-					OC::$WEBROOT = '/' . OC::$WEBROOT;
166
-				}
167
-			} else {
168
-				// The scriptName is not ending with OC::$SUBURI
169
-				// This most likely means that we are calling from CLI.
170
-				// However some cron jobs still need to generate
171
-				// a web URL, so we use overwritewebroot as a fallback.
172
-				OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
173
-			}
174
-
175
-			// Resolve /nextcloud to /nextcloud/ to ensure to always have a trailing
176
-			// slash which is required by URL generation.
177
-			if($_SERVER['REQUEST_URI'] === \OC::$WEBROOT &&
178
-					substr($_SERVER['REQUEST_URI'], -1) !== '/') {
179
-				header('Location: '.\OC::$WEBROOT.'/');
180
-				exit();
181
-			}
182
-		}
183
-
184
-		// search the apps folder
185
-		$config_paths = self::$config->getValue('apps_paths', array());
186
-		if (!empty($config_paths)) {
187
-			foreach ($config_paths as $paths) {
188
-				if (isset($paths['url']) && isset($paths['path'])) {
189
-					$paths['url'] = rtrim($paths['url'], '/');
190
-					$paths['path'] = rtrim($paths['path'], '/');
191
-					OC::$APPSROOTS[] = $paths;
192
-				}
193
-			}
194
-		} elseif (file_exists(OC::$SERVERROOT . '/apps')) {
195
-			OC::$APPSROOTS[] = array('path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true);
196
-		} elseif (file_exists(OC::$SERVERROOT . '/../apps')) {
197
-			OC::$APPSROOTS[] = array(
198
-				'path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps',
199
-				'url' => '/apps',
200
-				'writable' => true
201
-			);
202
-		}
203
-
204
-		if (empty(OC::$APPSROOTS)) {
205
-			throw new \RuntimeException('apps directory not found! Please put the Nextcloud apps folder in the Nextcloud folder'
206
-				. ' or the folder above. You can also configure the location in the config.php file.');
207
-		}
208
-		$paths = array();
209
-		foreach (OC::$APPSROOTS as $path) {
210
-			$paths[] = $path['path'];
211
-			if (!is_dir($path['path'])) {
212
-				throw new \RuntimeException(sprintf('App directory "%s" not found! Please put the Nextcloud apps folder in the'
213
-					. ' Nextcloud folder or the folder above. You can also configure the location in the'
214
-					. ' config.php file.', $path['path']));
215
-			}
216
-		}
217
-
218
-		// set the right include path
219
-		set_include_path(
220
-			implode(PATH_SEPARATOR, $paths)
221
-		);
222
-	}
223
-
224
-	public static function checkConfig() {
225
-		$l = \OC::$server->getL10N('lib');
226
-
227
-		// Create config if it does not already exist
228
-		$configFilePath = self::$configDir .'/config.php';
229
-		if(!file_exists($configFilePath)) {
230
-			@touch($configFilePath);
231
-		}
232
-
233
-		// Check if config is writable
234
-		$configFileWritable = is_writable($configFilePath);
235
-		if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled()
236
-			|| !$configFileWritable && self::checkUpgrade(false)) {
237
-
238
-			$urlGenerator = \OC::$server->getURLGenerator();
239
-
240
-			if (self::$CLI) {
241
-				echo $l->t('Cannot write into "config" directory!')."\n";
242
-				echo $l->t('This can usually be fixed by giving the webserver write access to the config directory')."\n";
243
-				echo "\n";
244
-				echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-dir_permissions') ])."\n";
245
-				exit;
246
-			} else {
247
-				OC_Template::printErrorPage(
248
-					$l->t('Cannot write into "config" directory!'),
249
-					$l->t('This can usually be fixed by '
250
-					. '%sgiving the webserver write access to the config directory%s.',
251
-					 array('<a href="' . $urlGenerator->linkToDocs('admin-dir_permissions') . '" target="_blank" rel="noreferrer">', '</a>'))
252
-				);
253
-			}
254
-		}
255
-	}
256
-
257
-	public static function checkInstalled() {
258
-		if (defined('OC_CONSOLE')) {
259
-			return;
260
-		}
261
-		// Redirect to installer if not installed
262
-		if (!\OC::$server->getSystemConfig()->getValue('installed', false) && OC::$SUBURI !== '/index.php' && OC::$SUBURI !== '/status.php') {
263
-			if (OC::$CLI) {
264
-				throw new Exception('Not installed');
265
-			} else {
266
-				$url = OC::$WEBROOT . '/index.php';
267
-				header('Location: ' . $url);
268
-			}
269
-			exit();
270
-		}
271
-	}
272
-
273
-	public static function checkMaintenanceMode() {
274
-		// Allow ajax update script to execute without being stopped
275
-		if (\OC::$server->getSystemConfig()->getValue('maintenance', false) && OC::$SUBURI != '/core/ajax/update.php') {
276
-			// send http status 503
277
-			header('HTTP/1.1 503 Service Temporarily Unavailable');
278
-			header('Status: 503 Service Temporarily Unavailable');
279
-			header('Retry-After: 120');
280
-
281
-			// render error page
282
-			$template = new OC_Template('', 'update.user', 'guest');
283
-			OC_Util::addScript('maintenance-check');
284
-			$template->printPage();
285
-			die();
286
-		}
287
-	}
288
-
289
-	/**
290
-	 * Checks if the version requires an update and shows
291
-	 * @param bool $showTemplate Whether an update screen should get shown
292
-	 * @return bool|void
293
-	 */
294
-	public static function checkUpgrade($showTemplate = true) {
295
-		if (\OCP\Util::needUpgrade()) {
296
-			$systemConfig = \OC::$server->getSystemConfig();
297
-			if ($showTemplate && !$systemConfig->getValue('maintenance', false)) {
298
-				self::printUpgradePage();
299
-				exit();
300
-			} else {
301
-				return true;
302
-			}
303
-		}
304
-		return false;
305
-	}
306
-
307
-	/**
308
-	 * Prints the upgrade page
309
-	 */
310
-	private static function printUpgradePage() {
311
-		$systemConfig = \OC::$server->getSystemConfig();
312
-
313
-		$disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false);
314
-		$tooBig = false;
315
-		if (!$disableWebUpdater) {
316
-			$apps = \OC::$server->getAppManager();
317
-			$tooBig = $apps->isInstalled('user_ldap') || $apps->isInstalled('user_shibboleth');
318
-			if (!$tooBig) {
319
-				// count users
320
-				$stats = \OC::$server->getUserManager()->countUsers();
321
-				$totalUsers = array_sum($stats);
322
-				$tooBig = ($totalUsers > 50);
323
-			}
324
-		}
325
-		if ($disableWebUpdater || $tooBig) {
326
-			// send http status 503
327
-			header('HTTP/1.1 503 Service Temporarily Unavailable');
328
-			header('Status: 503 Service Temporarily Unavailable');
329
-			header('Retry-After: 120');
330
-
331
-			// render error page
332
-			$template = new OC_Template('', 'update.use-cli', 'guest');
333
-			$template->assign('productName', 'nextcloud'); // for now
334
-			$template->assign('version', OC_Util::getVersionString());
335
-			$template->assign('tooBig', $tooBig);
336
-
337
-			$template->printPage();
338
-			die();
339
-		}
340
-
341
-		// check whether this is a core update or apps update
342
-		$installedVersion = $systemConfig->getValue('version', '0.0.0');
343
-		$currentVersion = implode('.', \OCP\Util::getVersion());
344
-
345
-		// if not a core upgrade, then it's apps upgrade
346
-		$isAppsOnlyUpgrade = (version_compare($currentVersion, $installedVersion, '='));
347
-
348
-		$oldTheme = $systemConfig->getValue('theme');
349
-		$systemConfig->setValue('theme', '');
350
-		OC_Util::addScript('config'); // needed for web root
351
-		OC_Util::addScript('update');
352
-
353
-		/** @var \OC\App\AppManager $appManager */
354
-		$appManager = \OC::$server->getAppManager();
355
-
356
-		$tmpl = new OC_Template('', 'update.admin', 'guest');
357
-		$tmpl->assign('version', OC_Util::getVersionString());
358
-		$tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade);
359
-
360
-		// get third party apps
361
-		$ocVersion = \OCP\Util::getVersion();
362
-		$incompatibleApps = $appManager->getIncompatibleApps($ocVersion);
363
-		$incompatibleShippedApps = [];
364
-		foreach ($incompatibleApps as $appInfo) {
365
-			if ($appManager->isShipped($appInfo['id'])) {
366
-				$incompatibleShippedApps[] = $appInfo['name'] . ' (' . $appInfo['id'] . ')';
367
-			}
368
-		}
369
-
370
-		if (!empty($incompatibleShippedApps)) {
371
-			$l = \OC::$server->getL10N('core');
372
-			$hint = $l->t('The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server.', [implode(', ', $incompatibleShippedApps)]);
373
-			throw new \OC\HintException('The files of the app ' . implode(', ', $incompatibleShippedApps) . ' were not replaced correctly. Make sure it is a version compatible with the server.', $hint);
374
-		}
375
-
376
-		$tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
377
-		$tmpl->assign('incompatibleAppsList', $incompatibleApps);
378
-		$tmpl->assign('productName', 'Nextcloud'); // for now
379
-		$tmpl->assign('oldTheme', $oldTheme);
380
-		$tmpl->printPage();
381
-	}
382
-
383
-	public static function initSession() {
384
-		// prevents javascript from accessing php session cookies
385
-		ini_set('session.cookie_httponly', true);
386
-
387
-		// set the cookie path to the Nextcloud directory
388
-		$cookie_path = OC::$WEBROOT ? : '/';
389
-		ini_set('session.cookie_path', $cookie_path);
390
-
391
-		// Let the session name be changed in the initSession Hook
392
-		$sessionName = OC_Util::getInstanceId();
393
-
394
-		try {
395
-			// Allow session apps to create a custom session object
396
-			$useCustomSession = false;
397
-			$session = self::$server->getSession();
398
-			OC_Hook::emit('OC', 'initSession', array('session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession));
399
-			if (!$useCustomSession) {
400
-				// set the session name to the instance id - which is unique
401
-				$session = new \OC\Session\Internal($sessionName);
402
-			}
403
-
404
-			$cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
405
-			$session = $cryptoWrapper->wrapSession($session);
406
-			self::$server->setSession($session);
407
-
408
-			// if session can't be started break with http 500 error
409
-		} catch (Exception $e) {
410
-			\OCP\Util::logException('base', $e);
411
-			//show the user a detailed error page
412
-			OC_Response::setStatus(OC_Response::STATUS_INTERNAL_SERVER_ERROR);
413
-			OC_Template::printExceptionErrorPage($e);
414
-			die();
415
-		}
416
-
417
-		$sessionLifeTime = self::getSessionLifeTime();
418
-
419
-		// session timeout
420
-		if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
421
-			if (isset($_COOKIE[session_name()])) {
422
-				setcookie(session_name(), null, -1, self::$WEBROOT ? : '/');
423
-			}
424
-			\OC::$server->getUserSession()->logout();
425
-		}
426
-
427
-		$session->set('LAST_ACTIVITY', time());
428
-	}
429
-
430
-	/**
431
-	 * @return string
432
-	 */
433
-	private static function getSessionLifeTime() {
434
-		return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
435
-	}
436
-
437
-	public static function loadAppClassPaths() {
438
-		foreach (OC_App::getEnabledApps() as $app) {
439
-			$appPath = OC_App::getAppPath($app);
440
-			if ($appPath === false) {
441
-				continue;
442
-			}
443
-
444
-			$file = $appPath . '/appinfo/classpath.php';
445
-			if (file_exists($file)) {
446
-				require_once $file;
447
-			}
448
-		}
449
-	}
450
-
451
-	/**
452
-	 * Try to set some values to the required Nextcloud default
453
-	 */
454
-	public static function setRequiredIniValues() {
455
-		@ini_set('default_charset', 'UTF-8');
456
-		@ini_set('gd.jpeg_ignore_warning', 1);
457
-	}
458
-
459
-	/**
460
-	 * Send the same site cookies
461
-	 */
462
-	private static function sendSameSiteCookies() {
463
-		$cookieParams = session_get_cookie_params();
464
-		$secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
465
-		$policies = [
466
-			'lax',
467
-			'strict',
468
-		];
469
-
470
-		// Append __Host to the cookie if it meets the requirements
471
-		$cookiePrefix = '';
472
-		if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
473
-			$cookiePrefix = '__Host-';
474
-		}
475
-
476
-		foreach($policies as $policy) {
477
-			header(
478
-				sprintf(
479
-					'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
480
-					$cookiePrefix,
481
-					$policy,
482
-					$cookieParams['path'],
483
-					$policy
484
-				),
485
-				false
486
-			);
487
-		}
488
-	}
489
-
490
-	/**
491
-	 * Same Site cookie to further mitigate CSRF attacks. This cookie has to
492
-	 * be set in every request if cookies are sent to add a second level of
493
-	 * defense against CSRF.
494
-	 *
495
-	 * If the cookie is not sent this will set the cookie and reload the page.
496
-	 * We use an additional cookie since we want to protect logout CSRF and
497
-	 * also we can't directly interfere with PHP's session mechanism.
498
-	 */
499
-	private static function performSameSiteCookieProtection() {
500
-		$request = \OC::$server->getRequest();
501
-
502
-		// Some user agents are notorious and don't really properly follow HTTP
503
-		// specifications. For those, have an automated opt-out. Since the protection
504
-		// for remote.php is applied in base.php as starting point we need to opt out
505
-		// here.
506
-		$incompatibleUserAgents = [
507
-			// OS X Finder
508
-			'/^WebDAVFS/',
509
-		];
510
-		if($request->isUserAgent($incompatibleUserAgents)) {
511
-			return;
512
-		}
513
-
514
-		if(count($_COOKIE) > 0) {
515
-			$requestUri = $request->getScriptName();
516
-			$processingScript = explode('/', $requestUri);
517
-			$processingScript = $processingScript[count($processingScript)-1];
518
-			// FIXME: In a SAML scenario we don't get any strict or lax cookie
519
-			// send for the ACS endpoint. Since we have some legacy code in Nextcloud
520
-			// (direct PHP files) the enforcement of lax cookies is performed here
521
-			// instead of the middleware.
522
-			//
523
-			// This means we cannot exclude some routes from the cookie validation,
524
-			// which normally is not a problem but is a little bit cumbersome for
525
-			// this use-case.
526
-			// Once the old legacy PHP endpoints have been removed we can move
527
-			// the verification into a middleware and also adds some exemptions.
528
-			//
529
-			// Questions about this code? Ask Lukas ;-)
530
-			$currentUrl = substr(explode('?',$request->getRequestUri(), 2)[0], strlen(\OC::$WEBROOT));
531
-			if($currentUrl === '/index.php/apps/user_saml/saml/acs' || $currentUrl === '/apps/user_saml/saml/acs') {
532
-				return;
533
-			}
534
-			// For the "index.php" endpoint only a lax cookie is required.
535
-			if($processingScript === 'index.php') {
536
-				if(!$request->passesLaxCookieCheck()) {
537
-					self::sendSameSiteCookies();
538
-					header('Location: '.$_SERVER['REQUEST_URI']);
539
-					exit();
540
-				}
541
-			} else {
542
-				// All other endpoints require the lax and the strict cookie
543
-				if(!$request->passesStrictCookieCheck()) {
544
-					self::sendSameSiteCookies();
545
-					// Debug mode gets access to the resources without strict cookie
546
-					// due to the fact that the SabreDAV browser also lives there.
547
-					if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
548
-						http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE);
549
-						exit();
550
-					}
551
-				}
552
-			}
553
-		} elseif(!isset($_COOKIE['nc_sameSiteCookielax']) || !isset($_COOKIE['nc_sameSiteCookiestrict'])) {
554
-			self::sendSameSiteCookies();
555
-		}
556
-	}
557
-
558
-	public static function init() {
559
-		// calculate the root directories
560
-		OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
561
-
562
-		// register autoloader
563
-		$loaderStart = microtime(true);
564
-		require_once __DIR__ . '/autoloader.php';
565
-		self::$loader = new \OC\Autoloader([
566
-			OC::$SERVERROOT . '/lib/private/legacy',
567
-		]);
568
-		if (defined('PHPUNIT_RUN')) {
569
-			self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
570
-		}
571
-		spl_autoload_register(array(self::$loader, 'load'));
572
-		$loaderEnd = microtime(true);
573
-
574
-		self::$CLI = (php_sapi_name() == 'cli');
575
-
576
-		// Add default composer PSR-4 autoloader
577
-		self::$composerAutoloader = require_once OC::$SERVERROOT . '/lib/composer/autoload.php';
578
-
579
-		try {
580
-			self::initPaths();
581
-			// setup 3rdparty autoloader
582
-			$vendorAutoLoad = OC::$SERVERROOT. '/3rdparty/autoload.php';
583
-			if (!file_exists($vendorAutoLoad)) {
584
-				throw new \RuntimeException('Composer autoloader not found, unable to continue. Check the folder "3rdparty". Running "git submodule update --init" will initialize the git submodule that handles the subfolder "3rdparty".');
585
-			}
586
-			require_once $vendorAutoLoad;
587
-
588
-		} catch (\RuntimeException $e) {
589
-			if (!self::$CLI) {
590
-				$claimedProtocol = strtoupper($_SERVER['SERVER_PROTOCOL']);
591
-				$protocol = in_array($claimedProtocol, ['HTTP/1.0', 'HTTP/1.1', 'HTTP/2']) ? $claimedProtocol : 'HTTP/1.1';
592
-				header($protocol . ' ' . OC_Response::STATUS_SERVICE_UNAVAILABLE);
593
-			}
594
-			// we can't use the template error page here, because this needs the
595
-			// DI container which isn't available yet
596
-			print($e->getMessage());
597
-			exit();
598
-		}
599
-
600
-		// setup the basic server
601
-		self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
602
-		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
603
-		\OC::$server->getEventLogger()->start('boot', 'Initialize');
604
-
605
-		// Don't display errors and log them
606
-		error_reporting(E_ALL | E_STRICT);
607
-		@ini_set('display_errors', 0);
608
-		@ini_set('log_errors', 1);
609
-
610
-		if(!date_default_timezone_set('UTC')) {
611
-			throw new \RuntimeException('Could not set timezone to UTC');
612
-		};
613
-
614
-		//try to configure php to enable big file uploads.
615
-		//this doesn´t work always depending on the webserver and php configuration.
616
-		//Let´s try to overwrite some defaults anyway
617
-
618
-		//try to set the maximum execution time to 60min
619
-		if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
620
-			@set_time_limit(3600);
621
-		}
622
-		@ini_set('max_execution_time', 3600);
623
-		@ini_set('max_input_time', 3600);
624
-
625
-		//try to set the maximum filesize to 10G
626
-		@ini_set('upload_max_filesize', '10G');
627
-		@ini_set('post_max_size', '10G');
628
-		@ini_set('file_uploads', '50');
629
-
630
-		self::setRequiredIniValues();
631
-		self::handleAuthHeaders();
632
-		self::registerAutoloaderCache();
633
-
634
-		// initialize intl fallback is necessary
635
-		\Patchwork\Utf8\Bootup::initIntl();
636
-		OC_Util::isSetLocaleWorking();
637
-
638
-		if (!defined('PHPUNIT_RUN')) {
639
-			OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
640
-			$debug = \OC::$server->getConfig()->getSystemValue('debug', false);
641
-			OC\Log\ErrorHandler::register($debug);
642
-		}
643
-
644
-		\OC::$server->getEventLogger()->start('init_session', 'Initialize session');
645
-		OC_App::loadApps(array('session'));
646
-		if (!self::$CLI) {
647
-			self::initSession();
648
-		}
649
-		\OC::$server->getEventLogger()->end('init_session');
650
-		self::checkConfig();
651
-		self::checkInstalled();
652
-
653
-		OC_Response::addSecurityHeaders();
654
-		if(self::$server->getRequest()->getServerProtocol() === 'https') {
655
-			ini_set('session.cookie_secure', true);
656
-		}
657
-
658
-		self::performSameSiteCookieProtection();
659
-
660
-		if (!defined('OC_CONSOLE')) {
661
-			$errors = OC_Util::checkServer(\OC::$server->getSystemConfig());
662
-			if (count($errors) > 0) {
663
-				if (self::$CLI) {
664
-					// Convert l10n string into regular string for usage in database
665
-					$staticErrors = [];
666
-					foreach ($errors as $error) {
667
-						echo $error['error'] . "\n";
668
-						echo $error['hint'] . "\n\n";
669
-						$staticErrors[] = [
670
-							'error' => (string)$error['error'],
671
-							'hint' => (string)$error['hint'],
672
-						];
673
-					}
674
-
675
-					try {
676
-						\OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
677
-					} catch (\Exception $e) {
678
-						echo('Writing to database failed');
679
-					}
680
-					exit(1);
681
-				} else {
682
-					OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
683
-					OC_Util::addStyle('guest');
684
-					OC_Template::printGuestPage('', 'error', array('errors' => $errors));
685
-					exit;
686
-				}
687
-			} elseif (self::$CLI && \OC::$server->getConfig()->getSystemValue('installed', false)) {
688
-				\OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
689
-			}
690
-		}
691
-		//try to set the session lifetime
692
-		$sessionLifeTime = self::getSessionLifeTime();
693
-		@ini_set('gc_maxlifetime', (string)$sessionLifeTime);
694
-
695
-		$systemConfig = \OC::$server->getSystemConfig();
696
-
697
-		// User and Groups
698
-		if (!$systemConfig->getValue("installed", false)) {
699
-			self::$server->getSession()->set('user_id', '');
700
-		}
701
-
702
-		OC_User::useBackend(new \OC\User\Database());
703
-		\OC::$server->getGroupManager()->addBackend(new \OC\Group\Database());
704
-
705
-		// Subscribe to the hook
706
-		\OCP\Util::connectHook(
707
-			'\OCA\Files_Sharing\API\Server2Server',
708
-			'preLoginNameUsedAsUserName',
709
-			'\OC\User\Database',
710
-			'preLoginNameUsedAsUserName'
711
-		);
712
-
713
-		//setup extra user backends
714
-		if (!self::checkUpgrade(false)) {
715
-			OC_User::setupBackends();
716
-		} else {
717
-			// Run upgrades in incognito mode
718
-			OC_User::setIncognitoMode(true);
719
-		}
720
-
721
-		self::registerCacheHooks();
722
-		self::registerFilesystemHooks();
723
-		self::registerShareHooks();
724
-		self::registerLogRotate();
725
-		self::registerEncryptionWrapper();
726
-		self::registerEncryptionHooks();
727
-		self::registerAccountHooks();
728
-		self::registerSettingsHooks();
729
-
730
-		//make sure temporary files are cleaned up
731
-		$tmpManager = \OC::$server->getTempManager();
732
-		register_shutdown_function(array($tmpManager, 'clean'));
733
-		$lockProvider = \OC::$server->getLockingProvider();
734
-		register_shutdown_function(array($lockProvider, 'releaseAll'));
735
-
736
-		// Check whether the sample configuration has been copied
737
-		if($systemConfig->getValue('copied_sample_config', false)) {
738
-			$l = \OC::$server->getL10N('lib');
739
-			header('HTTP/1.1 503 Service Temporarily Unavailable');
740
-			header('Status: 503 Service Temporarily Unavailable');
741
-			OC_Template::printErrorPage(
742
-				$l->t('Sample configuration detected'),
743
-				$l->t('It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php')
744
-			);
745
-			return;
746
-		}
747
-
748
-		$request = \OC::$server->getRequest();
749
-		$host = $request->getInsecureServerHost();
750
-		/**
751
-		 * if the host passed in headers isn't trusted
752
-		 * FIXME: Should not be in here at all :see_no_evil:
753
-		 */
754
-		if (!OC::$CLI
755
-			// overwritehost is always trusted, workaround to not have to make
756
-			// \OC\AppFramework\Http\Request::getOverwriteHost public
757
-			&& self::$server->getConfig()->getSystemValue('overwritehost') === ''
758
-			&& !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host)
759
-			&& self::$server->getConfig()->getSystemValue('installed', false)
760
-		) {
761
-			// Allow access to CSS resources
762
-			$isScssRequest = false;
763
-			if(strpos($request->getPathInfo(), '/css/') === 0) {
764
-				$isScssRequest = true;
765
-			}
766
-
767
-			if (!$isScssRequest) {
768
-				header('HTTP/1.1 400 Bad Request');
769
-				header('Status: 400 Bad Request');
770
-
771
-				\OC::$server->getLogger()->warning(
772
-					'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
773
-					[
774
-						'app' => 'core',
775
-						'remoteAddress' => $request->getRemoteAddress(),
776
-						'host' => $host,
777
-					]
778
-				);
779
-
780
-				$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
781
-				$tmpl->assign('domain', $host);
782
-				$tmpl->printPage();
783
-
784
-				exit();
785
-			}
786
-		}
787
-		\OC::$server->getEventLogger()->end('boot');
788
-	}
789
-
790
-	/**
791
-	 * register hooks for the cache
792
-	 */
793
-	public static function registerCacheHooks() {
794
-		//don't try to do this before we are properly setup
795
-		if (\OC::$server->getSystemConfig()->getValue('installed', false) && !self::checkUpgrade(false)) {
796
-
797
-			// NOTE: This will be replaced to use OCP
798
-			$userSession = self::$server->getUserSession();
799
-			$userSession->listen('\OC\User', 'postLogin', function () {
800
-				try {
801
-					$cache = new \OC\Cache\File();
802
-					$cache->gc();
803
-				} catch (\OC\ServerNotAvailableException $e) {
804
-					// not a GC exception, pass it on
805
-					throw $e;
806
-				} catch (\Exception $e) {
807
-					// a GC exception should not prevent users from using OC,
808
-					// so log the exception
809
-					\OC::$server->getLogger()->warning('Exception when running cache gc: ' . $e->getMessage(), array('app' => 'core'));
810
-				}
811
-			});
812
-		}
813
-	}
814
-
815
-	public static function registerSettingsHooks() {
816
-		$dispatcher = \OC::$server->getEventDispatcher();
817
-		$dispatcher->addListener(OCP\App\ManagerEvent::EVENT_APP_DISABLE, function($event) {
818
-			/** @var \OCP\App\ManagerEvent $event */
819
-			\OC::$server->getSettingsManager()->onAppDisabled($event->getAppID());
820
-		});
821
-		$dispatcher->addListener(OCP\App\ManagerEvent::EVENT_APP_UPDATE, function($event) {
822
-			/** @var \OCP\App\ManagerEvent $event */
823
-			$jobList = \OC::$server->getJobList();
824
-			$job = 'OC\\Settings\\RemoveOrphaned';
825
-			if(!($jobList->has($job, null))) {
826
-				$jobList->add($job);
827
-			}
828
-		});
829
-	}
830
-
831
-	private static function registerEncryptionWrapper() {
832
-		$manager = self::$server->getEncryptionManager();
833
-		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
834
-	}
835
-
836
-	private static function registerEncryptionHooks() {
837
-		$enabled = self::$server->getEncryptionManager()->isEnabled();
838
-		if ($enabled) {
839
-			\OCP\Util::connectHook('OCP\Share', 'post_shared', 'OC\Encryption\HookManager', 'postShared');
840
-			\OCP\Util::connectHook('OCP\Share', 'post_unshare', 'OC\Encryption\HookManager', 'postUnshared');
841
-			\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OC\Encryption\HookManager', 'postRename');
842
-			\OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', 'OC\Encryption\HookManager', 'postRestore');
843
-		}
844
-	}
845
-
846
-	private static function registerAccountHooks() {
847
-		$hookHandler = new \OC\Accounts\Hooks(\OC::$server->getLogger());
848
-		\OCP\Util::connectHook('OC_User', 'changeUser', $hookHandler, 'changeUserHook');
849
-	}
850
-
851
-	/**
852
-	 * register hooks for the cache
853
-	 */
854
-	public static function registerLogRotate() {
855
-		$systemConfig = \OC::$server->getSystemConfig();
856
-		if ($systemConfig->getValue('installed', false) && $systemConfig->getValue('log_rotate_size', false) && !self::checkUpgrade(false)) {
857
-			//don't try to do this before we are properly setup
858
-			//use custom logfile path if defined, otherwise use default of nextcloud.log in data directory
859
-			\OC::$server->getJobList()->add('OC\Log\Rotate');
860
-		}
861
-	}
862
-
863
-	/**
864
-	 * register hooks for the filesystem
865
-	 */
866
-	public static function registerFilesystemHooks() {
867
-		// Check for blacklisted files
868
-		OC_Hook::connect('OC_Filesystem', 'write', 'OC\Files\Filesystem', 'isBlacklisted');
869
-		OC_Hook::connect('OC_Filesystem', 'rename', 'OC\Files\Filesystem', 'isBlacklisted');
870
-	}
871
-
872
-	/**
873
-	 * register hooks for sharing
874
-	 */
875
-	public static function registerShareHooks() {
876
-		if (\OC::$server->getSystemConfig()->getValue('installed')) {
877
-			OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share20\Hooks', 'post_deleteUser');
878
-			OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share20\Hooks', 'post_removeFromGroup');
879
-			OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share20\Hooks', 'post_deleteGroup');
880
-		}
881
-	}
882
-
883
-	protected static function registerAutoloaderCache() {
884
-		// The class loader takes an optional low-latency cache, which MUST be
885
-		// namespaced. The instanceid is used for namespacing, but might be
886
-		// unavailable at this point. Furthermore, it might not be possible to
887
-		// generate an instanceid via \OC_Util::getInstanceId() because the
888
-		// config file may not be writable. As such, we only register a class
889
-		// loader cache if instanceid is available without trying to create one.
890
-		$instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
891
-		if ($instanceId) {
892
-			try {
893
-				$memcacheFactory = \OC::$server->getMemCacheFactory();
894
-				self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader'));
895
-			} catch (\Exception $ex) {
896
-			}
897
-		}
898
-	}
899
-
900
-	/**
901
-	 * Handle the request
902
-	 */
903
-	public static function handleRequest() {
904
-
905
-		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
906
-		$systemConfig = \OC::$server->getSystemConfig();
907
-		// load all the classpaths from the enabled apps so they are available
908
-		// in the routing files of each app
909
-		OC::loadAppClassPaths();
910
-
911
-		// Check if Nextcloud is installed or in maintenance (update) mode
912
-		if (!$systemConfig->getValue('installed', false)) {
913
-			\OC::$server->getSession()->clear();
914
-			$setupHelper = new OC\Setup(\OC::$server->getSystemConfig(), \OC::$server->getIniWrapper(),
915
-				\OC::$server->getL10N('lib'), \OC::$server->query(\OCP\Defaults::class), \OC::$server->getLogger(),
916
-				\OC::$server->getSecureRandom());
917
-			$controller = new OC\Core\Controller\SetupController($setupHelper);
918
-			$controller->run($_POST);
919
-			exit();
920
-		}
921
-
922
-		$request = \OC::$server->getRequest();
923
-		$requestPath = $request->getRawPathInfo();
924
-		if ($requestPath === '/heartbeat') {
925
-			return;
926
-		}
927
-		if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
928
-			self::checkMaintenanceMode();
929
-			self::checkUpgrade();
930
-		}
931
-
932
-		// emergency app disabling
933
-		if ($requestPath === '/disableapp'
934
-			&& $request->getMethod() === 'POST'
935
-			&& ((string)$request->getParam('appid')) !== ''
936
-		) {
937
-			\OCP\JSON::callCheck();
938
-			\OCP\JSON::checkAdminUser();
939
-			$appId = (string)$request->getParam('appid');
940
-			$appId = \OC_App::cleanAppId($appId);
941
-
942
-			\OC_App::disable($appId);
943
-			\OC_JSON::success();
944
-			exit();
945
-		}
946
-
947
-		// Always load authentication apps
948
-		OC_App::loadApps(['authentication']);
949
-
950
-		// Load minimum set of apps
951
-		if (!self::checkUpgrade(false)
952
-			&& !$systemConfig->getValue('maintenance', false)) {
953
-			// For logged-in users: Load everything
954
-			if(\OC::$server->getUserSession()->isLoggedIn()) {
955
-				OC_App::loadApps();
956
-			} else {
957
-				// For guests: Load only filesystem and logging
958
-				OC_App::loadApps(array('filesystem', 'logging'));
959
-				self::handleLogin($request);
960
-			}
961
-		}
962
-
963
-		if (!self::$CLI) {
964
-			try {
965
-				if (!$systemConfig->getValue('maintenance', false) && !self::checkUpgrade(false)) {
966
-					OC_App::loadApps(array('filesystem', 'logging'));
967
-					OC_App::loadApps();
968
-				}
969
-				OC_Util::setupFS();
970
-				OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
971
-				return;
972
-			} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
973
-				//header('HTTP/1.0 404 Not Found');
974
-			} catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
975
-				OC_Response::setStatus(405);
976
-				return;
977
-			}
978
-		}
979
-
980
-		// Handle WebDAV
981
-		if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
982
-			// not allowed any more to prevent people
983
-			// mounting this root directly.
984
-			// Users need to mount remote.php/webdav instead.
985
-			header('HTTP/1.1 405 Method Not Allowed');
986
-			header('Status: 405 Method Not Allowed');
987
-			return;
988
-		}
989
-
990
-		// Someone is logged in
991
-		if (\OC::$server->getUserSession()->isLoggedIn()) {
992
-			OC_App::loadApps();
993
-			OC_User::setupBackends();
994
-			OC_Util::setupFS();
995
-			// FIXME
996
-			// Redirect to default application
997
-			OC_Util::redirectToDefaultPage();
998
-		} else {
999
-			// Not handled and not logged in
1000
-			header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
1001
-		}
1002
-	}
1003
-
1004
-	/**
1005
-	 * Check login: apache auth, auth token, basic auth
1006
-	 *
1007
-	 * @param OCP\IRequest $request
1008
-	 * @return boolean
1009
-	 */
1010
-	static function handleLogin(OCP\IRequest $request) {
1011
-		$userSession = self::$server->getUserSession();
1012
-		if (OC_User::handleApacheAuth()) {
1013
-			return true;
1014
-		}
1015
-		if ($userSession->tryTokenLogin($request)) {
1016
-			return true;
1017
-		}
1018
-		if (isset($_COOKIE['nc_username'])
1019
-			&& isset($_COOKIE['nc_token'])
1020
-			&& isset($_COOKIE['nc_session_id'])
1021
-			&& $userSession->loginWithCookie($_COOKIE['nc_username'], $_COOKIE['nc_token'], $_COOKIE['nc_session_id'])) {
1022
-			return true;
1023
-		}
1024
-		if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
1025
-			return true;
1026
-		}
1027
-		return false;
1028
-	}
1029
-
1030
-	protected static function handleAuthHeaders() {
1031
-		//copy http auth headers for apache+php-fcgid work around
1032
-		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
1033
-			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
1034
-		}
1035
-
1036
-		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
1037
-		$vars = array(
1038
-			'HTTP_AUTHORIZATION', // apache+php-cgi work around
1039
-			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
1040
-		);
1041
-		foreach ($vars as $var) {
1042
-			if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
1043
-				list($name, $password) = explode(':', base64_decode($matches[1]), 2);
1044
-				$_SERVER['PHP_AUTH_USER'] = $name;
1045
-				$_SERVER['PHP_AUTH_PW'] = $password;
1046
-				break;
1047
-			}
1048
-		}
1049
-	}
62
+    /**
63
+     * Associative array for autoloading. classname => filename
64
+     */
65
+    public static $CLASSPATH = array();
66
+    /**
67
+     * The installation path for Nextcloud  on the server (e.g. /srv/http/nextcloud)
68
+     */
69
+    public static $SERVERROOT = '';
70
+    /**
71
+     * the current request path relative to the Nextcloud root (e.g. files/index.php)
72
+     */
73
+    private static $SUBURI = '';
74
+    /**
75
+     * the Nextcloud root path for http requests (e.g. nextcloud/)
76
+     */
77
+    public static $WEBROOT = '';
78
+    /**
79
+     * The installation path array of the apps folder on the server (e.g. /srv/http/nextcloud) 'path' and
80
+     * web path in 'url'
81
+     */
82
+    public static $APPSROOTS = array();
83
+
84
+    /**
85
+     * @var string
86
+     */
87
+    public static $configDir;
88
+
89
+    /**
90
+     * requested app
91
+     */
92
+    public static $REQUESTEDAPP = '';
93
+
94
+    /**
95
+     * check if Nextcloud runs in cli mode
96
+     */
97
+    public static $CLI = false;
98
+
99
+    /**
100
+     * @var \OC\Autoloader $loader
101
+     */
102
+    public static $loader = null;
103
+
104
+    /** @var \Composer\Autoload\ClassLoader $composerAutoloader */
105
+    public static $composerAutoloader = null;
106
+
107
+    /**
108
+     * @var \OC\Server
109
+     */
110
+    public static $server = null;
111
+
112
+    /**
113
+     * @var \OC\Config
114
+     */
115
+    private static $config = null;
116
+
117
+    /**
118
+     * @throws \RuntimeException when the 3rdparty directory is missing or
119
+     * the app path list is empty or contains an invalid path
120
+     */
121
+    public static function initPaths() {
122
+        if(defined('PHPUNIT_CONFIG_DIR')) {
123
+            self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/';
124
+        } elseif(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) {
125
+            self::$configDir = OC::$SERVERROOT . '/tests/config/';
126
+        } elseif($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
127
+            self::$configDir = rtrim($dir, '/') . '/';
128
+        } else {
129
+            self::$configDir = OC::$SERVERROOT . '/config/';
130
+        }
131
+        self::$config = new \OC\Config(self::$configDir);
132
+
133
+        OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
134
+        /**
135
+         * FIXME: The following lines are required because we can't yet instantiiate
136
+         *        \OC::$server->getRequest() since \OC::$server does not yet exist.
137
+         */
138
+        $params = [
139
+            'server' => [
140
+                'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'],
141
+                'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'],
142
+            ],
143
+        ];
144
+        $fakeRequest = new \OC\AppFramework\Http\Request($params, null, new \OC\AllConfig(new \OC\SystemConfig(self::$config)));
145
+        $scriptName = $fakeRequest->getScriptName();
146
+        if (substr($scriptName, -1) == '/') {
147
+            $scriptName .= 'index.php';
148
+            //make sure suburi follows the same rules as scriptName
149
+            if (substr(OC::$SUBURI, -9) != 'index.php') {
150
+                if (substr(OC::$SUBURI, -1) != '/') {
151
+                    OC::$SUBURI = OC::$SUBURI . '/';
152
+                }
153
+                OC::$SUBURI = OC::$SUBURI . 'index.php';
154
+            }
155
+        }
156
+
157
+
158
+        if (OC::$CLI) {
159
+            OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
160
+        } else {
161
+            if (substr($scriptName, 0 - strlen(OC::$SUBURI)) === OC::$SUBURI) {
162
+                OC::$WEBROOT = substr($scriptName, 0, 0 - strlen(OC::$SUBURI));
163
+
164
+                if (OC::$WEBROOT != '' && OC::$WEBROOT[0] !== '/') {
165
+                    OC::$WEBROOT = '/' . OC::$WEBROOT;
166
+                }
167
+            } else {
168
+                // The scriptName is not ending with OC::$SUBURI
169
+                // This most likely means that we are calling from CLI.
170
+                // However some cron jobs still need to generate
171
+                // a web URL, so we use overwritewebroot as a fallback.
172
+                OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
173
+            }
174
+
175
+            // Resolve /nextcloud to /nextcloud/ to ensure to always have a trailing
176
+            // slash which is required by URL generation.
177
+            if($_SERVER['REQUEST_URI'] === \OC::$WEBROOT &&
178
+                    substr($_SERVER['REQUEST_URI'], -1) !== '/') {
179
+                header('Location: '.\OC::$WEBROOT.'/');
180
+                exit();
181
+            }
182
+        }
183
+
184
+        // search the apps folder
185
+        $config_paths = self::$config->getValue('apps_paths', array());
186
+        if (!empty($config_paths)) {
187
+            foreach ($config_paths as $paths) {
188
+                if (isset($paths['url']) && isset($paths['path'])) {
189
+                    $paths['url'] = rtrim($paths['url'], '/');
190
+                    $paths['path'] = rtrim($paths['path'], '/');
191
+                    OC::$APPSROOTS[] = $paths;
192
+                }
193
+            }
194
+        } elseif (file_exists(OC::$SERVERROOT . '/apps')) {
195
+            OC::$APPSROOTS[] = array('path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true);
196
+        } elseif (file_exists(OC::$SERVERROOT . '/../apps')) {
197
+            OC::$APPSROOTS[] = array(
198
+                'path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps',
199
+                'url' => '/apps',
200
+                'writable' => true
201
+            );
202
+        }
203
+
204
+        if (empty(OC::$APPSROOTS)) {
205
+            throw new \RuntimeException('apps directory not found! Please put the Nextcloud apps folder in the Nextcloud folder'
206
+                . ' or the folder above. You can also configure the location in the config.php file.');
207
+        }
208
+        $paths = array();
209
+        foreach (OC::$APPSROOTS as $path) {
210
+            $paths[] = $path['path'];
211
+            if (!is_dir($path['path'])) {
212
+                throw new \RuntimeException(sprintf('App directory "%s" not found! Please put the Nextcloud apps folder in the'
213
+                    . ' Nextcloud folder or the folder above. You can also configure the location in the'
214
+                    . ' config.php file.', $path['path']));
215
+            }
216
+        }
217
+
218
+        // set the right include path
219
+        set_include_path(
220
+            implode(PATH_SEPARATOR, $paths)
221
+        );
222
+    }
223
+
224
+    public static function checkConfig() {
225
+        $l = \OC::$server->getL10N('lib');
226
+
227
+        // Create config if it does not already exist
228
+        $configFilePath = self::$configDir .'/config.php';
229
+        if(!file_exists($configFilePath)) {
230
+            @touch($configFilePath);
231
+        }
232
+
233
+        // Check if config is writable
234
+        $configFileWritable = is_writable($configFilePath);
235
+        if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled()
236
+            || !$configFileWritable && self::checkUpgrade(false)) {
237
+
238
+            $urlGenerator = \OC::$server->getURLGenerator();
239
+
240
+            if (self::$CLI) {
241
+                echo $l->t('Cannot write into "config" directory!')."\n";
242
+                echo $l->t('This can usually be fixed by giving the webserver write access to the config directory')."\n";
243
+                echo "\n";
244
+                echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-dir_permissions') ])."\n";
245
+                exit;
246
+            } else {
247
+                OC_Template::printErrorPage(
248
+                    $l->t('Cannot write into "config" directory!'),
249
+                    $l->t('This can usually be fixed by '
250
+                    . '%sgiving the webserver write access to the config directory%s.',
251
+                        array('<a href="' . $urlGenerator->linkToDocs('admin-dir_permissions') . '" target="_blank" rel="noreferrer">', '</a>'))
252
+                );
253
+            }
254
+        }
255
+    }
256
+
257
+    public static function checkInstalled() {
258
+        if (defined('OC_CONSOLE')) {
259
+            return;
260
+        }
261
+        // Redirect to installer if not installed
262
+        if (!\OC::$server->getSystemConfig()->getValue('installed', false) && OC::$SUBURI !== '/index.php' && OC::$SUBURI !== '/status.php') {
263
+            if (OC::$CLI) {
264
+                throw new Exception('Not installed');
265
+            } else {
266
+                $url = OC::$WEBROOT . '/index.php';
267
+                header('Location: ' . $url);
268
+            }
269
+            exit();
270
+        }
271
+    }
272
+
273
+    public static function checkMaintenanceMode() {
274
+        // Allow ajax update script to execute without being stopped
275
+        if (\OC::$server->getSystemConfig()->getValue('maintenance', false) && OC::$SUBURI != '/core/ajax/update.php') {
276
+            // send http status 503
277
+            header('HTTP/1.1 503 Service Temporarily Unavailable');
278
+            header('Status: 503 Service Temporarily Unavailable');
279
+            header('Retry-After: 120');
280
+
281
+            // render error page
282
+            $template = new OC_Template('', 'update.user', 'guest');
283
+            OC_Util::addScript('maintenance-check');
284
+            $template->printPage();
285
+            die();
286
+        }
287
+    }
288
+
289
+    /**
290
+     * Checks if the version requires an update and shows
291
+     * @param bool $showTemplate Whether an update screen should get shown
292
+     * @return bool|void
293
+     */
294
+    public static function checkUpgrade($showTemplate = true) {
295
+        if (\OCP\Util::needUpgrade()) {
296
+            $systemConfig = \OC::$server->getSystemConfig();
297
+            if ($showTemplate && !$systemConfig->getValue('maintenance', false)) {
298
+                self::printUpgradePage();
299
+                exit();
300
+            } else {
301
+                return true;
302
+            }
303
+        }
304
+        return false;
305
+    }
306
+
307
+    /**
308
+     * Prints the upgrade page
309
+     */
310
+    private static function printUpgradePage() {
311
+        $systemConfig = \OC::$server->getSystemConfig();
312
+
313
+        $disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false);
314
+        $tooBig = false;
315
+        if (!$disableWebUpdater) {
316
+            $apps = \OC::$server->getAppManager();
317
+            $tooBig = $apps->isInstalled('user_ldap') || $apps->isInstalled('user_shibboleth');
318
+            if (!$tooBig) {
319
+                // count users
320
+                $stats = \OC::$server->getUserManager()->countUsers();
321
+                $totalUsers = array_sum($stats);
322
+                $tooBig = ($totalUsers > 50);
323
+            }
324
+        }
325
+        if ($disableWebUpdater || $tooBig) {
326
+            // send http status 503
327
+            header('HTTP/1.1 503 Service Temporarily Unavailable');
328
+            header('Status: 503 Service Temporarily Unavailable');
329
+            header('Retry-After: 120');
330
+
331
+            // render error page
332
+            $template = new OC_Template('', 'update.use-cli', 'guest');
333
+            $template->assign('productName', 'nextcloud'); // for now
334
+            $template->assign('version', OC_Util::getVersionString());
335
+            $template->assign('tooBig', $tooBig);
336
+
337
+            $template->printPage();
338
+            die();
339
+        }
340
+
341
+        // check whether this is a core update or apps update
342
+        $installedVersion = $systemConfig->getValue('version', '0.0.0');
343
+        $currentVersion = implode('.', \OCP\Util::getVersion());
344
+
345
+        // if not a core upgrade, then it's apps upgrade
346
+        $isAppsOnlyUpgrade = (version_compare($currentVersion, $installedVersion, '='));
347
+
348
+        $oldTheme = $systemConfig->getValue('theme');
349
+        $systemConfig->setValue('theme', '');
350
+        OC_Util::addScript('config'); // needed for web root
351
+        OC_Util::addScript('update');
352
+
353
+        /** @var \OC\App\AppManager $appManager */
354
+        $appManager = \OC::$server->getAppManager();
355
+
356
+        $tmpl = new OC_Template('', 'update.admin', 'guest');
357
+        $tmpl->assign('version', OC_Util::getVersionString());
358
+        $tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade);
359
+
360
+        // get third party apps
361
+        $ocVersion = \OCP\Util::getVersion();
362
+        $incompatibleApps = $appManager->getIncompatibleApps($ocVersion);
363
+        $incompatibleShippedApps = [];
364
+        foreach ($incompatibleApps as $appInfo) {
365
+            if ($appManager->isShipped($appInfo['id'])) {
366
+                $incompatibleShippedApps[] = $appInfo['name'] . ' (' . $appInfo['id'] . ')';
367
+            }
368
+        }
369
+
370
+        if (!empty($incompatibleShippedApps)) {
371
+            $l = \OC::$server->getL10N('core');
372
+            $hint = $l->t('The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server.', [implode(', ', $incompatibleShippedApps)]);
373
+            throw new \OC\HintException('The files of the app ' . implode(', ', $incompatibleShippedApps) . ' were not replaced correctly. Make sure it is a version compatible with the server.', $hint);
374
+        }
375
+
376
+        $tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
377
+        $tmpl->assign('incompatibleAppsList', $incompatibleApps);
378
+        $tmpl->assign('productName', 'Nextcloud'); // for now
379
+        $tmpl->assign('oldTheme', $oldTheme);
380
+        $tmpl->printPage();
381
+    }
382
+
383
+    public static function initSession() {
384
+        // prevents javascript from accessing php session cookies
385
+        ini_set('session.cookie_httponly', true);
386
+
387
+        // set the cookie path to the Nextcloud directory
388
+        $cookie_path = OC::$WEBROOT ? : '/';
389
+        ini_set('session.cookie_path', $cookie_path);
390
+
391
+        // Let the session name be changed in the initSession Hook
392
+        $sessionName = OC_Util::getInstanceId();
393
+
394
+        try {
395
+            // Allow session apps to create a custom session object
396
+            $useCustomSession = false;
397
+            $session = self::$server->getSession();
398
+            OC_Hook::emit('OC', 'initSession', array('session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession));
399
+            if (!$useCustomSession) {
400
+                // set the session name to the instance id - which is unique
401
+                $session = new \OC\Session\Internal($sessionName);
402
+            }
403
+
404
+            $cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
405
+            $session = $cryptoWrapper->wrapSession($session);
406
+            self::$server->setSession($session);
407
+
408
+            // if session can't be started break with http 500 error
409
+        } catch (Exception $e) {
410
+            \OCP\Util::logException('base', $e);
411
+            //show the user a detailed error page
412
+            OC_Response::setStatus(OC_Response::STATUS_INTERNAL_SERVER_ERROR);
413
+            OC_Template::printExceptionErrorPage($e);
414
+            die();
415
+        }
416
+
417
+        $sessionLifeTime = self::getSessionLifeTime();
418
+
419
+        // session timeout
420
+        if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
421
+            if (isset($_COOKIE[session_name()])) {
422
+                setcookie(session_name(), null, -1, self::$WEBROOT ? : '/');
423
+            }
424
+            \OC::$server->getUserSession()->logout();
425
+        }
426
+
427
+        $session->set('LAST_ACTIVITY', time());
428
+    }
429
+
430
+    /**
431
+     * @return string
432
+     */
433
+    private static function getSessionLifeTime() {
434
+        return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
435
+    }
436
+
437
+    public static function loadAppClassPaths() {
438
+        foreach (OC_App::getEnabledApps() as $app) {
439
+            $appPath = OC_App::getAppPath($app);
440
+            if ($appPath === false) {
441
+                continue;
442
+            }
443
+
444
+            $file = $appPath . '/appinfo/classpath.php';
445
+            if (file_exists($file)) {
446
+                require_once $file;
447
+            }
448
+        }
449
+    }
450
+
451
+    /**
452
+     * Try to set some values to the required Nextcloud default
453
+     */
454
+    public static function setRequiredIniValues() {
455
+        @ini_set('default_charset', 'UTF-8');
456
+        @ini_set('gd.jpeg_ignore_warning', 1);
457
+    }
458
+
459
+    /**
460
+     * Send the same site cookies
461
+     */
462
+    private static function sendSameSiteCookies() {
463
+        $cookieParams = session_get_cookie_params();
464
+        $secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
465
+        $policies = [
466
+            'lax',
467
+            'strict',
468
+        ];
469
+
470
+        // Append __Host to the cookie if it meets the requirements
471
+        $cookiePrefix = '';
472
+        if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
473
+            $cookiePrefix = '__Host-';
474
+        }
475
+
476
+        foreach($policies as $policy) {
477
+            header(
478
+                sprintf(
479
+                    'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
480
+                    $cookiePrefix,
481
+                    $policy,
482
+                    $cookieParams['path'],
483
+                    $policy
484
+                ),
485
+                false
486
+            );
487
+        }
488
+    }
489
+
490
+    /**
491
+     * Same Site cookie to further mitigate CSRF attacks. This cookie has to
492
+     * be set in every request if cookies are sent to add a second level of
493
+     * defense against CSRF.
494
+     *
495
+     * If the cookie is not sent this will set the cookie and reload the page.
496
+     * We use an additional cookie since we want to protect logout CSRF and
497
+     * also we can't directly interfere with PHP's session mechanism.
498
+     */
499
+    private static function performSameSiteCookieProtection() {
500
+        $request = \OC::$server->getRequest();
501
+
502
+        // Some user agents are notorious and don't really properly follow HTTP
503
+        // specifications. For those, have an automated opt-out. Since the protection
504
+        // for remote.php is applied in base.php as starting point we need to opt out
505
+        // here.
506
+        $incompatibleUserAgents = [
507
+            // OS X Finder
508
+            '/^WebDAVFS/',
509
+        ];
510
+        if($request->isUserAgent($incompatibleUserAgents)) {
511
+            return;
512
+        }
513
+
514
+        if(count($_COOKIE) > 0) {
515
+            $requestUri = $request->getScriptName();
516
+            $processingScript = explode('/', $requestUri);
517
+            $processingScript = $processingScript[count($processingScript)-1];
518
+            // FIXME: In a SAML scenario we don't get any strict or lax cookie
519
+            // send for the ACS endpoint. Since we have some legacy code in Nextcloud
520
+            // (direct PHP files) the enforcement of lax cookies is performed here
521
+            // instead of the middleware.
522
+            //
523
+            // This means we cannot exclude some routes from the cookie validation,
524
+            // which normally is not a problem but is a little bit cumbersome for
525
+            // this use-case.
526
+            // Once the old legacy PHP endpoints have been removed we can move
527
+            // the verification into a middleware and also adds some exemptions.
528
+            //
529
+            // Questions about this code? Ask Lukas ;-)
530
+            $currentUrl = substr(explode('?',$request->getRequestUri(), 2)[0], strlen(\OC::$WEBROOT));
531
+            if($currentUrl === '/index.php/apps/user_saml/saml/acs' || $currentUrl === '/apps/user_saml/saml/acs') {
532
+                return;
533
+            }
534
+            // For the "index.php" endpoint only a lax cookie is required.
535
+            if($processingScript === 'index.php') {
536
+                if(!$request->passesLaxCookieCheck()) {
537
+                    self::sendSameSiteCookies();
538
+                    header('Location: '.$_SERVER['REQUEST_URI']);
539
+                    exit();
540
+                }
541
+            } else {
542
+                // All other endpoints require the lax and the strict cookie
543
+                if(!$request->passesStrictCookieCheck()) {
544
+                    self::sendSameSiteCookies();
545
+                    // Debug mode gets access to the resources without strict cookie
546
+                    // due to the fact that the SabreDAV browser also lives there.
547
+                    if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
548
+                        http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE);
549
+                        exit();
550
+                    }
551
+                }
552
+            }
553
+        } elseif(!isset($_COOKIE['nc_sameSiteCookielax']) || !isset($_COOKIE['nc_sameSiteCookiestrict'])) {
554
+            self::sendSameSiteCookies();
555
+        }
556
+    }
557
+
558
+    public static function init() {
559
+        // calculate the root directories
560
+        OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
561
+
562
+        // register autoloader
563
+        $loaderStart = microtime(true);
564
+        require_once __DIR__ . '/autoloader.php';
565
+        self::$loader = new \OC\Autoloader([
566
+            OC::$SERVERROOT . '/lib/private/legacy',
567
+        ]);
568
+        if (defined('PHPUNIT_RUN')) {
569
+            self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
570
+        }
571
+        spl_autoload_register(array(self::$loader, 'load'));
572
+        $loaderEnd = microtime(true);
573
+
574
+        self::$CLI = (php_sapi_name() == 'cli');
575
+
576
+        // Add default composer PSR-4 autoloader
577
+        self::$composerAutoloader = require_once OC::$SERVERROOT . '/lib/composer/autoload.php';
578
+
579
+        try {
580
+            self::initPaths();
581
+            // setup 3rdparty autoloader
582
+            $vendorAutoLoad = OC::$SERVERROOT. '/3rdparty/autoload.php';
583
+            if (!file_exists($vendorAutoLoad)) {
584
+                throw new \RuntimeException('Composer autoloader not found, unable to continue. Check the folder "3rdparty". Running "git submodule update --init" will initialize the git submodule that handles the subfolder "3rdparty".');
585
+            }
586
+            require_once $vendorAutoLoad;
587
+
588
+        } catch (\RuntimeException $e) {
589
+            if (!self::$CLI) {
590
+                $claimedProtocol = strtoupper($_SERVER['SERVER_PROTOCOL']);
591
+                $protocol = in_array($claimedProtocol, ['HTTP/1.0', 'HTTP/1.1', 'HTTP/2']) ? $claimedProtocol : 'HTTP/1.1';
592
+                header($protocol . ' ' . OC_Response::STATUS_SERVICE_UNAVAILABLE);
593
+            }
594
+            // we can't use the template error page here, because this needs the
595
+            // DI container which isn't available yet
596
+            print($e->getMessage());
597
+            exit();
598
+        }
599
+
600
+        // setup the basic server
601
+        self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
602
+        \OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
603
+        \OC::$server->getEventLogger()->start('boot', 'Initialize');
604
+
605
+        // Don't display errors and log them
606
+        error_reporting(E_ALL | E_STRICT);
607
+        @ini_set('display_errors', 0);
608
+        @ini_set('log_errors', 1);
609
+
610
+        if(!date_default_timezone_set('UTC')) {
611
+            throw new \RuntimeException('Could not set timezone to UTC');
612
+        };
613
+
614
+        //try to configure php to enable big file uploads.
615
+        //this doesn´t work always depending on the webserver and php configuration.
616
+        //Let´s try to overwrite some defaults anyway
617
+
618
+        //try to set the maximum execution time to 60min
619
+        if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
620
+            @set_time_limit(3600);
621
+        }
622
+        @ini_set('max_execution_time', 3600);
623
+        @ini_set('max_input_time', 3600);
624
+
625
+        //try to set the maximum filesize to 10G
626
+        @ini_set('upload_max_filesize', '10G');
627
+        @ini_set('post_max_size', '10G');
628
+        @ini_set('file_uploads', '50');
629
+
630
+        self::setRequiredIniValues();
631
+        self::handleAuthHeaders();
632
+        self::registerAutoloaderCache();
633
+
634
+        // initialize intl fallback is necessary
635
+        \Patchwork\Utf8\Bootup::initIntl();
636
+        OC_Util::isSetLocaleWorking();
637
+
638
+        if (!defined('PHPUNIT_RUN')) {
639
+            OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
640
+            $debug = \OC::$server->getConfig()->getSystemValue('debug', false);
641
+            OC\Log\ErrorHandler::register($debug);
642
+        }
643
+
644
+        \OC::$server->getEventLogger()->start('init_session', 'Initialize session');
645
+        OC_App::loadApps(array('session'));
646
+        if (!self::$CLI) {
647
+            self::initSession();
648
+        }
649
+        \OC::$server->getEventLogger()->end('init_session');
650
+        self::checkConfig();
651
+        self::checkInstalled();
652
+
653
+        OC_Response::addSecurityHeaders();
654
+        if(self::$server->getRequest()->getServerProtocol() === 'https') {
655
+            ini_set('session.cookie_secure', true);
656
+        }
657
+
658
+        self::performSameSiteCookieProtection();
659
+
660
+        if (!defined('OC_CONSOLE')) {
661
+            $errors = OC_Util::checkServer(\OC::$server->getSystemConfig());
662
+            if (count($errors) > 0) {
663
+                if (self::$CLI) {
664
+                    // Convert l10n string into regular string for usage in database
665
+                    $staticErrors = [];
666
+                    foreach ($errors as $error) {
667
+                        echo $error['error'] . "\n";
668
+                        echo $error['hint'] . "\n\n";
669
+                        $staticErrors[] = [
670
+                            'error' => (string)$error['error'],
671
+                            'hint' => (string)$error['hint'],
672
+                        ];
673
+                    }
674
+
675
+                    try {
676
+                        \OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
677
+                    } catch (\Exception $e) {
678
+                        echo('Writing to database failed');
679
+                    }
680
+                    exit(1);
681
+                } else {
682
+                    OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
683
+                    OC_Util::addStyle('guest');
684
+                    OC_Template::printGuestPage('', 'error', array('errors' => $errors));
685
+                    exit;
686
+                }
687
+            } elseif (self::$CLI && \OC::$server->getConfig()->getSystemValue('installed', false)) {
688
+                \OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
689
+            }
690
+        }
691
+        //try to set the session lifetime
692
+        $sessionLifeTime = self::getSessionLifeTime();
693
+        @ini_set('gc_maxlifetime', (string)$sessionLifeTime);
694
+
695
+        $systemConfig = \OC::$server->getSystemConfig();
696
+
697
+        // User and Groups
698
+        if (!$systemConfig->getValue("installed", false)) {
699
+            self::$server->getSession()->set('user_id', '');
700
+        }
701
+
702
+        OC_User::useBackend(new \OC\User\Database());
703
+        \OC::$server->getGroupManager()->addBackend(new \OC\Group\Database());
704
+
705
+        // Subscribe to the hook
706
+        \OCP\Util::connectHook(
707
+            '\OCA\Files_Sharing\API\Server2Server',
708
+            'preLoginNameUsedAsUserName',
709
+            '\OC\User\Database',
710
+            'preLoginNameUsedAsUserName'
711
+        );
712
+
713
+        //setup extra user backends
714
+        if (!self::checkUpgrade(false)) {
715
+            OC_User::setupBackends();
716
+        } else {
717
+            // Run upgrades in incognito mode
718
+            OC_User::setIncognitoMode(true);
719
+        }
720
+
721
+        self::registerCacheHooks();
722
+        self::registerFilesystemHooks();
723
+        self::registerShareHooks();
724
+        self::registerLogRotate();
725
+        self::registerEncryptionWrapper();
726
+        self::registerEncryptionHooks();
727
+        self::registerAccountHooks();
728
+        self::registerSettingsHooks();
729
+
730
+        //make sure temporary files are cleaned up
731
+        $tmpManager = \OC::$server->getTempManager();
732
+        register_shutdown_function(array($tmpManager, 'clean'));
733
+        $lockProvider = \OC::$server->getLockingProvider();
734
+        register_shutdown_function(array($lockProvider, 'releaseAll'));
735
+
736
+        // Check whether the sample configuration has been copied
737
+        if($systemConfig->getValue('copied_sample_config', false)) {
738
+            $l = \OC::$server->getL10N('lib');
739
+            header('HTTP/1.1 503 Service Temporarily Unavailable');
740
+            header('Status: 503 Service Temporarily Unavailable');
741
+            OC_Template::printErrorPage(
742
+                $l->t('Sample configuration detected'),
743
+                $l->t('It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php')
744
+            );
745
+            return;
746
+        }
747
+
748
+        $request = \OC::$server->getRequest();
749
+        $host = $request->getInsecureServerHost();
750
+        /**
751
+         * if the host passed in headers isn't trusted
752
+         * FIXME: Should not be in here at all :see_no_evil:
753
+         */
754
+        if (!OC::$CLI
755
+            // overwritehost is always trusted, workaround to not have to make
756
+            // \OC\AppFramework\Http\Request::getOverwriteHost public
757
+            && self::$server->getConfig()->getSystemValue('overwritehost') === ''
758
+            && !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host)
759
+            && self::$server->getConfig()->getSystemValue('installed', false)
760
+        ) {
761
+            // Allow access to CSS resources
762
+            $isScssRequest = false;
763
+            if(strpos($request->getPathInfo(), '/css/') === 0) {
764
+                $isScssRequest = true;
765
+            }
766
+
767
+            if (!$isScssRequest) {
768
+                header('HTTP/1.1 400 Bad Request');
769
+                header('Status: 400 Bad Request');
770
+
771
+                \OC::$server->getLogger()->warning(
772
+                    'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
773
+                    [
774
+                        'app' => 'core',
775
+                        'remoteAddress' => $request->getRemoteAddress(),
776
+                        'host' => $host,
777
+                    ]
778
+                );
779
+
780
+                $tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
781
+                $tmpl->assign('domain', $host);
782
+                $tmpl->printPage();
783
+
784
+                exit();
785
+            }
786
+        }
787
+        \OC::$server->getEventLogger()->end('boot');
788
+    }
789
+
790
+    /**
791
+     * register hooks for the cache
792
+     */
793
+    public static function registerCacheHooks() {
794
+        //don't try to do this before we are properly setup
795
+        if (\OC::$server->getSystemConfig()->getValue('installed', false) && !self::checkUpgrade(false)) {
796
+
797
+            // NOTE: This will be replaced to use OCP
798
+            $userSession = self::$server->getUserSession();
799
+            $userSession->listen('\OC\User', 'postLogin', function () {
800
+                try {
801
+                    $cache = new \OC\Cache\File();
802
+                    $cache->gc();
803
+                } catch (\OC\ServerNotAvailableException $e) {
804
+                    // not a GC exception, pass it on
805
+                    throw $e;
806
+                } catch (\Exception $e) {
807
+                    // a GC exception should not prevent users from using OC,
808
+                    // so log the exception
809
+                    \OC::$server->getLogger()->warning('Exception when running cache gc: ' . $e->getMessage(), array('app' => 'core'));
810
+                }
811
+            });
812
+        }
813
+    }
814
+
815
+    public static function registerSettingsHooks() {
816
+        $dispatcher = \OC::$server->getEventDispatcher();
817
+        $dispatcher->addListener(OCP\App\ManagerEvent::EVENT_APP_DISABLE, function($event) {
818
+            /** @var \OCP\App\ManagerEvent $event */
819
+            \OC::$server->getSettingsManager()->onAppDisabled($event->getAppID());
820
+        });
821
+        $dispatcher->addListener(OCP\App\ManagerEvent::EVENT_APP_UPDATE, function($event) {
822
+            /** @var \OCP\App\ManagerEvent $event */
823
+            $jobList = \OC::$server->getJobList();
824
+            $job = 'OC\\Settings\\RemoveOrphaned';
825
+            if(!($jobList->has($job, null))) {
826
+                $jobList->add($job);
827
+            }
828
+        });
829
+    }
830
+
831
+    private static function registerEncryptionWrapper() {
832
+        $manager = self::$server->getEncryptionManager();
833
+        \OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
834
+    }
835
+
836
+    private static function registerEncryptionHooks() {
837
+        $enabled = self::$server->getEncryptionManager()->isEnabled();
838
+        if ($enabled) {
839
+            \OCP\Util::connectHook('OCP\Share', 'post_shared', 'OC\Encryption\HookManager', 'postShared');
840
+            \OCP\Util::connectHook('OCP\Share', 'post_unshare', 'OC\Encryption\HookManager', 'postUnshared');
841
+            \OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OC\Encryption\HookManager', 'postRename');
842
+            \OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', 'OC\Encryption\HookManager', 'postRestore');
843
+        }
844
+    }
845
+
846
+    private static function registerAccountHooks() {
847
+        $hookHandler = new \OC\Accounts\Hooks(\OC::$server->getLogger());
848
+        \OCP\Util::connectHook('OC_User', 'changeUser', $hookHandler, 'changeUserHook');
849
+    }
850
+
851
+    /**
852
+     * register hooks for the cache
853
+     */
854
+    public static function registerLogRotate() {
855
+        $systemConfig = \OC::$server->getSystemConfig();
856
+        if ($systemConfig->getValue('installed', false) && $systemConfig->getValue('log_rotate_size', false) && !self::checkUpgrade(false)) {
857
+            //don't try to do this before we are properly setup
858
+            //use custom logfile path if defined, otherwise use default of nextcloud.log in data directory
859
+            \OC::$server->getJobList()->add('OC\Log\Rotate');
860
+        }
861
+    }
862
+
863
+    /**
864
+     * register hooks for the filesystem
865
+     */
866
+    public static function registerFilesystemHooks() {
867
+        // Check for blacklisted files
868
+        OC_Hook::connect('OC_Filesystem', 'write', 'OC\Files\Filesystem', 'isBlacklisted');
869
+        OC_Hook::connect('OC_Filesystem', 'rename', 'OC\Files\Filesystem', 'isBlacklisted');
870
+    }
871
+
872
+    /**
873
+     * register hooks for sharing
874
+     */
875
+    public static function registerShareHooks() {
876
+        if (\OC::$server->getSystemConfig()->getValue('installed')) {
877
+            OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share20\Hooks', 'post_deleteUser');
878
+            OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share20\Hooks', 'post_removeFromGroup');
879
+            OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share20\Hooks', 'post_deleteGroup');
880
+        }
881
+    }
882
+
883
+    protected static function registerAutoloaderCache() {
884
+        // The class loader takes an optional low-latency cache, which MUST be
885
+        // namespaced. The instanceid is used for namespacing, but might be
886
+        // unavailable at this point. Furthermore, it might not be possible to
887
+        // generate an instanceid via \OC_Util::getInstanceId() because the
888
+        // config file may not be writable. As such, we only register a class
889
+        // loader cache if instanceid is available without trying to create one.
890
+        $instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
891
+        if ($instanceId) {
892
+            try {
893
+                $memcacheFactory = \OC::$server->getMemCacheFactory();
894
+                self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader'));
895
+            } catch (\Exception $ex) {
896
+            }
897
+        }
898
+    }
899
+
900
+    /**
901
+     * Handle the request
902
+     */
903
+    public static function handleRequest() {
904
+
905
+        \OC::$server->getEventLogger()->start('handle_request', 'Handle request');
906
+        $systemConfig = \OC::$server->getSystemConfig();
907
+        // load all the classpaths from the enabled apps so they are available
908
+        // in the routing files of each app
909
+        OC::loadAppClassPaths();
910
+
911
+        // Check if Nextcloud is installed or in maintenance (update) mode
912
+        if (!$systemConfig->getValue('installed', false)) {
913
+            \OC::$server->getSession()->clear();
914
+            $setupHelper = new OC\Setup(\OC::$server->getSystemConfig(), \OC::$server->getIniWrapper(),
915
+                \OC::$server->getL10N('lib'), \OC::$server->query(\OCP\Defaults::class), \OC::$server->getLogger(),
916
+                \OC::$server->getSecureRandom());
917
+            $controller = new OC\Core\Controller\SetupController($setupHelper);
918
+            $controller->run($_POST);
919
+            exit();
920
+        }
921
+
922
+        $request = \OC::$server->getRequest();
923
+        $requestPath = $request->getRawPathInfo();
924
+        if ($requestPath === '/heartbeat') {
925
+            return;
926
+        }
927
+        if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
928
+            self::checkMaintenanceMode();
929
+            self::checkUpgrade();
930
+        }
931
+
932
+        // emergency app disabling
933
+        if ($requestPath === '/disableapp'
934
+            && $request->getMethod() === 'POST'
935
+            && ((string)$request->getParam('appid')) !== ''
936
+        ) {
937
+            \OCP\JSON::callCheck();
938
+            \OCP\JSON::checkAdminUser();
939
+            $appId = (string)$request->getParam('appid');
940
+            $appId = \OC_App::cleanAppId($appId);
941
+
942
+            \OC_App::disable($appId);
943
+            \OC_JSON::success();
944
+            exit();
945
+        }
946
+
947
+        // Always load authentication apps
948
+        OC_App::loadApps(['authentication']);
949
+
950
+        // Load minimum set of apps
951
+        if (!self::checkUpgrade(false)
952
+            && !$systemConfig->getValue('maintenance', false)) {
953
+            // For logged-in users: Load everything
954
+            if(\OC::$server->getUserSession()->isLoggedIn()) {
955
+                OC_App::loadApps();
956
+            } else {
957
+                // For guests: Load only filesystem and logging
958
+                OC_App::loadApps(array('filesystem', 'logging'));
959
+                self::handleLogin($request);
960
+            }
961
+        }
962
+
963
+        if (!self::$CLI) {
964
+            try {
965
+                if (!$systemConfig->getValue('maintenance', false) && !self::checkUpgrade(false)) {
966
+                    OC_App::loadApps(array('filesystem', 'logging'));
967
+                    OC_App::loadApps();
968
+                }
969
+                OC_Util::setupFS();
970
+                OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
971
+                return;
972
+            } catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
973
+                //header('HTTP/1.0 404 Not Found');
974
+            } catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
975
+                OC_Response::setStatus(405);
976
+                return;
977
+            }
978
+        }
979
+
980
+        // Handle WebDAV
981
+        if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
982
+            // not allowed any more to prevent people
983
+            // mounting this root directly.
984
+            // Users need to mount remote.php/webdav instead.
985
+            header('HTTP/1.1 405 Method Not Allowed');
986
+            header('Status: 405 Method Not Allowed');
987
+            return;
988
+        }
989
+
990
+        // Someone is logged in
991
+        if (\OC::$server->getUserSession()->isLoggedIn()) {
992
+            OC_App::loadApps();
993
+            OC_User::setupBackends();
994
+            OC_Util::setupFS();
995
+            // FIXME
996
+            // Redirect to default application
997
+            OC_Util::redirectToDefaultPage();
998
+        } else {
999
+            // Not handled and not logged in
1000
+            header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
1001
+        }
1002
+    }
1003
+
1004
+    /**
1005
+     * Check login: apache auth, auth token, basic auth
1006
+     *
1007
+     * @param OCP\IRequest $request
1008
+     * @return boolean
1009
+     */
1010
+    static function handleLogin(OCP\IRequest $request) {
1011
+        $userSession = self::$server->getUserSession();
1012
+        if (OC_User::handleApacheAuth()) {
1013
+            return true;
1014
+        }
1015
+        if ($userSession->tryTokenLogin($request)) {
1016
+            return true;
1017
+        }
1018
+        if (isset($_COOKIE['nc_username'])
1019
+            && isset($_COOKIE['nc_token'])
1020
+            && isset($_COOKIE['nc_session_id'])
1021
+            && $userSession->loginWithCookie($_COOKIE['nc_username'], $_COOKIE['nc_token'], $_COOKIE['nc_session_id'])) {
1022
+            return true;
1023
+        }
1024
+        if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
1025
+            return true;
1026
+        }
1027
+        return false;
1028
+    }
1029
+
1030
+    protected static function handleAuthHeaders() {
1031
+        //copy http auth headers for apache+php-fcgid work around
1032
+        if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
1033
+            $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
1034
+        }
1035
+
1036
+        // Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
1037
+        $vars = array(
1038
+            'HTTP_AUTHORIZATION', // apache+php-cgi work around
1039
+            'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
1040
+        );
1041
+        foreach ($vars as $var) {
1042
+            if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
1043
+                list($name, $password) = explode(':', base64_decode($matches[1]), 2);
1044
+                $_SERVER['PHP_AUTH_USER'] = $name;
1045
+                $_SERVER['PHP_AUTH_PW'] = $password;
1046
+                break;
1047
+            }
1048
+        }
1049
+    }
1050 1050
 }
1051 1051
 
1052 1052
 OC::init();
Please login to merge, or discard this patch.
lib/private/legacy/template.php 1 patch
Indentation   +326 added lines, -326 removed lines patch added patch discarded remove patch
@@ -44,330 +44,330 @@
 block discarded – undo
44 44
  */
45 45
 class OC_Template extends \OC\Template\Base {
46 46
 
47
-	/** @var string */
48
-	private $renderAs; // Create a full page?
49
-
50
-	/** @var string */
51
-	private $path; // The path to the template
52
-
53
-	/** @var array */
54
-	private $headers = array(); //custom headers
55
-
56
-	/** @var string */
57
-	protected $app; // app id
58
-
59
-	protected static $initTemplateEngineFirstRun = true;
60
-
61
-	/**
62
-	 * Constructor
63
-	 *
64
-	 * @param string $app app providing the template
65
-	 * @param string $name of the template file (without suffix)
66
-	 * @param string $renderAs If $renderAs is set, OC_Template will try to
67
-	 *                         produce a full page in the according layout. For
68
-	 *                         now, $renderAs can be set to "guest", "user" or
69
-	 *                         "admin".
70
-	 * @param bool $registerCall = true
71
-	 */
72
-	public function __construct( $app, $name, $renderAs = "", $registerCall = true ) {
73
-		// Read the selected theme from the config file
74
-		self::initTemplateEngine($renderAs);
75
-
76
-		$theme = OC_Util::getTheme();
77
-
78
-		$requestToken = (OC::$server->getSession() && $registerCall) ? \OCP\Util::callRegister() : '';
79
-
80
-		$parts = explode('/', $app); // fix translation when app is something like core/lostpassword
81
-		$l10n = \OC::$server->getL10N($parts[0]);
82
-		/** @var \OCP\Defaults $themeDefaults */
83
-		$themeDefaults = \OC::$server->query(\OCP\Defaults::class);
84
-
85
-		list($path, $template) = $this->findTemplate($theme, $app, $name);
86
-
87
-		// Set the private data
88
-		$this->renderAs = $renderAs;
89
-		$this->path = $path;
90
-		$this->app = $app;
91
-
92
-		parent::__construct($template, $requestToken, $l10n, $themeDefaults);
93
-	}
94
-
95
-	/**
96
-	 * @param string $renderAs
97
-	 */
98
-	public static function initTemplateEngine($renderAs) {
99
-		if (self::$initTemplateEngineFirstRun){
100
-
101
-			//apps that started before the template initialization can load their own scripts/styles
102
-			//so to make sure this scripts/styles here are loaded first we use OC_Util::addScript() with $prepend=true
103
-			//meaning the last script/style in this list will be loaded first
104
-			if (\OC::$server->getSystemConfig()->getValue ('installed', false) && $renderAs !== 'error' && !\OCP\Util::needUpgrade()) {
105
-				if (\OC::$server->getConfig ()->getAppValue ( 'core', 'backgroundjobs_mode', 'ajax' ) == 'ajax') {
106
-					OC_Util::addScript ( 'backgroundjobs', null, true );
107
-				}
108
-			}
109
-
110
-			OC_Util::addStyle('jquery-ui-fixes',null,true);
111
-			OC_Util::addVendorStyle('jquery-ui/themes/base/jquery-ui',null,true);
112
-			OC_Util::addStyle('server', null, true);
113
-			OC_Util::addVendorStyle('select2/select2', null, true);
114
-			OC_Util::addStyle('jquery.ocdialog');
115
-			OC_Util::addTranslations("core", null, true);
116
-			OC_Util::addScript('search', 'search', true);
117
-			OC_Util::addScript('merged-template-prepend', null, true);
118
-			OC_Util::addScript('jquery-ui-fixes');
119
-			OC_Util::addScript('files/fileinfo');
120
-			OC_Util::addScript('files/client');
121
-
122
-			if (\OC::$server->getConfig()->getSystemValue('debug')) {
123
-				// Add the stuff we need always
124
-				// following logic will import all vendor libraries that are
125
-				// specified in core/js/core.json
126
-				$fileContent = file_get_contents(OC::$SERVERROOT . '/core/js/core.json');
127
-				if($fileContent !== false) {
128
-					$coreDependencies = json_decode($fileContent, true);
129
-					foreach(array_reverse($coreDependencies['vendor']) as $vendorLibrary) {
130
-						//remove trailing ".js" as addVendorScript will append it
131
-						OC_Util::addVendorScript(
132
-							substr($vendorLibrary, 0, strlen($vendorLibrary) - 3),null,true);
133
-						}
134
- 				} else {
135
-					throw new \Exception('Cannot read core/js/core.json');
136
-				}
137
-			} else {
138
-				// Import all (combined) default vendor libraries
139
-				OC_Util::addVendorScript('core', null, true);
140
-			}
141
-
142
-			if (\OC::$server->getRequest()->isUserAgent([\OC\AppFramework\Http\Request::USER_AGENT_IE])) {
143
-				// polyfill for btoa/atob for IE friends
144
-				OC_Util::addVendorScript('base64/base64');
145
-				// shim for the davclient.js library
146
-				\OCP\Util::addScript('files/iedavclient');
147
-			}
148
-
149
-			self::$initTemplateEngineFirstRun = false;
150
-		}
151
-
152
-	}
153
-
154
-
155
-	/**
156
-	 * find the template with the given name
157
-	 * @param string $name of the template file (without suffix)
158
-	 *
159
-	 * Will select the template file for the selected theme.
160
-	 * Checking all the possible locations.
161
-	 * @param string $theme
162
-	 * @param string $app
163
-	 * @return string[]
164
-	 */
165
-	protected function findTemplate($theme, $app, $name) {
166
-		// Check if it is a app template or not.
167
-		if( $app !== '' ) {
168
-			$dirs = $this->getAppTemplateDirs($theme, $app, OC::$SERVERROOT, OC_App::getAppPath($app));
169
-		} else {
170
-			$dirs = $this->getCoreTemplateDirs($theme, OC::$SERVERROOT);
171
-		}
172
-		$locator = new \OC\Template\TemplateFileLocator( $dirs );
173
-		$template = $locator->find($name);
174
-		$path = $locator->getPath();
175
-		return array($path, $template);
176
-	}
177
-
178
-	/**
179
-	 * Add a custom element to the header
180
-	 * @param string $tag tag name of the element
181
-	 * @param array $attributes array of attributes for the element
182
-	 * @param string $text the text content for the element. If $text is null then the
183
-	 * element will be written as empty element. So use "" to get a closing tag.
184
-	 */
185
-	public function addHeader($tag, $attributes, $text=null) {
186
-		$this->headers[]= array(
187
-			'tag' => $tag,
188
-			'attributes' => $attributes,
189
-			'text' => $text
190
-		);
191
-	}
192
-
193
-	/**
194
-	 * Process the template
195
-	 * @return boolean|string
196
-	 *
197
-	 * This function process the template. If $this->renderAs is set, it
198
-	 * will produce a full page.
199
-	 */
200
-	public function fetchPage($additionalParams = null) {
201
-		$data = parent::fetchPage($additionalParams);
202
-
203
-		if( $this->renderAs ) {
204
-			$page = new TemplateLayout($this->renderAs, $this->app);
205
-
206
-			// Add custom headers
207
-			$headers = '';
208
-			foreach(OC_Util::$headers as $header) {
209
-				$headers .= '<'.\OCP\Util::sanitizeHTML($header['tag']);
210
-				foreach($header['attributes'] as $name=>$value) {
211
-					$headers .= ' '.\OCP\Util::sanitizeHTML($name).'="'.\OCP\Util::sanitizeHTML($value).'"';
212
-				}
213
-				if ($header['text'] !== null) {
214
-					$headers .= '>'.\OCP\Util::sanitizeHTML($header['text']).'</'.\OCP\Util::sanitizeHTML($header['tag']).'>';
215
-				} else {
216
-					$headers .= '/>';
217
-				}
218
-			}
219
-
220
-			$page->assign('headers', $headers);
221
-
222
-			$page->assign('content', $data);
223
-			return $page->fetchPage();
224
-		}
225
-
226
-		return $data;
227
-	}
228
-
229
-	/**
230
-	 * Include template
231
-	 *
232
-	 * @param string $file
233
-	 * @param array|null $additionalParams
234
-	 * @return string returns content of included template
235
-	 *
236
-	 * Includes another template. use <?php echo $this->inc('template'); ?> to
237
-	 * do this.
238
-	 */
239
-	public function inc( $file, $additionalParams = null ) {
240
-		return $this->load($this->path.$file.'.php', $additionalParams);
241
-	}
242
-
243
-	/**
244
-	 * Shortcut to print a simple page for users
245
-	 * @param string $application The application we render the template for
246
-	 * @param string $name Name of the template
247
-	 * @param array $parameters Parameters for the template
248
-	 * @return boolean|null
249
-	 */
250
-	public static function printUserPage( $application, $name, $parameters = array() ) {
251
-		$content = new OC_Template( $application, $name, "user" );
252
-		foreach( $parameters as $key => $value ) {
253
-			$content->assign( $key, $value );
254
-		}
255
-		print $content->printPage();
256
-	}
257
-
258
-	/**
259
-	 * Shortcut to print a simple page for admins
260
-	 * @param string $application The application we render the template for
261
-	 * @param string $name Name of the template
262
-	 * @param array $parameters Parameters for the template
263
-	 * @return bool
264
-	 */
265
-	public static function printAdminPage( $application, $name, $parameters = array() ) {
266
-		$content = new OC_Template( $application, $name, "admin" );
267
-		foreach( $parameters as $key => $value ) {
268
-			$content->assign( $key, $value );
269
-		}
270
-		return $content->printPage();
271
-	}
272
-
273
-	/**
274
-	 * Shortcut to print a simple page for guests
275
-	 * @param string $application The application we render the template for
276
-	 * @param string $name Name of the template
277
-	 * @param array|string $parameters Parameters for the template
278
-	 * @return bool
279
-	 */
280
-	public static function printGuestPage( $application, $name, $parameters = array() ) {
281
-		$content = new OC_Template( $application, $name, "guest" );
282
-		foreach( $parameters as $key => $value ) {
283
-			$content->assign( $key, $value );
284
-		}
285
-		return $content->printPage();
286
-	}
287
-
288
-	/**
289
-		* Print a fatal error page and terminates the script
290
-		* @param string $error_msg The error message to show
291
-		* @param string $hint An optional hint message - needs to be properly escaped
292
-		*/
293
-	public static function printErrorPage( $error_msg, $hint = '' ) {
294
-		if ($error_msg === $hint) {
295
-			// If the hint is the same as the message there is no need to display it twice.
296
-			$hint = '';
297
-		}
298
-
299
-		try {
300
-			$content = new \OC_Template( '', 'error', 'error', false );
301
-			$errors = array(array('error' => $error_msg, 'hint' => $hint));
302
-			$content->assign( 'errors', $errors );
303
-			$content->printPage();
304
-		} catch (\Exception $e) {
305
-			$logger = \OC::$server->getLogger();
306
-			$logger->error("$error_msg $hint", ['app' => 'core']);
307
-			$logger->logException($e, ['app' => 'core']);
308
-
309
-			header(self::getHttpProtocol() . ' 500 Internal Server Error');
310
-			header('Content-Type: text/plain; charset=utf-8');
311
-			print("$error_msg $hint");
312
-		}
313
-		die();
314
-	}
315
-
316
-	/**
317
-	 * print error page using Exception details
318
-	 * @param Exception | Throwable $exception
319
-	 */
320
-	public static function printExceptionErrorPage($exception, $fetchPage = false) {
321
-		try {
322
-			$request = \OC::$server->getRequest();
323
-			$content = new \OC_Template('', 'exception', 'error', false);
324
-			$content->assign('errorClass', get_class($exception));
325
-			$content->assign('errorMsg', $exception->getMessage());
326
-			$content->assign('errorCode', $exception->getCode());
327
-			$content->assign('file', $exception->getFile());
328
-			$content->assign('line', $exception->getLine());
329
-			$content->assign('trace', $exception->getTraceAsString());
330
-			$content->assign('debugMode', \OC::$server->getSystemConfig()->getValue('debug', false));
331
-			$content->assign('remoteAddr', $request->getRemoteAddress());
332
-			$content->assign('requestID', $request->getId());
333
-			if ($fetchPage) {
334
-				return $content->fetchPage();
335
-			}
336
-			$content->printPage();
337
-		} catch (\Exception $e) {
338
-			$logger = \OC::$server->getLogger();
339
-			$logger->logException($exception, ['app' => 'core']);
340
-			$logger->logException($e, ['app' => 'core']);
341
-
342
-			header(self::getHttpProtocol() . ' 500 Internal Server Error');
343
-			header('Content-Type: text/plain; charset=utf-8');
344
-			print("Internal Server Error\n\n");
345
-			print("The server encountered an internal error and was unable to complete your request.\n");
346
-			print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
347
-			print("More details can be found in the server log.\n");
348
-		}
349
-		die();
350
-	}
351
-
352
-	/**
353
-	 * This is only here to reduce the dependencies in case of an exception to
354
-	 * still be able to print a plain error message.
355
-	 *
356
-	 * Returns the used HTTP protocol.
357
-	 *
358
-	 * @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0.
359
-	 * @internal Don't use this - use AppFramework\Http\Request->getHttpProtocol instead
360
-	 */
361
-	protected static function getHttpProtocol() {
362
-		$claimedProtocol = strtoupper($_SERVER['SERVER_PROTOCOL']);
363
-		$validProtocols = [
364
-			'HTTP/1.0',
365
-			'HTTP/1.1',
366
-			'HTTP/2',
367
-		];
368
-		if(in_array($claimedProtocol, $validProtocols, true)) {
369
-			return $claimedProtocol;
370
-		}
371
-		return 'HTTP/1.1';
372
-	}
47
+    /** @var string */
48
+    private $renderAs; // Create a full page?
49
+
50
+    /** @var string */
51
+    private $path; // The path to the template
52
+
53
+    /** @var array */
54
+    private $headers = array(); //custom headers
55
+
56
+    /** @var string */
57
+    protected $app; // app id
58
+
59
+    protected static $initTemplateEngineFirstRun = true;
60
+
61
+    /**
62
+     * Constructor
63
+     *
64
+     * @param string $app app providing the template
65
+     * @param string $name of the template file (without suffix)
66
+     * @param string $renderAs If $renderAs is set, OC_Template will try to
67
+     *                         produce a full page in the according layout. For
68
+     *                         now, $renderAs can be set to "guest", "user" or
69
+     *                         "admin".
70
+     * @param bool $registerCall = true
71
+     */
72
+    public function __construct( $app, $name, $renderAs = "", $registerCall = true ) {
73
+        // Read the selected theme from the config file
74
+        self::initTemplateEngine($renderAs);
75
+
76
+        $theme = OC_Util::getTheme();
77
+
78
+        $requestToken = (OC::$server->getSession() && $registerCall) ? \OCP\Util::callRegister() : '';
79
+
80
+        $parts = explode('/', $app); // fix translation when app is something like core/lostpassword
81
+        $l10n = \OC::$server->getL10N($parts[0]);
82
+        /** @var \OCP\Defaults $themeDefaults */
83
+        $themeDefaults = \OC::$server->query(\OCP\Defaults::class);
84
+
85
+        list($path, $template) = $this->findTemplate($theme, $app, $name);
86
+
87
+        // Set the private data
88
+        $this->renderAs = $renderAs;
89
+        $this->path = $path;
90
+        $this->app = $app;
91
+
92
+        parent::__construct($template, $requestToken, $l10n, $themeDefaults);
93
+    }
94
+
95
+    /**
96
+     * @param string $renderAs
97
+     */
98
+    public static function initTemplateEngine($renderAs) {
99
+        if (self::$initTemplateEngineFirstRun){
100
+
101
+            //apps that started before the template initialization can load their own scripts/styles
102
+            //so to make sure this scripts/styles here are loaded first we use OC_Util::addScript() with $prepend=true
103
+            //meaning the last script/style in this list will be loaded first
104
+            if (\OC::$server->getSystemConfig()->getValue ('installed', false) && $renderAs !== 'error' && !\OCP\Util::needUpgrade()) {
105
+                if (\OC::$server->getConfig ()->getAppValue ( 'core', 'backgroundjobs_mode', 'ajax' ) == 'ajax') {
106
+                    OC_Util::addScript ( 'backgroundjobs', null, true );
107
+                }
108
+            }
109
+
110
+            OC_Util::addStyle('jquery-ui-fixes',null,true);
111
+            OC_Util::addVendorStyle('jquery-ui/themes/base/jquery-ui',null,true);
112
+            OC_Util::addStyle('server', null, true);
113
+            OC_Util::addVendorStyle('select2/select2', null, true);
114
+            OC_Util::addStyle('jquery.ocdialog');
115
+            OC_Util::addTranslations("core", null, true);
116
+            OC_Util::addScript('search', 'search', true);
117
+            OC_Util::addScript('merged-template-prepend', null, true);
118
+            OC_Util::addScript('jquery-ui-fixes');
119
+            OC_Util::addScript('files/fileinfo');
120
+            OC_Util::addScript('files/client');
121
+
122
+            if (\OC::$server->getConfig()->getSystemValue('debug')) {
123
+                // Add the stuff we need always
124
+                // following logic will import all vendor libraries that are
125
+                // specified in core/js/core.json
126
+                $fileContent = file_get_contents(OC::$SERVERROOT . '/core/js/core.json');
127
+                if($fileContent !== false) {
128
+                    $coreDependencies = json_decode($fileContent, true);
129
+                    foreach(array_reverse($coreDependencies['vendor']) as $vendorLibrary) {
130
+                        //remove trailing ".js" as addVendorScript will append it
131
+                        OC_Util::addVendorScript(
132
+                            substr($vendorLibrary, 0, strlen($vendorLibrary) - 3),null,true);
133
+                        }
134
+                    } else {
135
+                    throw new \Exception('Cannot read core/js/core.json');
136
+                }
137
+            } else {
138
+                // Import all (combined) default vendor libraries
139
+                OC_Util::addVendorScript('core', null, true);
140
+            }
141
+
142
+            if (\OC::$server->getRequest()->isUserAgent([\OC\AppFramework\Http\Request::USER_AGENT_IE])) {
143
+                // polyfill for btoa/atob for IE friends
144
+                OC_Util::addVendorScript('base64/base64');
145
+                // shim for the davclient.js library
146
+                \OCP\Util::addScript('files/iedavclient');
147
+            }
148
+
149
+            self::$initTemplateEngineFirstRun = false;
150
+        }
151
+
152
+    }
153
+
154
+
155
+    /**
156
+     * find the template with the given name
157
+     * @param string $name of the template file (without suffix)
158
+     *
159
+     * Will select the template file for the selected theme.
160
+     * Checking all the possible locations.
161
+     * @param string $theme
162
+     * @param string $app
163
+     * @return string[]
164
+     */
165
+    protected function findTemplate($theme, $app, $name) {
166
+        // Check if it is a app template or not.
167
+        if( $app !== '' ) {
168
+            $dirs = $this->getAppTemplateDirs($theme, $app, OC::$SERVERROOT, OC_App::getAppPath($app));
169
+        } else {
170
+            $dirs = $this->getCoreTemplateDirs($theme, OC::$SERVERROOT);
171
+        }
172
+        $locator = new \OC\Template\TemplateFileLocator( $dirs );
173
+        $template = $locator->find($name);
174
+        $path = $locator->getPath();
175
+        return array($path, $template);
176
+    }
177
+
178
+    /**
179
+     * Add a custom element to the header
180
+     * @param string $tag tag name of the element
181
+     * @param array $attributes array of attributes for the element
182
+     * @param string $text the text content for the element. If $text is null then the
183
+     * element will be written as empty element. So use "" to get a closing tag.
184
+     */
185
+    public function addHeader($tag, $attributes, $text=null) {
186
+        $this->headers[]= array(
187
+            'tag' => $tag,
188
+            'attributes' => $attributes,
189
+            'text' => $text
190
+        );
191
+    }
192
+
193
+    /**
194
+     * Process the template
195
+     * @return boolean|string
196
+     *
197
+     * This function process the template. If $this->renderAs is set, it
198
+     * will produce a full page.
199
+     */
200
+    public function fetchPage($additionalParams = null) {
201
+        $data = parent::fetchPage($additionalParams);
202
+
203
+        if( $this->renderAs ) {
204
+            $page = new TemplateLayout($this->renderAs, $this->app);
205
+
206
+            // Add custom headers
207
+            $headers = '';
208
+            foreach(OC_Util::$headers as $header) {
209
+                $headers .= '<'.\OCP\Util::sanitizeHTML($header['tag']);
210
+                foreach($header['attributes'] as $name=>$value) {
211
+                    $headers .= ' '.\OCP\Util::sanitizeHTML($name).'="'.\OCP\Util::sanitizeHTML($value).'"';
212
+                }
213
+                if ($header['text'] !== null) {
214
+                    $headers .= '>'.\OCP\Util::sanitizeHTML($header['text']).'</'.\OCP\Util::sanitizeHTML($header['tag']).'>';
215
+                } else {
216
+                    $headers .= '/>';
217
+                }
218
+            }
219
+
220
+            $page->assign('headers', $headers);
221
+
222
+            $page->assign('content', $data);
223
+            return $page->fetchPage();
224
+        }
225
+
226
+        return $data;
227
+    }
228
+
229
+    /**
230
+     * Include template
231
+     *
232
+     * @param string $file
233
+     * @param array|null $additionalParams
234
+     * @return string returns content of included template
235
+     *
236
+     * Includes another template. use <?php echo $this->inc('template'); ?> to
237
+     * do this.
238
+     */
239
+    public function inc( $file, $additionalParams = null ) {
240
+        return $this->load($this->path.$file.'.php', $additionalParams);
241
+    }
242
+
243
+    /**
244
+     * Shortcut to print a simple page for users
245
+     * @param string $application The application we render the template for
246
+     * @param string $name Name of the template
247
+     * @param array $parameters Parameters for the template
248
+     * @return boolean|null
249
+     */
250
+    public static function printUserPage( $application, $name, $parameters = array() ) {
251
+        $content = new OC_Template( $application, $name, "user" );
252
+        foreach( $parameters as $key => $value ) {
253
+            $content->assign( $key, $value );
254
+        }
255
+        print $content->printPage();
256
+    }
257
+
258
+    /**
259
+     * Shortcut to print a simple page for admins
260
+     * @param string $application The application we render the template for
261
+     * @param string $name Name of the template
262
+     * @param array $parameters Parameters for the template
263
+     * @return bool
264
+     */
265
+    public static function printAdminPage( $application, $name, $parameters = array() ) {
266
+        $content = new OC_Template( $application, $name, "admin" );
267
+        foreach( $parameters as $key => $value ) {
268
+            $content->assign( $key, $value );
269
+        }
270
+        return $content->printPage();
271
+    }
272
+
273
+    /**
274
+     * Shortcut to print a simple page for guests
275
+     * @param string $application The application we render the template for
276
+     * @param string $name Name of the template
277
+     * @param array|string $parameters Parameters for the template
278
+     * @return bool
279
+     */
280
+    public static function printGuestPage( $application, $name, $parameters = array() ) {
281
+        $content = new OC_Template( $application, $name, "guest" );
282
+        foreach( $parameters as $key => $value ) {
283
+            $content->assign( $key, $value );
284
+        }
285
+        return $content->printPage();
286
+    }
287
+
288
+    /**
289
+     * Print a fatal error page and terminates the script
290
+     * @param string $error_msg The error message to show
291
+     * @param string $hint An optional hint message - needs to be properly escaped
292
+     */
293
+    public static function printErrorPage( $error_msg, $hint = '' ) {
294
+        if ($error_msg === $hint) {
295
+            // If the hint is the same as the message there is no need to display it twice.
296
+            $hint = '';
297
+        }
298
+
299
+        try {
300
+            $content = new \OC_Template( '', 'error', 'error', false );
301
+            $errors = array(array('error' => $error_msg, 'hint' => $hint));
302
+            $content->assign( 'errors', $errors );
303
+            $content->printPage();
304
+        } catch (\Exception $e) {
305
+            $logger = \OC::$server->getLogger();
306
+            $logger->error("$error_msg $hint", ['app' => 'core']);
307
+            $logger->logException($e, ['app' => 'core']);
308
+
309
+            header(self::getHttpProtocol() . ' 500 Internal Server Error');
310
+            header('Content-Type: text/plain; charset=utf-8');
311
+            print("$error_msg $hint");
312
+        }
313
+        die();
314
+    }
315
+
316
+    /**
317
+     * print error page using Exception details
318
+     * @param Exception | Throwable $exception
319
+     */
320
+    public static function printExceptionErrorPage($exception, $fetchPage = false) {
321
+        try {
322
+            $request = \OC::$server->getRequest();
323
+            $content = new \OC_Template('', 'exception', 'error', false);
324
+            $content->assign('errorClass', get_class($exception));
325
+            $content->assign('errorMsg', $exception->getMessage());
326
+            $content->assign('errorCode', $exception->getCode());
327
+            $content->assign('file', $exception->getFile());
328
+            $content->assign('line', $exception->getLine());
329
+            $content->assign('trace', $exception->getTraceAsString());
330
+            $content->assign('debugMode', \OC::$server->getSystemConfig()->getValue('debug', false));
331
+            $content->assign('remoteAddr', $request->getRemoteAddress());
332
+            $content->assign('requestID', $request->getId());
333
+            if ($fetchPage) {
334
+                return $content->fetchPage();
335
+            }
336
+            $content->printPage();
337
+        } catch (\Exception $e) {
338
+            $logger = \OC::$server->getLogger();
339
+            $logger->logException($exception, ['app' => 'core']);
340
+            $logger->logException($e, ['app' => 'core']);
341
+
342
+            header(self::getHttpProtocol() . ' 500 Internal Server Error');
343
+            header('Content-Type: text/plain; charset=utf-8');
344
+            print("Internal Server Error\n\n");
345
+            print("The server encountered an internal error and was unable to complete your request.\n");
346
+            print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
347
+            print("More details can be found in the server log.\n");
348
+        }
349
+        die();
350
+    }
351
+
352
+    /**
353
+     * This is only here to reduce the dependencies in case of an exception to
354
+     * still be able to print a plain error message.
355
+     *
356
+     * Returns the used HTTP protocol.
357
+     *
358
+     * @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0.
359
+     * @internal Don't use this - use AppFramework\Http\Request->getHttpProtocol instead
360
+     */
361
+    protected static function getHttpProtocol() {
362
+        $claimedProtocol = strtoupper($_SERVER['SERVER_PROTOCOL']);
363
+        $validProtocols = [
364
+            'HTTP/1.0',
365
+            'HTTP/1.1',
366
+            'HTTP/2',
367
+        ];
368
+        if(in_array($claimedProtocol, $validProtocols, true)) {
369
+            return $claimedProtocol;
370
+        }
371
+        return 'HTTP/1.1';
372
+    }
373 373
 }
Please login to merge, or discard this patch.
lib/private/legacy/defaults.php 2 patches
Indentation   +249 added lines, -249 removed lines patch added patch discarded remove patch
@@ -31,280 +31,280 @@
 block discarded – undo
31 31
  */
32 32
 class OC_Defaults {
33 33
 
34
-	private $theme;
35
-	private $l;
34
+    private $theme;
35
+    private $l;
36 36
 
37
-	private $defaultEntity;
38
-	private $defaultName;
39
-	private $defaultTitle;
40
-	private $defaultBaseUrl;
41
-	private $defaultSyncClientUrl;
42
-	private $defaultiOSClientUrl;
43
-	private $defaultiTunesAppId;
44
-	private $defaultAndroidClientUrl;
45
-	private $defaultDocBaseUrl;
46
-	private $defaultDocVersion;
47
-	private $defaultSlogan;
48
-	private $defaultLogoClaim;
49
-	private $defaultColorPrimary;
50
-	private $defaultLogoUrl;
51
-	private $defaultCacheBuster;
37
+    private $defaultEntity;
38
+    private $defaultName;
39
+    private $defaultTitle;
40
+    private $defaultBaseUrl;
41
+    private $defaultSyncClientUrl;
42
+    private $defaultiOSClientUrl;
43
+    private $defaultiTunesAppId;
44
+    private $defaultAndroidClientUrl;
45
+    private $defaultDocBaseUrl;
46
+    private $defaultDocVersion;
47
+    private $defaultSlogan;
48
+    private $defaultLogoClaim;
49
+    private $defaultColorPrimary;
50
+    private $defaultLogoUrl;
51
+    private $defaultCacheBuster;
52 52
 
53
-	function __construct() {
54
-		$this->l = \OC::$server->getL10N('lib');
53
+    function __construct() {
54
+        $this->l = \OC::$server->getL10N('lib');
55 55
 
56
-		$this->defaultEntity = 'Nextcloud'; /* e.g. company name, used for footers and copyright notices */
57
-		$this->defaultName = 'Nextcloud'; /* short name, used when referring to the software */
58
-		$this->defaultTitle = 'Nextcloud'; /* can be a longer name, for titles */
59
-		$this->defaultBaseUrl = 'https://nextcloud.com';
60
-		$this->defaultSyncClientUrl = 'https://nextcloud.com/install/#install-clients';
61
-		$this->defaultiOSClientUrl = 'https://itunes.apple.com/us/app/nextcloud/id1125420102?mt=8';
62
-		$this->defaultiTunesAppId = '1125420102';
63
-		$this->defaultAndroidClientUrl = 'https://play.google.com/store/apps/details?id=com.nextcloud.client';
64
-		$this->defaultDocBaseUrl = 'https://docs.nextcloud.com';
65
-		$this->defaultDocVersion = '11'; // used to generate doc links
66
-		$this->defaultSlogan = $this->l->t('a safe home for all your data');
67
-		$this->defaultLogoClaim = '';
68
-		$this->defaultColorPrimary = '#0082c9';
69
-		$this->defaultLogoUrl = \OC::$server->getURLGenerator()->imagePath('core','logo.svg');
70
-		$this->defaultLogoUrl .=  '?v=' . hash('sha1', implode('.', \OCP\Util::getVersion()));
56
+        $this->defaultEntity = 'Nextcloud'; /* e.g. company name, used for footers and copyright notices */
57
+        $this->defaultName = 'Nextcloud'; /* short name, used when referring to the software */
58
+        $this->defaultTitle = 'Nextcloud'; /* can be a longer name, for titles */
59
+        $this->defaultBaseUrl = 'https://nextcloud.com';
60
+        $this->defaultSyncClientUrl = 'https://nextcloud.com/install/#install-clients';
61
+        $this->defaultiOSClientUrl = 'https://itunes.apple.com/us/app/nextcloud/id1125420102?mt=8';
62
+        $this->defaultiTunesAppId = '1125420102';
63
+        $this->defaultAndroidClientUrl = 'https://play.google.com/store/apps/details?id=com.nextcloud.client';
64
+        $this->defaultDocBaseUrl = 'https://docs.nextcloud.com';
65
+        $this->defaultDocVersion = '11'; // used to generate doc links
66
+        $this->defaultSlogan = $this->l->t('a safe home for all your data');
67
+        $this->defaultLogoClaim = '';
68
+        $this->defaultColorPrimary = '#0082c9';
69
+        $this->defaultLogoUrl = \OC::$server->getURLGenerator()->imagePath('core','logo.svg');
70
+        $this->defaultLogoUrl .=  '?v=' . hash('sha1', implode('.', \OCP\Util::getVersion()));
71 71
 
72
-		$themePath = OC::$SERVERROOT . '/themes/' . OC_Util::getTheme() . '/defaults.php';
73
-		if (file_exists($themePath)) {
74
-			// prevent defaults.php from printing output
75
-			ob_start();
76
-			require_once $themePath;
77
-			ob_end_clean();
78
-			if (class_exists('OC_Theme')) {
79
-				$this->theme = new OC_Theme();
80
-			}
81
-		}
82
-	}
72
+        $themePath = OC::$SERVERROOT . '/themes/' . OC_Util::getTheme() . '/defaults.php';
73
+        if (file_exists($themePath)) {
74
+            // prevent defaults.php from printing output
75
+            ob_start();
76
+            require_once $themePath;
77
+            ob_end_clean();
78
+            if (class_exists('OC_Theme')) {
79
+                $this->theme = new OC_Theme();
80
+            }
81
+        }
82
+    }
83 83
 
84
-	/**
85
-	 * @param string $method
86
-	 */
87
-	private function themeExist($method) {
88
-		if (isset($this->theme) && method_exists($this->theme, $method)) {
89
-			return true;
90
-		}
91
-		return false;
92
-	}
84
+    /**
85
+     * @param string $method
86
+     */
87
+    private function themeExist($method) {
88
+        if (isset($this->theme) && method_exists($this->theme, $method)) {
89
+            return true;
90
+        }
91
+        return false;
92
+    }
93 93
 
94
-	/**
95
-	 * Returns the base URL
96
-	 * @return string URL
97
-	 */
98
-	public function getBaseUrl() {
99
-		if ($this->themeExist('getBaseUrl')) {
100
-			return $this->theme->getBaseUrl();
101
-		} else {
102
-			return $this->defaultBaseUrl;
103
-		}
104
-	}
94
+    /**
95
+     * Returns the base URL
96
+     * @return string URL
97
+     */
98
+    public function getBaseUrl() {
99
+        if ($this->themeExist('getBaseUrl')) {
100
+            return $this->theme->getBaseUrl();
101
+        } else {
102
+            return $this->defaultBaseUrl;
103
+        }
104
+    }
105 105
 
106
-	/**
107
-	 * Returns the URL where the sync clients are listed
108
-	 * @return string URL
109
-	 */
110
-	public function getSyncClientUrl() {
111
-		if ($this->themeExist('getSyncClientUrl')) {
112
-			return $this->theme->getSyncClientUrl();
113
-		} else {
114
-			return $this->defaultSyncClientUrl;
115
-		}
116
-	}
106
+    /**
107
+     * Returns the URL where the sync clients are listed
108
+     * @return string URL
109
+     */
110
+    public function getSyncClientUrl() {
111
+        if ($this->themeExist('getSyncClientUrl')) {
112
+            return $this->theme->getSyncClientUrl();
113
+        } else {
114
+            return $this->defaultSyncClientUrl;
115
+        }
116
+    }
117 117
 
118
-	/**
119
-	 * Returns the URL to the App Store for the iOS Client
120
-	 * @return string URL
121
-	 */
122
-	public function getiOSClientUrl() {
123
-		if ($this->themeExist('getiOSClientUrl')) {
124
-			return $this->theme->getiOSClientUrl();
125
-		} else {
126
-			return $this->defaultiOSClientUrl;
127
-		}
128
-	}
118
+    /**
119
+     * Returns the URL to the App Store for the iOS Client
120
+     * @return string URL
121
+     */
122
+    public function getiOSClientUrl() {
123
+        if ($this->themeExist('getiOSClientUrl')) {
124
+            return $this->theme->getiOSClientUrl();
125
+        } else {
126
+            return $this->defaultiOSClientUrl;
127
+        }
128
+    }
129 129
 
130
-	/**
131
-	 * Returns the AppId for the App Store for the iOS Client
132
-	 * @return string AppId
133
-	 */
134
-	public function getiTunesAppId() {
135
-		if ($this->themeExist('getiTunesAppId')) {
136
-			return $this->theme->getiTunesAppId();
137
-		} else {
138
-			return $this->defaultiTunesAppId;
139
-		}
140
-	}
130
+    /**
131
+     * Returns the AppId for the App Store for the iOS Client
132
+     * @return string AppId
133
+     */
134
+    public function getiTunesAppId() {
135
+        if ($this->themeExist('getiTunesAppId')) {
136
+            return $this->theme->getiTunesAppId();
137
+        } else {
138
+            return $this->defaultiTunesAppId;
139
+        }
140
+    }
141 141
 
142
-	/**
143
-	 * Returns the URL to Google Play for the Android Client
144
-	 * @return string URL
145
-	 */
146
-	public function getAndroidClientUrl() {
147
-		if ($this->themeExist('getAndroidClientUrl')) {
148
-			return $this->theme->getAndroidClientUrl();
149
-		} else {
150
-			return $this->defaultAndroidClientUrl;
151
-		}
152
-	}
142
+    /**
143
+     * Returns the URL to Google Play for the Android Client
144
+     * @return string URL
145
+     */
146
+    public function getAndroidClientUrl() {
147
+        if ($this->themeExist('getAndroidClientUrl')) {
148
+            return $this->theme->getAndroidClientUrl();
149
+        } else {
150
+            return $this->defaultAndroidClientUrl;
151
+        }
152
+    }
153 153
 
154
-	/**
155
-	 * Returns the documentation URL
156
-	 * @return string URL
157
-	 */
158
-	public function getDocBaseUrl() {
159
-		if ($this->themeExist('getDocBaseUrl')) {
160
-			return $this->theme->getDocBaseUrl();
161
-		} else {
162
-			return $this->defaultDocBaseUrl;
163
-		}
164
-	}
154
+    /**
155
+     * Returns the documentation URL
156
+     * @return string URL
157
+     */
158
+    public function getDocBaseUrl() {
159
+        if ($this->themeExist('getDocBaseUrl')) {
160
+            return $this->theme->getDocBaseUrl();
161
+        } else {
162
+            return $this->defaultDocBaseUrl;
163
+        }
164
+    }
165 165
 
166
-	/**
167
-	 * Returns the title
168
-	 * @return string title
169
-	 */
170
-	public function getTitle() {
171
-		if ($this->themeExist('getTitle')) {
172
-			return $this->theme->getTitle();
173
-		} else {
174
-			return $this->defaultTitle;
175
-		}
176
-	}
166
+    /**
167
+     * Returns the title
168
+     * @return string title
169
+     */
170
+    public function getTitle() {
171
+        if ($this->themeExist('getTitle')) {
172
+            return $this->theme->getTitle();
173
+        } else {
174
+            return $this->defaultTitle;
175
+        }
176
+    }
177 177
 
178
-	/**
179
-	 * Returns the short name of the software
180
-	 * @return string title
181
-	 */
182
-	public function getName() {
183
-		if ($this->themeExist('getName')) {
184
-			return $this->theme->getName();
185
-		} else {
186
-			return $this->defaultName;
187
-		}
188
-	}
178
+    /**
179
+     * Returns the short name of the software
180
+     * @return string title
181
+     */
182
+    public function getName() {
183
+        if ($this->themeExist('getName')) {
184
+            return $this->theme->getName();
185
+        } else {
186
+            return $this->defaultName;
187
+        }
188
+    }
189 189
 
190
-	/**
191
-	 * Returns the short name of the software containing HTML strings
192
-	 * @return string title
193
-	 */
194
-	public function getHTMLName() {
195
-		if ($this->themeExist('getHTMLName')) {
196
-			return $this->theme->getHTMLName();
197
-		} else {
198
-			return $this->defaultName;
199
-		}
200
-	}
190
+    /**
191
+     * Returns the short name of the software containing HTML strings
192
+     * @return string title
193
+     */
194
+    public function getHTMLName() {
195
+        if ($this->themeExist('getHTMLName')) {
196
+            return $this->theme->getHTMLName();
197
+        } else {
198
+            return $this->defaultName;
199
+        }
200
+    }
201 201
 
202
-	/**
203
-	 * Returns entity (e.g. company name) - used for footer, copyright
204
-	 * @return string entity name
205
-	 */
206
-	public function getEntity() {
207
-		if ($this->themeExist('getEntity')) {
208
-			return $this->theme->getEntity();
209
-		} else {
210
-			return $this->defaultEntity;
211
-		}
212
-	}
202
+    /**
203
+     * Returns entity (e.g. company name) - used for footer, copyright
204
+     * @return string entity name
205
+     */
206
+    public function getEntity() {
207
+        if ($this->themeExist('getEntity')) {
208
+            return $this->theme->getEntity();
209
+        } else {
210
+            return $this->defaultEntity;
211
+        }
212
+    }
213 213
 
214
-	/**
215
-	 * Returns slogan
216
-	 * @return string slogan
217
-	 */
218
-	public function getSlogan() {
219
-		if ($this->themeExist('getSlogan')) {
220
-			return $this->theme->getSlogan();
221
-		} else {
222
-			return $this->defaultSlogan;
223
-		}
224
-	}
214
+    /**
215
+     * Returns slogan
216
+     * @return string slogan
217
+     */
218
+    public function getSlogan() {
219
+        if ($this->themeExist('getSlogan')) {
220
+            return $this->theme->getSlogan();
221
+        } else {
222
+            return $this->defaultSlogan;
223
+        }
224
+    }
225 225
 
226
-	/**
227
-	 * Returns logo claim
228
-	 * @return string logo claim
229
-	 */
230
-	public function getLogoClaim() {
231
-		if ($this->themeExist('getLogoClaim')) {
232
-			return $this->theme->getLogoClaim();
233
-		} else {
234
-			return $this->defaultLogoClaim;
235
-		}
236
-	}
226
+    /**
227
+     * Returns logo claim
228
+     * @return string logo claim
229
+     */
230
+    public function getLogoClaim() {
231
+        if ($this->themeExist('getLogoClaim')) {
232
+            return $this->theme->getLogoClaim();
233
+        } else {
234
+            return $this->defaultLogoClaim;
235
+        }
236
+    }
237 237
 
238
-	/**
239
-	 * Returns short version of the footer
240
-	 * @return string short footer
241
-	 */
242
-	public function getShortFooter() {
243
-		if ($this->themeExist('getShortFooter')) {
244
-			$footer = $this->theme->getShortFooter();
245
-		} else {
246
-			$footer = '<a href="'. $this->getBaseUrl() . '" target="_blank"' .
247
-				' rel="noreferrer">' .$this->getEntity() . '</a>'.
248
-				' – ' . $this->getSlogan();
249
-		}
238
+    /**
239
+     * Returns short version of the footer
240
+     * @return string short footer
241
+     */
242
+    public function getShortFooter() {
243
+        if ($this->themeExist('getShortFooter')) {
244
+            $footer = $this->theme->getShortFooter();
245
+        } else {
246
+            $footer = '<a href="'. $this->getBaseUrl() . '" target="_blank"' .
247
+                ' rel="noreferrer">' .$this->getEntity() . '</a>'.
248
+                ' – ' . $this->getSlogan();
249
+        }
250 250
 
251
-		return $footer;
252
-	}
251
+        return $footer;
252
+    }
253 253
 
254
-	/**
255
-	 * Returns long version of the footer
256
-	 * @return string long footer
257
-	 */
258
-	public function getLongFooter() {
259
-		if ($this->themeExist('getLongFooter')) {
260
-			$footer = $this->theme->getLongFooter();
261
-		} else {
262
-			$footer = $this->getShortFooter();
263
-		}
254
+    /**
255
+     * Returns long version of the footer
256
+     * @return string long footer
257
+     */
258
+    public function getLongFooter() {
259
+        if ($this->themeExist('getLongFooter')) {
260
+            $footer = $this->theme->getLongFooter();
261
+        } else {
262
+            $footer = $this->getShortFooter();
263
+        }
264 264
 
265
-		return $footer;
266
-	}
265
+        return $footer;
266
+    }
267 267
 
268
-	/**
269
-	 * @param string $key
270
-	 * @return string URL to doc with key
271
-	 */
272
-	public function buildDocLinkToKey($key) {
273
-		if ($this->themeExist('buildDocLinkToKey')) {
274
-			return $this->theme->buildDocLinkToKey($key);
275
-		}
276
-		return $this->getDocBaseUrl() . '/server/' . $this->defaultDocVersion . '/go.php?to=' . $key;
277
-	}
268
+    /**
269
+     * @param string $key
270
+     * @return string URL to doc with key
271
+     */
272
+    public function buildDocLinkToKey($key) {
273
+        if ($this->themeExist('buildDocLinkToKey')) {
274
+            return $this->theme->buildDocLinkToKey($key);
275
+        }
276
+        return $this->getDocBaseUrl() . '/server/' . $this->defaultDocVersion . '/go.php?to=' . $key;
277
+    }
278 278
 
279
-	/**
280
-	 * Returns primary color
281
-	 * @return string
282
-	 */
283
-	public function getColorPrimary() {
279
+    /**
280
+     * Returns primary color
281
+     * @return string
282
+     */
283
+    public function getColorPrimary() {
284 284
 
285
-		if ($this->themeExist('getColorPrimary')) {
286
-			return $this->theme->getColorPrimary();
287
-		}
288
-		if ($this->themeExist('getMailHeaderColor')) {
289
-			return $this->theme->getMailHeaderColor();
290
-		}
291
-		return $this->defaultColorPrimary;
292
-	}
285
+        if ($this->themeExist('getColorPrimary')) {
286
+            return $this->theme->getColorPrimary();
287
+        }
288
+        if ($this->themeExist('getMailHeaderColor')) {
289
+            return $this->theme->getMailHeaderColor();
290
+        }
291
+        return $this->defaultColorPrimary;
292
+    }
293 293
 
294
-	public function shouldReplaceIcons() {
295
-		return false;
296
-	}
294
+    public function shouldReplaceIcons() {
295
+        return false;
296
+    }
297 297
 
298
-	/**
299
-	 * Themed logo url
300
-	 *
301
-	 * @return string
302
-	 */
303
-	public function getLogo() {
304
-		if ($this->themeExist('getLogo')) {
305
-			return $this->theme->getLogo();
306
-		}
298
+    /**
299
+     * Themed logo url
300
+     *
301
+     * @return string
302
+     */
303
+    public function getLogo() {
304
+        if ($this->themeExist('getLogo')) {
305
+            return $this->theme->getLogo();
306
+        }
307 307
 
308
-		return $this->defaultLogoUrl;
309
-	}
308
+        return $this->defaultLogoUrl;
309
+    }
310 310
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -66,10 +66,10 @@  discard block
 block discarded – undo
66 66
 		$this->defaultSlogan = $this->l->t('a safe home for all your data');
67 67
 		$this->defaultLogoClaim = '';
68 68
 		$this->defaultColorPrimary = '#0082c9';
69
-		$this->defaultLogoUrl = \OC::$server->getURLGenerator()->imagePath('core','logo.svg');
70
-		$this->defaultLogoUrl .=  '?v=' . hash('sha1', implode('.', \OCP\Util::getVersion()));
69
+		$this->defaultLogoUrl = \OC::$server->getURLGenerator()->imagePath('core', 'logo.svg');
70
+		$this->defaultLogoUrl .= '?v='.hash('sha1', implode('.', \OCP\Util::getVersion()));
71 71
 
72
-		$themePath = OC::$SERVERROOT . '/themes/' . OC_Util::getTheme() . '/defaults.php';
72
+		$themePath = OC::$SERVERROOT.'/themes/'.OC_Util::getTheme().'/defaults.php';
73 73
 		if (file_exists($themePath)) {
74 74
 			// prevent defaults.php from printing output
75 75
 			ob_start();
@@ -243,9 +243,9 @@  discard block
 block discarded – undo
243 243
 		if ($this->themeExist('getShortFooter')) {
244 244
 			$footer = $this->theme->getShortFooter();
245 245
 		} else {
246
-			$footer = '<a href="'. $this->getBaseUrl() . '" target="_blank"' .
247
-				' rel="noreferrer">' .$this->getEntity() . '</a>'.
248
-				' – ' . $this->getSlogan();
246
+			$footer = '<a href="'.$this->getBaseUrl().'" target="_blank"'.
247
+				' rel="noreferrer">'.$this->getEntity().'</a>'.
248
+				' – '.$this->getSlogan();
249 249
 		}
250 250
 
251 251
 		return $footer;
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
 		if ($this->themeExist('buildDocLinkToKey')) {
274 274
 			return $this->theme->buildDocLinkToKey($key);
275 275
 		}
276
-		return $this->getDocBaseUrl() . '/server/' . $this->defaultDocVersion . '/go.php?to=' . $key;
276
+		return $this->getDocBaseUrl().'/server/'.$this->defaultDocVersion.'/go.php?to='.$key;
277 277
 	}
278 278
 
279 279
 	/**
Please login to merge, or discard this patch.
lib/private/Setup.php 1 patch
Indentation   +465 added lines, -465 removed lines patch added patch discarded remove patch
@@ -47,469 +47,469 @@
 block discarded – undo
47 47
 use OCP\Security\ISecureRandom;
48 48
 
49 49
 class Setup {
50
-	/** @var SystemConfig */
51
-	protected $config;
52
-	/** @var IniGetWrapper */
53
-	protected $iniWrapper;
54
-	/** @var IL10N */
55
-	protected $l10n;
56
-	/** @var Defaults */
57
-	protected $defaults;
58
-	/** @var ILogger */
59
-	protected $logger;
60
-	/** @var ISecureRandom */
61
-	protected $random;
62
-
63
-	/**
64
-	 * @param SystemConfig $config
65
-	 * @param IniGetWrapper $iniWrapper
66
-	 * @param Defaults $defaults
67
-	 * @param ILogger $logger
68
-	 * @param ISecureRandom $random
69
-	 */
70
-	function __construct(SystemConfig $config,
71
-						 IniGetWrapper $iniWrapper,
72
-						 IL10N $l10n,
73
-						 Defaults $defaults,
74
-						 ILogger $logger,
75
-						 ISecureRandom $random
76
-		) {
77
-		$this->config = $config;
78
-		$this->iniWrapper = $iniWrapper;
79
-		$this->l10n = $l10n;
80
-		$this->defaults = $defaults;
81
-		$this->logger = $logger;
82
-		$this->random = $random;
83
-	}
84
-
85
-	static $dbSetupClasses = [
86
-		'mysql' => \OC\Setup\MySQL::class,
87
-		'pgsql' => \OC\Setup\PostgreSQL::class,
88
-		'oci'   => \OC\Setup\OCI::class,
89
-		'sqlite' => \OC\Setup\Sqlite::class,
90
-		'sqlite3' => \OC\Setup\Sqlite::class,
91
-	];
92
-
93
-	/**
94
-	 * Wrapper around the "class_exists" PHP function to be able to mock it
95
-	 * @param string $name
96
-	 * @return bool
97
-	 */
98
-	protected function class_exists($name) {
99
-		return class_exists($name);
100
-	}
101
-
102
-	/**
103
-	 * Wrapper around the "is_callable" PHP function to be able to mock it
104
-	 * @param string $name
105
-	 * @return bool
106
-	 */
107
-	protected function is_callable($name) {
108
-		return is_callable($name);
109
-	}
110
-
111
-	/**
112
-	 * Wrapper around \PDO::getAvailableDrivers
113
-	 *
114
-	 * @return array
115
-	 */
116
-	protected function getAvailableDbDriversForPdo() {
117
-		return \PDO::getAvailableDrivers();
118
-	}
119
-
120
-	/**
121
-	 * Get the available and supported databases of this instance
122
-	 *
123
-	 * @param bool $allowAllDatabases
124
-	 * @return array
125
-	 * @throws Exception
126
-	 */
127
-	public function getSupportedDatabases($allowAllDatabases = false) {
128
-		$availableDatabases = array(
129
-			'sqlite' =>  array(
130
-				'type' => 'pdo',
131
-				'call' => 'sqlite',
132
-				'name' => 'SQLite'
133
-			),
134
-			'mysql' => array(
135
-				'type' => 'pdo',
136
-				'call' => 'mysql',
137
-				'name' => 'MySQL/MariaDB'
138
-			),
139
-			'pgsql' => array(
140
-				'type' => 'pdo',
141
-				'call' => 'pgsql',
142
-				'name' => 'PostgreSQL'
143
-			),
144
-			'oci' => array(
145
-				'type' => 'function',
146
-				'call' => 'oci_connect',
147
-				'name' => 'Oracle'
148
-			)
149
-		);
150
-		if ($allowAllDatabases) {
151
-			$configuredDatabases = array_keys($availableDatabases);
152
-		} else {
153
-			$configuredDatabases = $this->config->getValue('supportedDatabases',
154
-				array('sqlite', 'mysql', 'pgsql'));
155
-		}
156
-		if(!is_array($configuredDatabases)) {
157
-			throw new Exception('Supported databases are not properly configured.');
158
-		}
159
-
160
-		$supportedDatabases = array();
161
-
162
-		foreach($configuredDatabases as $database) {
163
-			if(array_key_exists($database, $availableDatabases)) {
164
-				$working = false;
165
-				$type = $availableDatabases[$database]['type'];
166
-				$call = $availableDatabases[$database]['call'];
167
-
168
-				if ($type === 'function') {
169
-					$working = $this->is_callable($call);
170
-				} elseif($type === 'pdo') {
171
-					$working = in_array($call, $this->getAvailableDbDriversForPdo(), TRUE);
172
-				}
173
-				if($working) {
174
-					$supportedDatabases[$database] = $availableDatabases[$database]['name'];
175
-				}
176
-			}
177
-		}
178
-
179
-		return $supportedDatabases;
180
-	}
181
-
182
-	/**
183
-	 * Gathers system information like database type and does
184
-	 * a few system checks.
185
-	 *
186
-	 * @return array of system info, including an "errors" value
187
-	 * in case of errors/warnings
188
-	 */
189
-	public function getSystemInfo($allowAllDatabases = false) {
190
-		$databases = $this->getSupportedDatabases($allowAllDatabases);
191
-
192
-		$dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT.'/data');
193
-
194
-		$errors = array();
195
-
196
-		// Create data directory to test whether the .htaccess works
197
-		// Notice that this is not necessarily the same data directory as the one
198
-		// that will effectively be used.
199
-		if(!file_exists($dataDir)) {
200
-			@mkdir($dataDir);
201
-		}
202
-		$htAccessWorking = true;
203
-		if (is_dir($dataDir) && is_writable($dataDir)) {
204
-			// Protect data directory here, so we can test if the protection is working
205
-			\OC\Setup::protectDataDirectory();
206
-
207
-			try {
208
-				$util = new \OC_Util();
209
-				$htAccessWorking = $util->isHtaccessWorking(\OC::$server->getConfig());
210
-			} catch (\OC\HintException $e) {
211
-				$errors[] = array(
212
-					'error' => $e->getMessage(),
213
-					'hint' => $e->getHint()
214
-				);
215
-				$htAccessWorking = false;
216
-			}
217
-		}
218
-
219
-		if (\OC_Util::runningOnMac()) {
220
-			$errors[] = array(
221
-				'error' => $this->l10n->t(
222
-					'Mac OS X is not supported and %s will not work properly on this platform. ' .
223
-					'Use it at your own risk! ',
224
-					$this->defaults->getName()
225
-				),
226
-				'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.')
227
-			);
228
-		}
229
-
230
-		if($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) {
231
-			$errors[] = array(
232
-				'error' => $this->l10n->t(
233
-					'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' .
234
-					'This will lead to problems with files over 4 GB and is highly discouraged.',
235
-					$this->defaults->getName()
236
-				),
237
-				'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.')
238
-			);
239
-		}
240
-
241
-		return array(
242
-			'hasSQLite' => isset($databases['sqlite']),
243
-			'hasMySQL' => isset($databases['mysql']),
244
-			'hasPostgreSQL' => isset($databases['pgsql']),
245
-			'hasOracle' => isset($databases['oci']),
246
-			'databases' => $databases,
247
-			'directory' => $dataDir,
248
-			'htaccessWorking' => $htAccessWorking,
249
-			'errors' => $errors,
250
-		);
251
-	}
252
-
253
-	/**
254
-	 * @param $options
255
-	 * @return array
256
-	 */
257
-	public function install($options) {
258
-		$l = $this->l10n;
259
-
260
-		$error = array();
261
-		$dbType = $options['dbtype'];
262
-
263
-		if(empty($options['adminlogin'])) {
264
-			$error[] = $l->t('Set an admin username.');
265
-		}
266
-		if(empty($options['adminpass'])) {
267
-			$error[] = $l->t('Set an admin password.');
268
-		}
269
-		if(empty($options['directory'])) {
270
-			$options['directory'] = \OC::$SERVERROOT."/data";
271
-		}
272
-
273
-		if (!isset(self::$dbSetupClasses[$dbType])) {
274
-			$dbType = 'sqlite';
275
-		}
276
-
277
-		$username = htmlspecialchars_decode($options['adminlogin']);
278
-		$password = htmlspecialchars_decode($options['adminpass']);
279
-		$dataDir = htmlspecialchars_decode($options['directory']);
280
-
281
-		$class = self::$dbSetupClasses[$dbType];
282
-		/** @var \OC\Setup\AbstractDatabase $dbSetup */
283
-		$dbSetup = new $class($l, 'db_structure.xml', $this->config,
284
-			$this->logger, $this->random);
285
-		$error = array_merge($error, $dbSetup->validate($options));
286
-
287
-		// validate the data directory
288
-		if (
289
-			(!is_dir($dataDir) and !mkdir($dataDir)) or
290
-			!is_writable($dataDir)
291
-		) {
292
-			$error[] = $l->t("Can't create or write into the data directory %s", array($dataDir));
293
-		}
294
-
295
-		if(count($error) != 0) {
296
-			return $error;
297
-		}
298
-
299
-		$request = \OC::$server->getRequest();
300
-
301
-		//no errors, good
302
-		if(isset($options['trusted_domains'])
303
-		    && is_array($options['trusted_domains'])) {
304
-			$trustedDomains = $options['trusted_domains'];
305
-		} else {
306
-			$trustedDomains = [$request->getInsecureServerHost()];
307
-		}
308
-
309
-		//use sqlite3 when available, otherwise sqlite2 will be used.
310
-		if($dbType=='sqlite' and class_exists('SQLite3')) {
311
-			$dbType='sqlite3';
312
-		}
313
-
314
-		//generate a random salt that is used to salt the local user passwords
315
-		$salt = $this->random->generate(30);
316
-		// generate a secret
317
-		$secret = $this->random->generate(48);
318
-
319
-		//write the config file
320
-		$this->config->setValues([
321
-			'passwordsalt'		=> $salt,
322
-			'secret'			=> $secret,
323
-			'trusted_domains'	=> $trustedDomains,
324
-			'datadirectory'		=> $dataDir,
325
-			'overwrite.cli.url'	=> $request->getServerProtocol() . '://' . $request->getInsecureServerHost() . \OC::$WEBROOT,
326
-			'dbtype'			=> $dbType,
327
-			'version'			=> implode('.', \OCP\Util::getVersion()),
328
-		]);
329
-
330
-		try {
331
-			$dbSetup->initialize($options);
332
-			$dbSetup->setupDatabase($username);
333
-		} catch (\OC\DatabaseSetupException $e) {
334
-			$error[] = array(
335
-				'error' => $e->getMessage(),
336
-				'hint' => $e->getHint()
337
-			);
338
-			return($error);
339
-		} catch (Exception $e) {
340
-			$error[] = array(
341
-				'error' => 'Error while trying to create admin user: ' . $e->getMessage(),
342
-				'hint' => ''
343
-			);
344
-			return($error);
345
-		}
346
-
347
-		//create the user and group
348
-		$user =  null;
349
-		try {
350
-			$user = \OC::$server->getUserManager()->createUser($username, $password);
351
-			if (!$user) {
352
-				$error[] = "User <$username> could not be created.";
353
-			}
354
-		} catch(Exception $exception) {
355
-			$error[] = $exception->getMessage();
356
-		}
357
-
358
-		if(count($error) == 0) {
359
-			$config = \OC::$server->getConfig();
360
-			$config->setAppValue('core', 'installedat', microtime(true));
361
-			$config->setAppValue('core', 'lastupdatedat', microtime(true));
362
-			$config->setAppValue('core', 'vendor', $this->getVendor());
363
-
364
-			$group =\OC::$server->getGroupManager()->createGroup('admin');
365
-			$group->addUser($user);
366
-
367
-			//guess what this does
368
-			Installer::installShippedApps();
369
-
370
-			// create empty file in data dir, so we can later find
371
-			// out that this is indeed an ownCloud data directory
372
-			file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data').'/.ocdata', '');
373
-
374
-			// Update .htaccess files
375
-			Setup::updateHtaccess();
376
-			Setup::protectDataDirectory();
377
-
378
-			self::installBackgroundJobs();
379
-
380
-			//and we are done
381
-			$config->setSystemValue('installed', true);
382
-
383
-			// Create a session token for the newly created user
384
-			// The token provider requires a working db, so it's not injected on setup
385
-			/* @var $userSession User\Session */
386
-			$userSession = \OC::$server->getUserSession();
387
-			$defaultTokenProvider = \OC::$server->query('OC\Authentication\Token\DefaultTokenProvider');
388
-			$userSession->setTokenProvider($defaultTokenProvider);
389
-			$userSession->login($username, $password);
390
-			$userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password);
391
-		}
392
-
393
-		return $error;
394
-	}
395
-
396
-	public static function installBackgroundJobs() {
397
-		\OC::$server->getJobList()->add('\OC\Authentication\Token\DefaultTokenCleanupJob');
398
-	}
399
-
400
-	/**
401
-	 * @return string Absolute path to htaccess
402
-	 */
403
-	private function pathToHtaccess() {
404
-		return \OC::$SERVERROOT.'/.htaccess';
405
-	}
406
-
407
-	/**
408
-	 * Append the correct ErrorDocument path for Apache hosts
409
-	 * @return bool True when success, False otherwise
410
-	 */
411
-	public static function updateHtaccess() {
412
-		$config = \OC::$server->getSystemConfig();
413
-
414
-		// For CLI read the value from overwrite.cli.url
415
-		if(\OC::$CLI) {
416
-			$webRoot = $config->getValue('overwrite.cli.url', '');
417
-			if($webRoot === '') {
418
-				return false;
419
-			}
420
-			$webRoot = parse_url($webRoot, PHP_URL_PATH);
421
-			$webRoot = rtrim($webRoot, '/');
422
-		} else {
423
-			$webRoot = !empty(\OC::$WEBROOT) ? \OC::$WEBROOT : '/';
424
-		}
425
-
426
-		$setupHelper = new \OC\Setup($config, \OC::$server->getIniWrapper(),
427
-			\OC::$server->getL10N('lib'), \OC::$server->query(Defaults::class), \OC::$server->getLogger(),
428
-			\OC::$server->getSecureRandom());
429
-
430
-		$htaccessContent = file_get_contents($setupHelper->pathToHtaccess());
431
-		$content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n";
432
-		$htaccessContent = explode($content, $htaccessContent, 2)[0];
433
-
434
-		//custom 403 error page
435
-		$content.= "\nErrorDocument 403 ".$webRoot."/core/templates/403.php";
436
-
437
-		//custom 404 error page
438
-		$content.= "\nErrorDocument 404 ".$webRoot."/core/templates/404.php";
439
-
440
-		// Add rewrite rules if the RewriteBase is configured
441
-		$rewriteBase = $config->getValue('htaccess.RewriteBase', '');
442
-		if($rewriteBase !== '') {
443
-			$content .= "\n<IfModule mod_rewrite.c>";
444
-			$content .= "\n  Options -MultiViews";
445
-			$content .= "\n  RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]";
446
-			$content .= "\n  RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]";
447
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !\\.(css|js|svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$";
448
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$";
449
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/remote.php";
450
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/public.php";
451
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/cron.php";
452
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php";
453
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/status.php";
454
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php";
455
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php";
456
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/robots.txt";
457
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/updater/";
458
-			$content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs-provider/";
459
-			$content .= "\n  RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.*";
460
-			$content .= "\n  RewriteRule . index.php [PT,E=PATH_INFO:$1]";
461
-			$content .= "\n  RewriteBase " . $rewriteBase;
462
-			$content .= "\n  <IfModule mod_env.c>";
463
-			$content .= "\n    SetEnv front_controller_active true";
464
-			$content .= "\n    <IfModule mod_dir.c>";
465
-			$content .= "\n      DirectorySlash off";
466
-			$content .= "\n    </IfModule>";
467
-			$content .= "\n  </IfModule>";
468
-			$content .= "\n</IfModule>";
469
-		}
470
-
471
-		if ($content !== '') {
472
-			//suppress errors in case we don't have permissions for it
473
-			return (bool) @file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent.$content . "\n");
474
-		}
475
-
476
-		return false;
477
-	}
478
-
479
-	public static function protectDataDirectory() {
480
-		//Require all denied
481
-		$now =  date('Y-m-d H:i:s');
482
-		$content = "# Generated by Nextcloud on $now\n";
483
-		$content.= "# line below if for Apache 2.4\n";
484
-		$content.= "<ifModule mod_authz_core.c>\n";
485
-		$content.= "Require all denied\n";
486
-		$content.= "</ifModule>\n\n";
487
-		$content.= "# line below if for Apache 2.2\n";
488
-		$content.= "<ifModule !mod_authz_core.c>\n";
489
-		$content.= "deny from all\n";
490
-		$content.= "Satisfy All\n";
491
-		$content.= "</ifModule>\n\n";
492
-		$content.= "# section for Apache 2.2 and 2.4\n";
493
-		$content.= "<ifModule mod_autoindex.c>\n";
494
-		$content.= "IndexIgnore *\n";
495
-		$content.= "</ifModule>\n";
496
-
497
-		$baseDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
498
-		file_put_contents($baseDir . '/.htaccess', $content);
499
-		file_put_contents($baseDir . '/index.html', '');
500
-	}
501
-
502
-	/**
503
-	 * Return vendor from which this version was published
504
-	 *
505
-	 * @return string Get the vendor
506
-	 *
507
-	 * Copy of \OC\Updater::getVendor()
508
-	 */
509
-	private function getVendor() {
510
-		// this should really be a JSON file
511
-		require \OC::$SERVERROOT . '/version.php';
512
-		/** @var string $vendor */
513
-		return (string) $vendor;
514
-	}
50
+    /** @var SystemConfig */
51
+    protected $config;
52
+    /** @var IniGetWrapper */
53
+    protected $iniWrapper;
54
+    /** @var IL10N */
55
+    protected $l10n;
56
+    /** @var Defaults */
57
+    protected $defaults;
58
+    /** @var ILogger */
59
+    protected $logger;
60
+    /** @var ISecureRandom */
61
+    protected $random;
62
+
63
+    /**
64
+     * @param SystemConfig $config
65
+     * @param IniGetWrapper $iniWrapper
66
+     * @param Defaults $defaults
67
+     * @param ILogger $logger
68
+     * @param ISecureRandom $random
69
+     */
70
+    function __construct(SystemConfig $config,
71
+                            IniGetWrapper $iniWrapper,
72
+                            IL10N $l10n,
73
+                            Defaults $defaults,
74
+                            ILogger $logger,
75
+                            ISecureRandom $random
76
+        ) {
77
+        $this->config = $config;
78
+        $this->iniWrapper = $iniWrapper;
79
+        $this->l10n = $l10n;
80
+        $this->defaults = $defaults;
81
+        $this->logger = $logger;
82
+        $this->random = $random;
83
+    }
84
+
85
+    static $dbSetupClasses = [
86
+        'mysql' => \OC\Setup\MySQL::class,
87
+        'pgsql' => \OC\Setup\PostgreSQL::class,
88
+        'oci'   => \OC\Setup\OCI::class,
89
+        'sqlite' => \OC\Setup\Sqlite::class,
90
+        'sqlite3' => \OC\Setup\Sqlite::class,
91
+    ];
92
+
93
+    /**
94
+     * Wrapper around the "class_exists" PHP function to be able to mock it
95
+     * @param string $name
96
+     * @return bool
97
+     */
98
+    protected function class_exists($name) {
99
+        return class_exists($name);
100
+    }
101
+
102
+    /**
103
+     * Wrapper around the "is_callable" PHP function to be able to mock it
104
+     * @param string $name
105
+     * @return bool
106
+     */
107
+    protected function is_callable($name) {
108
+        return is_callable($name);
109
+    }
110
+
111
+    /**
112
+     * Wrapper around \PDO::getAvailableDrivers
113
+     *
114
+     * @return array
115
+     */
116
+    protected function getAvailableDbDriversForPdo() {
117
+        return \PDO::getAvailableDrivers();
118
+    }
119
+
120
+    /**
121
+     * Get the available and supported databases of this instance
122
+     *
123
+     * @param bool $allowAllDatabases
124
+     * @return array
125
+     * @throws Exception
126
+     */
127
+    public function getSupportedDatabases($allowAllDatabases = false) {
128
+        $availableDatabases = array(
129
+            'sqlite' =>  array(
130
+                'type' => 'pdo',
131
+                'call' => 'sqlite',
132
+                'name' => 'SQLite'
133
+            ),
134
+            'mysql' => array(
135
+                'type' => 'pdo',
136
+                'call' => 'mysql',
137
+                'name' => 'MySQL/MariaDB'
138
+            ),
139
+            'pgsql' => array(
140
+                'type' => 'pdo',
141
+                'call' => 'pgsql',
142
+                'name' => 'PostgreSQL'
143
+            ),
144
+            'oci' => array(
145
+                'type' => 'function',
146
+                'call' => 'oci_connect',
147
+                'name' => 'Oracle'
148
+            )
149
+        );
150
+        if ($allowAllDatabases) {
151
+            $configuredDatabases = array_keys($availableDatabases);
152
+        } else {
153
+            $configuredDatabases = $this->config->getValue('supportedDatabases',
154
+                array('sqlite', 'mysql', 'pgsql'));
155
+        }
156
+        if(!is_array($configuredDatabases)) {
157
+            throw new Exception('Supported databases are not properly configured.');
158
+        }
159
+
160
+        $supportedDatabases = array();
161
+
162
+        foreach($configuredDatabases as $database) {
163
+            if(array_key_exists($database, $availableDatabases)) {
164
+                $working = false;
165
+                $type = $availableDatabases[$database]['type'];
166
+                $call = $availableDatabases[$database]['call'];
167
+
168
+                if ($type === 'function') {
169
+                    $working = $this->is_callable($call);
170
+                } elseif($type === 'pdo') {
171
+                    $working = in_array($call, $this->getAvailableDbDriversForPdo(), TRUE);
172
+                }
173
+                if($working) {
174
+                    $supportedDatabases[$database] = $availableDatabases[$database]['name'];
175
+                }
176
+            }
177
+        }
178
+
179
+        return $supportedDatabases;
180
+    }
181
+
182
+    /**
183
+     * Gathers system information like database type and does
184
+     * a few system checks.
185
+     *
186
+     * @return array of system info, including an "errors" value
187
+     * in case of errors/warnings
188
+     */
189
+    public function getSystemInfo($allowAllDatabases = false) {
190
+        $databases = $this->getSupportedDatabases($allowAllDatabases);
191
+
192
+        $dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT.'/data');
193
+
194
+        $errors = array();
195
+
196
+        // Create data directory to test whether the .htaccess works
197
+        // Notice that this is not necessarily the same data directory as the one
198
+        // that will effectively be used.
199
+        if(!file_exists($dataDir)) {
200
+            @mkdir($dataDir);
201
+        }
202
+        $htAccessWorking = true;
203
+        if (is_dir($dataDir) && is_writable($dataDir)) {
204
+            // Protect data directory here, so we can test if the protection is working
205
+            \OC\Setup::protectDataDirectory();
206
+
207
+            try {
208
+                $util = new \OC_Util();
209
+                $htAccessWorking = $util->isHtaccessWorking(\OC::$server->getConfig());
210
+            } catch (\OC\HintException $e) {
211
+                $errors[] = array(
212
+                    'error' => $e->getMessage(),
213
+                    'hint' => $e->getHint()
214
+                );
215
+                $htAccessWorking = false;
216
+            }
217
+        }
218
+
219
+        if (\OC_Util::runningOnMac()) {
220
+            $errors[] = array(
221
+                'error' => $this->l10n->t(
222
+                    'Mac OS X is not supported and %s will not work properly on this platform. ' .
223
+                    'Use it at your own risk! ',
224
+                    $this->defaults->getName()
225
+                ),
226
+                'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.')
227
+            );
228
+        }
229
+
230
+        if($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) {
231
+            $errors[] = array(
232
+                'error' => $this->l10n->t(
233
+                    'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' .
234
+                    'This will lead to problems with files over 4 GB and is highly discouraged.',
235
+                    $this->defaults->getName()
236
+                ),
237
+                'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.')
238
+            );
239
+        }
240
+
241
+        return array(
242
+            'hasSQLite' => isset($databases['sqlite']),
243
+            'hasMySQL' => isset($databases['mysql']),
244
+            'hasPostgreSQL' => isset($databases['pgsql']),
245
+            'hasOracle' => isset($databases['oci']),
246
+            'databases' => $databases,
247
+            'directory' => $dataDir,
248
+            'htaccessWorking' => $htAccessWorking,
249
+            'errors' => $errors,
250
+        );
251
+    }
252
+
253
+    /**
254
+     * @param $options
255
+     * @return array
256
+     */
257
+    public function install($options) {
258
+        $l = $this->l10n;
259
+
260
+        $error = array();
261
+        $dbType = $options['dbtype'];
262
+
263
+        if(empty($options['adminlogin'])) {
264
+            $error[] = $l->t('Set an admin username.');
265
+        }
266
+        if(empty($options['adminpass'])) {
267
+            $error[] = $l->t('Set an admin password.');
268
+        }
269
+        if(empty($options['directory'])) {
270
+            $options['directory'] = \OC::$SERVERROOT."/data";
271
+        }
272
+
273
+        if (!isset(self::$dbSetupClasses[$dbType])) {
274
+            $dbType = 'sqlite';
275
+        }
276
+
277
+        $username = htmlspecialchars_decode($options['adminlogin']);
278
+        $password = htmlspecialchars_decode($options['adminpass']);
279
+        $dataDir = htmlspecialchars_decode($options['directory']);
280
+
281
+        $class = self::$dbSetupClasses[$dbType];
282
+        /** @var \OC\Setup\AbstractDatabase $dbSetup */
283
+        $dbSetup = new $class($l, 'db_structure.xml', $this->config,
284
+            $this->logger, $this->random);
285
+        $error = array_merge($error, $dbSetup->validate($options));
286
+
287
+        // validate the data directory
288
+        if (
289
+            (!is_dir($dataDir) and !mkdir($dataDir)) or
290
+            !is_writable($dataDir)
291
+        ) {
292
+            $error[] = $l->t("Can't create or write into the data directory %s", array($dataDir));
293
+        }
294
+
295
+        if(count($error) != 0) {
296
+            return $error;
297
+        }
298
+
299
+        $request = \OC::$server->getRequest();
300
+
301
+        //no errors, good
302
+        if(isset($options['trusted_domains'])
303
+            && is_array($options['trusted_domains'])) {
304
+            $trustedDomains = $options['trusted_domains'];
305
+        } else {
306
+            $trustedDomains = [$request->getInsecureServerHost()];
307
+        }
308
+
309
+        //use sqlite3 when available, otherwise sqlite2 will be used.
310
+        if($dbType=='sqlite' and class_exists('SQLite3')) {
311
+            $dbType='sqlite3';
312
+        }
313
+
314
+        //generate a random salt that is used to salt the local user passwords
315
+        $salt = $this->random->generate(30);
316
+        // generate a secret
317
+        $secret = $this->random->generate(48);
318
+
319
+        //write the config file
320
+        $this->config->setValues([
321
+            'passwordsalt'		=> $salt,
322
+            'secret'			=> $secret,
323
+            'trusted_domains'	=> $trustedDomains,
324
+            'datadirectory'		=> $dataDir,
325
+            'overwrite.cli.url'	=> $request->getServerProtocol() . '://' . $request->getInsecureServerHost() . \OC::$WEBROOT,
326
+            'dbtype'			=> $dbType,
327
+            'version'			=> implode('.', \OCP\Util::getVersion()),
328
+        ]);
329
+
330
+        try {
331
+            $dbSetup->initialize($options);
332
+            $dbSetup->setupDatabase($username);
333
+        } catch (\OC\DatabaseSetupException $e) {
334
+            $error[] = array(
335
+                'error' => $e->getMessage(),
336
+                'hint' => $e->getHint()
337
+            );
338
+            return($error);
339
+        } catch (Exception $e) {
340
+            $error[] = array(
341
+                'error' => 'Error while trying to create admin user: ' . $e->getMessage(),
342
+                'hint' => ''
343
+            );
344
+            return($error);
345
+        }
346
+
347
+        //create the user and group
348
+        $user =  null;
349
+        try {
350
+            $user = \OC::$server->getUserManager()->createUser($username, $password);
351
+            if (!$user) {
352
+                $error[] = "User <$username> could not be created.";
353
+            }
354
+        } catch(Exception $exception) {
355
+            $error[] = $exception->getMessage();
356
+        }
357
+
358
+        if(count($error) == 0) {
359
+            $config = \OC::$server->getConfig();
360
+            $config->setAppValue('core', 'installedat', microtime(true));
361
+            $config->setAppValue('core', 'lastupdatedat', microtime(true));
362
+            $config->setAppValue('core', 'vendor', $this->getVendor());
363
+
364
+            $group =\OC::$server->getGroupManager()->createGroup('admin');
365
+            $group->addUser($user);
366
+
367
+            //guess what this does
368
+            Installer::installShippedApps();
369
+
370
+            // create empty file in data dir, so we can later find
371
+            // out that this is indeed an ownCloud data directory
372
+            file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data').'/.ocdata', '');
373
+
374
+            // Update .htaccess files
375
+            Setup::updateHtaccess();
376
+            Setup::protectDataDirectory();
377
+
378
+            self::installBackgroundJobs();
379
+
380
+            //and we are done
381
+            $config->setSystemValue('installed', true);
382
+
383
+            // Create a session token for the newly created user
384
+            // The token provider requires a working db, so it's not injected on setup
385
+            /* @var $userSession User\Session */
386
+            $userSession = \OC::$server->getUserSession();
387
+            $defaultTokenProvider = \OC::$server->query('OC\Authentication\Token\DefaultTokenProvider');
388
+            $userSession->setTokenProvider($defaultTokenProvider);
389
+            $userSession->login($username, $password);
390
+            $userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password);
391
+        }
392
+
393
+        return $error;
394
+    }
395
+
396
+    public static function installBackgroundJobs() {
397
+        \OC::$server->getJobList()->add('\OC\Authentication\Token\DefaultTokenCleanupJob');
398
+    }
399
+
400
+    /**
401
+     * @return string Absolute path to htaccess
402
+     */
403
+    private function pathToHtaccess() {
404
+        return \OC::$SERVERROOT.'/.htaccess';
405
+    }
406
+
407
+    /**
408
+     * Append the correct ErrorDocument path for Apache hosts
409
+     * @return bool True when success, False otherwise
410
+     */
411
+    public static function updateHtaccess() {
412
+        $config = \OC::$server->getSystemConfig();
413
+
414
+        // For CLI read the value from overwrite.cli.url
415
+        if(\OC::$CLI) {
416
+            $webRoot = $config->getValue('overwrite.cli.url', '');
417
+            if($webRoot === '') {
418
+                return false;
419
+            }
420
+            $webRoot = parse_url($webRoot, PHP_URL_PATH);
421
+            $webRoot = rtrim($webRoot, '/');
422
+        } else {
423
+            $webRoot = !empty(\OC::$WEBROOT) ? \OC::$WEBROOT : '/';
424
+        }
425
+
426
+        $setupHelper = new \OC\Setup($config, \OC::$server->getIniWrapper(),
427
+            \OC::$server->getL10N('lib'), \OC::$server->query(Defaults::class), \OC::$server->getLogger(),
428
+            \OC::$server->getSecureRandom());
429
+
430
+        $htaccessContent = file_get_contents($setupHelper->pathToHtaccess());
431
+        $content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n";
432
+        $htaccessContent = explode($content, $htaccessContent, 2)[0];
433
+
434
+        //custom 403 error page
435
+        $content.= "\nErrorDocument 403 ".$webRoot."/core/templates/403.php";
436
+
437
+        //custom 404 error page
438
+        $content.= "\nErrorDocument 404 ".$webRoot."/core/templates/404.php";
439
+
440
+        // Add rewrite rules if the RewriteBase is configured
441
+        $rewriteBase = $config->getValue('htaccess.RewriteBase', '');
442
+        if($rewriteBase !== '') {
443
+            $content .= "\n<IfModule mod_rewrite.c>";
444
+            $content .= "\n  Options -MultiViews";
445
+            $content .= "\n  RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]";
446
+            $content .= "\n  RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]";
447
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !\\.(css|js|svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$";
448
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$";
449
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/remote.php";
450
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/public.php";
451
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/cron.php";
452
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php";
453
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/status.php";
454
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php";
455
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php";
456
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/robots.txt";
457
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/updater/";
458
+            $content .= "\n  RewriteCond %{REQUEST_FILENAME} !/ocs-provider/";
459
+            $content .= "\n  RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.*";
460
+            $content .= "\n  RewriteRule . index.php [PT,E=PATH_INFO:$1]";
461
+            $content .= "\n  RewriteBase " . $rewriteBase;
462
+            $content .= "\n  <IfModule mod_env.c>";
463
+            $content .= "\n    SetEnv front_controller_active true";
464
+            $content .= "\n    <IfModule mod_dir.c>";
465
+            $content .= "\n      DirectorySlash off";
466
+            $content .= "\n    </IfModule>";
467
+            $content .= "\n  </IfModule>";
468
+            $content .= "\n</IfModule>";
469
+        }
470
+
471
+        if ($content !== '') {
472
+            //suppress errors in case we don't have permissions for it
473
+            return (bool) @file_put_contents($setupHelper->pathToHtaccess(), $htaccessContent.$content . "\n");
474
+        }
475
+
476
+        return false;
477
+    }
478
+
479
+    public static function protectDataDirectory() {
480
+        //Require all denied
481
+        $now =  date('Y-m-d H:i:s');
482
+        $content = "# Generated by Nextcloud on $now\n";
483
+        $content.= "# line below if for Apache 2.4\n";
484
+        $content.= "<ifModule mod_authz_core.c>\n";
485
+        $content.= "Require all denied\n";
486
+        $content.= "</ifModule>\n\n";
487
+        $content.= "# line below if for Apache 2.2\n";
488
+        $content.= "<ifModule !mod_authz_core.c>\n";
489
+        $content.= "deny from all\n";
490
+        $content.= "Satisfy All\n";
491
+        $content.= "</ifModule>\n\n";
492
+        $content.= "# section for Apache 2.2 and 2.4\n";
493
+        $content.= "<ifModule mod_autoindex.c>\n";
494
+        $content.= "IndexIgnore *\n";
495
+        $content.= "</ifModule>\n";
496
+
497
+        $baseDir = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
498
+        file_put_contents($baseDir . '/.htaccess', $content);
499
+        file_put_contents($baseDir . '/index.html', '');
500
+    }
501
+
502
+    /**
503
+     * Return vendor from which this version was published
504
+     *
505
+     * @return string Get the vendor
506
+     *
507
+     * Copy of \OC\Updater::getVendor()
508
+     */
509
+    private function getVendor() {
510
+        // this should really be a JSON file
511
+        require \OC::$SERVERROOT . '/version.php';
512
+        /** @var string $vendor */
513
+        return (string) $vendor;
514
+    }
515 515
 }
Please login to merge, or discard this patch.
lib/private/Mail/EMailTemplate.php 2 patches
Indentation   +169 added lines, -169 removed lines patch added patch discarded remove patch
@@ -38,25 +38,25 @@  discard block
 block discarded – undo
38 38
  * @package OC\Mail
39 39
  */
40 40
 class EMailTemplate implements IEMailTemplate {
41
-	/** @var Defaults */
42
-	protected $themingDefaults;
43
-	/** @var IURLGenerator */
44
-	protected $urlGenerator;
45
-	/** @var IL10N */
46
-	protected $l10n;
47
-
48
-	/** @var string */
49
-	protected $htmlBody = '';
50
-	/** @var string */
51
-	protected $plainBody = '';
52
-	/** @var bool indicated if the footer is added */
53
-	protected $headerAdded = false;
54
-	/** @var bool indicated if the body is already opened */
55
-	protected $bodyOpened = false;
56
-	/** @var bool indicated if the footer is added */
57
-	protected $footerAdded = false;
58
-
59
-	protected $head = <<<EOF
41
+    /** @var Defaults */
42
+    protected $themingDefaults;
43
+    /** @var IURLGenerator */
44
+    protected $urlGenerator;
45
+    /** @var IL10N */
46
+    protected $l10n;
47
+
48
+    /** @var string */
49
+    protected $htmlBody = '';
50
+    /** @var string */
51
+    protected $plainBody = '';
52
+    /** @var bool indicated if the footer is added */
53
+    protected $headerAdded = false;
54
+    /** @var bool indicated if the body is already opened */
55
+    protected $bodyOpened = false;
56
+    /** @var bool indicated if the footer is added */
57
+    protected $footerAdded = false;
58
+
59
+    protected $head = <<<EOF
60 60
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
61 61
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" style="-webkit-font-smoothing:antialiased;background:#f3f3f3!important">
62 62
 <head>
@@ -74,7 +74,7 @@  discard block
 block discarded – undo
74 74
 				<center data-parsed="" style="min-width:580px;width:100%">
75 75
 EOF;
76 76
 
77
-	protected $tail = <<<EOF
77
+    protected $tail = <<<EOF
78 78
 					</center>
79 79
 				</td>
80 80
 			</tr>
@@ -85,7 +85,7 @@  discard block
 block discarded – undo
85 85
 </html>
86 86
 EOF;
87 87
 
88
-	protected $header = <<<EOF
88
+    protected $header = <<<EOF
89 89
 <table align="center" class="wrapper header float-center" style="Margin:0 auto;background:#8a8a8a;background-color:%s;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%%">
90 90
 	<tr style="padding:0;text-align:left;vertical-align:top">
91 91
 		<td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:20px;text-align:left;vertical-align:top;word-wrap:break-word">
@@ -118,7 +118,7 @@  discard block
 block discarded – undo
118 118
 </table>
119 119
 EOF;
120 120
 
121
-	protected $heading = <<<EOF
121
+    protected $heading = <<<EOF
122 122
 <table align="center" class="container main-heading float-center" style="Margin:0 auto;background:0 0!important;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:580px">
123 123
 	<tbody>
124 124
 	<tr style="padding:0;text-align:left;vertical-align:top">
@@ -137,7 +137,7 @@  discard block
 block discarded – undo
137 137
 </table>
138 138
 EOF;
139 139
 
140
-	protected $bodyBegin = <<<EOF
140
+    protected $bodyBegin = <<<EOF
141 141
 <table align="center" class="wrapper content float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
142 142
 	<tr style="padding:0;text-align:left;vertical-align:top">
143 143
 		<td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
@@ -154,7 +154,7 @@  discard block
 block discarded – undo
154 154
 						</table>
155 155
 EOF;
156 156
 
157
-	protected $bodyText = <<<EOF
157
+    protected $bodyText = <<<EOF
158 158
 <table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%%">
159 159
 	<tbody>
160 160
 	<tr style="padding:0;text-align:left;vertical-align:top">
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
 </table>
174 174
 EOF;
175 175
 
176
-	protected $buttonGroup = <<<EOF
176
+    protected $buttonGroup = <<<EOF
177 177
 <table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%%">
178 178
 	<tbody>
179 179
 	<tr style="padding:0;text-align:left;vertical-align:top">
@@ -226,7 +226,7 @@  discard block
 block discarded – undo
226 226
 </table>
227 227
 EOF;
228 228
 
229
-	protected $bodyEnd = <<<EOF
229
+    protected $bodyEnd = <<<EOF
230 230
 
231 231
 					</td>
232 232
 				</tr>
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
 </table>
238 238
 EOF;
239 239
 
240
-	protected $footer = <<<EOF
240
+    protected $footer = <<<EOF
241 241
 <table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%%">
242 242
 	<tbody>
243 243
 	<tr style="padding:0;text-align:left;vertical-align:top">
@@ -263,146 +263,146 @@  discard block
 block discarded – undo
263 263
 </table>
264 264
 EOF;
265 265
 
266
-	/**
267
-	 * @param Defaults $themingDefaults
268
-	 * @param IURLGenerator $urlGenerator
269
-	 * @param IL10N $l10n
270
-	 */
271
-	public function __construct(Defaults $themingDefaults,
272
-								IURLGenerator $urlGenerator,
273
-								IL10N $l10n) {
274
-		$this->themingDefaults = $themingDefaults;
275
-		$this->urlGenerator = $urlGenerator;
276
-		$this->l10n = $l10n;
277
-		$this->htmlBody .= $this->head;
278
-	}
279
-
280
-	/**
281
-	 * Adds a header to the email
282
-	 */
283
-	public function addHeader() {
284
-		if ($this->headerAdded) {
285
-			return;
286
-		}
287
-		$this->headerAdded = true;
288
-
289
-		$logoUrl = $this->urlGenerator->getAbsoluteURL($this->themingDefaults->getLogo());
290
-		$this->htmlBody .= vsprintf($this->header, [$this->themingDefaults->getColorPrimary(), $logoUrl]);
291
-	}
292
-
293
-	/**
294
-	 * Adds a heading to the email
295
-	 *
296
-	 * @param string $title
297
-	 */
298
-	public function addHeading($title) {
299
-		if ($this->footerAdded) {
300
-			return;
301
-		}
302
-
303
-		$this->htmlBody .= vsprintf($this->heading, [$title]);
304
-		$this->plainBody .= $title . PHP_EOL . PHP_EOL;
305
-	}
306
-
307
-	/**
308
-	 * Adds a paragraph to the body of the email
309
-	 *
310
-	 * @param string $text
311
-	 */
312
-	public function addBodyText($text) {
313
-		if ($this->footerAdded) {
314
-			return;
315
-		}
316
-
317
-		if (!$this->bodyOpened) {
318
-			$this->htmlBody .= $this->bodyBegin;
319
-			$this->bodyOpened = true;
320
-		}
321
-
322
-		$this->htmlBody .= vsprintf($this->bodyText, [$text]);
323
-		$this->plainBody .= $text . PHP_EOL . PHP_EOL;
324
-	}
325
-
326
-	/**
327
-	 * Adds a button group of two buttons to the body of the email
328
-	 *
329
-	 * @param string $textLeft Text of left button
330
-	 * @param string $urlLeft URL of left button
331
-	 * @param string $textRight Text of right button
332
-	 * @param string $urlRight URL of right button
333
-	 */
334
-	public function addBodyButtonGroup($textLeft, $urlLeft, $textRight, $urlRight) {
335
-		if ($this->footerAdded) {
336
-			return;
337
-		}
338
-
339
-		if (!$this->bodyOpened) {
340
-			$this->htmlBody .= $this->bodyBegin;
341
-			$this->bodyOpened = true;
342
-		}
343
-
344
-		$color = $this->themingDefaults->getColorPrimary();
345
-		$this->htmlBody .= vsprintf($this->buttonGroup, [$color, $color, $urlLeft, $color, $textLeft, $urlRight, $textRight]);
346
-		$this->plainBody .= $textLeft . ': ' . $urlLeft . PHP_EOL;
347
-		$this->plainBody .= $textRight . ': ' . $urlRight . PHP_EOL . PHP_EOL;
348
-
349
-	}
350
-
351
-	/**
352
-	 * Adds a logo and a text to the footer. <br> in the text will be replaced by new lines in the plain text email
353
-	 *
354
-	 * @param string $text
355
-	 */
356
-	public function addFooter($text = '') {
357
-		if($text === '') {
358
-			$text = $this->themingDefaults->getName() . ' - ' . $this->themingDefaults->getSlogan() . '<br>' . $this->l10n->t('This is an automatically generated email, please do not reply.');
359
-		}
360
-
361
-		if ($this->footerAdded) {
362
-			return;
363
-		}
364
-		$this->footerAdded = true;
365
-
366
-		if ($this->bodyOpened) {
367
-			$this->htmlBody .= $this->bodyEnd;
368
-			$this->bodyOpened = false;
369
-		}
370
-
371
-		$this->htmlBody .= vsprintf($this->footer, [$text]);
372
-		$this->htmlBody .= $this->tail;
373
-		$this->plainBody .= '--' . PHP_EOL;
374
-		$this->plainBody .= str_replace('<br>', PHP_EOL, $text);
375
-	}
376
-
377
-	/**
378
-	 * Returns the rendered HTML email as string
379
-	 *
380
-	 * @return string
381
-	 */
382
-	public function renderHTML() {
383
-		if (!$this->footerAdded) {
384
-			$this->footerAdded = true;
385
-			if ($this->bodyOpened) {
386
-				$this->htmlBody .= $this->bodyEnd;
387
-			}
388
-			$this->htmlBody .= $this->tail;
389
-		}
390
-		return $this->htmlBody;
391
-	}
392
-
393
-	/**
394
-	 * Returns the rendered plain text email as string
395
-	 *
396
-	 * @return string
397
-	 */
398
-	public function renderText() {
399
-		if (!$this->footerAdded) {
400
-			$this->footerAdded = true;
401
-			if ($this->bodyOpened) {
402
-				$this->htmlBody .= $this->bodyEnd;
403
-			}
404
-			$this->htmlBody .= $this->tail;
405
-		}
406
-		return $this->plainBody;
407
-	}
266
+    /**
267
+     * @param Defaults $themingDefaults
268
+     * @param IURLGenerator $urlGenerator
269
+     * @param IL10N $l10n
270
+     */
271
+    public function __construct(Defaults $themingDefaults,
272
+                                IURLGenerator $urlGenerator,
273
+                                IL10N $l10n) {
274
+        $this->themingDefaults = $themingDefaults;
275
+        $this->urlGenerator = $urlGenerator;
276
+        $this->l10n = $l10n;
277
+        $this->htmlBody .= $this->head;
278
+    }
279
+
280
+    /**
281
+     * Adds a header to the email
282
+     */
283
+    public function addHeader() {
284
+        if ($this->headerAdded) {
285
+            return;
286
+        }
287
+        $this->headerAdded = true;
288
+
289
+        $logoUrl = $this->urlGenerator->getAbsoluteURL($this->themingDefaults->getLogo());
290
+        $this->htmlBody .= vsprintf($this->header, [$this->themingDefaults->getColorPrimary(), $logoUrl]);
291
+    }
292
+
293
+    /**
294
+     * Adds a heading to the email
295
+     *
296
+     * @param string $title
297
+     */
298
+    public function addHeading($title) {
299
+        if ($this->footerAdded) {
300
+            return;
301
+        }
302
+
303
+        $this->htmlBody .= vsprintf($this->heading, [$title]);
304
+        $this->plainBody .= $title . PHP_EOL . PHP_EOL;
305
+    }
306
+
307
+    /**
308
+     * Adds a paragraph to the body of the email
309
+     *
310
+     * @param string $text
311
+     */
312
+    public function addBodyText($text) {
313
+        if ($this->footerAdded) {
314
+            return;
315
+        }
316
+
317
+        if (!$this->bodyOpened) {
318
+            $this->htmlBody .= $this->bodyBegin;
319
+            $this->bodyOpened = true;
320
+        }
321
+
322
+        $this->htmlBody .= vsprintf($this->bodyText, [$text]);
323
+        $this->plainBody .= $text . PHP_EOL . PHP_EOL;
324
+    }
325
+
326
+    /**
327
+     * Adds a button group of two buttons to the body of the email
328
+     *
329
+     * @param string $textLeft Text of left button
330
+     * @param string $urlLeft URL of left button
331
+     * @param string $textRight Text of right button
332
+     * @param string $urlRight URL of right button
333
+     */
334
+    public function addBodyButtonGroup($textLeft, $urlLeft, $textRight, $urlRight) {
335
+        if ($this->footerAdded) {
336
+            return;
337
+        }
338
+
339
+        if (!$this->bodyOpened) {
340
+            $this->htmlBody .= $this->bodyBegin;
341
+            $this->bodyOpened = true;
342
+        }
343
+
344
+        $color = $this->themingDefaults->getColorPrimary();
345
+        $this->htmlBody .= vsprintf($this->buttonGroup, [$color, $color, $urlLeft, $color, $textLeft, $urlRight, $textRight]);
346
+        $this->plainBody .= $textLeft . ': ' . $urlLeft . PHP_EOL;
347
+        $this->plainBody .= $textRight . ': ' . $urlRight . PHP_EOL . PHP_EOL;
348
+
349
+    }
350
+
351
+    /**
352
+     * Adds a logo and a text to the footer. <br> in the text will be replaced by new lines in the plain text email
353
+     *
354
+     * @param string $text
355
+     */
356
+    public function addFooter($text = '') {
357
+        if($text === '') {
358
+            $text = $this->themingDefaults->getName() . ' - ' . $this->themingDefaults->getSlogan() . '<br>' . $this->l10n->t('This is an automatically generated email, please do not reply.');
359
+        }
360
+
361
+        if ($this->footerAdded) {
362
+            return;
363
+        }
364
+        $this->footerAdded = true;
365
+
366
+        if ($this->bodyOpened) {
367
+            $this->htmlBody .= $this->bodyEnd;
368
+            $this->bodyOpened = false;
369
+        }
370
+
371
+        $this->htmlBody .= vsprintf($this->footer, [$text]);
372
+        $this->htmlBody .= $this->tail;
373
+        $this->plainBody .= '--' . PHP_EOL;
374
+        $this->plainBody .= str_replace('<br>', PHP_EOL, $text);
375
+    }
376
+
377
+    /**
378
+     * Returns the rendered HTML email as string
379
+     *
380
+     * @return string
381
+     */
382
+    public function renderHTML() {
383
+        if (!$this->footerAdded) {
384
+            $this->footerAdded = true;
385
+            if ($this->bodyOpened) {
386
+                $this->htmlBody .= $this->bodyEnd;
387
+            }
388
+            $this->htmlBody .= $this->tail;
389
+        }
390
+        return $this->htmlBody;
391
+    }
392
+
393
+    /**
394
+     * Returns the rendered plain text email as string
395
+     *
396
+     * @return string
397
+     */
398
+    public function renderText() {
399
+        if (!$this->footerAdded) {
400
+            $this->footerAdded = true;
401
+            if ($this->bodyOpened) {
402
+                $this->htmlBody .= $this->bodyEnd;
403
+            }
404
+            $this->htmlBody .= $this->tail;
405
+        }
406
+        return $this->plainBody;
407
+    }
408 408
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -301,7 +301,7 @@  discard block
 block discarded – undo
301 301
 		}
302 302
 
303 303
 		$this->htmlBody .= vsprintf($this->heading, [$title]);
304
-		$this->plainBody .= $title . PHP_EOL . PHP_EOL;
304
+		$this->plainBody .= $title.PHP_EOL.PHP_EOL;
305 305
 	}
306 306
 
307 307
 	/**
@@ -320,7 +320,7 @@  discard block
 block discarded – undo
320 320
 		}
321 321
 
322 322
 		$this->htmlBody .= vsprintf($this->bodyText, [$text]);
323
-		$this->plainBody .= $text . PHP_EOL . PHP_EOL;
323
+		$this->plainBody .= $text.PHP_EOL.PHP_EOL;
324 324
 	}
325 325
 
326 326
 	/**
@@ -343,8 +343,8 @@  discard block
 block discarded – undo
343 343
 
344 344
 		$color = $this->themingDefaults->getColorPrimary();
345 345
 		$this->htmlBody .= vsprintf($this->buttonGroup, [$color, $color, $urlLeft, $color, $textLeft, $urlRight, $textRight]);
346
-		$this->plainBody .= $textLeft . ': ' . $urlLeft . PHP_EOL;
347
-		$this->plainBody .= $textRight . ': ' . $urlRight . PHP_EOL . PHP_EOL;
346
+		$this->plainBody .= $textLeft.': '.$urlLeft.PHP_EOL;
347
+		$this->plainBody .= $textRight.': '.$urlRight.PHP_EOL.PHP_EOL;
348 348
 
349 349
 	}
350 350
 
@@ -354,8 +354,8 @@  discard block
 block discarded – undo
354 354
 	 * @param string $text
355 355
 	 */
356 356
 	public function addFooter($text = '') {
357
-		if($text === '') {
358
-			$text = $this->themingDefaults->getName() . ' - ' . $this->themingDefaults->getSlogan() . '<br>' . $this->l10n->t('This is an automatically generated email, please do not reply.');
357
+		if ($text === '') {
358
+			$text = $this->themingDefaults->getName().' - '.$this->themingDefaults->getSlogan().'<br>'.$this->l10n->t('This is an automatically generated email, please do not reply.');
359 359
 		}
360 360
 
361 361
 		if ($this->footerAdded) {
@@ -370,7 +370,7 @@  discard block
 block discarded – undo
370 370
 
371 371
 		$this->htmlBody .= vsprintf($this->footer, [$text]);
372 372
 		$this->htmlBody .= $this->tail;
373
-		$this->plainBody .= '--' . PHP_EOL;
373
+		$this->plainBody .= '--'.PHP_EOL;
374 374
 		$this->plainBody .= str_replace('<br>', PHP_EOL, $text);
375 375
 	}
376 376
 
Please login to merge, or discard this patch.