base.php 32.2 KB
Newer Older
1
2
<?php
/**
Jakob Sack's avatar
Jakob Sack committed
3
4
5
 * ownCloud
 *
 * @author Frank Karlitschek
Frank Karlitschek's avatar
Frank Karlitschek committed
6
 * @copyright 2012 Frank Karlitschek frank@owncloud.org
Jakob Sack's avatar
Jakob Sack committed
7
8
9
10
11
12
13
14
15
16
 *
 * 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.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
17
 *
Jakob Sack's avatar
Jakob Sack committed
18
19
20
21
 * 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/>.
 *
 */
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
	public static function initPaths() {
Bart Visscher's avatar
Bart Visscher committed
84
85
		// calculate the root directories
		OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
86
87
88
89

		// ensure we can find OC_Config
		set_include_path(
			OC::$SERVERROOT . '/lib' . PATH_SEPARATOR .
90
			get_include_path()
91
92
		);

93
94
95
		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/')) {
96
			self::$configDir = OC::$SERVERROOT . '/tests/config/';
97
98
99
100
101
		} else {
			self::$configDir = OC::$SERVERROOT . '/config/';
		}
		OC_Config::$object = new \OC\Config(self::$configDir);

Bart Visscher's avatar
Bart Visscher committed
102
		OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
103
		$scriptName = OC_Request::scriptName();
Bart Visscher's avatar
Bart Visscher committed
104
105
106
107
108
109
110
111
112
113
114
		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';
			}
		}

115
116
		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
117

118
119
120
121
122
123
124
125
126
			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', '');
Bart Visscher's avatar
Bart Visscher committed
127
128
129
		}

		// search the 3rdparty folder
130
131
132
		OC::$THIRDPARTYROOT = OC_Config::getValue('3rdpartyroot', null);
		OC::$THIRDPARTYWEBROOT = OC_Config::getValue('3rdpartyurl', null);
		
133
		if (empty(OC::$THIRDPARTYROOT) && empty(OC::$THIRDPARTYWEBROOT)) {
134
135
136
137
138
139
140
141
			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), '/');
			}
		}
142
		if (empty(OC::$THIRDPARTYROOT) || !file_exists(OC::$THIRDPARTYROOT)) {
143
			echo('3rdparty directory not found! Please put the ownCloud 3rdparty'
144
145
				. ' folder in the ownCloud folder or the folder above.'
				. ' You can also configure the location in the config.php file.');
Victor Dubiniuk's avatar
Victor Dubiniuk committed
146
			return;
Bart Visscher's avatar
Bart Visscher committed
147
		}
148
		
Bart Visscher's avatar
Bart Visscher committed
149
150
151
152
153
154
155
156
157
158
159
160
161
		// 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
162
163
164
165
166
			OC::$APPSROOTS[] = array(
				'path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps',
				'url' => '/apps',
				'writable' => true
			);
Bart Visscher's avatar
Bart Visscher committed
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.');
Bart Visscher's avatar
Bart Visscher committed
172
173
		}
		$paths = array();
174
		foreach (OC::$APPSROOTS as $path) {
Bart Visscher's avatar
Bart Visscher committed
175
			$paths[] = $path['path'];
176
		}
Bart Visscher's avatar
Bart Visscher committed
177
178
179

		// set the right include path
		set_include_path(
180
			OC::$SERVERROOT . '/lib/private' . PATH_SEPARATOR .
181
182
			OC::$SERVERROOT . '/config' . PATH_SEPARATOR .
			OC::$THIRDPARTYROOT . '/3rdparty' . PATH_SEPARATOR .
183
			implode(PATH_SEPARATOR, $paths) . PATH_SEPARATOR .
184
185
			get_include_path() . PATH_SEPARATOR .
			OC::$SERVERROOT
Bart Visscher's avatar
Bart Visscher committed
186
187
		);
	}
188

189
	public static function checkConfig() {
190
		$l = \OC::$server->getL10N('lib');
191
192
		if (file_exists(self::$configDir . "/config.php")
			and !is_writable(self::$configDir . "/config.php")
193
		) {
194
			if (self::$CLI) {
195
196
				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";
197
				echo "\n";
198
				echo $l->t('See %s', array(\OC_Helper::linkToDocs('admin-dir_permissions')))."\n";
199
200
201
				exit;
			} else {
				OC_Template::printErrorPage(
202
203
204
205
					$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>'))
206
207
				);
			}
208
209
210
		}
	}

