/**
  * Return a users permission for a realm
  * 
  * This method will return the permissions a user has to a specified realm 
  * path. This method considers permissions of parent realms, and the 
  * permissions specifed for the groups to which the user belongs.
  * 
  * @param array $realmPath A realm path (either array of realm IDs or of realm names)
  * @param mixed $user Either a user name or a user id
  * @return boolean True/false if access is allowed/denied respectively
  * @todo Consider adding some caching to this method
  */
 public static function getDetailedUserrealmAccess($realmPath, $user)
 {
     global $cfg;
     //echo "Starting Detailed user realm access<br><br>";
     //debug_print_backtrace();
     //echo "<br><br>";
     $q = Database::getTotalQueries();
     $parentrealmID = 0;
     $allow = null;
     $isIDrealmPath = true;
     foreach ($realmPath as $rp) {
         if (!is_numeric($rp)) {
             $isIDrealmPath = false;
         }
     }
     $db = Database::getInstance();
     //echo "Executing: " . "return " . $cfg['Auth']['authUtilClassModule'] . "::getUserID($user);<br>";
     $userID = eval("return " . $cfg['Auth']['authUtilClassModule'] . "::getUserID({$user});");
     //echo "Getting detailed realm access for: " . $user . " ID as " . $userID . "<br>";
     for ($i = 0; $i < count($realmPath) && $allow !== false; $i++) {
         if ($isIDrealmPath) {
             $realmID = $realmPath[$i];
         } else {
             $sql = "SELECT realmid FROM realms WHERE name = '{$realmPath[$i]}' AND parentid = '{$parentrealmID}'";
             $realmID = $db->getOne($sql);
         }
         $groups = eval("return " . $cfg['Auth']['authUtilClassModule'] . "::getGroupsListForUser({$user});");
         if (count($groups) > 0) {
             $groupList = join(',', $groups);
             $sql = "SELECT allow FROM realmgrouplink WHERE realmid = '{$realmID}' AND groupid IN ({$groupList})";
             $groupperms = $db->getColumn($sql);
             foreach ($groupperms as $gp) {
                 if ($gp == 'y' && $allow !== false) {
                     $allow = true;
                 } elseif ($gp == 'n') {
                     $allow = false;
                 }
             }
         }
         $sql = "SELECT allow FROM realmuserlink WHERE realmid = '{$realmID}' AND userid = '{$userID}'";
         $userperms = $db->getColumn($sql);
         foreach ($userperms as $up) {
             //Deny takes precidence over allow
             if ($up == 'y' && $allow !== false) {
                 $allow = true;
             } elseif ($up == 'n') {
                 $allow = false;
             }
         }
         $parentrealmID = $realmID;
     }
     //echo "Finished getting Detailted user realm access<br>";
     return $allow;
 }
 /**
  * Initialise the Page object
  * 
  * Will determine if the required request variables are present.
  * If not present an exception will be thrown and caught 
  * 
  * @var string
  */
 public function __construct()
 {
     list($usec, $sec) = explode(" ", microtime());
     $startTime = (double) $usec + (double) $sec;
     global $cfg;
     try {
         ##############
         ## Include the Auth and AuthUtil classes
         #			$modulePath  = $cfg['general']['toolkitRoot'] . '/' . $cfg['Auth']['authClassModule'];
         $modulePath = $cfg['Auth']['dir']['root'];
         $moduleName = $cfg['Auth']['authClassModule'];
         // try to include Auth
         if (!(include_once "{$modulePath}/{$moduleName}.class.php")) {
             throw new Exception("It was not possible to include Auth.class.php. I tried to find it here: {$modulePath}/{$moduleName}.class.php");
         }
         if (!class_exists("Auth")) {
             throw new Exception("The {$moduleName}.class.php ({$modulePath}/{$moduleName}.class.php) file was included but the Auth class could not be found");
         }
         // try to include AuthUtil
         if (!(include_once "{$modulePath}/AuthUtil.class.php")) {
             throw new Exception("It was not possible to include AuthUtil.class.php. I tried to find it here: {$modulePath}/AuthUtil.class.php");
         }
         if (!class_exists("AuthUtil")) {
             throw new Exception("The AuthUtil.class.php ({$modulePath}/AuthUtil.class.php) file was included but the AuthUtil class could not be found");
         }
         $db = Database::getInstance($cfg['MVC']['dsn']);
         $errors = array();
         //Load data from superglobals
         $this->loadFieldData();
         //Redirect the user to the actual site (disabled when proxypassed)
         if ($cfg['general']['proxypass'] == 'f' && $_SERVER['HTTP_HOST'] != $cfg['general']['domain']) {
             $url = $cfg['general']['protocol'] . $cfg['general']['domain'] . $cfg['general']['siteRoot'];
             header("Location: {$url}");
             exit;
         }
         //Load template ID
         if (isset($this->fieldData['templateID']) && $this->fieldData['templateID'] != '') {
             $this->templateID = $this->fieldData['templateID'];
         } elseif (isset($cfg['smarty']['defaultTemplate'])) {
             $this->templateID = MVCUtils::getTemplateID($cfg['smarty']['defaultTemplate']);
         } else {
             //Template ID is required. Therefore throw an exception
             throw new LoggedException('No template ID or default template specified', 0, self::module);
         }
         //Load form name
         if (isset($this->fieldData['formName'])) {
             $this->formName = $this->fieldData['formName'];
         } else {
             //formName is not required, so set to empty string
             //note that forms will be ignored if this is not passed
             $this->fieldData['formName'] = null;
         }
         //Load the module names
         $this->viewerModuleName = $db->getOne("SELECT modulename FROM templates WHERE templateid = ?", array($this->templateID));
         if (isset($this->fieldData['moduleName']) && $this->fieldData['moduleName'] != '') {
             $this->modelModuleName = $this->fieldData['moduleName'];
         } else {
             $this->modelModuleName = 'MVC';
         }
         ### Check that the user has permission to use the submitted form
         // get the realmid of the submitted form
         $sql = 'SELECT realmid FROM forms WHERE formname = ? AND modulename = ?';
         $realmid = $db->getOne($sql, array($this->formName, $this->modelModuleName));
         $auth = Auth::getInstance();
         // If the realm id could not found then allow access
         // (this will cause 'Model' to be used - so no processing occurs)
         if (!$realmid) {
             //Access is allowed
             $modelAccess = true;
         } else {
             //Check if the user has access to the realm associated with the form
             if (!$auth->isLoggedIn()) {
                 $auth->attemptLogin($cfg['Auth']['anonuser']);
             } else {
                 $auth->attemptLogin();
             }
             $path = AuthUtil::getRealmPath($realmid);
             if (!AuthUtil::getDetailedUserrealmAccess($path, $auth->getUserID())) {
                 //If the user does not have permission, show an error
                 $modelAccess = false;
                 $errors = array('permission' => 'You do not have permission to use the submited form');
             } else {
                 //Set access flag to false
                 $modelAccess = true;
             }
         }
         //If access to the requested form is allowed
         if ($modelAccess) {
             //If a form was submitted
             if (isset($this->formName) && !is_null($this->formName)) {
                 //Then validate the form data
                 //Store any errors in $errors
                 $errors = $this->validate();
             }
         }
         //If the user has access to the requested template
         if ($this->checkAuth()) {
             if ($modelAccess) {
                 $newModel = MVCUtils::initializeModel(array($this->templateID), $this->formName, $this->modelModuleName, $this->viewerModuleName, $this->fieldData, $errors);
             } else {
                 $this->templateID = MVCUtils::getPermErrorTemplateID();
                 $newModel = MVCUtils::initializeModel(array($this->templateID), null, 'MVC', 'Auth', $this->fieldData, $errors);
             }
             //If there are errors then these will be passed in the $errors array,
             //if there are no errors then $errors will simple be an empty array
             //If no form name was passed, $this->formName will be null
         } else {
             //The user is not authorised to access this area
             $auth = Auth::getInstance();
             //Set the template ID to that of the permission error template
             $this->templateID = MVCUtils::getPermErrorTemplateID();
             //Get the reason for failure and specify an error message
             $reason = $auth->getFailureReason();
             if (count($errors) == 0) {
                 if ($reason == 2) {
                     $errors = array('permission' => 'Your session has been inactive for too long');
                 } elseif ($reason != 0) {
                     $errors = array('permission' => 'Unfortunately, an error has occurred. Please attempt logging in again.');
                 } else {
                     $errors = array('permission' => 'You do not have permission to view this page');
                 }
             }
             //Initialise the viewer for the permission error template
             if ($auth->getUserID() == $cfg['Auth']['anonuserID'] && $cfg['Auth']['anonuserredirect'] == 'y') {
                 $permErrorTID = $cfg['Auth']['anonuserRedirectTemplateID'];
                 $newModel = MVCUtils::initializeViewer(array($permErrorTID), null, 'tkfecommon', null, $errors);
             } else {
                 $permErrorTID = MVCUtils::getTemplateID($cfg['Auth']['permissionErrorTemplate']);
                 $newModel = MVCUtils::initializeViewer(array($permErrorTID), null, 'tkfecommon', null, $errors);
             }
         }
         //Print out the page
         echo $newModel->getCode();
     } catch (Exception $e) {
         //If a problem occured then create an error page
         $ev = new ExceptionViewer($e);
         $ev->printTemplate();
         exit;
     }
     //Show the execution time if set in config file
     if ($cfg['smarty']['showExecTime']) {
         list($usec, $sec) = explode(" ", microtime());
         $endTime = (double) $usec + (double) $sec;
         $totalTime = round($endTime - $startTime, 3);
         $log = Database::getQueryLog();
         echo "Total time to parse page: {$totalTime} seconds<br />\n";
         echo "Total number of queries: " . Database::getTotalQueries();
         echo "<br />Log: ";
         print_r($log);
     }
 }