Passed
Push — master ( 5cdc85...37718d )
by Morris
38:53 queued 21:57
created

OC   F

Complexity

Total Complexity 163

Size/Duplication

Total Lines 997
Duplicated Lines 6.32 %

Coupling/Cohesion

Components 1
Dependencies 47

Importance

Changes 0
Metric Value
wmc 163
lcom 1
cbo 47
dl 63
loc 997
rs 1.603
c 0
b 0
f 0

22 Methods

Rating   Name   Duplication   Size   Complexity  
F init() 0 234 27
A registerFilesystemHooks() 0 4 1
B registerCleanupHooks() 0 30 7
A getSessionLifeTime() 0 2 1
B handleLogin() 0 18 8
A registerShareHooks() 0 5 2
B checkConfig() 0 32 7
A loadAppClassPaths() 0 10 4
A registerAutoloaderCache() 0 13 3
B initSession() 0 48 9
F handleRequest() 0 113 22
A handleAuthHeaders() 0 17 6
A setRequiredIniValues() 0 3 1
A checkInstalled() 0 13 6
A registerAccountHooks() 0 3 1
A registerEncryptionWrapper() 0 3 1
A checkMaintenanceMode() 0 13 3
A registerEncryptionHooks() 0 7 2
A sendSameSiteCookies() 0 24 5
F initPaths() 0 100 25
B performSameSiteCookieProtection() 0 45 9
C printUpgradePage() 0 93 13

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like OC often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use OC, and based on these observations, apply Extract Interface, too.

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

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

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

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

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

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

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

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

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

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

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

Loading history...
299
		}
300
	}
301
302
	/**
303
	 * Prints the upgrade page
304
	 *
305
	 * @param \OC\SystemConfig $systemConfig
306
	 */
307
	private static function printUpgradePage(\OC\SystemConfig $systemConfig) {
308
		$disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false);
309
		$tooBig = false;
310
		if (!$disableWebUpdater) {
311
			$apps = \OC::$server->getAppManager();
312
			if ($apps->isInstalled('user_ldap')) {
313
				$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
314
315
				$result = $qb->selectAlias($qb->createFunction('COUNT(*)'), 'user_count')
316
					->from('ldap_user_mapping')
317
					->execute();
318
				$row = $result->fetch();
319
				$result->closeCursor();
320
321
				$tooBig = ($row['user_count'] > 50);
322
			}
323
			if (!$tooBig && $apps->isInstalled('user_saml')) {
324
				$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
325
326
				$result = $qb->selectAlias($qb->createFunction('COUNT(*)'), 'user_count')
327
					->from('user_saml_users')
328
					->execute();
329
				$row = $result->fetch();
330
				$result->closeCursor();
331
332
				$tooBig = ($row['user_count'] > 50);
333
			}
334
			if (!$tooBig) {
335
				// count users
336
				$stats = \OC::$server->getUserManager()->countUsers();
337
				$totalUsers = array_sum($stats);
0 ignored issues
show
Bug introduced by
It seems like $stats can also be of type integer; however, parameter $array of array_sum() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

337
				$totalUsers = array_sum(/** @scrutinizer ignore-type */ $stats);
Loading history...
338
				$tooBig = ($totalUsers > 50);
339
			}
340
		}
341
		$ignoreTooBigWarning = isset($_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup']) &&
342
			$_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup'] === 'IAmSuperSureToDoThis';
343
344
		if ($disableWebUpdater || ($tooBig && !$ignoreTooBigWarning)) {
345
			// send http status 503
346
			http_response_code(503);
347
			header('Retry-After: 120');
348
349
			// render error page
350
			$template = new OC_Template('', 'update.use-cli', 'guest');
351
			$template->assign('productName', 'nextcloud'); // for now
352
			$template->assign('version', OC_Util::getVersionString());
353
			$template->assign('tooBig', $tooBig);
354
355
			$template->printPage();
356
			die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
357
		}
358
359
		// check whether this is a core update or apps update
360
		$installedVersion = $systemConfig->getValue('version', '0.0.0');
361
		$currentVersion = implode('.', \OCP\Util::getVersion());
362
363
		// if not a core upgrade, then it's apps upgrade
364
		$isAppsOnlyUpgrade = version_compare($currentVersion, $installedVersion, '=');
365
366
		$oldTheme = $systemConfig->getValue('theme');
367
		$systemConfig->setValue('theme', '');
368
		OC_Util::addScript('config'); // needed for web root
369
		OC_Util::addScript('update');
370
371
		/** @var \OC\App\AppManager $appManager */
372
		$appManager = \OC::$server->getAppManager();
373
374
		$tmpl = new OC_Template('', 'update.admin', 'guest');
375
		$tmpl->assign('version', OC_Util::getVersionString());
376
		$tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade);