211
	public static function checkInstalled() {
Bart Visscher's avatar
Bart Visscher committed
212
		// Redirect to installer if not installed
213
		if (!\OC::$server->getConfig()->getSystemValue('installed', false) && OC::$SUBURI != '/index.php') {
214
215
			if (OC::$CLI) {
				throw new Exception('Not installed');
216
			} else {
217
218
				$url = 'http://' . $_SERVER['SERVER_NAME'] . OC::$WEBROOT . '/index.php';
				header('Location: ' . $url);
Bart Visscher's avatar
Bart Visscher committed
219
220
221
222
223
			}
			exit();
		}
	}

224
	public static function checkSSL() {
Bart Visscher's avatar
Bart Visscher committed
225
		// redirect to https site if configured
226
227
228
229
230
231
232
233
234
235
		if (\OC::$server->getConfig()->getSystemValue('forcessl', false)) {
			// Default HSTS policy
			$header = 'Strict-Transport-Security: max-age=31536000';

			// If SSL for subdomains is enabled add "; includeSubDomains" to the header
			if(\OC::$server->getConfig()->getSystemValue('forceSSLforSubdomains', false)) {
				$header .= '; includeSubDomains';
			}
			header($header);
			ini_set('session.cookie_secure', 'on');
Bart Visscher's avatar
Bart Visscher committed
236
			if (OC_Request::serverProtocol() <> 'https' and !OC::$CLI) {
237
				$url = 'https://' . OC_Request::serverHost() . OC_Request::requestUri();
Bart Visscher's avatar
Bart Visscher committed
238
239
240
				header("Location: $url");
				exit();
			}
241
242
243
244
245
		} else {
			// Invalidate HSTS headers
			if (OC_Request::serverProtocol() === 'https') {
				header('Strict-Transport-Security: max-age=0');
			}
Bart Visscher's avatar
Bart Visscher committed
246
247
		}
	}
248

249
	public static function checkMaintenanceMode() {
250
		// Allow ajax update script to execute without being stopped
251
		if (\OC::$server->getConfig()->getSystemValue('maintenance', false) && OC::$SUBURI != '/core/ajax/update.php') {
252
253
254
255
256
257
			// 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
258
			$tmpl = new OC_Template('', 'update.user', 'guest');
kondou's avatar
kondou committed
259
			OC_Util::addscript('maintenance-check');
260
261
			$tmpl->printPage();
			die();
262
263
264
		}
	}

265
266
267
	public static function checkSingleUserMode() {
		$user = OC_User::getUserSession()->getUser();
		$group = OC_Group::getManager()->get('admin');
268
		if ($user && \OC::$server->getConfig()->getSystemValue('singleuser', false) && !$group->inGroup($user)) {
269
270
271
272
273
274
275
276
277
278
279
280
			// 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();
		}
	}

281
282
283
284
	/**
	 * check if the instance needs to preform an upgrade
	 *
	 * @return bool
285
	 * @deprecated use \OCP\Util::needUpgrade() instead
286
287
	 */
	public static function needUpgrade() {
Vincent Petry's avatar
Vincent Petry committed
288
		return \OCP\Util::needUpgrade();
289
290
	}

Lukas Reschke's avatar
Lukas Reschke committed
291
292
293
294
295
	/**
	 * Checks if the version requires an update and shows
	 * @param bool $showTemplate Whether an update screen should get shown
	 * @return bool|void
	 */
296
	public static function checkUpgrade($showTemplate = true) {
Vincent Petry's avatar
Vincent Petry committed
297
		if (\OCP\Util::needUpgrade()) {
298
299
			$config = \OC::$server->getConfig();
			if ($showTemplate && !$config->getSystemValue('maintenance', false)) {
Vincent Petry's avatar
Vincent Petry committed
300
				$version = OC_Util::getVersion();
301
302
				$oldTheme = $config->getSystemValue('theme');
				$config->setSystemValue('theme', '');
303
304
305
306
				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
307
308
309
310
311
312
313

				// 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)) {
314
						$incompatibleApps[] = $info;
Vincent Petry's avatar
Vincent Petry committed
315
316
317
318
319
					}
				}
				$tmpl->assign('appList', $incompatibleApps);
				$tmpl->assign('productName', 'ownCloud'); // for now
				$tmpl->assign('oldTheme', $oldTheme);
320
321
322
323
324
325
326
327
328
				$tmpl->printPage();
				exit();
			} else {
				return true;
			}
		}
		return false;
	}

