Completed
Push — master ( bf0d96...8e7cff )
by Lukas
25:38 queued 10:30
created

OC::printUpgradePage()   D

Complexity

Conditions 13
Paths 126

Size

Total Lines 97
Code Lines 65

Duplication

Lines 22
Ratio 22.68 %

Importance

Changes 0
Metric Value
cc 13
eloc 65
nc 126
nop 0
dl 22
loc 97
rs 4.6605
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 Björn Schießle <[email protected]>
11
 * @author Christoph Wurst <[email protected]>
12
 * @author davidgumberg <[email protected]>
13
 * @author Florin Peter <[email protected]>
14
 * @author Georg Ehrke <[email protected]>
15
 * @author Hugo Gonzalez Labrador <[email protected]>
16
 * @author Individual IT Services <[email protected]>
17
 * @author Jakob Sack <[email protected]>
18
 * @author Joachim Bauch <[email protected]>
19
 * @author Joachim Sokolowski <[email protected]>
20
 * @author Joas Schilling <[email protected]>
21
 * @author Jörn Friedrich Dreyer <[email protected]>
22
 * @author Lukas Reschke <[email protected]>
23
 * @author Michael Gapczynski <[email protected]>
24
 * @author Morris Jobke <[email protected]>
25
 * @author Owen Winkler <[email protected]>
26
 * @author Phil Davis <[email protected]>
27
 * @author Ramiro Aparicio <[email protected]>
28
 * @author Robin Appelman <[email protected]>
29
 * @author Robin McCorkell <[email protected]>
30
 * @author Roeland Jago Douma <[email protected]>
31
 * @author Stefan Weil <[email protected]>
32
 * @author Thomas Müller <[email protected]>
33
 * @author Thomas Pulzer <[email protected]>
34
 * @author Thomas Tanghus <[email protected]>
35
 * @author Vincent Petry <[email protected]>
36
 * @author Volkan Gezer <[email protected]>
37
 *
38
 * @license AGPL-3.0
39
 *
40
 * This code is free software: you can redistribute it and/or modify
41
 * it under the terms of the GNU Affero General Public License, version 3,
42
 * as published by the Free Software Foundation.
43
 *
44
 * This program is distributed in the hope that it will be useful,
45
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
46
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47
 * GNU Affero General Public License for more details.
48
 *
49
 * You should have received a copy of the GNU Affero General Public License, version 3,
50
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
51
 *
52
 */
53
54
require_once 'public/Constants.php';
55
56
/**
57
 * Class that is a namespace for all global OC variables
58
 * No, we can not put this class in its own file because it is used by
59
 * OC_autoload!
60
 */
61
class OC {
62
	/**
63
	 * Associative array for autoloading. classname => filename
64
	 */
65
	public static $CLASSPATH = array();
66
	/**
67
	 * The installation path for Nextcloud  on the server (e.g. /srv/http/nextcloud)
68
	 */
69
	public static $SERVERROOT = '';
70
	/**
71
	 * the current request path relative to the Nextcloud root (e.g. files/index.php)
72
	 */
73
	private static $SUBURI = '';
74
	/**
75
	 * the Nextcloud root path for http requests (e.g. nextcloud/)
76
	 */
77
	public static $WEBROOT = '';
78
	/**
79
	 * The installation path array of the apps folder on the server (e.g. /srv/http/nextcloud) 'path' and
80
	 * web path in 'url'
81
	 */
82
	public static $APPSROOTS = array();
83
84
	/**
85
	 * @var string
86
	 */
87
	public static $configDir;
88
89
	/**
90
	 * requested app
91
	 */
92
	public static $REQUESTEDAPP = '';
93
94
	/**
95
	 * check if Nextcloud runs in cli mode
96
	 */
97
	public static $CLI = false;
98
99
	/**
100
	 * @var \OC\Autoloader $loader
101
	 */
102
	public static $loader = null;
103
104
	/** @var \Composer\Autoload\ClassLoader $composerAutoloader */
105
	public static $composerAutoloader = null;
106
107
	/**
108
	 * @var \OC\Server
109
	 */
110
	public static $server = null;
111
112
	/**
113
	 * @var \OC\Config
114
	 */
115
	private static $config = null;
116
117
	/**
118
	 * @throws \RuntimeException when the 3rdparty directory is missing or
119
	 * the app path list is empty or contains an invalid path
120
	 */
121
	public static function initPaths() {
122
		if(defined('PHPUNIT_CONFIG_DIR')) {
123
			self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/';
124
		} elseif(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) {
125
			self::$configDir = OC::$SERVERROOT . '/tests/config/';
126
		} elseif($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
127
			self::$configDir = rtrim($dir, '/') . '/';
128
		} else {
129
			self::$configDir = OC::$SERVERROOT . '/config/';
130
		}
131
		self::$config = new \OC\Config(self::$configDir);
132
133
		OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
134
		/**
135
		 * FIXME: The following lines are required because we can't yet instantiiate
136
		 *        \OC::$server->getRequest() since \OC::$server does not yet exist.
137
		 */
138
		$params = [
139
			'server' => [
140
				'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'],
141
				'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'],
142
			],
143
		];
