Completed
Push — stable8 ( 420dab...a42074 )
by
unknown
10:01
created

OC::initPaths()   F

Complexity

Conditions 25
Paths 1872

Size

Total Lines 105
Code Lines 67

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 25
eloc 67
nc 1872
nop 0
dl 0
loc 105
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
 * ownCloud
4
 *
5
 * @author Frank Karlitschek
6
 * @copyright 2012 Frank Karlitschek [email protected]
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
10
 * License as published by the Free Software Foundation; either
11
 * version 3 of the License, or any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public
19
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
23
require_once 'public/constants.php';
24
25
/**
26
 * Class that is a namespace for all global OC variables
27
 * No, we can not put this class in its own file because it is used by
28
 * OC_autoload!
29
 */
30
class OC {
31
	/**
32
	 * Associative array for autoloading. classname => filename
33
	 */
34
	public static $CLASSPATH = array();
35
	/**
36
	 * The installation path for owncloud on the server (e.g. /srv/http/owncloud)
37
	 */
38
	public static $SERVERROOT = '';
39
	/**
40
	 * the current request path relative to the owncloud root (e.g. files/index.php)
41
	 */
42
	private static $SUBURI = '';
43
	/**
44
	 * the owncloud root path for http requests (e.g. owncloud/)
45
	 */
46
	public static $WEBROOT = '';
47
	/**
48
	 * The installation path of the 3rdparty folder on the server (e.g. /srv/http/owncloud/3rdparty)
49
	 */
50
	public static $THIRDPARTYROOT = '';
51
	/**
52
	 * the root path of the 3rdparty folder for http requests (e.g. owncloud/3rdparty)
53
	 */
54
	public static $THIRDPARTYWEBROOT = '';
55
	/**
56
	 * The installation path array of the apps folder on the server (e.g. /srv/http/owncloud) 'path' and
57
	 * web path in 'url'
58
	 */
59
	public static $APPSROOTS = array();
60
61
	public static $configDir;
62
63
	/**
64
	 * requested app
65
	 */
66
	public static $REQUESTEDAPP = '';
67
68
	/**
69
	 * check if ownCloud runs in cli mode
70
	 */
71
	public static $CLI = false;
72
73
	/**
74
	 * @var \OC\Autoloader $loader
75
	 */
76
	public static $loader = null;
77
78
	/**
79
	 * @var \OC\Server
80
	 */
81
	public static $server = null;
82
83
	public static function initPaths() {
84
		// calculate the root directories
85
		OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
86
87
		// ensure we can find OC_Config
88
		set_include_path(
89
			OC::$SERVERROOT . '/lib' . PATH_SEPARATOR .
90
			get_include_path()
91
		);
92
93
		if(defined('PHPUNIT_CONFIG_DIR')) {
94
			self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/';
95
		} elseif(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) {
96
			self::$configDir = OC::$SERVERROOT . '/tests/config/';
97
		} else {
98
			self::$configDir = OC::$SERVERROOT . '/config/';
99
		}
100
		OC_Config::$object = new \OC\Config(self::$configDir);
101
102
		OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
103
		$scriptName = OC_Request::scriptName();
104
		if (substr($scriptName, -1) == '/') {
105
			$scriptName .= 'index.php';
106
			//make sure suburi follows the same rules as scriptName
107
			if (substr(OC::$SUBURI, -9) != 'index.php') {
108
				if (substr(OC::$SUBURI, -1) != '/') {
109
					OC::$SUBURI = OC::$SUBURI . '/';
110
				}
111
				OC::$SUBURI = OC::$SUBURI . 'index.php';
112
			}
113
		}
114
115
		if (substr($scriptName, 0 - strlen(OC::$SUBURI)) === OC::$SUBURI) {
116
			OC::$WEBROOT = substr($scriptName, 0, 0 - strlen(OC::$SUBURI));
117
118
			if (OC::$WEBROOT != '' && OC::$WEBROOT[0] !== '/') {
119
				OC::$WEBROOT = '/' . OC::$WEBROOT;
120
			}
121
		} else {
122
			// The scriptName is not ending with OC::$SUBURI
123
			// This most likely means that we are calling from CLI.
124
			// However some cron jobs still need to generate
125
			// a web URL, so we use overwritewebroot as a fallback.
126
			OC::$WEBROOT = OC_Config::getValue('overwritewebroot', '');
127
		}
128
129
		// search the 3rdparty folder
130
		OC::$THIRDPARTYROOT = OC_Config::getValue('3rdpartyroot', null);
131
		OC::$THIRDPARTYWEBROOT = OC_Config::getValue('3rdpartyurl', null);
132
		
133
		if (empty(OC::$THIRDPARTYROOT) && empty(OC::$THIRDPARTYWEBROOT)) {
134
			if (file_exists(OC::$SERVERROOT . '/3rdparty')) {
135
				OC::$THIRDPARTYROOT = OC::$SERVERROOT;
136
				OC::$THIRDPARTYWEBROOT = OC::$WEBROOT;
137
			} elseif (file_exists(OC::$SERVERROOT . '/../3rdparty')) {
138
				OC::$THIRDPARTYWEBROOT = rtrim(dirname(OC::$WEBROOT), '/');
139
				OC::$THIRDPARTYROOT = rtrim(dirname(OC::$SERVERROOT), '/');
140
			}
141
		}
142
		if (empty(OC::$THIRDPARTYROOT) || !file_exists(OC::$THIRDPARTYROOT)) {
143
			echo('3rdparty directory not found! Please put the ownCloud 3rdparty'
144
				. ' folder in the ownCloud folder or the folder above.'
145
				. ' You can also configure the location in the config.php file.');
146
			return;
147
		}
148
		
149
		// search the apps folder
150
		$config_paths = OC_Config::getValue('apps_paths', array());
151
		if (!empty($config_paths)) {
152
			foreach ($config_paths as $paths) {
153
				if (isset($paths['url']) && isset($paths['path'])) {
154
					$paths['url'] = rtrim($paths['url'], '/');
155
					$paths['path'] = rtrim($paths['path'], '/');
156
					OC::$APPSROOTS[] = $paths;
157
				}
158
			}
159
		} elseif (file_exists(OC::$SERVERROOT . '/apps')) {
160
			OC::$APPSROOTS[] = array('path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true);
161
		} elseif (file_exists(OC::$SERVERROOT . '/../apps')) {
162
			OC::$APPSROOTS[] = array(
163
				'path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps',
164
				'url' => '/apps',
165
				'writable' => true
166
			);
167
		}
168
169
		if (empty(OC::$APPSROOTS)) {
170
			throw new Exception('apps directory not found! Please put the ownCloud apps folder in the ownCloud folder'
171
				. ' or the folder above. You can also configure the location in the config.php file.');
172
		}
173
		$paths = array();
174
		foreach (OC::$APPSROOTS as $path) {
175
			$paths[] = $path['path'];
176
		}
177
178
		// set the right include path
179
		set_include_path(
180
			OC::$SERVERROOT . '/lib/private' . PATH_SEPARATOR .
181
			OC::$SERVERROOT . '/config' . PATH_SEPARATOR .
182
			OC::$THIRDPARTYROOT . '/3rdparty' . PATH_SEPARATOR .
183
			implode(PATH_SEPARATOR, $paths) . PATH_SEPARATOR .
184
			get_include_path() . PATH_SEPARATOR .
185
			OC::$SERVERROOT
186
		);
187
	}
188
189
	public static function checkConfig() {
190
		$l = \OC::$server->getL10N('lib');
191
192
		// Create config in case it does not already exists
193
		$configFilePath = self::$configDir .'/config.php';
194
		if(!file_exists($configFilePath)) {
195
			@touch($configFilePath);
196
		}
197
198
		// Check if config is writable
199
		$configFileWritable = is_writable($configFilePath);
200
		if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled()
201
			|| !$configFileWritable && \OCP\Util::needUpgrade()) {
202
			if (self::$CLI) {
203
				echo $l->t('Cannot write into "config" directory!')."\n";
204
				echo $l->t('This can usually be fixed by giving the webserver write access to the config directory')."\n";
205
				echo "\n";
206
				echo $l->t('See %s', array(\OC_Helper::linkToDocs('admin-dir_permissions')))."\n";
207
				exit;
208
			} else {
209
				OC_Template::printErrorPage(
210
					$l->t('Cannot write into "config" directory!'),
211
					$l->t('This can usually be fixed by '
212
					. '%sgiving the webserver write access to the config directory%s.',
213
					 array('<a href="'.\OC_Helper::linkToDocs('admin-dir_permissions').'" target="_blank">', '</a>'))
214
				);
215
			}
216
		}
217
	}
218
219
	public static function checkInstalled() {
220
		// Redirect to installer if not installed
221
		if (!\OC::$server->getSystemConfig()->getValue('installed', false) && OC::$SUBURI != '/index.php') {
222
			if (OC::$CLI) {
223
				throw new Exception('Not installed');
224
			} else {
225
				$url = 'http://' . $_SERVER['SERVER_NAME'] . OC::$WEBROOT . '/index.php';
226
				header('Location: ' . $url);
227
			}
228
			exit();
229
		}
230
	}
231
232
	public static function checkSSL() {
233
		// redirect to https site if configured
234
		if (\OC::$server->getSystemConfig()->getValue('forcessl', false)) {
235
			// Default HSTS policy
236
			$header = 'Strict-Transport-Security: max-age=31536000';
237
238
			// If SSL for subdomains is enabled add "; includeSubDomains" to the header
239
			if(\OC::$server->getSystemConfig()->getValue('forceSSLforSubdomains', false)) {
240
				$header .= '; includeSubDomains';
241
			}
242
			header($header);
243
			ini_set('session.cookie_secure', 'on');
244
			if (OC_Request::serverProtocol() <> 'https' and !OC::$CLI) {
245
				$url = 'https://' . OC_Request::serverHost() . OC_Request::requestUri();
246
				header("Location: $url");
247
				exit();
248
			}
249
		} else {
250
			// Invalidate HSTS headers
251
			if (OC_Request::serverProtocol() === 'https') {
252
				header('Strict-Transport-Security: max-age=0');
253
			}
254
		}
255
	}
256
257
	public static function checkMaintenanceMode() {
258
		// Allow ajax update script to execute without being stopped
259
		if (\OC::$server->getSystemConfig()->getValue('maintenance', false) && OC::$SUBURI != '/core/ajax/update.php') {
260
			// send http status 503
261
			header('HTTP/1.1 503 Service Temporarily Unavailable');
262
			header('Status: 503 Service Temporarily Unavailable');
263
			header('Retry-After: 120');
264
265
			// render error page
266
			$template = new OC_Template('', 'update.user', 'guest');
267
			OC_Util::addscript('maintenance-check');
268
			$template->printPage();
269
			die();
270
		}
271
	}
272
273
	public static function checkSingleUserMode($lockIfNoUserLoggedIn = false) {
274
		if (!\OC::$server->getSystemConfig()->getValue('singleuser', false)) {
275
			return;
276
		}
277
		$user = OC_User::getUserSession()->getUser();
278
		if ($user) {
279
			$group = \OC::$server->getGroupManager()->get('admin');
280
			if ($group->inGroup($user)) {
281
				return;
282
			}
283
		} else {
284
			if(!$lockIfNoUserLoggedIn) {
285
				return;
286
			}
287
		}
288
		// send http status 503
289
		header('HTTP/1.1 503 Service Temporarily Unavailable');
290
		header('Status: 503 Service Temporarily Unavailable');
291
		header('Retry-After: 120');
292
293
		// render error page
294
		$template = new OC_Template('', 'singleuser.user', 'guest');
295
		$template->printPage();
296
		die();
297
	}
298
299
	/**
300
	 * check if the instance needs to preform an upgrade
301
	 *
302
	 * @return bool
303
	 * @deprecated use \OCP\Util::needUpgrade() instead
304
	 */
305
	public static function needUpgrade() {
306
		return \OCP\Util::needUpgrade();
307
	}
308
309
	/**
310
	 * Checks if the version requires an update and shows
311
	 * @param bool $showTemplate Whether an update screen should get shown
312
	 * @return bool|void
313
	 */
314
	public static function checkUpgrade($showTemplate = true) {
315
		if (\OCP\Util::needUpgrade()) {
316
			$systemConfig = \OC::$server->getSystemConfig();
317
			if ($showTemplate && !$systemConfig->getValue('maintenance', false)) {
318
				$version = OC_Util::getVersion();
319
				$oldTheme = $systemConfig->getValue('theme');
320
				$systemConfig->setValue('theme', '');
321
				OC_Util::addScript('config'); // needed for web root
322
				OC_Util::addScript('update');
323
				$tmpl = new OC_Template('', 'update.admin', 'guest');
324
				$tmpl->assign('version', OC_Util::getVersionString());
325
326
				// get third party apps
327
				$apps = OC_App::getEnabledApps();
328
				$incompatibleApps = array();
329
				foreach ($apps as $appId) {
330
					$info = OC_App::getAppInfo($appId);
331
					if(!OC_App::isAppCompatible($version, $info)) {
0 ignored issues
show
Documentation introduced by
$version is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Bug introduced by
It seems like $info defined by \OC_App::getAppInfo($appId) on line 330 can also be of type null; however, OC_App::isAppCompatible() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
332
						$incompatibleApps[] = $info;
333
					}
334
				}
335
				$tmpl->assign('appList', $incompatibleApps);
336
				$tmpl->assign('productName', 'ownCloud'); // for now
337
				$tmpl->assign('oldTheme', $oldTheme);
338
				$tmpl->printPage();
339
				exit();
340
			} else {
341
				return true;
342
			}
343
		}
344
		return false;
345
	}
346
347
	public static function initTemplateEngine() {
348
		// Add the stuff we need always
349
		// following logic will import all vendor libraries that are
350
		// specified in core/js/core.json
351
		$fileContent = file_get_contents(OC::$SERVERROOT . '/core/js/core.json');
352
		if($fileContent !== false) {
353
			$coreDependencies = json_decode($fileContent, true);
354
			foreach($coreDependencies['vendor'] as $vendorLibrary) {
355
				// remove trailing ".js" as addVendorScript will append it
356
				OC_Util::addVendorScript(
357
					substr($vendorLibrary, 0, strlen($vendorLibrary) - 3));
358
			}
359
		} else {
360
			throw new \Exception('Cannot read core/js/core.json');
361
		}
362
363
		OC_Util::addScript("placeholders");
364
		OC_Util::addScript("jquery-tipsy");
365
		OC_Util::addScript("compatibility");
366
		OC_Util::addScript("jquery.ocdialog");
367
		OC_Util::addScript("oc-dialogs");
368
		OC_Util::addScript("js");
369
		OC_Util::addScript("l10n");
370
		OC_Util::addTranslations("core");
371
		OC_Util::addScript("octemplate");
372
		OC_Util::addScript("eventsource");
373
		OC_Util::addScript("config");
374
		//OC_Util::addScript( "multiselect" );
375
		OC_Util::addScript('search', 'search');
376
		OC_Util::addScript("oc-requesttoken");
377
		OC_Util::addScript("apps");
378
		OC_Util::addVendorScript('snapjs/dist/latest/snap');
379
380
		// avatars
381
		if (\OC::$server->getSystemConfig()->getValue('enable_avatars', true) === true) {
382
			\OC_Util::addScript('placeholder');
383
			\OC_Util::addVendorScript('blueimp-md5/js/md5');
384
			\OC_Util::addScript('jquery.avatar');
385
			\OC_Util::addScript('avatar');
386
		}
387
388
		OC_Util::addStyle("styles");
389
		OC_Util::addStyle("header");
390
		OC_Util::addStyle("mobile");
391
		OC_Util::addStyle("icons");
392
		OC_Util::addStyle("fonts");
393
		OC_Util::addStyle("apps");
394
		OC_Util::addStyle("fixes");
395
		OC_Util::addStyle("multiselect");
396
		OC_Util::addVendorStyle('jquery-ui/themes/base/jquery-ui');
397
		OC_Util::addStyle('jquery-ui-fixes');
398
		OC_Util::addStyle("jquery-tipsy");
399
		OC_Util::addStyle("jquery.ocdialog");
400
	}
401
402
	public static function initSession() {
403
		// prevents javascript from accessing php session cookies
404
		ini_set('session.cookie_httponly', '1;');
405
406
		// set the cookie path to the ownCloud directory
407
		$cookie_path = OC::$WEBROOT ? : '/';
408
		ini_set('session.cookie_path', $cookie_path);
409
410
		// Let the session name be changed in the initSession Hook
411
		$sessionName = OC_Util::getInstanceId();
412
413
		try {
414
			// Allow session apps to create a custom session object
415
			$useCustomSession = false;
416
			$session = self::$server->getSession();
417
			OC_Hook::emit('OC', 'initSession', array('session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession));
418
			if($useCustomSession) {
419
				// use the session reference as the new Session
420
				self::$server->setSession($session);
421
			} else {
422
				// set the session name to the instance id - which is unique
423
				self::$server->setSession(new \OC\Session\Internal($sessionName));
424
			}
425
			// if session cant be started break with http 500 error
426
		} catch (Exception $e) {
427
			//show the user a detailed error page
428
			OC_Response::setStatus(OC_Response::STATUS_INTERNAL_SERVER_ERROR);
429
			OC_Template::printExceptionErrorPage($e);
430
		}
431
432
		$sessionLifeTime = self::getSessionLifeTime();
433
		// regenerate session id periodically to avoid session fixation
434
		/**
435
		 * @var \OCP\ISession $session
436
		 */
437
		$session = self::$server->getSession();
438
		if (!$session->exists('SID_CREATED')) {
439
			$session->set('SID_CREATED', time());
440
		} else if (time() - $session->get('SID_CREATED') > $sessionLifeTime / 2) {
441
			session_regenerate_id(true);
442
			$session->set('SID_CREATED', time());
443
		}
444
445
		// session timeout
446
		if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
447
			if (isset($_COOKIE[session_name()])) {
448
				setcookie(session_name(), '', time() - 42000, $cookie_path);
449
			}
450
			session_unset();
451
			session_destroy();
452
			session_start();
453
		}
454
455
		$session->set('LAST_ACTIVITY', time());
456
	}
457
458
	/**
459
	 * @return string
460
	 */
461
	private static function getSessionLifeTime() {
462
		return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
463
	}
464
465
	public static function loadAppClassPaths() {
466 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...
467
			$file = OC_App::getAppPath($app) . '/appinfo/classpath.php';
468
			if (file_exists($file)) {
469
				require_once $file;
470
			}
471
		}
472
	}
473
474
475
	public static function init() {
476
		// register autoloader
477
		$loaderStart = microtime(true);
478
		require_once __DIR__ . '/autoloader.php';
479
		self::$loader = new \OC\Autoloader();
480
		spl_autoload_register(array(self::$loader, 'load'));
481
		$loaderEnd = microtime(true);
482
483
		self::initPaths();
484
485
		// setup 3rdparty autoloader
486
		$vendorAutoLoad = OC::$THIRDPARTYROOT . '/3rdparty/autoload.php';
487
		if (file_exists($vendorAutoLoad)) {
488
			require_once $vendorAutoLoad;
489
		} else {
490
			OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
491
			// we can't use the template error page here, because this needs the
492
			// DI container which isn't available yet
493
			print('Composer autoloader not found, unable to continue. Check the folder "3rdparty".');
494
			exit();
495
		}
496
497
		// setup the basic server
498
		self::$server = new \OC\Server(\OC::$WEBROOT);
499
		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
500
		\OC::$server->getEventLogger()->start('boot', 'Initialize');
501
502
		// Don't display errors and log them
503
		error_reporting(E_ALL | E_STRICT);
504
		@ini_set('display_errors', 0);
505
		@ini_set('log_errors', 1);
506
507
		self::$CLI = (php_sapi_name() == 'cli');
508
509
		date_default_timezone_set('UTC');
510
		ini_set('arg_separator.output', '&amp;');
511
512
		//try to configure php to enable big file uploads.
513
		//this doesn´t work always depending on the webserver and php configuration.
514
		//Let´s try to overwrite some defaults anyways
515
516
		//try to set the maximum execution time to 60min
517
		@set_time_limit(3600);
518
		@ini_set('max_execution_time', 3600);
519
		@ini_set('max_input_time', 3600);
520
521
		//try to set the maximum filesize to 10G
522
		@ini_set('upload_max_filesize', '10G');
523
		@ini_set('post_max_size', '10G');
524
		@ini_set('file_uploads', '50');
525
526
		self::handleAuthHeaders();
527
		self::registerAutoloaderCache();
528
529
		// initialize intl fallback is necessary
530
		\Patchwork\Utf8\Bootup::initIntl();
531
		OC_Util::isSetLocaleWorking();
532
533
		if (!defined('PHPUNIT_RUN')) {
534
			OC\Log\ErrorHandler::setLogger(OC_Log::$object);
535
			if (defined('DEBUG') and DEBUG) {
536
				OC\Log\ErrorHandler::register(true);
537
				set_exception_handler(array('OC_Template', 'printExceptionErrorPage'));
538
			} else {
539
				OC\Log\ErrorHandler::register();
540
			}
541
		}
542
543
		// register the stream wrappers
544
		stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir');
545
		stream_wrapper_register('static', 'OC\Files\Stream\StaticStream');
546
		stream_wrapper_register('close', 'OC\Files\Stream\Close');
547
		stream_wrapper_register('quota', 'OC\Files\Stream\Quota');
548
		stream_wrapper_register('oc', 'OC\Files\Stream\OC');
549
550
		\OC::$server->getEventLogger()->start('init_session', 'Initialize session');
551
		OC_App::loadApps(array('session'));
552
		if (!self::$CLI) {
553
			self::initSession();
554
		}
555
		\OC::$server->getEventLogger()->end('init_session');
556
		self::initTemplateEngine();
557
		self::checkConfig();
558
		self::checkInstalled();
559
		self::checkSSL();
560
		OC_Response::addSecurityHeaders();
561
562
		$errors = OC_Util::checkServer(\OC::$server->getConfig());
563
		if (count($errors) > 0) {
564
			if (self::$CLI) {
565
				// Convert l10n string into regular string for usage in database
566
				$staticErrors = [];
567
				foreach ($errors as $error) {
568
					echo $error['error'] . "\n";
569
					echo $error['hint'] . "\n\n";
570
					$staticErrors[] = [
571
						'error' => (string) $error['error'],
572
						'hint' => (string) $error['hint'],
573
					];
574
				}
575
576
				try {
577
					\OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
578
				} catch(\Exception $e) {
579
					echo('Writing to database failed');
580
				}
581
				exit();
582
			} else {
583
				OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
584
				OC_Template::printGuestPage('', 'error', array('errors' => $errors));
585
				exit;
586
			}
587
		} elseif(self::$CLI && \OC::$server->getConfig()->getSystemValue('installed', false)) {
588
				\OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
589
		}
590
591
		//try to set the session lifetime
592
		$sessionLifeTime = self::getSessionLifeTime();
593
		@ini_set('gc_maxlifetime', (string)$sessionLifeTime);
594
595
		$systemConfig = \OC::$server->getSystemConfig();
596
597
		// User and Groups
598
		if (!$systemConfig->getValue("installed", false)) {
599
			self::$server->getSession()->set('user_id', '');
600
		}
601
602
		OC_User::useBackend(new OC_User_Database());
603
		OC_Group::useBackend(new OC_Group_Database());
604
605
		//setup extra user backends
606
		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...
607
			OC_User::setupBackends();
608
		}
609
610
		self::registerCacheHooks();
611
		self::registerFilesystemHooks();
612
		self::registerPreviewHooks();
613
		self::registerShareHooks();
614
		self::registerLogRotate();
615
		self::registerLocalAddressBook();
616
617
		//make sure temporary files are cleaned up
618
		$tmpManager = \OC::$server->getTempManager();
619
		register_shutdown_function(array($tmpManager, 'clean'));
620
621
		if ($systemConfig->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...
622
			if (\OC::$server->getConfig()->getAppValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') {
623
				OC_Util::addScript('backgroundjobs');
624
			}
625
		}
626
627
		// Check whether the sample configuration has been copied
628
		if($systemConfig->getValue('copied_sample_config', false)) {
629
			$l = \OC::$server->getL10N('lib');
630
			header('HTTP/1.1 503 Service Temporarily Unavailable');
631
			header('Status: 503 Service Temporarily Unavailable');
632
			OC_Template::printErrorPage(
633
				$l->t('Sample configuration detected'),
634
				$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')
635
			);
636
			return;
637
		}
638
639
		$host = OC_Request::insecureServerHost();
640
		// if the host passed in headers isn't trusted
641
		if (!OC::$CLI
642
			// overwritehost is always trusted
643
			&& OC_Request::getOverwriteHost() === null
644
			&& !OC_Request::isTrustedDomain($host)
645
		) {
646
			header('HTTP/1.1 400 Bad Request');
647
			header('Status: 400 Bad Request');
648
649
			$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
650
			$tmpl->assign('domain', $_SERVER['SERVER_NAME']);
651
			$tmpl->printPage();
652
653
			exit();
654
		}
655
		\OC::$server->getEventLogger()->end('boot');
656
	}