329
	public static function initTemplateEngine() {
Bart Visscher's avatar
Bart Visscher committed
330
		// Add the stuff we need always
Vincent Petry's avatar
Vincent Petry committed
331
		// TODO: read from core/js/core.json
Morris Jobke's avatar
Morris Jobke committed
332
333
		OC_Util::addVendorScript('jquery/jquery.min');
		OC_Util::addVendorScript('jquery/jquery-migrate.min');
Thomas Mueller's avatar
Thomas Mueller committed
334
		OC_Util::addScript("jquery-ui-1.10.0.custom");
Bart Visscher's avatar
Bart Visscher committed
335
		OC_Util::addScript("jquery-showpassword");
336
		OC_Util::addScript("placeholders");
Bart Visscher's avatar
Bart Visscher committed
337
		OC_Util::addScript("jquery-tipsy");
338
		OC_Util::addScript("compatibility");
Morris Jobke's avatar
Morris Jobke committed
339
		OC_Util::addVendorScript("underscore/underscore");
340
		OC_Util::addScript("jquery.ocdialog");
Bart Visscher's avatar
Bart Visscher committed
341
342
		OC_Util::addScript("oc-dialogs");
		OC_Util::addScript("js");
343
		OC_Util::addScript("l10n");
Vincent Petry's avatar
Vincent Petry committed
344
		OC_Util::addTranslations("core");
345
		OC_Util::addScript("octemplate");
Bart Visscher's avatar
Bart Visscher committed
346
347
348
349
		OC_Util::addScript("eventsource");
		OC_Util::addScript("config");
		//OC_Util::addScript( "multiselect" );
		OC_Util::addScript('search', 'result');
350
		OC_Util::addScript("oc-requesttoken");
Bernhard Posselt's avatar
Bernhard Posselt committed
351
		OC_Util::addScript("apps");
Morris Jobke's avatar
Morris Jobke committed
352
		OC_Util::addVendorScript('snapjs/dist/latest/snap');
353
		OC_Util::addVendorScript('moment/min/moment-with-locales');
Bart Visscher's avatar
Bart Visscher committed
354

355
		// avatars
356
		if (\OC::$server->getConfig()->getSystemValue('enable_avatars', true) === true) {
357
			\OC_Util::addScript('placeholder');
Morris Jobke's avatar
Morris Jobke committed
358
			\OC_Util::addVendorScript('blueimp-md5/js/md5');
359
360
361
			\OC_Util::addScript('jquery.avatar');
			\OC_Util::addScript('avatar');
		}
kondou's avatar
kondou committed
362

Bart Visscher's avatar
Bart Visscher committed
363
		OC_Util::addStyle("styles");
364
		OC_Util::addStyle("header");
365
		OC_Util::addStyle("mobile");
366
		OC_Util::addStyle("icons");
367
		OC_Util::addStyle("fonts");
368
		OC_Util::addStyle("apps");
369
		OC_Util::addStyle("fixes");
Bart Visscher's avatar
Bart Visscher committed
370
		OC_Util::addStyle("multiselect");
Thomas Mueller's avatar
Thomas Mueller committed
371
		OC_Util::addStyle("jquery-ui-1.10.0.custom");
Bart Visscher's avatar
Bart Visscher committed
372
		OC_Util::addStyle("jquery-tipsy");
373
		OC_Util::addStyle("jquery.ocdialog");
Bart Visscher's avatar
Bart Visscher committed
374
375
	}

