Completed
Pull Request — master (#479)
by Lukas
33:52 queued 25:33
created

OC::sendSameSiteCookies()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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

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...
232
		}
233
234
		// Check if config is writable
235
		$configFileWritable = is_writable($configFilePath);
236
		if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled()
237
			|| !$configFileWritable && self::checkUpgrade(false)) {
238
239
			$urlGenerator = \OC::$server->getURLGenerator();
240
241
			if (self::$CLI) {
242
				echo $l->t('Cannot write into "config" directory!')."\n";
243
				echo $l->t('This can usually be fixed by giving the webserver write access to the config directory')."\n";
244
				echo "\n";
245
				echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-dir_permissions') ])."\n";
246
				exit;
247
			} else {
248
				OC_Template::printErrorPage(
249
					$l->t('Cannot write into "config" directory!'),
250
					$l->t('This can usually be fixed by '
251
					. '%sgiving the webserver write access to the config directory%s.',
252
					 array('<a href="' . $urlGenerator->linkToDocs('admin-dir_permissions') . '" target="_blank" rel="noreferrer">', '</a>'))
253
				);
254
			}
255
		}
256
	}
257
258
	public static function checkInstalled() {
259
		if (defined('OC_CONSOLE')) {
260
			return;
261
		}
262
		// Redirect to installer if not installed
263
		if (!\OC::$server->getSystemConfig()->getValue('installed', false) && OC::$SUBURI != '/index.php') {
264
			if (OC::$CLI) {
265
				throw new Exception('Not installed');
266
			} else {
267
				$url = 'http://' . $_SERVER['SERVER_NAME'] . OC::$WEBROOT . '/index.php';
268
				header('Location: ' . $url);
269
			}
270
			exit();
271
		}
272
	}
273
274
	public static function checkMaintenanceMode() {
275
		// Allow ajax update script to execute without being stopped
276
		if (\OC::$server->getSystemConfig()->getValue('maintenance', false) && OC::$SUBURI != '/core/ajax/update.php') {
277
			// send http status 503
278
			header('HTTP/1.1 503 Service Temporarily Unavailable');
279
			header('Status: 503 Service Temporarily Unavailable');
280
			header('Retry-After: 120');
281
282
			// render error page
283
			$template = new OC_Template('', 'update.user', 'guest');
284
			OC_Util::addScript('maintenance-check');
285
			$template->printPage();
286
			die();
287
		}
288
	}
289
290
	public static function checkSingleUserMode($lockIfNoUserLoggedIn = false) {
291
		if (!\OC::$server->getSystemConfig()->getValue('singleuser', false)) {
292
			return;
293
		}
294
		$user = OC_User::getUserSession()->getUser();
295
		if ($user) {
296
			$group = \OC::$server->getGroupManager()->get('admin');
297
			if ($group->inGroup($user)) {
0 ignored issues
show
Compatibility introduced by
$user of type object<OCP\IUser> is not a sub-type of object<OC\User\User>. It seems like you assume a concrete implementation of the interface OCP\IUser to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
298
				return;
299
			}
300
		} else {
301
			if(!$lockIfNoUserLoggedIn) {
302
				return;
303
			}
304
		}
305
		// send http status 503
306
		header('HTTP/1.1 503 Service Temporarily Unavailable');
307
		header('Status: 503 Service Temporarily Unavailable');
308
		header('Retry-After: 120');
309
310
		// render error page
311
		$template = new OC_Template('', 'singleuser.user', 'guest');
312
		$template->printPage();
313
		die();
314
	}
315
316
	/**
317
	 * Checks if the version requires an update and shows
318
	 * @param bool $showTemplate Whether an update screen should get shown
319
	 * @return bool|void
320
	 */
