OC   F
last analyzed

Complexity

Total Complexity 147

Size/Duplication

Total Lines 929
Duplicated Lines 1.51 %

Coupling/Cohesion

Components 1
Dependencies 49

Importance

Changes 0
Metric Value
dl 14
loc 929
rs 1.671
c 0
b 0
f 0
wmc 147
lcom 1
cbo 49

23 Methods

Rating   Name   Duplication   Size   Complexity  
F initPaths() 0 102 22
B checkConfig() 0 31 7
A checkInstalled() 0 15 5
A checkMaintenanceMode() 0 22 5
A checkSingleUserMode() 0 25 5
A checkUpgrade() 0 12 4
B printUpgradePage() 0 57 6
B initSession() 0 39 7
A getSessionLifeTime() 0 3 1
A loadAppClassPaths() 11 13 4
A setRequiredIniValues() 0 4 1
F init() 3 238 25
A registerCacheHooks() 0 21 5
A registerEncryptionWrapper() 0 4 1
A registerEncryptionHooks() 0 9 2
A registerLogRotate() 0 9 4
A registerFilesystemHooks() 0 5 1
A registerPreviewHooks() 0 10 1
A registerShareHooks() 0 7 2
A registerAutoloaderCache() 0 16 3
F handleRequest() 0 122 25
A handleLogin() 0 16 5
B handleAuthHeaders() 0 20 6

How to fix   Duplicated Code    Complexity   

Duplicated Code

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

Common duplication problems, and corresponding solutions are:

Complex Class

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

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

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

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

1
<?php
2
/**
3
 * @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
	private 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
	 * Try to set some values to the required ownCloud default
473
	 */
474
	public static function setRequiredIniValues() {
475
		@\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...
476
		@\ini_set('gd.jpeg_ignore_warning', 1);
477
	}
478
479
	/**
480
	 * @throws \OCP\AppFramework\QueryException
481
	 * @codeCoverageIgnore
482
	 */