657
658
	private static function registerLocalAddressBook() {
659
		self::$server->getContactsManager()->register(function() {
660
			$userManager = \OC::$server->getUserManager();
661
			\OC::$server->getContactsManager()->registerAddressBook(
662
				new \OC\Contacts\LocalAddressBook($userManager));
663
		});
664
	}
665
666
	/**
667
	 * register hooks for the cache
668
	 */
669
	public static function registerCacheHooks() {
670
		if (\OC::$server->getSystemConfig()->getValue('installed', false) && !\OCP\Util::needUpgrade()) { //don't try to do this before we are properly setup
671
			\OCP\BackgroundJob::registerJob('OC\Cache\FileGlobalGC');
672
673
			// NOTE: This will be replaced to use OCP
674
			$userSession = \OC_User::getUserSession();
675
			$userSession->listen('postLogin', '\OC\Cache\File', 'loginListener');
676
		}
677
	}
678
679
	/**
680
	 * register hooks for the cache
681
	 */
682
	public static function registerLogRotate() {
683
		$systemConfig = \OC::$server->getSystemConfig();
684
		if ($systemConfig->getValue('installed', false) && $systemConfig->getValue('log_rotate_size', false) && !\OCP\Util::needUpgrade()) {
685
			//don't try to do this before we are properly setup
686
			//use custom logfile path if defined, otherwise use default of owncloud.log in data directory
687
			\OCP\BackgroundJob::registerJob('OC\Log\Rotate', $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/owncloud.log'));
688
		}
689
	}
690
691
	/**
692
	 * register hooks for the filesystem
693
	 */
694
	public static function registerFilesystemHooks() {
695
		// Check for blacklisted files
696
		OC_Hook::connect('OC_Filesystem', 'write', 'OC\Files\Filesystem', 'isBlacklisted');
697
		OC_Hook::connect('OC_Filesystem', 'rename', 'OC\Files\Filesystem', 'isBlacklisted');
698
	}
699
700
	/**
701
	 * register hooks for previews
702
	 */
703
	public static function registerPreviewHooks() {
704
		OC_Hook::connect('OC_Filesystem', 'post_write', 'OC\Preview', 'post_write');
705
		OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'prepare_delete_files');
706
		OC_Hook::connect('\OCP\Versions', 'preDelete', 'OC\Preview', 'prepare_delete');
707
		OC_Hook::connect('\OCP\Trashbin', 'preDelete', 'OC\Preview', 'prepare_delete');
708
		OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC\Preview', 'post_delete_files');
709
		OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete');
710
		OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete');
711
	}
