base.php 34.4 KB
Newer Older
1
2
<?php
/**
3
 * ownCloud
Jakob Sack's avatar
Jakob Sack committed
4
 *
5
6
 * @author Frank Karlitschek
 * @copyright 2012 Frank Karlitschek frank@owncloud.org
Jakob Sack's avatar
Jakob Sack committed
7
 *
8
9
10
11
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or any later version.
Jakob Sack's avatar
Jakob Sack committed
12
 *
13
 * This library is distributed in the hope that it will be useful,
Jakob Sack's avatar
Jakob Sack committed
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
17
 *
18
19
 * You should have received a copy of the GNU Affero General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
Jakob Sack's avatar
Jakob Sack committed
20
21
 *
 */
22

23
24
require_once 'public/constants.php';

25
26
/**
 * Class that is a namespace for all global OC variables
27
28
 * No, we can not put this class in its own file because it is used by
 * OC_autoload!
29
 */
30
class OC {
Bart Visscher's avatar
Bart Visscher committed
31
	/**
32
	 * Associative array for autoloading. classname => filename
Bart Visscher's avatar
Bart Visscher committed
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
	 */
	public static $CLASSPATH = array();
	/**
	 * The installation path for owncloud on the server (e.g. /srv/http/owncloud)
	 */
	public static $SERVERROOT = '';
	/**
	 * the current request path relative to the owncloud root (e.g. files/index.php)
	 */
	private static $SUBURI = '';
	/**
	 * the owncloud root path for http requests (e.g. owncloud/)
	 */
	public static $WEBROOT = '';
	/**
	 * The installation path of the 3rdparty folder on the server (e.g. /srv/http/owncloud/3rdparty)
	 */
	public static $THIRDPARTYROOT = '';
	/**
	 * the root path of the 3rdparty folder for http requests (e.g. owncloud/3rdparty)
	 */
	public static $THIRDPARTYWEBROOT = '';
	/**
	 * The installation path array of the apps folder on the server (e.g. /srv/http/owncloud) 'path' and
	 * web path in 'url'
	 */
	public static $APPSROOTS = array();
60
61
62

	public static $configDir;

Lukas Reschke's avatar
Lukas Reschke committed
63
	/**
Bart Visscher's avatar
Bart Visscher committed
64
65
66
	 * requested app
	 */
	public static $REQUESTEDAPP = '';
Lukas Reschke's avatar
Lukas Reschke committed
67

Bart Visscher's avatar
Bart Visscher committed
68
	/**
69
	 * check if ownCloud runs in cli mode
Bart Visscher's avatar
Bart Visscher committed
70
71
	 */
	public static $CLI = false;
Thomas Müller's avatar
Thomas Müller committed
72

Bart Visscher's avatar
Bart Visscher committed
73
	/**
74
	 * @var \OC\Autoloader $loader
Bart Visscher's avatar
Bart Visscher committed
75
	 */
76
	public static $loader = null;
Bart Visscher's avatar
Bart Visscher committed
77

78
79
80
81
82
	/**
	 * @var \OC\Server
	 */
	public static $server = null;

83
84
85
86
	/**
	 * @throws \RuntimeException when the 3rdparty directory is missing or
	 * the app path list is empty or contains an invalid path
	 */
87
	public static function initPaths() {
Bart Visscher's avatar
Bart Visscher committed
88
89
		// calculate the root directories
		OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
90
91
92
93

		// ensure we can find OC_Config
		set_include_path(
			OC::$SERVERROOT . '/lib' . PATH_SEPARATOR .
94
			get_include_path()
95
96
		);

97
98
99
		if(defined('PHPUNIT_CONFIG_DIR')) {
			self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/';
		} elseif(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) {
100
			self::$configDir = OC::$SERVERROOT . '/tests/config/';
101
102
103
104
105
		} else {
			self::$configDir = OC::$SERVERROOT . '/config/';
		}
		OC_Config::$object = new \OC\Config(self::$configDir);

Bart Visscher's avatar
Bart Visscher committed
106
		OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
107
108
109
110
		/**
		 * FIXME: The following line is required because of a cyclic dependency
		 *        on IRequest.
		 */
111
112
113
114
115
116
117
118
		$params = [
			'server' => [
				'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'],
				'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'],
			],
		];
		$fakeRequest = new \OC\AppFramework\Http\Request($params, null, new \OC\AllConfig(new \OC\SystemConfig()));
		$scriptName = $fakeRequest->getScriptName();
Bart Visscher's avatar
Bart Visscher committed
119
120
121
122
123
124
125
126
127
128
129
		if (substr($scriptName, -1) == '/') {
			$scriptName .= 'index.php';
			//make sure suburi follows the same rules as scriptName
			if (substr(OC::$SUBURI, -9) != 'index.php') {
				if (substr(OC::$SUBURI, -1) != '/') {
					OC::$SUBURI = OC::$SUBURI . '/';
				}
				OC::$SUBURI = OC::$SUBURI . 'index.php';
			}
		}

130
131
132
133
134
		if (OC::$CLI) {
			OC::$WEBROOT = OC_Config::getValue('overwritewebroot', '');
		} else {
			if (substr($scriptName, 0 - strlen(OC::$SUBURI)) === OC::$SUBURI) {
				OC::$WEBROOT = substr($scriptName, 0, 0 - strlen(OC::$SUBURI));
Bart Visscher's avatar
Bart Visscher committed
135

136
137
138
139
140
141
142
143
144
				if (OC::$WEBROOT != '' && OC::$WEBROOT[0] !== '/') {
					OC::$WEBROOT = '/' . OC::$WEBROOT;
				}
			} else {
				// The scriptName is not ending with OC::$SUBURI
				// This most likely means that we are calling from CLI.
				// However some cron jobs still need to generate
				// a web URL, so we use overwritewebroot as a fallback.
				OC::$WEBROOT = OC_Config::getValue('overwritewebroot', '');
145
			}
Bart Visscher's avatar
Bart Visscher committed
146
147
148
		}

		// search the 3rdparty folder
