Passed
Push — master ( e11c5f...be49f7 )
by John
14:16 queued 11s
created

OC::setRequiredIniValues()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Adam Williamson <[email protected]>
6
 * @author Andreas Fischer <[email protected]>
7
 * @author Arthur Schiwon <[email protected]>
8
 * @author Bart Visscher <[email protected]>
9
 * @author Bernhard Posselt <[email protected]>
10
 * @author Bjoern Schiessle <[email protected]>
11
 * @author Björn Schießle <[email protected]>
12
 * @author Christoph Wurst <[email protected]>
13
 * @author Damjan Georgievski <[email protected]>
14
 * @author Daniel Kesselberg <[email protected]>
15
 * @author davidgumberg <[email protected]>
16
 * @author Eric Masseran <[email protected]>
17
 * @author Florin Peter <[email protected]>
18
 * @author Greta Doci <[email protected]>
19
 * @author J0WI <[email protected]>
20
 * @author Jakob Sack <[email protected]>
21
 * @author jaltek <[email protected]>
22
 * @author Jan-Christoph Borchardt <[email protected]>
23
 * @author Joachim Sokolowski <[email protected]>
24
 * @author Joas Schilling <[email protected]>
25
 * @author John Molakvoæ <[email protected]>
26
 * @author Jörn Friedrich Dreyer <[email protected]>
27
 * @author Jose Quinteiro <[email protected]>
28
 * @author Juan Pablo Villafáñez <[email protected]>
29
 * @author Julius Härtl <[email protected]>
30
 * @author Ko- <[email protected]>
31
 * @author Lukas Reschke <[email protected]>
32
 * @author MartB <[email protected]>
33
 * @author Michael Gapczynski <[email protected]>
34
 * @author Morris Jobke <[email protected]>
35
 * @author Owen Winkler <[email protected]>
36
 * @author Phil Davis <[email protected]>
37
 * @author Ramiro Aparicio <[email protected]>
38
 * @author Robin Appelman <[email protected]>
39
 * @author Robin McCorkell <[email protected]>
40
 * @author Roeland Jago Douma <[email protected]>
41
 * @author Sebastian Wessalowski <[email protected]>
42
 * @author Stefan Weil <[email protected]>
43
 * @author Thomas Müller <[email protected]>
44
 * @author Thomas Tanghus <[email protected]>
45
 * @author Tobia De Koninck <[email protected]>
46
 * @author Vincent Petry <[email protected]>
47
 * @author Volkan Gezer <[email protected]>
48
 *
49
 * @license AGPL-3.0
50
 *
51
 * This code is free software: you can redistribute it and/or modify
52
 * it under the terms of the GNU Affero General Public License, version 3,
53
 * as published by the Free Software Foundation.
54
 *
55
 * This program is distributed in the hope that it will be useful,
56
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
57
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
58
 * GNU Affero General Public License for more details.
59
 *
60
 * You should have received a copy of the GNU Affero General Public License, version 3,
61
 * along with this program. If not, see <http://www.gnu.org/licenses/>
62
 *
63
 */
64
65
use OCP\EventDispatcher\IEventDispatcher;
66
use OCP\Group\Events\UserRemovedEvent;
67
use OCP\ILogger;
68
use OCP\Share;
69
use OC\Encryption\HookManager;
70
use OC\Files\Filesystem;
71
use OC\Share20\Hooks;
72
use OCP\User\Events\UserChangedEvent;
73
74
require_once 'public/Constants.php';
75
76
/**
77
 * Class that is a namespace for all global OC variables
78
 * No, we can not put this class in its own file because it is used by
79
 * OC_autoload!
80
 */
81
class OC {
82
	/**
83
	 * Associative array for autoloading. classname => filename
84
	 */
85
	public static $CLASSPATH = [];
86
	/**
87
	 * The installation path for Nextcloud  on the server (e.g. /srv/http/nextcloud)
88
	 */
89
	public static $SERVERROOT = '';
90
	/**
91
	 * the current request path relative to the Nextcloud root (e.g. files/index.php)
92
	 */
93
	private static $SUBURI = '';
94
	/**
95
	 * the Nextcloud root path for http requests (e.g. nextcloud/)
96
	 */
97
	public static $WEBROOT = '';
98
	/**
99
	 * The installation path array of the apps folder on the server (e.g. /srv/http/nextcloud) 'path' and
100
	 * web path in 'url'
101
	 */
102
	public static $APPSROOTS = [];
103
104
	/**
105
	 * @var string
106
	 */
107
	public static $configDir;
108
109
	/**
110
	 * requested app
111
	 */
112
	public static $REQUESTEDAPP = '';
113
114
	/**
115
	 * check if Nextcloud runs in cli mode
116
	 */
117
	public static $CLI = false;
118
119
	/**
120
	 * @var \OC\Autoloader $loader
121
	 */
122
	public static $loader = null;
123
124
	/** @var \Composer\Autoload\ClassLoader $composerAutoloader */
125
	public static $composerAutoloader = null;
126
127
	/**
128
	 * @var \OC\Server
129
	 */
130
	public static $server = null;
131
132
	/**
133
	 * @var \OC\Config
134
	 */
135
	private static $config = null;
136
137
	/**
138
	 * @throws \RuntimeException when the 3rdparty directory is missing or
139
	 * the app path list is empty or contains an invalid path
140
	 */
141
	public static function initPaths() {
142
		if (defined('PHPUNIT_CONFIG_DIR')) {
143
			self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/';
0 ignored issues
show
Bug introduced by
The constant PHPUNIT_CONFIG_DIR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
144
		} elseif (defined('PHPUNIT_RUN') && PHPUNIT_RUN && is_dir(OC::$SERVERROOT . '/tests/config/')) {
0 ignored issues
show
Bug introduced by
The constant PHPUNIT_RUN was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
145
			self::$configDir = OC::$SERVERROOT . '/tests/config/';
146
		} elseif ($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
147
			self::$configDir = rtrim($dir, '/') . '/';
148
		} else {
149
			self::$configDir = OC::$SERVERROOT . '/config/';
150
		}
151
		self::$config = new \OC\Config(self::$configDir);
152
153
		OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
154
		/**
155
		 * FIXME: The following lines are required because we can't yet instantiate
156
		 *        \OC::$server->getRequest() since \OC::$server does not yet exist.
157
		 */
158
		$params = [
159
			'server' => [
160
				'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'],
161
				'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'],
162
			],
163
		];