712
713
	/**
714
	 * register hooks for sharing
715
	 */
716
	public static function registerShareHooks() {
717
		if (\OC::$server->getSystemConfig()->getValue('installed')) {
718
			OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share\Hooks', 'post_deleteUser');
719
			OC_Hook::connect('OC_User', 'post_addToGroup', 'OC\Share\Hooks', 'post_addToGroup');
720
			OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share\Hooks', 'post_removeFromGroup');
721
			OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share\Hooks', 'post_deleteGroup');
722
		}
723
	}
724
725
	protected static function registerAutoloaderCache() {
726
		// The class loader takes an optional low-latency cache, which MUST be
727
		// namespaced. The instanceid is used for namespacing, but might be
728
		// unavailable at this point. Futhermore, it might not be possible to
729
		// generate an instanceid via \OC_Util::getInstanceId() because the
730
		// config file may not be writable. As such, we only register a class
731
		// loader cache if instanceid is available without trying to create one.
732
		$instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
733
		if ($instanceId) {
734
			try {
735
				$memcacheFactory = new \OC\Memcache\Factory($instanceId);
736
				self::$loader->setMemoryCache($memcacheFactory->createLowLatency('Autoloader'));
737
			} catch (\Exception $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
738
			}
739
		}
740
	}
741
742
	/**
743
	 * Handle the request
744
	 */
