Passed
Push — master ( 7519a9...c67507 )
by Roeland
15:04
created

OC::loadAppClassPaths()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 4
nop 0
dl 0
loc 10
rs 10
c 0
b 0
f 0

1 Method

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

239
			/** @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...
240
		}
241
242
		// Check if config is writable
243
		$configFileWritable = is_writable($configFilePath);
244
		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...
245
			|| !$configFileWritable && \OCP\Util::needUpgrade()) {
246
247
			$urlGenerator = \OC::$server->getURLGenerator();
248
249
			if (self::$CLI) {
250
				echo $l->t('Cannot write into "config" directory!')."\n";
251
				echo $l->t('This can usually be fixed by giving the webserver write access to the config directory')."\n";
252
				echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-dir_permissions') ])."\n";
253
				echo "\n";
254
				echo $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it.')."\n";
255
				echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-config') ])."\n";
256
				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...
257
			} else {
258
				OC_Template::printErrorPage(
259
					$l->t('Cannot write into "config" directory!'),
260
					$l->t('This can usually be fixed by giving the webserver write access to the config directory. See %s',
261
					[ $urlGenerator->linkToDocs('admin-dir_permissions') ]) . '. '
262
					. $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it. See %s',
263
					[ $urlGenerator->linkToDocs('admin-config') ] ),
264
					503
265
				);
266
			}
267
		}
268
	}
269
270
	public static function checkInstalled() {
271
		if (defined('OC_CONSOLE')) {
272
			return;
273
		}
274
		// Redirect to installer if not installed
275
		if (!\OC::$server->getSystemConfig()->getValue('installed', false) && OC::$SUBURI !== '/index.php' && OC::$SUBURI !== '/status.php') {
276
			if (OC::$CLI) {
277
				throw new Exception('Not installed');
278
			} else {
279
				$url = OC::$WEBROOT . '/index.php';
280
				header('Location: ' . $url);
281
			}
282
			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...
283
		}
284
	}
285
286
	public static function checkMaintenanceMode() {
287
		// Allow ajax update script to execute without being stopped
288
		if (((bool) \OC::$server->getSystemConfig()->getValue('maintenance', false)) && OC::$SUBURI != '/core/ajax/update.php') {
289
			// send http status 503
290
			http_response_code(503);
291
			header('Retry-After: 120');
292
293
			// render error page
294
			$template = new OC_Template('', 'update.user', 'guest');
295
			OC_Util::addScript('maintenance-check');
296
			OC_Util::addStyle('core', 'guest');
297
			$template->printPage();
298
			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...
299
		}
300
	}
301
302
	/**
303
	 * Prints the upgrade page
304
	 *
305
	 * @param \OC\SystemConfig $systemConfig
306
	 */
307
	private static function printUpgradePage(\OC\SystemConfig $systemConfig) {
308
		$disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false);
309
		$tooBig = false;
310
		if (!$disableWebUpdater) {
311
			$apps = \OC::$server->getAppManager();
312
			if ($apps->isInstalled('user_ldap')) {
313
				$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
314
315
				$result = $qb->select($qb->func()->count('*', 'user_count'))
316
					->from('ldap_user_mapping')
317
					->execute();
318
				$row = $result->fetch();
319
				$result->closeCursor();
320
321
				$tooBig = ($row['user_count'] > 50);
322
			}
323
			if (!$tooBig && $apps->isInstalled('user_saml')) {
324
				$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
325
326
				$result = $qb->select($qb->func()->count('*', 'user_count'))
327
					->from('user_saml_users')
328
					->execute();
329
				$row = $result->fetch();
330
				$result->closeCursor();
331
332
				$tooBig = ($row['user_count'] > 50);
333
			}
334
			if (!$tooBig) {
335
				// count users
336
				$stats = \OC::$server->getUserManager()->countUsers();
337
				$totalUsers = array_sum($stats);
338
				$tooBig = ($totalUsers > 50);
339
			}
340
		}