144
		$fakeRequest = new \OC\AppFramework\Http\Request($params, null, new \OC\AllConfig(new \OC\SystemConfig(self::$config)));
145
		$scriptName = $fakeRequest->getScriptName();
146
		if (substr($scriptName, -1) == '/') {
147
			$scriptName .= 'index.php';
148
			//make sure suburi follows the same rules as scriptName
149
			if (substr(OC::$SUBURI, -9) != 'index.php') {
150
				if (substr(OC::$SUBURI, -1) != '/') {
151
					OC::$SUBURI = OC::$SUBURI . '/';
152
				}
153
				OC::$SUBURI = OC::$SUBURI . 'index.php';
154
			}
155
		}
156
157
158
		if (OC::$CLI) {
159
			OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
160
		} else {
161
			if (substr($scriptName, 0 - strlen(OC::$SUBURI)) === OC::$SUBURI) {
162
				OC::$WEBROOT = substr($scriptName, 0, 0 - strlen(OC::$SUBURI));
163
164
				if (OC::$WEBROOT != '' && OC::$WEBROOT[0] !== '/') {
165
					OC::$WEBROOT = '/' . OC::$WEBROOT;
166
				}
167
			} else {
168
				// The scriptName is not ending with OC::$SUBURI
169
				// This most likely means that we are calling from CLI.
170
				// However some cron jobs still need to generate
171
				// a web URL, so we use overwritewebroot as a fallback.
172
				OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
173
			}
174
175
			// Resolve /nextcloud to /nextcloud/ to ensure to always have a trailing
176
			// slash which is required by URL generation.
177
			if($_SERVER['REQUEST_URI'] === \OC::$WEBROOT &&
178
					substr($_SERVER['REQUEST_URI'], -1) !== '/') {
179
				header('Location: '.\OC::$WEBROOT.'/');
180
				exit();
181
			}
182
		}
183
184
		// search the apps folder
185
		$config_paths = self::$config->getValue('apps_paths', array());
186
		if (!empty($config_paths)) {
187
			foreach ($config_paths as $paths) {
188
				if (isset($paths['url']) && isset($paths['path'])) {
189
					$paths['url'] = rtrim($paths['url'], '/');
190
					$paths['path'] = rtrim($paths['path'], '/');
191
					OC::$APPSROOTS[] = $paths;
192
				}
193
			}
194
		} elseif (file_exists(OC::$SERVERROOT . '/apps')) {
195
			OC::$APPSROOTS[] = array('path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true);
196
		} elseif (file_exists(OC::$SERVERROOT . '/../apps')) {
197
			OC::$APPSROOTS[] = array(
198
				'path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps',
199
				'url' => '/apps',
200
				'writable' => true
201
			);
202
		}
203
204
		if (empty(OC::$APPSROOTS)) {
205
			throw new \RuntimeException('apps directory not found! Please put the Nextcloud apps folder in the Nextcloud folder'
206
				. ' or the folder above. You can also configure the location in the config.php file.');
207
		}
208
		$paths = array();
209
		foreach (OC::$APPSROOTS as $path) {
210
			$paths[] = $path['path'];
211
			if (!is_dir($path['path'])) {
212
				throw new \RuntimeException(sprintf('App directory "%s" not found! Please put the Nextcloud apps folder in the'
213
					. ' Nextcloud folder or the folder above. You can also configure the location in the'
214
					. ' config.php file.', $path['path']));
215
			}
216
		}
217
218
		// set the right include path
219
		set_include_path(
220
			implode(PATH_SEPARATOR, $paths)
221
		);
222
	}
223
224
	public static function checkConfig() {
225
		$l = \OC::$server->getL10N('lib');
226
227
		// Create config if it does not already exist
228
		$configFilePath = self::$configDir .'/config.php';
229
		if(!file_exists($configFilePath)) {
230
			@touch($configFilePath);
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...
231
		}
232
233
		// Check if config is writable
234
		$configFileWritable = is_writable($configFilePath);
235
		if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled()
236
			|| !$configFileWritable && self::checkUpgrade(false)) {
237
238
			$urlGenerator = \OC::$server->getURLGenerator();
239
240
			if (self::$CLI) {
241
				echo $l->t('Cannot write into "config" directory!')."\n";
242
				echo $l->t('This can usually be fixed by giving the webserver write access to the config directory')."\n";
243
				echo "\n";
244
				echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-dir_permissions') ])."\n";
245
				exit;
246
			} else {
247
				OC_Template::printErrorPage(
248
					$l->t('Cannot write into "config" directory!'),
249
					$l->t('This can usually be fixed by giving the webserver write access to the config directory. See %s',
250
					 [ $urlGenerator->linkToDocs('admin-dir_permissions') ])
251
				);
252
			}
253
		}
254
	}
