<?php
	/**
	 * This is the entry point for every request that should return HTML
	 * 
	 * (one exception is that it also returns translated text for javascript)
	 */
	// load config file
	if (!file_exists("config.php")){
		die("<strong>config.php is missing!</strong>");
	}

	include("init.php");
	include("config.php");
	include("defaults.php");

	ob_start();
	setlocale(LC_CTYPE, "en_US.UTF-8");

	// Start the session
	session_name(COOKIE_NAME);

	if($_POST && array_key_exists(COOKIE_NAME, $_POST)) {
		session_id($_POST[COOKIE_NAME]);
	}

	session_start();

	// check if config is correct
	if (defined("CONFIG_CHECK")){
		include("server/class.configcheck.php");
		new ConfigCheck(CONFIG_CHECK);
	}

	// Include the files
	require("mapi/mapi.util.php");
	require("mapi/mapicode.php");
	require("mapi/mapidefs.php");
	require("mapi/mapitags.php");
	require("mapi/mapiguid.php");
	require("mapi/class.baseexception.php");
	require("mapi/class.mapiexception.php");

	require("server/exceptions/class.ZarafaException.php");
	require("server/exceptions/class.ZarafaErrorException.php");
	require("server/util.php");
	include("server/gettext.php");

	require("server/core/class.json.php");
	require("server/core/constants.php");
	require("server/core/class.conversion.php");
	require("server/core/class.mapisession.php");
	require("server/core/class.entryid.php");
	
	require("server/core/class.settings.php");
	require("server/core/class.language.php");

	require("server/core/class.state.php");
	require("server/core/class.attachmentstate.php");

	require("server/core/class.pluginmanager.php");
	require("server/core/class.plugin.php");

	// Determine the action, use 'null' as default value
	// so we will recognize arguments without value properly.
	$logout = sanitizeGetValue('logout', null, STRING_REGEX) !== null;
	$logon = sanitizeGetValue('logon', null, STRING_REGEX) !== null;
	$load = sanitizeGetValue('load', false, FILENAME_REGEX);

	// Returns true if the given $load argument
	// requires a validated session.
	function loadNeedsSession($load)
	{
		return !empty($load) && $load !== 'logon' && $load !== 'translations.js'; 
	}

	// Destroy session
	function destroySession()
	{
		$_SESSION = array();

		if (isset($_COOKIE[session_name()])) {
			setcookie(session_name(), '', time()-42000, '/');
		}

		session_destroy();
	}

	if ($logout) {
		// The user requests to logout. We should destroy the
		// session, and redirect the user to the logon page.
		$actionURI = '?load=logon';

		destroySession();

		$user = sanitizeGetValue('user', false, USERNAME_REGEX);
		if ($user) {
			$actionURI .= '&user=' . rawurlencode($user);
		}

		// Redirect the user, this will reload the page
		// and request the logon page.
		header('Location: index.php' . $actionURI, true, 303);
		exit;
	} else if ($logon) {
		// The user requested to logon. Check if credentials were provided
		// or if the a remote user login is possible.
		$username = ($_POST && array_key_exists('username', $_POST)) ? $_POST['username'] : '';
		$password = ($_POST && array_key_exists('password', $_POST)) ? $_POST['password'] : '';

		if (isset($_SESSION['username']) && $_SESSION['username'] !== $username) {
			$hresult = MAPI_E_INVALID_WORKSTATION_ACCOUNT;
			// Logon failed because a session for another user already exists.
			// We force the user back to the logon page.
			$load = 'logon';
		} else if (!empty($username) && !empty($password)) {
			// Set the session variables if it is posted
			$_SESSION['username'] = $username;
			$_SESSION['password'] = $password;
		}

       } else if (!DISABLE_REMOTE_USER_LOGIN && !isset($_SESSION['username'])) {
               // REMOTE_USER is set when apache has authenticated the user
               // Don't perform single-signon when $_POST is set, as that implies
               // the user was sending us data from a form.
               if (!$_POST && $_SERVER && array_key_exists('REMOTE_USER', $_SERVER)) {
                       $_SESSION['username'] = $_SERVER['REMOTE_USER'];
                       if (LOGINNAME_STRIP_DOMAIN) {
                               $_SESSION['username'] = ereg_replace('@.*', '', $_SESSION['username']);
                       }   
                       $_SESSION['password'] = '';
		}
	}

	// Create global mapi object. This object is used in many other files
	$GLOBALS["mapisession"] = new MAPISession(session_id());

	// We will only allow the logon when the sessionid in the GET arguments matches the
	// sessionid as send in the cookie. Otherwise the cookie was somehow modified in the
	// browser.
	$sessionid = sanitizeGetValue('sessionid', '', ID_REGEX);
	if (loadNeedsSession($load) && $sessionid !== $GLOBALS["mapisession"]->getSessionId()) {
		$hresult = MAPI_E_INVALID_WORKSTATION_ACCOUNT;
	} else if ($load !== 'logon' && isset($_SESSION["username"]) && isset($_SESSION["password"])) {
		$sslcert_file = defined('SSLCERT_FILE') ? SSLCERT_FILE : null;
		$sslcert_pass = defined('SSLCERT_PASS') ? SSLCERT_PASS : null;
		$hresult = $GLOBALS["mapisession"]->logon($_SESSION["username"], $_SESSION["password"], DEFAULT_SERVER, $sslcert_file, $sslcert_pass);
	}

	// Check if user is authenticated
	if ($GLOBALS["mapisession"]->isLoggedOn()) {
		// Authenticated

		// Instantiate Plugin Manager
		$GLOBALS['PluginManager'] = new PluginManager(ENABLE_PLUGINS);
		$GLOBALS['PluginManager']->detectPlugins(DISABLED_PLUGINS_LIST);
		$GLOBALS['PluginManager']->initPlugins(DEBUG_LOADER);
		
		// Create globals settings object
		$GLOBALS["settings"] = new Settings();
		
		// Create global language object
		$GLOBALS["language"] = new Language();

		// Set session settings (language & style)
		foreach($GLOBALS["settings"]->getSessionSettings() as $key=>$value){
			$_SESSION[$key] = $value;
		}
		
		// Get settings from post or session or settings
		if (isset($_REQUEST["language"]) && $GLOBALS["language"]->is_language($_REQUEST["language"])) {
			$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);
			}
		}

		$GLOBALS["language"]->setLanguage($lang);
		if ($logon) {
			$GLOBALS['PluginManager']->triggerHook("server.index.login.success");
			header("Location: index.php", true, 303);
			exit;
		}

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

		// external files who need our login
		if ($load) {
			switch ($load) {
				case "translations.js":
					$GLOBALS['PluginManager']->triggerHook("server.index.load.jstranslations.before");
					include("client/translations.js.php");
					$GLOBALS['PluginManager']->triggerHook("server.index.load.jstranslations.after");
					break;
				case "custom":
					$name = sanitizeGetValue('name', '', STRING_REGEX);
					$GLOBALS['PluginManager']->triggerHook("server.index.load.custom", array('name' => $name));
					break;
				case "upload_attachment":
					$GLOBALS['PluginManager']->triggerHook("server.index.load.upload_attachment.before");
					include("server/upload_attachment.php");
					$GLOBALS['PluginManager']->triggerHook("server.index.load.upload_attachment.after");
					break;
				case "download_attachment":
					$GLOBALS['PluginManager']->triggerHook("server.index.load.download_attachment.before");
					include("client/download_attachment.php");
					$GLOBALS['PluginManager']->triggerHook("server.index.load.download_attachment.after");
					break;
				case "download_message":
					$GLOBALS['PluginManager']->triggerHook("server.index.load.download_message.before");
					include("client/download_message.php");
					$GLOBALS['PluginManager']->triggerHook("server.index.load.download_message.after");
					break;
				case "logon":
					include("client/login.php");
					break;
				default:
					// These hooks are defined twice (also when no "load" argument is supplied)
					$GLOBALS['PluginManager']->triggerHook("server.index.load.main.before");
					include("client/webclient.php");
					$GLOBALS['PluginManager']->triggerHook("server.index.load.main.after");
					break;
			}
		} else if ($_GET && array_key_exists("authenticate", $_GET)) {
			$version = trim(file_get_contents('version'));
			$data = array(
				"settings" => $GLOBALS["settings"]->getJSON(),
				"languages" => $GLOBALS["language"]->getJSON(),
				"user" => array(
					"username" 	=> addslashes($GLOBALS["mapisession"]->getUserName()),
					"fullname" 	=> addslashes($GLOBALS["mapisession"]->getFullName()),
					"entryid" 	=> bin2hex($GLOBALS["mapisession"]->getUserEntryid()),
					"email_address" => addslashes($GLOBALS["mapisession"]->getEmailAddress()),
					"smtp_address" 	=> addslashes($GLOBALS["mapisession"]->getSMTPAddress()),
					"search_key" 	=> bin2hex($GLOBALS["mapisession"]->getSearchKey()),
					"sessionid" 	=> $GLOBALS["mapisession"]->getSessionID()
				),
				"version" => array(
					"webapp"	=> $version,
					"zcp"		=> phpversion('mapi'),
					"server"	=> DEBUG_SHOW_SERVER ? DEBUG_SERVER_ADDRESS : '',
					"svn"		=> DEBUG_LOADER === LOAD_SOURCE ? svnversion() : ''
				),
				"server" => array(
					"enable_plugins"		=> !!ENABLE_PLUGINS,
					"enable_advanced_settings"	=> !!ENABLE_ADVANCED_SETTINGS,
					"max_attachments"		=> null,
					"max_attachment_size"		=> getMaxUploadSize(),
					"max_attachment_total_size"	=> null,
					"freebusy_load_start_offset" => FREEBUSY_LOAD_START_OFFSET,
					"freebusy_load_end_offset" => FREEBUSY_LOAD_END_OFFSET
				)
			);
			echo JSON::Encode(array("zarafa" => $data));
		} else if ($_GET && array_key_exists("verify", $_GET)) {
			
			$user = sanitizeGetValue('verify', false, USERNAME_REGEX);
			
			if($user == $_SESSION['username'])
				print "1";
			else
				print "0";
			
		} else if (!DISABLE_WELCOME_SCREEN && $GLOBALS["settings"]->get("zarafa/v1/main/show_welcome") !== false) {
			// The user wants to logon, but he never did this before (or was using
			// an older version of WebApp, before the Welcome screen was introduced),
			// we will show a Welcome to WebApp screen where some default settings
			// might be configured

			// These hooks are defined twice (also when there is a "load" argument supplied)
			$GLOBALS['PluginManager']->triggerHook("server.index.load.welcome.before");
			// Include welcome page
			include("client/welcome.php");
			$GLOBALS['PluginManager']->triggerHook("server.index.load.welcome.after");
		} else {
			// 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();

			// 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");
			// Include webclient
			include("client/webclient.php");
			$GLOBALS['PluginManager']->triggerHook("server.index.load.main.after");
		}

		// Save the settings to the MAPI store
		$GLOBALS['settings']->saveSettings();
	} else if (empty($load) || $load === 'logon') {
		// We are not authenticated, and the requested page was either
		// the logon page itself, or the default page. In either case
		// we can redirect the user back to the logon page.
		$GLOBALS["language"] = new Language();
		$GLOBALS["language"]->setLanguage(LANG);

		if(isset($GLOBALS["hresult"])) {
			switch($GLOBALS["hresult"]) {
				case MAPI_E_LOGON_FAILED:
				case MAPI_E_UNCONFIGURED:
					// destroy the session so another login attempt will not use preserved data
					destroySession();
					break;
			}
		}

		// NOTE: We have saved the $hresult in the $GLOBALS
		// object, the login.php will obtain the code from there.
		include("client/login.php");
	} else if ($hresult === MAPI_E_NETWORK_ERROR) {
		// The user is not logged in because the zarafa-server could not be reached.
		// Return a HTTP 503 error so the client can act upon this event correctly.
		header('HTTP/1.1 503 Service unavailable');
		header("X-Zarafa-Hresult: " . get_mapi_error_name($hresult));
	} else {
		// The session expired, or the user is otherwise not logged on.
		// Return a HTTP 401 error so the client can act upon this event correctly.
		header('HTTP/1.1 401 Unauthorized');
		header("X-Zarafa-Hresult: " . get_mapi_error_name($hresult));
	}
?>