341
		$ignoreTooBigWarning = isset($_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup']) &&
342
			$_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup'] === 'IAmSuperSureToDoThis';
343
344
		if ($disableWebUpdater || ($tooBig && !$ignoreTooBigWarning)) {
345
			// send http status 503
346
			http_response_code(503);
347
			header('Retry-After: 120');
348
349
			// render error page
350
			$template = new OC_Template('', 'update.use-cli', 'guest');
351
			$template->assign('productName', 'nextcloud'); // for now
352
			$template->assign('version', OC_Util::getVersionString());
353
			$template->assign('tooBig', $tooBig);
354
355
			$template->printPage();
356
			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...
357
		}
358
359
		// check whether this is a core update or apps update
360
		$installedVersion = $systemConfig->getValue('version', '0.0.0');
361
		$currentVersion = implode('.', \OCP\Util::getVersion());
362
363
		// if not a core upgrade, then it's apps upgrade
364
		$isAppsOnlyUpgrade = version_compare($currentVersion, $installedVersion, '=');
365
366
		$oldTheme = $systemConfig->getValue('theme');
367
		$systemConfig->setValue('theme', '');
368
		OC_Util::addScript('config'); // needed for web root
369
		OC_Util::addScript('update');
370
371
		/** @var \OC\App\AppManager $appManager */
372
		$appManager = \OC::$server->getAppManager();
373
374
		$tmpl = new OC_Template('', 'update.admin', 'guest');
375
		$tmpl->assign('version', OC_Util::getVersionString());
376
		$tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade);
377
378
		// get third party apps
379
		$ocVersion = \OCP\Util::getVersion();
380
		$ocVersion = implode('.', $ocVersion);
381
		$incompatibleApps = $appManager->getIncompatibleApps($ocVersion);
382
		$incompatibleShippedApps = [];
383
		foreach ($incompatibleApps as $appInfo) {
384
			if ($appManager->isShipped($appInfo['id'])) {
385
				$incompatibleShippedApps[] = $appInfo['name'] . ' (' . $appInfo['id'] . ')';
386
			}
387
		}
388
389
		if (!empty($incompatibleShippedApps)) {
390
			$l = \OC::$server->getL10N('core');
391
			$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)]);
392
			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);
393
		}
394
395
		$tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
396
		$tmpl->assign('incompatibleAppsList', $incompatibleApps);
397
		$tmpl->assign('productName', 'Nextcloud'); // for now
398
		$tmpl->assign('oldTheme', $oldTheme);
399
		$tmpl->printPage();
400
	}
