<?php
/**
 * @package Legacy
 * @version $Id: Legacy_Controller.class.php,v 1.1.2.64 2006/08/08 07:46:08 minahito Exp $
 */

if (!defined('XOOPS_ROOT_PATH')) exit();

define("LEGACY_CONTROLLER_STATE_PUBLIC", 1);
define("LEGACY_CONTROLLER_STATE_ADMIN", 2);

require_once XOOPS_ROOT_PATH . "/modules/base/kernel/Legacy_BlockProcedure.class.php";

/**
 * This class is a virtual controller that has the compatibility with XOOPS 2.0.x.
 * 
 * [NOTICE]
 * XOOPS 2.0.x can switch to public mode and control panel mode. This controller
 * emulates its process with using STATE. But, we may lose flexible setup by this
 * implement. Now, we are investigating the influence.
 *
 * [TODO]
 * XCube_Controller keeps a process that set up instances of some legacy classes,
 * yet. We should move its process to this controller.
 */
class Legacy_Controller extends XCube_Controller
{
	var $mXoopsUser;

	var $_mAdminModeFlag = false;
	var $_mStrategy = null;
	
	var $mDialogMode = false;
	
	/**
	 * @todo Rename this with "mModule"
	 */
	var $mModuleController = null;
	
	/**
	 * @var XCube_Deleagate
	 */
	var $mSiteLogin = null;
	
	/**
	 * @var XCube_Delegate
	 */
	var $mGetCountUnreadPM = null;
	
	/**
	 * @var XCube_Delegate
	 */
	var $mGetPMInboxUrl = null;
	
	/**
	 * @var XCube_Delegate
	 */
	var $mCheckLogin = null;
	
	/**
	 * @var XCube_Delegate
	 */
	var $mLogout = null;
	
	/**
	 * @var XCube_Delegate
	 */
	var $mCreateLanguageManager = null;
	
	var $mBlockShowFlags = array();
	var $mBlockContents = array();
	
	/**
	 * @deprecated
	 */
	var $mRenderSystem = null;
	
	function Legacy_Controller()
	{
		//
		// Setup member properties as member delegates.
		//
		$this->mSiteLogin =& new XCube_Delegate();
		$this->mSiteLogin->register("Site.Login");
		
		$this->mGetCountUnreadPM =& new XCube_Delegate();
		$this->mGetPMInboxUrl =& new XCube_Delegate();
		
		$this->mCheckLogin =& new XCube_Delegate();
		$this->mCheckLogin->register("Site.CheckLogin");
		
		$this->mLogout =& new XCube_Delegate();
		$this->mLogout->register("Site.Logout");
		
		$this->mCreateLanguageManager =& new XCube_Delegate();
		$this->mCreateLanguageManager->register("Legacy_Controller.CreateLanguageManager");
				
		set_magic_quotes_runtime(0);	// ^^;
		
		//
		// Decide status. [TEST]
		//
		$urlInfo=$this->_parseUrl();
		$adminStateFlag=false;

		if(count($urlInfo)>=3) {
			if(strtolower($urlInfo[0])=="modules" && strtolower($urlInfo[2])=="admin"){
				$adminStateFlag=true;
			}
			elseif($urlInfo[0] == "modules" && $urlInfo[1] == "system" && substr($urlInfo[2], 0, 9) == "admin.php") {
				$adminStateFlag=true;
			}
		}
		elseif(substr($urlInfo[0], 0, 9) == "admin.php") {
			$adminStateFlag=true;
		}

		$this->_mStrategy = $adminStateFlag ?  new Legacy_AdminControllerStrategy($this) : new Legacy_PublicControllerStrategy($this);
	}

	/**
	 * @access public
	 */
	function executeCommon()
	{
		//
		// Setup Filter chain and execute the process of these filters.
		//
		$this->_setupFilterChain();
		$this->_processFilter();

		// ^^;
		$this->_setupErrorHandler();

		$this->_setupEnvironment();
		
		$this->_setupLogger();

		$this->_setupDB();

        $this->_setupLanguage();

		$this->_setupConfig();
		
		$this->_setupDebugger();

		$this->_processPreBlockFilter();	// What's !?

		$this->_processHostAbstractLayer();

		$this->_setupSession();

		$this->_setupUser();

		$this->_setupModuleController();

		$this->_processModuleController();
	}
	
	function _setupLogger()
	{
		require_once XOOPS_ROOT_PATH.'/class/logger.php';
		$this->mLogger=&XoopsLogger::instance();
		$this->mLogger->startTime();

		$GLOBALS['xoopsLogger']=&$this->mLogger;
	}