483
	public static function init() {
484
		// calculate the root directories
485
		OC::$SERVERROOT = \str_replace("\\", '/', \substr(__DIR__, 0, -4));
486
487
		// register autoloader
488
		$loaderStart = \microtime(true);
489
		self::$CLI = (\in_array(\php_sapi_name(), ['cli', 'phpdbg']));
490
491
		// setup 3rdparty autoloader
492
		$vendorAutoLoad = OC::$SERVERROOT . '/lib/composer/autoload.php';
493
		if (!\file_exists($vendorAutoLoad)) {
494
			\printf('Composer autoloader not found, unable to continue. Please run "make".');
495
			exit();
496
		}
497
498
		// Add default composer PSR-4 autoloader
499
		self::$composerAutoloader = require $vendorAutoLoad;
500
		if (!self::$composerAutoloader) {
501
			print('Composer autoloader not found!');
502
			exit();
503
		}
504
		self::$loader = new Autoloader();
505
		if (\defined('PHPUNIT_RUN')) {
506
			self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
507
		}
508
		\spl_autoload_register([self::$loader, 'load']);
509
		$loaderEnd = \microtime(true);
510
511
		try {
512
			self::initPaths();
513
		} catch (\RuntimeException $e) {
514
			if (!self::$CLI) {
515
				// can`t use OC_Response::setStatus because server is not
516
				// initialized here
517
				\http_response_code(OC_Response::STATUS_SERVICE_UNAVAILABLE);
518
			}
519
			// we can't use the template error page here, because this needs the
520
			// DI container which isn't available yet
521
			print($e->getMessage());
522
			exit();
523
		}
524
525
		// setup the basic server
526
		self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
527
		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
528
		\OC::$server->getEventLogger()->start('boot', 'Initialize');
529
530
		// Don't display errors and log them
531
		\error_reporting(E_ALL | E_STRICT);
532
		@\ini_set('display_errors', 0);
533
		@\ini_set('log_errors', 1);
534
535
		if (!\date_default_timezone_set('UTC')) {
536
			\OC::$server->getLogger()->error('Could not set timezone to UTC');
537
		};
538
539
		//try to configure php to enable big file uploads.
540
		//this doesn´t work always depending on the webserver and php configuration.
541
		//Let´s try to overwrite some defaults anyway
542
543
		//try to set the maximum execution time to 60min
544
		@\set_time_limit(3600);
545
		@\ini_set('max_execution_time', 3600);
546
		@\ini_set('max_input_time', 3600);
547
548
		//try to set the maximum filesize to 10G
549
		@\ini_set('upload_max_filesize', '10G');
550
		@\ini_set('post_max_size', '10G');
551
		@\ini_set('file_uploads', '50');
552
553
		self::setRequiredIniValues();
554
		self::handleAuthHeaders();
555
		self::registerAutoloaderCache();
556
557
		// initialize intl fallback is necessary
558
		\Patchwork\Utf8\Bootup::initIntl();
559
		OC_Util::isSetLocaleWorking();
560
561
		if (!\defined('PHPUNIT_RUN')) {
562
			OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
563
			$debug = \OC::$server->getConfig()->getSystemValue('debug', false);
564
			OC\Log\ErrorHandler::register($debug);
565
		}
566
567
		// register the stream wrappers
568
		\stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir');
569
		\stream_wrapper_register('static', 'OC\Files\Stream\StaticStream');
570
		\stream_wrapper_register('close', 'OC\Files\Stream\Close');
571
		\stream_wrapper_register('quota', 'OC\Files\Stream\Quota');
572
573
		\OC::$server->getEventLogger()->start('init_session', 'Initialize session');
574
		OC_App::loadApps(['session', 'theme']);
575
		if (!self::$CLI) {
576
			self::initSession();
577
		}
578
579
		\OC::$server->getEventLogger()->end('init_session');
580
581
		// incognito mode for now
582
		$uid = \OC::$server->getSession()->get('user_id');
583
		\OC::$server->getSession()->set('user_id', null);
584
585
		self::checkConfig();
586
		self::checkInstalled();
587
588
		OC_Response::addSecurityHeaders();
589
590
		if (!\defined('OC_CONSOLE')) {
591
			$errors = OC_Util::checkServer(\OC::$server->getConfig());
592
			if (\count($errors) > 0) {
593
				if (self::$CLI) {
594
					// Convert l10n string into regular string for usage in database
595
					$staticErrors = [];
596
					foreach ($errors as $error) {
597
						echo $error['error'] . "\n";
598
						echo $error['hint'] . "\n\n";
599
						$staticErrors[] = [
600
							'error' => (string)$error['error'],
601
							'hint' => (string)$error['hint'],
602
						];
603
					}
604
605
					try {
606
						\OC::$server->getConfig()->setAppValue('core', 'cronErrors', \json_encode($staticErrors));
607
					} catch (\Exception $e) {
608
						echo('Writing to database failed');
609
					}
610
					exit(1);
611
				} else {
612
					OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
613
					OC_Template::printGuestPage('', 'error', ['errors' => $errors]);
614
					exit;
615
				}
616 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...
617
				\OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
618
			}
619
		}
620
621
		// set back user
622
		\OC::$server->getSession()->set('user_id', $uid);
623
624
		//try to set the session lifetime
625
		$sessionLifeTime = self::getSessionLifeTime();
626
		@\ini_set('gc_maxlifetime', (string)$sessionLifeTime);
627
628
		$systemConfig = \OC::$server->getSystemConfig();
629
630
		// User and Groups
631
		if ($systemConfig->getValue("installed", false)) {
632
			OC_User::useBackend(new \OC\User\Database());
633
			\OC::$server->getGroupManager()->addBackend(new \OC\Group\Database());
634
		} else {
635
			self::$server->getSession()->set('user_id', '');
636
		}
637
638
		// Subscribe to the hook
639
		\OCP\Util::connectHook(
640
			'\OCA\Files_Sharing\API\Server2Server',
641
			'preLoginNameUsedAsUserName',
642
			'\OC\User\Database',
643
			'preLoginNameUsedAsUserName'
644
		);
645
646
		//setup extra user backends
647
		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...
648
			OC_User::setupBackends();
649
		} else {
650
			// Run upgrades in incognito mode
651
			OC_User::setIncognitoMode(true);
652
		}
653
654
		self::registerCacheHooks();
655
		self::registerFilesystemHooks();
