<?php
/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage main
 * @copyright 2001-2012 Bitrix
 */
namespace Bitrix\Main;

/**
 * Http application extends application. Contains http specific methods.
 */
class HttpApplication extends Application
{
	/**
	 * Page of current request.
	 *
	 * @var \Bitrix\Main\Page
	 */
	protected $page;

	/**
	 * Creates new instance of http application.
	 *
	 * @param Server $server
	 */
	public function __construct(Server $server)
	{
		parent::__construct($server);
	}

	/**
	 * Initializes context of the current request.
	 */
	protected function initializeContext()
	{
		$context = new Context($this);

		$request = new HttpRequest($context, $_REQUEST);
		$request->initialize($_GET, $_POST, $_COOKIE, $_FILES);

		$response = new HttpResponse($context);

		$context->initialize($request, $response);

		$this->setContext($context);
	}

	/**
	 * Initializes default culture of the current request.
	 */
	protected function initializeCulture()
	{
		//$this->page->init();
	}

	/**
	 * Initializes basic part of kernel. It is called before update system call.
	 */
	protected function initializeBasicKernel()
	{
	}

	/**
	 * Initializes extended part of kernel. It is called after update system call.
	 */
	protected function initializeExtendedKernel()
	{
		//<start.php>

		// вызов агента
		$this->checkAgents();

		// открытие сессии
		$this->initSession();

		//////////////////////////////////////////////////////////////
		// OnPageStart
		/*$db_events = GetModuleEvents("main", "OnPageStart");
		while($arEvent = $db_events->Fetch())
			ExecuteModuleEventEx($arEvent);*/

		/*
		$event = new Event("main", "OnPageStart");
		$event->turnDebugOn();
		$event->send();
		\Bitrix\Main\Diag\Debug::DumpToFile($event->getDebugInfo(), "OnPageStart");
		*/

		$event = new Event("main", "OnPageStart");
		$event->send();
	}

	/**
	 * Initializes application shell. Called after initializeKernel.
	 *
	 * @param System\IApplicationStrategy $initStrategy
	 */
	protected function initializeShell(\Bitrix\Main\System\IApplicationStrategy $initStrategy = null)
	{
		$this->authenticateUser();

		if ($initStrategy != null)
			$initStrategy->authenticateUser();

		define("BX_STARTED", true); // нужен для инфоблоков чтобы понять - определен ли сайт???

		// определение текущего шаблона сайта
		//define the site template
		$this->initializeSiteTemplate();

		//magic parameters: show page creation time
		if($_GET["show_page_exec_time"]=="Y" || $_GET["show_page_exec_time"]=="N")
			$_SESSION["SESS_SHOW_TIME_EXEC"] = $_GET["show_page_exec_time"];

		//magic parameters: show included file processing time
		if($_GET["show_include_exec_time"]=="Y" || $_GET["show_include_exec_time"]=="N")
			$_SESSION["SESS_SHOW_INCLUDE_TIME_EXEC"] = $_GET["show_include_exec_time"];

		//magic parameters: show include areas
		if(isset($_GET["bitrix_include_areas"]) && $_GET["bitrix_include_areas"] <> "")
			$GLOBALS["APPLICATION"]->SetShowIncludeAreas($_GET["bitrix_include_areas"]=="Y");

		//magic sound
		if($GLOBALS["USER"]->IsAuthorized())
		{
			$cookie_prefix = \COption::GetOptionString('main', 'cookie_name', 'BITRIX_SM');
			if(!isset($_COOKIE[$cookie_prefix.'_SOUND_LOGIN_PLAYED']))
				$GLOBALS["APPLICATION"]->set_cookie('SOUND_LOGIN_PLAYED', 'Y', 0);
		}

		$event = new Event("main", "OnBeforeProlog");
		$event->send();

		///////////////////////////////////////////
		if((!(defined("STATISTIC_ONLY") && STATISTIC_ONLY && substr($GLOBALS["APPLICATION"]->GetCurPage(), 0, strlen(BX_ROOT."/admin/"))!=BX_ROOT."/admin/")) && \COption::GetOptionString("main", "include_charset", "Y")=="Y" && strlen(LANG_CHARSET)>0)
			header("Content-Type: text/html; charset=".LANG_CHARSET);

		if(\COption::GetOptionString("main", "set_p3p_header", "Y")=="Y")
			header("P3P: policyref=\"/bitrix/p3p.xml\", CP=\"NON DSP COR CUR ADM DEV PSA PSD OUR UNR BUS UNI COM NAV INT DEM STA\"");


		// проверка прав и вывод формы авторизации
		$this->authorizeUser();

		if ($initStrategy != null)
			$initStrategy->authorizeUser();

		/*patchvalidationmutatormark2*/       //Do not remove this

		if(isset($REDIRECT_STATUS) && $REDIRECT_STATUS==404)
		{
			if(\COption::GetOptionString("main", "header_200", "N")=="Y")
				\CHTTP::SetStatus("200 OK");
		}


		//$this->initializeSite();

		//UpdateSystem::ExecuteUpdaters(UpdateSystemUpdater::Main);
		//UpdateSystem::ExecuteUpdaters();

		//$this->authenticateUser();
		//$this->AuthorizeUser(); - событие на получение компонента авторизации
	}

