Completed
Pull Request — master (#32298)
by Thomas
12:54
created

OC::init()   F

Complexity

Conditions 25
Paths 2390

Size

Total Lines 224

Duplication

Lines 3
Ratio 1.34 %

Importance

Changes 0
Metric Value
cc 25
nc 2390
nop 0
dl 3
loc 224
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @author Adam Williamson <[email protected]>
4
 * @author Andreas Fischer <[email protected]>
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Bart Visscher <[email protected]>
7
 * @author Bernhard Posselt <[email protected]>
8
 * @author Björn Schießle <[email protected]>
9
 * @author Christoph Wurst <[email protected]>
10
 * @author davidgumberg <[email protected]>
11
 * @author Florin Peter <[email protected]>
12
 * @author Georg Ehrke <[email protected]>
13
 * @author Hugo Gonzalez Labrador <[email protected]>
14
 * @author Individual IT Services <[email protected]>
15
 * @author Jakob Sack <[email protected]>
16
 * @author Joachim Bauch <[email protected]>
17
 * @author Joas Schilling <[email protected]>
18
 * @author Jörn Friedrich Dreyer <[email protected]>
19
 * @author Juan Pablo Villafáñez <[email protected]>
20
 * @author Lukas Reschke <[email protected]>
21
 * @author Martin Mattel <[email protected]>
22
 * @author Michael Gapczynski <[email protected]>
23
 * @author Morris Jobke <[email protected]>
24
 * @author neumann <[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 Roeland Jago Douma <[email protected]>
32
 * @author scolebrook <[email protected]>
33
 * @author Stefan Weil <[email protected]>
34
 * @author Thomas Müller <[email protected]>
35
 * @author Thomas Tanghus <[email protected]>
36
 * @author Victor Dubiniuk <[email protected]>
37
 * @author Vincent Petry <[email protected]>
38
 * @author Volkan Gezer <[email protected]>
39
 *
40
 * @copyright Copyright (c) 2018, ownCloud GmbH
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 OC\Autoloader;
58
use OCP\IRequest;
59
60
require_once 'public/Constants.php';
61
62
/**
63
 * Class that is a namespace for all global OC variables
64
 * No, we can not put this class in its own file because it is used by
65
 * OC_autoload!
66
 */
67
class OC {
68
	/**
69
	 * Associative array for autoloading. classname => filename
70
	 */
71
	public static $CLASSPATH = [];
72
	/**
73
	 * The installation path for owncloud on the server (e.g. /srv/http/owncloud)
74
	 */
75
	public static $SERVERROOT = '';
76
	/**
77
	 * the current request path relative to the owncloud root (e.g. files/index.php)
78
	 */
79
	private static $SUBURI = '';
80
	/**
81
	 * the owncloud root path for http requests (e.g. owncloud/)
82
	 */
83
	public static $WEBROOT = '';
84
	/**
85
	 * The installation path array of the apps folder on the server (e.g. /srv/http/owncloud) 'path' and
86
	 * web path in 'url'
87
	 */
88
	public static $APPSROOTS = [];
89
90
	/**
91
	 * @var string
92
	 */
93
	public static $configDir;
94
95
	/**
96
	 * requested app
97
	 */
98
	public static $REQUESTEDAPP = '';
99
100
	/**
101
	 * check if ownCloud runs in cli mode
102
	 */
103
	public static $CLI = false;
104
105
	/**
106
	 * @var Autoloader $loader
107
	 */
108
	public static $loader = null;
109
110
	/** @var \Composer\Autoload\ClassLoader $composerAutoloader */
111
	public static $composerAutoloader = null;
112
113
	/**
114
	 * @var \OC\Server
115
	 */
116
	public static $server = null;
117
118
	/**
119
	 * @var \OC\Config
120
	 */
121
	private static $config = null;
122
123
	/**
124
	 * @throws \RuntimeException when the 3rdparty directory is missing or
125
	 * the app path list is empty or contains an invalid path
126
	 */
127
	public static function initPaths() {
128
		if (\defined('PHPUNIT_CONFIG_DIR')) {
129
			self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/';
130
		} elseif (\defined('PHPUNIT_RUN') and PHPUNIT_RUN and \is_dir(OC::$SERVERROOT . '/tests/config/')) {
131
			self::$configDir = OC::$SERVERROOT . '/tests/config/';
132
		} elseif ($dir = \getenv('OWNCLOUD_CONFIG_DIR')) {
133
			self::$configDir = \rtrim($dir, '/') . '/';
134
		} else {
135
			self::$configDir = OC::$SERVERROOT . '/config/';
136
		}
137
		self::$config = new \OC\Config(self::$configDir);
138
139
		OC::$SUBURI = \str_replace("\\", "/", \substr(\realpath($_SERVER["SCRIPT_FILENAME"]), \strlen(OC::$SERVERROOT)));
140
		/**
141
		 * FIXME: The following lines are required because we can't yet instantiiate
142
		 *        \OC::$server->getRequest() since \OC::$server does not yet exist.
143
		 */
144
		$params = [
145
			'server' => [
146
				'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'],
147
				'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'],
148
			],
149
		];
150
		/**
151
		 * The event dispatcher added here will not be used to listen any event.
152
		 * So if the modifications made in the configuration, by fakeRequest
153
		 * will not throw events.
154
		 */
155
		$fakeRequest = new \OC\AppFramework\Http\Request($params, null,
156
			new \OC\AllConfig(new \OC\SystemConfig(self::$config),
157
				new \Symfony\Component\EventDispatcher\EventDispatcher()));
158
		$scriptName = $fakeRequest->getScriptName();
159
		if (\substr($scriptName, -1) == '/') {
160
			$scriptName .= 'index.php';
161
			//make sure suburi follows the same rules as scriptName
162
			if (\substr(OC::$SUBURI, -9) != 'index.php') {
163
				if (\substr(OC::$SUBURI, -1) != '/') {
164
					OC::$SUBURI = OC::$SUBURI . '/';
165
				}
166
				OC::$SUBURI = OC::$SUBURI . 'index.php';
167
			}
168
		}
169
170
		if (OC::$CLI) {
171
			OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
172
		} else {
173
			if (\substr($scriptName, 0 - \strlen(OC::$SUBURI)) === OC::$SUBURI) {
174
				OC::$WEBROOT = \substr($scriptName, 0, 0 - \strlen(OC::$SUBURI));
175
176
				if (OC::$WEBROOT != '' && OC::$WEBROOT[0] !== '/') {
177
					OC::$WEBROOT = '/' . OC::$WEBROOT;
178
				}
179
			} else {
180
				// The scriptName is not ending with OC::$SUBURI
181
				// This most likely means that we are calling from CLI.
182
				// However some cron jobs still need to generate
183
				// a web URL, so we use overwritewebroot as a fallback.
184
				OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
185
			}
186
187
			// Resolve /owncloud to /owncloud/ to ensure to always have a trailing
188
			// slash which is required by URL generation.
189
			if ($_SERVER['REQUEST_URI'] === \OC::$WEBROOT &&
190
					\substr($_SERVER['REQUEST_URI'], -1) !== '/') {
191
				\header('Location: '.\OC::$WEBROOT.'/');
192
				exit();
193
			}
194
		}
195
196
		// search the apps folder
197
		$config_paths = self::$config->getValue('apps_paths', []);
198
		if (!empty($config_paths)) {
199
			foreach ($config_paths as $paths) {
200
				if (isset($paths['url'], $paths['path'])) {
201
					$paths['url'] = \rtrim($paths['url'], '/');
202
					$paths['path'] = \rtrim($paths['path'], '/');
203
					OC::$APPSROOTS[] = $paths;
204
				}
205
			}
206
		} elseif (\file_exists(OC::$SERVERROOT . '/apps')) {
207
			OC::$APPSROOTS[] = ['path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true];
208
		}
209
210
		if (empty(OC::$APPSROOTS)) {
211
			throw new \RuntimeException('apps directory not found! Please put the ownCloud apps folder in the ownCloud folder'
212
				. ' or the folder above. You can also configure the location in the config.php file.');
213
		}
214
		$paths = [];
215
		foreach (OC::$APPSROOTS as $path) {
216
			$paths[] = $path['path'];
217
			if (!\is_dir($path['path'])) {
218
				throw new \RuntimeException(\sprintf('App directory "%s" not found! Please put the ownCloud apps folder in the'
219
					. ' ownCloud folder or the folder above. You can also configure the location in the'
220
					. ' config.php file.', $path['path']));
221
			}
222
		}
223
224
		// set the right include path
225
		\set_include_path(
226
			\implode(PATH_SEPARATOR, $paths)
227
		);
228
	}
229
230
	public static function checkConfig() {
231
		$l = \OC::$server->getL10N('lib');
232
233
		// Create config if it does not already exist
234
		$configFilePath = self::$configDir .'/config.php';
235
		if (!\file_exists($configFilePath)) {
236
			@\touch($configFilePath);
237
		}
238
239
		// Check if config is writable
240
		$configFileWritable = \is_writable($configFilePath);
241
		if (!$configFileWritable && !\OC::$server->getConfig()->isSystemConfigReadOnly()
242
			|| !$configFileWritable && self::checkUpgrade(false)) {
243
			$urlGenerator = \OC::$server->getURLGenerator();
244
245
			if (self::$CLI) {
246
				echo $l->t('Cannot write into "config" directory!')."\n";
247
				echo $l->t('This can usually be fixed by giving the webserver write access to the config directory')."\n";
248
				echo "\n";
249
				echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-dir_permissions') ])."\n";
250
				exit;
251
			} else {
252
				OC_Template::printErrorPage(
253
					$l->t('Cannot write into "config" directory!'),
254
					$l->t('This can usually be fixed by '
255
					. '%sgiving the webserver write access to the config directory%s.',
256
					 ['<a href="' . $urlGenerator->linkToDocs('admin-dir_permissions') . '" target="_blank" rel="noreferrer">', '</a>'])
257
				);
258
			}
259
		}
260
	}
261
262
	public static function checkInstalled() {
263
		if (\defined('OC_CONSOLE')) {
264
			return;
265
		}
266
		// Redirect to installer if not installed
267
		if (!\OC::$server->getSystemConfig()->getValue('installed', false) && OC::$SUBURI != '/index.php') {
268
			if (OC::$CLI) {
269
				throw new Exception('Not installed');
270
			} else {
271
				$url = OC::$WEBROOT . '/index.php';
272
				\header('Location: ' . $url);
273
			}
274
			exit();
275
		}
276
	}
277
278
	/**
279
	 * Limit maintenance mode access
280
	 * @param IRequest $request
281
	 */
282
	public static function checkMaintenanceMode(IRequest $request) {
283
		// Check if requested URL matches 'index.php/occ'
284
		$isOccControllerRequested = \preg_match('|/index\.php$|', $request->getScriptName()) === 1
285
				&& \strpos($request->getPathInfo(), '/occ/') === 0;
286
		// Allow ajax update script to execute without being stopped
287
		if (
288
			\OC::$server->getSystemConfig()->getValue('maintenance', false)
289
			&& OC::$SUBURI != '/core/ajax/update.php'
290
			&& !$isOccControllerRequested
291
		) {
292
			// send http status 503
293
			\header('HTTP/1.1 503 Service Temporarily Unavailable');
294
			\header('Status: 503 Service Temporarily Unavailable');
295
			\header('Retry-After: 120');
296
297
			// render error page
298
			$template = new OC_Template('', 'update.user', 'guest');
299
			OC_Util::addScript('maintenance-check');
300
			$template->printPage();
301
			die();
302
		}
303
	}
304
305
	public static function checkSingleUserMode($lockIfNoUserLoggedIn = false) {
306
		if (!\OC::$server->getSystemConfig()->getValue('singleuser', false)) {
307
			return;
308
		}
309
		$user = OC_User::getUserSession()->getUser();
310
		if ($user) {
311
			$group = \OC::$server->getGroupManager()->get('admin');
312
			if ($group->inGroup($user)) {
313
				return;
314
			}
315
		} else {
316
			if (!$lockIfNoUserLoggedIn) {
317
				return;
318
			}
319
		}
320
		// send http status 503
321
		\header('HTTP/1.1 503 Service Temporarily Unavailable');
322
		\header('Status: 503 Service Temporarily Unavailable');
323
		\header('Retry-After: 120');
324
325
		// render error page
326
		$template = new OC_Template('', 'singleuser.user', 'guest');
327
		$template->printPage();
328
		die();
329
	}
330
331
	/**
332
	 * Checks if the version requires an update and shows
333
	 * @param bool $showTemplate Whether an update screen should get shown
334
	 * @return bool
335
	 */
336
	public static function checkUpgrade($showTemplate = true) {
337
		if (\OCP\Util::needUpgrade()) {
338
			$systemConfig = \OC::$server->getSystemConfig();
339
			if ($showTemplate && !$systemConfig->getValue('maintenance', false)) {
340
				self::printUpgradePage();
341
				exit();
342
			} else {
343
				return true;
344
			}
345
		}
346
		return false;
347
	}
348
349
	/**
350
	 * Prints the upgrade page
351
	 */
352
	private static function printUpgradePage() {
353
		$systemConfig = \OC::$server->getSystemConfig();
354
355
		$disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false);
356
		$tooBig = false;
357
		if (!$disableWebUpdater) {
358
			$apps = \OC::$server->getAppManager();
359
			$tooBig = $apps->isInstalled('user_ldap') || $apps->isInstalled('user_shibboleth');
360
			if (!$tooBig) {
361
				// count users
362
				$db = new \OC\User\Database();
363
				$tooBig = ($db->countUsers() > 50);
364
			}
365
		}
366
		if ($disableWebUpdater || $tooBig) {
367
			// send http status 503
368
			\header('HTTP/1.1 503 Service Temporarily Unavailable');
369
			\header('Status: 503 Service Temporarily Unavailable');
370
			\header('Retry-After: 120');
371
372
			// render error page
373
			$template = new OC_Template('', 'update.use-cli', 'guest');
374
			$template->assign('productName', 'ownCloud'); // for now
375
			$template->assign('version', OC_Util::getVersionString());
376
			$template->assign('tooBig', $tooBig);
377
378
			$template->printPage();
379
			die();
380
		}
381
382
		// check whether this is a core update or apps update
383
		$installedVersion = $systemConfig->getValue('version', '0.0.0');
384
		$currentVersion = \implode('.', \OCP\Util::getVersion());
385
386
		// if not a core upgrade, then it's apps upgrade
387
		$isAppsOnlyUpgrade = (\version_compare($currentVersion, $installedVersion, '='));
388
389
		$oldTheme = $systemConfig->getValue('theme');
390
		$systemConfig->setValue('theme', '');
391
		\OCP\Util::addScript('config'); // needed for web root
392
		\OCP\Util::addScript('update');
393
		\OCP\Util::addStyle('update');
394
395
		/** @var \OC\App\AppManager $appManager */
396
		$appManager = \OC::$server->getAppManager();
397
398
		$tmpl = new OC_Template('', 'update.admin', 'guest');
399
		$tmpl->assign('version', OC_Util::getVersionString());
400
		$tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade);
401
402
		// get third party apps
403
		$ocVersion = \OCP\Util::getVersion();
404
		$tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
405
		$tmpl->assign('productName', 'ownCloud'); // for now
406
		$tmpl->assign('oldTheme', $oldTheme);
407
		$tmpl->printPage();
408
	}