	function _setupEnvironment()
	{
		parent::_setupEnvironment();
		require_once XOOPS_ROOT_PATH."/include/version.php";
		
		require_once XOOPS_ROOT_PATH."/settings/definition.inc.php";
		define("XOOPS_BASE_PATH",XOOPS_MODULE_PATH."/".XOOPS_BASE_PROC_NAME);

		require_once XOOPS_ROOT_PATH.'/include/functions.php';

		require_once XOOPS_ROOT_PATH.'/kernel/object.php';
		require_once XOOPS_ROOT_PATH.'/class/criteria.php';
		require_once XOOPS_ROOT_PATH.'/class/token.php';
		require_once XOOPS_ROOT_PATH."/class/module.textsanitizer.php";

		require_once XOOPS_BASE_PATH."/kernel/object.php";				// ToDo (here?)
		require_once XOOPS_BASE_PATH."/kernel/handler.php";				// ToDo
		require_once XOOPS_ROOT_PATH."/class/XCube_Utils.class.php";	// ToDo

		require_once XOOPS_ROOT_PATH.'/class/xoopssecurity.php';
		$_GLOBALS['xoopsSecurity'] = new XoopsSecurity();

		require_once XOOPS_ROOT_PATH."/include/version.php";
	}

	/**
	 * [NOTICE]
	 * We set up only filters that are decided to register by us. This is not
	 * flexible. This is not the style fixed.
	 *
	 * [MEMO]
	 * For test, you can use automatic loading plug-in with writing a setting
	 * in site_custom.ini.php.
	 * 
	 * site_custom.ini.php:
	 *  [Legacy]
	 *  AutoPreload = 1
	 *
	 */
	function _setupFilterChain()
	{
		$primaryPreloads = $this->mRoot->getSiteConfig('Legacy.PrimaryPreloads');
		foreach ($primaryPreloads as $className => $classPath) {
			if (file_exists(XOOPS_ROOT_PATH . $classPath)) {
				require_once XOOPS_ROOT_PATH . $classPath;
				if (class_exists($className)) {
					$filter =& new $className($this);
					$this->addActionFilter($filter);
					unset($filter);
				}
			}
		}

		//
		// Auto pre-loading.
		//
		if($this->mRoot->getSiteConfig('Legacy', 'AutoPreload')==1) {
			$this->_executePreload(XOOPS_ROOT_PATH . "/preload");
		}
	}

	function _setupBlock()
	{
		$this->_mStrategy->setupBlock();
	}

	/**
	 * Process of Block. Fetch objects from $this->mBlockChain, render the
	 * result of the object with html data, and set those result to member
	 * property.
	 * 
	 * In this member function, the cache mechanism has to be important. If the
	 * object has its cache, this function loads the cache data instead of
	 * calling the business logic of the block.
	 *
	 * @access protected
	 */
	function _processBlock()
	{
		$i=0;
		
		//
		// Create render-target for blocks. We use reset() to re-cycle this
		// object in the foreach loop.
		//
		$renderTarget =& new XCube_RenderTarget();
		$renderTarget->setType(XCUBE_RENDER_TARGET_TYPE_BLOCK);
		
		$cache =& $this->mRoot->getCacheSystem();

		foreach ($this->mBlockChain as $blockProcedure) {
			$cache->reset();
			$renderTarget->reset();

			$cache->setResourceName("block" . $blockProcedure->getId());
			if ($cache->isCache($blockProcedure->getCacheTime())) {
				$content = $cache->load();
				if ($content) {
					$this->mBlockShowFlags[$blockProcedure->getEntryIndex()] = true;
					$this->mBlockContents[$blockProcedure->getEntryIndex()][] = array(
							'name' => $blockProcedure->getName(),
							'title'   => $blockProcedure->getTitle(),
							'content' => $content,
							'weight'  => $blockProcedure->getWeight()
					);
				}
			}
			else {
				$blockProcedure->execute($this, $this->getXoopsUser(), $renderTarget);

				if (!$blockProcedure->hasResult()) {
					continue;
				}
				
				$renderSystem =& $this->mRoot->getRenderSystem($blockProcedure->getRenderSystemName());
				$renderSystem->renderBlock($renderTarget);
				
				$this->mBlockShowFlags[$blockProcedure->getEntryIndex()] = true;
				$this->mBlockContents[$blockProcedure->getEntryIndex()][] = array(
						'name' => $blockProcedure->getName(),
						'title'=>$blockProcedure->getTitle(),
						'content'=>$renderTarget->getResult(),
						'weight'=>$blockProcedure->getWeight()
				);

				if ($blockProcedure->getCacheTime() > 0) {
					$cache->save($renderTarget);
				}
			}

			unset($blockProcedure);
		}
	}

	function _parseUrl()
	{
		$ret = array();
		
		$nakedRootPath=substr(strstr(XOOPS_URL,$_SERVER['HTTP_HOST']),strlen($_SERVER['HTTP_HOST'])) . "/";
		$subPath=substr($_SERVER['REQUEST_URI'],strlen($nakedRootPath));

		return explode("/",$subPath);
	}

	function _setupModuleController()
	{
		$this->_mStrategy->setupModuleController();
	}

	function _processModuleController()
	{
		$this->mModuleController->prepare();

		if ($this->mModuleController->isModuleProcess()) {
			if (!$this->mModuleController->isActive()) {
				die('NOT ACTIVE');	///< @todo
			}

   			if (!$this->mModuleController->hasPermission()) {
				$this->executeRedirect(XOOPS_URL,1,_NOPERM);	// TODO Depens on const message catalog.
   			}

			$this->mModuleController->setupLanguage();
			
			$GLOBALS['xoopsModule'] =& $this->mModuleController->mModuleObject;			// TODO
			$GLOBALS['xoopsModuleConfig'] = $this->mModuleController->getConfig();
		}
	}