255
256
	public static function checkInstalled() {
257
		if (defined('OC_CONSOLE')) {
258
			return;
259
		}
260
		// Redirect to installer if not installed
261
		if (!\OC::$server->getSystemConfig()->getValue('installed', false) && OC::$SUBURI !== '/index.php' && OC::$SUBURI !== '/status.php') {
262
			if (OC::$CLI) {
263
				throw new Exception('Not installed');
264
			} else {
265
				$url = OC::$WEBROOT . '/index.php';
266
				header('Location: ' . $url);
267
			}
268
			exit();
269
		}
270
	}
271
272
	public static function checkMaintenanceMode() {
273
		// Allow ajax update script to execute without being stopped
274
		if (\OC::$server->getSystemConfig()->getValue('maintenance', false) && OC::$SUBURI != '/core/ajax/update.php') {
275
			// send http status 503
276
			header('HTTP/1.1 503 Service Temporarily Unavailable');
277
			header('Status: 503 Service Temporarily Unavailable');
278
			header('Retry-After: 120');
279
280
			// render error page
281
			$template = new OC_Template('', 'update.user', 'guest');
282
			OC_Util::addScript('maintenance-check');
283
			$template->printPage();
284
			die();
285
		}
286
	}
287
288
	/**
289
	 * Checks if the version requires an update and shows
290
	 * @param bool $showTemplate Whether an update screen should get shown
291
	 * @return bool|void
292
	 */
293
	public static function checkUpgrade($showTemplate = true) {
294
		if (\OCP\Util::needUpgrade()) {
295
			$systemConfig = \OC::$server->getSystemConfig();
296
			if ($showTemplate && !$systemConfig->getValue('maintenance', false)) {
297
				self::printUpgradePage();
298
				exit();
299
			} else {
300
				return true;
301
			}
302
		}
303
		return false;
304
	}
305
306
	/**
307
	 * Prints the upgrade page
308
	 */
309
	private static function printUpgradePage() {
310
		$systemConfig = \OC::$server->getSystemConfig();
311
312
		$disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false);
313
		$tooBig = false;
314
		if (!$disableWebUpdater) {
315
			$apps = \OC::$server->getAppManager();
316
			$tooBig = false;
317 View Code Duplication
			if ($apps->isInstalled('user_ldap')) {
318
				$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
319
320
				$result = $qb->selectAlias($qb->createFunction('COUNT(*)'), 'user_count')
321
					->from('ldap_user_mapping')
322
					->execute();
323
				$row = $result->fetch();
324
				$result->closeCursor();
325
326
				$tooBig = ($row['user_count'] > 50);
327
			}
328 View Code Duplication
			if (!$tooBig && $apps->isInstalled('user_saml')) {
329
				$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
330
331
				$result = $qb->selectAlias($qb->createFunction('COUNT(*)'), 'user_count')
332
					->from('user_saml_users')
333
					->execute();
334
				$row = $result->fetch();
335
				$result->closeCursor();
336
337
				$tooBig = ($row['user_count'] > 50);
338
			}
339
			if (!$tooBig) {
340
				// count users
341
				$stats = \OC::$server->getUserManager()->countUsers();
342
				$totalUsers = array_sum($stats);
343
				$tooBig = ($totalUsers > 50);
344
			}
345
		}
346
		$ignoreTooBigWarning = isset($_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup']) &&
347
			$_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup'] === 'IAmSuperSureToDoThis';
348
349
		if ($disableWebUpdater || ($tooBig && !$ignoreTooBigWarning)) {
350
			// send http status 503
351
			header('HTTP/1.1 503 Service Temporarily Unavailable');
352
			header('Status: 503 Service Temporarily Unavailable');
353
			header('Retry-After: 120');
354
355
			// render error page
356
			$template = new OC_Template('', 'update.use-cli', 'guest');
357
			$template->assign('productName', 'nextcloud'); // for now
358
			$template->assign('version', OC_Util::getVersionString());
359
			$template->assign('tooBig', $tooBig);
360
361
			$template->printPage();
362
			die();
363
		}
364
365
		// check whether this is a core update or apps update
366
		$installedVersion = $systemConfig->getValue('version', '0.0.0');
367
		$currentVersion = implode('.', \OCP\Util::getVersion());
368
369
		// if not a core upgrade, then it's apps upgrade
370
		$isAppsOnlyUpgrade = (version_compare($currentVersion, $installedVersion, '='));
371
372
		$oldTheme = $systemConfig->getValue('theme');
373
		$systemConfig->setValue('theme', '');
374
		OC_Util::addScript('config'); // needed for web root
375
		OC_Util::addScript('update');
376
377
		/** @var \OC\App\AppManager $appManager */
378
		$appManager = \OC::$server->getAppManager();
379
380
		$tmpl = new OC_Template('', 'update.admin', 'guest');
381
		$tmpl->assign('version', OC_Util::getVersionString());
382
		$tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade);
383
384
		// get third party apps
385
		$ocVersion = \OCP\Util::getVersion();
386
		$incompatibleApps = $appManager->getIncompatibleApps($ocVersion);
0 ignored issues
show
Documentation introduced by
$ocVersion is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
387
		$incompatibleShippedApps = [];