409
410
	public static function initSession() {
411
		// Let the session name be changed in the initSession Hook
412
		$sessionName = OC_Util::getInstanceId();
413
414
		try {
415
			// Allow session apps to create a custom session object
416
			$useCustomSession = false;
417
			$session = self::$server->getSession();
418
			OC_Hook::emit('OC', 'initSession', ['session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession]);
419
			if (!$useCustomSession) {
420
				// set the session name to the instance id - which is unique
421
				$session = new \OC\Session\Internal($sessionName);
422
			}
423
424
			$cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
425
			$session = $cryptoWrapper->wrapSession($session);
426
			self::$server->setSession($session);
427
428
			// if session can't be started break with http 500 error
429
		} catch (Exception $e) {
430
			\OCP\Util::logException('base', $e);
431
			//show the user a detailed error page
432
			OC_Response::setStatus(OC_Response::STATUS_INTERNAL_SERVER_ERROR);
433
			OC_Template::printExceptionErrorPage($e);
434
			die();
435
		}
436
437
		$sessionLifeTime = self::getSessionLifeTime();
438
439
		// session timeout
440
		if ($session->exists('LAST_ACTIVITY') && (\time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
441
			if (isset($_COOKIE[\session_name()])) {
442
				\setcookie(\session_name(), null, -1, self::$WEBROOT ? : '/');
443
			}
444
			\OC::$server->getUserSession()->logout();
445
		}
446
447
		$session->set('LAST_ACTIVITY', \time());
448
	}
449
450
	/**
451
	 * @return string
452
	 */
453
	public static function getSessionLifeTime() {
454
		return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
455
	}
456
457
	public static function loadAppClassPaths() {
458 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...
459
			$appPath = OC_App::getAppPath($app);
460
			if ($appPath === false) {
461
				continue;
462
			}
463
464
			$file = $appPath . '/appinfo/classpath.php';
465
			if (\file_exists($file)) {
466
				require_once $file;
467
			}
468
		}
469
	}
470
471
	/**
472
	 * @throws \OCP\AppFramework\QueryException
473
	 * @codeCoverageIgnore
474
	 */
475
	public static function init() {
476
		// calculate the root directories
477
		OC::$SERVERROOT = \str_replace("\\", '/', \substr(__DIR__, 0, -4));
478
479
		// register autoloader
480
		$loaderStart = \microtime(true);
481
		self::$CLI = (\in_array(\php_sapi_name(), ['cli', 'phpdbg']));
482
483
		// setup 3rdparty autoloader
484
		$vendorAutoLoad = OC::$SERVERROOT . '/lib/composer/autoload.php';
485
		if (!\file_exists($vendorAutoLoad)) {
486
			\printf('Composer autoloader not found, unable to continue. Please run "make".');
487
			exit();
488
		}
489
490
		// Add default composer PSR-4 autoloader
491
		self::$composerAutoloader = require $vendorAutoLoad;
492
		if (!self::$composerAutoloader) {
493
			print('Composer autoloader not found!');
494
			exit();
495
		}
496
		self::$loader = new Autoloader();
497
		if (\defined('PHPUNIT_RUN')) {
498
			self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
499
		}
500
		\spl_autoload_register([self::$loader, 'load']);
501
		$loaderEnd = \microtime(true);
502
503
		try {
504
			self::initPaths();
505
		} catch (\RuntimeException $e) {
506
			if (!self::$CLI) {
507
				// can`t use OC_Response::setStatus because server is not
508
				// initialized here
509
				\http_response_code(OC_Response::STATUS_SERVICE_UNAVAILABLE);
510
			}
511
			// we can't use the template error page here, because this needs the
512
			// DI container which isn't available yet
513
			print($e->getMessage());
514
			exit();
515
		}
516
517
		// setup the basic server
518
		self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
519
		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
520
		\OC::$server->getEventLogger()->start('boot', 'Initialize');
521
522
		// Don't display errors and log them
523
		\error_reporting(E_ALL | E_STRICT);
524
525
		if (!\date_default_timezone_set('UTC')) {
526
			\OC::$server->getLogger()->error('Could not set timezone to UTC');
527
		};
528
529
		//try to configure php to enable big file uploads.
530
		//this doesn´t work always depending on the webserver and php configuration.
531
		//Let´s try to overwrite some defaults anyway
532
533
		//try to set the maximum execution time to 60min
534
		@\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...
535
536
		self::handleAuthHeaders();
537
		self::registerAutoloaderCache();
538
539
		// initialize intl fallback is necessary
540
		\Patchwork\Utf8\Bootup::initIntl();
541
		OC_Util::isSetLocaleWorking();
542
543
		if (!\defined('PHPUNIT_RUN')) {
544
			OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
545
			$debug = \OC::$server->getConfig()->getSystemValue('debug', false);
546
			OC\Log\ErrorHandler::register($debug);
547
		}
548
549
		// register the stream wrappers
550
		\stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir');
551
		\stream_wrapper_register('static', 'OC\Files\Stream\StaticStream');
552
		\stream_wrapper_register('close', 'OC\Files\Stream\Close');
553
		\stream_wrapper_register('quota', 'OC\Files\Stream\Quota');
554
555
		\OC::$server->getEventLogger()->start('init_session', 'Initialize session');
556
		OC_App::loadApps(['session', 'theme']);
557
		if (!self::$CLI) {
558
			self::initSession();
559
		}
560
561
		\OC::$server->getEventLogger()->end('init_session');
562
563
		// incognito mode for now
564
		$uid = \OC::$server->getSession()->get('user_id');
565
		\OC::$server->getSession()->set('user_id', null);
566
567
		self::checkConfig();
568
		self::checkInstalled();
569
570
		OC_Response::addSecurityHeaders();
571
572
		if (!\defined('OC_CONSOLE')) {
573
			$errors = OC_Util::checkServer(\OC::$server->getConfig());
574
			if (\count($errors) > 0) {
575
				if (self::$CLI) {
576
					// Convert l10n string into regular string for usage in database
577
					$staticErrors = [];
578
					foreach ($errors as $error) {
579
						echo $error['error'] . "\n";
580
						echo $error['hint'] . "\n\n";
581
						$staticErrors[] = [
582
							'error' => (string)$error['error'],
583
							'hint' => (string)$error['hint'],
584
						];
585
					}
586
587
					try {
588
						\OC::$server->getConfig()->setAppValue('core', 'cronErrors', \json_encode($staticErrors));
589
					} catch (\Exception $e) {
590
						echo('Writing to database failed');
591
					}
592
					exit(1);
593
				} else {
594
					OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
595
					OC_Template::printGuestPage('', 'error', ['errors' => $errors]);
596
					exit;
597
				}
598 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...
599
				\OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
600
			}
601
		}
602
603
		// set back user
604
		\OC::$server->getSession()->set('user_id', $uid);
605
606
		$systemConfig = \OC::$server->getSystemConfig();
607
608
		// User and Groups
609
		if ($systemConfig->getValue("installed", false)) {
610
			OC_User::useBackend(new \OC\User\Database());
611
			\OC::$server->getGroupManager()->addBackend(new \OC\Group\Database());
612
		} else {
613
			self::$server->getSession()->set('user_id', '');
614
		}
615
616
		// Subscribe to the hook
617
		\OCP\Util::connectHook(
618
			'\OCA\Files_Sharing\API\Server2Server',
619
			'preLoginNameUsedAsUserName',
620
			'\OC\User\Database',
621
			'preLoginNameUsedAsUserName'
622
		);
623
624
		//setup extra user backends
625
		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...
626
			OC_User::setupBackends();
627
		} else {
628
			// Run upgrades in incognito mode
629
			OC_User::setIncognitoMode(true);
630
		}
631
632
		self::registerCacheHooks();
633
		self::registerFilesystemHooks();
634
		if ($systemConfig->getValue('enable_previews', true)) {
635
			self::registerPreviewHooks();
636
		}
637
		self::registerShareHooks();
638
		self::registerLogRotate();
639
		if ($systemConfig->getValue("installed", false)) {
640
			self::registerEncryptionWrapper();
641
			self::registerEncryptionHooks();
642
		}
643
644
		//make sure temporary files are cleaned up
645
		\OC::$server->getShutdownHandler()->register(function () {
646
			$tmpManager = \OC::$server->getTempManager();
647
			$tmpManager->clean();
648
		});
649
		\OC::$server->getShutdownHandler()->register(function () {
650
			$lockProvider = \OC::$server->getLockingProvider();
651
			$lockProvider->releaseAll();
652
		});
653
654
		// Check whether the sample configuration has been copied
655
		if ($systemConfig->getValue('copied_sample_config', false)) {
656
			$l = \OC::$server->getL10N('lib');
657
			\header('HTTP/1.1 503 Service Temporarily Unavailable');
658
			\header('Status: 503 Service Temporarily Unavailable');
659
			OC_Template::printErrorPage(
660
				$l->t('Sample configuration detected'),
661
				$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')
662
			);
663
			return;
664
		}
665
666
		$request = \OC::$server->getRequest();
667
		$host = $request->getInsecureServerHost();
668
		/**
669
		 * if the host passed in headers isn't trusted
670
		 * FIXME: Should not be in here at all :see_no_evil:
671
		 */
672
		if (!OC::$CLI
673
			// overwritehost is always trusted, workaround to not have to make
674
			// \OC\AppFramework\Http\Request::getOverwriteHost public
675
			&& self::$server->getConfig()->getSystemValue('overwritehost') === ''
676
			&& !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host)
677
			&& self::$server->getConfig()->getSystemValue('installed', false)
678
		) {
679
			\header('HTTP/1.1 400 Bad Request');
680
			\header('Status: 400 Bad Request');
681
682
			\OC::$server->getLogger()->warning(
683
					'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
684
					[
685
						'app' => 'core',
686
						'remoteAddress' => $request->getRemoteAddress(),
687
						'host' => $host,
688
					]
689
			);
690
691
			$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
692
			$tmpl->assign('domain', $host);
693
			$tmpl->printPage();
694
695
			exit();
696
		}
697
		\OC::$server->getEventLogger()->end('boot');
698
	}