745
	public static function handleRequest() {
746
		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
747
		$systemConfig = \OC::$server->getSystemConfig();
748
		// load all the classpaths from the enabled apps so they are available
749
		// in the routing files of each app
750
		OC::loadAppClassPaths();
751
752
		// Check if ownCloud is installed or in maintenance (update) mode
753
		if (!$systemConfig->getValue('installed', false)) {
754
			\OC::$server->getSession()->clear();
755
			$controller = new OC\Core\Setup\Controller(\OC::$server->getConfig(), \OC::$server->getIniWrapper(), \OC::$server->getL10N('core'), new \OC_Defaults());
756
			$controller->run($_POST);
757
			exit();
758
		}
759
760
		$request = OC_Request::getPathInfo();
761
		if (substr($request, -3) !== '.js') { // we need these files during the upgrade
762
			self::checkMaintenanceMode();
763
			self::checkUpgrade();
764
		}
765
766
		// Always load authentication apps
767
		OC_App::loadApps(['authentication']);
768
769
		// Load minimum set of apps
770
		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...
771
			&& !$systemConfig->getValue('maintenance', false)
772
			&& !\OCP\Util::needUpgrade()) {
773
			// For logged-in users: Load everything
774
			if(OC_User::isLoggedIn()) {
775
				OC_App::loadApps();
776
			} else {
777
				// For guests: Load only filesystem and logging
778
				OC_App::loadApps(array('filesystem', 'logging'));
779
				\OC_User::tryBasicAuthLogin();
780
			}
781
		}
