Completed
Push — master ( 2eca9c...0adc68 )
by Lukas
14:43 queued 06:36
created

OC::registerLogRotate()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 4
nc 2
nop 0
dl 0
loc 8
rs 9.2
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Adam Williamson <[email protected]>
6
 * @author Andreas Fischer <[email protected]>
7
 * @author Arthur Schiwon <[email protected]>
8
 * @author Bart Visscher <[email protected]>
9
 * @author Bernhard Posselt <[email protected]>
10
 * @author 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 '
250
					. '%sgiving the webserver write access to the config directory%s.',
251
					 array('<a href="' . $urlGenerator->linkToDocs('admin-dir_permissions') . '" target="_blank" rel="noreferrer">', '</a>'))
252
				);
253
			}
254
		}
255
	}
256
257
	public static function checkInstalled() {
258
		if (defined('OC_CONSOLE')) {
259
			return;
260
		}
261
		// Redirect to installer if not installed
262
		if (!\OC::$server->getSystemConfig()->getValue('installed', false) && OC::$SUBURI !== '/index.php' && OC::$SUBURI !== '/status.php') {
263
			if (OC::$CLI) {
264
				throw new Exception('Not installed');
265
			} else {
266
				$url = OC::$WEBROOT . '/index.php';
267
				header('Location: ' . $url);
268
			}
269
			exit();
270
		}
271
	}
272
273
	public static function checkMaintenanceMode() {
274
		// Allow ajax update script to execute without being stopped
275
		if (\OC::$server->getSystemConfig()->getValue('maintenance', false) && OC::$SUBURI != '/core/ajax/update.php') {
276
			// send http status 503
277
			header('HTTP/1.1 503 Service Temporarily Unavailable');
278
			header('Status: 503 Service Temporarily Unavailable');
279
			header('Retry-After: 120');
280
281
			// render error page
282
			$template = new OC_Template('', 'update.user', 'guest');
283
			OC_Util::addScript('maintenance-check');
284
			$template->printPage();
285
			die();
286
		}
287
	}
288
289
	public static function checkSingleUserMode($lockIfNoUserLoggedIn = false) {
290
		if (!\OC::$server->getSystemConfig()->getValue('singleuser', false)) {
291
			return;
292
		}
293
		$user = OC_User::getUserSession()->getUser();
294
		if ($user) {
295
			$group = \OC::$server->getGroupManager()->get('admin');
296
			if ($group->inGroup($user)) {
0 ignored issues
show
Compatibility introduced by
$user of type object<OCP\IUser> is not a sub-type of object<OC\User\User>. It seems like you assume a concrete implementation of the interface OCP\IUser to be always present.

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

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

Loading history...
297
				return;
298
			}
299
		} else {
300
			if(!$lockIfNoUserLoggedIn) {
301
				return;
302
			}
303
		}
304
		// send http status 503
305
		header('HTTP/1.1 503 Service Temporarily Unavailable');
306
		header('Status: 503 Service Temporarily Unavailable');
307
		header('Retry-After: 120');
308
309
		// render error page
310
		$template = new OC_Template('', 'singleuser.user', 'guest');
311
		$template->printPage();
312
		die();
313
	}
314
315
	/**
316
	 * Checks if the version requires an update and shows
317
	 * @param bool $showTemplate Whether an update screen should get shown
318
	 * @return bool|void
319
	 */
320
	public static function checkUpgrade($showTemplate = true) {
321
		if (\OCP\Util::needUpgrade()) {
322
			$systemConfig = \OC::$server->getSystemConfig();
323
			if ($showTemplate && !$systemConfig->getValue('maintenance', false)) {
324
				self::printUpgradePage();
325
				exit();
326
			} else {
327
				return true;
328
			}
329
		}
330
		return false;
331
	}
332
333
	/**
334
	 * Prints the upgrade page
335
	 */
336
	private static function printUpgradePage() {
337
		$systemConfig = \OC::$server->getSystemConfig();
338
339
		$disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false);
340
		$tooBig = false;