699
700
	/**
701
	 * register hooks for the cache
702
	 */
703
	public static function registerCacheHooks() {
704
		//don't try to do this before we are properly setup
705
		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...
706
707
			// NOTE: This will be replaced to use OCP
708
			$userSession = self::$server->getUserSession();
709
			$userSession->listen('\OC\User', 'postLogin', function () {
710
				try {
711
					$cache = new \OC\Cache\File();
712
					$cache->gc();
713
				} catch (\OC\ServerNotAvailableException $e) {
714
					// not a GC exception, pass it on
715
					throw $e;
716
				} catch (\Exception $e) {
717
					// a GC exception should not prevent users from using OC,
718
					// so log the exception
719
					\OC::$server->getLogger()->warning('Exception when running cache gc: ' . $e->getMessage(), ['app' => 'core']);
720
				}
721
			});
722
		}
723
	}
724
725
	private static function registerEncryptionWrapper() {
726
		$manager = self::$server->getEncryptionManager();
727
		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
728
	}
729
730
	private static function registerEncryptionHooks() {
731
		$enabled = self::$server->getEncryptionManager()->isEnabled();
732
		if ($enabled) {
733
			\OCP\Util::connectHook('OCP\Share', 'post_shared', 'OC\Encryption\HookManager', 'postShared');
734
			\OCP\Util::connectHook('OCP\Share', 'post_unshare', 'OC\Encryption\HookManager', 'postUnshared');
735
			\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OC\Encryption\HookManager', 'postRename');
736
			\OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', 'OC\Encryption\HookManager', 'postRestore');
737
		}
738
	}
