index.php 10.4 KB
Newer Older
1 2 3 4 5 6 7 8 9
<?php
	/**
	 * This is the entry point for every request that should return HTML
	 * (one exception is that it also returns translated text for javascript)
	 */

	// Bootstrap the script
	require_once('server/includes/bootstrap.php');

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
	// Added in 3.4.0, remove check in 3.5.0
	if (!function_exists('gitversion')) {
		/**
		 * Obtain the current Git working branch
		 * @return string the current git working branch
		 */
		function gitversion()
		{
			if (is_dir(BASE_PATH . DIRECTORY_SEPARATOR . '.git')) {
				return trim(@shell_exec("git symbolic-ref --short HEAD || git rev-parse --short HEAD ."));
			} else {
				return '';
			}
		}
	} else {
		error_log('Remove gitversion() function in debug.php it\'s deprecated');
	}

28 29 30 31 32 33 34 35 36 37 38 39 40 41
	/*
	 * Get the favicon either from theme or use the default.
	 *
	 * @param string theme the users theme
	 * @return string favicon
	 */
	function getFavicon($theme)
	{

		if ( $theme ) {
			$favicon = Theming::getFavicon($theme);
		}

		if ( !isset($favicon) || $favicon === false) {
42
			$favicon = 'client/resources/images/favicon.ico?kv2.2.0';
43 44 45 46
		}

		return $favicon;
	}
47

48
	// If the user wants to logout (and is not using single-signon)
49
	// then destroy the session and redirect to this page, so the login page
50 51
	// will be shown
	if ( isset($_GET['logout']) && !WebAppAuthentication::isUsingSingleSignOn() ){
52

53 54 55 56
		// GET variable user will be set when the user was logged out because of session timeout
		// or because he logged out in another window.
		$username = sanitizeGetValue('user', '', USERNAME_REGEX);
		$webappSession->destroy();
57 58
		$location =  rtrim(dirname($_SERVER['PHP_SELF']), '/').'/';
		header('Location: ' . $location . ($username?'?user='.rawurlencode($username):''), true, 303);
59 60
		die();
	}
61

62 63 64 65 66 67 68
	// Check if an action GET-parameter was sent with the request.
	// This parameter is set when the webapp was opened by clicking on
	// a mailto: link in the browser.
	// If so, we will store it in the session, so we can use it later.
	if ( isset($_GET['action']) && !empty($_GET['action']) ) {
		storeURLDataToSession();
	}
69

70 71 72 73 74 75
	// Check if the continue parameter was set. This will be set e.g. when someone
	// uses the WebApp to login to another application with OpenID Connect.
	if ( isset($_GET['continue']) && !empty($_GET['continue']) && !isset($_GET['wacontinue']) ) {
		$_SESSION['continue'] = $_GET['continue'];
	}

76 77 78
	// Try to authenticate the user
	WebAppAuthentication::authenticate();

79
	$webappTitle = defined('WEBAPP_TITLE') && WEBAPP_TITLE ? WEBAPP_TITLE : 'Kopano WebApp';
80

