Location: PHPKode > projects > Sierra-php PHP Application Framework > sierra/lib/auth/SRA_Authenticator.php
<?php
// {{{ Header
/*
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 | SIERRA : PHP Application Framework  http://code.google.com/p/sierra-php |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 | Copyright 2005 Jason Read                                               |
 |                                                                         |
 | Licensed under the Apache License, Version 2.0 (the "License");         |
 | you may not use this file except in compliance with the License.        |
 | You may obtain a copy of the License at                                 |
 |                                                                         |
 |     http://www.apache.org/licenses/LICENSE-2.0                          |
 |                                                                         |
 | Unless required by applicable law or agreed to in writing, software     |
 | distributed under the License is distributed on an "AS IS" BASIS,       |
 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.|
 | See the License for the specific language governing permissions and     |
 | limitations under the License.                                          |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 */
// }}}

// {{{ Imports
require_once('util/SRA_Params.php');
// }}}

// {{{ Constants

/**
 * the attribute key under which the username will be stored in the 'attrs' attribute
 * @type string
 */
define('SRA_AUTHENTICATOR_ATTR_USER', 'user');

/**
 * status code signifying that the user was authenticated successfully
 * @type int
 */
define('SRA_AUTHENTICATOR_STATUS_SUCCESS', 1);

/**
 * status code signifying that the user authentication failed (but a more 
 * specific reason is not known). this is the default status code.
 * @type int
 */
define('SRA_AUTHENTICATOR_STATUS_FAILED', 2);

/**
 * status code signifying that the user authentication failed because the password 
 * specified is not valid (the user is valid)
 * @type int
 */
define('SRA_AUTHENTICATOR_STATUS_INVALID_PSWD', 4);

/**
 * status code signifying that the user authentication failed because the username 
 * specified is not valid
 * @type int
 */
define('SRA_AUTHENTICATOR_STATUS_INVALID_USER', 8);

/**
 * status code signifying that the user authentication was successful, but the 
 * user attribute validation failed
 * @type int
 */
define('SRA_AUTHENTICATOR_STATUS_INVALID_ATTRS', 16);

/**
 * status code signifying that the user authentication failed due to a system error
 * @type int
 */
define('SRA_AUTHENTICATOR_STATUS_ERROR', 32);

/**
 * the default timeout value where access tracking is performed based on IP
 * @type int
 */
define('SRA_AUTHENTICATOR_DEFAULT_TIMEOUT', 15);

/**
 * file prefix for storing authenticator cache files and login counts in a file
 * @type string
 */
define('SRA_AUTHENTICATOR_FILE_PREFIX', '.sierra_auth_');

/**
 * the name of a cookie to set when a user logs out
 * @type string
 */
define('SRA_AUTHENTICATOR_LOGOUT_COOKIE', 'sraLogout');

/**
 * file prefix for storing logout records
 * @type string
 */
define('SRA_AUTHENTICATOR_LOGOUT_FILE_PREFIX', '.sierra_auth_logout_');

/**
 * the attribute key under which the username will be stored in the 'attrs' attribute
 * @type string
 */
define('SRA_AUTHENTICATOR_LOGOUT_FWD_VAR', 'sraLogoutFwd');

/**
 * SRA_Authenticator debug flag
 * @type  boolean
 */
define('SRA_AUTHENTICATOR_DEBUG', FALSE);

/**
 * SRA_Authenticator debug file
 * @type  string
 */
define('SRA_AUTHENTICATOR_DEBUG_FILE', SRA_DIR . '/tmp/.sierra_auth_debug');

// }}}

// {{{ SRA_Authenticator
/**
 * Abstract class defining the API that should be adhered to by any SIERRA 
 * SRA_Authenticator.
 * 
 * @author  Jason Read <hide@address.com>
 * @package sierra.auth
 */
class SRA_Authenticator {
  // {{{ Attributes
  // public attributes
	/**
   * associative array of user attributes. will always contain 
	 * the 'SRA_AUTHENTICATOR_ATTR_USER' hash key and may additionally specify 
   * other attributes extracted by the SRA_Authenticator
	 * @type array
	 */
	var $attrs = array();
	
	/**
   * if the status is SRA_AUTHENTICATOR_STATUS_INVALID_ATTRS, this will be the 
	 * name of the attribute that was not matched
	 * @type string
	 */
	var $unmatchedAttr;
	
	/**
   * an optional container for SRA_Authenticator specific error codes/messages
	 * @type string
	 */
	var $errMsg;

	/**
   * the authentication status. will correspond with one of the SRA_AUTHENTICATOR_STATUS_* 
	 * constants
	 * @type int
	 */
	var $status = SRA_AUTHENTICATOR_STATUS_FAILED;
	
  
  // private attributes
	/**
   * unique identifier for this authenticator instance
	 * @type string
	 */
	var $_id;
	
	/**
   * the log file where successful login records should be recorded. 
	 * if not specified, they will not be recorded. the path should be 
	 * relative to {sierra-dir}/log
	 * @type string
	 */
	var $_accessLog;
	
	/**
   * keeps track of the # of times the user has attempted to login with this 
	 * authenticator
	 * @type string
	 */
	var $_attemptCount = 0;
	
	/**
   * the template that should be displayed if the user clicks cancel when the 
	 * login box is displayed. if not specified, a blank screen will be displayed
	 * @type string
	 */
	var $_cancelTpl;
  
  /**
   * whether or not the user has already been prompted for their username and 
   * password from the console
   * @type boolean
   */
  var $_consolePrompted = FALSE;
  
	/**
   * allows the SRA_Authenticator instance to be morphed to a specific entity
	 * @type string
	 */
  var $_entityType;
	
	/**
   * whether or not the user exceeded the max allowed login attempts
	 * @type boolean
	 */
	var $_exceededMaxLoginAttemptCount = FALSE;
	
	/**
   * the log file where failed login attempts should be recorded. if 
	 * not specified, they will be recorded in the default app log 
	 * file
	 * @type string
	 */
	var $_failureLog;
	
	/**
   * a global PHP variable under which this SRA_Authenticator instance 
	 * should be stored when invoked. If an SRA_Authenticator already 
	 * exists in this variable, then it will be replaced with this
	 * instance.
	 * @type string
	 */
	var $_globalVar;
  
	/**
   * template containing an html login form which should be displayed instead of 
   * the default http authentication prompt (the login dialog displayed by your 
   * browser). when used, this form should post back to itself (action="") 
   * utilizing method="post" and contain form fields for both user (name="user") 
   * and password (name="password"). if a login is unsuccessful, this template 
   * will be re-dispalyed with the template variable "authStatus" set to one of 
   * the SRA_AUTHENTICATOR_STATUS_* constant values. 
   *
   *   Note: if multiple authenticators have been used, the template variable 
   *         "authStatus" will contain the status code from the last attempted 
   *         authenticator and "authStatus_[authenticator id]", template 
   *         variables will also be used in order to distinguish between the 
   *         different statuses. 
   *
   *   Note: if this template is being re-displayed due to a login error, the 
   *         previous post fields will be accessible using the template variable 
   *         'form' which will be a reference to $_POST
   *
   *   Note: if multiple authenticators are specified for a given resource, 
   *         'login-tpl' will be displayed from the last authenticator only
   *
   *   Note: standard http authentication will still be used for web services
   *
   *   Note: when login-tpl is used, the user and password will be stored in a 
   *         PHP session variable and thereby subject to session expiration and 
   *         repeat logins based on your PHP session ttl. when this occurs, the 
   *         template variable 'timeout' will be set to true
   * 
   *   Note: when this option is used, the $_SERVER['PHP_AUTH_USER'] and 
   *         $_SERVER['PHP_AUTH_PW'] super global values will automatically be 
   *         set
   *
   *   Note: if a session timeout occurs during a POST, you can support that 
   *         without losing data by adding something like the following to your 
   *         login-tpl:
   *          {foreach from=$form key=name item=val}
   *          {if $name neq 'user' && $name neq 'password'}
   *          <textarea name="{$name}" style="display:none">{$val}</textarea>
   *          {/if}
   *          {/foreach}
   *
	 * @type string
	 */
	var $_loginTpl;
	