149
150
151
		OC::$THIRDPARTYROOT = OC_Config::getValue('3rdpartyroot', null);
		OC::$THIRDPARTYWEBROOT = OC_Config::getValue('3rdpartyurl', null);
		
152
		if (empty(OC::$THIRDPARTYROOT) && empty(OC::$THIRDPARTYWEBROOT)) {
153
154
155
156
157
158
159
160
			if (file_exists(OC::$SERVERROOT . '/3rdparty')) {
				OC::$THIRDPARTYROOT = OC::$SERVERROOT;
				OC::$THIRDPARTYWEBROOT = OC::$WEBROOT;
			} elseif (file_exists(OC::$SERVERROOT . '/../3rdparty')) {
				OC::$THIRDPARTYWEBROOT = rtrim(dirname(OC::$WEBROOT), '/');
				OC::$THIRDPARTYROOT = rtrim(dirname(OC::$SERVERROOT), '/');
			}
		}
161
		if (empty(OC::$THIRDPARTYROOT) || !file_exists(OC::$THIRDPARTYROOT)) {
162
			throw new \RuntimeException('3rdparty directory not found! Please put the ownCloud 3rdparty'
163
164
				. ' folder in the ownCloud folder or the folder above.'
				. ' You can also configure the location in the config.php file.');
Bart Visscher's avatar
Bart Visscher committed
165
		}
166
		
Bart Visscher's avatar
Bart Visscher committed
167
168
169
170
171
172
173
174
175
176
177
178
179
		// search the apps folder
		$config_paths = OC_Config::getValue('apps_paths', array());
		if (!empty($config_paths)) {
			foreach ($config_paths as $paths) {
				if (isset($paths['url']) && isset($paths['path'])) {
					$paths['url'] = rtrim($paths['url'], '/');
					$paths['path'] = rtrim($paths['path'], '/');
					OC::$APPSROOTS[] = $paths;
				}
			}
		} elseif (file_exists(OC::$SERVERROOT . '/apps')) {
			OC::$APPSROOTS[] = array('path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true);
		} elseif (file_exists(OC::$SERVERROOT . '/../apps')) {
Bart Visscher's avatar
Bart Visscher committed
180
181
182
183
184
			OC::$APPSROOTS[] = array(
				'path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps',
				'url' => '/apps',
				'writable' => true
			);
Bart Visscher's avatar
Bart Visscher committed
185
186
187
		}

		if (empty(OC::$APPSROOTS)) {
188
			throw new \RuntimeException('apps directory not found! Please put the ownCloud apps folder in the ownCloud folder'
189
				. ' or the folder above. You can also configure the location in the config.php file.');
Bart Visscher's avatar
Bart Visscher committed
190
191
		}
		$paths = array();
192
		foreach (OC::$APPSROOTS as $path) {
Bart Visscher's avatar
Bart Visscher committed
193
			$paths[] = $path['path'];
194
195
196
197
198
			if (!is_dir($path['path'])) {
				throw new \RuntimeException(sprintf('App directory "%s" not found! Please put the ownCloud apps folder in the'
					. ' ownCloud folder or the folder above. You can also configure the location in the'
					. ' config.php file.', $path['path']));
			}
199
		}
Bart Visscher's avatar
Bart Visscher committed
200
201
202

		// set the right include path
		set_include_path(
203
			OC::$SERVERROOT . '/lib/private' . PATH_SEPARATOR .
204
205
			OC::$SERVERROOT . '/config' . PATH_SEPARATOR .
			OC::$THIRDPARTYROOT . '/3rdparty' . PATH_SEPARATOR .
206
			implode(PATH_SEPARATOR, $paths) . PATH_SEPARATOR .
207
208
			get_include_path() . PATH_SEPARATOR .
			OC::$SERVERROOT
Bart Visscher's avatar
Bart Visscher committed
209
210
		);
	}
211

212
	public static function checkConfig() {
213
		$l = \OC::$server->getL10N('lib');
214
215
216
217
218
219
220
221
222

		// Create config in case it does not already exists
		$configFilePath = self::$configDir .'/config.php';
		if(!file_exists($configFilePath)) {
			@touch($configFilePath);
		}

		// Check if config is writable
		$configFileWritable = is_writable($configFilePath);
Lukas Reschke's avatar
Lukas Reschke committed
223
224
		if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled()
			|| !$configFileWritable && \OCP\Util::needUpgrade()) {
225
			if (self::$CLI) {
226
227
				echo $l->t('Cannot write into "config" directory!')."\n";
				echo $l->t('This can usually be fixed by giving the webserver write access to the config directory')."\n";
228
				echo "\n";
229
				echo $l->t('See %s', array(\OC_Helper::linkToDocs('admin-dir_permissions')))."\n";
230
231
232
				exit;
			} else {
				OC_Template::printErrorPage(
233
234
235
236
					$l->t('Cannot write into "config" directory!'),
					$l->t('This can usually be fixed by '
					. '%sgiving the webserver write access to the config directory%s.',
					 array('<a href="'.\OC_Helper::linkToDocs('admin-dir_permissions').'" target="_blank">', '</a>'))
237
238
				);
			}
239
240
241
		}
	}