81 82
	// If we could not authenticate the user, we will show the login page
	if ( !WebAppAuthentication::isAuthenticated() ){
83 84 85 86

		// Get language from the cookie, or from the language that is set by the admin
		$Language = new Language();
		$lang = isset($_COOKIE['lang']) ? $_COOKIE['lang'] : LANG;
87
		$lang = $Language->resolveLanguage($lang);
88 89
		$Language->setLanguage($lang);

90 91 92 93 94
		// If GET parameter 'load' is defined, we defer handling to the load.php script
		if ( isset($_GET['load']) && $_GET['load']!=='logon' ) {
			include(BASE_PATH . 'server/includes/load.php');
			die();
		}
95

96 97 98 99
		// Set some template variables for the login page
		$branch = DEBUG_LOADER===LOAD_SOURCE ? gitversion() : '';
		$version = 'WebApp ' . trim(file_get_contents('version'));
		$user = sanitizeGetValue('user', '', USERNAME_REGEX);
100

101 102 103 104 105 106
		$url = '?logon';

		if ( isset($_GET["logout"]) && $_GET["logout"]=="auto" ){
			$error = _("You have been automatically logged out");
		} else {
			$error = WebAppAuthentication::getErrorMessage();
107 108 109 110 111 112
			if(empty($error) && useSecureCookies() && getRequestProtocol() == 'http') {
				header("HTTP/1.0 400 Bad Request");
				include(BASE_PATH . 'server/includes/templates/BadRequest.php');
				error_log("Rejected insecure request as configuration for 'INSECURE_COOKIES' is false.");
				die();
			}
113
		}
114

115 116 117
		// If a username was passed as GET parameter we will prefill the username input
		// of the login form with it.
		$user = isset($_GET['user']) ? htmlentities($_GET['user']) : '';
118

119 120 121 122
		// Lets add a header when login failed (DeskApp needs it to identify failed login attempts)
		if ( WebAppAuthentication::getErrorCode() !== NOERROR ){
			header("X-Zarafa-Hresult: " . get_mapi_error_name(WebAppAuthentication::getErrorCode()));
		}
123

124 125 126 127 128 129 130 131
		// Set a template variable for the favicon of the login, welcome, and webclient page
		$theme = Theming::getActiveTheme();
		$favicon = getFavicon(Theming::getActiveTheme());

		// Include the login template
		include(BASE_PATH . 'server/includes/templates/login.php');
		die();
	}
132

133
	// The user is authenticated! Let's get ready to start the webapp.
134

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
	// Check if we need to redirect the user after login (e.g. when using the WebApp
	// to login to another application with OIDC).
	if ( isset($_SESSION['continue']) ){
		$continue = $_SESSION['continue'];
		unset($_SESSION['continue']);

		if ( isContinueRedirectAllowed($continue) ){
			// Add the parameter 'wacontinue' to make sure we will not keep redirecting
			// to ourself.
			$continue = explode('#', $continue);
			if ( strpos($continue[0], '?') === false ){
				$continue[0] .= '?';
			} else {
				$continue[0] .= '&';
			}
			$continue[0] .= 'wacontinue';
			$continue = implode('#', $continue);

			header('Location: ' . $continue , true, 302);
			die();
		}
	}

158
	// If the user just logged in or if url data was stored in the session,
159
	// we will redirect to make sure that a browser refresh will not post
160 161 162
	// the credentials again, and that the url data is taken away from the
	// url in the address bar (so a browser refresh will not pass them again)
	if ( WebAppAuthentication::isUsingLoginForm() || isset($_GET['action']) && !empty($_GET['action']) ){
163 164
		$location =  rtrim(dirname($_SERVER['PHP_SELF']), '/').'/';
		header('Location: ' . $location , true, 303);
165 166
		die();
	}
167 168

	// TODO: we could replace all references to $GLOBALS['mapisession']
169 170 171 172 173 174 175
	// with WebAppAuthentication::getMapiSession(), that way we would
	// lose at least one GLOBAL (because globals suck)
	$GLOBALS['mapisession'] = WebAppAuthentication::getMapiSession();

	// Instantiate Plugin Manager and init the plugins (btw: globals suck)
	$GLOBALS['PluginManager'] = new PluginManager(ENABLE_PLUGINS);
	$GLOBALS['PluginManager']->detectPlugins(DISABLED_PLUGINS_LIST);
176 177 178 179 180

	// Initialize plugins and prevent any output which might be written as
	// plugins might be uncleanly output white-space and other stuff. We must
	// not allow this here as it can destroy the response data.
	ob_start();
181
	$GLOBALS['PluginManager']->initPlugins(DEBUG_LOADER);
182
	ob_end_clean();
183 184

	$Language = new Language();
185

186
	// Create globals settings object (btw: globals suck)
187
	$GLOBALS["settings"] = new Settings($Language);
188 189 190 191

	// Create global operations object
	$GLOBALS["operations"] = new Operations();

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
	// If webapp feature is not enabled for the user,
	// we will show the login page with appropriated error message.
	if($GLOBALS['mapisession']->isWebappDisableAsFeature()) {
		header("X-Zarafa-Hresult: " . get_mapi_error_name(MAPI_E_WEBAPP_FEATURE_DISABLED));

		$error = _("Sorry, access to WebApp is not available with this user account. Please contact your system administrator.");
		// Set some template variables for the login page
		$user = sanitizeGetValue('user', '', USERNAME_REGEX);

		$url = '?logon';
		// Set a template variable for the favicon of the login, welcome, and webclient page
		$theme = Theming::getActiveTheme();
		$favicon = getFavicon(Theming::getActiveTheme());
		$webappSession->destroy();
		// Include the login template
		include(BASE_PATH . 'server/includes/templates/login.php');
		die();
	}