341
		if (!$disableWebUpdater) {
342
			$apps = \OC::$server->getAppManager();
343
			$tooBig = $apps->isInstalled('user_ldap') || $apps->isInstalled('user_shibboleth');
344
			if (!$tooBig) {
345
				// count users
346
				$stats = \OC::$server->getUserManager()->countUsers();
347
				$totalUsers = array_sum($stats);
348
				$tooBig = ($totalUsers > 50);
349
			}
350
		}
351
		if ($disableWebUpdater || $tooBig) {
352
			// send http status 503
353
			header('HTTP/1.1 503 Service Temporarily Unavailable');
354
			header('Status: 503 Service Temporarily Unavailable');
355
			header('Retry-After: 120');
356
357
			// render error page
358
			$template = new OC_Template('', 'update.use-cli', 'guest');
359
			$template->assign('productName', 'nextcloud'); // for now
360
			$template->assign('version', OC_Util::getVersionString());
361
			$template->assign('tooBig', $tooBig);
362
363
			$template->printPage();
364
			die();
365
		}
366
367
		// check whether this is a core update or apps update
368
		$installedVersion = $systemConfig->getValue('version', '0.0.0');
369
		$currentVersion = implode('.', \OCP\Util::getVersion());
370
371
		// if not a core upgrade, then it's apps upgrade
372
		$isAppsOnlyUpgrade = (version_compare($currentVersion, $installedVersion, '='));
373
374
		$oldTheme = $systemConfig->getValue('theme');
375
		$systemConfig->setValue('theme', '');
376
		\OCP\Util::addScript('config'); // needed for web root
377
		\OCP\Util::addScript('update');
378
		\OCP\Util::addStyle('update');
379
380
		/** @var \OC\App\AppManager $appManager */
381
		$appManager = \OC::$server->getAppManager();
382
383
		$tmpl = new OC_Template('', 'update.admin', 'guest');
384
		$tmpl->assign('version', OC_Util::getVersionString());
385
		$tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade);
386
387
		// get third party apps
388
		$ocVersion = \OCP\Util::getVersion();
389
		$incompatibleApps = $appManager->getIncompatibleApps($ocVersion);
390
		$incompatibleShippedApps = [];
391
		foreach ($incompatibleApps as $appInfo) {
392
			if ($appManager->isShipped($appInfo['id'])) {
393
				$incompatibleShippedApps[] = $appInfo['name'] . ' (' . $appInfo['id'] . ')';
394
			}
395
		}
396
397
		if (!empty($incompatibleShippedApps)) {
398
			$l = \OC::$server->getL10N('core');
399
			$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)]);
400
			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);
401
		}
402
403
		$tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
404
		$tmpl->assign('incompatibleAppsList', $incompatibleApps);
405
		$tmpl->assign('productName', 'Nextcloud'); // for now
406
		$tmpl->assign('oldTheme', $oldTheme);
407
		$tmpl->printPage();
408
	}