242
	public static function checkInstalled() {
243
244
245
		if (defined('OC_CONSOLE')) {
			return;
		}
Bart Visscher's avatar
Bart Visscher committed
246
		// Redirect to installer if not installed
247
		if (!\OC::$server->getSystemConfig()->getValue('installed', false) && OC::$SUBURI != '/index.php') {
248
249
			if (OC::$CLI) {
				throw new Exception('Not installed');
250
			} else {
251
252
				$url = 'http://' . $_SERVER['SERVER_NAME'] . OC::$WEBROOT . '/index.php';
				header('Location: ' . $url);
Bart Visscher's avatar
Bart Visscher committed
253
254
255
256
257
			}
			exit();
		}
	}

258
	public static function checkMaintenanceMode() {
259
		// Allow ajax update script to execute without being stopped
260
		if (\OC::$server->getSystemConfig()->getValue('maintenance', false) && OC::$SUBURI != '/core/ajax/update.php') {
261
262
263
264
265
266
			// send http status 503
			header('HTTP/1.1 503 Service Temporarily Unavailable');
			header('Status: 503 Service Temporarily Unavailable');
			header('Retry-After: 120');

			// render error page
267
			$tmpl = new OC_Template('', 'update.user', 'guest');
kondou's avatar
kondou committed
268
			OC_Util::addscript('maintenance-check');
269
270
			$tmpl->printPage();
			die();
271
272
273
		}
	}

274
275
276
	public static function checkSingleUserMode() {
		$user = OC_User::getUserSession()->getUser();
		$group = OC_Group::getManager()->get('admin');
277
		if ($user && \OC::$server->getSystemConfig()->getValue('singleuser', false) && !$group->inGroup($user)) {
278
279
280
281
282
283
284
285
286
287
288
289
			// send http status 503
			header('HTTP/1.1 503 Service Temporarily Unavailable');
			header('Status: 503 Service Temporarily Unavailable');
			header('Retry-After: 120');

			// render error page
			$tmpl = new OC_Template('', 'singleuser.user', 'guest');
			$tmpl->printPage();
			die();
		}
	}

290
291
292
293
	/**
	 * check if the instance needs to preform an upgrade
	 *
	 * @return bool
294
	 * @deprecated use \OCP\Util::needUpgrade() instead
295
296
	 */
	public static function needUpgrade() {
Vincent Petry's avatar
Vincent Petry committed
297
		return \OCP\Util::needUpgrade();
298
299
	}

Lukas Reschke's avatar
Lukas Reschke committed
300
301
302
303
304
	/**
	 * Checks if the version requires an update and shows
	 * @param bool $showTemplate Whether an update screen should get shown
	 * @return bool|void
	 */
305
	public static function checkUpgrade($showTemplate = true) {
Vincent Petry's avatar
Vincent Petry committed
306
		if (\OCP\Util::needUpgrade()) {
307
308
			$systemConfig = \OC::$server->getSystemConfig();
			if ($showTemplate && !$systemConfig->getValue('maintenance', false)) {
Vincent Petry's avatar
Vincent Petry committed
309
				$version = OC_Util::getVersion();
310
311
				$oldTheme = $systemConfig->getValue('theme');
				$systemConfig->setValue('theme', '');
312
313
314
315
				OC_Util::addScript('config'); // needed for web root
				OC_Util::addScript('update');
				$tmpl = new OC_Template('', 'update.admin', 'guest');
				$tmpl->assign('version', OC_Util::getVersionString());
Vincent Petry's avatar
Vincent Petry committed
316
317
318
319
320
321
322

				// get third party apps
				$apps = OC_App::getEnabledApps();
				$incompatibleApps = array();
				foreach ($apps as $appId) {
					$info = OC_App::getAppInfo($appId);
					if(!OC_App::isAppCompatible($version, $info)) {
323
						$incompatibleApps[] = $info;
Vincent Petry's avatar
Vincent Petry committed
324
325
326
327
328
					}
				}
				$tmpl->assign('appList', $incompatibleApps);
				$tmpl->assign('productName', 'ownCloud'); // for now
				$tmpl->assign('oldTheme', $oldTheme);
329
330
331
332
333
334
335
336
337
				$tmpl->printPage();
				exit();
			} else {
				return true;
			}
		}
		return false;
	}

