Completed
Push — master ( e8cbe7...f3c40f )
by Victor
21:02 queued 11:32
created

OC::init()   F

Complexity

Conditions 26
Paths 4776

Size

Total Lines 242
Code Lines 145

Duplication

Lines 3
Ratio 1.24 %

Importance

Changes 0
Metric Value
cc 26
eloc 145
nc 4776
nop 0
dl 3
loc 242
rs 2
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) 2017, 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 OCP\IRequest;
58
59
require_once 'public/Constants.php';
60
61
/**
62
 * Class that is a namespace for all global OC variables
63
 * No, we can not put this class in its own file because it is used by
64
 * OC_autoload!
65
 */
66
class OC {
67
	/**
68
	 * Associative array for autoloading. classname => filename
69
	 */
70
	public static $CLASSPATH = [];
71
	/**
72
	 * The installation path for owncloud on the server (e.g. /srv/http/owncloud)
73
	 */
74
	public static $SERVERROOT = '';
75
	/**
76
	 * the current request path relative to the owncloud root (e.g. files/index.php)
77
	 */
78
	private static $SUBURI = '';
79
	/**
80
	 * the owncloud root path for http requests (e.g. owncloud/)
81
	 */
82
	public static $WEBROOT = '';
83
	/**
84
	 * The installation path array of the apps folder on the server (e.g. /srv/http/owncloud) 'path' and
85
	 * web path in 'url'
86
	 */
87
	public static $APPSROOTS = [];
88
89
	/**
90
	 * @var string
91
	 */
92
	public static $configDir;
93
94
	/**
95
	 * requested app
96
	 */
97
	public static $REQUESTEDAPP = '';
98
99
	/**
100
	 * check if ownCloud runs in cli mode
101
	 */
102
	public static $CLI = false;
103
104
	/**
105
	 * @var \OC\Autoloader $loader
106
	 */
107
	public static $loader = null;
108
109
	/** @var \Composer\Autoload\ClassLoader $composerAutoloader */
110
	public static $composerAutoloader = null;
111
112
	/**
113
	 * @var \OC\Server
114
	 */
115
	public static $server = null;
116
117
	/**
118
	 * @var \OC\Config
119
	 */
120
	private static $config = null;
121
122
	/**
123
	 * @throws \RuntimeException when the 3rdparty directory is missing or
124
	 * the app path list is empty or contains an invalid path
125
	 */
126
	public static function initPaths() {
127
		if(defined('PHPUNIT_CONFIG_DIR')) {
128
			self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/';
129
		} elseif(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) {
130
			self::$configDir = OC::$SERVERROOT . '/tests/config/';
131
		} elseif($dir = getenv('OWNCLOUD_CONFIG_DIR')) {
132
			self::$configDir = rtrim($dir, '/') . '/';
133
		} else {
134
			self::$configDir = OC::$SERVERROOT . '/config/';
135
		}
136
		self::$config = new \OC\Config(self::$configDir);
137
138
		OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
139
		/**
140
		 * FIXME: The following lines are required because we can't yet instantiiate
141
		 *        \OC::$server->getRequest() since \OC::$server does not yet exist.
142
		 */
143
		$params = [
144
			'server' => [
145
				'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'],
146
				'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'],
147
			],
148
		];
149
		$fakeRequest = new \OC\AppFramework\Http\Request($params, null, new \OC\AllConfig(new \OC\SystemConfig(self::$config)));
150
		$scriptName = $fakeRequest->getScriptName();
151
		if (substr($scriptName, -1) == '/') {
152
			$scriptName .= 'index.php';
153
			//make sure suburi follows the same rules as scriptName
154
			if (substr(OC::$SUBURI, -9) != 'index.php') {
155
				if (substr(OC::$SUBURI, -1) != '/') {
156
					OC::$SUBURI = OC::$SUBURI . '/';
157
				}
158
				OC::$SUBURI = OC::$SUBURI . 'index.php';
159
			}
160
		}