	/**
   * the uri that the user should be forwarded to when a logout occurs
	 * @type string
	 */
	var $_logoutFwdUri;
	
	/**
   * $_GET variable that will result in the user being logged out of this 
	 * authenticator. a manual logout can also be performed via the 
	 * SRA_Authenticator.logout instance method. the value of this parameter should 
	 * be something besides empty string or 0 in order for a logout to be 
	 * triggered automatically
	 * @type string
	 */
	var $_logoutGetVar;
	
	/**
   * $_POST variable that will result in the user being logged out of this 
	 * authenticator. a manual logout can also be performed via the 
	 * SRA_Authenticator.logout instance method. the value of this parameter should 
	 * be something besides empty string or 0 in order for a logout to be 
	 * triggered automatically
	 * @type string
	 */
	var $_logoutPostVar;
	
	/**
   * the template that should be displayed if a logout has been performed. if 
	 * both logout-fwd-uri and logout-tpl are specified, the template will take 
	 * priority. if neither are specified, the user will be forwarded to the same 
	 * page they are on, resulting in an authentication dialog being displayed
	 * @type string
	 */
	var $_logoutTpl;
	
	/**
   * key/value pairs that must also be matched for a successful user 
	 * authentication to take place where the "key" is the identifier or the 
	 * attribute (as specified in the authenticator params of type "attrs") and 
	 * the value is a regular expression to match against that value.
	 * @type array
	 */
	var $_matchAllAttrs;
	
	/**
   * same as _matchAllAttrs, but only 1 needs to match
	 * @type array
	 */
	var $_matchOneAttrs;
	
	/**
   * template to display if an attribute match fails. attribute matches are 
	 * defined in the "restrict-access" elements. if not specified, the login 
	 * prompt wil be re-displayed until the user enters credentials with proper 
	 * access or the max-attempts is exceeded
	 * @type string
	 */
	var $_matchFailTpl;
	
	/**
   * the maximum # of failed attempts before the max-attempt-tpl 
	 * template is displayed. login attempts are tracked using sessions
	 * or IP address (based on the max-attempt-track attribute). if this
	 * attribute is 0 (default) then unlimited attempts are allowed
	 * @type int
	 */
	var $_maxAttempts;
	
	/**
   * the template to display if the user exceeds the "max-attempts" value. 
	 * REQUIRED if max-attempts is specified and > 0
	 * @type String
	 */
	var $_maxAttemptTpl;
	
	/**
   * whether or not to track login attempts based on IP. the default behavior is 
	 * to track based on a session cookie
	 * @type boolean
	 */
	var $_maxAttemptIp;
	
	/**
   * # of minutes to wait before allowing a user to re-attempt to login after 
	 * they have exceeded "max-attempts". Only applies to IP based login attempt 
	 * tracking "max-attempt-ip"
	 * @type int
	 */
	var $_maxAttemptTimeout;
	
	/**
   * the password to authenticate
	 * @type string
	 */
	var $_pswd;
	
	/**
   * the template to display if a system error occurs when this authenticator 
	 * is invoked
	 * @type String
	 */
	var $_sysErrTpl;
	
	/**
   * the template variable under which this SRA_Authenticator instance should be 
	 * stored when invoked. If an SRA_Authenticator already exists under this 
	 * variable, then it will be replaced with this instance. 
	 * @type String
	 */
	var $_tplVar;
	
	/**
   * the username to authenticate
	 * @type string
	 */
	var $_user;
	
	/**
   * whether or not sessions should be used to store valid logins. if sessions 
	 * are not used, then the user will be re-authenticated with each http request 
	 * (they will not be required to re-submit login information, but the 
	 * authenticator will be hit each time that they make a request) based on the 
	 * PHP_AUTH_USER and PHP_AUTH_PW global variables. the default value for this 
	 * attribute is TRUE
	 * @type boolean
	 */
	var $_useSessions;
	
	/**
   * the params specified for this authenticator
	 * @type SRA_Params
	 */
	var $_params = FALSE;
	
	/**
   * authentication resource string
	 * @type string
	 */
	var $_resource;
  
  /**
   * if an $entityType has been specified and successfully instantiated, this 
   * instance variable will be a reference to that entity for the user
   * @type object
   */
  var $_userEntity;
	
	/**
   * whether or not this SRA_Authenticator has already been written to cache
	 * @type boolean
	 */
	var $_written = FALSE;
	
  // }}}
  
  // {{{ Operations
  // constructor(s)
	// {{{ SRA_Authenticator
	/**
	 * Constructor API. Should be invoked by all sub-classes on first line via 
	 * parent::SRA_Authenticator($user, $pass, $params). There should be no other 
	 * logic with sub-class constructors as this constructor will also invoke the 
	 * _authenticate method which is the location where all validation and attr 
	 * extraction logic should be placed. For an example of how to properly create 
	 * a new SRA_Authenticator, review the code for one of the standard SRA_Authenticator 
	 * implementations including SRA_DbAuthenticator and SRA_LdapAuthenticator
   * @access public
	 */
	function SRA_Authenticator($id, $accessLog, $cancelTpl, $entityType, $entityUserCol, $failureLog, $globalVar, $loginTpl, 
                         $logoutFwdUri, $logoutGetVar, $logoutPostVar, $logoutTpl, $matchAllAttrs, $matchOneAttrs, 
												 $matchFailTpl, $maxAttempts, $maxAttemptTpl, $maxAttemptIp, 
												 $maxAttemptTimeout, & $params, $resource, $sysErrTpl, 
												 $tplVar, $useSessions) {
		if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("SRA_Authenticator::SRA_Authenticator: Instantiate authenticator - id: $id, " . 
										 "accessLog: $accessLog, cancelTpl: $cancelTpl, entityType: $entityType, $entityUserCol: $entityUserCol, failureLog: $failureLog, " . 
										 "globalVar: $globalVar, loginTpl: $loginTpl, logoutFwdUri: $logoutFwdUri, logoutGetVar: $logoutGetVar, " . 
										 "logoutPostVar: $logoutPostVar, logoutTpl: $logoutTpl, maxAttempts: $maxAttempts, " . 
										 "maxAttemptTpl: $maxAttemptTpl, maxAttemptTimeout=$maxAttemptTimeout, " . 
										 "resource: $resource, sysErrTpl: $sysErrTpl, tplVar: $tplVar, useSessions: $useSessions, PHP_AUTH_USER: " . 
                     $_SERVER['PHP_AUTH_USER'] . ' PHP_AUTH_PW: ' . $_SERVER['PHP_AUTH_PW'], 
										 SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
		if (!$id) {
			$msg = "SRA_Authenticator::SRA_Authenticator: Failed - id not specified";
			$this->err = SRA_Error::logError($msg, __FILE__, __LINE__);
			return;
		}
		$this->_id = $id;
		
		if ($accessLog) {
			$this->_accessLog = SRA_Controller::getAppLogDir() . '/' . $accessLog;
		}
		
		$this->_cancelTpl = $cancelTpl;
    $this->_entityType = $entityType;
    $this->_entityUserCol = $entityUserCol;
		if ($failureLog && $failureLog != '0') {
			$this->_failureLog = SRA_Controller::getAppLogDir() . '/' . $failureLog;
		}
		else if ($failureLog != '0') {
			$this->_failureLog = SRA_Controller::getAppErrorLogFile();
		}
		$this->_globalVar = $globalVar;
		$this->_matchAllAttrs = $matchAllAttrs;
		$this->_matchOneAttrs = $matchOneAttrs;
		$this->_matchFailTpl = $matchFailTpl;
    $this->_loginTpl = $loginTpl;
		$this->_logoutFwdUri = $logoutFwdUri;
		$this->_logoutGetVar = $logoutGetVar;
		$this->_logoutPostVar = $logoutPostVar;
		$this->_logoutTpl = $logoutTpl;
		$this->_maxAttempts = $maxAttempts;
		if ($maxAttempts > 0 && !$maxAttemptTpl) {
			$msg = "SRA_Authenticator::SRA_Authenticator: Failed - maxAttempts ${maxAttempts} specified, but no maxAttemptTpl";
			$this->err = SRA_Error::logError($msg, __FILE__, __LINE__);
			return;
		}
		$this->_maxAttemptTpl = $maxAttemptTpl;
		$this->_maxAttemptIp = $maxAttemptIp;
		$this->_maxAttemptTimeout = SRA_AUTHENTICATOR_DEFAULT_TIMEOUT;
		if (is_numeric($maxAttemptTimeout) && $maxAttemptTimeout > 0) {
			$this->_maxAttemptTimeout = $maxAttemptTimeout;
		}
		if (!SRA_Params::isValid($params)) {
			$msg = "SRA_Authenticator::SRA_Authenticator: Failed - No SRA_Params parameter specified";
			$this->err = SRA_Error::logError($msg, __FILE__, __LINE__);
			return;
		}
		$this->_params =& $params;
		$this->_pswd = $_SERVER['PHP_AUTH_PW'];
		$this->_user = $_SERVER['PHP_AUTH_USER'];
		if (!$sysErrTpl) {
			$msg = "SRA_Authenticator::SRA_Authenticator: Failed - sysErrTpl not specified";
			$this->err = SRA_Error::logError($msg, __FILE__, __LINE__);
			return;
		}
		if (!$resource) {
			$msg = "SRA_Authenticator::SRA_Authenticator: Failed - resource not specified";
			$this->err = SRA_Error::logError($msg, __FILE__, __LINE__);
			return;
		}
		$this->_resource = $resource;
		$this->_sysErrTpl = $sysErrTpl;
		$this->_tplVar = $tplVar;
		$this->_useSessions = $useSessions;
		
		$this->attrs[SRA_AUTHENTICATOR_ATTR_USER] = $this->_user;
		global $_wsGateway;
    
		// prompt for credentials if not already authenticated
		if (!$this->checkForLogout() && ((!isset($_SERVER['PHP_AUTH_USER'])) || (!isset($_SERVER['PHP_AUTH_PW'])) || (!SRA_Controller::runningFromCli() && $this->_logoutFileExists()))) {
      if (!$_wsGateway && !isset($_COOKIE[SRA_AUTHENTICATOR_LOGOUT_COOKIE]) && $this->_logoutFileExists()) {
        if (SRA_AUTHENTICATOR_DEBUG) 
          SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: Logout cookie does not exist for - PHP_AUTH_USER: " . $_SERVER['PHP_AUTH_USER'] . ', ' . 
                           "PHP_AUTH_PW: " . $_SERVER['PHP_AUTH_PW'] . '. Logout file will be deleted', SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, 
                           FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE);
        unlink($this->_getLogoutFile());
      }
      else if (!$_wsGateway) {
        if (SRA_AUTHENTICATOR_DEBUG) 
          SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: Prompting user - PHP_AUTH_USER: " . $_SERVER['PHP_AUTH_USER'] . ', ' . 
                           "PHP_AUTH_PW: " . $_SERVER['PHP_AUTH_PW'] . ', _logoutFileExists: ' . 
                           $this->_logoutFileExists(), SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, 
                           FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE);
        $this->_displayLoginDialog();
      }
		}
    