338
	public static function initTemplateEngine() {
Bart Visscher's avatar
Bart Visscher committed
339
		// Add the stuff we need always
340
341
342
343
344
345
346
347
348
349
350
351
352
353
		// following logic will import all vendor libraries that are
		// specified in core/js/core.json
		$fileContent = file_get_contents(OC::$SERVERROOT . '/core/js/core.json');
		if($fileContent !== false) {
			$coreDependencies = json_decode($fileContent, true);
			foreach($coreDependencies['vendor'] as $vendorLibrary) {
				// remove trailing ".js" as addVendorScript will append it
				OC_Util::addVendorScript(
					substr($vendorLibrary, 0, strlen($vendorLibrary) - 3));
			}
		} else {
			throw new \Exception('Cannot read core/js/core.json');
		}

354
		OC_Util::addScript("placeholders");
Bart Visscher's avatar
Bart Visscher committed
355
		OC_Util::addScript("jquery-tipsy");
356
		OC_Util::addScript("compatibility");
357
		OC_Util::addScript("jquery.ocdialog");
Bart Visscher's avatar
Bart Visscher committed
358
359
		OC_Util::addScript("oc-dialogs");
		OC_Util::addScript("js");
360
		OC_Util::addScript("l10n");
Vincent Petry's avatar
Vincent Petry committed
361
		OC_Util::addTranslations("core");
362
		OC_Util::addScript("octemplate");
Bart Visscher's avatar
Bart Visscher committed
363
364
365
		OC_Util::addScript("eventsource");
		OC_Util::addScript("config");
		//OC_Util::addScript( "multiselect" );
366
		OC_Util::addScript('search', 'search');
367
		OC_Util::addScript("oc-requesttoken");
Bernhard Posselt's avatar
Bernhard Posselt committed
368
		OC_Util::addScript("apps");
Morris Jobke's avatar
Morris Jobke committed
369
		OC_Util::addVendorScript('snapjs/dist/latest/snap');
Bart Visscher's avatar
Bart Visscher committed
370

371
		// avatars
372
		if (\OC::$server->getSystemConfig()->getValue('enable_avatars', true) === true) {
373
			\OC_Util::addScript('placeholder');
Morris Jobke's avatar
Morris Jobke committed
374
			\OC_Util::addVendorScript('blueimp-md5/js/md5');
375
376
377
			\OC_Util::addScript('jquery.avatar');
			\OC_Util::addScript('avatar');
		}
kondou's avatar
kondou committed
378

Bart Visscher's avatar
Bart Visscher committed
379
		OC_Util::addStyle("styles");
380
		OC_Util::addStyle("header");
381
		OC_Util::addStyle("mobile");
382
		OC_Util::addStyle("icons");
383
		OC_Util::addStyle("fonts");
384
		OC_Util::addStyle("apps");
385
		OC_Util::addStyle("fixes");
Bart Visscher's avatar
Bart Visscher committed
386
		OC_Util::addStyle("multiselect");
387
388
		OC_Util::addVendorStyle('jquery-ui/themes/base/jquery-ui');
		OC_Util::addStyle('jquery-ui-fixes');
Bart Visscher's avatar
Bart Visscher committed
389
		OC_Util::addStyle("jquery-tipsy");
390
		OC_Util::addStyle("jquery.ocdialog");
Bart Visscher's avatar
Bart Visscher committed
391
392
	}