388
		foreach ($incompatibleApps as $appInfo) {
389
			if ($appManager->isShipped($appInfo['id'])) {
390
				$incompatibleShippedApps[] = $appInfo['name'] . ' (' . $appInfo['id'] . ')';
391
			}
392
		}
393
394
		if (!empty($incompatibleShippedApps)) {
395
			$l = \OC::$server->getL10N('core');
396
			$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)]);
397
			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);
398
		}
399
400
		$tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
0 ignored issues
show
Documentation introduced by
$ocVersion is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
401
		$tmpl->assign('incompatibleAppsList', $incompatibleApps);
402
		$tmpl->assign('productName', 'Nextcloud'); // for now
403
		$tmpl->assign('oldTheme', $oldTheme);
404
		$tmpl->printPage();
405
	}
406
407
	public static function initSession() {
408
		// prevents javascript from accessing php session cookies
409
		ini_set('session.cookie_httponly', true);
410
411
		// set the cookie path to the Nextcloud directory
412
		$cookie_path = OC::$WEBROOT ? : '/';
413
		ini_set('session.cookie_path', $cookie_path);
414
415
		// Let the session name be changed in the initSession Hook
416
		$sessionName = OC_Util::getInstanceId();
417
418
		try {
419
			// Allow session apps to create a custom session object
420
			$useCustomSession = false;
421
			$session = self::$server->getSession();
422
			OC_Hook::emit('OC', 'initSession', array('session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession));
423
			if (!$useCustomSession) {
424
				// set the session name to the instance id - which is unique
425
				$session = new \OC\Session\Internal($sessionName);
426
			}
427
428
			$cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
429
			$session = $cryptoWrapper->wrapSession($session);
430
			self::$server->setSession($session);
431
432
			// if session can't be started break with http 500 error
433
		} catch (Exception $e) {
434
			\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...
435
			//show the user a detailed error page
436
			OC_Response::setStatus(OC_Response::STATUS_INTERNAL_SERVER_ERROR);
437
			OC_Template::printExceptionErrorPage($e);
438
			die();
439
		}
440
441
		$sessionLifeTime = self::getSessionLifeTime();
442
443
		// session timeout
444
		if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
445
			if (isset($_COOKIE[session_name()])) {
446
				setcookie(session_name(), null, -1, self::$WEBROOT ? : '/');
447
			}
448
			\OC::$server->getUserSession()->logout();
449
		}
450
451
		$session->set('LAST_ACTIVITY', time());
452
	}
453
454
	/**
455
	 * @return string
456
	 */
457
	private static function getSessionLifeTime() {
458
		return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
459
	}
460
461
	public static function loadAppClassPaths() {
462 View Code Duplication
		foreach (OC_App::getEnabledApps() as $app) {
463
			$appPath = OC_App::getAppPath($app);
464
			if ($appPath === false) {
465
				continue;
466
			}
467
468
			$file = $appPath . '/appinfo/classpath.php';
469
			if (file_exists($file)) {
470
				require_once $file;
471
			}
472
		}
473
	}
474
475
	/**
476
	 * Try to set some values to the required Nextcloud default
477
	 */
478
	public static function setRequiredIniValues() {
479
		@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...
480
		@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...
481
	}
482
483
	/**
484
	 * Send the same site cookies
485
	 */
486
	private static function sendSameSiteCookies() {
487
		$cookieParams = session_get_cookie_params();
488
		$secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
489
		$policies = [
490
			'lax',
491
			'strict',
492
		];
493
494
		// Append __Host to the cookie if it meets the requirements
495
		$cookiePrefix = '';
496
		if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
497
			$cookiePrefix = '__Host-';
498
		}
499
500
		foreach($policies as $policy) {
501
			header(
502
				sprintf(
503
					'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
504
					$cookiePrefix,
505
					$policy,
506
					$cookieParams['path'],
507
					$policy
508
				),
509
				false
510
			);
511
		}
512
	}
513
514
	/**
515
	 * Same Site cookie to further mitigate CSRF attacks. This cookie has to
516
	 * be set in every request if cookies are sent to add a second level of
517
	 * defense against CSRF.
518
	 *
519
	 * If the cookie is not sent this will set the cookie and reload the page.
520
	 * We use an additional cookie since we want to protect logout CSRF and
521
	 * also we can't directly interfere with PHP's session mechanism.
522
	 */