	function _processHostAbstractLayer()
	{
		if ( !isset($_SERVER['PATH_TRANSLATED']) && isset($_SERVER['SCRIPT_FILENAME']) ) {
			// There is this setting for CGI mode. @todo We have to confirm this.
			$_SERVER['PATH_TRANSLATED'] =& $_SERVER['SCRIPT_FILENAME'];
		} elseif ( isset($_SERVER['PATH_TRANSLATED']) && !isset($_SERVER['SCRIPT_FILENAME']) ) {
			// There is this setting for IIS Win2K. Really?
			$_SERVER['SCRIPT_FILENAME'] =& $_SERVER['PATH_TRANSLATED'];
		}

		// IIS does not set REQUEST_URI. This system defines it. But...
		if (empty($_SERVER['REQUEST_URI'])) {
			if ( !( $_SERVER[ 'REQUEST_URI' ] = @$_SERVER['PHP_SELF'] ) ) {
				$_SERVER[ 'REQUEST_URI' ] = $_SERVER['SCRIPT_NAME'];
			}
			if ( isset( $_SERVER[ 'QUERY_STRING' ] ) ) {
				$_SERVER[ 'REQUEST_URI' ] .= '?' . $_SERVER[ 'QUERY_STRING' ];
			}
		    
			// Guard for XSS string of PHP_SELF
			// @todo I must move this logic to preload plugin.
			if(preg_match("/[\<\>\"\'\(\)]/",$_SERVER['REQUEST_URI']))
				die();
		}

		// What is this!? But, old system depends this setting. We have to confirm it and modify!
		$GLOBALS['xoopsRequestUri'] = $_SERVER[ 'REQUEST_URI' ];
	}

	function _setupUser()
	{
		$this->mSiteLogin->call(new XCube_Ref($this->mXoopsUser));
		
		// Set instance to global variable for compatiblity with XOOPS 2.0.x
		$GLOBALS['xoopsUser'] =& $this->mXoopsUser;
		$GLOBALS['xoopsUserIsAdmin'] = is_object($this->mXoopsUser) ? $this->mXoopsUser->isAdmin(1) : false;	//@todo Remove '1'

		//
		// Set member handler to global variables for compatibility with XOOPS 2.0.x.
		//		
		$GLOBALS['xoopsMemberHandler'] =& xoops_gethandler('member');
		$GLOBALS['member_handler'] =& $GLOBALS['xoopsMemberHandler'];
	}
	
	function _setupErrorHandler()
	{
	}

	/**
	 * Create the instance of DataBase class, and set it to member property.
	 * @access protected
	 */
	function _setupDB()
	{
		if(!defined('XOOPS_XMLRPC'))
			define('XOOPS_DB_CHKREF', 1);
		else
			define('XOOPS_DB_CHKREF', 0);

		require_once XOOPS_ROOT_PATH.'/class/database/databasefactory.php';

		if ($_SERVER['REQUEST_METHOD'] != 'POST' || !xoops_refcheck(XOOPS_DB_CHKREF)) {
			define('XOOPS_DB_PROXY', 1);
		}

		$this->mDB =& XoopsDatabaseFactory::getDatabaseConnection();

		$GLOBALS['xoopsDB']=&$this->mDB;
	}
	
	/**
	 * Create a instance of Legacy_LanguageManager by the specified language,
	 * and set it to member properties.
	 * 
	 * [Notice]
	 * Now, this member function sets a string to the member property without
	 * language manager.
	 */
	function _setupLanguage()
	{
		require_once XOOPS_BASE_PATH."/kernel/Legacy_LanguageManager.class.php";
		
		$language = "english";
		
		$handler =& xoops_gethandler('config');
		$criteria =& new CriteriaCompo(new Criteria('conf_modid', 0));
		$criteria->add(new Criteria('conf_catid', XOOPS_CONF));
		$criteria->add(new Criteria('conf_name', 'language'));
		$configs =& $handler->getConfigs($criteria);
		
		if (count($configs) > 0) {
			$language = $configs[0]->get('conf_value', 'none');
        }
		
		$this->mRoot->mLanguageManager =& $this->_createLanguageManager($language);
		$this->mRoot->mLanguageManager->setLanguage($language);
		$this->mRoot->mLanguageManager->prepare();

		$this->mRoot->mLanguageManager->loadGlobalMessageCatalog();
		
		// If you use special page, load message catalog for it.
		if (isset($xoopsOption['pagetype'])) {
			$this->mRoot->mLanguageManager->loadPageTypeMessageCatalog($xoopsOption['pagetype']);
		}
    }