393
	public static function initSession() {
Bart Visscher's avatar
Bart Visscher committed
394
		// prevents javascript from accessing php session cookies
395
		ini_set('session.cookie_httponly', true);
Bart Visscher's avatar
Bart Visscher committed
396

397
		// set the cookie path to the ownCloud directory
398
		$cookie_path = OC::$WEBROOT ? : '/';
399
		ini_set('session.cookie_path', $cookie_path);
400

401
402
403
		// Let the session name be changed in the initSession Hook
		$sessionName = OC_Util::getInstanceId();

404
		try {
405
406
			// Allow session apps to create a custom session object
			$useCustomSession = false;
Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
407
408
409
410
411
412
			$session = self::$server->getSession();
			OC_Hook::emit('OC', 'initSession', array('session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession));
			if($useCustomSession) {
				// use the session reference as the new Session
				self::$server->setSession($session);
			} else {
413
				// set the session name to the instance id - which is unique
Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
414
				self::$server->setSession(new \OC\Session\Internal($sessionName));
415
			}
Robin Appelman's avatar
Robin Appelman committed
416
			// if session cant be started break with http 500 error
417
		} catch (Exception $e) {
418
			\OCP\Util::logException('base', $e);
419
420
421
			//show the user a detailed error page
			OC_Response::setStatus(OC_Response::STATUS_INTERNAL_SERVER_ERROR);
			OC_Template::printExceptionErrorPage($e);
422
		}
Bart Visscher's avatar
Bart Visscher committed
423

424
		$sessionLifeTime = self::getSessionLifeTime();
Bart Visscher's avatar
Bart Visscher committed
425
		// regenerate session id periodically to avoid session fixation
Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
426
427
428
429
430
431
432
		/**
		 * @var \OCP\ISession $session
		 */
		$session = self::$server->getSession();
		if (!$session->exists('SID_CREATED')) {
			$session->set('SID_CREATED', time());
		} else if (time() - $session->get('SID_CREATED') > $sessionLifeTime / 2) {
Bart Visscher's avatar
Bart Visscher committed
433
			session_regenerate_id(true);
Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
434
			$session->set('SID_CREATED', time());
Bart Visscher's avatar
Bart Visscher committed
435
436
437
		}

		// session timeout
Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
438
		if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
Bart Visscher's avatar
Bart Visscher committed
439
			if (isset($_COOKIE[session_name()])) {
440
				setcookie(session_name(), '', time() - 42000, $cookie_path);
Bart Visscher's avatar
Bart Visscher committed
441
442
443
444
445
			}
			session_unset();
			session_destroy();
			session_start();
		}
Robin Appelman's avatar
Robin Appelman committed
446

Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
447
		$session->set('LAST_ACTIVITY', time());
Bart Visscher's avatar
Bart Visscher committed
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
458
459
460
	public static function loadAppClassPaths() {
		foreach (OC_APP::getEnabledApps() as $app) {
			$file = OC_App::getAppPath($app) . '/appinfo/classpath.php';
			if (file_exists($file)) {
Bernhard Posselt's avatar
Bernhard Posselt committed
461
462
463
464
				require_once $file;
			}
		}
	}
465
466


467
	public static function init() {
Bart Visscher's avatar
Bart Visscher committed
468
		// register autoloader
Robin Appelman's avatar
Robin Appelman committed
469
		$loaderStart = microtime(true);
470
		require_once __DIR__ . '/autoloader.php';
471
		self::$loader = new \OC\Autoloader();
472
		spl_autoload_register(array(self::$loader, 'load'));
Robin Appelman's avatar
Robin Appelman committed
473
		$loaderEnd = microtime(true);
Bart Visscher's avatar
Bart Visscher committed
474

475
476
		self::$CLI = (php_sapi_name() == 'cli');

477
478
479
480
481
482
483
		try {
			self::initPaths();
			// setup 3rdparty autoloader
			$vendorAutoLoad = OC::$THIRDPARTYROOT . '/3rdparty/autoload.php';
			if (!file_exists($vendorAutoLoad)) {
				throw new \RuntimeException('Composer autoloader not found, unable to continue. Check the folder "3rdparty".');
			}
484
			require_once $vendorAutoLoad;
485
486

		} catch (\RuntimeException $e) {
487
			OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
488
489
			// we can't use the template error page here, because this needs the
			// DI container which isn't available yet
490
			print($e->getMessage());
491
			exit();
492
493
494
		}

		// setup the basic server
Lukas Reschke's avatar
Lukas Reschke committed
495
		self::$server = new \OC\Server(\OC::$WEBROOT);
Robin Appelman's avatar
Robin Appelman committed
496
		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
Robin Appelman's avatar
Robin Appelman committed
497
		\OC::$server->getEventLogger()->start('boot', 'Initialize');
Bart Visscher's avatar
Bart Visscher committed
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522

		// set some stuff
		//ob_start();
		error_reporting(E_ALL | E_STRICT);
		if (defined('DEBUG') && DEBUG) {
			ini_set('display_errors', 1);
		}

		date_default_timezone_set('UTC');
		ini_set('arg_separator.output', '&amp;');

		//try to configure php to enable big file uploads.
		//this doesn´t work always depending on the webserver and php configuration.
		//Let´s try to overwrite some defaults anyways

		//try to set the maximum execution time to 60min
		@set_time_limit(3600);
		@ini_set('max_execution_time', 3600);
		@ini_set('max_input_time', 3600);

		//try to set the maximum filesize to 10G
		@ini_set('upload_max_filesize', '10G');
		@ini_set('post_max_size', '10G');
		@ini_set('file_uploads', '50');

523
		self::handleAuthHeaders();
524
		self::registerAutoloaderCache();
525

526
527
		// initialize intl fallback is necessary
		\Patchwork\Utf8\Bootup::initIntl();
528
		OC_Util::isSetLocaleWorking();
529

530
		if (!defined('PHPUNIT_RUN')) {
531
			OC\Log\ErrorHandler::setLogger(OC_Log::$object);
532
			if (defined('DEBUG') and DEBUG) {
533
				OC\Log\ErrorHandler::register(true);
534
535
536
537
				set_exception_handler(array('OC_Template', 'printExceptionErrorPage'));
			} else {
				OC\Log\ErrorHandler::register();
			}
538
539
		}

Bart Visscher's avatar
Bart Visscher committed
540
		// register the stream wrappers
541
542
543
		stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir');
		stream_wrapper_register('static', 'OC\Files\Stream\StaticStream');
		stream_wrapper_register('close', 'OC\Files\Stream\Close');
544
		stream_wrapper_register('quota', 'OC\Files\Stream\Quota');
545
		stream_wrapper_register('oc', 'OC\Files\Stream\OC');
Bart Visscher's avatar
Bart Visscher committed
546

Robin Appelman's avatar
Robin Appelman committed
547
		\OC::$server->getEventLogger()->start('init_session', 'Initialize session');
548
		OC_App::loadApps(array('session'));
549
		if (!self::$CLI) {
550
			self::initSession();
551
		}
Robin Appelman's avatar
Robin Appelman committed
552
		\OC::$server->getEventLogger()->end('init_session');
Vincent Petry's avatar
Vincent Petry committed
553
		self::initTemplateEngine();
554
555
		self::checkConfig();
		self::checkInstalled();
556

557
		OC_Response::addSecurityHeaders();
558
559
560
		if(self::$server->getRequest()->getServerProtocol() === 'https') {
			ini_set('session.cookie_secure', true);
		}
Bart Visscher's avatar
Bart Visscher committed
561

562
		$errors = OC_Util::checkServer(\OC::$server->getConfig());
Bart Visscher's avatar
Bart Visscher committed
563
		if (count($errors) > 0) {
564
			if (self::$CLI) {
565
566
				// Convert l10n string into regular string for usage in database
				$staticErrors = [];
567
				foreach ($errors as $error) {
568
					echo $error['error'] . "\n";
569
					echo $error['hint'] . "\n\n";
Lukas Reschke's avatar
Lukas Reschke committed
570
571
572
573
					$staticErrors[] = [
						'error' => (string) $error['error'],
						'hint' => (string) $error['hint'],
					];
574
				}
575
576
577
578
579
580

				try {
					\OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
				} catch(\Exception $e) {
					echo('Writing to database failed');
				}
581
				exit(1);
582
			} else {
583
				OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
584
				OC_Template::printGuestPage('', 'error', array('errors' => $errors));
585
				exit;
586
			}
587
588
		} elseif(self::$CLI && \OC::$server->getConfig()->getSystemValue('installed', false)) {
				\OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
Bart Visscher's avatar
Bart Visscher committed
589
590
		}

591
592
593
594
		//try to set the session lifetime
		$sessionLifeTime = self::getSessionLifeTime();
		@ini_set('gc_maxlifetime', (string)$sessionLifeTime);

595
		$systemConfig = \OC::$server->getSystemConfig();
596

Bart Visscher's avatar
Bart Visscher committed
597
		// User and Groups
598
		if (!$systemConfig->getValue("installed", false)) {
Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
599
			self::$server->getSession()->set('user_id', '');
Bart Visscher's avatar
Bart Visscher committed
600
601
602
603
		}

		OC_User::useBackend(new OC_User_Database());
		OC_Group::useBackend(new OC_Group_Database());
Arthur Schiwon's avatar
Arthur Schiwon committed
604

Bart Visscher's avatar
Bart Visscher committed
605
		//setup extra user backends
606
607
608
		if (!self::checkUpgrade(false)) {
			OC_User::setupBackends();
		}
Bart Visscher's avatar
Bart Visscher committed
609
610
611

		self::registerCacheHooks();
		self::registerFilesystemHooks();
612
		self::registerPreviewHooks();
Bart Visscher's avatar
Bart Visscher committed
613
		self::registerShareHooks();
614
		self::registerLogRotate();
615
		self::registerLocalAddressBook();
Bart Visscher's avatar
Bart Visscher committed
616
617

		//make sure temporary files are cleaned up
618
619
		$tmpManager = \OC::$server->getTempManager();
		register_shutdown_function(array($tmpManager, 'clean'));
Bart Visscher's avatar
Bart Visscher committed
620

621
622
		if ($systemConfig->getValue('installed', false) && !self::checkUpgrade(false)) {
			if (\OC::$server->getConfig()->getAppValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') {
Bart Visscher's avatar
Bart Visscher committed
623
624
625
				OC_Util::addScript('backgroundjobs');
			}
		}
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
631
632
633
634
635
636
637
			header('HTTP/1.1 503 Service Temporarily Unavailable');
			header('Status: 503 Service Temporarily Unavailable');
			OC_Template::printErrorPage(
				$l->t('Sample configuration detected'),
				$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')
			);
			return;
		}
638

639
640
641
642
643
644
		$request = \OC::$server->getRequest();
		$host = $request->getInsecureServerHost();
		/**
		 * if the host passed in headers isn't trusted
		 * FIXME: Should not be in here at all :see_no_evil:
		 */
645
		if (!OC::$CLI
646
647
648
			// overwritehost is always trusted, workaround to not have to make
			// \OC\AppFramework\Http\Request::getOverwriteHost public
			&& self::$server->getConfig()->getSystemValue('overwritehost') === ''
Lukas Reschke's avatar
Lukas Reschke committed
649
			&& !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host)
650
			&& self::$server->getConfig()->getSystemValue('installed', false)
651
652
653
		) {
			header('HTTP/1.1 400 Bad Request');
			header('Status: 400 Bad Request');
654

655
			$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
656
			$tmpl->assign('domain', $request->server['SERVER_NAME']);
657
			$tmpl->printPage();
658
659

			exit();
660
		}
Robin Appelman's avatar
Robin Appelman committed
661
		\OC::$server->getEventLogger()->end('boot');
Bart Visscher's avatar
Bart Visscher committed
662
663
	}