523
	private static function performSameSiteCookieProtection() {
524
		$request = \OC::$server->getRequest();
525
526
		// Some user agents are notorious and don't really properly follow HTTP
527
		// specifications. For those, have an automated opt-out. Since the protection
528
		// for remote.php is applied in base.php as starting point we need to opt out
529
		// here.
530
		$incompatibleUserAgents = [
531
			// OS X Finder
532
			'/^WebDAVFS/',
533
		];
534
		if($request->isUserAgent($incompatibleUserAgents)) {
535
			return;
536
		}
537
538
		if(count($_COOKIE) > 0) {
539
			$requestUri = $request->getScriptName();
540
			$processingScript = explode('/', $requestUri);
541
			$processingScript = $processingScript[count($processingScript)-1];
542
			// FIXME: In a SAML scenario we don't get any strict or lax cookie
543
			// send for the ACS endpoint. Since we have some legacy code in Nextcloud
544
			// (direct PHP files) the enforcement of lax cookies is performed here
545
			// instead of the middleware.
546
			//
547
			// This means we cannot exclude some routes from the cookie validation,
548
			// which normally is not a problem but is a little bit cumbersome for
549
			// this use-case.
550
			// Once the old legacy PHP endpoints have been removed we can move
551
			// the verification into a middleware and also adds some exemptions.
552
			//
553
			// Questions about this code? Ask Lukas ;-)
554
			$currentUrl = substr(explode('?',$request->getRequestUri(), 2)[0], strlen(\OC::$WEBROOT));
555
			if($currentUrl === '/index.php/apps/user_saml/saml/acs' || $currentUrl === '/apps/user_saml/saml/acs') {
556
				return;
557
			}
558
			// For the "index.php" endpoint only a lax cookie is required.
559
			if($processingScript === 'index.php') {
560
				if(!$request->passesLaxCookieCheck()) {
561
					self::sendSameSiteCookies();
562
					header('Location: '.$_SERVER['REQUEST_URI']);
563
					exit();
564
				}
565
			} else {
566
				// All other endpoints require the lax and the strict cookie
567
				if(!$request->passesStrictCookieCheck()) {
568
					self::sendSameSiteCookies();
569
					// Debug mode gets access to the resources without strict cookie
570
					// due to the fact that the SabreDAV browser also lives there.
571
					if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
572
						http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE);
573
						exit();
574
					}
575
				}
576
			}
577
		} elseif(!isset($_COOKIE['nc_sameSiteCookielax']) || !isset($_COOKIE['nc_sameSiteCookiestrict'])) {
578
			self::sendSameSiteCookies();
579
		}
580
	}
581
582
	public static function init() {
583
		// calculate the root directories
584
		OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
585
586
		// register autoloader
587
		$loaderStart = microtime(true);
588
		require_once __DIR__ . '/autoloader.php';
589
		self::$loader = new \OC\Autoloader([
590
			OC::$SERVERROOT . '/lib/private/legacy',
591
		]);
592
		if (defined('PHPUNIT_RUN')) {
593
			self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
594
		}
595
		spl_autoload_register(array(self::$loader, 'load'));
596
		$loaderEnd = microtime(true);
597
598
		self::$CLI = (php_sapi_name() == 'cli');
599
600
		// Add default composer PSR-4 autoloader
601
		self::$composerAutoloader = require_once OC::$SERVERROOT . '/lib/composer/autoload.php';
602
603
		try {
604
			self::initPaths();
605
			// setup 3rdparty autoloader
606
			$vendorAutoLoad = OC::$SERVERROOT. '/3rdparty/autoload.php';
607
			if (!file_exists($vendorAutoLoad)) {
608
				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".');
609
			}
610
			require_once $vendorAutoLoad;
611
612
		} catch (\RuntimeException $e) {
613
			if (!self::$CLI) {
614
				$claimedProtocol = strtoupper($_SERVER['SERVER_PROTOCOL']);
615
				$protocol = in_array($claimedProtocol, ['HTTP/1.0', 'HTTP/1.1', 'HTTP/2']) ? $claimedProtocol : 'HTTP/1.1';
616
				header($protocol . ' ' . OC_Response::STATUS_SERVICE_UNAVAILABLE);
617
			}
618
			// we can't use the template error page here, because this needs the
619
			// DI container which isn't available yet
620
			print($e->getMessage());
621
			exit();
622
		}
623
624
		// setup the basic server
625
		self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
626
		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
627
		\OC::$server->getEventLogger()->start('boot', 'Initialize');
628
629
		// Don't display errors and log them
630
		error_reporting(E_ALL | E_STRICT);
631
		@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...
632
		@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...
633
634
		if(!date_default_timezone_set('UTC')) {
635
			throw new \RuntimeException('Could not set timezone to UTC');
636
		};
637
638
		//try to configure php to enable big file uploads.
639
		//this doesn´t work always depending on the webserver and php configuration.
640
		//Let´s try to overwrite some defaults anyway
641
642
		//try to set the maximum execution time to 60min
643
		if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
644
			@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...
645
		}
646
		@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...
647
		@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...
648
649
		//try to set the maximum filesize to 10G
650
		@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...
651
		@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...
652
		@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...
653
654
		self::setRequiredIniValues();
655
		self::handleAuthHeaders();
656
		self::registerAutoloaderCache();
657
658
		// initialize intl fallback is necessary
659
		\Patchwork\Utf8\Bootup::initIntl();
660
		OC_Util::isSetLocaleWorking();
661
662
		if (!defined('PHPUNIT_RUN')) {
663
			OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
664
			$debug = \OC::$server->getConfig()->getSystemValue('debug', false);
665
			OC\Log\ErrorHandler::register($debug);
666
		}
667
668
		\OC::$server->getEventLogger()->start('init_session', 'Initialize session');
669
		OC_App::loadApps(array('session'));