164
		$fakeRequest = new \OC\AppFramework\Http\Request(
165
			$params,
166
			new \OC\AppFramework\Http\RequestId($_SERVER['UNIQUE_ID'] ?? '', new \OC\Security\SecureRandom()),
167
			new \OC\AllConfig(new \OC\SystemConfig(self::$config))
168
		);
169
		$scriptName = $fakeRequest->getScriptName();
170
		if (substr($scriptName, -1) == '/') {
171
			$scriptName .= 'index.php';
172
			//make sure suburi follows the same rules as scriptName
173
			if (substr(OC::$SUBURI, -9) != 'index.php') {
174
				if (substr(OC::$SUBURI, -1) != '/') {
175
					OC::$SUBURI = OC::$SUBURI . '/';
176
				}
177
				OC::$SUBURI = OC::$SUBURI . 'index.php';
178
			}
179
		}
180
181
182
		if (OC::$CLI) {
183
			OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
184
		} else {
185
			if (substr($scriptName, 0 - strlen(OC::$SUBURI)) === OC::$SUBURI) {
186
				OC::$WEBROOT = substr($scriptName, 0, 0 - strlen(OC::$SUBURI));
187
188
				if (OC::$WEBROOT != '' && OC::$WEBROOT[0] !== '/') {
189
					OC::$WEBROOT = '/' . OC::$WEBROOT;
190
				}
191
			} else {
192
				// The scriptName is not ending with OC::$SUBURI
193
				// This most likely means that we are calling from CLI.
194
				// However some cron jobs still need to generate
195
				// a web URL, so we use overwritewebroot as a fallback.
196
				OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
197
			}
198
199
			// Resolve /nextcloud to /nextcloud/ to ensure to always have a trailing
200
			// slash which is required by URL generation.
201
			if (isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] === \OC::$WEBROOT &&
202
					substr($_SERVER['REQUEST_URI'], -1) !== '/') {
203
				header('Location: '.\OC::$WEBROOT.'/');
204
				exit();
205
			}
206
		}
207
208
		// search the apps folder
209
		$config_paths = self::$config->getValue('apps_paths', []);
210
		if (!empty($config_paths)) {
211
			foreach ($config_paths as $paths) {
212
				if (isset($paths['url']) && isset($paths['path'])) {
213
					$paths['url'] = rtrim($paths['url'], '/');
214
					$paths['path'] = rtrim($paths['path'], '/');
215
					OC::$APPSROOTS[] = $paths;
216
				}
217
			}
218
		} elseif (file_exists(OC::$SERVERROOT . '/apps')) {
219
			OC::$APPSROOTS[] = ['path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true];
220
		}
221
222
		if (empty(OC::$APPSROOTS)) {
223
			throw new \RuntimeException('apps directory not found! Please put the Nextcloud apps folder in the Nextcloud folder'
224
				. '. You can also configure the location in the config.php file.');
225
		}
226
		$paths = [];
227
		foreach (OC::$APPSROOTS as $path) {
228
			$paths[] = $path['path'];
229
			if (!is_dir($path['path'])) {
230
				throw new \RuntimeException(sprintf('App directory "%s" not found! Please put the Nextcloud apps folder in the'
231
					. ' Nextcloud folder. You can also configure the location in the config.php file.', $path['path']));
232
			}
233
		}
234
235
		// set the right include path
236
		set_include_path(
237
			implode(PATH_SEPARATOR, $paths)
238
		);
239
	}
240
241
	public static function checkConfig() {
242
		$l = \OC::$server->getL10N('lib');
243
244
		// Create config if it does not already exist
245
		$configFilePath = self::$configDir .'/config.php';
246
		if (!file_exists($configFilePath)) {
247
			@touch($configFilePath);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for touch(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

247
			/** @scrutinizer ignore-unhandled */ @touch($configFilePath);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
248
		}
249
250
		// Check if config is writable
251
		$configFileWritable = is_writable($configFilePath);
252
		if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled()
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (! $configFileWritable &...OCP\Util::needUpgrade(), Probably Intended Meaning: ! $configFileWritable &&...CP\Util::needUpgrade())
Loading history...
253
			|| !$configFileWritable && \OCP\Util::needUpgrade()) {
254
			$urlGenerator = \OC::$server->getURLGenerator();
255
256
			if (self::$CLI) {
257
				echo $l->t('Cannot write into "config" directory!')."\n";
258
				echo $l->t('This can usually be fixed by giving the web server write access to the config directory.')."\n";
259
				echo "\n";
260
				echo $l->t('But, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it.')."\n";
261
				echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-config') ])."\n";
262
				exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
263
			} else {
264
				OC_Template::printErrorPage(
265
					$l->t('Cannot write into "config" directory!'),
266
					$l->t('This can usually be fixed by giving the web server write access to the config directory.') . ' '
267
					. $l->t('But, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it.') . ' '
268
					. $l->t('See %s', [ $urlGenerator->linkToDocs('admin-config') ]),
269
					503
270
				);
271
			}
272
		}
273
	}