321
	public static function checkUpgrade($showTemplate = true) {
322
		if (\OCP\Util::needUpgrade()) {
323
			$systemConfig = \OC::$server->getSystemConfig();
324
			if ($showTemplate && !$systemConfig->getValue('maintenance', false)) {
325
				self::printUpgradePage();
326
				exit();
327
			} else {
328
				return true;
329
			}
330
		}
331
		return false;
332
	}
333
334
	/**
335
	 * Prints the upgrade page
336
	 */
337
	private static function printUpgradePage() {
338
		$systemConfig = \OC::$server->getSystemConfig();
339
340
		$disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false);
341
		$tooBig = false;
342
		if (!$disableWebUpdater) {
343
			$apps = \OC::$server->getAppManager();
344
			$tooBig = $apps->isInstalled('user_ldap') || $apps->isInstalled('user_shibboleth');
345
			if (!$tooBig) {
346
				// count users
347
				$stats = \OC::$server->getUserManager()->countUsers();
348
				$totalUsers = array_sum($stats);
349
				$tooBig = ($totalUsers > 50);
350
			}
351
		}
352
		if ($disableWebUpdater || $tooBig) {
353
			// send http status 503
354
			header('HTTP/1.1 503 Service Temporarily Unavailable');
355
			header('Status: 503 Service Temporarily Unavailable');
356
			header('Retry-After: 120');
357
358
			// render error page
359
			$template = new OC_Template('', 'update.use-cli', 'guest');
360
			$template->assign('productName', 'owncloud'); // for now
361
			$template->assign('version', OC_Util::getVersionString());
362
			$template->assign('tooBig', $tooBig);
363
364
			$template->printPage();
365
			die();
366
		}
367
368
		// check whether this is a core update or apps update
369
		$installedVersion = $systemConfig->getValue('version', '0.0.0');
370
		$currentVersion = implode('.', \OCP\Util::getVersion());
371
372
		// if not a core upgrade, then it's apps upgrade
373
		$isAppsOnlyUpgrade = (version_compare($currentVersion, $installedVersion, '='));
374
375
		$oldTheme = $systemConfig->getValue('theme');
376
		$systemConfig->setValue('theme', '');
377
		\OCP\Util::addScript('config'); // needed for web root
378
		\OCP\Util::addScript('update');
379
		\OCP\Util::addStyle('update');
380
381
		$appManager = \OC::$server->getAppManager();
382
383
		$tmpl = new OC_Template('', 'update.admin', 'guest');
384
		$tmpl->assign('version', OC_Util::getVersionString());
385
		$tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade);
386
387
		// get third party apps
388
		$ocVersion = \OCP\Util::getVersion();
389
		$tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
390
		$tmpl->assign('incompatibleAppsList', $appManager->getIncompatibleApps($ocVersion));
391
		$tmpl->assign('productName', 'ownCloud'); // for now
392
		$tmpl->assign('oldTheme', $oldTheme);
393
		$tmpl->printPage();
394
	}