664
665
666
667
668
669
670
671
	private static function registerLocalAddressBook() {
		self::$server->getContactsManager()->register(function() {
			$userManager = \OC::$server->getUserManager();
			\OC::$server->getContactsManager()->registerAddressBook(
				new \OC\Contacts\LocalAddressBook($userManager));
		});
	}

Bart Visscher's avatar
Bart Visscher committed
672
673
674
	/**
	 * register hooks for the cache
	 */
675
	public static function registerCacheHooks() {
676
		if (\OC::$server->getSystemConfig()->getValue('installed', false) && !\OCP\Util::needUpgrade()) { //don't try to do this before we are properly setup
677
			\OCP\BackgroundJob::registerJob('OC\Cache\FileGlobalGC');
678

Thomas Tanghus's avatar
Thomas Tanghus committed
679
680
			// NOTE: This will be replaced to use OCP
			$userSession = \OC_User::getUserSession();
681
			$userSession->listen('postLogin', '\OC\Cache\File', 'loginListener');
682
		}
Bart Visscher's avatar
Bart Visscher committed
683
684
	}

685
686
687
688
	/**
	 * register hooks for the cache
	 */
	public static function registerLogRotate() {
689
690
		$systemConfig = \OC::$server->getSystemConfig();
		if ($systemConfig->getValue('installed', false) && $systemConfig->getValue('log_rotate_size', false) && !\OCP\Util::needUpgrade()) {
691
			//don't try to do this before we are properly setup
692
			//use custom logfile path if defined, otherwise use default of owncloud.log in data directory
693
			\OCP\BackgroundJob::registerJob('OC\Log\Rotate', $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/owncloud.log'));
694
695
696
		}
	}

Bart Visscher's avatar
Bart Visscher committed
697
698
699
	/**
	 * register hooks for the filesystem
	 */
700
	public static function registerFilesystemHooks() {
Bart Visscher's avatar
Bart Visscher committed
701
		// Check for blacklisted files
702
703
		OC_Hook::connect('OC_Filesystem', 'write', 'OC\Files\Filesystem', 'isBlacklisted');
		OC_Hook::connect('OC_Filesystem', 'rename', 'OC\Files\Filesystem', 'isBlacklisted');
Bart Visscher's avatar
Bart Visscher committed
704
705
	}

706
707
708
709
	/**
	 * register hooks for previews
	 */
	public static function registerPreviewHooks() {
Georg Ehrke's avatar
Georg Ehrke committed
710
		OC_Hook::connect('OC_Filesystem', 'post_write', 'OC\Preview', 'post_write');
Bjoern Schiessle's avatar
Bjoern Schiessle committed
711
		OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'prepare_delete_files');
712
713
		OC_Hook::connect('\OCP\Versions', 'preDelete', 'OC\Preview', 'prepare_delete');
		OC_Hook::connect('\OCP\Trashbin', 'preDelete', 'OC\Preview', 'prepare_delete');
Bjoern Schiessle's avatar
Bjoern Schiessle committed
714
		OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC\Preview', 'post_delete_files');
715
716
		OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete');
		OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete');
717
718
	}