274
275
	public static function checkInstalled(\OC\SystemConfig $systemConfig) {
276
		if (defined('OC_CONSOLE')) {
277
			return;
278
		}
279
		// Redirect to installer if not installed
280
		if (!$systemConfig->getValue('installed', false) && OC::$SUBURI !== '/index.php' && OC::$SUBURI !== '/status.php') {
281
			if (OC::$CLI) {
282
				throw new Exception('Not installed');
283
			} else {
284
				$url = OC::$WEBROOT . '/index.php';
285
				header('Location: ' . $url);
286
			}
287
			exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
288
		}
289
	}
290
291
	public static function checkMaintenanceMode(\OC\SystemConfig $systemConfig) {
292
		// Allow ajax update script to execute without being stopped
293
		if (((bool) $systemConfig->getValue('maintenance', false)) && OC::$SUBURI != '/core/ajax/update.php') {
294
			// send http status 503
295
			http_response_code(503);
296
			header('Retry-After: 120');
297
298
			// render error page
299
			$template = new OC_Template('', 'update.user', 'guest');
300
			OC_Util::addScript('maintenance');
301
			OC_Util::addStyle('core', 'guest');
302
			$template->printPage();
303
			die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
304
		}
305
	}
306
307
	/**
308
	 * Prints the upgrade page
309
	 *
310
	 * @param \OC\SystemConfig $systemConfig
311
	 */
312
	private static function printUpgradePage(\OC\SystemConfig $systemConfig) {
313
		$disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false);
314
		$tooBig = false;
315
		if (!$disableWebUpdater) {
316
			$apps = \OC::$server->getAppManager();
317
			if ($apps->isInstalled('user_ldap')) {
318
				$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
319
320
				$result = $qb->select($qb->func()->count('*', 'user_count'))
321
					->from('ldap_user_mapping')
322
					->execute();
323
				$row = $result->fetch();
324
				$result->closeCursor();
325
326
				$tooBig = ($row['user_count'] > 50);
327
			}
328
			if (!$tooBig && $apps->isInstalled('user_saml')) {
329
				$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
330
331
				$result = $qb->select($qb->func()->count('*', 'user_count'))
332
					->from('user_saml_users')
333
					->execute();
334
				$row = $result->fetch();
335
				$result->closeCursor();
336
337
				$tooBig = ($row['user_count'] > 50);
338
			}
339
			if (!$tooBig) {
340
				// count users
341
				$stats = \OC::$server->getUserManager()->countUsers();
342
				$totalUsers = array_sum($stats);
343
				$tooBig = ($totalUsers > 50);
344
			}
345
		}
346
		$ignoreTooBigWarning = isset($_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup']) &&
347
			$_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup'] === 'IAmSuperSureToDoThis';
348
349
		if ($disableWebUpdater || ($tooBig && !$ignoreTooBigWarning)) {
350
			// send http status 503
351
			http_response_code(503);
352
			header('Retry-After: 120');
353
354
			// render error page
355
			$template = new OC_Template('', 'update.use-cli', 'guest');
356
			$template->assign('productName', 'nextcloud'); // for now
357
			$template->assign('version', OC_Util::getVersionString());
358
			$template->assign('tooBig', $tooBig);
359
360
			$template->printPage();
361
			die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
362
		}
363
364
		// check whether this is a core update or apps update
365
		$installedVersion = $systemConfig->getValue('version', '0.0.0');
366
		$currentVersion = implode('.', \OCP\Util::getVersion());
367
368
		// if not a core upgrade, then it's apps upgrade
369
		$isAppsOnlyUpgrade = version_compare($currentVersion, $installedVersion, '=');
370
371
		$oldTheme = $systemConfig->getValue('theme');
372
		$systemConfig->setValue('theme', '');
373
		\OCP\Util::addScript('core', 'common');
374
		\OCP\Util::addScript('core', 'main');
375
		\OCP\Util::addTranslations('core');
376
		\OCP\Util::addScript('core', 'update');
377
378
		/** @var \OC\App\AppManager $appManager */
379
		$appManager = \OC::$server->getAppManager();
380
381
		$tmpl = new OC_Template('', 'update.admin', 'guest');
382
		$tmpl->assign('version', OC_Util::getVersionString());
383
		$tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade);
384
385
		// get third party apps
386
		$ocVersion = \OCP\Util::getVersion();
387
		$ocVersion = implode('.', $ocVersion);
388
		$incompatibleApps = $appManager->getIncompatibleApps($ocVersion);
389
		$incompatibleShippedApps = [];
390
		foreach ($incompatibleApps as $appInfo) {
391
			if ($appManager->isShipped($appInfo['id'])) {
392
				$incompatibleShippedApps[] = $appInfo['name'] . ' (' . $appInfo['id'] . ')';
393
			}
394
		}