161
162
163
		if (OC::$CLI) {
164
			OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
165
		} else {
166
			if (substr($scriptName, 0 - strlen(OC::$SUBURI)) === OC::$SUBURI) {
167
				OC::$WEBROOT = substr($scriptName, 0, 0 - strlen(OC::$SUBURI));
168
169
				if (OC::$WEBROOT != '' && OC::$WEBROOT[0] !== '/') {
170
					OC::$WEBROOT = '/' . OC::$WEBROOT;
171
				}
172
			} else {
173
				// The scriptName is not ending with OC::$SUBURI
174
				// This most likely means that we are calling from CLI.
175
				// However some cron jobs still need to generate
176
				// a web URL, so we use overwritewebroot as a fallback.
177
				OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
178
			}
179
180
			// Resolve /owncloud to /owncloud/ to ensure to always have a trailing
181
			// slash which is required by URL generation.
182
			if($_SERVER['REQUEST_URI'] === \OC::$WEBROOT &&
183
					substr($_SERVER['REQUEST_URI'], -1) !== '/') {
184
				header('Location: '.\OC::$WEBROOT.'/');
185
				exit();
186
			}
187
		}
188
189
		// search the apps folder
190
		$config_paths = self::$config->getValue('apps_paths', []);
191
		if (!empty($config_paths)) {
192
			foreach ($config_paths as $paths) {
193
				if (isset($paths['url']) && isset($paths['path'])) {
194
					$paths['url'] = rtrim($paths['url'], '/');
195
					$paths['path'] = rtrim($paths['path'], '/');
196
					OC::$APPSROOTS[] = $paths;
197
				}
198
			}
199
		} elseif (file_exists(OC::$SERVERROOT . '/apps')) {
200
			OC::$APPSROOTS[] = ['path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true];
201
		} elseif (file_exists(OC::$SERVERROOT . '/../apps')) {
202
			OC::$APPSROOTS[] = [
203
				'path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps',
204
				'url' => '/apps',
205
				'writable' => true
206
			];
207
		}
208
209
		if (empty(OC::$APPSROOTS)) {
210
			throw new \RuntimeException('apps directory not found! Please put the ownCloud apps folder in the ownCloud folder'
211
				. ' or the folder above. You can also configure the location in the config.php file.');
212
		}
213
		$paths = [];
214
		foreach (OC::$APPSROOTS as $path) {
215
			$paths[] = $path['path'];
216
			if (!is_dir($path['path'])) {
217
				throw new \RuntimeException(sprintf('App directory "%s" not found! Please put the ownCloud apps folder in the'
218
					. ' ownCloud folder or the folder above. You can also configure the location in the'
219
					. ' config.php file.', $path['path']));
220
			}
221
		}
222
223
		// set the right include path
224
		set_include_path(
225
			implode(PATH_SEPARATOR, $paths)
226
		);
227
	}
228
229
	public static function checkConfig() {
230
		$l = \OC::$server->getL10N('lib');
231
232
		// Create config if it does not already exist
233
		$configFilePath = self::$configDir .'/config.php';
234
		if(!file_exists($configFilePath)) {
235
			@touch($configFilePath);
236
		}
237
238
		// Check if config is writable
239
		$configFileWritable = is_writable($configFilePath);
240
		if (!$configFileWritable && !\OC::$server->getConfig()->isSystemConfigReadOnly()
241
			|| !$configFileWritable && self::checkUpgrade(false)) {
242
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
		// prevents javascript from accessing php session cookies
412
		ini_set('session.cookie_httponly', true);
413
414
		// set the cookie path to the ownCloud 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', ['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);
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 ownCloud 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);
484
	}