670
		if (!self::$CLI) {
671
			self::initSession();
672
		}
673
		\OC::$server->getEventLogger()->end('init_session');
674
		self::checkConfig();
675
		self::checkInstalled();
676
677
		OC_Response::addSecurityHeaders();
678
		if(self::$server->getRequest()->getServerProtocol() === 'https') {
679
			ini_set('session.cookie_secure', true);
680
		}
681
682
		self::performSameSiteCookieProtection();
683
684
		if (!defined('OC_CONSOLE')) {
685
			$errors = OC_Util::checkServer(\OC::$server->getSystemConfig());
686
			if (count($errors) > 0) {
687
				if (self::$CLI) {
688
					// Convert l10n string into regular string for usage in database
689
					$staticErrors = [];
690
					foreach ($errors as $error) {
691
						echo $error['error'] . "\n";
692
						echo $error['hint'] . "\n\n";
693
						$staticErrors[] = [
694
							'error' => (string)$error['error'],
695
							'hint' => (string)$error['hint'],
696
						];
697
					}
698
699
					try {
700
						\OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
701
					} catch (\Exception $e) {
702
						echo('Writing to database failed');
703
					}
704
					exit(1);
705
				} else {
706
					OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
707
					OC_Util::addStyle('guest');
708
					OC_Template::printGuestPage('', 'error', array('errors' => $errors));
709
					exit;
710
				}
711 View Code Duplication
			} elseif (self::$CLI && \OC::$server->getConfig()->getSystemValue('installed', false)) {
712
				\OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
713
			}
714
		}
715
		//try to set the session lifetime
716
		$sessionLifeTime = self::getSessionLifeTime();
717
		@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...
718
719
		$systemConfig = \OC::$server->getSystemConfig();
720
721
		// User and Groups
722
		if (!$systemConfig->getValue("installed", false)) {
723
			self::$server->getSession()->set('user_id', '');
724
		}
725
726
		OC_User::useBackend(new \OC\User\Database());
727
		\OC::$server->getGroupManager()->addBackend(new \OC\Group\Database());
728
729
		// Subscribe to the hook
730
		\OCP\Util::connectHook(
731
			'\OCA\Files_Sharing\API\Server2Server',
732
			'preLoginNameUsedAsUserName',
733
			'\OC\User\Database',
734
			'preLoginNameUsedAsUserName'
735
		);
736
737
		//setup extra user backends
738
		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...
739
			OC_User::setupBackends();
740
		} else {
741
			// Run upgrades in incognito mode
742
			OC_User::setIncognitoMode(true);
743
		}
744
745
		self::registerCacheHooks();
746
		self::registerFilesystemHooks();
747
		self::registerShareHooks();
748
		self::registerLogRotate();
749
		self::registerEncryptionWrapper();
750
		self::registerEncryptionHooks();
751
		self::registerAccountHooks();
752
		self::registerSettingsHooks();
753
754
		$settings = new \OC\Settings\Application();
755
		$settings->register();
756
757
		//make sure temporary files are cleaned up
758
		$tmpManager = \OC::$server->getTempManager();
759
		register_shutdown_function(array($tmpManager, 'clean'));
760
		$lockProvider = \OC::$server->getLockingProvider();
761
		register_shutdown_function(array($lockProvider, 'releaseAll'));
762
763
		// Check whether the sample configuration has been copied
764
		if($systemConfig->getValue('copied_sample_config', false)) {
765
			$l = \OC::$server->getL10N('lib');
766
			header('HTTP/1.1 503 Service Temporarily Unavailable');
767
			header('Status: 503 Service Temporarily Unavailable');
768
			OC_Template::printErrorPage(
769
				$l->t('Sample configuration detected'),
770
				$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')
771
			);
772
			return;
773
		}
774
775
		$request = \OC::$server->getRequest();
776
		$host = $request->getInsecureServerHost();
777
		/**
778
		 * if the host passed in headers isn't trusted
779
		 * FIXME: Should not be in here at all :see_no_evil:
780
		 */
781
		if (!OC::$CLI
782
			// overwritehost is always trusted, workaround to not have to make
783
			// \OC\AppFramework\Http\Request::getOverwriteHost public
784
			&& self::$server->getConfig()->getSystemValue('overwritehost') === ''
785
			&& !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host)
786
			&& self::$server->getConfig()->getSystemValue('installed', false)
787
		) {
788
			// Allow access to CSS resources
789
			$isScssRequest = false;
790
			if(strpos($request->getPathInfo(), '/css/') === 0) {
791
				$isScssRequest = true;
792
			}
793
794
			if (!$isScssRequest) {
795
				header('HTTP/1.1 400 Bad Request');
796
				header('Status: 400 Bad Request');
797
798
				\OC::$server->getLogger()->warning(
799
					'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
800
					[
801
						'app' => 'core',
802
						'remoteAddress' => $request->getRemoteAddress(),
803
						'host' => $host,
804
					]
805
				);
806
807
				$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
808
				$tmpl->assign('domain', $host);
809
				$tmpl->printPage();
810
811
				exit();
812
			}
813
		}