409
410
	public static function initSession() {
411
		// prevents javascript from accessing php session cookies
412
		ini_set('session.cookie_httponly', true);
413
414
		// set the cookie path to the Nextcloud directory
415
		$cookie_path = OC::$WEBROOT ? : '/';
416
		ini_set('session.cookie_path', $cookie_path);
417
418
		// Let the session name be changed in the initSession Hook
419
		$sessionName = OC_Util::getInstanceId();
420
421
		try {
422
			// Allow session apps to create a custom session object
423
			$useCustomSession = false;
424
			$session = self::$server->getSession();
425
			OC_Hook::emit('OC', 'initSession', array('session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession));
426
			if (!$useCustomSession) {
427
				// set the session name to the instance id - which is unique
428
				$session = new \OC\Session\Internal($sessionName);
429
			}
430
431
			$cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
432
			$session = $cryptoWrapper->wrapSession($session);
433
			self::$server->setSession($session);
434
435
			// if session can't be started break with http 500 error
436
		} catch (Exception $e) {
437
			\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...
438
			//show the user a detailed error page
439
			OC_Response::setStatus(OC_Response::STATUS_INTERNAL_SERVER_ERROR);
440
			OC_Template::printExceptionErrorPage($e);
441
			die();
442
		}
443
444
		$sessionLifeTime = self::getSessionLifeTime();
445
446
		// session timeout
447
		if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
448
			if (isset($_COOKIE[session_name()])) {
449
				setcookie(session_name(), null, -1, self::$WEBROOT ? : '/');
450
			}
451
			\OC::$server->getUserSession()->logout();
452
		}
453
454
		$session->set('LAST_ACTIVITY', time());
455
	}
456
457
	/**
458
	 * @return string
459
	 */
460
	private static function getSessionLifeTime() {
461
		return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
462
	}
463
464
	public static function loadAppClassPaths() {
465 View Code Duplication
		foreach (OC_App::getEnabledApps() as $app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
466
			$appPath = OC_App::getAppPath($app);
467
			if ($appPath === false) {
468
				continue;
469
			}
470
471
			$file = $appPath . '/appinfo/classpath.php';
472
			if (file_exists($file)) {
473
				require_once $file;
474
			}
475
		}
476
	}
477
478
	/**
479
	 * Try to set some values to the required Nextcloud default
480
	 */
481
	public static function setRequiredIniValues() {
482
		@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...
483
		@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...
484
	}
485
486
	/**
487
	 * Send the same site cookies
488
	 */
489
	private static function sendSameSiteCookies() {
490
		$cookieParams = session_get_cookie_params();
491
		$secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
492
		$policies = [
493
			'lax',
494
			'strict',
495
		];
496
497
		// Append __Host to the cookie if it meets the requirements
498
		$cookiePrefix = '';
499
		if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
500
			$cookiePrefix = '__Host-';
501
		}
502
503
		foreach($policies as $policy) {
504
			header(
505
				sprintf(
506
					'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
507
					$cookiePrefix,
508
					$policy,
509
					$cookieParams['path'],
510
					$policy
511
				),
512
				false
513
			);
514
		}
515
	}
516
517
	/**
518
	 * Same Site cookie to further mitigate CSRF attacks. This cookie has to
519
	 * be set in every request if cookies are sent to add a second level of
520
	 * defense against CSRF.
521
	 *
522
	 * If the cookie is not sent this will set the cookie and reload the page.
523
	 * We use an additional cookie since we want to protect logout CSRF and
524
	 * also we can't directly interfere with PHP's session mechanism.
525
	 */
526
	private static function performSameSiteCookieProtection() {
527
		$request = \OC::$server->getRequest();
528
529
		// Some user agents are notorious and don't really properly follow HTTP
530
		// specifications. For those, have an automated opt-out. Since the protection
531
		// for remote.php is applied in base.php as starting point we need to opt out
532
		// here.
533
		$incompatibleUserAgents = [
534
			// OS X Finder
535
			'/^WebDAVFS/',
536
		];
537
		if($request->isUserAgent($incompatibleUserAgents)) {
538
			return;
539
		}
540
541
		// Chrome on Android has a bug that it doesn't sent cookies with the
542
		// same-site attribute for the download manager. To work around that
543
		// all same-site cookies get deleted and recreated directly. Awesome!
544
		// FIXME: Remove once Chrome 54 is deployed to end-users
545
		// @see https://github.com/nextcloud/server/pull/1454
546
		if($request->isUserAgent([\OC\AppFramework\Http\Request::USER_AGENT_ANDROID_MOBILE_CHROME])) {
547
			return;
548
		}
549
550
		if(count($_COOKIE) > 0) {
551
			$requestUri = $request->getScriptName();
552
			$processingScript = explode('/', $requestUri);
553
			$processingScript = $processingScript[count($processingScript)-1];
554
			// FIXME: In a SAML scenario we don't get any strict or lax cookie
555
			// send for the ACS endpoint. Since we have some legacy code in Nextcloud
556
			// (direct PHP files) the enforcement of lax cookies is performed here
557
			// instead of the middleware.
558
			//
559
			// This means we cannot exclude some routes from the cookie validation,
560
			// which normally is not a problem but is a little bit cumbersome for
561
			// this use-case.
562
			// Once the old legacy PHP endpoints have been removed we can move
563
			// the verification into a middleware and also adds some exemptions.
564
			//
565
			// Questions about this code? Ask Lukas ;-)
566
			$currentUrl = substr(explode('?',$request->getRequestUri(), 2)[0], strlen(\OC::$WEBROOT));
567
			if($currentUrl === '/index.php/apps/user_saml/saml/acs') {
568
				return;
569
			}
570
			// For the "index.php" endpoint only a lax cookie is required.
571
			if($processingScript === 'index.php') {
572
				if(!$request->passesLaxCookieCheck()) {
573
					self::sendSameSiteCookies();
574
					header('Location: '.$_SERVER['REQUEST_URI']);
575
					exit();
576
				}
577
			} else {
578
				// All other endpoints require the lax and the strict cookie
579
				if(!$request->passesStrictCookieCheck()) {
580
					self::sendSameSiteCookies();
581
					// Debug mode gets access to the resources without strict cookie
582
					// due to the fact that the SabreDAV browser also lives there.
583
					if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
584
						http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE);
585
						exit();
586
					}
587
				}
588
			}
