PageRenderTime 76ms CodeModel.GetById 2ms app.highlight 64ms RepoModel.GetById 1ms app.codeStats 0ms

/classes/module/ModuleHandler.class.php

https://github.com/prologos/xe-core
PHP | 1234 lines | 951 code | 139 blank | 144 comment | 245 complexity | af18a44e16d8fcf99168109ecfc1004f MD5 | raw file
   1<?php
   2/* Copyright (C) NAVER <http://www.navercorp.com> */
   3
   4/**
   5 * @class ModuleHandler
   6 * @author NAVER (developers@xpressengine.com)
   7 * Handling modules
   8 *
   9 * @remarks This class is to excute actions of modules.
  10 *          Constructing an instance without any parameterconstructor, it finds the target module based on Context.
  11 *          If there is no act on the found module, excute an action referencing action_forward.
  12 * */
  13class ModuleHandler extends Handler
  14{
  15
  16	var $module = NULL; ///< Module
  17	var $act = NULL; ///< action
  18	var $mid = NULL; ///< Module ID
  19	var $document_srl = NULL; ///< Document Number
  20	var $module_srl = NULL; ///< Module Number
  21	var $module_info = NULL; ///< Module Info. Object
  22	var $error = NULL; ///< an error code.
  23	var $httpStatusCode = NULL; ///< http status code.
  24
  25	/**
  26	 * prepares variables to use in moduleHandler
  27	 * @param string $module name of module
  28	 * @param string $act name of action
  29	 * @param int $mid
  30	 * @param int $document_srl
  31	 * @param int $module_srl
  32	 * @return void
  33	 * */
  34
  35	function ModuleHandler($module = '', $act = '', $mid = '', $document_srl = '', $module_srl = '')
  36	{
  37		// If XE has not installed yet, set module as install
  38		if(!Context::isInstalled())
  39		{
  40			$this->module = 'install';
  41			$this->act = Context::get('act');
  42			return;
  43		}
  44
  45		$oContext = Context::getInstance();
  46		if($oContext->isSuccessInit == FALSE)
  47		{
  48			$logged_info = Context::get('logged_info');
  49			if($logged_info->is_admin != "Y")
  50			{
  51				$this->error = 'msg_invalid_request';
  52				return;
  53			}
  54		}
  55
  56		// Set variables from request arguments
  57		$this->module = $module ? $module : Context::get('module');
  58		$this->act = $act ? $act : Context::get('act');
  59		$this->mid = $mid ? $mid : Context::get('mid');
  60		$this->document_srl = $document_srl ? (int) $document_srl : (int) Context::get('document_srl');
  61		$this->module_srl = $module_srl ? (int) $module_srl : (int) Context::get('module_srl');
  62		$this->entry = Context::convertEncodingStr(Context::get('entry'));
  63
  64		// Validate variables to prevent XSS
  65		$isInvalid = NULL;
  66		if($this->module && !preg_match("/^([a-z0-9\_\-]+)$/i", $this->module))
  67		{
  68			$isInvalid = TRUE;
  69		}
  70		if($this->mid && !preg_match("/^([a-z0-9\_\-]+)$/i", $this->mid))
  71		{
  72			$isInvalid = TRUE;
  73		}
  74		if($this->act && !preg_match("/^([a-z0-9\_\-]+)$/i", $this->act))
  75		{
  76			$isInvalid = TRUE;
  77		}
  78		if($isInvalid)
  79		{
  80			htmlHeader();
  81			echo Context::getLang("msg_invalid_request");
  82			htmlFooter();
  83			Context::close();
  84			exit;
  85		}
  86
  87		if(isset($this->act) && (strlen($this->act) >= 4 && substr_compare($this->act, 'disp', 0, 4) === 0))
  88		{
  89			if(Context::get('_use_ssl') == 'optional' && Context::isExistsSSLAction($this->act) && $_SERVER['HTTPS'] != 'on')
  90			{
  91				if(Context::get('_https_port')!=null) {
  92					header('location:https://' . $_SERVER['HTTP_HOST'] . ':' . Context::get('_https_port') . $_SERVER['REQUEST_URI']);
  93				} else {
  94					header('location:https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
  95				}
  96				return;
  97			}
  98		}
  99
 100		// call a trigger before moduleHandler init
 101		ModuleHandler::triggerCall('moduleHandler.init', 'before', $this);
 102
 103		// execute addon (before module initialization)
 104		$called_position = 'before_module_init';
 105		$oAddonController = getController('addon');
 106		$addon_file = $oAddonController->getCacheFilePath(Mobile::isFromMobilePhone() ? 'mobile' : 'pc');
 107		if(file_exists($addon_file)) include($addon_file);
 108	}
 109
 110	/**
 111	 * Initialization. It finds the target module based on module, mid, document_srl, and prepares to execute an action
 112	 * @return boolean true: OK, false: redirected
 113	 * */
 114	function init()
 115	{
 116		
 117		$oModuleModel = getModel('module');
 118		$site_module_info = Context::get('site_module_info');
 119
 120		// if success_return_url and error_return_url is incorrect
 121		$urls = array(Context::get('success_return_url'), Context::get('error_return_url'));
 122		foreach($urls as $url)
 123		{
 124			if(empty($url))
 125			{
 126				continue;
 127			}
 128		
 129			$urlInfo = parse_url($url);
 130			$host = $urlInfo['host'];
 131		
 132			$dbInfo = Context::getDBInfo();
 133			$defaultUrlInfo = parse_url($dbInfo->default_url);
 134			$defaultHost = $defaultUrlInfo['host'];
 135		
 136			if($host && ($host != $defaultHost && $host != $site_module_info->domain))
 137			{
 138				throw new Exception('msg_default_url_is_null');
 139			}
 140		}
 141		
 142		if(!$this->document_srl && $this->mid && $this->entry)
 143		{
 144			$oDocumentModel = getModel('document');
 145			$this->document_srl = $oDocumentModel->getDocumentSrlByAlias($this->mid, $this->entry);
 146			if($this->document_srl)
 147			{
 148				Context::set('document_srl', $this->document_srl);
 149			}
 150		}
 151
 152		// Get module's information based on document_srl, if it's specified
 153		if($this->document_srl)
 154		{
 155			
 156			$module_info = $oModuleModel->getModuleInfoByDocumentSrl($this->document_srl);
 157			// If the document does not exist, remove document_srl
 158			if(!$module_info)
 159			{
 160				unset($this->document_srl);
 161			}
 162			else
 163			{
 164				// If it exists, compare mid based on the module information
 165				// if mids are not matching, set it as the document's mid
 166				if(!$this->mid || ($this->mid != $module_info->mid))
 167				{
 168					
 169					if(Context::getRequestMethod() == 'GET')
 170					{
 171						$this->mid = $module_info->mid;
 172						header('location:' . getNotEncodedSiteUrl($site_info->domain, 'mid', $this->mid, 'document_srl', $this->document_srl));
 173						return FALSE;
 174					}
 175					else
 176					{
 177						$this->mid = $module_info->mid;
 178						Context::set('mid', $this->mid);
 179					}
 180					
 181				}
 182				// if requested module is different from one of the document, remove the module information retrieved based on the document number
 183				if($this->module && $module_info->module != $this->module)
 184				{
 185					unset($module_info);
 186				}
 187			}
 188
 189		}
 190
 191		// If module_info is not set yet, and there exists mid information, get module information based on the mid
 192		if(!$module_info && $this->mid)
 193		{
 194			$module_info = $oModuleModel->getModuleInfoByMid($this->mid, $site_module_info->site_srl);
 195			//if($this->module && $module_info->module != $this->module) unset($module_info);
 196		}
 197
 198		// redirect, if module_site_srl and site_srl are different
 199		if(!$this->module && !$module_info && $site_module_info->site_srl == 0 && $site_module_info->module_site_srl > 0)
 200		{
 201			$site_info = $oModuleModel->getSiteInfo($site_module_info->module_site_srl);
 202			header("location:" . getNotEncodedSiteUrl($site_info->domain, 'mid', $site_module_info->mid));
 203			return FALSE;
 204		}
 205
 206		// If module_info is not set still, and $module does not exist, find the default module
 207		if(!$module_info && !$this->module && !$this->mid)
 208		{
 209			$module_info = $site_module_info;
 210		}
 211
 212		if(!$module_info && !$this->module && $site_module_info->module_site_srl)
 213		{
 214			$module_info = $site_module_info;
 215		}
 216
 217		// redirect, if site_srl of module_info is different from one of site's module_info
 218		if($module_info && $module_info->site_srl != $site_module_info->site_srl && !isCrawler())
 219		{
 220			// If the module is of virtual site
 221			if($module_info->site_srl)
 222			{
 223				$site_info = $oModuleModel->getSiteInfo($module_info->site_srl);
 224				$redirect_url = getNotEncodedSiteUrl($site_info->domain, 'mid', Context::get('mid'), 'document_srl', Context::get('document_srl'), 'module_srl', Context::get('module_srl'), 'entry', Context::get('entry'));
 225				// If it's called from a virtual site, though it's not a module of the virtual site
 226			}
 227			else
 228			{
 229				$db_info = Context::getDBInfo();
 230				if(!$db_info->default_url)
 231				{
 232					return Context::getLang('msg_default_url_is_not_defined');
 233				}
 234				else
 235				{
 236					$redirect_url = getNotEncodedSiteUrl($db_info->default_url, 'mid', Context::get('mid'), 'document_srl', Context::get('document_srl'), 'module_srl', Context::get('module_srl'), 'entry', Context::get('entry'));
 237				}
 238			}
 239			header("location:" . $redirect_url);
 240			return FALSE;
 241		}
 242
 243		// If module info was set, retrieve variables from the module information
 244		if($module_info)
 245		{
 246			$this->module = $module_info->module;
 247			$this->mid = $module_info->mid;
 248			$this->module_info = $module_info;
 249			Context::setBrowserTitle($module_info->browser_title);
 250
 251			$viewType = (Mobile::isFromMobilePhone()) ? 'M' : 'P';
 252			$targetSrl = (Mobile::isFromMobilePhone()) ? 'mlayout_srl' : 'layout_srl';
 253
 254			// use the site default layout.
 255			if($module_info->{$targetSrl} == -1)
 256			{
 257				$oLayoutAdminModel = getAdminModel('layout');
 258				$layoutSrl = $oLayoutAdminModel->getSiteDefaultLayout($viewType, $module_info->site_srl);
 259			}
 260			else
 261			{
 262				$layoutSrl = $module_info->{$targetSrl};
 263			}
 264
 265			// reset a layout_srl in module_info.
 266			$module_info->{$targetSrl} = $layoutSrl;
 267
 268			$part_config = $oModuleModel->getModulePartConfig('layout', $layoutSrl);
 269			Context::addHtmlHeader($part_config->header_script);
 270		}
 271
 272		// Set module and mid into module_info
 273		if(!isset($this->module_info))
 274		{
 275			$this->module_info = new stdClass();
 276		}
 277		$this->module_info->module = $this->module;
 278		$this->module_info->mid = $this->mid;
 279
 280		// Set site_srl add 2011 08 09
 281		$this->module_info->site_srl = $site_module_info->site_srl;
 282
 283		// Still no module? it's an error
 284		if(!$this->module)
 285		{
 286			$this->error = 'msg_module_is_not_exists';
 287			$this->httpStatusCode = '404';
 288		}
 289
 290		// If mid exists, set mid into context
 291		if($this->mid)
 292		{
 293			Context::set('mid', $this->mid, TRUE);
 294		}
 295		
 296		// Call a trigger after moduleHandler init
 297		$output = ModuleHandler::triggerCall('moduleHandler.init', 'after', $this->module_info);
 298		if(!$output->toBool())
 299		{
 300			$this->error = $output->getMessage();
 301			return TRUE;
 302		}
 303
 304		// Set current module info into context
 305		Context::set('current_module_info', $this->module_info);
 306
 307		return TRUE;
 308	}
 309
 310	/**
 311	 * get a module instance and execute an action
 312	 * @return ModuleObject executed module instance
 313	 * */
 314	function procModule()
 315	{
 316		$oModuleModel = getModel('module');
 317
 318		// If error occurred while preparation, return a message instance
 319		if($this->error)
 320		{
 321			$this->_setInputErrorToContext();
 322			$type = Mobile::isFromMobilePhone() ? 'mobile' : 'view';
 323			$oMessageObject = ModuleHandler::getModuleInstance('message', $type);
 324			$oMessageObject->setError(-1);
 325			$oMessageObject->setMessage($this->error);
 326			$oMessageObject->dispMessage();
 327			if($this->httpStatusCode)
 328			{
 329				$oMessageObject->setHttpStatusCode($this->httpStatusCode);
 330			}
 331			return $oMessageObject;
 332		}
 333
 334		// Get action information with conf/module.xml
 335		$xml_info = $oModuleModel->getModuleActionXml($this->module);
 336
 337		// If not installed yet, modify act
 338		if($this->module == "install")
 339		{
 340			if(!$this->act || !$xml_info->action->{$this->act})
 341			{
 342				$this->act = $xml_info->default_index_act;
 343			}
 344		}
 345
 346		// if act exists, find type of the action, if not use default index act
 347		if(!$this->act)
 348		{
 349			$this->act = $xml_info->default_index_act;
 350		}
 351
 352		// still no act means error
 353		if(!$this->act)
 354		{
 355			$this->error = 'msg_module_is_not_exists';
 356			$this->httpStatusCode = '404';
 357
 358			$this->_setInputErrorToContext();
 359			$type = Mobile::isFromMobilePhone() ? 'mobile' : 'view';
 360			$oMessageObject = ModuleHandler::getModuleInstance('message', $type);
 361			$oMessageObject->setError(-1);
 362			$oMessageObject->setMessage($this->error);
 363			$oMessageObject->dispMessage();
 364			if($this->httpStatusCode)
 365			{
 366				$oMessageObject->setHttpStatusCode($this->httpStatusCode);
 367			}
 368			return $oMessageObject;
 369		}
 370
 371		// get type, kind
 372		$type = $xml_info->action->{$this->act}->type;
 373		$ruleset = $xml_info->action->{$this->act}->ruleset;
 374		$kind = stripos($this->act, 'admin') !== FALSE ? 'admin' : '';
 375		if(!$kind && $this->module == 'admin')
 376		{
 377			$kind = 'admin';
 378		}
 379
 380		// check REQUEST_METHOD in controller
 381		if($type == 'controller')
 382		{
 383			$allowedMethod = $xml_info->action->{$this->act}->method;
 384
 385			if(!$allowedMethod)
 386			{
 387				$allowedMethodList[0] = 'POST';
 388			}
 389			else
 390			{
 391				$allowedMethodList = explode('|', strtoupper($allowedMethod));
 392			}
 393
 394			if(!in_array(strtoupper($_SERVER['REQUEST_METHOD']), $allowedMethodList))
 395			{
 396				$this->error = "msg_invalid_request";
 397				$oMessageObject = ModuleHandler::getModuleInstance('message', 'view');
 398				$oMessageObject->setError(-1);
 399				$oMessageObject->setMessage($this->error);
 400				$oMessageObject->dispMessage();
 401				return $oMessageObject;
 402			}
 403		}
 404
 405		if($this->module_info->use_mobile != "Y")
 406		{
 407			Mobile::setMobile(FALSE);
 408		}
 409
 410		// Admin ip
 411		$logged_info = Context::get('logged_info');
 412		if($kind == 'admin' && $_SESSION['denied_admin'] == 'Y')
 413		{
 414			$this->_setInputErrorToContext();
 415			$this->error = "msg_not_permitted_act";
 416			$oMessageObject = ModuleHandler::getModuleInstance('message', $type);
 417			$oMessageObject->setError(-1);
 418			$oMessageObject->setMessage($this->error);
 419			$oMessageObject->dispMessage();
 420			return $oMessageObject;
 421		}
 422
 423		// if(type == view, and case for using mobilephone)
 424		if($type == "view" && Mobile::isFromMobilePhone() && Context::isInstalled())
 425		{
 426			$orig_type = "view";
 427			$type = "mobile";
 428			// create a module instance
 429			$oModule = $this->getModuleInstance($this->module, $type, $kind);
 430			if(!is_object($oModule) || !method_exists($oModule, $this->act))
 431			{
 432				$type = $orig_type;
 433				Mobile::setMobile(FALSE);
 434				$oModule = $this->getModuleInstance($this->module, $type, $kind);
 435			}
 436		}
 437		else
 438		{
 439			// create a module instance
 440			$oModule = $this->getModuleInstance($this->module, $type, $kind);
 441		}
 442
 443		if(!is_object($oModule))
 444		{
 445			$this->_setInputErrorToContext();
 446			$type = Mobile::isFromMobilePhone() ? 'mobile' : 'view';
 447			$oMessageObject = ModuleHandler::getModuleInstance('message', $type);
 448			$oMessageObject->setError(-1);
 449			$oMessageObject->setMessage($this->error);
 450			$oMessageObject->dispMessage();
 451			if($this->httpStatusCode)
 452			{
 453				$oMessageObject->setHttpStatusCode($this->httpStatusCode);
 454			}
 455			return $oMessageObject;
 456		}
 457
 458		// If there is no such action in the module object
 459		if(!isset($xml_info->action->{$this->act}) || !method_exists($oModule, $this->act))
 460		{
 461
 462			if(!Context::isInstalled())
 463			{
 464				$this->_setInputErrorToContext();
 465				$this->error = 'msg_invalid_request';
 466				$oMessageObject = ModuleHandler::getModuleInstance('message', $type);
 467				$oMessageObject->setError(-1);
 468				$oMessageObject->setMessage($this->error);
 469				$oMessageObject->dispMessage();
 470				if($this->httpStatusCode)
 471				{
 472					$oMessageObject->setHttpStatusCode($this->httpStatusCode);
 473				}
 474				return $oMessageObject;
 475			}
 476
 477			$forward = NULL;
 478			// 1. Look for the module with action name
 479			if(preg_match('/^([a-z]+)([A-Z])([a-z0-9\_]+)(.*)$/', $this->act, $matches))
 480			{
 481				$module = strtolower($matches[2] . $matches[3]);
 482				$xml_info = $oModuleModel->getModuleActionXml($module);
 483
 484				if($xml_info->action->{$this->act} && ((stripos($this->act, 'admin') !== FALSE) || $xml_info->action->{$this->act}->standalone != 'false'))
 485				{
 486					$forward = new stdClass();
 487					$forward->module = $module;
 488					$forward->type = $xml_info->action->{$this->act}->type;
 489					$forward->ruleset = $xml_info->action->{$this->act}->ruleset;
 490					$forward->act = $this->act;
 491				}
 492				else
 493				{
 494					$this->error = 'msg_invalid_request';
 495					$oMessageObject = ModuleHandler::getModuleInstance('message', 'view');
 496					$oMessageObject->setError(-1);
 497					$oMessageObject->setMessage($this->error);
 498					$oMessageObject->dispMessage();
 499
 500					return $oMessageObject;
 501				}
 502			}
 503
 504			if(!$forward)
 505			{
 506				$forward = $oModuleModel->getActionForward($this->act);
 507			}
 508
 509			if($forward->module && $forward->type && $forward->act && $forward->act == $this->act)
 510			{
 511				$kind = stripos($forward->act, 'admin') !== FALSE ? 'admin' : '';
 512				$type = $forward->type;
 513				$ruleset = $forward->ruleset;
 514				$tpl_path = $oModule->getTemplatePath();
 515				$orig_module = $oModule;
 516
 517				if($type == "view" && Mobile::isFromMobilePhone())
 518				{
 519					$orig_type = "view";
 520					$type = "mobile";
 521					// create a module instance
 522					$oModule = $this->getModuleInstance($forward->module, $type, $kind);
 523					if(!is_object($oModule) || !method_exists($oModule, $this->act))
 524					{
 525						$type = $orig_type;
 526						Mobile::setMobile(FALSE);
 527						$oModule = $this->getModuleInstance($forward->module, $type, $kind);
 528					}
 529				}
 530				else
 531				{
 532					$oModule = $this->getModuleInstance($forward->module, $type, $kind);
 533				}
 534
 535				if(!is_object($oModule))
 536				{
 537					$type = Mobile::isFromMobilePhone() ? 'mobile' : 'view';
 538					$this->_setInputErrorToContext();
 539					$oMessageObject = ModuleHandler::getModuleInstance('message', $type);
 540					$oMessageObject->setError(-1);
 541					$oMessageObject->setMessage('msg_module_is_not_exists');
 542					$oMessageObject->dispMessage();
 543					if($this->httpStatusCode)
 544					{
 545						$oMessageObject->setHttpStatusCode($this->httpStatusCode);
 546					}
 547					return $oMessageObject;
 548				}
 549
 550				$xml_info = $oModuleModel->getModuleActionXml($forward->module);
 551				$oMemberModel = getModel('member');
 552
 553				if($this->module == "admin" && $type == "view")
 554				{
 555					if($logged_info->is_admin == 'Y')
 556					{
 557						if($this->act != 'dispLayoutAdminLayoutModify')
 558						{
 559							$oAdminView = getAdminView('admin');
 560							$oAdminView->makeGnbUrl($forward->module);
 561							$oModule->setLayoutPath("./modules/admin/tpl");
 562							$oModule->setLayoutFile("layout.html");
 563						}
 564					}
 565					else
 566					{
 567						$this->_setInputErrorToContext();
 568
 569						$this->error = 'msg_is_not_administrator';
 570						$oMessageObject = ModuleHandler::getModuleInstance('message', $type);
 571						$oMessageObject->setError(-1);
 572						$oMessageObject->setMessage($this->error);
 573						$oMessageObject->dispMessage();
 574						return $oMessageObject;
 575					}
 576				}
 577				if($kind == 'admin')
 578				{
 579					$grant = $oModuleModel->getGrant($this->module_info, $logged_info);
 580					if(!$grant->is_admin && !$grant->manager)
 581					{
 582						$this->_setInputErrorToContext();
 583						$this->error = 'msg_is_not_manager';
 584						$oMessageObject = ModuleHandler::getModuleInstance('message', 'view');
 585						$oMessageObject->setError(-1);
 586						$oMessageObject->setMessage($this->error);
 587						$oMessageObject->dispMessage();
 588						return $oMessageObject;
 589					}
 590				}
 591			}
 592			else if($xml_info->default_index_act && method_exists($oModule, $xml_info->default_index_act))
 593			{
 594				$this->act = $xml_info->default_index_act;
 595			}
 596			else
 597			{
 598				$this->error = 'msg_invalid_request';
 599				$oModule->setError(-1);
 600				$oModule->setMessage($this->error);
 601				return $oModule;
 602			}
 603		}
 604
 605		// ruleset check...
 606		if(!empty($ruleset))
 607		{
 608			$rulesetModule = $forward->module ? $forward->module : $this->module;
 609			$rulesetFile = $oModuleModel->getValidatorFilePath($rulesetModule, $ruleset, $this->mid);
 610			if(!empty($rulesetFile))
 611			{
 612				if($_SESSION['XE_VALIDATOR_ERROR_LANG'])
 613				{
 614					$errorLang = $_SESSION['XE_VALIDATOR_ERROR_LANG'];
 615					foreach($errorLang as $key => $val)
 616					{
 617						Context::setLang($key, $val);
 618					}
 619					unset($_SESSION['XE_VALIDATOR_ERROR_LANG']);
 620				}
 621
 622				$Validator = new Validator($rulesetFile);
 623				$result = $Validator->validate();
 624				if(!$result)
 625				{
 626					$lastError = $Validator->getLastError();
 627					$returnUrl = Context::get('error_return_url');
 628					$errorMsg = $lastError['msg'] ? $lastError['msg'] : 'validation error';
 629
 630					//for xml response
 631					$oModule->setError(-1);
 632					$oModule->setMessage($errorMsg);
 633					//for html redirect
 634					$this->error = $errorMsg;
 635					$_SESSION['XE_VALIDATOR_ERROR'] = -1;
 636					$_SESSION['XE_VALIDATOR_MESSAGE'] = $this->error;
 637					$_SESSION['XE_VALIDATOR_MESSAGE_TYPE'] = 'error';
 638					$_SESSION['XE_VALIDATOR_RETURN_URL'] = $returnUrl;
 639					$_SESSION['XE_VALIDATOR_ID'] = Context::get('xe_validator_id');
 640					$this->_setInputValueToSession();
 641					return $oModule;
 642				}
 643			}
 644		}
 645
 646		$oModule->setAct($this->act);
 647
 648		$this->module_info->module_type = $type;
 649		$oModule->setModuleInfo($this->module_info, $xml_info);
 650
 651		$skipAct = array(
 652				'dispEditorConfigPreview' => 1,
 653				'dispLayoutPreviewWithModule' => 1
 654		);
 655		if($type == "view" && $this->module_info->use_mobile == "Y" && Mobile::isMobileCheckByAgent() && !isset($skipAct[Context::get('act')]))
 656		{
 657			global $lang;
 658			$header = '<style>div.xe_mobile{opacity:0.7;margin:1em 0;padding:.5em;background:#333;border:1px solid #666;border-left:0;border-right:0}p.xe_mobile{text-align:center;margin:1em 0}a.xe_mobile{color:#ff0;font-weight:bold;font-size:24px}@media only screen and (min-width:500px){a.xe_mobile{font-size:15px}}</style>';
 659			$footer = '<div class="xe_mobile"><p class="xe_mobile"><a class="xe_mobile" href="' . getUrl('m', '1') . '">' . $lang->msg_pc_to_mobile . '</a></p></div>';
 660			Context::addHtmlHeader($header);
 661			Context::addHtmlFooter($footer);
 662		}
 663
 664		if($type == "view" && $kind != 'admin')
 665		{
 666			$module_config = $oModuleModel->getModuleConfig('module');
 667			if($module_config->htmlFooter)
 668			{
 669				Context::addHtmlFooter($module_config->htmlFooter);
 670			}
 671			if($module_config->siteTitle)
 672			{
 673				$siteTitle = Context::getBrowserTitle();
 674				if(!$siteTitle)
 675				{
 676					Context::setBrowserTitle($module_config->siteTitle);
 677				}
 678			}
 679		}
 680
 681		// if failed message exists in session, set context
 682		$this->_setInputErrorToContext();
 683
 684		$procResult = $oModule->proc();
 685
 686		$methodList = array('XMLRPC' => 1, 'JSON' => 1, 'JS_CALLBACK' => 1);
 687		if(!$oModule->stop_proc && !isset($methodList[Context::getRequestMethod()]))
 688		{
 689			$error = $oModule->getError();
 690			$message = $oModule->getMessage();
 691			$messageType = $oModule->getMessageType();
 692			$redirectUrl = $oModule->getRedirectUrl();
 693			if($messageType == 'error') debugPrint($message, 'ERROR');
 694
 695			if(!$procResult)
 696			{
 697				$this->error = $message;
 698				if(!$redirectUrl && Context::get('error_return_url'))
 699				{
 700					$redirectUrl = Context::get('error_return_url');
 701				}
 702				$this->_setInputValueToSession();
 703			}
 704			else
 705			{
 706
 707			}
 708
 709			$_SESSION['XE_VALIDATOR_ERROR'] = $error;
 710			$_SESSION['XE_VALIDATOR_ID'] = Context::get('xe_validator_id');
 711			if($message != 'success')
 712			{
 713				$_SESSION['XE_VALIDATOR_MESSAGE'] = $message;
 714			}
 715			$_SESSION['XE_VALIDATOR_MESSAGE_TYPE'] = $messageType;
 716
 717			if(Context::get('xeVirtualRequestMethod') != 'xml')
 718			{
 719				$_SESSION['XE_VALIDATOR_RETURN_URL'] = $redirectUrl;
 720			}
 721		}
 722
 723		unset($logged_info);
 724		return $oModule;
 725	}
 726
 727	/**
 728	 * set error message to Session.
 729	 * @return void
 730	 * */
 731	function _setInputErrorToContext()
 732	{
 733		if($_SESSION['XE_VALIDATOR_ERROR'] && !Context::get('XE_VALIDATOR_ERROR'))
 734		{
 735			Context::set('XE_VALIDATOR_ERROR', $_SESSION['XE_VALIDATOR_ERROR']);
 736		}
 737		if($_SESSION['XE_VALIDATOR_MESSAGE'] && !Context::get('XE_VALIDATOR_MESSAGE'))
 738		{
 739			Context::set('XE_VALIDATOR_MESSAGE', $_SESSION['XE_VALIDATOR_MESSAGE']);
 740		}
 741		if($_SESSION['XE_VALIDATOR_MESSAGE_TYPE'] && !Context::get('XE_VALIDATOR_MESSAGE_TYPE'))
 742		{
 743			Context::set('XE_VALIDATOR_MESSAGE_TYPE', $_SESSION['XE_VALIDATOR_MESSAGE_TYPE']);
 744		}
 745		if($_SESSION['XE_VALIDATOR_RETURN_URL'] && !Context::get('XE_VALIDATOR_RETURN_URL'))
 746		{
 747			Context::set('XE_VALIDATOR_RETURN_URL', $_SESSION['XE_VALIDATOR_RETURN_URL']);
 748		}
 749		if($_SESSION['XE_VALIDATOR_ID'] && !Context::get('XE_VALIDATOR_ID'))
 750		{
 751			Context::set('XE_VALIDATOR_ID', $_SESSION['XE_VALIDATOR_ID']);
 752		}
 753		if(count($_SESSION['INPUT_ERROR']))
 754		{
 755			Context::set('INPUT_ERROR', $_SESSION['INPUT_ERROR']);
 756		}
 757
 758		$this->_clearErrorSession();
 759	}
 760
 761	/**
 762	 * clear error message to Session.
 763	 * @return void
 764	 * */
 765	function _clearErrorSession()
 766	{
 767		$_SESSION['XE_VALIDATOR_ERROR'] = '';
 768		$_SESSION['XE_VALIDATOR_MESSAGE'] = '';
 769		$_SESSION['XE_VALIDATOR_MESSAGE_TYPE'] = '';
 770		$_SESSION['XE_VALIDATOR_RETURN_URL'] = '';
 771		$_SESSION['XE_VALIDATOR_ID'] = '';
 772		$_SESSION['INPUT_ERROR'] = '';
 773	}
 774
 775	/**
 776	 * occured error when, set input values to session.
 777	 * @return void
 778	 * */
 779	function _setInputValueToSession()
 780	{
 781		$requestVars = Context::getRequestVars();
 782		unset($requestVars->act, $requestVars->mid, $requestVars->vid, $requestVars->success_return_url, $requestVars->error_return_url);
 783		foreach($requestVars AS $key => $value)
 784		{
 785			$_SESSION['INPUT_ERROR'][$key] = $value;
 786		}
 787	}
 788
 789	/**
 790	 * display contents from executed module
 791	 * @param ModuleObject $oModule module instance
 792	 * @return void
 793	 * */
 794	function displayContent($oModule = NULL)
 795	{
 796		// If the module is not set or not an object, set error
 797		if(!$oModule || !is_object($oModule))
 798		{
 799			$this->error = 'msg_module_is_not_exists';
 800			$this->httpStatusCode = '404';
 801		}
 802
 803		// If connection to DB has a problem even though it's not install module, set error
 804		if($this->module != 'install' && isset($GLOBALS['__DB__']) && $GLOBALS['__DB__'][Context::getDBType()]->isConnected() == FALSE)
 805		{
 806			$this->error = 'msg_dbconnect_failed';
 807		}
 808
 809		// Call trigger after moduleHandler proc
 810		$output = ModuleHandler::triggerCall('moduleHandler.proc', 'after', $oModule);
 811		if(!$output->toBool())
 812		{
 813			$this->error = $output->getMessage();
 814		}
 815
 816		// Use message view object, if HTML call
 817		$methodList = array('XMLRPC' => 1, 'JSON' => 1, 'JS_CALLBACK' => 1);
 818		if(!isset($methodList[Context::getRequestMethod()]))
 819		{
 820
 821			if($_SESSION['XE_VALIDATOR_RETURN_URL'])
 822			{
 823				$display_handler = new DisplayHandler();
 824				$display_handler->_debugOutput();
 825
 826				header('location:' . $_SESSION['XE_VALIDATOR_RETURN_URL']);
 827				return;
 828			}
 829
 830			// If error occurred, handle it
 831			if($this->error)
 832			{
 833				// display content with message module instance
 834				$type = Mobile::isFromMobilePhone() ? 'mobile' : 'view';
 835				$oMessageObject = ModuleHandler::getModuleInstance('message', $type);
 836				$oMessageObject->setError(-1);
 837				$oMessageObject->setMessage($this->error);
 838				$oMessageObject->dispMessage();
 839
 840				if($oMessageObject->getHttpStatusCode() && $oMessageObject->getHttpStatusCode() != '200')
 841				{
 842					$this->_setHttpStatusMessage($oMessageObject->getHttpStatusCode());
 843					$oMessageObject->setTemplateFile('http_status_code');
 844				}
 845
 846				// If module was called normally, change the templates of the module into ones of the message view module
 847				if($oModule)
 848				{
 849					$oModule->setTemplatePath($oMessageObject->getTemplatePath());
 850					$oModule->setTemplateFile($oMessageObject->getTemplateFile());
 851					// Otherwise, set message instance as the target module
 852				}
 853				else
 854				{
 855					$oModule = $oMessageObject;
 856				}
 857
 858				$this->_clearErrorSession();
 859			}
 860
 861			// Check if layout_srl exists for the module
 862			if(Mobile::isFromMobilePhone())
 863			{
 864				$layout_srl = $oModule->module_info->mlayout_srl;
 865			}
 866			else
 867			{
 868				$layout_srl = $oModule->module_info->layout_srl;
 869			}
 870
 871			// if layout_srl is rollback by module, set default layout
 872			if($layout_srl == -1)
 873			{
 874				$viewType = (Mobile::isFromMobilePhone()) ? 'M' : 'P';
 875				$oLayoutAdminModel = getAdminModel('layout');
 876				$layout_srl = $oLayoutAdminModel->getSiteDefaultLayout($viewType, $oModule->module_info->site_srl);
 877			}
 878
 879			if($layout_srl && !$oModule->getLayoutFile())
 880			{
 881
 882				// If layout_srl exists, get information of the layout, and set the location of layout_path/ layout_file
 883				$oLayoutModel = getModel('layout');
 884				$layout_info = $oLayoutModel->getLayout($layout_srl);
 885				if($layout_info)
 886				{
 887
 888					// Input extra_vars into $layout_info
 889					if($layout_info->extra_var_count)
 890					{
 891
 892						foreach($layout_info->extra_var as $var_id => $val)
 893						{
 894							if($val->type == 'image')
 895							{
 896								if(strncmp('./files/attach/images/', $val->value, 22) === 0)
 897								{
 898									$val->value = Context::getRequestUri() . substr($val->value, 2);
 899								}
 900							}
 901							$layout_info->{$var_id} = $val->value;
 902						}
 903					}
 904					// Set menus into context
 905					if($layout_info->menu_count)
 906					{
 907						foreach($layout_info->menu as $menu_id => $menu)
 908						{
 909							// set default menu set(included home menu)
 910							if(!$menu->menu_srl || $menu->menu_srl == -1)
 911							{
 912								$oMenuAdminController = getAdminController('menu');
 913								$homeMenuCacheFile = $oMenuAdminController->getHomeMenuCacheFile();
 914
 915								if(FileHandler::exists($homeMenuCacheFile))
 916								{
 917									include($homeMenuCacheFile);
 918								}
 919
 920								if(!$menu->menu_srl)
 921								{
 922									$menu->xml_file = str_replace('.xml.php', $homeMenuSrl . '.xml.php', $menu->xml_file);
 923									$menu->php_file = str_replace('.php', $homeMenuSrl . '.php', $menu->php_file);
 924									$layout_info->menu->{$menu_id}->menu_srl = $homeMenuSrl;
 925								}
 926								else
 927								{
 928									$menu->xml_file = str_replace($menu->menu_srl, $homeMenuSrl, $menu->xml_file);
 929									$menu->php_file = str_replace($menu->menu_srl, $homeMenuSrl, $menu->php_file);
 930								}
 931							}
 932
 933							$php_file = FileHandler::exists($menu->php_file);
 934							if($php_file)
 935							{
 936								include($php_file);
 937							}
 938							Context::set($menu_id, $menu);
 939						}
 940					}
 941
 942					// Set layout information into context
 943					Context::set('layout_info', $layout_info);
 944
 945					$oModule->setLayoutPath($layout_info->path);
 946					$oModule->setLayoutFile('layout');
 947
 948					// If layout was modified, use the modified version
 949					$edited_layout = $oLayoutModel->getUserLayoutHtml($layout_info->layout_srl);
 950					if(file_exists($edited_layout))
 951					{
 952						$oModule->setEditedLayoutFile($edited_layout);
 953					}
 954				}
 955			}
 956			$isLayoutDrop = Context::get('isLayoutDrop');
 957			if($isLayoutDrop)
 958			{
 959				$kind = stripos($this->act, 'admin') !== FALSE ? 'admin' : '';
 960				if($kind == 'admin')
 961				{
 962					$oModule->setLayoutFile('popup_layout');
 963				}
 964				else
 965				{
 966					$oModule->setLayoutPath('common/tpl');
 967					$oModule->setLayoutFile('default_layout');
 968				}
 969			}
 970		}
 971
 972		// Display contents
 973		$oDisplayHandler = new DisplayHandler();
 974		$oDisplayHandler->printContent($oModule);
 975	}
 976
 977	/**
 978	 * returns module's path
 979	 * @param string $module module name
 980	 * @return string path of the module
 981	 * */
 982	function getModulePath($module)
 983	{
 984		return sprintf('./modules/%s/', $module);
 985	}
 986
 987	/**
 988	 * It creates a module instance
 989	 * @param string $module module name
 990	 * @param string $type instance type, (e.g., view, controller, model)
 991	 * @param string $kind admin or svc
 992	 * @return ModuleObject module instance (if failed it returns null)
 993	 * @remarks if there exists a module instance created before, returns it.
 994	 * */
 995	function &getModuleInstance($module, $type = 'view', $kind = '')
 996	{
 997
 998		if(__DEBUG__ == 3)
 999		{
1000			$start_time = getMicroTime();
1001		}
1002
1003		$parent_module = $module;
1004		$kind = strtolower($kind);
1005		$type = strtolower($type);
1006
1007		$kinds = array('svc' => 1, 'admin' => 1);
1008		if(!isset($kinds[$kind]))
1009		{
1010			$kind = 'svc';
1011		}
1012
1013		$key = $module . '.' . ($kind != 'admin' ? '' : 'admin') . '.' . $type;
1014
1015		if(is_array($GLOBALS['__MODULE_EXTEND__']) && array_key_exists($key, $GLOBALS['__MODULE_EXTEND__']))
1016		{
1017			$module = $extend_module = $GLOBALS['__MODULE_EXTEND__'][$key];
1018		}
1019
1020		// if there is no instance of the module in global variable, create a new one
1021		if(!isset($GLOBALS['_loaded_module'][$module][$type][$kind]))
1022		{
1023			ModuleHandler::_getModuleFilePath($module, $type, $kind, $class_path, $high_class_file, $class_file, $instance_name);
1024
1025			if($extend_module && (!is_readable($high_class_file) || !is_readable($class_file)))
1026			{
1027				$module = $parent_module;
1028				ModuleHandler::_getModuleFilePath($module, $type, $kind, $class_path, $high_class_file, $class_file, $instance_name);
1029			}
1030
1031			// Get base class name and load the file contains it
1032			if(!class_exists($module, false))
1033			{
1034				$high_class_file = sprintf('%s%s%s.class.php', _XE_PATH_, $class_path, $module);
1035				if(!file_exists($high_class_file))
1036				{
1037					return NULL;
1038				}
1039				require_once($high_class_file);
1040			}
1041
1042			// Get the name of the class file
1043			if(!is_readable($class_file))
1044			{
1045				return NULL;
1046			}
1047
1048			// Create an instance with eval function
1049			require_once($class_file);
1050			if(!class_exists($instance_name, false))
1051			{
1052				return NULL;
1053			}
1054			$tmp_fn = create_function('', "return new {$instance_name}();");
1055			$oModule = $tmp_fn();
1056			if(!is_object($oModule))
1057			{
1058				return NULL;
1059			}
1060
1061			// Load language files for the class
1062			Context::loadLang($class_path . 'lang');
1063			if($extend_module)
1064			{
1065				Context::loadLang(ModuleHandler::getModulePath($parent_module) . 'lang');
1066			}
1067
1068			// Set variables to the instance
1069			$oModule->setModule($module);
1070			$oModule->setModulePath($class_path);
1071
1072			// If the module has a constructor, run it.
1073			if(!isset($GLOBALS['_called_constructor'][$instance_name]))
1074			{
1075				$GLOBALS['_called_constructor'][$instance_name] = TRUE;
1076				if(@method_exists($oModule, $instance_name))
1077				{
1078					$oModule->{$instance_name}();
1079				}
1080			}
1081
1082			// Store the created instance into GLOBALS variable
1083			$GLOBALS['_loaded_module'][$module][$type][$kind] = $oModule;
1084		}
1085
1086		if(__DEBUG__ == 3)
1087		{
1088			$GLOBALS['__elapsed_class_load__'] += getMicroTime() - $start_time;
1089		}
1090
1091		// return the instance
1092		return $GLOBALS['_loaded_module'][$module][$type][$kind];
1093	}
1094
1095	function _getModuleFilePath($module, $type, $kind, &$classPath, &$highClassFile, &$classFile, &$instanceName)
1096	{
1097		$classPath = ModuleHandler::getModulePath($module);
1098
1099		$highClassFile = sprintf('%s%s%s.class.php', _XE_PATH_, $classPath, $module);
1100		$highClassFile = FileHandler::getRealPath($highClassFile);
1101
1102		$types = array('view','controller','model','api','wap','mobile','class');
1103		if(!in_array($type, $types))
1104		{
1105			$type = $types[0];
1106		}
1107		if($type == 'class')
1108		{
1109			$instanceName = '%s';
1110			$classFile = '%s%s.%s.php';
1111		}
1112		elseif($kind == 'admin' && array_search($type, $types) < 3)
1113		{
1114			$instanceName = '%sAdmin%s';
1115			$classFile = '%s%s.admin.%s.php';
1116		}
1117		else
1118		{
1119			$instanceName = '%s%s';
1120			$classFile = '%s%s.%s.php';
1121		}
1122
1123		$instanceName = sprintf($instanceName, $module, ucfirst($type));
1124		$classFile = FileHandler::getRealPath(sprintf($classFile, $classPath, $module, $type));
1125	}
1126
1127	/**
1128	 * call a trigger
1129	 * @param string $trigger_name trigger's name to call
1130	 * @param string $called_position called position
1131	 * @param object $obj an object as a parameter to trigger
1132	 * @return Object
1133	 * */
1134	function triggerCall($trigger_name, $called_position, &$obj)
1135	{
1136		// skip if not installed
1137		if(!Context::isInstalled())
1138		{
1139			return new Object();
1140		}
1141
1142		$oModuleModel = getModel('module');
1143		$triggers = $oModuleModel->getTriggers($trigger_name, $called_position);
1144		if(!$triggers || count($triggers) < 1)
1145		{
1146			return new Object();
1147		}
1148
1149		foreach($triggers as $item)
1150		{
1151			$module = $item->module;
1152			$type = $item->type;
1153			$called_method = $item->called_method;
1154
1155			// todo why don't we call a normal class object ?
1156			$oModule = getModule($module, $type);
1157			if(!$oModule || !method_exists($oModule, $called_method))
1158			{
1159				continue;
1160			}
1161
1162			$output = $oModule->{$called_method}($obj);
1163			if(is_object($output) && method_exists($output, 'toBool') && !$output->toBool())
1164			{
1165				return $output;
1166			}
1167			unset($oModule);
1168		}
1169
1170		return new Object();
1171	}
1172
1173	/**
1174	 * get http status message by http status code
1175	 * @param string $code
1176	 * @return string
1177	 * */
1178	function _setHttpStatusMessage($code)
1179	{
1180		$statusMessageList = array(
1181			'100' => 'Continue',
1182			'101' => 'Switching Protocols',
1183			'201' => 'OK', // todo check array key '201'
1184			'201' => 'Created',
1185			'202' => 'Accepted',
1186			'203' => 'Non-Authoritative Information',
1187			'204' => 'No Content',
1188			'205' => 'Reset Content',
1189			'206' => 'Partial Content',
1190			'300' => 'Multiple Choices',
1191			'301' => 'Moved Permanently',
1192			'302' => 'Found',
1193			'303' => 'See Other',
1194			'304' => 'Not Modified',
1195			'305' => 'Use Proxy',
1196			'307' => 'Temporary Redirect',
1197			'400' => 'Bad Request',
1198			'401' => 'Unauthorized',
1199			'402' => 'Payment Required',
1200			'403' => 'Forbidden',
1201			'404' => 'Not Found',
1202			'405' => 'Method Not Allowed',
1203			'406' => 'Not Acceptable',
1204			'407' => 'Proxy Authentication Required',
1205			'408' => 'Request Timeout',
1206			'409' => 'Conflict',
1207			'410' => 'Gone',
1208			'411' => 'Length Required',
1209			'412' => 'Precondition Failed',
1210			'413' => 'Request Entity Too Large',
1211			'414' => 'Request-URI Too Long',
1212			'415' => 'Unsupported Media Type',
1213			'416' => 'Requested Range Not Satisfiable',
1214			'417' => 'Expectation Failed',
1215			'500' => 'Internal Server Error',
1216			'501' => 'Not Implemented',
1217			'502' => 'Bad Gateway',
1218			'503' => 'Service Unavailable',
1219			'504' => 'Gateway Timeout',
1220			'505' => 'HTTP Version Not Supported',
1221		);
1222		$statusMessage = $statusMessageList[$code];
1223		if(!$statusMessage)
1224		{
1225			$statusMessage = 'OK';
1226		}
1227
1228		Context::set('http_status_code', $code);
1229		Context::set('http_status_message', $statusMessage);
1230	}
1231
1232}
1233/* End of file ModuleHandler.class.php */
1234/* Location: ./classes/module/ModuleHandler.class.php */