376
	public static function initSession() {
Bart Visscher's avatar
Bart Visscher committed
377
378
379
		// prevents javascript from accessing php session cookies
		ini_set('session.cookie_httponly', '1;');

380
		// set the cookie path to the ownCloud directory
381
		$cookie_path = OC::$WEBROOT ? : '/';
382
		ini_set('session.cookie_path', $cookie_path);
383

384
385
386
		// Let the session name be changed in the initSession Hook
		$sessionName = OC_Util::getInstanceId();

387
		try {
388
389
			// Allow session apps to create a custom session object
			$useCustomSession = false;
Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
390
391
392
393
394
395
			$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 {
396
				// set the session name to the instance id - which is unique
Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
397
				self::$server->setSession(new \OC\Session\Internal($sessionName));
398
			}
Robin Appelman's avatar
Robin Appelman committed
399
			// if session cant be started break with http 500 error
400
		} catch (Exception $e) {
401
402
403
			//show the user a detailed error page
			OC_Response::setStatus(OC_Response::STATUS_INTERNAL_SERVER_ERROR);
			OC_Template::printExceptionErrorPage($e);
404
		}
Bart Visscher's avatar
Bart Visscher committed
405

406
		$sessionLifeTime = self::getSessionLifeTime();
Bart Visscher's avatar
Bart Visscher committed
407
		// regenerate session id periodically to avoid session fixation
Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
408
409
410
411
412
413
414
		/**
		 * @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
415
			session_regenerate_id(true);
Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
416
			$session->set('SID_CREATED', time());
Bart Visscher's avatar
Bart Visscher committed
417
418
419
		}

		// session timeout
Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
420
		if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
Bart Visscher's avatar
Bart Visscher committed
421
			if (isset($_COOKIE[session_name()])) {
422
				setcookie(session_name(), '', time() - 42000, $cookie_path);
Bart Visscher's avatar
Bart Visscher committed
423
424
425
426
427
			}
			session_unset();
			session_destroy();
			session_start();
		}
Robin Appelman's avatar
Robin Appelman committed
428

Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
429
		$session->set('LAST_ACTIVITY', time());
Bart Visscher's avatar
Bart Visscher committed
430
431
	}

432
	/**
433
	 * @return string
434
435
	 */
	private static function getSessionLifeTime() {
436
		return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
437
438
	}

439
440
441
442
	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
443
444
445
446
				require_once $file;
			}
		}
	}
447
448