782
783
		if (!self::$CLI and (!isset($_GET["logout"]) or ($_GET["logout"] !== 'true'))) {
784
			try {
785
				if (!$systemConfig->getValue('maintenance', false) && !\OCP\Util::needUpgrade()) {
786
					OC_App::loadApps(array('filesystem', 'logging'));
787
					OC_App::loadApps();
788
				}
789
				self::checkSingleUserMode();
790
				OC_Util::setupFS();
791
				OC::$server->getRouter()->match(OC_Request::getRawPathInfo());
792
				return;
793
			} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\Routin...sourceNotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
794
				//header('HTTP/1.0 404 Not Found');
795
			} catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\Routin...thodNotAllowedException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
796
				OC_Response::setStatus(405);
797
				return;
798
			}
799
		}
800
801
		// Handle redirect URL for logged in users
802
		if (isset($_REQUEST['redirect_url']) && OC_User::isLoggedIn()) {
803
			$location = OC_Helper::makeURLAbsolute(urldecode($_REQUEST['redirect_url']));
804
805
			// Deny the redirect if the URL contains a @
806
			// This prevents unvalidated redirects like ?redirect_url=:[email protected]
807
			if (strpos($location, '@') === false) {
808
				header('Location: ' . $location);
809
				return;
810
			}
811
		}