    $userVariable =& $this->_getUserVariable();
		
		// check for existing authentication instance in session

		$foundInSession = FALSE;
		if (!SRA_Controller::runningFromCli() && $this->_useSessions) {
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: Use sessions, checking for valid session instance", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			$cache =& $this->_getFromCache();
			
			if ($cache) {
				if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: Cached session instance found (session id: " . session_id() . ")", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
				
				// set match attrs if applicable
				if (count($this->_matchAllAttrs) || count($this->_matchOneAttrs)) {
					if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: Setting and checking match attrs", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
					$cache->_matchAllAttrs = $this->_matchAllAttrs;
					$cache->_matchOneAttrs = $this->_matchOneAttrs;
					$cache->_matchAttributes(TRUE);
				}
				//update _attemptCount
				$this->_attemptCount = $cache->_attemptCount;

				// cache is valid
				if ($cache->status == SRA_AUTHENTICATOR_STATUS_SUCCESS) {
					if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: Cached session is in success state", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
					$cache->_pswd = $this->_pswd;
					SRA_Util::mergeObject($this, $cache, TRUE);
          if (!isset($_SERVER['PHP_AUTH_USER'])) { $_SERVER['PHP_AUTH_USER'] = $this->_user; }
          $userVariable =& $this->_getUserVariable();
					$foundInSession = TRUE;
				}
				// user exceeded _maxAttempts in cache
				else if ($this->_maxAttempts > 0 && $cache->_exceededMaxLoginAttemptCount && $cache->status != SRA_AUTHENTICATOR_STATUS_SUCCESS) {
					if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: Max attempts exceeded and cached session is not in successful state", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
					$tpl =& SRA_Controller::getAppTemplate();
					$tpl->display($this->_maxAttemptTpl);
					exit;
				}
			}
			else {
				if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: Cached session instance not found", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			}
		}
		else if ($this->status != SRA_AUTHENTICATOR_STATUS_SUCCESS && $this->_maxAttempts > 0 && $this->_getLoginAttemptCount() > $this->_maxAttempts) {
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: Sessions not used and max attempt count exceeded", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			$tpl =& SRA_Controller::getAppTemplate();
			$tpl->display($this->_maxAttemptTpl);
			exit;
		}
		
		if (!$foundInSession) {
      include_once('util/SRA_Cache.php');
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: SRA_Authenticator not found in session, authenticating", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
      $cacheTtl = NULL;
      $cacheKey = NULL;
      if ($this->_params && is_numeric($cacheTtl = $this->_params->getParam('cache-auth')) && $cacheTtl > 0 && $this->_user && $this->_pswd && ($temp = SRA_Cache::getCache($cacheKey = '_sraAuthCache_' . $this->_id . '_' . SRA_Controller::getCurrentAppId() . '_' . $this->_user . '_' . base64_encode($this->_pswd)))) {
        if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: got authentication status from cache", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
        $this->status = $temp;
      }
			else if (SRA_Error::isError($this->_authenticate($this->_user, $this->_pswd))) {
				if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: SRA_Error: _authenticate returned error", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
				$this->status = SRA_AUTHENTICATOR_STATUS_ERROR;
			}
      else if ($cacheTtl && $cacheKey) {
        if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: caching authentication status " . $this->status, SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
        SRA_Cache::setCache($cacheKey, $this->status, $cacheTtl*1);
      }
			$this->_matchAttributes();
			$this->_completeAuth();
			
			if ($this->status == SRA_AUTHENTICATOR_STATUS_ERROR && $this->_sysErrTpl) {
				if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: SRA_Error: System error occurred. displaying system error template", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
				$tpl =& SRA_Controller::getAppTemplate();
				$tpl->display($this->_sysErrTpl);
				exit;
			}
		}
		
		if ($this->_attemptCount || $this->status != SRA_AUTHENTICATOR_STATUS_SUCCESS) {
			$this->_updateLoginAttempts();
		}
    
    if ($this->status == SRA_AUTHENTICATOR_STATUS_SUCCESS && ($this->_globalVar || $this->_tplVar)) {
      if (!$userVariable) { $userVariable =& $this->attrs; }
      if ($this->_globalVar) {
        SRA_Util::setGlobal($this->_globalVar, $userVariable);
      }
      if ($this->_tplVar) {
        $tpl =& SRA_Controller::getAppTemplate();
        $tpl->assignByRef($this->_tplVar, $userVariable);
      }
    }
		
		// store authentication instance in the session (if not already stored when _updateLoginAttempts was called above)
		if (!SRA_Controller::runningFromCli() && $this->_useSessions && !$foundInSession && !$this->_written) {
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: Writing session to cache file", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			$this->_writeToCache();
		}
		else {
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: Write to cache is not necessary: _useSessions $this->_useSessions, foundInSession $foundInSession, written $this->_written", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
		}

		if ($this->_exceededMaxLoginAttemptCount) {
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: SRA_Error: exceed max login attempt count", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			exit;
		}
		
		// check for logout
		if ($this->status == SRA_AUTHENTICATOR_STATUS_SUCCESS && $this->checkForLogout()) {
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: Logout occurred", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			$this->logout();
		}
		
    global $_sraAuthSkipConstructorLogin;
		if ($this->status == SRA_AUTHENTICATOR_STATUS_SUCCESS) {
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: SUCCESS", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
		}
		else if (!$_sraAuthSkipConstructorLogin) {
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::SRA_Authenticator: FAILED - $this->status", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
      if (!$_wsGateway) { $this->_displayLoginDialog(); }
		}
	}
	// }}}
	
  
  // public operations
	
	
	// {{{ checkForLogout
	/**
	 * returns TRUE if one of the logout $_GET or $_POST values exists
   * @access public
	 * @return boolean
	 */
	function checkForLogout() {
		return (($this->_logoutGetVar && $_GET[$this->_logoutGetVar]) || ($this->_logoutPostVar && $_POST[$this->_logoutPostVar]));
	}
	// }}}
	