589
		} elseif(!isset($_COOKIE['nc_sameSiteCookielax']) || !isset($_COOKIE['nc_sameSiteCookiestrict'])) {
590
			self::sendSameSiteCookies();
591
		}
592
	}
593
594
	public static function init() {
595
		// calculate the root directories
596
		OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
597
598
		// register autoloader
599
		$loaderStart = microtime(true);
600
		require_once __DIR__ . '/autoloader.php';
601
		self::$loader = new \OC\Autoloader([
602
			OC::$SERVERROOT . '/lib/private/legacy',
603
		]);
604
		if (defined('PHPUNIT_RUN')) {
605
			self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
606
		}
607
		spl_autoload_register(array(self::$loader, 'load'));
608
		$loaderEnd = microtime(true);
609
610
		self::$CLI = (php_sapi_name() == 'cli');
611
612
		// Add default composer PSR-4 autoloader
613
		self::$composerAutoloader = require_once OC::$SERVERROOT . '/lib/composer/autoload.php';
614
615
		try {
616
			self::initPaths();
617
			// setup 3rdparty autoloader
618
			$vendorAutoLoad = OC::$SERVERROOT. '/3rdparty/autoload.php';
619
			if (!file_exists($vendorAutoLoad)) {
620
				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".');
621
			}
622
			require_once $vendorAutoLoad;
623
624
		} catch (\RuntimeException $e) {
625
			if (!self::$CLI) {
626
				$claimedProtocol = strtoupper($_SERVER['SERVER_PROTOCOL']);
627
				$protocol = in_array($claimedProtocol, ['HTTP/1.0', 'HTTP/1.1', 'HTTP/2']) ? $claimedProtocol : 'HTTP/1.1';
628
				header($protocol . ' ' . OC_Response::STATUS_SERVICE_UNAVAILABLE);
629
			}
630
			// we can't use the template error page here, because this needs the
631
			// DI container which isn't available yet
632
			print($e->getMessage());
633
			exit();
634
		}
635
636
		// setup the basic server
637
		self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
638
		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
639
		\OC::$server->getEventLogger()->start('boot', 'Initialize');
640
641
		// Don't display errors and log them
642
		error_reporting(E_ALL | E_STRICT);
643
		@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...
644
		@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...
645
646
		if(!date_default_timezone_set('UTC')) {
647
			throw new \RuntimeException('Could not set timezone to UTC');
648
		};
649
650
		//try to configure php to enable big file uploads.
651
		//this doesn´t work always depending on the webserver and php configuration.
652
		//Let´s try to overwrite some defaults anyway
653
654
		//try to set the maximum execution time to 60min
655
		@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...
656
		@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...
657
		@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...
658
659
		//try to set the maximum filesize to 10G
660
		@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...
661
		@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...
662
		@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...
663
664
		self::setRequiredIniValues();
665
		self::handleAuthHeaders();
666
		self::registerAutoloaderCache();
667
668
		// initialize intl fallback is necessary
669
		\Patchwork\Utf8\Bootup::initIntl();
670
		OC_Util::isSetLocaleWorking();
671
672
		if (!defined('PHPUNIT_RUN')) {
673
			OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
674
			$debug = \OC::$server->getConfig()->getSystemValue('debug', false);
675
			OC\Log\ErrorHandler::register($debug);
676
		}
677
678
		// register the stream wrappers
679
		stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir');
680
		stream_wrapper_register('static', 'OC\Files\Stream\StaticStream');
681
		stream_wrapper_register('close', 'OC\Files\Stream\Close');
682
		stream_wrapper_register('quota', 'OC\Files\Stream\Quota');
683
684
		\OC::$server->getEventLogger()->start('init_session', 'Initialize session');
685
		OC_App::loadApps(array('session'));
686
		if (!self::$CLI) {
687
			self::initSession();
688
		}
689
		\OC::$server->getEventLogger()->end('init_session');
690
		self::checkConfig();
691
		self::checkInstalled();
692
693
		OC_Response::addSecurityHeaders();
694
		if(self::$server->getRequest()->getServerProtocol() === 'https') {
695
			ini_set('session.cookie_secure', true);
696
		}
697
698
		self::performSameSiteCookieProtection();
699
700
		if (!defined('OC_CONSOLE')) {
701
			$errors = OC_Util::checkServer(\OC::$server->getConfig());
702
			if (count($errors) > 0) {
703
				if (self::$CLI) {
704
					// Convert l10n string into regular string for usage in database
705
					$staticErrors = [];
706
					foreach ($errors as $error) {
707
						echo $error['error'] . "\n";
708
						echo $error['hint'] . "\n\n";
709
						$staticErrors[] = [
710
							'error' => (string)$error['error'],
711
							'hint' => (string)$error['hint'],
712
						];
713
					}
714
715
					try {
716
						\OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
717
					} catch (\Exception $e) {
718
						echo('Writing to database failed');
719
					}
720
					exit(1);
721
				} else {
722
					OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
723
					OC_Template::printGuestPage('', 'error', array('errors' => $errors));
724
					exit;
725
				}
726 View Code Duplication
			} elseif (self::$CLI && \OC::$server->getConfig()->getSystemValue('installed', false)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
727
				\OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
728
			}
729
		}
730
		//try to set the session lifetime
731
		$sessionLifeTime = self::getSessionLifeTime();
732
		@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...
733
734
		$systemConfig = \OC::$server->getSystemConfig();
735
736
		// User and Groups
737
		if (!$systemConfig->getValue("installed", false)) {
738
			self::$server->getSession()->set('user_id', '');
739
		}
740
741
		OC_User::useBackend(new \OC\User\Database());
742
		OC_Group::useBackend(new \OC\Group\Database());
743
744
		// Subscribe to the hook
745
		\OCP\Util::connectHook(
746
			'\OCA\Files_Sharing\API\Server2Server',
747
			'preLoginNameUsedAsUserName',
748
			'\OC\User\Database',
749
			'preLoginNameUsedAsUserName'
750
		);
751
752
		//setup extra user backends
753
		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...
754
			OC_User::setupBackends();
755
		} else {
756
			// Run upgrades in incognito mode
757
			OC_User::setIncognitoMode(true);
758
		}