	/**
	 * Factory for the language manager. At first, this member function
	 * delegates to get a instance of LanguageManager. If it can't get it, do
	 * the following process: 
	 * 
	 * 1) Try creating a instance of 'Legacy_LanguageManager_' . ucfirst($language)
	 * 2) If the class doesn't exist, try loading  'LanguageManager.class.php' 
	 *    in the specified language.
	 * 3) Re-try creating the instance.
	 * 
	 * If it can't create any instances, create a instance of
	 * Legacy_LanguageManager as default.
	 * 
	 * @access protected
	 * @param string $language 
	 * @return Legacy_LanguageManager
	 */	
	function &_createLanguageManager($language)
	{
		require_once XOOPS_BASE_PATH . "/kernel/Legacy_LanguageManager.class.php";

		$languageManager = null;
		
		$this->mCreateLanguageManager->call(new XCube_Ref($languageManager), $language);
		
		if (!is_object($languageManager)) {
			$className = "Legacy_LanguageManager_" . ucfirst(strtolower($language));
			
			//
			// If the class exists, create a instance. Else, load the file, and
			// try creating a instance again.
			//
			if (class_exists($className)) {
				$languageManager =& new $className();
			}
			else {
				$filePath = XOOPS_ROOT_PATH . "/language/" . $language . "/LanguageManager.class.php";
				if (file_exists($filePath)) {
					require_once $filePath;
				}
				
				if (class_exists($className)) {
					$languageManager =& new $className();
				}
				else {
					//
					// Default
					//
					$languageManager =& new Legacy_LanguageManager();
				}
			}
		}
		
		return $languageManager;
	}

	function _setupConfig()
	{
		$configHandler=&xoops_gethandler('config');
		$this->mConfig=&$configHandler->getConfigsByCat(XOOPS_CONF);

		$this->setMainTheme($this->mConfig['theme_set']);
		if ($this->mLanguage) {
		    $this->mConfig['language'] = $this->mLanguage;
        }
		$GLOBALS['xoopsConfig']=&$this->mConfig;
	}

	/**
	 * Set debbuger object to member property.
	 * @return void
	 */
	function _setupDebugger()
	{
		error_reporting(0);

		require_once XOOPS_BASE_PATH . "/class/DebuggerManager.class.php";
		
		$debug_mode = $this->mConfig['debug_mode'];
		if (defined("OH_MY_GOD_HELP_ME")) {
			$debug_mode = XOOPS_DEBUG_PHP;
		}

		$this->mDebugger =& Legacy_DebuggerManager::getInstance($debug_mode);
		$this->mDebugger->prepare();

		$GLOBALS['xoopsDebugger']=&$this->mDebugger;
	}

	function _processPreBlockFilter()
    {
		//
		// Auto pre-loading for Module.
		//
		if ($this->mRoot->getSiteConfig('Legacy', 'AutoPreload') == 1) {
            $moduleHandler =& xoops_gethandler('module');
            $moduleObjects =& $moduleHandler->getObjects();
            foreach ($moduleObjects as $moduleObject) {
                $mod_dir = $moduleObject->getVar('dirname');
                $dir = XOOPS_ROOT_PATH . '/modules/' . $mod_dir . '/preload/';
    			if(is_dir($dir)) {
    			    $files = glob($dir.'*.class.php');
    			    if (is_array($files)) {
						foreach($files as $file) {
							require_once $file;
							if (preg_match("/(\w+)\.class\.php/", $file, $matches)) {
								$className = ucfirst($mod_dir) . "_" . $matches[1];
						
								if (class_exists($className)) {
									$instance =& new $className($this);
									$this->addActionFilter($instance);
								}
							}
						}
    			    }
    			}
            }
        }
        parent::_processPreBlockFilter();
    }

	function _setupSession()
	{
		global $xoopsDB;

		$sessionHandler=&xoops_gethandler('session');
		
		session_set_save_handler( 
			array(&$sessionHandler,"open"),
			array(&$sessionHandler,"close"),
			array(&$sessionHandler, 'read'),
			array(&$sessionHandler, 'write'),
			array(&$sessionHandler, 'destroy'),
			array(&$sessionHandler, 'gc'));
		
		session_start();
	}

	
	function executeHeader()
	{
		//
		// TODO Now, I done for working admin panel.
		//
		parent::executeHeader();

		//
		//  We changed a render-system class in a pure drawing system. Therefore
		// a controller should not ask him for careful work for compatibility.
		//

		//
		// The following comment-outed line is old version process.
		//
		// $this->mRenderSystem->_processStartPage();

		require_once XOOPS_ROOT_PATH.'/include/old_theme_functions.php';
		$GLOBALS['xoopsTheme']['thename'] = $GLOBALS['xoopsConfig']['theme_set'];

		//
		// cache check
		//
		$cacheSystem =& $this->mRoot->getCacheSystem();
		$xoopsModule =& $this->mModuleController->getXoopsModule();
		
		if ($this->_isModuleCache($xoopsModule)) {
			$url = xoops_getenv('REQUEST_URI');
			$cacheSystem->setResourceName($url);
			
			if ($cacheSystem->isCache($this->_getModuleCacheTime($xoopsModule))) {
				$renderSystem =& $this->mRoot->getRenderSystem($this->mModuleController->getDependRenderSystem());
				$renderTarget =& $renderSystem->createRenderTarget(XCUBE_RENDER_TARGET_TYPE_MAIN);
				$renderTarget->setResult($cacheSystem->load());

				$this->_executeViewTheme($renderTarget);

				exit(0);
			}
		}

		ob_start();
	}
	