395
396
	public static function initSession() {
397
		// prevents javascript from accessing php session cookies
398
		ini_set('session.cookie_httponly', true);
399
400
		// set the cookie path to the Nextcloud directory
401
		$cookie_path = OC::$WEBROOT ? : '/';
402
		ini_set('session.cookie_path', $cookie_path);
403
404
		// Let the session name be changed in the initSession Hook
405
		$sessionName = OC_Util::getInstanceId();
406
407
		try {
408
			// Allow session apps to create a custom session object
409
			$useCustomSession = false;
410
			$session = self::$server->getSession();
411
			OC_Hook::emit('OC', 'initSession', array('session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession));
412
			if (!$useCustomSession) {
413
				// set the session name to the instance id - which is unique
414
				$session = new \OC\Session\Internal($sessionName);
415
			}
416
417
			$cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
418
			$session = $cryptoWrapper->wrapSession($session);
419
			self::$server->setSession($session);
420
421
			// if session can't be started break with http 500 error
422
		} catch (Exception $e) {
423
			\OCP\Util::logException('base', $e);
0 ignored issues
show
Deprecated Code introduced by
The method OCP\Util::logException() has been deprecated with message: 8.2.0 use logException of \OCP\ILogger

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
424
			//show the user a detailed error page
425
			OC_Response::setStatus(OC_Response::STATUS_INTERNAL_SERVER_ERROR);
426
			OC_Template::printExceptionErrorPage($e);
427
			die();
428
		}
429
430
		$sessionLifeTime = self::getSessionLifeTime();
431
432
		// session timeout
433
		if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
434
			if (isset($_COOKIE[session_name()])) {
435
				setcookie(session_name(), null, -1, self::$WEBROOT ? : '/');
436
			}
437
			\OC::$server->getUserSession()->logout();
438
		}
439
440
		$session->set('LAST_ACTIVITY', time());
441
	}
442
443
	/**
444
	 * @return string
445
	 */
446
	private static function getSessionLifeTime() {
447
		return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
448
	}
449
450
	public static function loadAppClassPaths() {
451 View Code Duplication
		foreach (OC_App::getEnabledApps() as $app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
452
			$appPath = OC_App::getAppPath($app);
453
			if ($appPath === false) {
454
				continue;
455
			}
456
457
			$file = $appPath . '/appinfo/classpath.php';
458
			if (file_exists($file)) {
459
				require_once $file;
460
			}
461
		}
462
	}
463
464
	/**
465
	 * Try to set some values to the required Nextcloud default
466
	 */
467
	public static function setRequiredIniValues() {
468
		@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 here. This can introduce security issues, and is generally not recommended.

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...
469
		@ini_set('gd.jpeg_ignore_warning', 1);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
470
	}
471
472
	/**
473
	 * Send the same site cookies
474
	 */
475
	private static function sendSameSiteCookies() {
476
		$cookieParams = session_get_cookie_params();
477
		$secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
478
		$policies = [
479
			'lax',
480
			'strict',
481
		];
482
		foreach($policies as $policy) {
483
			header(
484
				sprintf(
485
					'Set-Cookie: nc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
486
					$policy,
487
					$cookieParams['path'],
488
					$policy
489
				),
490
				false
491
			);
492
		}
493
	}
494
495
	/**
496
	 * Same Site cookie to further mitigate CSRF attacks. This cookie has to
497
	 * be set in every request if cookies are sent to add a second level of
498
	 * defense against CSRF.
499
	 *
500
	 * If the cookie is not sent this will set the cookie and reload the page.
501
	 * We use an additional cookie since we want to protect logout CSRF and
502
	 * also we can't directly interfere with PHP's session mechanism.
503
	 */
504
	private static function performSameSiteCookieProtection() {
505
		if(count($_COOKIE) > 0) {
506
			$request = \OC::$server->getRequest();
507
			$requestUri = $request->getScriptName();
508
			$processingScript = explode('/', $requestUri);
509
			$processingScript = $processingScript[count($processingScript)-1];
510
			// FIXME: In a SAML scenario we don't get any strict or lax cookie
511
			// send for the ACS endpoint. Since we have some legacy code in Nextcloud
512
			// (direct PHP files) the enforcement of lax cookies is performed here
513
			// instead of the middleware.
514
			//
515
			// This means we cannot exclude some routes from the cookie validation,
516
			// which normally is not a problem but is a little bit cumbersome for
517
			// this use-case.
518
			// Once the old legacy PHP endpoints have been removed we can move
519
			// the verification into a middleware and also adds some exemptions.
520
			//
521
			// Questions about this code? Ask Lukas ;-)
522
			$currentUrl = substr(explode('?',$request->getRequestUri(), 2)[0], strlen(\OC::$WEBROOT));
523
			if($currentUrl === '/index.php/apps/user_saml/saml/acs') {
524
				return;
525
			}
526
			// For the "index.php" endpoint only a lax cookie is required.
527
			if($processingScript === 'index.php') {
528
				if(!$request->passesLaxCookieCheck()) {
529
					self::sendSameSiteCookies();
530
					header('Location: '.$_SERVER['REQUEST_URI']);
531
					exit();
532
				}
533
			} else {
534
				// All other endpoints require the lax and the strict cookie
535
				if(!$request->passesStrictCookieCheck()) {
536
					self::sendSameSiteCookies();
537
					// Debug mode gets access to the resources without strict cookie
538
					// due to the fact that the SabreDAV browser also lives there.
539
					if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
540
						http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE);
541
						exit();
542
					}
543
				}
544
			}
545
		} elseif(!isset($_COOKIE['nc_sameSiteCookielax']) || !isset($_COOKIE['nc_sameSiteCookiestrict'])) {
546
			self::sendSameSiteCookies();
547
		}