759
760
		self::registerCacheHooks();
761
		self::registerFilesystemHooks();
762
		if ($systemConfig->getValue('enable_previews', true)) {
763
			self::registerPreviewHooks();
764
		}
765
		self::registerShareHooks();
766
		self::registerLogRotate();
767
		self::registerEncryptionWrapper();
768
		self::registerEncryptionHooks();
769
		self::registerSettingsHooks();
770
771
		//make sure temporary files are cleaned up
772
		$tmpManager = \OC::$server->getTempManager();
773
		register_shutdown_function(array($tmpManager, 'clean'));
774
		$lockProvider = \OC::$server->getLockingProvider();
775
		register_shutdown_function(array($lockProvider, 'releaseAll'));
776
777
		// Check whether the sample configuration has been copied
778
		if($systemConfig->getValue('copied_sample_config', false)) {
779
			$l = \OC::$server->getL10N('lib');
780
			header('HTTP/1.1 503 Service Temporarily Unavailable');
781
			header('Status: 503 Service Temporarily Unavailable');
782
			OC_Template::printErrorPage(
783
				$l->t('Sample configuration detected'),
784
				$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')
785
			);
786
			return;
787
		}
788
789
		$request = \OC::$server->getRequest();
790
		$host = $request->getInsecureServerHost();
