<?php
	/**
	* This file is the dispatcher of the whole application, every request for data enters 
	* here. XML is received and send to the client.
	*/
	
	// Include files
	include("init.php");
	include("config.php");
	include("defaults.php");
	include("server/util.php");
	include("server/gettext.php");
	
	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/core/class.json.php");
	require("server/core/class.conversion.php");
	require("server/core/class.mapisession.php");
	require("server/core/class.entryid.php");

	include("server/core/constants.php");
	
	include("server/core/class.state.php");
	include("server/core/class.jsonrequest.php");
	include("server/modules/class.module.php");
	include("server/modules/class.listmodule.php");
	include("server/modules/class.itemmodule.php");
	include("server/core/class.operations.php");
	include("server/core/class.properties.php");
	include("server/core/class.bus.php");
	include("server/core/class.settings.php");
	include("server/core/class.language.php");
	include("server/core/class.pluginmanager.php");
	include("server/core/class.plugin.php");

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

	// Callback function for unserialize
	// Module objects of the previous request are stored in the session. With this
	// function they are restored to PHP objects.
	ini_set("unserialize_callback_func", "sessionModuleLoader");
	
	// Start session
	session_name(COOKIE_NAME);
	session_start();
	
	// Create global mapi object. This object is used in many other files
	$GLOBALS["mapisession"] = new MAPISession();
	// Logon, the username and password are set in the "index.php" file. So whenever
	// an user enters this file, the username and password whould be set in the $_SESSION
	// variable
	if (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);
	}else{
		$hresult = MAPI_E_UNCONFIGURED;
	}

	if(isset($_SESSION["lang"])) {
		$session_lang = $_SESSION["lang"];
	}else{
		$session_lang = LANG;
	}
	
	// Close the session now, so we're not blocking other clients
	session_write_close();

	// Set headers for JSON
	header("Content-Type: application/json; charset=utf-8");
	header("Expires: ".gmdate( "D, d M Y H:i:s")."GMT");
	header("Last-Modified: ".gmdate( "D, d M Y H:i:s")."GMT");
	header("Cache-Control: no-cache, must-revalidate");
	header("Pragma: no-cache");
	header("X-Zarafa: ".phpversion("mapi").(defined("SVN") ? "-".SVN:""));
		
	// Check is the user is authenticated
	if ($GLOBALS["mapisession"]->isLoggedOn()) {
		// Authenticated
		// Execute request
		
		// Instantiate Plugin Manager
		$GLOBALS['PluginManager'] = new PluginManager(ENABLE_PLUGINS);
		$GLOBALS['PluginManager']->detectPlugins(DISABLED_PLUGINS_LIST);
		$GLOBALS['PluginManager']->initPlugins(DEBUG_LOADER);

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

		// Create global entryId object
		$GLOBALS["entryid"] = new EntryId();
		// Create global language object
		$GLOBALS["language"] = new Language();
		// Set the correct language
		$GLOBALS["language"]->setLanguage($session_lang);

		// Get the state information for this subsystem
		if(isset($_GET["subsystem"]))
			$subsystem = $_GET["subsystem"];
		else
			$subsystem = "anonymous"; // Currently should never happen	

		$state = new State($subsystem);
		
		// Lock the state of this subsystem
		$state->open();
		
		// Get the bus object for this subsystem
		$bus = $state->read("bus");

		if(!$bus) {
			// Create global bus object
			$bus = new Bus();
		}
		
		// Make bus global
		$GLOBALS["bus"] = $bus;
		
		// Reset any spurious information in the bus state
		$GLOBALS["bus"]->reset();

		// Create global properties object
		$properties = $state->read("properties");

		if (!$properties) {
			$properties = new Properties();
		}
		$GLOBALS["properties"] = $properties;

		// Reset any spurious information in the properties state
		$GLOBALS["properties"]->reset();

		// Create new request object
		$request = new JSONRequest();

		// Get the XML from the client
		$xml = readData();

		if (function_exists("dump_json")) {
			dump_json($xml,"in"); // debugging
		}

		// Get Attachment data from state and put it into the $_SESSION
		$attachment_state = new State('attachments');
		$attachment_state->open();
		$_SESSION['files'] = $attachment_state->read("files");
		$_SESSION['deleteattachment'] = $attachment_state->read("deleteattachment");
		$checksum = md5(serialize($_SESSION['files']) . serialize($_SESSION['deleteattachment']));
		$attachment_state->close();

		// Execute the request
		try {
			$xml = $request->execute($xml);
		} catch (Exception $e) {
			// invalid requestdata exception
			dump($e);
		}

		// Get Attachment data from $_SESSION and put it into the state, but only if something has changed
		if(md5(serialize($_SESSION['files']) . serialize($_SESSION['deleteattachment'])) != $checksum) {
			$attachment_state = new State('attachments');
			$attachment_state->open();
			$attachment_state->write("files", $_SESSION['files']);
			$attachment_state->write("deleteattachment", $_SESSION['deleteattachment']);
			$attachment_state->close();
		}
		// Prevent the SESSION data to be stored elsewhere
		unset($_SESSION['files'], $_SESSION['deleteattachment']);

		if (function_exists("dump_json")) dump_json($xml,"out"); // debugging

		// Check if we can use gzip compression
		if ((!defined("DEBUG_GZIP")||DEBUG_GZIP) && $GLOBALS["settings"]->get("global/use_gzip","true")=="true" && function_exists("gzencode") && isset($_SERVER["HTTP_ACCEPT_ENCODING"]) && strpos($_SERVER["HTTP_ACCEPT_ENCODING"], "gzip")!==false){
			// Set the correct header and compress the XML
			header("Content-Encoding: gzip");
			echo gzencode($xml);
		}else {
			echo $xml;
		}

		// Reset the BUS, and save it to the state file
		$GLOBALS["bus"]->reset();
		$state->write("bus", $GLOBALS["bus"], false);

		// Reset the properties and save it to the state file
		$GLOBALS["properties"]->reset();
		$state->write("properties", $GLOBALS["properties"], false);

		// Write al changes to disk
		$state->flush();

		// You can skip this as well because the lock is freed after the PHP script ends
		// anyway. (only for PHP < 5.3.2)
		$state->close();

	} else {
		$errorTag = array(
			"zarafa" => array(
				"error" => array(
					"type" => ERROR_MAPI,
					"info" => array(
						"hresult" => $hresult,
						"hresult_name" => get_mapi_error_name($hresult),
						"display_message" => _("Logon failed")
					)
				)
			)
		);

		echo json_encode($errorTag);
	}
?>