449
	public static function init() {
Bart Visscher's avatar
Bart Visscher committed
450
		// register autoloader
Robin Appelman's avatar
Robin Appelman committed
451
		$loaderStart = microtime(true);
452
		require_once __DIR__ . '/autoloader.php';
453
		self::$loader = new \OC\Autoloader();
454
		spl_autoload_register(array(self::$loader, 'load'));
Robin Appelman's avatar
Robin Appelman committed
455
		$loaderEnd = microtime(true);
Bart Visscher's avatar
Bart Visscher committed
456

Robin Appelman's avatar
Robin Appelman committed
457
		self::initPaths();
458
459
460
461

		// setup 3rdparty autoloader
		$vendorAutoLoad = OC::$THIRDPARTYROOT . '/3rdparty/autoload.php';
		if (file_exists($vendorAutoLoad)) {
462
			require_once $vendorAutoLoad;
463
464
465
466
467
468
		} else {
			OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
			OC_Template::printErrorPage('Composer autoloader not found, unable to continue.');
		}

		// setup the basic server
Lukas Reschke's avatar
Lukas Reschke committed
469
		self::$server = new \OC\Server(\OC::$WEBROOT);
Robin Appelman's avatar
Robin Appelman committed
470
		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
Robin Appelman's avatar
Robin Appelman committed
471
		\OC::$server->getEventLogger()->start('boot', 'Initialize');
Bart Visscher's avatar
Bart Visscher committed
472
473
474
475
476
477
478
479
480
481
482
483
484

		// set some stuff
		//ob_start();
		error_reporting(E_ALL | E_STRICT);
		if (defined('DEBUG') && DEBUG) {
			ini_set('display_errors', 1);
		}
		self::$CLI = (php_sapi_name() == 'cli');

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

		// try to switch magic quotes off.
485
		if (get_magic_quotes_gpc() == 1) {
Frank Karlitschek's avatar
Frank Karlitschek committed
486
			ini_set('magic_quotes_runtime', 0);
Bart Visscher's avatar
Bart Visscher committed
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
		}
		//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');

502
		self::handleAuthHeaders();
503
		self::registerAutoloaderCache();
504

505
506
		// initialize intl fallback is necessary
		\Patchwork\Utf8\Bootup::initIntl();
507
		OC_Util::isSetLocaleWorking();
508

509
		if (!defined('PHPUNIT_RUN')) {
510
			OC\Log\ErrorHandler::setLogger(OC_Log::$object);
511
			if (defined('DEBUG') and DEBUG) {
512
				OC\Log\ErrorHandler::register(true);
513
514
515
516
				set_exception_handler(array('OC_Template', 'printExceptionErrorPage'));
			} else {
				OC\Log\ErrorHandler::register();
			}
517
518
		}

Bart Visscher's avatar
Bart Visscher committed
519
		// register the stream wrappers
520
521
522
		stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir');
		stream_wrapper_register('static', 'OC\Files\Stream\StaticStream');
		stream_wrapper_register('close', 'OC\Files\Stream\Close');
523
		stream_wrapper_register('quota', 'OC\Files\Stream\Quota');
524
		stream_wrapper_register('oc', 'OC\Files\Stream\OC');
Bart Visscher's avatar
Bart Visscher committed
525

Robin Appelman's avatar
Robin Appelman committed
526
		\OC::$server->getEventLogger()->start('init_session', 'Initialize session');
527
		OC_App::loadApps(array('session'));
528
		if (!self::$CLI) {
529
			self::initSession();
530
		}
Robin Appelman's avatar
Robin Appelman committed
531
		\OC::$server->getEventLogger()->end('init_session');
Vincent Petry's avatar
Vincent Petry committed
532
		self::initTemplateEngine();
533
534
535
		self::checkConfig();
		self::checkInstalled();
		self::checkSSL();
536
		OC_Response::addSecurityHeaders();
Bart Visscher's avatar
Bart Visscher committed
537

538
		$errors = OC_Util::checkServer(\OC::$server->getConfig());
Bart Visscher's avatar
Bart Visscher committed
539
		if (count($errors) > 0) {
540
541
			if (self::$CLI) {
				foreach ($errors as $error) {
542
					echo $error['error'] . "\n";
543
544
545
					echo $error['hint'] . "\n\n";
				}
			} else {
546
				OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
547
548
				OC_Template::printGuestPage('', 'error', array('errors' => $errors));
			}
Bart Visscher's avatar
Bart Visscher committed
549
550
551
			exit;
		}

552
553
554
555
		//try to set the session lifetime
		$sessionLifeTime = self::getSessionLifeTime();
		@ini_set('gc_maxlifetime', (string)$sessionLifeTime);

556
557
		$config = \OC::$server->getConfig();

Bart Visscher's avatar
Bart Visscher committed
558
		// User and Groups
559
		if (!$config->getSystemValue("installed", false)) {
Jörn Friedrich Dreyer's avatar
Jörn Friedrich Dreyer committed
560
			self::$server->getSession()->set('user_id', '');
Bart Visscher's avatar
Bart Visscher committed
561
562
563
564
		}

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

Bart Visscher's avatar
Bart Visscher committed
566
		//setup extra user backends
567
568
569
		if (!self::checkUpgrade(false)) {
			OC_User::setupBackends();
		}
Bart Visscher's avatar
Bart Visscher committed
570
571
572

		self::registerCacheHooks();
		self::registerFilesystemHooks();
573
		self::registerPreviewHooks();
Bart Visscher's avatar
Bart Visscher committed
574
		self::registerShareHooks();
575
		self::registerLogRotate();
576
		self::registerLocalAddressBook();
Bart Visscher's avatar
Bart Visscher committed
577
578

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

582
		if ($config->getSystemValue('installed', false) && !self::checkUpgrade(false)) {
583
			if (\OC::$server->getAppConfig()->getValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') {
Bart Visscher's avatar
Bart Visscher committed
584
585
586
				OC_Util::addScript('backgroundjobs');
			}
		}
587
588

		// Check whether the sample configuration has been copied
589
		if($config->getSystemValue('copied_sample_config', false)) {
590
			$l = \OC::$server->getL10N('lib');
591
592
593
594
595
596
597
598
			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;
		}
599
600
601
602
603
604
605
606
607
608

		$host = OC_Request::insecureServerHost();
		// if the host passed in headers isn't trusted
		if (!OC::$CLI
			// overwritehost is always trusted
			&& OC_Request::getOverwriteHost() === null
			&& !OC_Request::isTrustedDomain($host)
		) {
			header('HTTP/1.1 400 Bad Request');
			header('Status: 400 Bad Request');
609

610
			$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
611
			$tmpl->assign('domain', $_SERVER['SERVER_NAME']);
612
			$tmpl->printPage();
613
614

			exit();
615
		}
Robin Appelman's avatar
Robin Appelman committed
616
		\OC::$server->getEventLogger()->end('boot');
Bart Visscher's avatar
Bart Visscher committed
617
618
	}