548
	}
549
550
	public static function init() {
551
		// calculate the root directories
552
		OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
553
554
		// register autoloader
555
		$loaderStart = microtime(true);
556
		require_once __DIR__ . '/autoloader.php';
557
		self::$loader = new \OC\Autoloader([
558
			OC::$SERVERROOT . '/lib/private/legacy',
559
		]);
560
		if (defined('PHPUNIT_RUN')) {
561
			self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
562
		}
563
		spl_autoload_register(array(self::$loader, 'load'));
564
		$loaderEnd = microtime(true);
565
566
		self::$CLI = (php_sapi_name() == 'cli');
567
568
		// Add default composer PSR-4 autoloader
569
		self::$composerAutoloader = require_once OC::$SERVERROOT . '/lib/composer/autoload.php';
570
571
		try {
572
			self::initPaths();
573
			// setup 3rdparty autoloader
574
			$vendorAutoLoad = OC::$SERVERROOT. '/3rdparty/autoload.php';
575
			if (!file_exists($vendorAutoLoad)) {
576
				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".');
577
			}
578
			require_once $vendorAutoLoad;
579
580
		} catch (\RuntimeException $e) {
581
			if (!self::$CLI) {
582
				$claimedProtocol = strtoupper($_SERVER['SERVER_PROTOCOL']);
583
				$protocol = in_array($claimedProtocol, ['HTTP/1.0', 'HTTP/1.1', 'HTTP/2']) ? $claimedProtocol : 'HTTP/1.1';
584
				header($protocol . ' ' . OC_Response::STATUS_SERVICE_UNAVAILABLE);
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();
590
		}
591
592
		// setup the basic server
593
		self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
594
		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
595
		\OC::$server->getEventLogger()->start('boot', 'Initialize');
596
597
		// Don't display errors and log them
598
		error_reporting(E_ALL | E_STRICT);
599
		@ini_set('display_errors', 0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
600
		@ini_set('log_errors', 1);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
601
602
		date_default_timezone_set('UTC');
603
604
		//try to configure php to enable big file uploads.
605
		//this doesn´t work always depending on the webserver and php configuration.
606
		//Let´s try to overwrite some defaults anyway
607
608
		//try to set the maximum execution time to 60min
609
		@set_time_limit(3600);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
610
		@ini_set('max_execution_time', 3600);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
611
		@ini_set('max_input_time', 3600);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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
613
		//try to set the maximum filesize to 10G
614
		@ini_set('upload_max_filesize', '10G');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
615
		@ini_set('post_max_size', '10G');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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
		@ini_set('file_uploads', '50');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
617
618
		self::setRequiredIniValues();
619
		self::handleAuthHeaders();
620
		self::registerAutoloaderCache();
621
622
		// initialize intl fallback is necessary
623
		\Patchwork\Utf8\Bootup::initIntl();
624
		OC_Util::isSetLocaleWorking();
625
626
		if (!defined('PHPUNIT_RUN')) {
627
			OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
628
			$debug = \OC::$server->getConfig()->getSystemValue('debug', false);
629
			OC\Log\ErrorHandler::register($debug);
630
		}
631
632
		// register the stream wrappers
633
		stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir');
634
		stream_wrapper_register('static', 'OC\Files\Stream\StaticStream');
635
		stream_wrapper_register('close', 'OC\Files\Stream\Close');
636
		stream_wrapper_register('quota', 'OC\Files\Stream\Quota');
637
		stream_wrapper_register('oc', 'OC\Files\Stream\OC');
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
		if(self::$server->getRequest()->getServerProtocol() === 'https') {
650
			ini_set('session.cookie_secure', true);
651
		}
652
653
		self::performSameSiteCookieProtection();
654
655
		if (!defined('OC_CONSOLE')) {
656
			$errors = OC_Util::checkServer(\OC::$server->getConfig());
657
			if (count($errors) > 0) {
658
				if (self::$CLI) {
659
					// Convert l10n string into regular string for usage in database
660
					$staticErrors = [];
661
					foreach ($errors as $error) {
662
						echo $error['error'] . "\n";
663
						echo $error['hint'] . "\n\n";
664
						$staticErrors[] = [
665
							'error' => (string)$error['error'],
666
							'hint' => (string)$error['hint'],
667
						];
668
					}
669
670
					try {
671
						\OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
672
					} catch (\Exception $e) {
673
						echo('Writing to database failed');
674
					}
675
					exit(1);
676
				} else {
677
					OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
678
					OC_Template::printGuestPage('', 'error', array('errors' => $errors));
679
					exit;
680
				}
681 View Code Duplication
			} elseif (self::$CLI && \OC::$server->getConfig()->getSystemValue('installed', false)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
682
				\OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
683
			}
684
		}
685
		//try to set the session lifetime
686
		$sessionLifeTime = self::getSessionLifeTime();
687
		@ini_set('gc_maxlifetime', (string)$sessionLifeTime);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
688
689
		$systemConfig = \OC::$server->getSystemConfig();
690
691
		// User and Groups
692
		if (!$systemConfig->getValue("installed", false)) {
693
			self::$server->getSession()->set('user_id', '');
694
		}
695
696
		OC_User::useBackend(new \OC\User\Database());
697
		OC_Group::useBackend(new \OC\Group\Database());
698
699
		// Subscribe to the hook
700
		\OCP\Util::connectHook(
701
			'\OCA\Files_Sharing\API\Server2Server',
702
			'preLoginNameUsedAsUserName',
703
			'\OC\User\Database',
704
			'preLoginNameUsedAsUserName'
705
		);
706
707
		//setup extra user backends
708
		if (!self::checkUpgrade(false)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::checkUpgrade(false) of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
709
			OC_User::setupBackends();
710
		} else {
711
			// Run upgrades in incognito mode
712
			OC_User::setIncognitoMode(true);
713
		}
714
715
		self::registerCacheHooks();
716
		self::registerFilesystemHooks();
717
		if ($systemConfig->getValue('enable_previews', true)) {
718
			self::registerPreviewHooks();
719
		}
720
		self::registerShareHooks();
721
		self::registerLogRotate();
722
		self::registerEncryptionWrapper();
723
		self::registerEncryptionHooks();
724
725
		//make sure temporary files are cleaned up
726
		$tmpManager = \OC::$server->getTempManager();
727
		register_shutdown_function(array($tmpManager, 'clean'));
728
		$lockProvider = \OC::$server->getLockingProvider();
729
		register_shutdown_function(array($lockProvider, 'releaseAll'));
730
731
		// Check whether the sample configuration has been copied
732
		if($systemConfig->getValue('copied_sample_config', false)) {
733
			$l = \OC::$server->getL10N('lib');
734
			header('HTTP/1.1 503 Service Temporarily Unavailable');
735
			header('Status: 503 Service Temporarily Unavailable');
736
			OC_Template::printErrorPage(
737
				$l->t('Sample configuration detected'),
738
				$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')
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
			header('HTTP/1.1 400 Bad Request');
757
			header('Status: 400 Bad Request');
758
759
			\OC::$server->getLogger()->warning(
760
					'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
761
					[
762
						'app' => 'core',
763
						'remoteAddress' => $request->getRemoteAddress(),
764
						'host' => $host,
765
					]
766
			);
767
768
			$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
769
			$tmpl->assign('domain', $host);
770
			$tmpl->printPage();
771
772
			exit();
773
		}
774
		\OC::$server->getEventLogger()->end('boot');
775
	}
776
777
	/**
778
	 * register hooks for the cache
779
	 */
780
	public static function registerCacheHooks() {
781
		//don't try to do this before we are properly setup
782
		if (\OC::$server->getSystemConfig()->getValue('installed', false) && !self::checkUpgrade(false)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::checkUpgrade(false) of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
783
784
			// NOTE: This will be replaced to use OCP
785
			$userSession = self::$server->getUserSession();
786
			$userSession->listen('\OC\User', 'postLogin', function () {
787
				try {
788
					$cache = new \OC\Cache\File();
789
					$cache->gc();
790
				} catch (\OC\ServerNotAvailableException $e) {
791
					// not a GC exception, pass it on
792
					throw $e;
793
				} catch (\Exception $e) {
794
					// a GC exception should not prevent users from using OC,
795
					// so log the exception
796
					\OC::$server->getLogger()->warning('Exception when running cache gc: ' . $e->getMessage(), array('app' => 'core'));
797
				}
798
			});
799
		}
800
	}
801
802
	private static function registerEncryptionWrapper() {
803
		$manager = self::$server->getEncryptionManager();
804
		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
805
	}
806
807
	private static function registerEncryptionHooks() {
808
		$enabled = self::$server->getEncryptionManager()->isEnabled();
809
		if ($enabled) {
810
			\OCP\Util::connectHook('OCP\Share', 'post_shared', 'OC\Encryption\HookManager', 'postShared');
811
			\OCP\Util::connectHook('OCP\Share', 'post_unshare', 'OC\Encryption\HookManager', 'postUnshared');
812
			\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OC\Encryption\HookManager', 'postRename');
813
			\OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', 'OC\Encryption\HookManager', 'postRestore');
814
		}
815
	}
816
817
	/**
818
	 * register hooks for the cache
819
	 */
820
	public static function registerLogRotate() {
821
		$systemConfig = \OC::$server->getSystemConfig();
822
		if ($systemConfig->getValue('installed', false) && $systemConfig->getValue('log_rotate_size', false) && !self::checkUpgrade(false)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::checkUpgrade(false) of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
823
			//don't try to do this before we are properly setup
824
			//use custom logfile path if defined, otherwise use default of nextcloud.log in data directory
825
			\OCP\BackgroundJob::registerJob('OC\Log\Rotate', $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/nextcloud.log'));
0 ignored issues
show
Deprecated Code introduced by
The method OCP\BackgroundJob::registerJob() has been deprecated with message: 8.1.0 Use \OC::$server->getJobList()->add() instead

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
826
		}
827
	}
828
829
	/**
830
	 * register hooks for the filesystem
831
	 */
832
	public static function registerFilesystemHooks() {
833
		// Check for blacklisted files
834
		OC_Hook::connect('OC_Filesystem', 'write', 'OC\Files\Filesystem', 'isBlacklisted');
835
		OC_Hook::connect('OC_Filesystem', 'rename', 'OC\Files\Filesystem', 'isBlacklisted');
836
	}
837
838
	/**
839
	 * register hooks for previews
840
	 */
841
	public static function registerPreviewHooks() {
842
		OC_Hook::connect('OC_Filesystem', 'post_write', 'OC\Preview', 'post_write');
843
		OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'prepare_delete_files');
844
		OC_Hook::connect('\OCP\Versions', 'preDelete', 'OC\Preview', 'prepare_delete');
845
		OC_Hook::connect('\OCP\Trashbin', 'preDelete', 'OC\Preview', 'prepare_delete');
846
		OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC\Preview', 'post_delete_files');
847
		OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete_versions');
848
		OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete');
849
		OC_Hook::connect('\OCP\Versions', 'rollback', 'OC\Preview', 'post_delete_versions');
850
	}
851
852
	/**
853
	 * register hooks for sharing
854
	 */
855
	public static function registerShareHooks() {
856
		if (\OC::$server->getSystemConfig()->getValue('installed')) {
857
			OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share20\Hooks', 'post_deleteUser');
858
			OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share20\Hooks', 'post_removeFromGroup');
859
			OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share20\Hooks', 'post_deleteGroup');
860
		}
861
	}
862
863
	protected static function registerAutoloaderCache() {
864
		// The class loader takes an optional low-latency cache, which MUST be
865
		// namespaced. The instanceid is used for namespacing, but might be
866
		// unavailable at this point. Furthermore, it might not be possible to
867
		// generate an instanceid via \OC_Util::getInstanceId() because the
868
		// config file may not be writable. As such, we only register a class
869
		// loader cache if instanceid is available without trying to create one.
870
		$instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
871
		if ($instanceId) {
872
			try {
873
				$memcacheFactory = \OC::$server->getMemCacheFactory();
874
				self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader'));
0 ignored issues
show
Bug introduced by
The method createLocal() does not exist on OCP\ICacheFactory. Did you maybe mean create()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
875
			} catch (\Exception $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
876
			}
877
		}
878
	}
879
880
	/**
881
	 * Handle the request
882
	 */
883
	public static function handleRequest() {
884
885
		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
886
		$systemConfig = \OC::$server->getSystemConfig();
887
		// load all the classpaths from the enabled apps so they are available
888
		// in the routing files of each app
889
		OC::loadAppClassPaths();
890
891
		// Check if Nextcloud is installed or in maintenance (update) mode
892
		if (!$systemConfig->getValue('installed', false)) {
893
			\OC::$server->getSession()->clear();
894
			$setupHelper = new OC\Setup(\OC::$server->getConfig(), \OC::$server->getIniWrapper(),
895
				\OC::$server->getL10N('lib'), \OC::$server->getThemingDefaults(), \OC::$server->getLogger(),
896
				\OC::$server->getSecureRandom());
897
			$controller = new OC\Core\Controller\SetupController($setupHelper);
898
			$controller->run($_POST);
899
			exit();
900
		}
901
902
		$request = \OC::$server->getRequest();
903
		$requestPath = $request->getRawPathInfo();
904
		if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
905
			self::checkMaintenanceMode();
906
			self::checkUpgrade();
907
		}
908
909
		// emergency app disabling
910
		if ($requestPath === '/disableapp'
911
			&& $request->getMethod() === 'POST'
912
			&& ((string)$request->getParam('appid')) !== ''
913
		) {
914
			\OCP\JSON::callCheck();
0 ignored issues
show
Deprecated Code introduced by
The method OCP\JSON::callCheck() has been deprecated with message: 8.1.0 Use annotation based CSRF checks from the AppFramework instead

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
915
			\OCP\JSON::checkAdminUser();
0 ignored issues
show
Deprecated Code introduced by
The method OCP\JSON::checkAdminUser() has been deprecated with message: 8.1.0 Use annotation based ACLs from the AppFramework instead

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
916
			$appId = (string)$request->getParam('appid');
917
			$appId = \OC_App::cleanAppId($appId);
918
919
			\OC_App::disable($appId);
920
			\OC_JSON::success();
0 ignored issues
show
Deprecated Code introduced by
The method OC_JSON::success() has been deprecated with message: Use a AppFramework JSONResponse instead

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
921
			exit();
922
		}
923
924
		// Always load authentication apps
925
		OC_App::loadApps(['authentication']);
926
927
		// Load minimum set of apps
928
		if (!self::checkUpgrade(false)
0 ignored issues
show
Bug Best Practice introduced by
The expression self::checkUpgrade(false) of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
929
			&& !$systemConfig->getValue('maintenance', false)) {
930
			// For logged-in users: Load everything
931
			if(OC_User::isLoggedIn()) {
0 ignored issues
show
Deprecated Code introduced by
The method OC_User::isLoggedIn() has been deprecated with message: use \OC::$server->getUserSession()->isLoggedIn()

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
932
				OC_App::loadApps();
933
			} else {
934
				// For guests: Load only filesystem and logging
935
				OC_App::loadApps(array('filesystem', 'logging'));
936
				self::handleLogin($request);
937
			}
938
		}
939
940
		if (!self::$CLI) {
941
			try {
942
				if (!$systemConfig->getValue('maintenance', false) && !self::checkUpgrade(false)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::checkUpgrade(false) of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
943
					OC_App::loadApps(array('filesystem', 'logging'));
944
					OC_App::loadApps();
945
				}
946
				self::checkSingleUserMode();
947
				OC_Util::setupFS();
948
				OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
0 ignored issues
show
Deprecated Code introduced by
The method OCP\Route\IRouter::match() has been deprecated with message: 9.0.0

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
949
				return;
950
			} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\Routin...sourceNotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
951
				//header('HTTP/1.0 404 Not Found');
952
			} catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\Routin...thodNotAllowedException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
953
				OC_Response::setStatus(405);
954
				return;
955
			}
956
		}
957
958
		// Handle WebDAV
959
		if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
960
			// not allowed any more to prevent people
961
			// mounting this root directly.
962
			// Users need to mount remote.php/webdav instead.
963
			header('HTTP/1.1 405 Method Not Allowed');
964
			header('Status: 405 Method Not Allowed');
965
			return;
966
		}