	/**
	 * @return bool
	 */
	function _isModuleCache($xoopsModule)
	{
		return (xoops_getenv('REQUEST_METHOD') != 'POST' && is_object($xoopsModule) && !empty($this->mConfig['module_cache'][$xoopsModule->getVar('mid')]));
	}
	
	/**
	 * @return int
	 */
	function _getModuleCacheTime($xoopsModule)
	{
		return $this->mConfig['module_cache'][$xoopsModule->getVar('mid')];
	}

	/**
	 * @var string $theme
	 */	
	function setMainTheme($theme)
	{
		$this->mMainTheme = $theme;
		$this->mConfig['theme_set'] = $theme;
	}
	
	function executeView()
	{
		$renderSystem =& $this->mRoot->getRenderSystem($this->mModuleController->getDependRenderSystem());
		$renderTarget =& $this->mModuleController->getRenderTarget();
		
		//
		//  Buffering handling of standard output for main render target is responsibility
		// of a controller. Of course all controllers do not have to implement this.
		// The following lines are movement for compatibility and the feature of
		// this controller.
		//
		

		// require_once XOOPS_ROOT_PATH . '/include/notification_select.php';

		// Wmm...
		if (is_object($renderTarget)) {
			if ($renderTarget->getTemplateName() == null) {
				if (isset($GLOBALS['xoopsOption']['template_main'])) {
					$renderTarget->setTemplateName($GLOBALS['xoopsOption']['template_main']);
				}
			}
			
			$renderTarget->setAttribute("stdout_buffer", ob_get_contents());
		}

		ob_end_clean();
		
		if (is_object($renderTarget)) {
			$renderSystem->renderWithTarget($renderTarget);

			//
			// Cache Control
			//
			$xoopsModule =& $this->mModuleController->getXoopsModule();
			if ($this->_isModuleCache($xoopsModule)) {
				$url = xoops_getenv('REQUEST_URI');
				$cacheSystem =& $this->mRoot->getCacheSystem();
				$cacheSystem->setResourceName($url);
				$cacheSystem->save($renderTarget);
			}
		}

		
		$this->_executeViewTheme($renderTarget);
	}
	
	/**
	 * $resultRenderTarget object The render target of content's result.
	 */
	function _executeViewTheme(&$resultRenderTarget)
	{
		//
		// Theme Control
		//
		$screenTarget = $this->mDialogMode ? new Legacy_DialogRenderTarget() : new Legacy_ThemeRenderTarget();
		
		if (is_object($resultRenderTarget)) {
			$screenTarget->setAttribute('xoops_contents', $resultRenderTarget->getResult());
		}

		//
		// Get the render-system through theme object.
		//
		$theme =& $this->_mStrategy->getMainThemeObject();

		$renderSystem =& $this->mRoot->getRenderSystem($theme->get('render_system'));
		$screenTarget->setTemplateName($theme->get('dirname'));

		//
		// Rendering.
		//
		$renderSystem->renderWithTarget($screenTarget);

		//
		// Debug Process
		//
		$isAdmin=false;
		if(is_object($this->mXoopsUser)) {
			if($this->mModuleController->isModuleProcess() && $this->mModuleController->isActive()) {
				// @todo I depend on Legacy Module Controller.
				$mid=$this->mModuleController->mModuleObject->getVar('mid');
			}
			else {
				$mid=1;	///< @todo Do not use literal directly!
			}

			$isAdmin = $this->mXoopsUser->isAdmin($mid);
		}

		if ($isAdmin) {
			$this->mDebugger->displayLog();
		}
	}

	function &_createDelegateManager()
	{
		$delegateManager =& parent::_createDelegateManager();
		
		$file = XOOPS_ROOT_PATH . "/modules/base/kernel/Legacy_EventFunctions.class.php";
		
		$delegateManager->add('Legacypage.Notifications.Access', 'Legacy_EventFunction::notifications', $file);
		$delegateManager->add('Legacyfunction.Notificatins.Select', 'Legacy_EventFunction::notifications_select', $file);
		$delegateManager->add('Legacypage.Search.Access', 'Legacy_EventFunction::search', $file);
		$delegateManager->add('Legacypage.Imagemanager.Access', 'Legacy_EventFunction::imageManager', $file);
		$delegateManager->add('Legacypage.Backend.Access', 'Legacy_EventFunction::backend', $file);
		$delegateManager->add('Legacypage.Misc.Access', 'Legacy_EventFunction::misc', $file);
		$delegateManager->add('User_UserViewAction.GetUserPosts', 'Legacy_EventFunction::recountPost', $file);
		
		return $delegateManager;
	}
	
	function &_createServiceManager()
	{
		$serviceManager =& parent::_createServiceManager();
		
		require_once XOOPS_ROOT_PATH . "/modules/base/service/LegacySearchService.class.php";
		$searchService =& new Legacy_SearchService();
		$searchService->prepare();
		
		$serviceManager->addService('LegacySearch', $searchService);

		return $serviceManager;
	}
	