812
		// Handle WebDAV
813
		if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
814
			// not allowed any more to prevent people
815
			// mounting this root directly.
816
			// Users need to mount remote.php/webdav instead.
817
			header('HTTP/1.1 405 Method Not Allowed');
818
			header('Status: 405 Method Not Allowed');
819
			return;
820
		}
821
822
		// Redirect to index if the logout link is accessed without valid session
823
		// this is needed to prevent "Token expired" messages while login if a session is expired
824
		// @see https://github.com/owncloud/core/pull/8443#issuecomment-42425583
825
		if(isset($_GET['logout']) && !OC_User::isLoggedIn()) {
826
			header("Location: " . OC::$WEBROOT.(empty(OC::$WEBROOT) ? '/' : ''));
827
			return;
828
		}
829
830
		// Someone is logged in
831
		if (OC_User::isLoggedIn()) {
832
			OC_App::loadApps();
833
			OC_User::setupBackends();
834
			OC_Util::setupFS();
835
			if (isset($_GET["logout"]) and ($_GET["logout"])) {
836
				OC_JSON::callCheck();
837
				if (isset($_COOKIE['oc_token'])) {
838
					\OC::$server->getConfig()->deleteUserValue(OC_User::getUser(), 'login_token', $_COOKIE['oc_token']);
839
				}
840
				OC_User::logout();
841
				// redirect to webroot and add slash if webroot is empty
842
				header("Location: " . OC::$WEBROOT.(empty(OC::$WEBROOT) ? '/' : ''));
843
			} else {
844
				// Redirect to default application
845
				OC_Util::redirectToDefaultPage();
846
			}
847
		} else {
848
			// Not handled and not logged in
849
			self::handleLogin();
850
		}