	// {{{ logout
	/**
	 * removed the user's login state to this authenticator
   * @access public
	 * @return void
	 */
	function logout() {
    if (!SRA_Controller::runningFromCli()) {
      if ($this->_id && $this->_user && !$this->_logoutFileExists() && !$this->_loginTpl) {
        SRA_File::touch($this->_getLogoutFile());
        setcookie(SRA_AUTHENTICATOR_LOGOUT_COOKIE);
      }
      $this->_killSession();
      if (isset($_GET[SRA_AUTHENTICATOR_LOGOUT_FWD_VAR])) {
        header('Location: ' . $_GET[SRA_AUTHENTICATOR_LOGOUT_FWD_VAR]);
      }
      else if ($this->_logoutTpl) {
        $tpl =& SRA_Controller::getAppTemplate();
        $tpl->display($this->_logoutTpl);
      }
      else if ($this->_logoutFwdUri) {
        header('Location: ' . $this->_logoutFwdUri);
      }
      else {
        header('Location: ' . $_SERVER['SCRIPT_URL']);
      }
      exit;
    }
	}
	// }}}
	
	// {{{ authenticate()
	/**
	 * Static method used to initiate authentication. called each time a app 
	 * is initialized (using SRA_Controller::init())
	 *
	 * @param array $sysConf the system configuration
	 * @param array $appConf the app configuration
	 * @access public static
	 * @return boolean
	 */
	function authenticate(& $sysConf, & $appConf) {
    global $_wsGateway;
    if (isset($appConf['restrict-access']) && isset($appConf['restrict-access']['attributes'])) {
      $appConf['restrict-access'] = array($appConf['restrict-access']);
    }
    if (isset($sysConf['restrict-access']) && isset($sysConf['restrict-access']['attributes'])) {
      $sysConf['restrict-access'] = array($sysConf['restrict-access']);
    }
		// restrictions
		if (isset($appConf['restrict-access']) && is_array($appConf['restrict-access']) && is_array($sysConf['restrict-access'])) {
      $restrictions = array();
      $keys = array_keys($appConf['restrict-access']);
      foreach($keys as $key) {
        $restrictions[] = $appConf['restrict-access'][$key];
      }
      $keys = array_keys($sysConf['restrict-access']);
      foreach($keys as $key) {
        $restrictions[] = $sysConf['restrict-access'][$key];
      }
		}
		else if (isset($appConf['restrict-access']) && is_array($appConf['restrict-access'])) {
			$restrictions = $appConf['restrict-access'];
		}
		else if (isset($sysConf['restrict-access']) && is_array($sysConf['restrict-access'])) {
			$restrictions = $sysConf['restrict-access'];
		}
		// authenticators
		if (isset($appConf['authenticator']) && is_array($appConf['authenticator']) && is_array($sysConf['authenticator'])) {
			$authenticators = array_merge($appConf['authenticator'], $sysConf['authenticator']);
		}
		else if (isset($appConf['authenticator']) && is_array($appConf['authenticator'])) {
			$authenticators = $appConf['authenticator'];
		}
		else if (isset($sysConf['authenticator']) && is_array($sysConf['authenticator'])) {
			$authenticators = $sysConf['authenticator'];
		}
		
		if (isset($restrictions) && isset($authenticators)) {
			$keys = array_keys($restrictions);
			$doAuths = array();
			$authInstances = array();
			$authMatchAllParams = array();
			$authMatchOneParams = array();
			foreach ($keys as $key) {
				foreach(explode('|', $restrictions[$key]['attributes']['match']) as $match) {
          $match = $match == '*' ? '.*' : $match;
          if (!SRA_Util::beginsWith($match, '/')) $match = '/' . $match;
          if (!SRA_Util::endsWith($match, '/')) $match .= '/i';
          
          if ((trim(strtolower($match)) == strtolower($_SERVER['SCRIPT_FILENAME']) || 
              strstr(strtolower($_SERVER['SCRIPT_FILENAME']), strtolower($match)) || 
              preg_match($match, $_SERVER['SCRIPT_FILENAME']) || 
              preg_match($match, $_SERVER['REQUEST_URI']))) {
            $authIds = explode(' ', $restrictions[$key]['attributes']['authenticators']);
            foreach ($authIds as $authId) {
              if (!isset($authMatchAllParams[$authId])) {
                $authMatchAllParams[$authId] = array();
              }
              if (!isset($authMatchOneParams[$authId])) {
                $authMatchOneParams[$authId] = array();
              }
              if (!isset($authenticators[$authId])) {
                $msg = "SRA_Authenticator::authenticate: Failed - SRA_Authenticator id ${authId} is not valid";
                return SRA_Error::logError($msg, __FILE__, __LINE__);
                return FALSE;
              }
              else {
                if (isset($restrictions[$key]['param'])) {
                  $matchAttrs = new SRA_Params($restrictions[$key]['param']);
                  $matchAttrs = $matchAttrs->getParams(array($id, SRA_PARAMS_NO_TYPE));
                  if ($restrictions[$key]['attributes']['validate-one-attr'] == '1') {
                    SRA_Util::mergeArray($authMatchOneParams[$authId], $matchAttrs);
                  }
                  else {
                    SRA_Util::mergeArray($authMatchAllParams[$authId], $matchAttrs);
                  }
                }
                $doAuths[$authId] = $restrictions[$key];
              }
            }
          }
        }
			}
			$authenticated = $doAuths && count($doAuths) ? FALSE : TRUE;
      global $_sraAuthSkipConstructorLogin;
			foreach (array_keys($doAuths) as $authId) {
        $_sraAuthSkipConstructorLogin = TRUE;
        if (!SRA_Authenticator::_evalRestrictAccessCond($doAuths[$authId]['attributes'])) {
          unset($authInstances[$authId]);
          continue; 
        }
				if (SRA_Authenticator::isValid($authInstances[$authId] =& SRA_Authenticator::_getAuthenticator($authenticators[$authId], $authMatchAllParams[$authId], $authMatchOneParams[$authId]))) {
					if (!SRA_Controller::runningFromCli() && $restrictions[$key]['attributes']['auth-all'] == '1' && $authInstances[$authId]->status != SRA_AUTHENTICATOR_STATUS_SUCCESS) {
            $authInstances[$authId]->_displayLoginDialog();
					}
					else if ($authInstances[$authId]->status == SRA_AUTHENTICATOR_STATUS_SUCCESS) {
						$authenticated = TRUE;
            if ($restrictions[$key]['attributes']['auth-all'] != '1') break;
					}
				}
				else {
					$msg = "SRA_Authenticator::authenticate: Failed - SRA_Authenticator id ${authId} could not be instantiated";
					return SRA_Error::logError($msg, __FILE__, __LINE__);
				}
			}
      unset($_sraAuthSkipConstructorLogin);
			if (!$authenticated) {
				foreach ($authIds as $authId) {
					if (isset($authInstances[$authId]) && $authInstances[$authId]->status != SRA_AUTHENTICATOR_STATUS_SUCCESS) {
						if (!$_wsGateway) { 
              if ($authInstances[$authId]->_failureLog) SRA_LogEntry::log('FAILED: ' . $authInstances[$authId]->status . ' - ' . $authInstances[$authId]->_completeAuthLogMessage(), $authInstances[$authId]->_failureLog, TRUE, $authInstances[$authId]->_id);
              $authInstances[$authId]->_displayLoginDialog();
            }
					}
				}
			}
		}
    else if (SRA_Controller::runningFromCli() || $_wsGateway) {
      $authenticated = TRUE;
    }
		return SRA_Controller::runningFromCli() || $_wsGateway ? $authenticated : TRUE;
	}
	// }}}
  