619
620
621
622
623
624
625
626
	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
627
628
629
	/**
	 * register hooks for the cache
	 */
630
	public static function registerCacheHooks() {
631
		if (\OC::$server->getConfig()->getSystemValue('installed', false) && !\OCP\Util::needUpgrade()) { //don't try to do this before we are properly setup
632
			\OCP\BackgroundJob::registerJob('OC\Cache\FileGlobalGC');
633

Thomas Tanghus's avatar
Thomas Tanghus committed
634
635
			// NOTE: This will be replaced to use OCP
			$userSession = \OC_User::getUserSession();
636
			$userSession->listen('postLogin', '\OC\Cache\File', 'loginListener');
637
		}
Bart Visscher's avatar
Bart Visscher committed
638
639
	}

640
641
642
643
	/**
	 * register hooks for the cache
	 */
	public static function registerLogRotate() {
644
645
		$config = \OC::$server->getConfig();
		if ($config->getSystemValue('installed', false) && $config->getSystemValue('log_rotate_size', false) && !\OCP\Util::needUpgrade()) {
646
			//don't try to do this before we are properly setup
647
			//use custom logfile path if defined, otherwise use default of owncloud.log in data directory
648
			\OCP\BackgroundJob::registerJob('OC\Log\Rotate', $config->getSystemValue('logfile', $config->getSystemValue('datadirectory', OC::$SERVERROOT . '/data') . '/owncloud.log'));
649
650
651
		}
	}

Bart Visscher's avatar
Bart Visscher committed
652
653
654
	/**
	 * register hooks for the filesystem
	 */
655
	public static function registerFilesystemHooks() {
Bart Visscher's avatar
Bart Visscher committed
656
		// Check for blacklisted files
657
658
		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
659
660
	}

661
662
663
664
	/**
	 * register hooks for previews
	 */
	public static function registerPreviewHooks() {
Georg Ehrke's avatar
Georg Ehrke committed
665
		OC_Hook::connect('OC_Filesystem', 'post_write', 'OC\Preview', 'post_write');
Bjoern Schiessle's avatar
Bjoern Schiessle committed
666
		OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'prepare_delete_files');
667
668
		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
669
		OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC\Preview', 'post_delete_files');
670
671
		OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete');
		OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete');
672
673
	}

Bart Visscher's avatar
Bart Visscher committed
674
675
676
	/**
	 * register hooks for sharing
	 */
677
	public static function registerShareHooks() {
678
		if (\OC::$server->getConfig()->getSystemValue('installed')) {
679
680
681
682
			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');
683
		}
Bart Visscher's avatar
Bart Visscher committed
684
685
	}

686
687
688
689
690
691
692
	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.
693
		$instanceId = \OC::$server->getConfig()->getSystemValue('instanceid', null);
694
695
696
697
698
699
700
701
702
		if ($instanceId) {
			try {
				$memcacheFactory = new \OC\Memcache\Factory($instanceId);
				self::$loader->setMemoryCache($memcacheFactory->createLowLatency('Autoloader'));
			} catch (\Exception $ex) {
			}
		}
	}

Bart Visscher's avatar
Bart Visscher committed
703
	/**
704
	 * Handle the request
Bart Visscher's avatar
Bart Visscher committed
705
	 */