739
740
	/**
741
	 * register hooks for the cache
742
	 */
743
	public static function registerLogRotate() {
744
		$systemConfig = \OC::$server->getSystemConfig();
745
		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...
746
			//don't try to do this before we are properly setup
747
			//use custom logfile path if defined, otherwise use default of owncloud.log in data directory
748
			$jobList = \OC::$server->getJobList();
749
			$jobList->add('OC\Log\Rotate', $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/owncloud.log'));
750
		}
751
	}
752
753
	/**
754
	 * register hooks for the filesystem
755
	 */
756
	public static function registerFilesystemHooks() {
757
		// Check for blacklisted files
758
		OC_Hook::connect('OC_Filesystem', 'write', 'OC\Files\Filesystem', 'isForbiddenFileOrDir_Hook');
759
		OC_Hook::connect('OC_Filesystem', 'rename', 'OC\Files\Filesystem', 'isForbiddenFileOrDir_Hook');
760
	}
761
762
	/**
763
	 * register hooks for previews
764
	 */
765
	public static function registerPreviewHooks() {
766
		OC_Hook::connect('OC_Filesystem', 'post_write', 'OC\Preview', 'post_write');
767
		OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'prepare_delete_files');
768
		OC_Hook::connect('\OCP\Versions', 'preDelete', 'OC\Preview', 'prepare_delete');