	/**
	 * Check the login request through delegates, and set XoopsObject to member
	 * property if the login is success.
	 * 
	 * @access public
	 */
	function checkLogin()
	{
		if (!is_object($this->mXoopsUser)) {
			$this->mCheckLogin->call(new XCube_Ref($this->mXoopsUser));

			if(is_object($this->mXoopsUser)) {
				// RMV-NOTIFY
				// Perform some maintenance of notification records
				$notification_handler =& xoops_gethandler('notification');
				$notification_handler->doLoginMaintenance($this->mXoopsUser->get('uid'));

				XCube_DelegateUtils::call("Site.CheckLogin.Success", new XCube_Ref($this->mXoopsUser));

				//
				// Fall back process for login success.
				//
				$url = XOOPS_URL;
				if (!empty($_POST['xoops_redirect']) && !strpos(xoops_getrequest('xoops_redirect'), 'register')) {
					$parsed = parse_url(XOOPS_URL);
					$url = isset($parsed['scheme']) ? $parsed['scheme'].'://' : 'http://';
					
					if (isset($parsed['host'])) {
						$url .= isset($parsed['port']) ? $parsed['host'] . ':' . $parsed['port'] . trim(xoops_getrequest('xoops_redirect')): $parsed['host'] . trim(xoops_getrequest('xoops_redirect'));
					} else {
						$url .= xoops_getenv('HTTP_HOST') . trim(xoops_getrequest('xoops_redirect'));
					}
				}
				
				$this->mRoot->mLanguageManager->loadModuleMessageCatalog('base');

				$this->executeRedirect($url, 1, XCube_Utils::formatMessage(_MD_BASE_MESSAGE_LOGIN_SUCCESS, $this->mXoopsUser->get('uname')));
			}
			else {
				XCube_DelegateUtils::call("Site.CheckLogin.Fail", new XCube_Ref($this->mXoopsUser));
				
				//
				// Fall back process for login fail.
				//
				$this->executeRedirect(XOOPS_URL . "/user.php", 1, _US_INCORRECTLOGIN);
			}
		}
		else {
			$this->executeForward(XOOPS_URL);
		}
	}
	
	/**
	 * The current user logout.
	 * 
	 * @access public
	 */
	function logout()
	{
		$successFlag = false;
		$xoopsUser =& $this->getXoopsUser();
		
		if (is_object($xoopsUser)) {
			$this->mLogout->call(new XCube_Ref($successFlag), $xoopsUser);
			if ($successFlag) {
				XCube_DelegateUtils::call("Site.Logout.Success", $xoopsUser);
				$this->executeRedirect(XOOPS_URL, 1, array(_US_LOGGEDOUT, _US_THANKYOUFORVISIT));
			}
			else {
				XCube_DelegateUtils::call("Site.Logout.Fail", $xoopsUser);
			}
		}
		else {
			$this->executeForward(XOOPS_URL);
		}
	}

	/**
	 * @deprecated
	 * @see setStrategy()
	 */
	function switchStateCompulsory(&$strategy)
	{
		$this->setStrategy($strategy);
	}
	
	/**
	 * CAUTION!!
	 * This method has a special mission.
	 * Because this method changes state after executeCommon, this resets now property.
	 * It depends on XCube_Controller steps.
	 *
	 * @param Legacy_AbstractControllerStrategy $strategy
	 */
	function setStrategy(&$strategy)
	{
		if($strategy->mStatusFlag != $this->_mStrategy->mStatusFlag) {
			$this->_mStrategy =& $strategy;
			
			//
			// The following line depends on XCube_Controller process of executeCommon.
			// But, There is no other method.
			//
			$this->_setupModuleController();
			$this->_processModuleController();
		}
	}

	function &getXoopsUser()
	{
		return $this->mXoopsUser;
	}

	/**
	 * Set bool flag to dialog mode flag.
	 * If you set true, executeView() will use Legacy_DialogRenderTarget class as
	 * render target.
	 * @param $flag bool
	 */
	function setDialogMode($flag)
	{
		$this->mDialogMode = $flag;
	}

	/**
	 * Return dialog mode flag.
	 * @return bool
	 */
	function getDialogMode()
	{
		return $this->mDialogMode;
	}
	
	/**
	 *  Return current module object. But, it's decided by the rules of the state.
	 *  Preferences page, Help page and some pages returns the specified module by
	 * dirname. It's useful for controlling a theme. 
	 * 
	 * @return XoopsModule
	 */
	function &getVirtualCurrentModule()
	{
		$ret =& $this->_mStrategy->getVirtualCurrentModule();
		return $ret;
	}
	
	/**
	 * Return URL of pm inbox. This is X2 fixed feature.
	 * 
	 * @param $uid int ID of the user
	 * @return string if any functions don't return value, return null.
	 */
	function getPMInboxUrl($uid)
	{
		$url = null;
		$this->mGetPMInboxUrl->call(new XCube_Ref($url), $uid);
		
		return $url;
	}