401
402
	public static function initSession() {
403
		if(self::$server->getRequest()->getServerProtocol() === 'https') {
404
			ini_set('session.cookie_secure', true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $newvalue of ini_set(). ( Ignorable by Annotation )

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

404
			ini_set('session.cookie_secure', /** @scrutinizer ignore-type */ true);
Loading history...
405
		}
406
407
		// prevents javascript from accessing php session cookies
408
		ini_set('session.cookie_httponly', 'true');
409
410
		// set the cookie path to the Nextcloud directory
411
		$cookie_path = OC::$WEBROOT ? : '/';
412
		ini_set('session.cookie_path', $cookie_path);
413
414
		// Let the session name be changed in the initSession Hook
415
		$sessionName = OC_Util::getInstanceId();
416
417
		try {
418
			// Allow session apps to create a custom session object
419
			$useCustomSession = false;
420
			$session = self::$server->getSession();
421
			OC_Hook::emit('OC', 'initSession', array('session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession));
422
			if (!$useCustomSession) {
0 ignored issues
show
introduced by
The condition $useCustomSession is always false.
Loading history...
423
				// set the session name to the instance id - which is unique
424
				$session = new \OC\Session\Internal($sessionName);
425
			}
426
427
			$cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
428
			$session = $cryptoWrapper->wrapSession($session);
429
			self::$server->setSession($session);
430
431
			// if session can't be started break with http 500 error
432
		} catch (Exception $e) {
433
			\OC::$server->getLogger()->logException($e, ['app' => 'base']);
434
			//show the user a detailed error page
435
			OC_Template::printExceptionErrorPage($e, 500);
436
			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...
437
		}
438
439
		$sessionLifeTime = self::getSessionLifeTime();
440
441
		// session timeout
442
		if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
443
			if (isset($_COOKIE[session_name()])) {
444
				setcookie(session_name(), '', -1, self::$WEBROOT ? : '/');
445
			}
446
			\OC::$server->getUserSession()->logout();
447
		}
448
449
		$session->set('LAST_ACTIVITY', time());
450
	}
451
452
	/**
453
	 * @return string
454
	 */
455
	private static function getSessionLifeTime() {
456
		return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
457
	}
458
459
	/**
460
	 * Try to set some values to the required Nextcloud default
461
	 */
462
	public static function setRequiredIniValues() {
463
		@ini_set('default_charset', 'UTF-8');
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

463
		/** @scrutinizer ignore-unhandled */ @ini_set('default_charset', 'UTF-8');

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...
464
		@ini_set('gd.jpeg_ignore_warning', '1');
465
	}
466
467
	/**
468
	 * Send the same site cookies
469
	 */
470
	private static function sendSameSiteCookies() {
471
		$cookieParams = session_get_cookie_params();
472
		$secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
473
		$policies = [
474
			'lax',
475
			'strict',
476
		];
477
478
		// Append __Host to the cookie if it meets the requirements
479
		$cookiePrefix = '';
480
		if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
481
			$cookiePrefix = '__Host-';
482
		}
483
484
		foreach($policies as $policy) {
485
			header(
486
				sprintf(
487
					'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
488
					$cookiePrefix,
489
					$policy,
490
					$cookieParams['path'],
491
					$policy
492
				),
493
				false
494
			);
495
		}
496
	}
497
498
	/**
499
	 * Same Site cookie to further mitigate CSRF attacks. This cookie has to
500
	 * be set in every request if cookies are sent to add a second level of
501
	 * defense against CSRF.
502
	 *
503
	 * If the cookie is not sent this will set the cookie and reload the page.
504
	 * We use an additional cookie since we want to protect logout CSRF and
505
	 * also we can't directly interfere with PHP's session mechanism.
506
	 */
507
	private static function performSameSiteCookieProtection() {
508
		$request = \OC::$server->getRequest();
509
510
		// Some user agents are notorious and don't really properly follow HTTP
511
		// specifications. For those, have an automated opt-out. Since the protection
512
		// for remote.php is applied in base.php as starting point we need to opt out
513
		// here.
514
		$incompatibleUserAgents = \OC::$server->getConfig()->getSystemValue('csrf.optout');
515
516
		// Fallback, if csrf.optout is unset
517
		if (!is_array($incompatibleUserAgents)) {
518
			$incompatibleUserAgents = [
519
				// OS X Finder
520
				'/^WebDAVFS/',
521
				// Windows webdav drive
522
				'/^Microsoft-WebDAV-MiniRedir/',
523
			];
524
		}
525
526
		if($request->isUserAgent($incompatibleUserAgents)) {
527
			return;
528
		}
529
530
		if(count($_COOKIE) > 0) {
531
			$requestUri = $request->getScriptName();
532
			$processingScript = explode('/', $requestUri);
533
			$processingScript = $processingScript[count($processingScript)-1];
534
535
			// index.php routes are handled in the middleware
536
			if($processingScript === 'index.php') {
537
				return;
538
			}
539
540
			// All other endpoints require the lax and the strict cookie
541
			if(!$request->passesStrictCookieCheck()) {
542
				self::sendSameSiteCookies();
543
				// Debug mode gets access to the resources without strict cookie
544
				// due to the fact that the SabreDAV browser also lives there.
545
				if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
546
					http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE);
547
					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...
548
				}
549
			}
550
		} elseif(!isset($_COOKIE['nc_sameSiteCookielax']) || !isset($_COOKIE['nc_sameSiteCookiestrict'])) {
551
			self::sendSameSiteCookies();
552
		}
553
	}