377
378
		// get third party apps
379
		$ocVersion = \OCP\Util::getVersion();
380
		$ocVersion = implode('.', $ocVersion);
381
		$incompatibleApps = $appManager->getIncompatibleApps($ocVersion);
382
		$incompatibleShippedApps = [];
383
		foreach ($incompatibleApps as $appInfo) {
384
			if ($appManager->isShipped($appInfo['id'])) {
385
				$incompatibleShippedApps[] = $appInfo['name'] . ' (' . $appInfo['id'] . ')';
386
			}
387
		}
388
389
		if (!empty($incompatibleShippedApps)) {
390
			$l = \OC::$server->getL10N('core');
391
			$hint = $l->t('The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server.', [implode(', ', $incompatibleShippedApps)]);
392
			throw new \OC\HintException('The files of the app ' . implode(', ', $incompatibleShippedApps) . ' were not replaced correctly. Make sure it is a version compatible with the server.', $hint);
393
		}
394
395
		$tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
396
		$tmpl->assign('incompatibleAppsList', $incompatibleApps);
397
		$tmpl->assign('productName', 'Nextcloud'); // for now
398
		$tmpl->assign('oldTheme', $oldTheme);
399
		$tmpl->printPage();
400
	}
401
402
	public static function initSession() {
403
		if(self::$server->getRequest()->getServerProtocol() === 'https') {
404
			ini_set('session.cookie_secure', true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $newvalue of ini_set(). ( Ignorable by Annotation )

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

404
			ini_set('session.cookie_secure', /** @scrutinizer ignore-type */ true);
Loading history...
405
		}
406
407
		// prevents javascript from accessing php session cookies
408
		ini_set('session.cookie_httponly', 'true');
409
410
		// set the cookie path to the Nextcloud directory
411
		$cookie_path = OC::$WEBROOT ? : '/';
412
		ini_set('session.cookie_path', $cookie_path);
413
414
		// Let the session name be changed in the initSession Hook
415
		$sessionName = OC_Util::getInstanceId();
416
417
		try {
418
			// Allow session apps to create a custom session object
419
			$useCustomSession = false;
420
			$session = self::$server->getSession();
421
			OC_Hook::emit('OC', 'initSession', array('session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession));
422
			if (!$useCustomSession) {
0 ignored issues
show
introduced by
The condition $useCustomSession is always false.
Loading history...
423
				// set the session name to the instance id - which is unique
424
				$session = new \OC\Session\Internal($sessionName);
425
			}
426
427
			$cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
428
			$session = $cryptoWrapper->wrapSession($session);
429
			self::$server->setSession($session);
430
431
			// if session can't be started break with http 500 error
432
		} catch (Exception $e) {
433
			\OC::$server->getLogger()->logException($e, ['app' => 'base']);
434
			//show the user a detailed error page
435
			OC_Template::printExceptionErrorPage($e, 500);
436
			die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
437
		}
438
439
		$sessionLifeTime = self::getSessionLifeTime();
440
441
		// session timeout
442
		if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
443
			if (isset($_COOKIE[session_name()])) {
444
				setcookie(session_name(), '', -1, self::$WEBROOT ? : '/');
445
			}
446
			\OC::$server->getUserSession()->logout();
447
		}
448
449
		$session->set('LAST_ACTIVITY', time());
450
	}
451
452
	/**
453
	 * @return string
454
	 */
455
	private static function getSessionLifeTime() {
456
		return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
457
	}
458
459
	public static function loadAppClassPaths() {
460
		foreach (OC_App::getEnabledApps() as $app) {
461
			$appPath = OC_App::getAppPath($app);
462
			if ($appPath === false) {
463
				continue;
464
			}
465
466
			$file = $appPath . '/appinfo/classpath.php';
467
			if (file_exists($file)) {
468
				require_once $file;
469
			}
470
		}
471
	}
472
473
	/**
474
	 * Try to set some values to the required Nextcloud default
475
	 */
476
	public static function setRequiredIniValues() {
477
		@ini_set('default_charset', 'UTF-8');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ini_set(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

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

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
478
		@ini_set('gd.jpeg_ignore_warning', '1');
479
	}
480
481
	/**
482
	 * Send the same site cookies
483
	 */
484
	private static function sendSameSiteCookies() {
485
		$cookieParams = session_get_cookie_params();
486
		$secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
487
		$policies = [
488
			'lax',
489
			'strict',
490
		];
491
492
		// Append __Host to the cookie if it meets the requirements
493
		$cookiePrefix = '';
494
		if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
495
			$cookiePrefix = '__Host-';
496
		}
497
498
		foreach($policies as $policy) {
499
			header(
500
				sprintf(
501
					'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
502
					$cookiePrefix,
503
					$policy,
504
					$cookieParams['path'],
505
					$policy
506
				),
507
				false
508
			);
509
		}
510
	}
511
512
	/**
513
	 * Same Site cookie to further mitigate CSRF attacks. This cookie has to
514
	 * be set in every request if cookies are sent to add a second level of
515
	 * defense against CSRF.
516
	 *
517
	 * If the cookie is not sent this will set the cookie and reload the page.
518
	 * We use an additional cookie since we want to protect logout CSRF and
519
	 * also we can't directly interfere with PHP's session mechanism.
520
	 */
521
	private static function performSameSiteCookieProtection() {
522
		$request = \OC::$server->getRequest();
523
524
		// Some user agents are notorious and don't really properly follow HTTP
525
		// specifications. For those, have an automated opt-out. Since the protection
526
		// for remote.php is applied in base.php as starting point we need to opt out
527
		// here.
528
		$incompatibleUserAgents = \OC::$server->getConfig()->getSystemValue('csrf.optout');
529
530
		// Fallback, if csrf.optout is unset
531
		if (!is_array($incompatibleUserAgents)) {
532
			$incompatibleUserAgents = [
533
				// OS X Finder
534
				'/^WebDAVFS/',
535
				// Windows webdav drive
536
				'/^Microsoft-WebDAV-MiniRedir/',
537
			];
538
		}
539
540
		if($request->isUserAgent($incompatibleUserAgents)) {
541
			return;
542
		}
543
544
		if(count($_COOKIE) > 0) {
545
			$requestUri = $request->getScriptName();
546
			$processingScript = explode('/', $requestUri);
547
			$processingScript = $processingScript[count($processingScript)-1];
548
549
			// index.php routes are handled in the middleware
550
			if($processingScript === 'index.php') {
551
				return;
552
			}
553
554
			// All other endpoints require the lax and the strict cookie
555
			if(!$request->passesStrictCookieCheck()) {
556
				self::sendSameSiteCookies();
557
				// Debug mode gets access to the resources without strict cookie
558
				// due to the fact that the SabreDAV browser also lives there.
559
				if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
560
					http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE);
561
					exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

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

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

Loading history...
607
		}
608
609
		// setup the basic server
610
		self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
611
		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
612
		\OC::$server->getEventLogger()->start('boot', 'Initialize');
613
614
		// Don't display errors and log them
615
		error_reporting(E_ALL | E_STRICT);
616
		@ini_set('display_errors', '0');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ini_set(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

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

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

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

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

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

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

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
630
		}
631
		@ini_set('max_execution_time', '3600');
632
		@ini_set('max_input_time', '3600');
633
634
		//try to set the maximum filesize to 10G
635
		@ini_set('upload_max_filesize', '10G');
636
		@ini_set('post_max_size', '10G');
637
		@ini_set('file_uploads', '50');
638
639
		self::setRequiredIniValues();
640
		self::handleAuthHeaders();
641
		self::registerAutoloaderCache();
642
643
		// initialize intl fallback is necessary
644
		\Patchwork\Utf8\Bootup::initIntl();
645
		OC_Util::isSetLocaleWorking();
646
647
		if (!defined('PHPUNIT_RUN')) {
648
			OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
649
			$debug = \OC::$server->getConfig()->getSystemValue('debug', false);
650
			OC\Log\ErrorHandler::register($debug);
651
		}
652
653
		\OC::$server->getEventLogger()->start('init_session', 'Initialize session');
654
		OC_App::loadApps(array('session'));
655
		if (!self::$CLI) {
656
			self::initSession();
657
		}
658
		\OC::$server->getEventLogger()->end('init_session');
659
		self::checkConfig();
660
		self::checkInstalled();
661
662
		OC_Response::addSecurityHeaders();
663
664
		self::performSameSiteCookieProtection();
665
666
		if (!defined('OC_CONSOLE')) {
667
			$errors = OC_Util::checkServer(\OC::$server->getSystemConfig());
668
			if (count($errors) > 0) {
669
				if (self::$CLI) {
670
					// Convert l10n string into regular string for usage in database
671
					$staticErrors = [];
672
					foreach ($errors as $error) {
673
						echo $error['error'] . "\n";
674
						echo $error['hint'] . "\n\n";
675
						$staticErrors[] = [
676
							'error' => (string)$error['error'],
677
							'hint' => (string)$error['hint'],
678
						];
679
					}
680
681
					try {
682
						\OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
683
					} catch (\Exception $e) {
684
						echo('Writing to database failed');
685
					}
686
					exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
687
				} else {
688
					http_response_code(503);
689
					OC_Util::addStyle('guest');
690
					OC_Template::printGuestPage('', 'error', array('errors' => $errors));
691
					exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

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

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

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

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

Loading history...
800
			}
801
		}
802
		\OC::$server->getEventLogger()->end('boot');
803
	}
804
805
	/**
806
	 * register hooks for the cleanup of cache and bruteforce protection
807
	 */
808
	public static function registerCleanupHooks() {
809
		//don't try to do this before we are properly setup
810
		if (\OC::$server->getSystemConfig()->getValue('installed', false) && !\OCP\Util::needUpgrade()) {
811
812
			// NOTE: This will be replaced to use OCP
813
			$userSession = self::$server->getUserSession();
814
			$userSession->listen('\OC\User', 'postLogin', function () use ($userSession) {
0 ignored issues
show
Unused Code introduced by
The import $userSession is not used and could be removed.

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

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

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

820
					$throttler->resetDelay($request->getRemoteAddress(), 'login', /** @scrutinizer ignore-type */ ['user' => $uid]);
Loading history...
821
				}
822
823
				try {
824
					$cache = new \OC\Cache\File();
825
					$cache->gc();
826
				} catch (\OC\ServerNotAvailableException $e) {
827
					// not a GC exception, pass it on
828
					throw $e;
829
				} catch (\OC\ForbiddenException $e) {
830
					// filesystem blocked for this request, ignore
831
				} catch (\Exception $e) {
832
					// a GC exception should not prevent users from using OC,
833
					// so log the exception
834
					\OC::$server->getLogger()->logException($e, [
835
						'message' => 'Exception when running cache gc.',
836
						'level' => ILogger::WARN,
837
						'app' => 'core',
838
					]);
839
				}
840
			});
841
		}
842
	}
843
844
	private static function registerEncryptionWrapper() {
845
		$manager = self::$server->getEncryptionManager();
846
		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
847
	}
848
849
	private static function registerEncryptionHooks() {
850
		$enabled = self::$server->getEncryptionManager()->isEnabled();
851
		if ($enabled) {
852
			\OCP\Util::connectHook(Share::class, 'post_shared', HookManager::class, 'postShared');
853
			\OCP\Util::connectHook(Share::class, 'post_unshare', HookManager::class, 'postUnshared');
854
			\OCP\Util::connectHook('OC_Filesystem', 'post_rename', HookManager::class, 'postRename');
855
			\OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', HookManager::class, 'postRestore');
856
		}
857
	}
858
859
	private static function registerAccountHooks() {
860
		$hookHandler = new \OC\Accounts\Hooks(\OC::$server->getLogger());
861
		\OCP\Util::connectHook('OC_User', 'changeUser', $hookHandler, 'changeUserHook');
862
	}
863
864
	/**
865
	 * register hooks for the filesystem
866
	 */
867
	public static function registerFilesystemHooks() {
868
		// Check for blacklisted files
869
		OC_Hook::connect('OC_Filesystem', 'write', Filesystem::class, 'isBlacklisted');
870
		OC_Hook::connect('OC_Filesystem', 'rename', Filesystem::class, 'isBlacklisted');
871
	}
872
873
	/**
874
	 * register hooks for sharing
875
	 */
876
	public static function registerShareHooks() {
877
		if (\OC::$server->getSystemConfig()->getValue('installed')) {
878
			OC_Hook::connect('OC_User', 'post_deleteUser', Hooks::class, 'post_deleteUser');
879
			OC_Hook::connect('OC_User', 'post_removeFromGroup', Hooks::class, 'post_removeFromGroup');
880
			OC_Hook::connect('OC_User', 'post_deleteGroup', Hooks::class, 'post_deleteGroup');
881
		}
882
	}
883
884
	protected static function registerAutoloaderCache() {
885
		// The class loader takes an optional low-latency cache, which MUST be
886
		// namespaced. The instanceid is used for namespacing, but might be
887
		// unavailable at this point. Furthermore, it might not be possible to
888
		// generate an instanceid via \OC_Util::getInstanceId() because the
889
		// config file may not be writable. As such, we only register a class
890
		// loader cache if instanceid is available without trying to create one.
891
		$instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
892
		if ($instanceId) {
893
			try {
894
				$memcacheFactory = \OC::$server->getMemCacheFactory();
895
				self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader'));
896
			} catch (\Exception $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
897
			}
898
		}
899
	}
900
901
	/**
902
	 * Handle the request
903
	 */
904
	public static function handleRequest() {
905
906
		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
907
		$systemConfig = \OC::$server->getSystemConfig();
908
		// load all the classpaths from the enabled apps so they are available
909
		// in the routing files of each app
910
		OC::loadAppClassPaths();
911
912
		// Check if Nextcloud is installed or in maintenance (update) mode
913
		if (!$systemConfig->getValue('installed', false)) {
914
			\OC::$server->getSession()->clear();
915
			$setupHelper = new OC\Setup(
916
				$systemConfig,
917
				\OC::$server->getIniWrapper(),
918
				\OC::$server->getL10N('lib'),
919
				\OC::$server->query(\OCP\Defaults::class),
0 ignored issues
show
Bug introduced by
It seems like OC::server->query(OCP\Defaults::class) can also be of type stdClass; however, parameter $defaults of OC\Setup::__construct() does only seem to accept OCP\Defaults, maybe add an additional type check? ( Ignorable by Annotation )

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

919
				/** @scrutinizer ignore-type */ \OC::$server->query(\OCP\Defaults::class),
Loading history...
920
				\OC::$server->getLogger(),
921
				\OC::$server->getSecureRandom(),
922
				\OC::$server->query(\OC\Installer::class)
0 ignored issues
show
Bug introduced by
It seems like OC::server->query(OC\Installer::class) can also be of type stdClass; however, parameter $installer of OC\Setup::__construct() does only seem to accept OC\Installer, maybe add an additional type check? ( Ignorable by Annotation )

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

922
				/** @scrutinizer ignore-type */ \OC::$server->query(\OC\Installer::class)
Loading history...
923
			);
924
			$controller = new OC\Core\Controller\SetupController($setupHelper);
925
			$controller->run($_POST);
926
			exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
927
		}
928
929
		$request = \OC::$server->getRequest();
930
		$requestPath = $request->getRawPathInfo();
931
		if ($requestPath === '/heartbeat') {
932
			return;
933
		}
934
		if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
935
			self::checkMaintenanceMode();
936
937
			if (\OCP\Util::needUpgrade()) {
938
				if (function_exists('opcache_reset')) {
939
					opcache_reset();
940
				}
941
				if (!$systemConfig->getValue('maintenance', false)) {
942
					self::printUpgradePage($systemConfig);
943
					exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
944
				}
945
			}
946
		}
947
948
		// emergency app disabling
949
		if ($requestPath === '/disableapp'
950
			&& $request->getMethod() === 'POST'
951
			&& ((array)$request->getParam('appid')) !== ''
952
		) {
953
			\OC_JSON::callCheck();
0 ignored issues
show
Deprecated Code introduced by
The function OC_JSON::callCheck() has been deprecated: Use annotation based CSRF checks from the AppFramework instead ( Ignorable by Annotation )

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

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

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

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

Loading history...
954
			\OC_JSON::checkAdminUser();
955
			$appIds = (array)$request->getParam('appid');
956
			foreach($appIds as $appId) {
957
				$appId = \OC_App::cleanAppId($appId);
958
				\OC::$server->getAppManager()->disableApp($appId);
959
			}
960
			\OC_JSON::success();
961
			exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
962
		}
963
964
		// Always load authentication apps
965
		OC_App::loadApps(['authentication']);
966
967
		// Load minimum set of apps
968
		if (!\OCP\Util::needUpgrade()
969
			&& !$systemConfig->getValue('maintenance', false)) {
970
			// For logged-in users: Load everything
971
			if(\OC::$server->getUserSession()->isLoggedIn()) {
972
				OC_App::loadApps();
973
			} else {
974
				// For guests: Load only filesystem and logging
975
				OC_App::loadApps(array('filesystem', 'logging'));
976
				self::handleLogin($request);
977
			}
978
		}
979
980
		if (!self::$CLI) {
981
			try {
982
				if (!$systemConfig->getValue('maintenance', false) && !\OCP\Util::needUpgrade()) {
983
					OC_App::loadApps(array('filesystem', 'logging'));
984
					OC_App::loadApps();
985
				}
986
				OC_Util::setupFS();
987
				OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
0 ignored issues
show
Deprecated Code introduced by
The function OCP\Route\IRouter::match() has been deprecated: 9.0.0 ( Ignorable by Annotation )

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

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

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

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

Loading history...
988
				return;
989
			} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
990
				//header('HTTP/1.0 404 Not Found');
991
			} catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
992
				http_response_code(405);
993
				return;
994
			}
995
		}