769
		OC_Hook::connect('\OCP\Trashbin', 'preDelete', 'OC\Preview', 'prepare_delete');
770
		OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC\Preview', 'post_delete_files');
771
		OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete_versions');
772
		OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete');
773
		OC_Hook::connect('\OCP\Versions', 'rollback', 'OC\Preview', 'post_delete_versions');
774
	}
775
776
	/**
777
	 * register hooks for sharing
778
	 */
779
	public static function registerShareHooks() {
780
		if (\OC::$server->getSystemConfig()->getValue('installed')) {
781
			OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share20\Hooks', 'post_deleteUser');
782
			OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share20\Hooks', 'post_removeFromGroup');
783
			OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share20\Hooks', 'post_deleteGroup');
784
		}
785
	}
786
787
	protected static function registerAutoloaderCache() {
788
		// The class loader takes an optional low-latency cache, which MUST be
789
		// namespaced. The instanceid is used for namespacing, but might be
790
		// unavailable at this point. Furthermore, it might not be possible to
791
		// generate an instanceid via \OC_Util::getInstanceId() because the
792
		// config file may not be writable. As such, we only register a class
793
		// loader cache if instanceid is available without trying to create one.
794
		$instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
795
		if ($instanceId) {
796
			try {
797
				$memcacheFactory = \OC::$server->getMemCacheFactory();
798
				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...
799
			} catch (\Exception $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
800
			}
801
		}
802
	}