	// {{{ promptConsole
	/**
	 * this method prompts the user for a username and password at the command 
   * line and sets those values in the $_SERVER['PHP_AUTH_PW'] and 
   * $_SERVER['PHP_AUTH_USER'] globals. it returns TRUE on success, FALSE 
   * otherwise. this method can be overriden by implementing authenticators
	 * @access public
	 * @return boolean
	 */
	function promptConsole() {
    $user = $_SERVER['PHP_AUTH_USER'];
    $password = $_SERVER['PHP_AUTH_PW'];
    if (!$user || !$password) {
      $rb =& SRA_Controller::getAppResources();
      $_readline = function_exists('readline');
      
      if (!$_readline) { $stdin = fopen('php://stdin', 'r'); }
      echo $rb->getString($this->_resource) . "\n\n";
      while(TRUE) {
        if (!$user) {
          if ($_readline) {
            $user = readline($rb->getString('console.auth.user') . ' ');
          }
          else {
            echo $rb->getString('console.auth.user') . ' ';
            $user = trim(fgets($stdin,1000));
          }
          if (!$user) { continue; }
        }
        if (!$password) {
          if ($_readline) {
            $password = readline($rb->getString('console.auth.password') . ' ');
          }
          else {
            echo $rb->getString('console.auth.password') . ' ';
            $password = trim(fgets($stdin,1000));
          }
          if (!$password) { continue; }
        }
        break;
      }
      if (!$_readline) { fclose($stdin); }
    }
    $_SERVER['PHP_AUTH_USER'] = $user;
    $_SERVER['PHP_AUTH_PW'] = $password;
    return TRUE;
	}
	// }}}
	
	
	// {{{ getUserId()
	/**
	 * Static method that returns the user id for the current active user if the 
	 * user is in a secured area
	 *
	 * @access	public static
	 * @return	string
	 */
	function getUserId() {
		return $_SERVER['PHP_AUTH_USER'];
	}
	// }}}
	
	
	// {{{ matchAttribute
	/**
	 * returns TRUE if a given attribute is present and equal to the value 
	 * specified (if a value is specified - otherwise returns TRUE if present). 
	 * if the $attr is an array and $val is specified, then each value in the 
	 * $attr will be checked for a corresponding match
	 * @param string $attr the name of the attribute
	 * @param string $val an optional value to match. may be a regular expression
	 * or a fixed value
   * @access public
	 * @return boolean
	 */
	function matchAttribute($attr, $val = FALSE) {
		if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::matchAttribute: attr: $attr, val: $val", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
		if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug($this->attrs, SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
    $entityAttr = FALSE;
		if (isset($this->attrs[$attr]) || (isset($this->_userEntity) && is_object($this->_userEntity) && ($entityAttr = $this->_userEntity->getAttribute($attr)))) {
			if ($val) {
				$attr = $entityAttr ? $entityAttr : $this->attrs[$attr];
				if (!is_array($attr)) {
					$attr = array($attr);
				}
				$keys = array_keys($attr);
				foreach ($keys as $key) {
					if ((trim(strtolower($val)) == trim(strtolower($attr[$key])) || 
							strstr(trim(strtolower($attr[$key])), trim(strtolower($val))) || 
							ereg("^" . strtolower($val) . "+$", strtolower($attr[$key])))) {
						return TRUE;
					}
				}
			}
			else {
				return TRUE;
			}
		}
		return FALSE;
	}
	// }}}
	
	
	// {{{ isValid()
	/**
	 * Static method that returns true if the object parameter is a SRA_Authenticator object.
	 *
	 * @param  Object $object The object to validate
	 * @access	public
	 * @return	boolean
	 */
	function isValid( & $object ) {
		return (is_object($object) && (!isset($object->err) || !SRA_Error::isError($object->err)) && (strtolower(get_class($object)) == 'sra_authenticator' || is_subclass_of($object, 'SRA_Authenticator')));
	}
	// }}}
	
	
	// {{{ toString
	/**
	 * Returns a string representation of this object
   * @access public
	 * @return String
	 */
	function toString() {
		return SRA_Util::objectToString($this);
	}
	// }}}
	
  
  // private operations
	// {{{ _authenticate
	/**
	 * MUST be implemented by sub-classes. Should authenticate the user and set 
	 * the value of the status attribute according to one of the SRA_AUTHENTICATOR_STATUS_* 
	 * constants
   * @param string $user the username to authenticate
   * @param string $pswd the password to authenticate
   * @access private
	 * @return void or SRA_Error object
	 */
	function _authenticate($user, $pswd) {
		$msg = "SRA_Authenticator::_authenticate: Failed - MUST be implemented by the sub-class";
		return SRA_Error::logError($msg, __FILE__, __LINE__);
	}
	// }}}
	
	// {{{ _completeAuth
	/**
	 * If an authentication does not result in an SRA_Error, this method is invoked to 
	 * complete the login process based on the status code set by the corresponding 
	 * sub-class _authenticate invocation
   * @access private
	 * @return void
	 */
	function _completeAuth() {
		$tpl =& SRA_Controller::getAppTemplate();
		if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_completeAuth: Logging - " . $this->_completeAuthLogMessage(), SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
		// status specific behavior
		switch ($this->status) {
			case SRA_AUTHENTICATOR_STATUS_SUCCESS: 
				if ($this->_accessLog) {
					SRA_LogEntry::log("SUCCESS: " . $this->_completeAuthLogMessage(), $this->_accessLog, TRUE, $this->_id);
				}
				break;
			case SRA_AUTHENTICATOR_STATUS_FAILED: 
			case SRA_AUTHENTICATOR_STATUS_INVALID_PSWD: 
			case SRA_AUTHENTICATOR_STATUS_INVALID_USER: 
			case SRA_AUTHENTICATOR_STATUS_INVALID_ATTRS:
        global $_sraAuthSkipConstructorLogin;
				if (!$_sraAuthSkipConstructorLogin && $this->_failureLog) {
					SRA_LogEntry::log('FAILED: ' . $this->status . ' - ' . $this->_completeAuthLogMessage(), $this->_failureLog, TRUE, $this->_id);
				}
				break;
			case SRA_AUTHENTICATOR_STATUS_ERROR: 

				break;
		}
    if ($this->_loginTpl) {
      $tpl =& SRA_Controller::getAppTemplate();
      $tpl->assign('authStatus', $this->status);
      $tpl->assign('authStatus_' . $this->_id, $this->status);
      if ($this->status == SRA_AUTHENTICATOR_STATUS_SUCCESS && $_POST && isset($_POST['user']) && isset($_POST['password'])) {
        setcookie('sra-auth-completed', '1');
      }
    }
	}
	// }}}
  
  
	// {{{ _completeAuthLogMessage
	/**
	 * returns the log message used by _completeAuth
   * @access private
	 * @return void
	 */
	function _completeAuthLogMessage() {
		return 'RESOURCE: ' . $_SERVER['SCRIPT_FILENAME'] . ' USER: ' . $this->_user . 
							' IP: ' . $_SERVER['REMOTE_ADDR'] . ' ATTEMPT: ' . $this->_getLoginAttemptCount() . 
							' SERVER: ' . $_SERVER['SERVER_NAME'] . ' AGENT: ' . $_SERVER['HTTP_USER_AGENT'] . 
              ' CACHE FILE: ' . $this->_getCacheFileName();
	}
	// }}}
	
	
	// {{{ _displayLoginDialog
	/**
	 * prompts the user for login credentials
   * @access private
	 * @return SRA_Authenticator
	 */
	function _displayLoginDialog() {
    global $_wsGateway;
		if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_displayLoginDialog: Display login prompt", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
		$rb =& SRA_Controller::getAppResources();
		if (SRA_Controller::runningFromCli()) {
      if (!$this->_consolePrompted) {
        if (!$this->promptConsole()) {
          exit;
        }
        $this->_consolePrompted = TRUE;
        $this->_user = $_SERVER['PHP_AUTH_USER'];
        $this->_pswd = $_SERVER['PHP_AUTH_PW'];
        $this->attrs[SRA_AUTHENTICATOR_ATTR_USER] = $this->_user;
      }
    }
    else if ($this->_loginTpl && !$_wsGateway) {
      $tpl =& SRA_Controller::getAppTemplate();
      $tpl->assign('timeout', isset($_COOKIE['sra-auth-completed']) && $_COOKIE['sra-auth-completed'] == '1');
      $tpl->assignByRef('form', $_POST);
      $tpl->display($this->_loginTpl);
      exit;
    }
    else {
      header('WWW-Authenticate: Basic realm="' . $rb->getString($this->_resource) . '"'); 
      header('HTTP/1.0 401 Unauthorized');
      if ($this->_cancelTpl) {
        $tpl =& SRA_Controller::getAppTemplate();
        $tpl->display($this->_cancelTpl);
      }
      if ($this->_logoutFileExists()) {
        unlink($this->_getLogoutFile());
      }
      exit;
    }
	}
	// }}}
  
	// {{{ _evalRestrictAccessCond
	/**
	 * evaluates the conditional parameters for a "restrict-access" element as 
   * defined in app-config. returns TRUE if no conditional parameters are 
   * specified, or if they are specified and evaluate to TRUE
   * @param hash $config hash containing the "restrict-access" "cond-" 
   * parameters (see app-config dtd for more info)
   * @access private
	 * @return boolean
	 */
  function _evalRestrictAccessCond(&$config) {
    $result = TRUE;
    if (isset($config['cond-var'])) {
      $config['cond-op'] = isset($config['cond-op']) ? $config['cond-op']*1 : 1;
      $config['cond-var-type'] = isset($config['cond-var-type']) && ($config['cond-var-type'] == 'form' || $config['cond-var-type'] == 'global' || $config['cond-var-type'] == 'session') ? $config['cond-var-type'] : 'global';
      if ($config['cond-var-type'] == 'form') {
        $var = isset($_POST[$config['cond-var']]) ? $_POST[$config['cond-var']] : (isset($_GET[$config['cond-var']]) ? $_GET[$config['cond-var']] : NULL);
      }
      else if ($config['cond-var-type'] == 'global') {
        $var =& SRA_Util::getGlobal($config['cond-var']);
      }
      else {
        session_start();
        $var = $_SESSION[$config['cond-var']];
      }
      if (is_object($var) && isset($config['cond-var-attr'])) {
        $attr = $config['cond-var-attr'];
        $varAttr = isset($var->${attr}) ? $var->${attr} : (method_exists($var, $attr) ? $var->${attr}() : (method_exists($var, 'getAttribute') ? $var->getAttribute($attr) : NULL));
      }
      else {
        $varAttr = $var;
      }
      $val = isset($config['cond-val']) ? $config['cond-val'] : TRUE;
      
      // greater than/equal
      if ($config['cond-op'] & 2 && $config['cond-op'] & 1) { $result = $varAttr >= $val; }
      
      // greater than
      else if ($config['cond-op'] & 2) { $result = $varAttr > $val; }
      
      // less than/equal
      else if ($config['cond-op'] & 4 && $config['cond-op'] & 1) { $result = $varAttr <= $val; }
      
      // less than
      else if ($config['cond-op'] & 4) { $result = $varAttr < $val; }
      
      // identical
      else if ($config['cond-op'] & 1 && $config['cond-op'] & 512) { $result = $varAttr === $val; }
      
      // equal
      else if ($config['cond-op'] & 1) { $result = $varAttr == $val; }
      
      // starts with
      else if ($config['cond-op'] & 8) { $result = SRA_Util::beginsWith($varAttr, $val); }
      
      // ends with
      else if ($config['cond-op'] & 16) { $result = SRA_Util::endsWith($varAttr, $val); }
      
      // substring
      else if ($config['cond-op'] & 32) { $result = strpos($varAttr, $val) !== FALSE; }
      
      // negate
      if ($config['cond-op'] & 256) { $result = !$result; }
      
    }
    return $result;
  }
  // }}}
	
	
	// {{{ _getAuthenticator
	/**
	 * instantiate and returns an SRA_Authenticator based on the configuration and 
	 * restrictions specified
   * @access private
	 * @return SRA_Authenticator
	 */
	function & _getAuthenticator(& $conf, $matchAllAttrs, $matchOneAttrs) {
		$id = $conf['attributes']['key'];
		
		// hard-coded path
		if ($conf['attributes']['path']) {
			$search = $conf['attributes']['path'];
		}
		else {
			$search = $conf['attributes']['type'] . '.' . SRA_SYS_PHP_EXTENSION;
		}
		$search = SRA_Util::removeLeadingSlash($search);
		if (file_exists(SRA_Controller::getAppLibDir() . '/' . $search)) {
			$path = SRA_Controller::getAppLibDir() . '/' . $search;
		}
		else if (file_exists(SRA_LIB_DIR . '/auth/' . $search)) {
			$path = SRA_LIB_DIR . '/auth/' . $search;
		}
		else if (file_exists(SRA_LIB_DIR . '/' . $search)) {
			$path = SRA_LIB_DIR . '/' . $search;
		}
		else if (file_exists($search)) {
			$path = $search;
		}
		else if (file_exists('/' . $search)) {
			$path = '/' . $search;
		}
		if (!$path) {
			$msg = "SRA_Authenticator::_getAuthenticator: Failed - Cannot locate authenticator ${id}";
			return SRA_Error::logError($msg, __FILE__, __LINE__);
		}
		$className = $conf['attributes']['type'];
		include_once($path);
		if (!class_exists($className)) {
			$msg = "SRA_Authenticator::_getAuthenticator: Failed - Class type ${className} is not valid";
			return SRA_Error::logError($msg, __FILE__, __LINE__);
		}
		$maxAttempts = 0;
		if (isset($conf['attributes']['max-attempts'])) {
			$maxAttempts = $conf['attributes']['max-attempts'];
		}
		$maxAttemptIp = FALSE;
		if (isset($conf['attributes']['max-attempt-ip'])) {
			$maxAttemptIp = $conf['attributes']['max-attempt-ip'] == '1';
		}
		$maxAttemptTimeout = SRA_AUTHENTICATOR_DEFAULT_TIMEOUT;
		if (isset($conf['attributes']['max-attempt-timeout'])) {
			$maxAttemptTimeout = $conf['attributes']['max-attempt-timeout'];
		}
		$useSessions = TRUE;
		if (isset($conf['attributes']['use-sessions'])) {
			$useSessions = $conf['attributes']['use-sessions'] == '1';
		}
    
    if (isset($conf['attributes']['login-tpl'])) {
      session_start();
      // check for login-tpl form post
      if (count($_POST) && $_POST['user'] && $_POST['password']) {
        $_SERVER['PHP_AUTH_USER'] = $_POST['user'];
        $_SERVER['PHP_AUTH_PW'] = $_POST['password'];
        $_SESSION['sra-auth-user'] = $_POST['user'];
        $_SESSION['sra-auth-pw'] = $_POST['password'];
      }
      // check for login credentials in session
      else if (isset($_SESSION['sra-auth-user']) && isset($_SESSION['sra-auth-pw'])) {
        $_SERVER['PHP_AUTH_USER'] = $_SESSION['sra-auth-user'];
        $_SERVER['PHP_AUTH_PW'] = $_SESSION['sra-auth-pw'];
      }
    }
    
    // don't use sessions for wget or shell connections
    if ($useSessions) $useSessions = !isset($_SERVER['HTTP_USER_AGENT']) || preg_match('/wget/i', $_SERVER['HTTP_USER_AGENT']) || preg_match('/curl/i', $_SERVER['HTTP_USER_AGENT']) ? FALSE : TRUE;
    
		$obj = new ${className}($id, $conf['attributes']['access-log'], $conf['attributes']['cancel-tpl'], 
                            $conf['attributes']['entity-type'], $conf['attributes']['entity-user-col'], 
														$conf['attributes']['failure-log'], $conf['attributes']['global-var'], 
														$conf['attributes']['login-tpl'], $conf['attributes']['logout-fwd-uri'], 
														$conf['attributes']['logout-get-var'], $conf['attributes']['logout-post-var'], 
														$conf['attributes']['logout-tpl'], $matchAllAttrs, $matchOneAttrs, 
														$conf['attributes']['match-fail-tpl'], 
												 		$maxAttempts, $conf['attributes']['max-attempt-tpl'], 
														$maxAttemptIp, $maxAttemptTimeout, new SRA_Params($conf['param']), 
														$conf['attributes']['resource'], $conf['attributes']['sys-err-tpl'], 
														$conf['attributes']['tpl-var'], $useSessions);
														
		return $obj;
	}
	// }}}
	
	
	// {{{ _getCacheFileName
	/**
	 * returns the file name to use for caching operations for this instance of SRA_Authenticator
   * @access private
	 * @return string
	 */
	function _getCacheFileName() {
		if (!session_id()) { session_start(); }
		$cacheFile = $this->_getCacheFilePrefix() . session_id();
		if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_getCacheFileName: Cache file is $cacheFile", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
		return session_id() ? $cacheFile : FALSE;
	}
	// }}}
	
	
	// {{{ _getCacheFilePrefix
	/**
	 * returns the file name prefix for session cache files
   * @access private
	 * @return string
	 */
	function _getCacheFilePrefix() {
		return SRA_Controller::getAppTmpDir() . '/' . SRA_AUTHENTICATOR_FILE_PREFIX . $this->_id;
	}
	// }}}
	
	
	// {{{ _getFromCache
	/**
	 * gets an SRA_Authenticator from cache if it exists. this function only works with 
	 * sessions enabled
   * @access private
	 * @return SRA_Authenticator|FALSE
	 */
	function & _getFromCache() {
		static $cached = array();
		
		if ($this->_writeToCache(TRUE)) {
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_getFromCache: Instance retrieved from write cache", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			return $this->_writeToCache(TRUE);
		}
		else {
			$fileName = $this->_getCacheFileName();
			if ($fileName && !isset($cached[$fileName])) {
				$cached[$fileName] = file_exists($fileName) ? unserialize(SRA_File::toString($fileName)) : FALSE;
        if (!$this->_user && SRA_Authenticator::isValid($cached[$fileName])) { $this->_user = $cached[$fileName]->_user; }
				if (SRA_AUTHENTICATOR_DEBUG && file_exists($fileName)) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_getFromCache: Instance retrieved from file $fileName", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			}
			return isset($cached[$fileName]) && SRA_Authenticator::isValid($cached[$fileName]) ? $cached[$fileName] : FALSE;
		}
	}
	// }}}
	
	
	// {{{ _getLoginAttemptCount
	/**
	 * returns the # of times that this user has attempted to login based on the 
	 * tracking method specified (IP or sessions)
   * @access private
	 * @return int
	 */
	function _getLoginAttemptCount() {
    if (!SRA_Controller::runningFromCli()) {
      // tracking based on IP
      if ($this->_maxAttemptIp) {
        $file = SRA_Controller::getAppTmpDir() . '/' . SRA_AUTHENTICATOR_FILE_PREFIX . $this->_id . $_SERVER['REMOTE_ADDR'];
        // delete old files
        if (file_exists($file) && (filectime($file) < (time() - ($this->_maxAttemptTimeout * 60)))) {
          unlink($file);
        }
        
        $ret = 1;
        if (file_exists($file)) {
          $fp = fopen($file, 'r');
          $data = fread($fp, 4096);
          fclose($fp);
          $data = explode('\n', $data);
          if (is_numeric($data[0])) {
            $ret = $data[0];
          }
        }
        if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_getLoginAttemptCount: Returning login attempt count $ret for IP " . $_SERVER['REMOTE_ADDR'] . " from file $file", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
        return $ret;
      }
      // tracking based on session
      else {
        if ($this->_attemptCount) {
          return $this->_attemptCount;
        }
        else if ($auth =& $this->_getFromCache()) {
          $ret = $auth->_attemptCount;
        }
        else {
          $ret = 1;
        }
        if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_getLoginAttemptCount: Returning login attempt count $ret for Session " . session_id(), SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
        return $ret;
      }
    }
    else {
      return 1;
    }
	}
	// }}}
	
	
	// {{{ _getLogoutFile
	/**
	 * returns the path to the logout file. this file will be created each time 
	 * the user logs out and deleted (if it exists) each time the user logs in 
	 * successfully
   * @access private
	 * @return string
	 */
	function _getLogoutFile() {
		$logoutFile = SRA_Controller::getAppTmpDir() . '/' . SRA_AUTHENTICATOR_LOGOUT_FILE_PREFIX . $this->_user;
		if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_getLogoutFile: Returning logout file $logoutFile", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
		return $logoutFile;
	}
	// }}}
	
  
	// {{{ _getUserVariable
	/**
	 * returns the user variable for this authenticator (if applicable)
   * @access private
	 * @return mixed
	 */
  function &_getUserVariable() {
    if (isset($_SERVER['PHP_AUTH_USER']) && $this->_entityType) {
      if (!SRA_Error::isError($dao =& SRA_DaoFactory::getDao($this->_entityType))) {
        if ($this->_entityUserCol && SRA_Database::isValid($db =& SRA_Controller::getAppDb()) && !SRA_Error::isError($tmp =& $dao->findBySqlConstraints(array($this->_entityUserCol => $db->convertText($_SERVER['PHP_AUTH_USER'])))) && count($tmp) == 1) {
          $userVariable =& $tmp[0];
          $this->_userEntity =& $tmp[0];
        }
        else if (!$this->_entityUserCol && !SRA_Error::isError($tmp =& $dao->findByPk($_SERVER['PHP_AUTH_USER'])) && is_object($tmp)) {
          $userVariable =& $tmp;
          $this->_userEntity =& $tmp;
        }
      }
    }
    return $userVariable;
  }
  // }}}
  
	
	// {{{ _killSession
	/**
	 * kills any data in the current session if the SRA_Authenticator uses sessions
   * @access private
	 * @return string
	 */
	function _killSession() {
		if ($this->_useSessions) {
			$this->_removeFromCache();
			session_start();
			$_SESSION = array();
			if (isset($_COOKIE[session_name()])) {
			  setcookie(session_name(), '', time()-42000, '/');
        if ($this->_loginTpl) {
          setcookie('sra-auth-completed', '', time()-42000, '/');
        }
			}
			session_destroy();
		}
	}
	// }}}
	
	
	// {{{ _logoutFileExists
	/**
	 * returns TRUE if a logout file exists for this authenticator and user
   * @access private
	 * @return boolean
	 */
	function _logoutFileExists() {
		return $this->_user && file_exists($this->_getLogoutFile());
	}
	// }}}
	
	
	// {{{ _matchAttributes
	/**
	 * matches SRA_Authenticator instance attributes if applicable and sets the 
	 * corresponding status code. alternatively, if a "match-fail-tpl" has been 
	 * defined, it will be displayed immediately and the process exited
   * @access private
	 * @return void
	 */
	function _matchAttributes($ignoreMatchFail = FALSE) {
		// first, convert scalar attributes to arrays where necessary
		if ($attrs = $this->_params->getParams('aattrs')) {
			$keys = array_keys($attrs);
			foreach ($keys as $key) {
				$akey = $key;
				if ($attrs[$key]) {
					$akey = $attrs[$key];
				}
				if (isset($this->attrs[$akey]) && !is_array($this->attrs[$akey])) {
					$this->attrs[$akey] = explode(' ', $this->attrs[$akey]);
				}
			}
		}
		if ($this->status == SRA_AUTHENTICATOR_STATUS_SUCCESS && (is_array($this->_matchAllAttrs) || is_array($this->_matchOneAttrs))) {
			$attrs = $this->attrs[$akey];
			if (!is_array($attrs)) {
				$attrs = array($attrs);
			}
			$keys = array_keys($this->_matchOneAttrs);
      if (isset($this->_userEntity) && is_object($this->_userEntity) && method_exists($this->_userEntity, 'getAttribute')) {
        // get additional _userEntity attributes
        foreach ($keys as $key) {
          if (!isset($attrs[$key])) {
            $attrs[$key] = $this->_userEntity->getAttribute($key);
          }
        }
      }
      $akeys = array_keys($attrs);
			$validatedOneAttr = FALSE;
			$validatedAllAttr = TRUE;
			$unmatchedAttr = FALSE;
			foreach ($keys as $key) {
				$match = FALSE;
				foreach ($akeys as $akey) {
					if ((trim(strtolower($this->_matchOneAttrs[$key])) == trim(strtolower($attrs[$akey])) || 
							strstr(trim(strtolower($attrs[$akey])), trim(strtolower($this->_matchOneAttrs[$key]))) || 
							ereg("^" . strtolower($this->_matchOneAttrs[$key]) . "+$", strtolower($attrs[$akey])))) {
						$match = TRUE;
						if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_matchAttributes: Match One: Found match $key/" . $this->_matchOneAttrs[$key], SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
						break;
					}
					else {
						if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_matchAttributes: Match One: NO match $key/" . $this->_matchOneAttrs[$key], SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
						$this->unmatchedAttr = $key;
					}
				}
				if ($match) {
					$validatedOneAttr = TRUE;
					break;
				}
			}
			$validatedOneAttr = count($this->_matchOneAttrs) ? $validatedOneAttr : TRUE;
      
			$keys = array_keys($this->_matchAllAttrs);
      if (isset($this->_userEntity) && is_object($this->_userEntity) && method_exists($this->_userEntity, 'getAttribute')) {
        // get additional _userEntity attributes
        foreach ($keys as $key) {
          if (!isset($attrs[$key])) {
            $attrs[$key] = $this->_userEntity->getAttribute($key);
          }
        }
      }
      $akeys = array_keys($attrs);
			foreach ($keys as $key) {
				$match = FALSE;
				foreach ($akeys as $akey) {
					if ((trim(strtolower($this->_matchAllAttrs[$key])) == trim(strtolower($attrs[$akey])) || 
							strstr(trim(strtolower($attrs[$akey])), trim(strtolower($this->_matchAllAttrs[$key]))) || 
							ereg("^" . strtolower($this->_matchAllAttrs[$key]) . "+$", strtolower($attrs[$akey])))) {
						$match = TRUE;
						if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_matchAttributes: Match All: Found match $key/" . $this->_matchAllAttrs[$key], SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
						break;
					}
					else {
						if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_matchAttributes: Match All: NO match $key/" . $this->_matchAllAttrs[$key], SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
						$this->unmatchedAttr = $key;
					}
				}
				if (!$match) {
					$validatedAllAttr = FALSE;
					break;
				}
			}
			$validatedAllAttr = count($this->_matchAllAttrs) ? $validatedAllAttr : TRUE;
			
			if ($validatedAllAttr && $validatedOneAttr) {
				if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_matchAttributes: Match succeeded", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
				$this->status = SRA_AUTHENTICATOR_STATUS_SUCCESS;
				$this->unmatchedAttr = FALSE;
			}
			else {
				if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_matchAttributes: Match failed", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
				$this->status = SRA_AUTHENTICATOR_STATUS_INVALID_ATTRS;
				// display match failed template
				if ($this->_matchFailTpl && !$ignoreMatchFail) {
					if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_matchAttributes: Displaying match-fail-tpl $this->_matchFailTpl", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
					$tpl =& SRA_Controller::getAppTemplate();
					$tpl->display($this->_matchFailTpl);
					exit;
				}
			}
		}
	}
	// }}}
	
	
	// {{{ _removeFromCache
	/**
	 * removes an authenticator cache file if it exists
   * @access private
	 * @return void
	 */
	function _removeFromCache() {
		if ($fileName = $this->_getCacheFileName()) {
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_removeFromCache: Removing $fileName from cache", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			unlink($fileName);
		}
	}
	// }}}
	
	
	// {{{ _updateLoginAttempts
	/**
	 * updates the failed login attempts count if applicable. sets _exceededMaxLoginAttemptCount 
	 * to true if applicable
   * @access private
	 * @return void
	 */
	function _updateLoginAttempts() {
		if ($this->status != SRA_AUTHENTICATOR_STATUS_ERROR && $this->_maxAttempts > 0) {
			// tracking based on IP
			if ($this->_maxAttemptIp) {
				if ($this->status != SRA_AUTHENTICATOR_STATUS_SUCCESS) {
					$loginCount = $this->_getLoginAttemptCount() + 1;
				}
				else {
					$loginCount = 0;
				}
				if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_updateLoginAttempts: Setting login attempt count $loginCount for IP: " . $_SERVER['REMOTE_ADDR'], SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
				$file = SRA_Controller::getAppTmpDir() . '/' . SRA_AUTHENTICATOR_FILE_PREFIX . $this->_id . $_SERVER['REMOTE_ADDR'];
				$fp = fopen($file, 'w');
				fwrite($fp, $loginCount);
				fclose($fp);
			}
			// tracking based on session
			else {
				if (!session_id()) {
					session_start();
				}
				if ($this->status != SRA_AUTHENTICATOR_STATUS_SUCCESS) {
					$loginCount = $this->_getLoginAttemptCount() + 1;
				}
				else {
					$loginCount = 0;
				}
				if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_updateLoginAttempts: Status: $this->status Setting login attempt count $loginCount for session " . session_id(), SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
				$this->_attemptCount = $loginCount;
				$this->_writeToCache();
			}
			
			// max login attempts exceeded
			if ($this->status != SRA_AUTHENTICATOR_STATUS_SUCCESS && $loginCount > $this->_maxAttempts) {
				$this->_exceededMaxLoginAttemptCount = TRUE;
				if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_updateLoginAttempts: $loginCount exceeded max allowed", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
				if ($this->_maxAttemptTpl) {
					$tpl =& SRA_Controller::getAppTemplate();
					if ($this->_tplVar) {
						$tpl->assignByRef($this->_tplVar, $this);
					}
					$tpl->display($this->_maxAttemptTpl);
					exit;
				}
			}
			else {
				$this->_exceededMaxLoginAttemptCount = FALSE;
				if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_updateLoginAttempts: $loginCount is OK", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			}
		}
	}
	// }}}
	
	
	// {{{ _writeToCache
	/**
	 * writes the current SRA_Authenticator instance to cache based on the user's 
	 * session_id
	 * @param boolean $lookup whether or not to attempt to lookup the authenticator 
	 * in cache and return it if it exists (it will only exist if previously 
	 * written)
   * @access private
	 * @return void
	 */
	function & _writeToCache($lookup = FALSE) {
		static $written = array();
		if ($fileName = $this->_getCacheFileName()) {
			// lookup
			if ($lookup && isset($written[$fileName])) {
				return $written[$fileName];
			}
			else if ($lookup) {
				return FALSE;
			}
			
			// don't store password in cache file
			$pswd = $this->_pswd;
			$this->_pswd = FALSE;
			$attrs = FALSE;
			SRA_File::write($fileName, serialize($this));
			$this->_pswd = $pswd;
			$written[$fileName] =& $this;
			$this->_written = TRUE;
			
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_writeToCache: Wrote to cache $fileName", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			
			// remove old cache files
			$prefix = $this->_getCacheFilePrefix();
			$files = SRA_File::getFileList(dirname($prefix), '/^' . basename($prefix) . '.*$/');
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_writeToCache: Evaluating cache files: ", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug($files, SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
			foreach ($files as $file) {
				if (!file_exists($sfile = session_save_path() . '/sess_' . str_replace(basename($prefix), '', basename($file)))) {
					if (SRA_AUTHENTICATOR_DEBUG) { SRA_Util::printDebug("$this->_id: SRA_Authenticator::_writeToCache: Removing old cache file: $file", SRA_AUTHENTICATOR_DEBUG, __FILE__, __LINE__, FALSE, FALSE, TRUE, SRA_AUTHENTICATOR_DEBUG_FILE); }
					unlink($file);
				}
			}
		}
	}
	// }}}
  
}
// }}}
?>
Return current item: Sierra-php PHP Application Framework