554
555
	public static function init() {
556
		// calculate the root directories
557
		OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
558
559
		// register autoloader
560
		$loaderStart = microtime(true);
561
		require_once __DIR__ . '/autoloader.php';
562
		self::$loader = new \OC\Autoloader([
563
			OC::$SERVERROOT . '/lib/private/legacy',
564
		]);
565
		if (defined('PHPUNIT_RUN')) {
566
			self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
567
		}
568
		spl_autoload_register(array(self::$loader, 'load'));
569
		$loaderEnd = microtime(true);
570
571
		self::$CLI = (php_sapi_name() == 'cli');
572
573
		// Add default composer PSR-4 autoloader
574
		self::$composerAutoloader = require_once OC::$SERVERROOT . '/lib/composer/autoload.php';
575
576
		try {
577
			self::initPaths();
578
			// setup 3rdparty autoloader
579
			$vendorAutoLoad = OC::$SERVERROOT. '/3rdparty/autoload.php';
580
			if (!file_exists($vendorAutoLoad)) {
581
				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".');
582
			}
583
			require_once $vendorAutoLoad;
584
585
		} catch (\RuntimeException $e) {
586
			if (!self::$CLI) {
587
				http_response_code(503);
588
			}
589
			// we can't use the template error page here, because this needs the
590
			// DI container which isn't available yet
591
			print($e->getMessage());
592
			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...
593
		}
594
595
		// setup the basic server
596
		self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
597
		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
598
		\OC::$server->getEventLogger()->start('boot', 'Initialize');
599
600
		// Don't display errors and log them
601
		error_reporting(E_ALL | E_STRICT);
602
		@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

602
		/** @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...
603
		@ini_set('log_errors', '1');
604
605
		if(!date_default_timezone_set('UTC')) {
606
			throw new \RuntimeException('Could not set timezone to UTC');
607
		}
608
609
		//try to configure php to enable big file uploads.
610
		//this doesn´t work always depending on the webserver and php configuration.
611
		//Let´s try to overwrite some defaults anyway
612
613
		//try to set the maximum execution time to 60min
614
		if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
615
			@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

615
			/** @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...
616
		}
617
		@ini_set('max_execution_time', '3600');
618
		@ini_set('max_input_time', '3600');
619
620
		//try to set the maximum filesize to 10G
621
		@ini_set('upload_max_filesize', '10G');
622
		@ini_set('post_max_size', '10G');
623
		@ini_set('file_uploads', '50');
624
625
		self::setRequiredIniValues();
626
		self::handleAuthHeaders();
627
		self::registerAutoloaderCache();
628
629
		// initialize intl fallback is necessary
630
		\Patchwork\Utf8\Bootup::initIntl();
631
		OC_Util::isSetLocaleWorking();
632
633
		if (!defined('PHPUNIT_RUN')) {
634
			OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
635
			$debug = \OC::$server->getConfig()->getSystemValue('debug', false);
636
			OC\Log\ErrorHandler::register($debug);
637
		}
638
639
		\OC::$server->getEventLogger()->start('init_session', 'Initialize session');
640
		OC_App::loadApps(array('session'));
641
		if (!self::$CLI) {
642
			self::initSession();
643
		}
644
		\OC::$server->getEventLogger()->end('init_session');
645
		self::checkConfig();
646
		self::checkInstalled();
647
648
		OC_Response::addSecurityHeaders();
649
650
		self::performSameSiteCookieProtection();
651
652
		if (!defined('OC_CONSOLE')) {
653
			$errors = OC_Util::checkServer(\OC::$server->getSystemConfig());
654
			if (count($errors) > 0) {
655
				if (self::$CLI) {
656
					// Convert l10n string into regular string for usage in database
657
					$staticErrors = [];
658
					foreach ($errors as $error) {
659
						echo $error['error'] . "\n";
660
						echo $error['hint'] . "\n\n";
661
						$staticErrors[] = [
662
							'error' => (string)$error['error'],
663
							'hint' => (string)$error['hint'],
664
						];
665
					}
666
667
					try {
668
						\OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
669
					} catch (\Exception $e) {
670
						echo('Writing to database failed');
671
					}
672
					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...
673
				} else {
674
					http_response_code(503);
675
					OC_Util::addStyle('guest');
676
					OC_Template::printGuestPage('', 'error', array('errors' => $errors));
677
					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...
678
				}
679
			} elseif (self::$CLI && \OC::$server->getConfig()->getSystemValue('installed', false)) {
680
				\OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
681
			}
682
		}
683
		//try to set the session lifetime
684
		$sessionLifeTime = self::getSessionLifeTime();
685
		@ini_set('gc_maxlifetime', (string)$sessionLifeTime);
686
687
		$systemConfig = \OC::$server->getSystemConfig();
688
689
		// User and Groups
690
		if (!$systemConfig->getValue("installed", false)) {
691
			self::$server->getSession()->set('user_id', '');
692
		}
693
694
		OC_User::useBackend(new \OC\User\Database());
695
		\OC::$server->getGroupManager()->addBackend(new \OC\Group\Database());
696
697
		// Subscribe to the hook
698
		\OCP\Util::connectHook(
699
			'\OCA\Files_Sharing\API\Server2Server',
700
			'preLoginNameUsedAsUserName',
701
			'\OC\User\Database',
702
			'preLoginNameUsedAsUserName'
703
		);
704
705
		//setup extra user backends
706
		if (!\OCP\Util::needUpgrade()) {
707
			OC_User::setupBackends();
708
		} else {
709
			// Run upgrades in incognito mode
710
			OC_User::setIncognitoMode(true);
711
		}
712
713
		self::registerCleanupHooks();
714
		self::registerFilesystemHooks();
715
		self::registerShareHooks();
716
		self::registerEncryptionWrapper();
717
		self::registerEncryptionHooks();
718
		self::registerAccountHooks();
719
720
		// Make sure that the application class is not loaded before the database is setup
721
		if ($systemConfig->getValue("installed", false)) {
722
			$settings = new \OC\Settings\Application();
723
			$settings->register();
724
		}
725
726
		//make sure temporary files are cleaned up
727
		$tmpManager = \OC::$server->getTempManager();
728
		register_shutdown_function(array($tmpManager, 'clean'));
729
		$lockProvider = \OC::$server->getLockingProvider();
730
		register_shutdown_function(array($lockProvider, 'releaseAll'));
731
732
		// Check whether the sample configuration has been copied
733
		if($systemConfig->getValue('copied_sample_config', false)) {
734
			$l = \OC::$server->getL10N('lib');
735
			OC_Template::printErrorPage(
736
				$l->t('Sample configuration detected'),
737
				$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'),
738
				503
739
			);
740
			return;
741
		}
742
743
		$request = \OC::$server->getRequest();
744
		$host = $request->getInsecureServerHost();
745
		/**
746
		 * if the host passed in headers isn't trusted
747
		 * FIXME: Should not be in here at all :see_no_evil:
748
		 */
749
		if (!OC::$CLI
750
			// overwritehost is always trusted, workaround to not have to make
751
			// \OC\AppFramework\Http\Request::getOverwriteHost public
752
			&& self::$server->getConfig()->getSystemValue('overwritehost') === ''
753
			&& !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host)
754
			&& self::$server->getConfig()->getSystemValue('installed', false)
755
		) {
756
			// Allow access to CSS resources
757
			$isScssRequest = false;
758
			if(strpos($request->getPathInfo(), '/css/') === 0) {
759
				$isScssRequest = true;
760
			}
761
762
			if(substr($request->getRequestUri(), -11) === '/status.php') {
763
				http_response_code(400);
764
				header('Content-Type: application/json');
765
				echo '{"error": "Trusted domain error.", "code": 15}';
766
				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...
767
			}
768
769
			if (!$isScssRequest) {
770
				http_response_code(400);
771
772
				\OC::$server->getLogger()->info(
773
					'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
774
					[
775
						'app' => 'core',
776
						'remoteAddress' => $request->getRemoteAddress(),
777
						'host' => $host,
778
					]
779
				);
780
781
				$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
782
				$tmpl->assign('docUrl', \OC::$server->getURLGenerator()->linkToDocs('admin-trusted-domains'));
783
				$tmpl->printPage();
784
785
				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...
786
			}
787
		}