485
486
	public static function init() {
487
		// calculate the root directories
488
		OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
489
490
		// register autoloader
491
		$loaderStart = microtime(true);
492
		require_once __DIR__ . '/autoloader.php';
493
		self::$loader = new \OC\Autoloader([
494
			OC::$SERVERROOT . '/lib/private/legacy',
495
		]);
496
		if (defined('PHPUNIT_RUN')) {
497
			self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
498
		}
499
		spl_autoload_register([self::$loader, 'load']);
500
		$loaderEnd = microtime(true);
501
502
		self::$CLI = (in_array(php_sapi_name(), ['cli', 'phpdbg']));
503
504
		// setup 3rdparty autoloader
505
		$vendorAutoLoad = OC::$SERVERROOT . '/lib/composer/autoload.php';
506
		if (!file_exists($vendorAutoLoad)) {
507
			printf('Composer autoloader not found, unable to continue. Please run "make".');
508
			exit();
509
		}
510
511
		// Add default composer PSR-4 autoloader
512
		self::$composerAutoloader = require $vendorAutoLoad;
513
		if (!self::$composerAutoloader) {
514
			print('Composer autoloader not found!');
515
			exit();
516
		}
517
518
		try {
519
			self::initPaths();
520
		} catch (\RuntimeException $e) {
521
			if (!self::$CLI) {
522
				// can`t use OC_Response::setStatus because server is not
523
				// initialized here
524
				http_response_code(OC_Response::STATUS_SERVICE_UNAVAILABLE);
525
			}
526
			// we can't use the template error page here, because this needs the
527
			// DI container which isn't available yet
528
			print($e->getMessage());
529
			exit();
530
		}
531
532
		// setup the basic server
533
		self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
534
		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
535
		\OC::$server->getEventLogger()->start('boot', 'Initialize');
536
537
		// Don't display errors and log them
538
		error_reporting(E_ALL | E_STRICT);
539
		@ini_set('display_errors', 0);
540
		@ini_set('log_errors', 1);
541
542
		if(!date_default_timezone_set('UTC')) {
543
			\OC::$server->getLogger()->error('Could not set timezone to UTC');
544
		};
545
546
		//try to configure php to enable big file uploads.
547
		//this doesn´t work always depending on the webserver and php configuration.
548
		//Let´s try to overwrite some defaults anyway
549
550
		//try to set the maximum execution time to 60min
551
		@set_time_limit(3600);
552
		@ini_set('max_execution_time', 3600);
553
		@ini_set('max_input_time', 3600);
554
555
		//try to set the maximum filesize to 10G
556
		@ini_set('upload_max_filesize', '10G');
557
		@ini_set('post_max_size', '10G');
558
		@ini_set('file_uploads', '50');
559
560
		self::setRequiredIniValues();
561
		self::handleAuthHeaders();
562
		self::registerAutoloaderCache();
563
564
		// initialize intl fallback is necessary
565
		\Patchwork\Utf8\Bootup::initIntl();
566
		OC_Util::isSetLocaleWorking();
567
568
		if (!defined('PHPUNIT_RUN')) {
569
			OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
570
			$debug = \OC::$server->getConfig()->getSystemValue('debug', false);
571
			OC\Log\ErrorHandler::register($debug);
572
		}
573
574
		// register the stream wrappers
575
		stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir');
576
		stream_wrapper_register('static', 'OC\Files\Stream\StaticStream');
577
		stream_wrapper_register('close', 'OC\Files\Stream\Close');
578
		stream_wrapper_register('quota', 'OC\Files\Stream\Quota');
579
580
		\OC::$server->getEventLogger()->start('init_session', 'Initialize session');
581
		OC_App::loadApps(['session']);
582
		if (!self::$CLI) {
583
			\OC_App::loadApps(['theme']);
584
			self::initSession();
585
		}
586
587
		\OC::$server->getEventLogger()->end('init_session');
588
589
		// incognito mode for now
590
		$uid = \OC::$server->getSession()->get('user_id');
591
		\OC::$server->getSession()->set('user_id', null);
592
593
		self::checkConfig();
594
		self::checkInstalled();
595
596
		OC_Response::addSecurityHeaders();
597
		if(self::$server->getRequest()->getServerProtocol() === 'https') {
598
			ini_set('session.cookie_secure', true);
599
		}
600
601
		if (!defined('OC_CONSOLE')) {
602
			$errors = OC_Util::checkServer(\OC::$server->getConfig());
603
			if (count($errors) > 0) {
604
				if (self::$CLI) {
605
					// Convert l10n string into regular string for usage in database
606
					$staticErrors = [];
607
					foreach ($errors as $error) {
608
						echo $error['error'] . "\n";
609
						echo $error['hint'] . "\n\n";
610
						$staticErrors[] = [
611
							'error' => (string)$error['error'],
612
							'hint' => (string)$error['hint'],
613
						];
614
					}
615
616
					try {
617
						\OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
618
					} catch (\Exception $e) {
619
						echo('Writing to database failed');
620
					}
621
					exit(1);
622
				} else {
623
					OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
624
					OC_Template::printGuestPage('', 'error', ['errors' => $errors]);
625
					exit;
626
				}
627 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...
628
				\OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
629
			}
630
		}
631
632
		// set back user
633
		\OC::$server->getSession()->set('user_id', $uid);
634
635
		//try to set the session lifetime
636
		$sessionLifeTime = self::getSessionLifeTime();
637
		@ini_set('gc_maxlifetime', (string)$sessionLifeTime);
638
639
		$systemConfig = \OC::$server->getSystemConfig();
640
641
		// User and Groups
642
		if ($systemConfig->getValue("installed", false)) {
643
			OC_User::useBackend(new \OC\User\Database());
644
			\OC::$server->getGroupManager()->addBackend(new \OC\Group\Database());
645
		} else {
646
			self::$server->getSession()->set('user_id', '');
647
		}
648
649
		// Subscribe to the hook
650
		\OCP\Util::connectHook(
651
			'\OCA\Files_Sharing\API\Server2Server',
652
			'preLoginNameUsedAsUserName',
653
			'\OC\User\Database',
654
			'preLoginNameUsedAsUserName'
655
		);
656
657
		//setup extra user backends
658
		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...
659
			OC_User::setupBackends();
660
		} else {
661
			// Run upgrades in incognito mode
662
			OC_User::setIncognitoMode(true);
663
		}