851
	}
852
853
	protected static function handleAuthHeaders() {
854
		//copy http auth headers for apache+php-fcgid work around
855
		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
856
			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
857
		}
858
859
		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
860
		$vars = array(
861
			'HTTP_AUTHORIZATION', // apache+php-cgi work around
862
			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
863
		);
864
		foreach ($vars as $var) {
865
			if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
866
				list($name, $password) = explode(':', base64_decode($matches[1]), 2);
867
				$_SERVER['PHP_AUTH_USER'] = $name;
868
				$_SERVER['PHP_AUTH_PW'] = $password;
869
				break;
870
			}
871
		}
872
	}
873
874
	protected static function handleLogin() {
875
		OC_App::loadApps(array('prelogin'));
876
		$error = array();
877
		$messages = [];
878
879
		try {
880
			// auth possible via apache module?
881
			if (OC::tryApacheAuth()) {
882
				$error[] = 'apacheauthfailed';
883
			} // remember was checked after last login
884
			elseif (OC::tryRememberLogin()) {
885
				$error[] = 'invalidcookie';
886
			} // logon via web form
887
			elseif (OC::tryFormLogin()) {
888
				$error[] = 'invalidpassword';
889
			}
890
		} catch (\OC\User\LoginException $e) {
891
			$messages[] = $e->getMessage();
892
		} catch (\Exception $ex) {
893
			\OCP\Util::logException('handleLogin', $ex);
894
			// do not disclose information. show generic error
895
			$error[] = 'internalexception';
896
		}
897
898
		OC_Util::displayLoginPage(array_unique($error), $messages);
899
	}