788
		\OC::$server->getEventLogger()->end('boot');
789
	}
790
791
	/**
792
	 * register hooks for the cleanup of cache and bruteforce protection
793
	 */
794
	public static function registerCleanupHooks() {
795
		//don't try to do this before we are properly setup
796
		if (\OC::$server->getSystemConfig()->getValue('installed', false) && !\OCP\Util::needUpgrade()) {
797
798
			// NOTE: This will be replaced to use OCP
799
			$userSession = self::$server->getUserSession();
800
			$userSession->listen('\OC\User', 'postLogin', function () use ($userSession) {
0 ignored issues
show
Unused Code introduced by
The import $userSession is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
801
				if (!defined('PHPUNIT_RUN')) {
802
					// reset brute force delay for this IP address and username
803
					$uid = \OC::$server->getUserSession()->getUser()->getUID();
804
					$request = \OC::$server->getRequest();
805
					$throttler = \OC::$server->getBruteForceThrottler();
806
					$throttler->resetDelay($request->getRemoteAddress(), 'login', ['user' => $uid]);
0 ignored issues
show
Bug introduced by
array('user' => $uid) of type array<string,string> is incompatible with the type string expected by parameter $metadata of OC\Security\Bruteforce\Throttler::resetDelay(). ( Ignorable by Annotation )

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

806
					$throttler->resetDelay($request->getRemoteAddress(), 'login', /** @scrutinizer ignore-type */ ['user' => $uid]);
Loading history...
807
				}
808
809
				try {
810
					$cache = new \OC\Cache\File();
811
					$cache->gc();
812
				} catch (\OC\ServerNotAvailableException $e) {
813
					// not a GC exception, pass it on
814
					throw $e;
815
				} catch (\OC\ForbiddenException $e) {
816
					// filesystem blocked for this request, ignore
817
				} catch (\Exception $e) {
818
					// a GC exception should not prevent users from using OC,
819
					// so log the exception
820
					\OC::$server->getLogger()->logException($e, [
821
						'message' => 'Exception when running cache gc.',
822
						'level' => ILogger::WARN,
823
						'app' => 'core',
824
					]);
825
				}
826
			});
827
		}
828
	}