664
665
		self::registerCacheHooks();
666
		self::registerFilesystemHooks();
667
		if ($systemConfig->getValue('enable_previews', true)) {
668
			self::registerPreviewHooks();
669
		}
670
		self::registerShareHooks();
671
		self::registerLogRotate();
672
		if ($systemConfig->getValue("installed", false)) {
673
			self::registerEncryptionWrapper();
674
			self::registerEncryptionHooks();
675
		}
676
677
		//make sure temporary files are cleaned up
678
		$tmpManager = \OC::$server->getTempManager();
679
		register_shutdown_function([$tmpManager, 'clean']);
680
		$lockProvider = \OC::$server->getLockingProvider();
681
		register_shutdown_function([$lockProvider, 'releaseAll']);
682
683
		// Check whether the sample configuration has been copied
684
		if($systemConfig->getValue('copied_sample_config', false)) {
685
			$l = \OC::$server->getL10N('lib');
686
			header('HTTP/1.1 503 Service Temporarily Unavailable');
687
			header('Status: 503 Service Temporarily Unavailable');
688
			OC_Template::printErrorPage(
689
				$l->t('Sample configuration detected'),
690
				$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')
691
			);
692
			return;
693
		}
694
695
		$request = \OC::$server->getRequest();
696
		$host = $request->getInsecureServerHost();
697
		/**
698
		 * if the host passed in headers isn't trusted
699
		 * FIXME: Should not be in here at all :see_no_evil:
700
		 */
701
		if (!OC::$CLI
702
			// overwritehost is always trusted, workaround to not have to make
703
			// \OC\AppFramework\Http\Request::getOverwriteHost public
704
			&& self::$server->getConfig()->getSystemValue('overwritehost') === ''
705
			&& !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host)
706
			&& self::$server->getConfig()->getSystemValue('installed', false)
707
		) {
708
			header('HTTP/1.1 400 Bad Request');
709
			header('Status: 400 Bad Request');
710
711
			\OC::$server->getLogger()->warning(
712
					'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
713
					[
714
						'app' => 'core',
715
						'remoteAddress' => $request->getRemoteAddress(),
716
						'host' => $host,
717
					]
718
			);
719
720
			$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
721
			$tmpl->assign('domain', $host);
722
			$tmpl->printPage();
723
724
			exit();
725
		}
726
		\OC::$server->getEventLogger()->end('boot');
727
	}
728
729
	/**
730
	 * register hooks for the cache
731
	 */
732
	public static function registerCacheHooks() {
733
		//don't try to do this before we are properly setup
734
		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...
735
736
			// NOTE: This will be replaced to use OCP
737
			$userSession = self::$server->getUserSession();
738
			$userSession->listen('\OC\User', 'postLogin', function () {
739
				try {
740
					$cache = new \OC\Cache\File();
741
					$cache->gc();
742
				} catch (\OC\ServerNotAvailableException $e) {
743
					// not a GC exception, pass it on
744
					throw $e;
745
				} catch (\Exception $e) {
746
					// a GC exception should not prevent users from using OC,
747
					// so log the exception
748
					\OC::$server->getLogger()->warning('Exception when running cache gc: ' . $e->getMessage(), ['app' => 'core']);
749
				}
750
			});
751
		}
752
	}
753
754
	private static function registerEncryptionWrapper() {
755
		$manager = self::$server->getEncryptionManager();
756
		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
757
	}
758
759
	private static function registerEncryptionHooks() {
760
		$enabled = self::$server->getEncryptionManager()->isEnabled();
761
		if ($enabled) {
762
			\OCP\Util::connectHook('OCP\Share', 'post_shared', 'OC\Encryption\HookManager', 'postShared');
763
			\OCP\Util::connectHook('OCP\Share', 'post_unshare', 'OC\Encryption\HookManager', 'postUnshared');
764
			\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OC\Encryption\HookManager', 'postRename');
765
			\OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', 'OC\Encryption\HookManager', 'postRestore');
766
		}
767
	}