395
396
		if (!empty($incompatibleShippedApps)) {
397
			$l = \OC::$server->getL10N('core');
398
			$hint = $l->t('The files of the app %1$s were not replaced correctly. Make sure it is a version compatible with the server.', [implode(', ', $incompatibleShippedApps)]);
399
			throw new \OCP\HintException('The files of the app ' . implode(', ', $incompatibleShippedApps) . ' were not replaced correctly. Make sure it is a version compatible with the server.', $hint);
400
		}
401
402
		$tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
403
		$tmpl->assign('incompatibleAppsList', $incompatibleApps);
404
		try {
405
			$defaults = new \OC_Defaults();
406
			$tmpl->assign('productName', $defaults->getName());
407
		} catch (Throwable $error) {
408
			$tmpl->assign('productName', 'Nextcloud');
409
		}
410
		$tmpl->assign('oldTheme', $oldTheme);
411
		$tmpl->printPage();
412
	}
413
414
	public static function initSession() {
415
		if (self::$server->getRequest()->getServerProtocol() === 'https') {
416
			ini_set('session.cookie_secure', 'true');
417
		}
418
419
		// prevents javascript from accessing php session cookies
420
		ini_set('session.cookie_httponly', 'true');
421
422
		// set the cookie path to the Nextcloud directory
423
		$cookie_path = OC::$WEBROOT ? : '/';
424
		ini_set('session.cookie_path', $cookie_path);
425
426
		// Let the session name be changed in the initSession Hook
427
		$sessionName = OC_Util::getInstanceId();
428
429
		try {
430
			// set the session name to the instance id - which is unique
431
			$session = new \OC\Session\Internal($sessionName);
432
433
			$cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
434
			$session = $cryptoWrapper->wrapSession($session);
435
			self::$server->setSession($session);
436
437
			// if session can't be started break with http 500 error
438
		} catch (Exception $e) {
439
			\OC::$server->getLogger()->logException($e, ['app' => 'base']);
440
			//show the user a detailed error page
441
			OC_Template::printExceptionErrorPage($e, 500);
442
			die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
443
		}
444
445
		$sessionLifeTime = self::getSessionLifeTime();
446
447
		// session timeout
448
		if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
449
			if (isset($_COOKIE[session_name()])) {
450
				setcookie(session_name(), '', -1, self::$WEBROOT ? : '/');
451
			}
452
			\OC::$server->getUserSession()->logout();
453
		}
454
455
		$session->set('LAST_ACTIVITY', time());
456
	}
457
458
	/**
459
	 * @return string
460
	 */
461
	private static function getSessionLifeTime() {
462
		return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
463
	}
464
465
	/**
466
	 * Send the same site cookies
467
	 */
468
	private static function sendSameSiteCookies() {
469
		$cookieParams = session_get_cookie_params();
470
		$secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
471
		$policies = [
472
			'lax',
473
			'strict',
474
		];
475
476
		// Append __Host to the cookie if it meets the requirements
477
		$cookiePrefix = '';
478
		if ($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
479
			$cookiePrefix = '__Host-';
480
		}
481
482
		foreach ($policies as $policy) {
483
			header(
484
				sprintf(
485
					'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
486
					$cookiePrefix,
487
					$policy,
488
					$cookieParams['path'],
489
					$policy
490
				),
491
				false
492
			);
493
		}
494
	}
495
496
	/**
497
	 * Same Site cookie to further mitigate CSRF attacks. This cookie has to
498
	 * be set in every request if cookies are sent to add a second level of
499
	 * defense against CSRF.
500
	 *
501
	 * If the cookie is not sent this will set the cookie and reload the page.
502
	 * We use an additional cookie since we want to protect logout CSRF and
503
	 * also we can't directly interfere with PHP's session mechanism.
504
	 */
505
	private static function performSameSiteCookieProtection(\OCP\IConfig $config) {
506
		$request = \OC::$server->getRequest();
507
508
		// Some user agents are notorious and don't really properly follow HTTP
509
		// specifications. For those, have an automated opt-out. Since the protection
510
		// for remote.php is applied in base.php as starting point we need to opt out
511
		// here.
512
		$incompatibleUserAgents = $config->getSystemValue('csrf.optout');
513
514
		// Fallback, if csrf.optout is unset
515
		if (!is_array($incompatibleUserAgents)) {
516
			$incompatibleUserAgents = [
517
				// OS X Finder
518
				'/^WebDAVFS/',
519
				// Windows webdav drive
520
				'/^Microsoft-WebDAV-MiniRedir/',
521
			];
522
		}
523
524
		if ($request->isUserAgent($incompatibleUserAgents)) {
525
			return;
526
		}
527
528
		if (count($_COOKIE) > 0) {
529
			$requestUri = $request->getScriptName();
530
			$processingScript = explode('/', $requestUri);
531
			$processingScript = $processingScript[count($processingScript) - 1];
532
533
			// index.php routes are handled in the middleware
534
			if ($processingScript === 'index.php') {
535
				return;
536
			}
537
538
			// All other endpoints require the lax and the strict cookie
539
			if (!$request->passesStrictCookieCheck()) {
540
				self::sendSameSiteCookies();
541
				// Debug mode gets access to the resources without strict cookie
542
				// due to the fact that the SabreDAV browser also lives there.
543
				if (!$config->getSystemValue('debug', false)) {
544
					http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE);
545
					exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
546
				}
547
			}
548
		} elseif (!isset($_COOKIE['nc_sameSiteCookielax']) || !isset($_COOKIE['nc_sameSiteCookiestrict'])) {
549
			self::sendSameSiteCookies();
550
		}