829
830
	private static function registerEncryptionWrapper() {
831
		$manager = self::$server->getEncryptionManager();
832
		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
833
	}
834
835
	private static function registerEncryptionHooks() {
836
		$enabled = self::$server->getEncryptionManager()->isEnabled();
837
		if ($enabled) {
838
			\OCP\Util::connectHook(Share::class, 'post_shared', HookManager::class, 'postShared');
839
			\OCP\Util::connectHook(Share::class, 'post_unshare', HookManager::class, 'postUnshared');
840
			\OCP\Util::connectHook('OC_Filesystem', 'post_rename', HookManager::class, 'postRename');
841
			\OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', HookManager::class, 'postRestore');
842
		}
843
	}
844
845
	private static function registerAccountHooks() {
846
		$hookHandler = new \OC\Accounts\Hooks(\OC::$server->getLogger());
847
		\OCP\Util::connectHook('OC_User', 'changeUser', $hookHandler, 'changeUserHook');
848
	}
849
850
	/**
851
	 * register hooks for the filesystem
852
	 */
853
	public static function registerFilesystemHooks() {
854
		// Check for blacklisted files
855
		OC_Hook::connect('OC_Filesystem', 'write', Filesystem::class, 'isBlacklisted');
856
		OC_Hook::connect('OC_Filesystem', 'rename', Filesystem::class, 'isBlacklisted');
857
	}
858
859
	/**
860
	 * register hooks for sharing
861
	 */
862
	public static function registerShareHooks() {
863
		if (\OC::$server->getSystemConfig()->getValue('installed')) {
864
			OC_Hook::connect('OC_User', 'post_deleteUser', Hooks::class, 'post_deleteUser');
865
			OC_Hook::connect('OC_User', 'post_removeFromGroup', Hooks::class, 'post_removeFromGroup');
866
			OC_Hook::connect('OC_User', 'post_deleteGroup', Hooks::class, 'post_deleteGroup');
867
		}
868
	}
869
870
	protected static function registerAutoloaderCache() {
871
		// The class loader takes an optional low-latency cache, which MUST be
872
		// namespaced. The instanceid is used for namespacing, but might be
873
		// unavailable at this point. Furthermore, it might not be possible to
874
		// generate an instanceid via \OC_Util::getInstanceId() because the
875
		// config file may not be writable. As such, we only register a class
876
		// loader cache if instanceid is available without trying to create one.
877
		$instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
878
		if ($instanceId) {
879
			try {
880
				$memcacheFactory = \OC::$server->getMemCacheFactory();
881
				self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader'));
882
			} catch (\Exception $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
883
			}
884
		}
885
	}
886
887
	/**
888
	 * Handle the request
889
	 */
890
	public static function handleRequest() {
891
892
		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
893
		$systemConfig = \OC::$server->getSystemConfig();
894
895
		// Check if Nextcloud is installed or in maintenance (update) mode
896
		if (!$systemConfig->getValue('installed', false)) {
897
			\OC::$server->getSession()->clear();
898
			$setupHelper = new OC\Setup(
899
				$systemConfig,
900
				\OC::$server->getIniWrapper(),
901
				\OC::$server->getL10N('lib'),
902
				\OC::$server->query(\OCP\Defaults::class),
903
				\OC::$server->getLogger(),
904
				\OC::$server->getSecureRandom(),
905
				\OC::$server->query(\OC\Installer::class)
906
			);
907
			$controller = new OC\Core\Controller\SetupController($setupHelper);
908
			$controller->run($_POST);
909
			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...
910
		}
911
912
		$request = \OC::$server->getRequest();
913
		$requestPath = $request->getRawPathInfo();
914
		if ($requestPath === '/heartbeat') {
915
			return;
916
		}
917
		if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
918
			self::checkMaintenanceMode();
919
920
			if (\OCP\Util::needUpgrade()) {
921
				if (function_exists('opcache_reset')) {
922
					opcache_reset();
923
				}
924
				if (!((bool) $systemConfig->getValue('maintenance', false))) {
925
					self::printUpgradePage($systemConfig);
926
					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...
927
				}
928
			}
929
		}