	protected function authorizeUser()
	{
		if ((!defined("NOT_CHECK_PERMISSIONS") || NOT_CHECK_PERMISSIONS !== true) && (!defined(
			"NOT_CHECK_FILE_PERMISSIONS"
		) || NOT_CHECK_FILE_PERMISSIONS !== true)
		)
		{
////////////////////////////////////
//  $this->page->Authorize();
			$arAuthResult = $GLOBALS["APPLICATION"]->arAuthResult;

			$real_path = $GLOBALS["APPLICATION"]->GetCurPage(true);
			if (isset($_SERVER["REAL_FILE_PATH"]) && $_SERVER["REAL_FILE_PATH"] != "")
				$real_path = $_SERVER["REAL_FILE_PATH"];

			if (!$GLOBALS["USER"]->CanDoFileOperation('fm_view_file', Array(SITE_ID, $real_path)) || (defined(
				"NEED_AUTH"
			) && NEED_AUTH && !$GLOBALS["USER"]->IsAuthorized())
			)
			{
				if ($GLOBALS["USER"]->IsAuthorized() && strlen($arAuthResult["MESSAGE"]) <= 0)
					$arAuthResult = array(
						"MESSAGE" => GetMessage("ACCESS_DENIED") . ' ' . GetMessage(
							"ACCESS_DENIED_FILE", array("#FILE#" => $real_path)
						), "TYPE" => "ERROR"
					);

				if (defined("ADMIN_SECTION") && ADMIN_SECTION == true)
				{
					if ($_REQUEST["mode"] == "list" || $_REQUEST["mode"] == "settings")
					{
						echo "<script>top.location='" . $GLOBALS["APPLICATION"]->GetCurPage() . "?" . DeleteParam(
							array("mode")
						) . "';</script>";
						die();
					}
					elseif ($_REQUEST["mode"] == "frame")
					{
						echo "<script type=\"text/javascript\">
					var w = (opener? opener.window:parent.window);
					w.location.href='" . $GLOBALS["APPLICATION"]->GetCurPage() . "?" . DeleteParam(array("mode")) . "';
				</script>";
						die();
					}
				}

				$GLOBALS["APPLICATION"]->AuthForm($arAuthResult);
			}
		}
	}