967
968
		// Someone is logged in
969
		if (OC_User::isLoggedIn()) {
0 ignored issues
show
Deprecated Code introduced by
The method OC_User::isLoggedIn() has been deprecated with message: use \OC::$server->getUserSession()->isLoggedIn()

This method 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 method will be removed from the class and what other method or class to use instead.

Loading history...
970
			OC_App::loadApps();
971
			OC_User::setupBackends();
972
			OC_Util::setupFS();
973
			// FIXME
974
			// Redirect to default application
975
			OC_Util::redirectToDefaultPage();
976
		} else {
977
			// Not handled and not logged in
978
			header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
979
		}
980
	}
981
982
	/**
983
	 * Check login: apache auth, auth token, basic auth
984
	 *
985
	 * @param OCP\IRequest $request
986
	 * @return boolean
987
	 */
988
	static function handleLogin(OCP\IRequest $request) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
989
		$userSession = self::$server->getUserSession();
990
		if (OC_User::handleApacheAuth()) {
991
			return true;
992
		}
993
		if ($userSession->tryTokenLogin($request)) {
994
			return true;
995
		}
996
		if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
997
			return true;
998
		}
999
		return false;
1000
	}
1001
1002
	protected static function handleAuthHeaders() {
1003
		//copy http auth headers for apache+php-fcgid work around
1004
		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
1005
			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
1006
		}
1007
1008
		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
1009
		$vars = array(
1010
			'HTTP_AUTHORIZATION', // apache+php-cgi work around
1011
			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
1012
		);
1013
		foreach ($vars as $var) {
1014
			if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
1015
				list($name, $password) = explode(':', base64_decode($matches[1]), 2);
1016
				$_SERVER['PHP_AUTH_USER'] = $name;
1017
				$_SERVER['PHP_AUTH_PW'] = $password;
1018
				break;
1019
			}
1020
		}
1021
	}
1022
}
1023
1024
OC::init();
1025