791
		/**
792
		 * if the host passed in headers isn't trusted
793
		 * FIXME: Should not be in here at all :see_no_evil:
794
		 */
795
		if (!OC::$CLI
796
			// overwritehost is always trusted, workaround to not have to make
797
			// \OC\AppFramework\Http\Request::getOverwriteHost public
798
			&& self::$server->getConfig()->getSystemValue('overwritehost') === ''
799
			&& !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host)
800
			&& self::$server->getConfig()->getSystemValue('installed', false)
801
		) {
802
			header('HTTP/1.1 400 Bad Request');
803
			header('Status: 400 Bad Request');
804
805
			\OC::$server->getLogger()->warning(
806
					'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
807
					[
808
						'app' => 'core',
809
						'remoteAddress' => $request->getRemoteAddress(),
810
						'host' => $host,
811
					]
812
			);
813
814
			$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
815
			$tmpl->assign('domain', $host);
816
			$tmpl->printPage();
817
818
			exit();
819
		}
820
		\OC::$server->getEventLogger()->end('boot');
821
	}
822
823
	/**
824
	 * register hooks for the cache
825
	 */
826
	public static function registerCacheHooks() {
827
		//don't try to do this before we are properly setup
828
		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...
829
830
			// NOTE: This will be replaced to use OCP
831
			$userSession = self::$server->getUserSession();
832
			$userSession->listen('\OC\User', 'postLogin', function () {
833
				try {
834
					$cache = new \OC\Cache\File();
835
					$cache->gc();
836
				} catch (\OC\ServerNotAvailableException $e) {
837
					// not a GC exception, pass it on
838
					throw $e;
839
				} catch (\Exception $e) {
840
					// a GC exception should not prevent users from using OC,
841
					// so log the exception
842
					\OC::$server->getLogger()->warning('Exception when running cache gc: ' . $e->getMessage(), array('app' => 'core'));
843
				}
844
			});
845
		}
846
	}
847
848
	public static function registerSettingsHooks() {
849
		$dispatcher = \OC::$server->getEventDispatcher();
850
		$dispatcher->addListener(OCP\App\ManagerEvent::EVENT_APP_DISABLE, function($event) {
851
			/** @var \OCP\App\ManagerEvent $event */
852
			\OC::$server->getSettingsManager()->onAppDisabled($event->getAppID());
853
		});
854
		$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...
855
			/** @var \OCP\App\ManagerEvent $event */
856
			$jobList = \OC::$server->getJobList();
857
			$job = 'OC\\Settings\\RemoveOrphaned';
858
			if(!($jobList->has($job, null))) {
859
				$jobList->add($job);
860
			}
861
		});
862
	}
863
864
	private static function registerEncryptionWrapper() {
865
		$manager = self::$server->getEncryptionManager();
866
		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
867
	}
868
869
	private static function registerEncryptionHooks() {
870
		$enabled = self::$server->getEncryptionManager()->isEnabled();
871
		if ($enabled) {
872
			\OCP\Util::connectHook('OCP\Share', 'post_shared', 'OC\Encryption\HookManager', 'postShared');
873
			\OCP\Util::connectHook('OCP\Share', 'post_unshare', 'OC\Encryption\HookManager', 'postUnshared');
874
			\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OC\Encryption\HookManager', 'postRename');
875
			\OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', 'OC\Encryption\HookManager', 'postRestore');
876
		}
877
	}
878
879
	/**
880
	 * register hooks for the cache
881
	 */
882
	public static function registerLogRotate() {
883
		$systemConfig = \OC::$server->getSystemConfig();
884
		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...
885
			//don't try to do this before we are properly setup
886
			//use custom logfile path if defined, otherwise use default of nextcloud.log in data directory
887
			\OCP\BackgroundJob::registerJob('OC\Log\Rotate', $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/nextcloud.log'));
0 ignored issues
show
Deprecated Code introduced by
The method OCP\BackgroundJob::registerJob() has been deprecated with message: 8.1.0 Use \OC::$server->getJobList()->add() instead

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

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

Loading history...
888
		}
889
	}