814
		\OC::$server->getEventLogger()->end('boot');
815
	}
816
817
	/**
818
	 * register hooks for the cache
819
	 */
820
	public static function registerCacheHooks() {
821
		//don't try to do this before we are properly setup
822
		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...
823
824
			// NOTE: This will be replaced to use OCP
825
			$userSession = self::$server->getUserSession();
826
			$userSession->listen('\OC\User', 'postLogin', function () {
827
				try {
828
					$cache = new \OC\Cache\File();
829
					$cache->gc();
830
				} catch (\OC\ServerNotAvailableException $e) {
831
					// not a GC exception, pass it on
832
					throw $e;
833
				} catch (\OC\ForbiddenException $e) {
834
					// filesystem blocked for this request, ignore
835
				} catch (\Exception $e) {
836
					// a GC exception should not prevent users from using OC,
837
					// so log the exception
838
					\OC::$server->getLogger()->warning('Exception when running cache gc: ' . $e->getMessage(), array('app' => 'core'));
839
				}
840
			});
841
		}
842
	}
843
844
	public static function registerSettingsHooks() {
845
		$dispatcher = \OC::$server->getEventDispatcher();
846
		$dispatcher->addListener(OCP\App\ManagerEvent::EVENT_APP_DISABLE, function($event) {
847
			/** @var \OCP\App\ManagerEvent $event */
848
			\OC::$server->getSettingsManager()->onAppDisabled($event->getAppID());
849
		});
850
		$dispatcher->addListener(OCP\App\ManagerEvent::EVENT_APP_UPDATE, function($event) {
0 ignored issues
show
Unused Code introduced by
The parameter $event is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
851
			/** @var \OCP\App\ManagerEvent $event */
852
			$jobList = \OC::$server->getJobList();
853
			$job = 'OC\\Settings\\RemoveOrphaned';
854
			if(!($jobList->has($job, null))) {
855
				$jobList->add($job);
856
			}
857
		});
858
	}
859
860
	private static function registerEncryptionWrapper() {
861
		$manager = self::$server->getEncryptionManager();
862
		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
863
	}
864
865
	private static function registerEncryptionHooks() {
866
		$enabled = self::$server->getEncryptionManager()->isEnabled();
867
		if ($enabled) {
868
			\OCP\Util::connectHook('OCP\Share', 'post_shared', 'OC\Encryption\HookManager', 'postShared');
869
			\OCP\Util::connectHook('OCP\Share', 'post_unshare', 'OC\Encryption\HookManager', 'postUnshared');
870
			\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OC\Encryption\HookManager', 'postRename');
871
			\OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', 'OC\Encryption\HookManager', 'postRestore');
872
		}
873
	}
874
875
	private static function registerAccountHooks() {
876
		$hookHandler = new \OC\Accounts\Hooks(\OC::$server->getLogger());
877
		\OCP\Util::connectHook('OC_User', 'changeUser', $hookHandler, 'changeUserHook');
878
	}
879
880
	/**
881
	 * register hooks for the cache
882
	 */
883
	public static function registerLogRotate() {
884
		$systemConfig = \OC::$server->getSystemConfig();
885
		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...
886
			//don't try to do this before we are properly setup
887
			//use custom logfile path if defined, otherwise use default of nextcloud.log in data directory
888
			\OC::$server->getJobList()->add('OC\Log\Rotate');
889
		}
890
	}
891
892
	/**
893
	 * register hooks for the filesystem
894
	 */
895
	public static function registerFilesystemHooks() {
896
		// Check for blacklisted files
897
		OC_Hook::connect('OC_Filesystem', 'write', 'OC\Files\Filesystem', 'isBlacklisted');
898
		OC_Hook::connect('OC_Filesystem', 'rename', 'OC\Files\Filesystem', 'isBlacklisted');
899
	}
900
901
	/**
902
	 * register hooks for sharing
903
	 */
904
	public static function registerShareHooks() {
905
		if (\OC::$server->getSystemConfig()->getValue('installed')) {
906
			OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share20\Hooks', 'post_deleteUser');
907
			OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share20\Hooks', 'post_removeFromGroup');
908
			OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share20\Hooks', 'post_deleteGroup');
909
		}
910
	}
911
912
	protected static function registerAutoloaderCache() {
913
		// The class loader takes an optional low-latency cache, which MUST be
914
		// namespaced. The instanceid is used for namespacing, but might be
915
		// unavailable at this point. Furthermore, it might not be possible to
916
		// generate an instanceid via \OC_Util::getInstanceId() because the
917
		// config file may not be writable. As such, we only register a class
918
		// loader cache if instanceid is available without trying to create one.
919
		$instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
920
		if ($instanceId) {
921
			try {
922
				$memcacheFactory = \OC::$server->getMemCacheFactory();
923
				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...
924
			} catch (\Exception $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
925
			}
926
		}
927
	}
928
929
	/**
930
	 * Handle the request
931
	 */