768
769
	/**
770
	 * register hooks for the cache
771
	 */
772
	public static function registerLogRotate() {
773
		$systemConfig = \OC::$server->getSystemConfig();
774
		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...
775
			//don't try to do this before we are properly setup
776
			//use custom logfile path if defined, otherwise use default of owncloud.log in data directory
777
			\OCP\BackgroundJob::registerJob('OC\Log\Rotate', $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/owncloud.log'));
778
		}
779
	}
780
781
	/**
782
	 * register hooks for the filesystem
783
	 */
784
	public static function registerFilesystemHooks() {
785
		// Check for blacklisted files
786
		OC_Hook::connect('OC_Filesystem', 'write', 'OC\Files\Filesystem', 'isForbiddenFileOrDir_Hook');
787
		OC_Hook::connect('OC_Filesystem', 'rename', 'OC\Files\Filesystem', 'isForbiddenFileOrDir_Hook');
788
	}
789
790
	/**
791
	 * register hooks for previews
792
	 */
793
	public static function registerPreviewHooks() {
794
		OC_Hook::connect('OC_Filesystem', 'post_write', 'OC\Preview', 'post_write');
795
		OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'prepare_delete_files');
796
		OC_Hook::connect('\OCP\Versions', 'preDelete', 'OC\Preview', 'prepare_delete');
797
		OC_Hook::connect('\OCP\Trashbin', 'preDelete', 'OC\Preview', 'prepare_delete');
798
		OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC\Preview', 'post_delete_files');
799
		OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete_versions');
800
		OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete');
801
		OC_Hook::connect('\OCP\Versions', 'rollback', 'OC\Preview', 'post_delete_versions');
802
	}
803
804
	/**
805
	 * register hooks for sharing
806
	 */
807
	public static function registerShareHooks() {
808
		if (\OC::$server->getSystemConfig()->getValue('installed')) {
809
			OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share20\Hooks', 'post_deleteUser');
810
			OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share20\Hooks', 'post_removeFromGroup');
811
			OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share20\Hooks', 'post_deleteGroup');
812
		}
813
	}
814
815
	protected static function registerAutoloaderCache() {
816
		// The class loader takes an optional low-latency cache, which MUST be
817
		// namespaced. The instanceid is used for namespacing, but might be
818
		// unavailable at this point. Furthermore, it might not be possible to
819
		// generate an instanceid via \OC_Util::getInstanceId() because the
820
		// config file may not be writable. As such, we only register a class
821
		// loader cache if instanceid is available without trying to create one.
822
		$instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
823
		if ($instanceId) {
824
			try {
825
				$memcacheFactory = \OC::$server->getMemCacheFactory();
826
				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...
827
			} catch (\Exception $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
828
			}
829
		}
830
	}
831
832
	/**
833
	 * Handle the request
834
	 */
835
	public static function handleRequest() {
836
837
		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
838
		$systemConfig = \OC::$server->getSystemConfig();
839
		// load all the classpaths from the enabled apps so they are available
840
		// in the routing files of each app
841
		OC::loadAppClassPaths();
842
843
		// Check if ownCloud is installed or in maintenance (update) mode
844
		if (!$systemConfig->getValue('installed', false)) {
845
			\OC::$server->getSession()->clear();
846
			$setupHelper = new OC\Setup(\OC::$server->getConfig(), \OC::$server->getIniWrapper(),
847
				\OC::$server->getL10N('lib'), new \OC_Defaults(), \OC::$server->getLogger(),
848
				\OC::$server->getSecureRandom());
849
850
			$controller = new OC\Core\Controller\SetupController($setupHelper);
851
			$controller->run($_POST);
852
			exit();
853
		}
854
855
		$request = \OC::$server->getRequest();
856
		// Check if requested URL matches 'index.php/occ'
857
		$isOccControllerRequested = preg_match('|/index\.php$|', $request->getScriptName()) === 1
858
			&& strpos($request->getPathInfo(), '/occ/') === 0;
859
860
		$needUpgrade = false;
861
		$requestPath = $request->getRawPathInfo();
862
		if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
863
			self::checkMaintenanceMode($request);
864
			$needUpgrade = self::checkUpgrade(!$isOccControllerRequested);
865
		}