656
		if ($systemConfig->getValue('enable_previews', true)) {
657
			self::registerPreviewHooks();
658
		}
659
		self::registerShareHooks();
660
		self::registerLogRotate();
661
		if ($systemConfig->getValue("installed", false)) {
662
			self::registerEncryptionWrapper();
663
			self::registerEncryptionHooks();
664
		}
665
666
		//make sure temporary files are cleaned up
667
		\OC::$server->getShutdownHandler()->register(function () {
668
			$tmpManager = \OC::$server->getTempManager();
669
			$tmpManager->clean();
670
		});
671
		\OC::$server->getShutdownHandler()->register(function () {
672
			$lockProvider = \OC::$server->getLockingProvider();
673
			$lockProvider->releaseAll();
674
		});
675
676
		// Check whether the sample configuration has been copied
677
		if ($systemConfig->getValue('copied_sample_config', false)) {
678
			$l = \OC::$server->getL10N('lib');
679
			\header('HTTP/1.1 503 Service Temporarily Unavailable');
680
			\header('Status: 503 Service Temporarily Unavailable');
681
			OC_Template::printErrorPage(
682
				$l->t('Sample configuration detected'),
683
				$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')
684
			);
685
			return;
686
		}
687
688
		$request = \OC::$server->getRequest();
689
		$host = $request->getInsecureServerHost();
690
		/**
691
		 * if the host passed in headers isn't trusted
692
		 * FIXME: Should not be in here at all :see_no_evil:
693
		 */
694
		if (!OC::$CLI
695
			// overwritehost is always trusted, workaround to not have to make
696
			// \OC\AppFramework\Http\Request::getOverwriteHost public
697
			&& self::$server->getConfig()->getSystemValue('overwritehost') === ''
698
			&& !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host)
699
			&& self::$server->getConfig()->getSystemValue('installed', false)
700
		) {
701
			\header('HTTP/1.1 400 Bad Request');
702
			\header('Status: 400 Bad Request');
703
704
			\OC::$server->getLogger()->warning(
705
					'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
706
					[
707
						'app' => 'core',
708
						'remoteAddress' => $request->getRemoteAddress(),
709
						'host' => $host,
710
					]
711
			);
712
713
			$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
714
			$tmpl->assign('domain', $host);
715
			$tmpl->printPage();
716
717
			exit();
718
		}
719
		\OC::$server->getEventLogger()->end('boot');
720
	}
721
722
	/**
723
	 * register hooks for the cache
724
	 */
725
	public static function registerCacheHooks() {
726
		//don't try to do this before we are properly setup
727
		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...
728
729
			// NOTE: This will be replaced to use OCP
730
			$userSession = self::$server->getUserSession();
731
			$userSession->listen('\OC\User', 'postLogin', function () {
732
				try {
733
					$cache = new \OC\Cache\File();
734
					$cache->gc();
735
				} catch (\OC\ServerNotAvailableException $e) {
736
					// not a GC exception, pass it on
737
					throw $e;
738
				} catch (\Exception $e) {
739
					// a GC exception should not prevent users from using OC,
740
					// so log the exception
741
					\OC::$server->getLogger()->warning('Exception when running cache gc: ' . $e->getMessage(), ['app' => 'core']);
742
				}
743
			});
744
		}
745
	}
746
747
	private static function registerEncryptionWrapper() {
748
		$manager = self::$server->getEncryptionManager();
749
		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
750
	}
751
752
	private static function registerEncryptionHooks() {
753
		$enabled = self::$server->getEncryptionManager()->isEnabled();
754
		if ($enabled) {
755
			\OCP\Util::connectHook('OCP\Share', 'post_shared', 'OC\Encryption\HookManager', 'postShared');
756
			\OCP\Util::connectHook('OCP\Share', 'post_unshare', 'OC\Encryption\HookManager', 'postUnshared');
757
			\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OC\Encryption\HookManager', 'postRename');
758
			\OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', 'OC\Encryption\HookManager', 'postRestore');
759
		}
760
	}
761
762
	/**
763
	 * register hooks for the cache
764
	 */