900
901
	/**
902
	 * Remove outdated and therefore invalid tokens for a user
903
	 * @param string $user
904
	 */
905
	protected static function cleanupLoginTokens($user) {
906
		$config = \OC::$server->getConfig();
907
		$cutoff = time() - $config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
908
		$tokens = $config->getUserKeys($user, 'login_token');
909
		foreach ($tokens as $token) {
910
			$time = $config->getUserValue($user, 'login_token', $token);
911
			if ($time < $cutoff) {
912
				$config->deleteUserValue($user, 'login_token', $token);
913
			}
914
		}
915
	}
916
917
	/**
918
	 * Try to login a user via HTTP authentication
919
	 * @return bool|void
920
	 */
921
	protected static function tryApacheAuth() {
922
		$return = OC_User::handleApacheAuth();
923
924
		// if return is true we are logged in -> redirect to the default page
925
		if ($return === true) {
926
			$_REQUEST['redirect_url'] = \OC_Request::requestUri();
927
			OC_Util::redirectToDefaultPage();
928
			exit;
929
		}
930
931
		// in case $return is null apache based auth is not enabled
932
		return is_null($return) ? false : true;
933
	}
934
935
	/**
936
	 * Try to login a user using the remember me cookie.
937
	 * @return bool Whether the provided cookie was valid
938
	 */
939
	protected static function tryRememberLogin() {
940
		if (!isset($_COOKIE["oc_remember_login"])
941
			|| !isset($_COOKIE["oc_token"])
942
			|| !isset($_COOKIE["oc_username"])
943
			|| !$_COOKIE["oc_remember_login"]
944
			|| !OC_Util::rememberLoginAllowed()
945
		) {
946
			return false;
947
		}
948
949
		if (defined("DEBUG") && DEBUG) {
950
			OC_Log::write('core', 'Trying to login from cookie', OC_Log::DEBUG);
951
		}
952
953
		if(OC_User::userExists($_COOKIE['oc_username'])) {
954
			self::cleanupLoginTokens($_COOKIE['oc_username']);
955
			// verify whether the supplied "remember me" token was valid
956
			$granted = OC_User::loginWithCookie(
957
				$_COOKIE['oc_username'], $_COOKIE['oc_token']);
958
			if($granted === true) {
959
				OC_Util::redirectToDefaultPage();
960
				// doesn't return
961
			}
962
			OC_Log::write('core', 'Authentication cookie rejected for user ' .
963
				$_COOKIE['oc_username'], OC_Log::WARN);
964
			// if you reach this point you have changed your password
965
			// or you are an attacker
966
			// we can not delete tokens here because users may reach
967
			// this point multiple times after a password change
968
		}
969
970
		OC_User::unsetMagicInCookie();
971
		return true;
972
	}
973
974
	/**
975
	 * Tries to login a user using the form based authentication
976
	 * @return bool|void
977
	 */
978
	protected static function tryFormLogin() {
979
		if (!isset($_POST["user"]) || !isset($_POST['password'])) {
980
			return false;
981
		}
982
983
		if(!OC_Util::isCallRegistered()) {
984
			return false;
985
		}
986
		OC_App::loadApps();
987
988
		//setup extra user backends
989
		OC_User::setupBackends();
990
991
		if (OC_User::login($_POST["user"], $_POST["password"])) {
992
			$userId = OC_User::getUser();
993
994
			// setting up the time zone
995
			if (isset($_POST['timezone-offset'])) {
996
				self::$server->getSession()->set('timezone', $_POST['timezone-offset']);
997
				self::$server->getConfig()->setUserValue($userId, 'core', 'timezone', $_POST['timezone']);
998
			}
999
1000
			self::cleanupLoginTokens($userId);
1001
			if (!empty($_POST["remember_login"])) {
1002
				if (defined("DEBUG") && DEBUG) {
1003
					self::$server->getLogger()->debug('Setting remember login to cookie', array('app' => 'core'));
1004
				}
1005
				$token = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(32);
1006
				self::$server->getConfig()->setUserValue($userId, 'login_token', $token, time());
1007
				OC_User::setMagicInCookie($userId, $token);
1008
			} else {
1009
				OC_User::unsetMagicInCookie();
1010
			}
1011
			OC_Util::redirectToDefaultPage();
1012
			exit();
1013
		}
1014
		return true;
1015
	}
1016
}
1017
1018
if (!function_exists('get_temp_dir')) {
1019
	/**
1020
	 * Get the temporary dir to store uploaded data
1021
	 * @return null|string Path to the temporary directory or null
1022
	 */
1023
	function get_temp_dir() {
1024
		if ($temp = ini_get('upload_tmp_dir')) return $temp;
1025
		if ($temp = getenv('TMP')) return $temp;
1026
		if ($temp = getenv('TEMP')) return $temp;
1027
		if ($temp = getenv('TMPDIR')) return $temp;
1028
		$temp = tempnam(__FILE__, '');
1029
		if (file_exists($temp)) {
1030
			unlink($temp);
1031
			return dirname($temp);
1032
		}
1033
		if ($temp = sys_get_temp_dir()) return $temp;
1034
1035
		return null;
1036
	}
1037
}
1038
1039
OC::init();
1040