Bart Visscher's avatar
Bart Visscher committed
719
720
721
	/**
	 * register hooks for sharing
	 */
722
	public static function registerShareHooks() {
723
		if (\OC::$server->getSystemConfig()->getValue('installed')) {
724
725
726
727
			OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share\Hooks', 'post_deleteUser');
			OC_Hook::connect('OC_User', 'post_addToGroup', 'OC\Share\Hooks', 'post_addToGroup');
			OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share\Hooks', 'post_removeFromGroup');
			OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share\Hooks', 'post_deleteGroup');
728
		}
Bart Visscher's avatar
Bart Visscher committed
729
730
	}

731
732
733
734
735
736
737
	protected static function registerAutoloaderCache() {
		// The class loader takes an optional low-latency cache, which MUST be
		// namespaced. The instanceid is used for namespacing, but might be
		// unavailable at this point. Futhermore, it might not be possible to
		// generate an instanceid via \OC_Util::getInstanceId() because the
		// config file may not be writable. As such, we only register a class
		// loader cache if instanceid is available without trying to create one.
738
		$instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
739
740
		if ($instanceId) {
			try {
741
742
				$memcacheFactory = \OC::$server->getMemCacheFactory();
				self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader'));
743
744
745
746
747
			} catch (\Exception $ex) {
			}
		}
	}

Bart Visscher's avatar
Bart Visscher committed
748
	/**
749
	 * Handle the request
Bart Visscher's avatar
Bart Visscher committed
750
	 */
751
	public static function handleRequest() {
752

Robin Appelman's avatar
Robin Appelman committed
753
		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
754
		$systemConfig = \OC::$server->getSystemConfig();
Bernhard Posselt's avatar
Bernhard Posselt committed
755
756
757
		// load all the classpaths from the enabled apps so they are available
		// in the routing files of each app
		OC::loadAppClassPaths();
758

759
		// Check if ownCloud is installed or in maintenance (update) mode
760
		if (!$systemConfig->getValue('installed', false)) {
Lukas Reschke's avatar
Lukas Reschke committed
761
			\OC::$server->getSession()->clear();
762
763
			$setupHelper = new OC\Setup(\OC::$server->getConfig(), \OC::$server->getIniWrapper(), \OC::$server->getL10N('lib'), new \OC_Defaults());
			$controller = new OC\Core\Setup\Controller($setupHelper);
764
			$controller->run($_POST);
765
766
			exit();
		}
767

768
		$request = \OC::$server->getRequest()->getPathInfo();
769
		if (substr($request, -3) !== '.js') { // we need these files during the upgrade
770
771
772
			self::checkMaintenanceMode();
			self::checkUpgrade();
		}
773

774
775
776
		// Always load authentication apps
		OC_App::loadApps(['authentication']);

777
		// Load minimum set of apps
778
779
780
		if (!self::checkUpgrade(false)
			&& !$systemConfig->getValue('maintenance', false)
			&& !\OCP\Util::needUpgrade()) {
781
782
783
784
			// For logged-in users: Load everything
			if(OC_User::isLoggedIn()) {
				OC_App::loadApps();
			} else {
785
				// For guests: Load only filesystem and logging
786
787
788
789
790
				OC_App::loadApps(array('filesystem', 'logging'));
				\OC_User::tryBasicAuthLogin();
			}
		}

791
		if (!self::$CLI and (!isset($_GET["logout"]) or ($_GET["logout"] !== 'true'))) {
792
			try {
793
				if (!$systemConfig->getValue('maintenance', false) && !\OCP\Util::needUpgrade()) {
794
					OC_App::loadApps(array('filesystem', 'logging'));
795
					OC_App::loadApps();
796
				}
797
				self::checkSingleUserMode();
798
				OC_Util::setupFS();
799
				OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
800
801
802
803
804
805
806
				return;
			} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
				//header('HTTP/1.0 404 Not Found');
			} catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
				OC_Response::setStatus(405);
				return;
			}
Bart Visscher's avatar
Bart Visscher committed
807
		}
808

809
810
811
		// Handle redirect URL for logged in users
		if (isset($_REQUEST['redirect_url']) && OC_User::isLoggedIn()) {
			$location = OC_Helper::makeURLAbsolute(urldecode($_REQUEST['redirect_url']));
Robin Appelman's avatar
Robin Appelman committed
812

Lukas Reschke's avatar
Lukas Reschke committed
813
814
			// Deny the redirect if the URL contains a @
			// This prevents unvalidated redirects like ?redirect_url=:user@domain.com
815
			if (strpos($location, '@') === false) {
Lukas Reschke's avatar
Lukas Reschke committed
816
817
818
				header('Location: ' . $location);
				return;
			}
819
820
821
		}
		// Handle WebDAV
		if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
822
823
824
825
826
			// not allowed any more to prevent people
			// mounting this root directly.
			// Users need to mount remote.php/webdav instead.
			header('HTTP/1.1 405 Method Not Allowed');
			header('Status: 405 Method Not Allowed');
827
828
829
			return;
		}

830
831
832
833
834
835
836
837
		// Redirect to index if the logout link is accessed without valid session
		// this is needed to prevent "Token expired" messages while login if a session is expired
		// @see https://github.com/owncloud/core/pull/8443#issuecomment-42425583
		if(isset($_GET['logout']) && !OC_User::isLoggedIn()) {
			header("Location: " . OC::$WEBROOT.(empty(OC::$WEBROOT) ? '/' : ''));
			return;
		}