930
931
		// emergency app disabling
932
		if ($requestPath === '/disableapp'
933
			&& $request->getMethod() === 'POST'
934
			&& ((array)$request->getParam('appid')) !== ''
935
		) {
936
			\OC_JSON::callCheck();
0 ignored issues
show
Deprecated Code introduced by
The function OC_JSON::callCheck() has been deprecated: Use annotation based CSRF checks from the AppFramework instead ( Ignorable by Annotation )

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

936
			/** @scrutinizer ignore-deprecated */ \OC_JSON::callCheck();

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

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

Loading history...
937
			\OC_JSON::checkAdminUser();
938
			$appIds = (array)$request->getParam('appid');
939
			foreach($appIds as $appId) {
940
				$appId = \OC_App::cleanAppId($appId);
941
				\OC::$server->getAppManager()->disableApp($appId);
942
			}
943
			\OC_JSON::success();
944
			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...
945
		}
946
947
		// Always load authentication apps
948
		OC_App::loadApps(['authentication']);
949
950
		// Load minimum set of apps
951
		if (!\OCP\Util::needUpgrade()
952
			&& !((bool) $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 (!((bool) $systemConfig->getValue('maintenance', false)) && !\OCP\Util::needUpgrade()) {
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());
0 ignored issues
show
Deprecated Code introduced by
The function OCP\Route\IRouter::match() has been deprecated: 9.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

970
				/** @scrutinizer ignore-deprecated */ OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());

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

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

Loading history...
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
				http_response_code(405);
976
				return;
977
			}
978
		}
979
980
		// Handle WebDAV
981
		if (isset($_SERVER['REQUEST_METHOD']) && $_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
			http_response_code(405);
986
			return;
987
		}
988
989
		// Someone is logged in
990
		if (\OC::$server->getUserSession()->isLoggedIn()) {
991
			OC_App::loadApps();
992
			OC_User::setupBackends();
993
			OC_Util::setupFS();
994
			// FIXME
995
			// Redirect to default application
996
			OC_Util::redirectToDefaultPage();
997
		} else {
998
			// Not handled and not logged in
999
			header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
1000
		}
1001
	}
1002
1003
	/**
1004
	 * Check login: apache auth, auth token, basic auth
1005
	 *
1006
	 * @param OCP\IRequest $request
1007
	 * @return boolean
1008
	 */
1009
	static function handleLogin(OCP\IRequest $request) {
1010
		$userSession = self::$server->getUserSession();
1011
		if (OC_User::handleApacheAuth()) {
1012
			return true;
1013
		}
1014
		if ($userSession->tryTokenLogin($request)) {
1015
			return true;
1016
		}
1017
		if (isset($_COOKIE['nc_username'])
1018
			&& isset($_COOKIE['nc_token'])
1019
			&& isset($_COOKIE['nc_session_id'])
1020
			&& $userSession->loginWithCookie($_COOKIE['nc_username'], $_COOKIE['nc_token'], $_COOKIE['nc_session_id'])) {
1021
			return true;
1022
		}
1023
		if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
1024
			return true;
1025
		}
1026
		return false;
1027
	}
1028
1029
	protected static function handleAuthHeaders() {
1030
		//copy http auth headers for apache+php-fcgid work around
1031
		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
1032
			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
1033
		}
1034
1035
		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
1036
		$vars = array(
1037
			'HTTP_AUTHORIZATION', // apache+php-cgi work around
1038
			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
1039
		);
1040
		foreach ($vars as $var) {
1041
			if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
1042
				list($name, $password) = explode(':', base64_decode($matches[1]), 2);
1043
				$_SERVER['PHP_AUTH_USER'] = $name;
1044
				$_SERVER['PHP_AUTH_PW'] = $password;
1045
				break;
1046
			}
1047
		}
1048
	}
1049
}
1050
1051
OC::init();
1052