803
804
	/**
805
	 * Handle the request
806
	 */
807
	public static function handleRequest() {
808
		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
809
		$systemConfig = \OC::$server->getSystemConfig();
810
		// load all the classpaths from the enabled apps so they are available
811
		// in the routing files of each app
812
		OC::loadAppClassPaths();
813
814
		// Check if ownCloud is installed or in maintenance (update) mode
815
		if (!$systemConfig->getValue('installed', false)) {
816
			\OC::$server->getSession()->clear();
817
			$setupHelper = new OC\Setup(\OC::$server->getConfig(), \OC::$server->getIniWrapper(),
818
				\OC::$server->getL10N('lib'), new \OC_Defaults(), \OC::$server->getLogger(),
819
				\OC::$server->getSecureRandom());
820
821
			$controller = new OC\Core\Controller\SetupController($setupHelper);
822
			$controller->run($_POST);
823
			exit();
824
		}
825
826
		$request = \OC::$server->getRequest();
827
		// Check if requested URL matches 'index.php/occ'
828
		$isOccControllerRequested = \preg_match('|/index\.php$|', $request->getScriptName()) === 1
829
			&& \strpos($request->getPathInfo(), '/occ/') === 0;
830
831
		$needUpgrade = false;
832
		$requestPath = $request->getRawPathInfo();
833
		if (\substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
834
			self::checkMaintenanceMode($request);
835
			$needUpgrade = self::checkUpgrade(!$isOccControllerRequested);
836
		}
837
838
		// emergency app disabling
839
		if ($requestPath === '/disableapp'
840
			&& $request->getMethod() === 'POST'
841
			&& ((string)$request->getParam('appid')) !== ''
842
		) {
843
			\OCP\JSON::callCheck();
844
			\OCP\JSON::checkAdminUser();
845
			$appId = (string)$request->getParam('appid');
846
			$appId = \OC_App::cleanAppId($appId);
847
848
			\OC_App::disable($appId);
849
			\OC_JSON::success();
850
			exit();
851
		}
852
853
		try {
854
			// Always load authentication apps
855
			OC_App::loadApps(['authentication']);
856
		} catch (\OC\NeedsUpdateException $e) {
857
			if ($isOccControllerRequested && $needUpgrade) {
858
				OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
859
				return;
860
			}
861
			throw $e;
862
		}
863
864
		// Load minimum set of apps
865
		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...
866
			&& !$systemConfig->getValue('maintenance', false)) {
867
			// For logged-in users: Load everything
868
			$userSession = \OC::$server->getUserSession();
869
			if ($userSession->isLoggedIn() && $userSession->verifyAuthHeaders($request)) {
870
				OC_App::loadApps();
871
			} else {
872
				// For guests: Load only filesystem and logging
873
				OC_App::loadApps(['filesystem', 'logging']);
874
			}
875
		}