211
	// Set session settings (language & style)
212
	foreach($GLOBALS["settings"]->getSessionSettings($Language) as $key=>$value){
213 214 215 216
		$_SESSION[$key] = $value;
	}

	// Get language from the request, or the session, or the user settings, or the config
217
	if (isset($_REQUEST["language"]) && $Language->is_language($_REQUEST["language"])) {
218 219 220 221 222 223 224 225 226 227 228 229 230
		$lang = $_REQUEST["language"];
		$GLOBALS["settings"]->set("zarafa/v1/main/language", $lang);
	} else if(isset($_SESSION["lang"])) {
		$lang = $_SESSION["lang"];
		$GLOBALS["settings"]->set("zarafa/v1/main/language", $lang);
	} else {
		$lang = $GLOBALS["settings"]->get("zarafa/v1/main/language");
		if (empty($lang)) {
			$lang = LANG;
			$GLOBALS["settings"]->set("zarafa/v1/main/language", $lang);
		}
	}

231
	$Language->setLanguage($lang);
232
	setcookie('lang', $lang, 0, '/', '', getRequestProtocol() === 'https');
233 234 235

	// add extra header
	header("X-Zarafa: " . trim(file_get_contents('version')));
236

237 238 239
	// Set a template variable for the favicon of the login, welcome, and webclient page
	$theme = Theming::getActiveTheme();
	$favicon = getFavicon(Theming::getActiveTheme());
240 241
	$hideFavorites = $GLOBALS["settings"]->get("zarafa/v1/contexts/hierarchy/hide_favorites") ? 'hideFavorites' : '';
	$scrollFavorites = $GLOBALS["settings"]->get("zarafa/v1/contexts/hierarchy/scroll_favorites") ? 'scrollFavorites' : '';
242 243 244 245 246 247

	// If GET parameter 'load' is defined, we defer handling to the load.php script
	if ( isset($_GET['load']) ) {
		include(BASE_PATH . 'server/includes/load.php');
		die();
	}
248

249
	if (!DISABLE_WELCOME_SCREEN && $GLOBALS["settings"]->get("zarafa/v1/main/show_welcome") !== false) {
250

251 252 253 254 255
		// These hooks are defined twice (also when there is a "load" argument supplied)
		$GLOBALS['PluginManager']->triggerHook("server.index.load.welcome.before");
		include(BASE_PATH . 'server/includes/templates/welcome.php');
		$GLOBALS['PluginManager']->triggerHook("server.index.load.welcome.after");
	} else {
256

257 258 259 260 261 262 263 264 265 266 267 268 269
		// Set the show_welcome to true, so that when the admin is changing the
		// DISABLE_WELCOME_SCREEN option to false after some time, the users who are already
		// using the WebApp are not bothered with the Welcome Screen.
		$GLOBALS["settings"]->set("zarafa/v1/main/show_welcome", false);

		// Clean up old state files in tmp/session/
		$state = new State("index");
		$state->clean();

		// Clean up old attachments in tmp/attachments/
		$state = new AttachmentState();
		$state->clean();

270 271 272
		// Fetch the hierarchy state cache for unread counters notifications for subfolders
		$counterState = new State('counters_sessiondata');
		$counterState->open();
273
		$counterState->write("sessionData", updateHierarchyCounters());
274 275
		$counterState->close();

276 277 278 279 280
		// clean search folders
		cleanSearchFolders();

		// These hooks are defined twice (also when there is a "load" argument supplied)
		$GLOBALS['PluginManager']->triggerHook("server.index.load.main.before");
281

282 283 284 285
		// Include webclient
		include(BASE_PATH . 'server/includes/templates/webclient.php');
		$GLOBALS['PluginManager']->triggerHook("server.index.load.main.after");
	}