706
	public static function handleRequest() {
Robin Appelman's avatar
Robin Appelman committed
707
		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
708
		$config = \OC::$server->getConfig();
Bernhard Posselt's avatar
Bernhard Posselt committed
709
710
711
		// load all the classpaths from the enabled apps so they are available
		// in the routing files of each app
		OC::loadAppClassPaths();
712

713
		// Check if ownCloud is installed or in maintenance (update) mode
714
		if (!$config->getSystemValue('installed', false)) {
Lukas Reschke's avatar
Lukas Reschke committed
715
			\OC::$server->getSession()->clear();
716
			$controller = new OC\Core\Setup\Controller(\OC::$server->getConfig());
717
			$controller->run($_POST);
718
719
			exit();
		}
720

721
		$request = OC_Request::getPathInfo();
722
		if (substr($request, -3) !== '.js') { // we need these files during the upgrade
723
724
725
			self::checkMaintenanceMode();
			self::checkUpgrade();
		}
726

727
		if (!self::$CLI and (!isset($_GET["logout"]) or ($_GET["logout"] !== 'true'))) {
728
			try {
729
				if (!$config->getSystemValue('maintenance', false) && !\OCP\Util::needUpgrade()) {
730
731
					OC_App::loadApps(array('authentication'));
					OC_App::loadApps(array('filesystem', 'logging'));
732
					OC_App::loadApps();
733
				}
734
				self::checkSingleUserMode();
735
				OC_Util::setupFS();
736
				OC::$server->getRouter()->match(OC_Request::getRawPathInfo());
737
738
739
740
741
742
743
				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
744
		}
745

Lukas Reschke's avatar
Lukas Reschke committed
746
747
748
749
750
751
752
		// Load minimum set of apps
		if (!self::checkUpgrade(false)) {
			// For logged-in users: Load everything
			if(OC_User::isLoggedIn()) {
				OC_App::loadApps();
			} else {
				// For guests: Load only authentication, filesystem and logging
753
754
				OC_App::loadApps(array('authentication'));
				OC_App::loadApps(array('filesystem', 'logging'));
Lukas Reschke's avatar
Lukas Reschke committed
755
756
			}
		}
757
758
759
760

		// 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
761

Lukas Reschke's avatar
Lukas Reschke committed
762
763
			// Deny the redirect if the URL contains a @
			// This prevents unvalidated redirects like ?redirect_url=:user@domain.com
764
			if (strpos($location, '@') === false) {
Lukas Reschke's avatar
Lukas Reschke committed
765
766
767
				header('Location: ' . $location);
				return;
			}
768
769
770
		}
		// Handle WebDAV
		if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
771
772
773
774
775
			// 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');
776
777
778
			return;
		}

779
780
781
782
783
784
785
786
		// 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
787
		// Someone is logged in
Bart Visscher's avatar
Bart Visscher committed
788
789
790
		if (OC_User::isLoggedIn()) {
			OC_App::loadApps();
			OC_User::setupBackends();
791
			OC_Util::setupFS();
Bart Visscher's avatar
Bart Visscher committed
792
			if (isset($_GET["logout"]) and ($_GET["logout"])) {
793
				OC_JSON::callCheck();
Bart Visscher's avatar
Bart Visscher committed
794
				if (isset($_COOKIE['oc_token'])) {
795
					$config->deleteUserValue(OC_User::getUser(), 'login_token', $_COOKIE['oc_token']);
Bart Visscher's avatar
Bart Visscher committed
796
797
				}
				OC_User::logout();
798
799
				// redirect to webroot and add slash if webroot is empty
				header("Location: " . OC::$WEBROOT.(empty(OC::$WEBROOT) ? '/' : ''));
Bart Visscher's avatar
Bart Visscher committed
800
			} else {
Lukas Reschke's avatar
Lukas Reschke committed
801
802
				// Redirect to default application
				OC_Util::redirectToDefaultPage();
Bart Visscher's avatar
Bart Visscher committed
803
			}
Lukas Reschke's avatar
Lukas Reschke committed
804
805
806
		} else {
			// Not handled and not logged in
			self::handleLogin();
Bart Visscher's avatar
Bart Visscher committed
807
808
809
		}
	}

810
811
812
813
814
815
816
817
818
819
820
821
822
823
	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
824
825
				$_SERVER['PHP_AUTH_USER'] = $name;
				$_SERVER['PHP_AUTH_PW'] = $password;
826
827
828
829
830
				break;
			}
		}
	}