890
891
	/**
892
	 * register hooks for the filesystem
893
	 */
894
	public static function registerFilesystemHooks() {
895
		// Check for blacklisted files
896
		OC_Hook::connect('OC_Filesystem', 'write', 'OC\Files\Filesystem', 'isBlacklisted');
897
		OC_Hook::connect('OC_Filesystem', 'rename', 'OC\Files\Filesystem', 'isBlacklisted');
898
	}
899
900
	/**
901
	 * register hooks for previews
902
	 */
903
	public static function registerPreviewHooks() {
904
		OC_Hook::connect('OC_Filesystem', 'post_write', 'OC\Preview', 'post_write');
905
		OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'prepare_delete_files');
906
		OC_Hook::connect('\OCP\Versions', 'preDelete', 'OC\Preview', 'prepare_delete');
907
		OC_Hook::connect('\OCP\Trashbin', 'preDelete', 'OC\Preview', 'prepare_delete');
908
		OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC\Preview', 'post_delete_files');
909
		OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete_versions');
910
		OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete');
911
		OC_Hook::connect('\OCP\Versions', 'rollback', 'OC\Preview', 'post_delete_versions');
912
	}
913
914
	/**
915
	 * register hooks for sharing
916
	 */
917
	public static function registerShareHooks() {
918
		if (\OC::$server->getSystemConfig()->getValue('installed')) {
919
			OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share20\Hooks', 'post_deleteUser');
920
			OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share20\Hooks', 'post_removeFromGroup');
921
			OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share20\Hooks', 'post_deleteGroup');
922
		}
923
	}
924
925
	protected static function registerAutoloaderCache() {
926
		// The class loader takes an optional low-latency cache, which MUST be
927
		// namespaced. The instanceid is used for namespacing, but might be
928
		// unavailable at this point. Furthermore, it might not be possible to
929
		// generate an instanceid via \OC_Util::getInstanceId() because the
930
		// config file may not be writable. As such, we only register a class
931
		// loader cache if instanceid is available without trying to create one.
932
		$instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
933
		if ($instanceId) {
934
			try {
935
				$memcacheFactory = \OC::$server->getMemCacheFactory();
936
				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...
937
			} catch (\Exception $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
938
			}
939
		}
940
	}
941
942
	/**
943
	 * Handle the request
944
	 */
945
	public static function handleRequest() {
946
947
		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
948
		$systemConfig = \OC::$server->getSystemConfig();
949
		// load all the classpaths from the enabled apps so they are available
950
		// in the routing files of each app
951
		OC::loadAppClassPaths();
952
953
		// Check if Nextcloud is installed or in maintenance (update) mode
954
		if (!$systemConfig->getValue('installed', false)) {
955
			\OC::$server->getSession()->clear();
956
			$setupHelper = new OC\Setup(\OC::$server->getConfig(), \OC::$server->getIniWrapper(),
957
				\OC::$server->getL10N('lib'), \OC::$server->getThemingDefaults(), \OC::$server->getLogger(),
958
				\OC::$server->getSecureRandom());
959
			$controller = new OC\Core\Controller\SetupController($setupHelper);
960
			$controller->run($_POST);
961
			exit();
962
		}
963
964
		$request = \OC::$server->getRequest();
965
		$requestPath = $request->getRawPathInfo();
966
		if ($requestPath === '/heartbeat') {
967
			return;
968
		}
969
		if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
970
			self::checkMaintenanceMode();
971
			self::checkUpgrade();
972
		}
973
974
		// emergency app disabling
975
		if ($requestPath === '/disableapp'
976
			&& $request->getMethod() === 'POST'
977
			&& ((string)$request->getParam('appid')) !== ''
978
		) {
979
			\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...
980
			\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...
981
			$appId = (string)$request->getParam('appid');
982
			$appId = \OC_App::cleanAppId($appId);
983
984
			\OC_App::disable($appId);
985
			\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...
986
			exit();
987
		}