551
	}
552
553
	public static function init() {
554
		// calculate the root directories
555
		OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
556
557
		// register autoloader
558
		$loaderStart = microtime(true);
559
		require_once __DIR__ . '/autoloader.php';
560
		self::$loader = new \OC\Autoloader([
561
			OC::$SERVERROOT . '/lib/private/legacy',
562
		]);
563
		if (defined('PHPUNIT_RUN')) {
564
			self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
565
		}
566
		spl_autoload_register([self::$loader, 'load']);
567
		$loaderEnd = microtime(true);
568
569
		self::$CLI = (php_sapi_name() == 'cli');
570
571
		// Add default composer PSR-4 autoloader
572
		self::$composerAutoloader = require_once OC::$SERVERROOT . '/lib/composer/autoload.php';
573
574
		try {
575
			self::initPaths();
576
			// setup 3rdparty autoloader
577
			$vendorAutoLoad = OC::$SERVERROOT. '/3rdparty/autoload.php';
578
			if (!file_exists($vendorAutoLoad)) {
579
				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".');
580
			}
581
			require_once $vendorAutoLoad;
582
		} catch (\RuntimeException $e) {
583
			if (!self::$CLI) {
584
				http_response_code(503);
585
			}
586
			// we can't use the template error page here, because this needs the
587
			// DI container which isn't available yet
588
			print($e->getMessage());
589
			exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
590
		}
591
592
		// setup the basic server
593
		self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
594
		self::$server->boot();
595
596
		$eventLogger = \OC::$server->getEventLogger();
597
		$eventLogger->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
598
		$eventLogger->start('request', 'Full request after autoloading');
599
		register_shutdown_function(function () use ($eventLogger) {
600
			$eventLogger->end('request');
601
		});
602
		$eventLogger->start('boot', 'Initialize');
603
		$eventLogger->start('runtime', 'Runtime (total - autoloader)');
604
605
		// Override php.ini and log everything if we're troubleshooting
606
		if (self::$config->getValue('loglevel') === ILogger::DEBUG) {
607
			error_reporting(E_ALL);
608
		}
609
610
		// Don't display errors and log them
611
		@ini_set('display_errors', '0');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ini_set(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

611
		/** @scrutinizer ignore-unhandled */ @ini_set('display_errors', '0');

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
612
		@ini_set('log_errors', '1');
613
614
		if (!date_default_timezone_set('UTC')) {
615
			throw new \RuntimeException('Could not set timezone to UTC');
616
		}
617
618
		//try to configure php to enable big file uploads.
619
		//this doesn´t work always depending on the web server and php configuration.
620
		//Let´s try to overwrite some defaults anyway
621
622
		//try to set the maximum execution time to 60min
623
		if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
624
			@set_time_limit(3600);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for set_time_limit(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

624
			/** @scrutinizer ignore-unhandled */ @set_time_limit(3600);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
625
		}
626
		@ini_set('max_execution_time', '3600');
627
		@ini_set('max_input_time', '3600');
628
629
		self::handleAuthHeaders();
630
		$systemConfig = \OC::$server->get(\OC\SystemConfig::class);
631
		self::registerAutoloaderCache($systemConfig);
632
633
		// initialize intl fallback if necessary
634
		OC_Util::isSetLocaleWorking();
635
636
		$config = \OC::$server->get(\OCP\IConfig::class);
637
		if (!defined('PHPUNIT_RUN')) {
638
			OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
639
			$debug = $config->getSystemValue('debug', false);
640
			OC\Log\ErrorHandler::register($debug);
641
		}
642
643
		/** @var \OC\AppFramework\Bootstrap\Coordinator $bootstrapCoordinator */
644
		$bootstrapCoordinator = \OC::$server->query(\OC\AppFramework\Bootstrap\Coordinator::class);
645
		$bootstrapCoordinator->runInitialRegistration();
646
647
		$eventLogger->start('init_session', 'Initialize session');
648
		OC_App::loadApps(['session']);
649
		if (!self::$CLI) {
650
			self::initSession();
651
		}
652
		$eventLogger->end('init_session');
653
		self::checkConfig();
654
		self::checkInstalled($systemConfig);
655
656
		OC_Response::addSecurityHeaders();
657
658
		self::performSameSiteCookieProtection($config);
659
660
		if (!defined('OC_CONSOLE')) {
661
			$errors = OC_Util::checkServer($systemConfig);
662
			if (count($errors) > 0) {
663
				if (!self::$CLI) {
664
					http_response_code(503);
665
					OC_Util::addStyle('guest');
666
					try {
667
						OC_Template::printGuestPage('', 'error', ['errors' => $errors]);
668
						exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
669
					} catch (\Exception $e) {
670
						// In case any error happens when showing the error page, we simply fall back to posting the text.
671
						// This might be the case when e.g. the data directory is broken and we can not load/write SCSS to/from it.
672
					}
673
				}
674
675
				// Convert l10n string into regular string for usage in database
676
				$staticErrors = [];
677
				foreach ($errors as $error) {
678
					echo $error['error'] . "\n";
679
					echo $error['hint'] . "\n\n";
680
					$staticErrors[] = [
681
						'error' => (string)$error['error'],
682
						'hint' => (string)$error['hint'],
683
					];
684
				}
685
686
				try {
687
					$config->setAppValue('core', 'cronErrors', json_encode($staticErrors));
688
				} catch (\Exception $e) {
689
					echo('Writing to database failed');
690
				}
691
				exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
692
			} elseif (self::$CLI && $config->getSystemValue('installed', false)) {
693
				$config->deleteAppValue('core', 'cronErrors');
694
			}
695
		}
696
		//try to set the session lifetime
697
		$sessionLifeTime = self::getSessionLifeTime();
698
		@ini_set('gc_maxlifetime', (string)$sessionLifeTime);
699
700
		// User and Groups
701
		if (!$systemConfig->getValue("installed", false)) {
702
			self::$server->getSession()->set('user_id', '');
703
		}
704
705
		OC_User::useBackend(new \OC\User\Database());
706
		\OC::$server->getGroupManager()->addBackend(new \OC\Group\Database());
707
708
		// Subscribe to the hook
709
		\OCP\Util::connectHook(
710
			'\OCA\Files_Sharing\API\Server2Server',
711
			'preLoginNameUsedAsUserName',
712
			'\OC\User\Database',
713
			'preLoginNameUsedAsUserName'
714
		);
715
716
		//setup extra user backends
717
		if (!\OCP\Util::needUpgrade()) {
718
			OC_User::setupBackends();
719
		} else {
720
			// Run upgrades in incognito mode
721
			OC_User::setIncognitoMode(true);
722
		}
723
724
		self::registerCleanupHooks($systemConfig);
725
		self::registerFilesystemHooks();
726
		self::registerShareHooks($systemConfig);
727
		self::registerEncryptionWrapperAndHooks();
728
		self::registerAccountHooks();
729
		self::registerResourceCollectionHooks();
730
		self::registerAppRestrictionsHooks();
731
732
		// Make sure that the application class is not loaded before the database is setup
733
		if ($systemConfig->getValue("installed", false)) {
734
			OC_App::loadApp('settings');
735
			/* Build core application to make sure that listeners are registered */
736
			self::$server->get(\OC\Core\Application::class);
737
		}
738
739
		//make sure temporary files are cleaned up
740
		$tmpManager = \OC::$server->getTempManager();
741
		register_shutdown_function([$tmpManager, 'clean']);
742
		$lockProvider = \OC::$server->getLockingProvider();
743
		register_shutdown_function([$lockProvider, 'releaseAll']);
744
745
		// Check whether the sample configuration has been copied
746
		if ($systemConfig->getValue('copied_sample_config', false)) {
747
			$l = \OC::$server->getL10N('lib');
748
			OC_Template::printErrorPage(
749
				$l->t('Sample configuration detected'),
750
				$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'),
751
				503
752
			);
753
			return;
754
		}
755
756
		$request = \OC::$server->getRequest();
757
		$host = $request->getInsecureServerHost();
758
		/**
759
		 * if the host passed in headers isn't trusted
760
		 * FIXME: Should not be in here at all :see_no_evil:
761
		 */
762
		if (!OC::$CLI
763
			&& !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host)
764
			&& $config->getSystemValue('installed', false)
765
		) {
766
			// Allow access to CSS resources
767
			$isScssRequest = false;
768
			if (strpos($request->getPathInfo(), '/css/') === 0) {
769
				$isScssRequest = true;
770
			}
771
772
			if (substr($request->getRequestUri(), -11) === '/status.php') {
773
				http_response_code(400);
774
				header('Content-Type: application/json');
775
				echo '{"error": "Trusted domain error.", "code": 15}';
776
				exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
777
			}
778
779
			if (!$isScssRequest) {
780
				http_response_code(400);
781
782
				\OC::$server->getLogger()->warning(
783
					'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
784
					[
785
						'app' => 'core',
786
						'remoteAddress' => $request->getRemoteAddress(),
787
						'host' => $host,
788
					]
789
				);
790
791
				$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
792
				$tmpl->assign('docUrl', \OC::$server->getURLGenerator()->linkToDocs('admin-trusted-domains'));
793
				$tmpl->printPage();
794
795
				exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
796
			}
797
		}
798
		$eventLogger->end('boot');
799
		$eventLogger->log('init', 'OC::init', $loaderStart, microtime(true));
800
	}