765
	public static function registerLogRotate() {
766
		$systemConfig = \OC::$server->getSystemConfig();
767
		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...
768
			//don't try to do this before we are properly setup
769
			//use custom logfile path if defined, otherwise use default of owncloud.log in data directory
770
			$jobList = \OC::$server->getJobList();
771
			$jobList->add('OC\Log\Rotate', $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/owncloud.log'));
772
		}
773
	}
774
775
	/**
776
	 * register hooks for the filesystem
777
	 */
778
	public static function registerFilesystemHooks() {
779
		// Check for blacklisted files
780
		OC_Hook::connect('OC_Filesystem', 'write', 'OC\Files\Filesystem', 'isForbiddenFileOrDir_Hook');
781
		OC_Hook::connect('OC_Filesystem', 'rename', 'OC\Files\Filesystem', 'isForbiddenFileOrDir_Hook');
782
	}
783
784
	/**
785
	 * register hooks for previews
786
	 */
787
	public static function registerPreviewHooks() {
788
		OC_Hook::connect('OC_Filesystem', 'post_write', 'OC\Preview', 'post_write');
789
		OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'prepare_delete_files');
790
		OC_Hook::connect('\OCP\Versions', 'preDelete', 'OC\Preview', 'prepare_delete');
791
		OC_Hook::connect('\OCP\Trashbin', 'preDelete', 'OC\Preview', 'prepare_delete');
792
		OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC\Preview', 'post_delete_files');
793
		OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete_versions');
794
		OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete');
795
		OC_Hook::connect('\OCP\Versions', 'rollback', 'OC\Preview', 'post_delete_versions');
796
	}
797
798
	/**
799
	 * register hooks for sharing
800
	 */
801
	public static function registerShareHooks() {
802
		if (\OC::$server->getSystemConfig()->getValue('installed')) {
803
			OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share20\Hooks', 'post_deleteUser');
804
			OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share20\Hooks', 'post_removeFromGroup');
805
			OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share20\Hooks', 'post_deleteGroup');
806
		}
807
	}
808
809
	protected static function registerAutoloaderCache() {
810
		// The class loader takes an optional low-latency cache, which MUST be
811
		// namespaced. The instanceid is used for namespacing, but might be
812
		// unavailable at this point. Furthermore, it might not be possible to
813
		// generate an instanceid via \OC_Util::getInstanceId() because the
814
		// config file may not be writable. As such, we only register a class
815
		// loader cache if instanceid is available without trying to create one.
816
		$instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
817
		if ($instanceId) {
818
			try {
819
				$memcacheFactory = \OC::$server->getMemCacheFactory();
820
				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...
821
			} catch (\Exception $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
822
			}
823
		}
824
	}
825
826
	/**
827
	 * Handle the request
828
	 */
829
	public static function handleRequest() {
830
		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
831
		$systemConfig = \OC::$server->getSystemConfig();
832
		// load all the classpaths from the enabled apps so they are available
833
		// in the routing files of each app
834
		OC::loadAppClassPaths();
835
836
		// Check if ownCloud is installed or in maintenance (update) mode
837
		if (!$systemConfig->getValue('installed', false)) {
838
			\OC::$server->getSession()->clear();
839
			$setupHelper = new OC\Setup(\OC::$server->getConfig(), \OC::$server->getIniWrapper(),
840
				\OC::$server->getL10N('lib'), new \OC_Defaults(), \OC::$server->getLogger(),
841
				\OC::$server->getSecureRandom());
842
843
			$controller = new OC\Core\Controller\SetupController($setupHelper);
844
			$controller->run($_POST);
845
			exit();
846
		}
847
848
		$request = \OC::$server->getRequest();
849
		// Check if requested URL matches 'index.php/occ'
850
		$isOccControllerRequested = \preg_match('|/index\.php$|', $request->getScriptName()) === 1
851
			&& \strpos($request->getPathInfo(), '/occ/') === 0;
852
853
		$needUpgrade = false;
854
		$requestPath = $request->getRawPathInfo();
855
		if (\substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
856
			self::checkMaintenanceMode($request);
857
			$needUpgrade = self::checkUpgrade(!$isOccControllerRequested);
858
		}
859
860
		// emergency app disabling
861
		if ($requestPath === '/disableapp'
862
			&& $request->getMethod() === 'POST'
863
			&& ((string)$request->getParam('appid')) !== ''
864
		) {
865
			\OCP\JSON::callCheck();
866
			\OCP\JSON::checkAdminUser();
867
			$appId = (string)$request->getParam('appid');
868
			$appId = \OC_App::cleanAppId($appId);
869
870
			\OC_App::disable($appId);
871
			\OC_JSON::success();
872
			exit();
873
		}
874
875
		try {
876
			// Always load authentication apps
877
			OC_App::loadApps(['authentication']);
878
		} catch (\OC\NeedsUpdateException $e) {
879
			if ($isOccControllerRequested && $needUpgrade) {
880
				OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
881
				return;
882
			}
883
			throw $e;
884
		}
885
886
		// Load minimum set of apps
887
		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...
888
			&& !$systemConfig->getValue('maintenance', false)) {
889
			// For logged-in users: Load everything
890
			$userSession = \OC::$server->getUserSession();
891
			if ($userSession->isLoggedIn() && $userSession->verifyAuthHeaders($request)) {
892
				OC_App::loadApps();
893
			} else {
894
				// For guests: Load only filesystem and logging
895
				OC_App::loadApps(['filesystem', 'logging']);
896
			}
897
		}