Lukas Reschke's avatar
Lukas Reschke committed
838
		// Someone is logged in
Bart Visscher's avatar
Bart Visscher committed
839
840
841
		if (OC_User::isLoggedIn()) {
			OC_App::loadApps();
			OC_User::setupBackends();
842
			OC_Util::setupFS();
Bart Visscher's avatar
Bart Visscher committed
843
			if (isset($_GET["logout"]) and ($_GET["logout"])) {
844
				OC_JSON::callCheck();
Bart Visscher's avatar
Bart Visscher committed
845
				if (isset($_COOKIE['oc_token'])) {
846
					\OC::$server->getConfig()->deleteUserValue(OC_User::getUser(), 'login_token', $_COOKIE['oc_token']);
Bart Visscher's avatar
Bart Visscher committed
847
848
				}
				OC_User::logout();
849
850
				// redirect to webroot and add slash if webroot is empty
				header("Location: " . OC::$WEBROOT.(empty(OC::$WEBROOT) ? '/' : ''));
Bart Visscher's avatar
Bart Visscher committed
851
			} else {
Lukas Reschke's avatar
Lukas Reschke committed
852
853
				// Redirect to default application
				OC_Util::redirectToDefaultPage();
Bart Visscher's avatar
Bart Visscher committed
854
			}
Lukas Reschke's avatar
Lukas Reschke committed
855
856
857
		} else {
			// Not handled and not logged in
			self::handleLogin();
Bart Visscher's avatar
Bart Visscher committed
858
859
860
		}
	}

861
862
863
864
865
866
867
868
869
870
871
872
873
874
	protected static function handleAuthHeaders() {
		//copy http auth headers for apache+php-fcgid work around
		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
		}

		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
		$vars = array(
			'HTTP_AUTHORIZATION', // apache+php-cgi work around
			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
		);
		foreach ($vars as $var) {
			if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
				list($name, $password) = explode(':', base64_decode($matches[1]), 2);
Lukas Reschke's avatar
Lukas Reschke committed
875
876
				$_SERVER['PHP_AUTH_USER'] = $name;
				$_SERVER['PHP_AUTH_PW'] = $password;
877
878
879
880
881
				break;
			}
		}
	}

882
	protected static function handleLogin() {
Bart Visscher's avatar
Bart Visscher committed
883
884
		OC_App::loadApps(array('prelogin'));
		$error = array();
885
		$messages = [];
886

887
888
889
890
891
892
893
894
895
896
897
898
899
		try {
			// auth possible via apache module?
			if (OC::tryApacheAuth()) {
				$error[] = 'apacheauthfailed';
			} // remember was checked after last login
			elseif (OC::tryRememberLogin()) {
				$error[] = 'invalidcookie';
			} // logon via web form
			elseif (OC::tryFormLogin()) {
				$error[] = 'invalidpassword';
			}
		} catch (\OC\User\LoginException $e) {
			$messages[] = $e->getMessage();
Bart Visscher's avatar
Bart Visscher committed
900
		}
Thomas Tanghus's avatar
Thomas Tanghus committed
901

902
		OC_Util::displayLoginPage(array_unique($error), $messages);
Bart Visscher's avatar
Bart Visscher committed
903
904
	}

Lukas Reschke's avatar
Lukas Reschke committed
905
906
907
908
	/**
	 * Remove outdated and therefore invalid tokens for a user
	 * @param string $user
	 */
909
	protected static function cleanupLoginTokens($user) {
910
911
912
		$config = \OC::$server->getConfig();
		$cutoff = time() - $config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
		$tokens = $config->getUserKeys($user, 'login_token');
Bart Visscher's avatar
Bart Visscher committed
913
		foreach ($tokens as $token) {
914
			$time = $config->getUserValue($user, 'login_token', $token);
Bart Visscher's avatar
Bart Visscher committed
915
			if ($time < $cutoff) {
916
				$config->deleteUserValue($user, 'login_token', $token);
Bart Visscher's avatar
Bart Visscher committed
917
918
919
920
			}
		}
	}

Lukas Reschke's avatar
Lukas Reschke committed
921
922
923
924
	/**
	 * Try to login a user via HTTP authentication
	 * @return bool|void
	 */
925
	protected static function tryApacheAuth() {
926
927
928
929
		$return = OC_User::handleApacheAuth();

		// if return is true we are logged in -> redirect to the default page
		if ($return === true) {
930
			$_REQUEST['redirect_url'] = \OC::$server->getRequest()->getRequestUri();
931
932
933
934
935
936
			OC_Util::redirectToDefaultPage();
			exit;
		}

		// in case $return is null apache based auth is not enabled
		return is_null($return) ? false : true;
937
938
	}

Lukas Reschke's avatar
Lukas Reschke committed
939
940
941
942
	/**
	 * Try to login a user using the remember me cookie.
	 * @return bool Whether the provided cookie was valid
	 */
943
	protected static function tryRememberLogin() {
Bart Visscher's avatar
Bart Visscher committed
944
945
946
947
		if (!isset($_COOKIE["oc_remember_login"])
			|| !isset($_COOKIE["oc_token"])
			|| !isset($_COOKIE["oc_username"])
			|| !$_COOKIE["oc_remember_login"]
948
			|| !OC_Util::rememberLoginAllowed()
949
		) {
Bart Visscher's avatar
Bart Visscher committed
950
951
			return false;
		}