876
877
		if (!self::$CLI) {
878
			try {
879
				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...
880
					OC_App::loadApps(['filesystem', 'logging']);
881
					OC_App::loadApps();
882
				}
883
				self::checkSingleUserMode();
884
				OC_Util::setupFS();
885
				OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
886
				return;
887
			} catch (\OC\NeedsUpdateException $e) {
888
				if ($isOccControllerRequested && $needUpgrade) {
889
					OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
890
					return;
891
				}
892
				throw $e;
893
			} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
894
				//header('HTTP/1.0 404 Not Found');
895
				$dispatcher = \OC::$server->getEventDispatcher();
896
				$dispatcher->dispatch(\OCP\Http\HttpEvents::EVENT_404, new OCP\Http\HttpEvents(
897
					\OCP\Http\HttpEvents::EVENT_404,
898
					OC::$server->getRequest()
899
				));
900
			} catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
901
				OC_Response::setStatus(405);
902
				return;
903
			}
904
		}
905
906
		// Handle WebDAV
907
		if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
908
			// not allowed any more to prevent people
909
			// mounting this root directly.
910
			// Users need to mount remote.php/webdav instead.
911
			\header('HTTP/1.1 405 Method Not Allowed');
912
			\header('Status: 405 Method Not Allowed');
913
			return;