898
899
		if (!self::$CLI) {
900
			try {
901
				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...
902
					OC_App::loadApps(['filesystem', 'logging']);
903
					OC_App::loadApps();
904
				}
905
				self::checkSingleUserMode();
906
				OC_Util::setupFS();
907
				OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
908
				return;
909
			} catch (\OC\NeedsUpdateException $e) {
910
				if ($isOccControllerRequested && $needUpgrade) {
911
					OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
912
					return;
913
				}
914
				throw $e;
915
			} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
916
				//header('HTTP/1.0 404 Not Found');
917
				$dispatcher = \OC::$server->getEventDispatcher();
918
				$dispatcher->dispatch(\OCP\Http\HttpEvents::EVENT_404, new OCP\Http\HttpEvents(
919
					\OCP\Http\HttpEvents::EVENT_404,
920
					OC::$server->getRequest()
921
				));
922
			} catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
923
				OC_Response::setStatus(405);
924
				return;
925
			}
926
		}
927
928
		// Handle WebDAV
929
		if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
930
			// not allowed any more to prevent people
931
			// mounting this root directly.
932
			// Users need to mount remote.php/webdav instead.
933
			\header('HTTP/1.1 405 Method Not Allowed');
934
			\header('Status: 405 Method Not Allowed');
935
			return;
936
		}
937
938
		// Someone is logged in
939
		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...
940
			OC_App::loadApps();
941
			OC_User::setupBackends();
942
			OC_Util::setupFS();
943
			// FIXME
944
			// Redirect to default application
945
			OC_Util::redirectToDefaultPage();
946
		} else {
947
			// Not handled and not logged in
948
			\header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
949
		}
950
	}
951
952
	/**
953
	 * Check login: apache auth, auth token, basic auth
954
	 *
955
	 * @param OCP\IRequest $request
956
	 * @return boolean
957
	 */
958
	public static function handleLogin(OCP\IRequest $request) {
959
		$userSession = self::$server->getUserSession();
960
		if (OC_User::handleApacheAuth()) {
961
			return true;
962
		}
963
		if ($userSession->tryTokenLogin($request)) {
964
			return true;
965
		}
966
		if ($userSession->tryAuthModuleLogin($request)) {
967
			return true;
968
		}
969
		if ($userSession->tryBasicAuthLogin($request)) {
970
			return true;
971
		}
972
		return false;
973
	}
974
975
	protected static function handleAuthHeaders() {
976
		//copy http auth headers for apache+php-fcgid work around
977
		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
978
			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
979
		}
980
981
		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
982
		$vars = [
983
			'HTTP_AUTHORIZATION', // apache+php-cgi work around
984
			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
985
		];
986
		foreach ($vars as $var) {
987
			if (isset($_SERVER[$var]) && \preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
988
				list($name, $password) = \explode(':', \base64_decode($matches[1]), 2);
989
				$_SERVER['PHP_AUTH_USER'] = $name;
990
				$_SERVER['PHP_AUTH_PW'] = $password;
991
				break;
992
			}
993
		}
994
	}
995
}
996
997
OC::init();
998