	/**
	 * Return counts of unread pm. This is X2 fixed feature.
	 * 
	 * @param $uid int ID of the user
	 * @return int
	 */
	function getCountUnreadPM($uid)
	{
		$count = 0;
		$this->mGetCountUnreadPM->call(new XCube_Ref($count), $uid);
		
		return $count;
	}

	/**
	 * This member function works to redirect as well as redirect_header().
	 * But, this member function handles raw values which hasn't been converted
	 * by htmlspecialchars(). Therefore, if user calls this function with the
	 * wrong value, some problems may be raised. If you can't understand the
	 * difference, use not this function but redirect_header().
	 * 
	 * @param string $url     redirect URL. Don't use user's variables or request.
	 * @param int    $time    waiting time (sec)
	 * @param string $message This string doesn't include tags.
	 * 
	 * @todo We'll change this function to delegate.
	 */
	function executeRedirect($url, $time = 1, $message = null)
	{
		global $xoopsConfig, $xoopsRequestUri;

		//
		// Check the following by way of caution.
		//
		if (preg_match("/(javascript|vbscript):/si", $url)) {
			$url = XOOPS_URL;
		}
		
		$displayMessage = "";
		if (is_array($message)) {
			foreach (array_keys($message) as $key) {
				$message[$key] = htmlspecialchars($message[$key], ENT_QUOTES);
			}
			$displayMessage = implode("<br/>", $message);
		}
		else {
			$displayMessage = $message;
		}
		
		$url = htmlspecialchars($url, ENT_QUOTES);
		if (defined('SID') && (! isset($_COOKIE[session_name()]) || ($xoopsConfig['use_mysession'] && $xoopsConfig['session_name'] != '' && !isset($_COOKIE[$xoopsConfig['session_name']])))) {
			if (!strstr($url, '?')) {
				$url .= '?' . SID;
			}
			else {
				$url .= '&amp;' . SID;
			}
		}

		if (!defined('XOOPS_CPFUNC_LOADED')) {
			require_once XOOPS_ROOT_PATH.'/class/template.php';
			$xoopsTpl = new XoopsTpl();
			$xoopsTpl->assign('sitename', htmlspecialchars($xoopsConfig['sitename'], ENT_QUOTES));
			$xoopsTpl->assign('langcode', _LANGCODE);
			$xoopsTpl->assign('charset', _CHARSET);
			$xoopsTpl->assign('time', $time);

			$xoopsTpl->assign('url', $url);
			$xoopsTpl->assign('message', $displayMessage);
			$xoopsTpl->assign('lang_ifnotreload', sprintf(_IFNOTRELOAD, $url));
			$GLOBALS['xoopsModuleUpdate'] = 1;
			$xoopsTpl->display('db:system_redirect.html');
		} else {
			$url = preg_replace("/&amp;/i", '&', htmlspecialchars($url, ENT_QUOTES));
			echo '
			<html>
			<head>
			<title>'.htmlspecialchars($xoopsConfig['sitename']).'</title>
			<meta http-equiv="Content-Type" content="text/html; charset='._CHARSET.'" />
			<meta http-equiv="Refresh" content="'.$time.'; url='.$url.'" />
			<style type="text/css">
					body {background-color : #fcfcfc; font-size: 12px; font-family: Trebuchet MS,Verdana, Arial, Helvetica, sans-serif; margin: 0px;}
					.redirect {width: 70%; margin: 110px; text-align: center; padding: 15px; border: #e0e0e0 1px solid; color: #666666; background-color: #f6f6f6;}
					.redirect a:link {color: #666666; text-decoration: none; font-weight: bold;}
					.redirect a:visited {color: #666666; text-decoration: none; font-weight: bold;}
					.redirect a:hover {color: #999999; text-decoration: underline; font-weight: bold;}
			</style>
			</head>
			<body>
			<div align="center">
			<div class="redirect">
			<span style="font-size: 16px; font-weight: bold;">'.$displayMessage.'</span>
			<hr style="height: 3px; border: 3px #E18A00 solid; width: 95%;" />
			<p>'.sprintf(_IFNOTRELOAD, $url).'</p>
			</div>
			</div>
			</body>
			</html>';
		}
		
		exit();
	}
}

/**
 * @abstract
 */
class Legacy_AbstractControllerStrategy
{
	/**
	 * @var Legacy_Controller
	 */
	var $mController = null;
	
	var $mStatusFlag;
	
	function Legacy_AbstractControllerStrategy(&$controller)
	{
		$this->mController =& $controller;
	}

	/**
	 * Create a instance of ModuleController, and set it to mModuleController
	 * property of $controller.
	 * 
	 * @param $controller Legacy_Controller
	 */
	function setupModuleController()
	{
	}

	function setupBlock()
	{
	}

	/**
	 * @return XoopsModule
	 * @see Legacy_Controller::getVirtualCurrentModule()
	 */	
	function &getVirtualCurrentModule()
	{
		$ret = null;
		return $ret;
	}
	
	function &getMainThemeObject()
	{
	}
}

class Legacy_PublicControllerStrategy extends Legacy_AbstractControllerStrategy
{
	var $mStatusFlag = LEGACY_CONTROLLER_STATE_PUBLIC;
	
	function Legacy_PublicControllerStrategy(&$controller)
	{
		parent::Legacy_AbstractControllerStrategy($controller);
		
		if (!defined("LEGACY_DEPENDENCE_RENDERER")) {
			define("LEGACY_DEPENDENCE_RENDERER", "Legacy_RenderSystem");
		}
	}

	function setupModuleController()
	{
		require_once XOOPS_BASE_PATH . "/kernel/Legacy_ModuleController.class.php";
		$this->mController->mModuleController =& new Legacy_ModuleController($this->mController);
	}

	function setupBlock()
	{
		$showFlag =0;
		$mid=0;

		if($this->mController->mModuleController->isModuleProcess()) {
			$showFlag = (preg_match("/index\.php$/i", xoops_getenv('PHP_SELF')) && $this->mController->mConfig['startpage'] == $this->mController->mModuleController->mModuleObject->getVar('dirname'));
			$mid = $this->mController->mModuleController->mModuleObject->getVar('mid');
		}
		else {
			//
			// If you does not have module_contoller, this request is to toppage or other pages of toppage.
			//
			$mid = preg_match("/index\.php$/i", xoops_getenv('PHP_SELF')) ? -1 : 0;
		}

        $blockHandler =& xoops_gethandler('block');
		$showCenterFlag = (SHOW_CENTERBLOCK_LEFT | SHOW_CENTERBLOCK_CENTER | SHOW_CENTERBLOCK_RIGHT);
		$showRightFlag = SHOW_SIDEBLOCK_RIGHT;
		$showFlag = SHOW_SIDEBLOCK_LEFT | $showRightFlag | $showCenterFlag;
		$groups = is_object($this->mController->mXoopsUser) ? $this->mController->mXoopsUser->getGroups() : XOOPS_GROUP_ANONYMOUS;

		$blockObjects=&$blockHandler->getBlocks($groups, $mid, $showFlag);
		foreach($blockObjects as $blockObject) {
			$this->mController->mBlockChain[] =& new Legacy_AdaptBlockProcedure($blockObject);
			unset($blockObject);
		}
	}

	function &getMainThemeObject()
	{
		// [TODO]
		// Because get() of the virtual handler is heavy, we have to consider
		// the new solution about this process.
		//
		$handler =& xoops_getmodulehandler('theme', 'base');
		$theme =& $handler->get($this->mController->getMainTheme());
		
		return $theme;
	}
}

class Legacy_AdminControllerStrategy extends Legacy_AbstractControllerStrategy
{
	var $mStatusFlag = LEGACY_CONTROLLER_STATE_ADMIN;
	
	/**
	 *  If this array includes current action, getVirtualCurrentModule() returns
	 * the module object that specified by dirname.
	 * 
	 * @access private
	 */
	var $_mSpecialActions = array("Help", "CommentList");

	function Legacy_AdminControllerStrategy(&$controller)
	{
		parent::Legacy_AbstractControllerStrategy($controller);
		
		//
		// TODO We have to develop complated-switching-controller-mechanizm.
		//
		if (!defined("LEGACY_DEPENDENCE_RENDERER")) {
			define("LEGACY_DEPENDENCE_RENDERER", "Legacy_AdminRenderSystem");
		}
	}

	function setupModuleController()
	{
		require_once XOOPS_BASE_PATH . "/kernel/Legacy_AdminModuleController.class.php";
		$this->mController->mModuleController =& new Legacy_AdminModuleController($this->mController);
	}

	function setupBlock()
	{
		require_once XOOPS_BASE_PATH . "/admin/blocks/AdminActionSearch.class.php";
		require_once XOOPS_BASE_PATH . "/admin/blocks/AdminSideMenu.class.php";
		$this->mController->mBlockChain[] =& new Legacy_AdminActionSearch();
		$this->mController->mBlockChain[] =& new Legacy_AdminSideMenu();
	}

	function &getVirtualCurrentModule()
	{
		$module = null;
		
		if ($this->mController->mModuleController->isModuleProcess()) {
			$module =& $this->mController->mModuleController->getXoopsModule();
			
			if ($module->get('dirname') == "base" && isset($_REQUEST['dirname'])) {
				if (in_array(xoops_getrequest('action'), $this->_mSpecialActions)) {
					$handler =& xoops_gethandler('module');
					$module =& $handler->getByDirname(xoops_getrequest('dirname'));
				}
			}
			elseif ($module->get('dirname') == "base" && xoops_getrequest('action') == 'PreferenceEdit' && isset($_REQUEST['confmod_id'])) {
				$handler =& xoops_gethandler('module');
				$module =& $handler->get(intval(xoops_getrequest('confmod_id')));
			}
		}

		return $module;
	}

	function &getMainThemeObject()
	{
		$handler =& xoops_getmodulehandler('theme', 'base');
		$theme =& $handler->create();
		
		//
		// TODO Load manifesto here.
		//
		$theme->set('dirname', $this->mController->mRoot->mSiteConfig['Legacy']['Theme']);
		$theme->set('render_system', 'Legacy_AdminRenderSystem');
		
		return $theme;
	}
}

?>