914
		}
915
916
		// Someone is logged in
917
		if ($userSession->isLoggedIn() && $userSession->verifyAuthHeaders($request)) {
0 ignored issues
show
Bug introduced by
The variable $userSession does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
918
			OC_App::loadApps();
919
			OC_User::setupBackends();
920
			OC_Util::setupFS();
921
			// FIXME
922
			// Redirect to default application
923
			OC_Util::redirectToDefaultPage();
924
		} else {
925
			// Not handled and not logged in
926
			\header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
927
		}
928
	}
929
930
	/**
931
	 * Check login: apache auth, auth token, basic auth
932
	 *
933
	 * @param OCP\IRequest $request
934
	 * @return boolean
935
	 */
936
	public static function handleLogin(OCP\IRequest $request) {
937
		$userSession = self::$server->getUserSession();
938
		if (OC_User::handleApacheAuth()) {
939
			return true;
940
		}
941
		if ($userSession->tryTokenLogin($request)) {
942
			return true;
943
		}
944
		if ($userSession->tryAuthModuleLogin($request)) {
945
			return true;
946
		}
947
		if ($userSession->tryBasicAuthLogin($request)) {
948
			return true;
949
		}
950
		return false;
951
	}
952
953
	protected static function handleAuthHeaders() {
954
		//copy http auth headers for apache+php-fcgid work around
955
		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
956
			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
957
		}
958
959
		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
960
		$vars = [
961
			'HTTP_AUTHORIZATION', // apache+php-cgi work around
962
			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
963
		];
964
		foreach ($vars as $var) {
965
			if (isset($_SERVER[$var]) && \preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
966
				list($name, $password) = \explode(':', \base64_decode($matches[1]), 2);
967
				$_SERVER['PHP_AUTH_USER'] = $name;
968
				$_SERVER['PHP_AUTH_PW'] = $password;
969
				break;
970
			}
971
		}
972
	}
973
}
974
975
OC::init();
976