801
802
	/**
803
	 * register hooks for the cleanup of cache and bruteforce protection
804
	 */
805
	public static function registerCleanupHooks(\OC\SystemConfig $systemConfig) {
806
		//don't try to do this before we are properly setup
807
		if ($systemConfig->getValue('installed', false) && !\OCP\Util::needUpgrade()) {
808
809
			// NOTE: This will be replaced to use OCP
810
			$userSession = self::$server->getUserSession();
811
			$userSession->listen('\OC\User', 'postLogin', function () use ($userSession) {
812
				if (!defined('PHPUNIT_RUN') && $userSession->isLoggedIn()) {
813
					// reset brute force delay for this IP address and username
814
					$uid = \OC::$server->getUserSession()->getUser()->getUID();
815
					$request = \OC::$server->getRequest();
816
					$throttler = \OC::$server->getBruteForceThrottler();
817
					$throttler->resetDelay($request->getRemoteAddress(), 'login', ['user' => $uid]);
818
				}
819
820
				try {
821
					$cache = new \OC\Cache\File();
822
					$cache->gc();
823
				} catch (\OC\ServerNotAvailableException $e) {
824
					// not a GC exception, pass it on
825
					throw $e;
826
				} catch (\OC\ForbiddenException $e) {
827
					// filesystem blocked for this request, ignore
828
				} catch (\Exception $e) {
829
					// a GC exception should not prevent users from using OC,
830
					// so log the exception
831
					\OC::$server->getLogger()->logException($e, [
832
						'message' => 'Exception when running cache gc.',
833
						'level' => ILogger::WARN,
0 ignored issues
show
Deprecated Code introduced by
The constant OCP\ILogger::WARN has been deprecated: 20.0.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

833
						'level' => /** @scrutinizer ignore-deprecated */ ILogger::WARN,

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
834
						'app' => 'core',
835
					]);
836
				}
837
			});
838
		}
839
	}