996
997
		// Handle WebDAV
998
		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PROPFIND') {
999
			// not allowed any more to prevent people
1000
			// mounting this root directly.
1001
			// Users need to mount remote.php/webdav instead.
1002
			http_response_code(405);
1003
			return;
1004
		}
1005
1006
		// Someone is logged in
1007
		if (\OC::$server->getUserSession()->isLoggedIn()) {
1008
			OC_App::loadApps();
1009
			OC_User::setupBackends();
1010
			OC_Util::setupFS();
1011
			// FIXME
1012
			// Redirect to default application
1013
			OC_Util::redirectToDefaultPage();
1014
		} else {
1015
			// Not handled and not logged in
1016
			header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
1017
		}
1018
	}
1019
1020
	/**
1021
	 * Check login: apache auth, auth token, basic auth
1022
	 *
1023
	 * @param OCP\IRequest $request
1024
	 * @return boolean
1025
	 */
1026
	static function handleLogin(OCP\IRequest $request) {
1027
		$userSession = self::$server->getUserSession();
1028
		if (OC_User::handleApacheAuth()) {
1029
			return true;
1030
		}
1031
		if ($userSession->tryTokenLogin($request)) {
1032
			return true;
1033
		}
1034
		if (isset($_COOKIE['nc_username'])
1035
			&& isset($_COOKIE['nc_token'])
1036
			&& isset($_COOKIE['nc_session_id'])
1037
			&& $userSession->loginWithCookie($_COOKIE['nc_username'], $_COOKIE['nc_token'], $_COOKIE['nc_session_id'])) {
1038
			return true;
1039
		}
1040
		if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
1041
			return true;
1042
		}
1043
		return false;
1044
	}
1045
1046
	protected static function handleAuthHeaders() {
1047
		//copy http auth headers for apache+php-fcgid work around
1048
		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
1049
			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
1050
		}
1051
1052
		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
1053
		$vars = array(
1054
			'HTTP_AUTHORIZATION', // apache+php-cgi work around
1055
			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
1056
		);
1057
		foreach ($vars as $var) {
1058
			if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
1059
				list($name, $password) = explode(':', base64_decode($matches[1]), 2);
1060
				$_SERVER['PHP_AUTH_USER'] = $name;
1061
				$_SERVER['PHP_AUTH_PW'] = $password;
1062
				break;
1063
			}
1064
		}
1065
	}
1066
}
1067
1068
OC::init();
1069