932
	public static function handleRequest() {
933
934
		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
935
		$systemConfig = \OC::$server->getSystemConfig();
936
		// load all the classpaths from the enabled apps so they are available
937
		// in the routing files of each app
938
		OC::loadAppClassPaths();
939
940
		// Check if Nextcloud is installed or in maintenance (update) mode
941
		if (!$systemConfig->getValue('installed', false)) {
942
			\OC::$server->getSession()->clear();
943
			$setupHelper = new OC\Setup(\OC::$server->getSystemConfig(), \OC::$server->getIniWrapper(),
944
				\OC::$server->getL10N('lib'), \OC::$server->query(\OCP\Defaults::class), \OC::$server->getLogger(),
945
				\OC::$server->getSecureRandom());
946
			$controller = new OC\Core\Controller\SetupController($setupHelper);
947
			$controller->run($_POST);
948
			exit();
949
		}
950
951
		$request = \OC::$server->getRequest();
952
		$requestPath = $request->getRawPathInfo();
953
		if ($requestPath === '/heartbeat') {
954
			return;
955
		}
956
		if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
957
			self::checkMaintenanceMode();
958
			self::checkUpgrade();
959
		}
960
961
		// emergency app disabling
962
		if ($requestPath === '/disableapp'
963
			&& $request->getMethod() === 'POST'
964
			&& ((array)$request->getParam('appid')) !== ''
965
		) {
966
			\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...
967
			\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...
968
			$appIds = (array)$request->getParam('appid');
969
			foreach($appIds as $appId) {
970
				$appId = \OC_App::cleanAppId($appId);
971
				\OC_App::disable($appId);
972
			}
973
			\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...
974
			exit();
975
		}
976
977
		// Always load authentication apps
978
		OC_App::loadApps(['authentication']);
979
980
		// Load minimum set of apps
981
		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...
982
			&& !$systemConfig->getValue('maintenance', false)) {
983
			// For logged-in users: Load everything
984
			if(\OC::$server->getUserSession()->isLoggedIn()) {
985
				OC_App::loadApps();
986
			} else {
987
				// For guests: Load only filesystem and logging
988
				OC_App::loadApps(array('filesystem', 'logging'));
989
				self::handleLogin($request);
990
			}
991
		}
992
993
		if (!self::$CLI) {
994
			try {
995
				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...
996
					OC_App::loadApps(array('filesystem', 'logging'));
997
					OC_App::loadApps();
998
				}
999
				OC_Util::setupFS();
1000
				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...
1001
				return;
1002
			} 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...
1003
				//header('HTTP/1.0 404 Not Found');
1004
			} 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...
1005
				OC_Response::setStatus(405);
1006
				return;
1007
			}
1008
		}
1009
1010
		// Handle WebDAV
1011
		if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
1012
			// not allowed any more to prevent people
1013
			// mounting this root directly.
1014
			// Users need to mount remote.php/webdav instead.
1015
			header('HTTP/1.1 405 Method Not Allowed');
1016
			header('Status: 405 Method Not Allowed');
1017
			return;
1018
		}
1019
1020
		// Someone is logged in
1021
		if (\OC::$server->getUserSession()->isLoggedIn()) {
1022
			OC_App::loadApps();
1023
			OC_User::setupBackends();
1024
			OC_Util::setupFS();
1025
			// FIXME
1026
			// Redirect to default application
1027
			OC_Util::redirectToDefaultPage();
1028
		} else {
1029
			// Not handled and not logged in
1030
			header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
1031
		}
1032
	}
1033
1034
	/**
1035
	 * Check login: apache auth, auth token, basic auth
1036
	 *
1037
	 * @param OCP\IRequest $request
1038
	 * @return boolean
1039
	 */
1040
	static function handleLogin(OCP\IRequest $request) {
1041
		$userSession = self::$server->getUserSession();
1042
		if (OC_User::handleApacheAuth()) {
1043
			return true;
1044
		}
1045
		if ($userSession->tryTokenLogin($request)) {
1046
			return true;
1047
		}
1048
		if (isset($_COOKIE['nc_username'])
1049
			&& isset($_COOKIE['nc_token'])
1050
			&& isset($_COOKIE['nc_session_id'])
1051
			&& $userSession->loginWithCookie($_COOKIE['nc_username'], $_COOKIE['nc_token'], $_COOKIE['nc_session_id'])) {
1052
			return true;
1053
		}
1054
		if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
1055
			return true;
1056
		}
1057
		return false;
1058
	}
1059
1060
	protected static function handleAuthHeaders() {
1061
		//copy http auth headers for apache+php-fcgid work around
1062
		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
1063
			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
1064
		}
1065
1066
		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
1067
		$vars = array(
1068
			'HTTP_AUTHORIZATION', // apache+php-cgi work around
1069
			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
1070
		);
1071
		foreach ($vars as $var) {
1072
			if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
1073
				list($name, $password) = explode(':', base64_decode($matches[1]), 2);
1074
				$_SERVER['PHP_AUTH_USER'] = $name;
1075
				$_SERVER['PHP_AUTH_PW'] = $password;
1076
				break;
1077
			}
1078
		}
1079
	}
1080
}
1081
1082
OC::init();
1083