988
989
		// Always load authentication apps
990
		OC_App::loadApps(['authentication']);
991
992
		// Load minimum set of apps
993
		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...
994
			&& !$systemConfig->getValue('maintenance', false)) {
995
			// For logged-in users: Load everything
996
			if(OC_User::isLoggedIn()) {
0 ignored issues
show
Deprecated Code introduced by
The method OC_User::isLoggedIn() has been deprecated with message: use \OC::$server->getUserSession()->isLoggedIn()

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

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

Loading history...
997
				OC_App::loadApps();
998
			} else {
999
				// For guests: Load only filesystem and logging
1000
				OC_App::loadApps(array('filesystem', 'logging'));
1001
				self::handleLogin($request);
1002
			}
1003
		}
1004
1005
		if (!self::$CLI) {
1006
			try {
1007
				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...
1008
					OC_App::loadApps(array('filesystem', 'logging'));
1009
					OC_App::loadApps();
1010
				}
1011
				self::checkSingleUserMode();
1012
				OC_Util::setupFS();
1013
				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...
1014
				return;
1015
			} 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...
1016
				//header('HTTP/1.0 404 Not Found');
1017
			} 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...
1018
				OC_Response::setStatus(405);
1019
				return;
1020
			}
1021
		}
1022
1023
		// Handle WebDAV
1024
		if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
1025
			// not allowed any more to prevent people
1026
			// mounting this root directly.
1027
			// Users need to mount remote.php/webdav instead.
1028
			header('HTTP/1.1 405 Method Not Allowed');
1029
			header('Status: 405 Method Not Allowed');
1030
			return;
1031
		}
1032
1033
		// Someone is logged in
1034
		if (OC_User::isLoggedIn()) {
0 ignored issues
show
Deprecated Code introduced by
The method OC_User::isLoggedIn() has been deprecated with message: use \OC::$server->getUserSession()->isLoggedIn()

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

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

Loading history...
1035
			OC_App::loadApps();
1036
			OC_User::setupBackends();
1037
			OC_Util::setupFS();
1038
			// FIXME
1039
			// Redirect to default application
1040
			OC_Util::redirectToDefaultPage();
1041
		} else {
1042
			// Not handled and not logged in
1043
			header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
1044
		}
1045
	}
1046
1047
	/**
1048
	 * Check login: apache auth, auth token, basic auth
1049
	 *
1050
	 * @param OCP\IRequest $request
1051
	 * @return boolean
1052
	 */
1053
	static function handleLogin(OCP\IRequest $request) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

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

Loading history...
1054
		$userSession = self::$server->getUserSession();
1055
		if (OC_User::handleApacheAuth()) {
1056
			return true;
1057
		}
1058
		if ($userSession->tryTokenLogin($request)) {
1059
			return true;
1060
		}
1061
		if (isset($_COOKIE['nc_username'])
1062
			&& isset($_COOKIE['nc_token'])
1063
			&& isset($_COOKIE['nc_session_id'])
1064
			&& $userSession->loginWithCookie($_COOKIE['nc_username'], $_COOKIE['nc_token'], $_COOKIE['nc_session_id'])) {
1065
			return true;
1066
		}
1067
		if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
1068
			return true;
1069
		}
1070
		return false;
1071
	}
1072
1073
	protected static function handleAuthHeaders() {
1074
		//copy http auth headers for apache+php-fcgid work around
1075
		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
1076
			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
1077
		}
1078
1079
		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
1080
		$vars = array(
1081
			'HTTP_AUTHORIZATION', // apache+php-cgi work around
1082
			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
1083
		);
1084
		foreach ($vars as $var) {
1085
			if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
1086
				list($name, $password) = explode(':', base64_decode($matches[1]), 2);
1087
				$_SERVER['PHP_AUTH_USER'] = $name;
1088
				$_SERVER['PHP_AUTH_PW'] = $password;
1089
				break;
1090
			}
1091
		}
1092
	}
1093
}
1094
1095
OC::init();
1096