831
	protected static function handleLogin() {
Bart Visscher's avatar
Bart Visscher committed
832
833
		OC_App::loadApps(array('prelogin'));
		$error = array();
834

835
836
837
		// auth possible via apache module?
		if (OC::tryApacheAuth()) {
			$error[] = 'apacheauthfailed';
838
		} // remember was checked after last login
839
		elseif (OC::tryRememberLogin()) {
Bart Visscher's avatar
Bart Visscher committed
840
			$error[] = 'invalidcookie';
841
842
		} // logon via web form
		elseif (OC::tryFormLogin()) {
Bart Visscher's avatar
Bart Visscher committed
843
844
			$error[] = 'invalidpassword';
		}
Thomas Tanghus's avatar
Thomas Tanghus committed
845

Bart Visscher's avatar
Bart Visscher committed
846
847
848
		OC_Util::displayLoginPage(array_unique($error));
	}

Lukas Reschke's avatar
Lukas Reschke committed
849
850
851
852
	/**
	 * Remove outdated and therefore invalid tokens for a user
	 * @param string $user
	 */
853
	protected static function cleanupLoginTokens($user) {
854
855
856
		$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
857
		foreach ($tokens as $token) {
858
			$time = $config->getUserValue($user, 'login_token', $token);
Bart Visscher's avatar
Bart Visscher committed
859
			if ($time < $cutoff) {
860
				$config->deleteUserValue($user, 'login_token', $token);
Bart Visscher's avatar
Bart Visscher committed
861
862
863
864
			}
		}
	}

Lukas Reschke's avatar
Lukas Reschke committed
865
866
867
868
	/**
	 * Try to login a user via HTTP authentication
	 * @return bool|void
	 */
869
	protected static function tryApacheAuth() {
870
871
872
873
874
875
876
877
878
879
880
		$return = OC_User::handleApacheAuth();

		// if return is true we are logged in -> redirect to the default page
		if ($return === true) {
			$_REQUEST['redirect_url'] = \OC_Request::requestUri();
			OC_Util::redirectToDefaultPage();
			exit;
		}

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

Lukas Reschke's avatar
Lukas Reschke committed
883
884
885
886
	/**
	 * Try to login a user using the remember me cookie.
	 * @return bool Whether the provided cookie was valid
	 */
887
	protected static function tryRememberLogin() {
Bart Visscher's avatar
Bart Visscher committed
888
889
890
891
		if (!isset($_COOKIE["oc_remember_login"])
			|| !isset($_COOKIE["oc_token"])
			|| !isset($_COOKIE["oc_username"])
			|| !$_COOKIE["oc_remember_login"]
892
			|| !OC_Util::rememberLoginAllowed()
893
		) {
Bart Visscher's avatar
Bart Visscher committed
894
895
			return false;
		}
896

Bart Visscher's avatar
Bart Visscher committed
897
898
899
		if (defined("DEBUG") && DEBUG) {
			OC_Log::write('core', 'Trying to login from cookie', OC_Log::DEBUG);
		}
900
901

		if(OC_User::userExists($_COOKIE['oc_username'])) {
Bart Visscher's avatar
Bart Visscher committed
902
			self::cleanupLoginTokens($_COOKIE['oc_username']);
Lukas Reschke's avatar
Lukas Reschke committed
903
			// verify whether the supplied "remember me" token was valid
904
905
906
			$granted = OC_User::loginWithCookie(
				$_COOKIE['oc_username'], $_COOKIE['oc_token']);
			if($granted === true) {
Bart Visscher's avatar
Bart Visscher committed
907
908
909
				OC_Util::redirectToDefaultPage();
				// doesn't return
			}
910
911
			OC_Log::write('core', 'Authentication cookie rejected for user ' .
				$_COOKIE['oc_username'], OC_Log::WARN);
Bart Visscher's avatar
Bart Visscher committed
912
913
914
915
916
			// if you reach this point you have changed your password
			// or you are an attacker
			// we can not delete tokens here because users may reach
			// this point multiple times after a password change
		}
917

Bart Visscher's avatar
Bart Visscher committed
918
919
920
921
		OC_User::unsetMagicInCookie();
		return true;
	}

Lukas Reschke's avatar
Lukas Reschke committed
922
	/**
923
	 * Tries to login a user using the form based authentication
Lukas Reschke's avatar
Lukas Reschke committed
924