	protected function initializeSiteTemplate()
	{
		if (!defined("ADMIN_SECTION") || ADMIN_SECTION !== true)
		{
			if (array_key_exists(
				"bitrix_preview_site_template", $_REQUEST
			) && $_REQUEST["bitrix_preview_site_template"] <> "" && $GLOBALS["USER"]->CanDoOperation(
				'view_other_settings'
			)
			)
			{
				//preview of site template
				$aTemplates = \CSiteTemplate::GetByID($_REQUEST["bitrix_preview_site_template"]);
				if ($template = $aTemplates->Fetch())
					define("SITE_TEMPLATE_ID", $template["ID"]);
				else
					define("SITE_TEMPLATE_ID", \CSite::GetCurTemplate());
			}
			else
				define("SITE_TEMPLATE_ID", \CSite::GetCurTemplate());

			define("SITE_TEMPLATE_PATH", BX_PERSONAL_ROOT . '/templates/' . SITE_TEMPLATE_ID);
		}
	}

	protected function checkAgents()
	{
		if(\COption::GetOptionString("main", "check_agents", "Y")=="Y")
		{
			define("START_EXEC_AGENTS_1", microtime());
			$GLOBALS["BX_STATE"] = "AG";
			$GLOBALS["DB"]->StartUsingMasterOnly();
			\CAgent::CheckAgents();
			$GLOBALS["DB"]->StopUsingMasterOnly();
			define("START_EXEC_AGENTS_2", microtime());
			$GLOBALS["BX_STATE"] = "PB";
		}
	}

	protected function initSession()
	{
		// это в HttpApplication, нужно для открытия сессии
		if($domain = $GLOBALS["APPLICATION"]->GetCookieDomain())
			ini_set("session.cookie_domain", $domain);

		// для хранения сессии в других местах
		if(\COption::GetOptionString("security", "session", "N") === "Y" && \CModule::IncludeModule("security"))
			\CSecuritySession::Init();

		//diagnostic for spaces in init.php etc.
		//message is shown in the admin section
		$GLOBALS["aHeadersInfo"] = array();
		if(headers_sent($hs_file, $hs_line))
			$GLOBALS["aHeadersInfo"] = array("file"=>$hs_file, "line"=>$hs_line);

		session_start();
	}

	protected function authenticateUser()
	{
		$user = new \Bitrix\Main\Security\CurrentUser();
		$this->context->setUser($user);

		/////////////////////////////////////////////////////////////////
		// убрать строку когда checkSecurity не будет ссылаться на $USER
		$GLOBALS["USER"] = new \CUser;
		// перенести строку в authenticateUser когда checkSecurity не будет ссылаться на $USER
		$this->context->getUser()->checkSecurity();
	}

	/**
	 * Starts request execution. Should be called after initialize.
	 */
	public function start()
	{
		if(!$this->page)
			$this->page = $this->getPageByFactory();

		register_shutdown_function(array($this, "finish"));

		$this->page->startRequest();
	}

	/**
	 * Finishes request execution.
	 * It is registered in start() and called automatically on script shutdown.
	 */
	public function finish()
	{
		$buffer = $this->page->Render();

		$response = $this->context->getResponse();
		$response->flush($buffer);

		$this->managedCache->finalize();
		// агенты и евенты
	}

	/**
	 * Page factory. Should return object of appropriate Page subclass.
	 *
	 * @return Page
	 */
	protected function getPageByFactory()
	{
		// на событии получаем пользовательский вариант
		// если пользовательского нет - делаем по-умолчанию

		//$request = $this->GetRequest();

		//if ($request->IsAdminSection())
		//	return new CAdminPage();
		//elseif ($request->IsMobile())
		//	return new CMobilePage();
		//elseif ($request["light"] == "Y")
		//	return new LightPage();

		return new PublicPage($this);
	}

	/**
	 * Sets page of current request.
	 *
	 * @param Page $page
	 */
	public function setPage(Page $page)
	{
		$this->page = $page;
	}

	/**
	 * Returns page of current request.
	 *
	 * @return Page
	 */
	public function getPage()
	{
		return $this->page;
	}
}