840
841
	private static function registerEncryptionWrapperAndHooks() {
842
		$manager = self::$server->getEncryptionManager();
843
		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
844
845
		$enabled = $manager->isEnabled();
846
		if ($enabled) {
847
			\OCP\Util::connectHook(Share::class, 'post_shared', HookManager::class, 'postShared');
848
			\OCP\Util::connectHook(Share::class, 'post_unshare', HookManager::class, 'postUnshared');
849
			\OCP\Util::connectHook('OC_Filesystem', 'post_rename', HookManager::class, 'postRename');
850
			\OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', HookManager::class, 'postRestore');
851
		}
852
	}
853
854
	private static function registerAccountHooks() {
855
		/** @var IEventDispatcher $dispatcher */
856
		$dispatcher = \OC::$server->get(IEventDispatcher::class);
857
		$dispatcher->addServiceListener(UserChangedEvent::class, \OC\Accounts\Hooks::class);
858
	}
859
860
	private static function registerAppRestrictionsHooks() {
861
		/** @var \OC\Group\Manager $groupManager */
862
		$groupManager = self::$server->query(\OCP\IGroupManager::class);
863
		$groupManager->listen('\OC\Group', 'postDelete', function (\OCP\IGroup $group) {
864
			$appManager = self::$server->getAppManager();
865
			$apps = $appManager->getEnabledAppsForGroup($group);
866
			foreach ($apps as $appId) {
867
				$restrictions = $appManager->getAppRestriction($appId);
868
				if (empty($restrictions)) {
869
					continue;
870
				}
871
				$key = array_search($group->getGID(), $restrictions);
872
				unset($restrictions[$key]);
873
				$restrictions = array_values($restrictions);
874
				if (empty($restrictions)) {
875
					$appManager->disableApp($appId);
876
				} else {
877
					$appManager->enableAppForGroups($appId, $restrictions);
878
				}
879
			}
880
		});
881
	}
882
883
	private static function registerResourceCollectionHooks() {
884
		\OC\Collaboration\Resources\Listener::register(\OC::$server->getEventDispatcher());
885
	}
886
887
	/**
888
	 * register hooks for the filesystem
889
	 */
890
	public static function registerFilesystemHooks() {
891
		// Check for blacklisted files
892
		OC_Hook::connect('OC_Filesystem', 'write', Filesystem::class, 'isBlacklisted');
893
		OC_Hook::connect('OC_Filesystem', 'rename', Filesystem::class, 'isBlacklisted');
894
	}
895
896
	/**
897
	 * register hooks for sharing
898
	 */
899
	public static function registerShareHooks(\OC\SystemConfig $systemConfig) {
900
		if ($systemConfig->getValue('installed')) {
901
			OC_Hook::connect('OC_User', 'post_deleteUser', Hooks::class, 'post_deleteUser');
902
			OC_Hook::connect('OC_User', 'post_deleteGroup', Hooks::class, 'post_deleteGroup');
903
904
			/** @var IEventDispatcher $dispatcher */
905
			$dispatcher = \OC::$server->get(IEventDispatcher::class);
906
			$dispatcher->addServiceListener(UserRemovedEvent::class, \OC\Share20\UserRemovedListener::class);
907
		}
908
	}
909
910
	protected static function registerAutoloaderCache(\OC\SystemConfig $systemConfig) {
911
		// The class loader takes an optional low-latency cache, which MUST be
912
		// namespaced. The instanceid is used for namespacing, but might be
913
		// unavailable at this point. Furthermore, it might not be possible to
914
		// generate an instanceid via \OC_Util::getInstanceId() because the
915
		// config file may not be writable. As such, we only register a class
916
		// loader cache if instanceid is available without trying to create one.
917
		$instanceId = $systemConfig->getValue('instanceid', null);
918
		if ($instanceId) {
919
			try {
920
				$memcacheFactory = \OC::$server->getMemCacheFactory();
921
				self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader'));
922
			} catch (\Exception $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
923
			}
924
		}
925
	}
926
927
	/**
928
	 * Handle the request
929
	 */