866
867
		// emergency app disabling
868
		if ($requestPath === '/disableapp'
869
			&& $request->getMethod() === 'POST'
870
			&& ((string)$request->getParam('appid')) !== ''
871
		) {
872
			\OCP\JSON::callCheck();
873
			\OCP\JSON::checkAdminUser();
874
			$appId = (string)$request->getParam('appid');
875
			$appId = \OC_App::cleanAppId($appId);
876
877
			\OC_App::disable($appId);
878
			\OC_JSON::success();
879
			exit();
880
		}
881
882
		try {
883
			// Always load authentication apps
884
			OC_App::loadApps(['authentication']);
885
		} catch (\OC\NeedsUpdateException $e) {
886
			if ($isOccControllerRequested && $needUpgrade){
887
				OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
888
				return;
889
			}
890
			throw $e;
891
		}
892
893
		// Load minimum set of apps
894
		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...
895
			&& !$systemConfig->getValue('maintenance', false)) {
896
			// For logged-in users: Load everything
897
			$userSession = \OC::$server->getUserSession();
898
			if($userSession->isLoggedIn() && $userSession->verifyAuthHeaders($request)) {
899
				OC_App::loadApps();
900
			} else {
901
				// For guests: Load only filesystem and logging
902
				OC_App::loadApps(['filesystem', 'logging']);
903
				self::handleLogin($request);
904
			}
905
		}
906
907
		if (!self::$CLI) {
908
			try {
909
				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...
910
					OC_App::loadApps(['filesystem', 'logging']);
911
					OC_App::loadApps();
912
				}
913
				self::checkSingleUserMode();
914
				OC_Util::setupFS();
915
				OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
916
				return;
917
			} catch (\OC\NeedsUpdateException $e) {
918
				if ($isOccControllerRequested && $needUpgrade){
919
					OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
920
					return;
921
				}
922
				throw $e;
923
			} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
924
				//header('HTTP/1.0 404 Not Found');
925
				$dispatcher = \OC::$server->getEventDispatcher();
926
				$dispatcher->dispatch(\OCP\Http\HttpEvents::EVENT_404, new OCP\Http\HttpEvents(
927
					\OCP\Http\HttpEvents::EVENT_404,
928
					OC::$server->getRequest()
929
				));
930
			} catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
931
				OC_Response::setStatus(405);
932
				return;
933
			}
934
		}
935
936
		// Handle WebDAV
937
		if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
938
			// not allowed any more to prevent people
939
			// mounting this root directly.
940
			// Users need to mount remote.php/webdav instead.
941
			header('HTTP/1.1 405 Method Not Allowed');
942
			header('Status: 405 Method Not Allowed');
943
			return;
944
		}
945
946
		// Someone is logged in
947
		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...
948
			OC_App::loadApps();
949
			OC_User::setupBackends();
950
			OC_Util::setupFS();
951
			// FIXME
952
			// Redirect to default application
953
			OC_Util::redirectToDefaultPage();
954
		} else {
955
			// Not handled and not logged in
956
			header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
957
		}
958
	}
959
960
	/**
961
	 * Check login: apache auth, auth token, basic auth
962
	 *
963
	 * @param OCP\IRequest $request
964
	 * @return boolean
965
	 */
966
	static function handleLogin(OCP\IRequest $request) {
967
		$userSession = self::$server->getUserSession();
968
		if (OC_User::handleApacheAuth()) {
969
			return true;
970
		}
971
		if ($userSession->tryTokenLogin($request)) {
972
			return true;
973
		}
974
		if ($userSession->tryAuthModuleLogin($request)) {
975
			return true;
976
		}
977
		if ($userSession->tryBasicAuthLogin($request)) {
978
			return true;
979
		}
980
		return false;
981
	}
982
983
	protected static function handleAuthHeaders() {
984
		//copy http auth headers for apache+php-fcgid work around
985
		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
986
			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
987
		}
988
989
		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
990
		$vars = [
991
			'HTTP_AUTHORIZATION', // apache+php-cgi work around
992
			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
993
		];
994
		foreach ($vars as $var) {
995
			if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
996
				list($name, $password) = explode(':', base64_decode($matches[1]), 2);
997
				$_SERVER['PHP_AUTH_USER'] = $name;
998
				$_SERVER['PHP_AUTH_PW'] = $password;
999
				break;
1000
			}
1001
		}
1002
	}
1003
}
1004
1005
OC::init();
1006