930
	public static function handleRequest() {
931
		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
932
		$systemConfig = \OC::$server->getSystemConfig();
933
934
		// Check if Nextcloud is installed or in maintenance (update) mode
935
		if (!$systemConfig->getValue('installed', false)) {
936
			\OC::$server->getSession()->clear();
937
			$setupHelper = new OC\Setup(
938
				$systemConfig,
939
				\OC::$server->get(\bantu\IniGetWrapper\IniGetWrapper::class),
940
				\OC::$server->getL10N('lib'),
941
				\OC::$server->query(\OCP\Defaults::class),
942
				\OC::$server->get(\Psr\Log\LoggerInterface::class),
943
				\OC::$server->getSecureRandom(),
944
				\OC::$server->query(\OC\Installer::class)
945
			);
946
			$controller = new OC\Core\Controller\SetupController($setupHelper);
947
			$controller->run($_POST);
948
			exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
949
		}
950
951
		$request = \OC::$server->getRequest();
952
		$requestPath = $request->getRawPathInfo();
953
		if ($requestPath === '/heartbeat') {
954
			return;
955
		}
956
		if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
957
			self::checkMaintenanceMode($systemConfig);
958
959
			if (\OCP\Util::needUpgrade()) {
960
				if (function_exists('opcache_reset')) {
961
					opcache_reset();
962
				}
963
				if (!((bool) $systemConfig->getValue('maintenance', false))) {
964
					self::printUpgradePage($systemConfig);
965
					exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
966
				}
967
			}
968
		}
969
970
		// emergency app disabling
971
		if ($requestPath === '/disableapp'
972
			&& $request->getMethod() === 'POST'
973
			&& ((array)$request->getParam('appid')) !== ''
974
		) {
975
			\OC_JSON::callCheck();
976
			\OC_JSON::checkAdminUser();
977
			$appIds = (array)$request->getParam('appid');
978
			foreach ($appIds as $appId) {
979
				$appId = \OC_App::cleanAppId($appId);
980
				\OC::$server->getAppManager()->disableApp($appId);
981
			}
982
			\OC_JSON::success();
983
			exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
984
		}
985
986
		// Always load authentication apps
987
		OC_App::loadApps(['authentication']);
988
989
		// Load minimum set of apps
990
		if (!\OCP\Util::needUpgrade()
991
			&& !((bool) $systemConfig->getValue('maintenance', false))) {
992
			// For logged-in users: Load everything
993
			if (\OC::$server->getUserSession()->isLoggedIn()) {
994
				OC_App::loadApps();
995
			} else {
996
				// For guests: Load only filesystem and logging
997
				OC_App::loadApps(['filesystem', 'logging']);
998
999
				// Don't try to login when a client is trying to get a OAuth token.
1000
				// OAuth needs to support basic auth too, so the login is not valid
1001
				// inside Nextcloud and the Login exception would ruin it.
1002
				if ($request->getRawPathInfo() !== '/apps/oauth2/api/v1/token') {
1003
					self::handleLogin($request);
1004
				}
1005
			}
1006
		}
1007
1008
		if (!self::$CLI) {
1009
			try {
1010
				if (!((bool) $systemConfig->getValue('maintenance', false)) && !\OCP\Util::needUpgrade()) {
1011
					OC_App::loadApps(['filesystem', 'logging']);
1012
					OC_App::loadApps();
1013
				}
1014
				OC::$server->get(\OC\Route\Router::class)->match($request->getRawPathInfo());
1015
				return;
1016
			} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
1017
				//header('HTTP/1.0 404 Not Found');
1018
			} catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
1019
				http_response_code(405);
1020
				return;
1021
			}
1022
		}
1023
1024
		// Handle WebDAV
1025
		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PROPFIND') {
1026
			// not allowed any more to prevent people
1027
			// mounting this root directly.
1028
			// Users need to mount remote.php/webdav instead.
1029
			http_response_code(405);
1030
			return;
1031
		}
1032
1033
		// Someone is logged in
1034
		if (\OC::$server->getUserSession()->isLoggedIn()) {
1035
			OC_App::loadApps();
1036
			OC_User::setupBackends();
1037
			OC_Util::setupFS();
1038
			header('Location: ' . \OC::$server->getURLGenerator()->linkToDefaultPageUrl());
1039
		} else {
1040
			// Not handled and not logged in
1041
			header('Location: ' . \OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
1042
		}
1043
	}
1044
1045
	/**
1046
	 * Check login: apache auth, auth token, basic auth
1047
	 *
1048
	 * @param OCP\IRequest $request
1049
	 * @return boolean
1050
	 */
1051
	public static function handleLogin(OCP\IRequest $request) {
1052
		$userSession = self::$server->getUserSession();
1053
		if (OC_User::handleApacheAuth()) {
1054
			return true;
1055
		}
1056
		if ($userSession->tryTokenLogin($request)) {
1057
			return true;
1058
		}
1059
		if (isset($_COOKIE['nc_username'])
1060
			&& isset($_COOKIE['nc_token'])
1061
			&& isset($_COOKIE['nc_session_id'])
1062
			&& $userSession->loginWithCookie($_COOKIE['nc_username'], $_COOKIE['nc_token'], $_COOKIE['nc_session_id'])) {
1063
			return true;
1064
		}
1065
		if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
1066
			return true;
1067
		}
1068
		return false;
1069
	}
1070
1071
	protected static function handleAuthHeaders() {
1072
		//copy http auth headers for apache+php-fcgid work around
1073
		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
1074
			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
1075
		}
1076
1077
		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
1078
		$vars = [
1079
			'HTTP_AUTHORIZATION', // apache+php-cgi work around
1080
			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
1081
		];
1082
		foreach ($vars as $var) {
1083
			if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
1084
				$credentials = explode(':', base64_decode($matches[1]), 2);
1085
				if (count($credentials) === 2) {
1086
					$_SERVER['PHP_AUTH_USER'] = $credentials[0];
1087
					$_SERVER['PHP_AUTH_PW'] = $credentials[1];
1088
					break;
1089
				}
1090
			}
1091
		}
1092
	}
1093
}
1094
1095
OC::init();
1096