ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: DB_eSession PHP class facilitates having sessions stored in a MySQL database.
Submitter: Lawrence O (other recipes)
Last Updated: 2004/11/28
Version no: 1.0
Category: Session Management

 

5 stars 1 vote(s)


Description:

DB_eSession is a feature packed PHP class that stores session data in a MySQL database rather than flat files. It is powerful, designed with security in mind, and yet easy to utilize. The web site has a full package download containing example scripts too.

Source: Text Source

<?PHP //Make sure there are no whitespaces before '<' on this line.
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | DB_eSession is a feature packed PHP class that stores session data   |
// | in a MySQL database rather than files. It is powerful, designed with |
// | security in mind, and yet easy to utilize. The code contains lots of |
// | comments, it comes with full documentation, and examples of how to   |
// | use the class including a basic authentication login/logout process. |
// | It includes member functions useful (to webmasters) for monitoring or|
// | viewing, deleting, and altering sessions validity like in the case of|
// | locking one or more sessions upon detection of unauthorized use.     |
// | This custom MySQL database session handler class might just be what  |
// | you're looking to implement on your web or intranet site. Enjoy it!  |
// |                                                                      |
// | This script has been created and released under the GNU GPL and is   |
// | free to use and redistribute only if this whole header comments and  |
// | copyright statement are not removed. Author gives no warranties. Use |
// | at your own risk. Read the copyright, disclaimer, and license.       |
// |                                                                      |
// | System Requirements: Any OS supporting a web server for PHP to run.  |
// | Requires PHP version 4.2.0 or higher, MySQL version 3.22.5 or later. |
// | libmcrypt ver 2.2.x or higher is optional for encryption/decryption. |
// | session.auto_start PHP setting needs to be off. Register_globals can |
// | be on or off.                                                        |
// |                                                                      |
// | Tested under PHP ver 4.3.2/4/5, MySQL version 4.0.15/18, mcrypt 2.4.x|
// |                                                                      |
// +----------------------------------------------------------------------+
// | DB_eSession, Copyright (c) 2004 Lawrence Osiris, All Rights Reserved |
// +----------------------------------------------------------------------+
// | This program is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU General Public License as published by |
// | the Free Software Foundation; either version 2 of the License, or    |
// | (at your option) any later version.                                  |
// |                                                                      |
// | This program is distributed in the hope that it will be useful,      |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
// | GNU General Public License for more details.                         |
// |                                                                      |
// | You should have received a copy of the GNU General Public License    |
// | along with this program; if not, write to the                        |
// |                                                                      |
// | Free Software Foundation, Inc.,                                      |
// | 59 Temple Place, Suite 330,                                          |
// | Boston, MA  02111-1307  USA                                          |
// |                                                                      |
// | Or you may obtain the license at http://www.gnu.org/copyleft/gpl.html|
// |                                                                      |
// +----------------------------------------------------------------------+
// | Author: Lawrence Osiris <code@dearneighbor.com>                      |
// | At web: http://www.code.dearneighbor.com                             |
// |                                                                      |
// | Silas Palmer from Australia, wrote the code in sessEncode and        |
// | sessDecode member functions. Code used with permission and under GNU |
// | GPL too. Web address: http://www.silaspalmer.com                     |
// |                                                                      |
// +----------------------------------------------------------------------+
// |                                                                      |
// |                      C H A N G E   L O G                             |
// |                      -------------------                             |
// |                                                                      |
// | DATE        VERSION  DESCRIPTION                                     |
// | ----------  -------  ----------------------------------------------- |
// | 05/05/2004   1.0.0   Initial code distribution to the general public |
// | 06/03/2004   1.0.1   sessDecode: removed substr() and added trim().  |
// | 08/08/2004   1.0.2   sessDecode: Initialized $_decoded variable.     |
// |                      _getSecID: Commented out HTTP_ACCEPT_ENCODING.  |
// +----------------------------------------------------------------------+


/**
 * DB_ESESSION_LOADED - For checking whether the class has been defined. You can
 * use DB_ESESSION_LOADED or class_exists().
 *
 * @access public
 * @global bool To indicate this class has been loaded (with an include or require)
 */
define('DB_ESESSION_LOADED', TRUE);


/**
 * @package    DB_eSession
 * @license    http://opensource.org/licenses/gpl-license.php GNU Public License
 * @author     Lawrence Osiris <code@dearneighbor.com>
 * @link       http://www.code.dearneighbor.com
 * @copyright  Copyright &copy; 2004, Lawrence Osiris
 * @version    $Version: 1.0.0$
 * @access     public
 */
class DB_eSession
{

    /**
     * @var    string $_ver This scripts version number
     * @access private
     */
    var $_ver = '1.0.0';


    /**
     * @var    string $_REQ_VER The minimum PHP version number this script
     *                          requires in order to execute successfully.
     * @access private
     */
    var $_REQ_VER = '4.2.0';


    /**
     * @var    string $_mysql_ver The current MySQL version number
     * @access private
     */
    var $_mysql_ver = NULL;


    /**
     * @var    int $_dbh The resource link to the session database
     * @access private
     */
    var $_dbh;


    /**
     * @var    array $_db Holds session database access and table info.
     * @access private
     */
    var $_db = array();


    /**
     * @var    array $_sess_opt Holds the session configuration option values
     * @access private
     */
    var $_sess_opt = array();


    /**
     * @var    string $_sess_name Holds the current session name.
     * @access private
     */
    var $_sess_name = NULL;


    /**
     * @var    int $_sess_ID_len Holds the character length of session ID.
     * @access private
     */
    var $_sess_ID_len;


    /**
     * @var    string $_DEFAULT_LANG What the default language code is
     * @access private
     */
    var $_DEFAULT_LANG;


    /**
     * @var    string $_CURRENT_LANG What the current language code in use is
     * @access private
     */
    var $_CURRENT_LANG;


    /**
     * @var    bool   $_stop_on_warn Whether to stop script on encountering a
     *                warning message. Set $_param['stop_on_warn'].
     * @access private
     */
    var $_stop_on_warn;


    /**
     * @var    string $_WRN_COLOR Contains font color for warning messages.
     * @access private
     */
    var $_WRN_COLOR;


    /**
     * @var    string $_WRN_SIZE Contains font size for warning messages.
     * @access private
     */
    var $_WRN_SIZE;


    /**
     * @var    array $_WRN_MSGS Contains warning message constants for ea. lang.
     * @access private
     */
    var $_WRN_MSGS;


    /**
     * @var    string $_warnings Contains any non-fatal warning messages
     * @access private
     */
    var $_warnings = NULL;


    /**
     * @var    bool   $_stop_on_error Whether to stop script on encountering an
     *                error message or not. Set $_param['stop_on_error'].
     * @access private
     */
    var $_stop_on_error;


    /**
     * @var    string $_ERR_COLOR Contains font color for error messages.
     * @access private
     */
    var $_ERR_COLOR;


    /**
     * @var    string $_ERR_SIZE Contains font size for error messages.
     * @access private
     */
    var $_ERR_SIZE;


    /**
     * @var    array $_ERR_MSGS Contains error message constants for ea. lang.
     * @access private
     */
    var $_ERR_MSGS;


    /**
     * @var    string $_errors Contains error messages encountered
     * @access private
     */
    var $_errors = NULL;


    /**
     * @var    bool $_DETAIL_ERR_MSGS Display detail errors/warnings or not.
     * @access private
     */
    var $_DETAIL_ERR_MSGS;


    /**
     * @var    int $_MIN_SESS_ID_LEN Holds the minimum session ID length (12)
     * @access private
     */
    var $_MIN_SESS_ID_LEN = 12;


    /**
     * @var    int $_MAX_SESS_ID_LEN Holds the maximum session ID length of 32
     * @access private
     */
    var $_MAX_SESS_ID_LEN = 32;


    /**
     * @var    int $_SESS_LIFE Holds the session life duration in seconds
     * @access private
     */
    var $_SESS_LIFE;


    /**
     * @var    int $_SESS_TIMEOUT Holds the absolute session life in seconds
     * @access private
     */
    var $_SESS_TIMEOUT;


    /**
     * @var    int $_SEC_LEVEL Holds a number designating session security level
     * @access private
     */
    var $_SEC_LEVEL;

    /**
     * @var    bool $_ENCRYPT A flag to turn on session encryption TRUE/FALSE
     * @access private
     */
    var $_ENCRYPT;


    /**
     * @var    bool $_ENCRYPT_KEY A value used in session encryption/decryption
     * @access private
     */
    var $_ENCRYPT_KEY;

    /**
     * @var    bool $_ENC_KEY_HASHED An md5 value of $_ENCRYPT_KEY for security.
     * @access private
     */
    var $_ENC_KEY_HASHED;


    /**
     * @var    bool $_MCRYPT A flag to indicate if mcrypt library installed
     * @access private
     */
    var $_MCRYPT;


    /**
     * @var    bool $_MCRYPT_LATEST A flag to indicate if it's a newer library
     * @access private
     */
    var $_MCRYPT_LATEST;


    /**
     * @var    string $_KEY_PREFIX A secret key used in prefixing MD5 hashes
     * @access private
     */
    var $_KEY_PREFIX;


    /**
     * @var    string $_KEY_SUFFIX A secret key used in suffixing MD5 hashes
     * @access private
     */
    var $_KEY_SUFFIX;


    /**
     * @var    string $_CONF_PSWD A confirmation password for delete and lock
     * @access private
     */
    var $_CONF_PSWD;


    /**
     * @var    bool $_MAGIC_QUOTES_GPC Determines if GET/POST/COOKIE data are
     *              slashed
     * @access private
     */
    var $_MAGIC_QUOTES_GPC;


    /**
     * @var    bool $_MAGIC_QUOTES_RUNTIME Determines if external source data is
     *              slashed after reads (like from a DB)
     * @access private
     */
    var $_MAGIC_QUOTES_RUNTIME;


    /**
     * @var    bool $_ARG_SEP Output argument separator. Usually '&'.
     * @access private
     */
    var $_ARG_SEP;


    /**
     * @var    bool $_SLASH_ANYWAY Forces addslashes to occur to session data
     * @access private
     */
    var $_SLASH_ANYWAY;


    /**
     * @var    bool $_STRIP_ANYWAY Forces stripslashes to occur to session data
     * @access private
     */
    var $_STRIP_ANYWAY;


    /**
     * @var    bool $_GC_DEL_LOCKED Garbage Collection delete locked session T/F
     * @access private
     */
    var $_GC_DEL_LOCKED;


    /**
     * DB_eSession - Constructor
     * You could change to always pass by reference like this: (&$_param)
     * Or you could leave as is, and pass by reference to save on memory, like
     * this: $sess = new DB_eSession(&$sess_param);
     *
     * @param  array $_param Various database and session setting options
     * @return obj   New instance of DB_eSession class
     * @access private
     */
    function DB_eSession($_param = array())
    {
        define('STOP', TRUE);

        /**
         * Check minimum PHP version number for script to work, and
         * produce error if it doesn't meet that requirement.
         * version_compare() requires PHP v4.1.0 to work but shouldn't
         * use here because current PHP might be less than that.
         */
        if (strcmp($this->_REQ_VER, PHP_VERSION) > 0) {

            $this->_errors = PHP_VERSION . ' < ' . $this->_REQ_VER . "\n";
            /**
             * Display error and stop execution regardless of _stop_on_error
             * setting.
             */
            $this->_handleErrors(STOP);     // Severe error - exit script

        }


        if (is_array($_param)) {
            $_not_array = NULL;

        } else {
            $_not_array = 'NOT_ARRAY';      // For producing a warning
            $_param = array();
        }


        /**
         * Set the default and current language codes for displaying error and
         * warning messages. Default is 'en' for English.
         */
        $this->_DEFAULT_LANG = isSet($_param['default_lang']) ?
                                     $_param['default_lang']  : 'en';


        $this->_CURRENT_LANG = isSet($_param['current_lang']) ?
                                     $_param['current_lang']  :
                                     isSet($_SERVER['HTTP_ACCEPT_LANGUAGE']) ?
                        substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2) : 'en';


        /**
         * Set $_param['stop_on_error'] => FALSE to not have this class
         * stop execution upon an error. This means you will handle the
         * error checking and displays in your script. Default is to stop
         * (TRUE). This is used as the initial setting. This can be turned
         * on and off at any time by using stopOnErrors() or endStopOnErrors().
         */
        $this->_stop_on_error = (bool) isSet($_param['stop_on_error']) ?
                                             $_param['stop_on_error']  : TRUE;

        /**
         * Set the font color for error messages (any valid HTML syntax)
         */
        $this->_ERR_COLOR = isSet($_param['error_color']) ?
                                  $_param['error_color']  : 'RED';

        /**
         * Set the font size for error messages (any valid HTML syntax)
         */
        $this->_ERR_SIZE  = isSet($_param['error_size'])  ?
                                  $_param['error_size']   : '+0';

        /**
         * Set $_param['stop_on_warn'] => TRUE to have this class
         * stop execution upon a warning. Default is not to stop (FALSE). This
         * is used as the initial setting. This can be turned on and off at any
         * time by using stopOnWarnings() or endStopOnWarnings().
         */
        $this->_stop_on_warn = (bool) isSet($_param['stop_on_warn']) ?
                                            $_param['stop_on_warn']  : FALSE;

        /**
         * Set the font color for warning messages (any valid HTML syntax)
         */
        $this->_WRN_COLOR = isSet($_param['warn_color']) ?
                                  $_param['warn_color']  : 'BLUE';

        /**
         * Set the font size for warning messages (any valid HTML syntax)
         */
        $this->_WRN_SIZE  = isSet($_param['warn_size'])  ?
                                  $_param['warn_size']   : '+0';

        /**
         * Set to TRUE to display SQL syntax and other values when displaying
         * errors or warning messages encountered. Default is FALSE for security
         * purposes. Turn on mostly when in development or testing your site,
         * but remember to turn it off for a production ready site.
         */
        $this->_DETAIL_ERR_MSGS = (bool) isSet($_param['detail_err_msgs']) ?
                                               $_param['detail_err_msgs']  :
                                               FALSE;


        /**
         * Set $_param['buffer'] => TRUE to have this class
         * execute the ob_start() command to start buffering the output.
         * You may want to use if you can't resolve the 'headers already sent'
         * warning message generated by PHP/this script. The ob_end_flush()
         * is called implicitly at the end of your script. It flushes out the
         * contents of the buffer to the browser, and destroys the current
         * output buffer.
         */
        $_buffer = (bool) isSet($_param['buffer']) ? $_param['buffer'] : FALSE;
        if ($_buffer)
            ob_start();


        /**
         * Set the path and filename of the file containing the errors array
         * constants. You can use relative (recommended) or absolute file paths.
         * For security, specify a filename without the '.php' because the
         * class will automatically add '.php' to the end. i.e. If you specify
         * 'errors.php' this class will try to locate a file called
         * 'errors.php.php'. So, just specify 'errors'. The default path is
         * the current directory (where your script is running from), but
         * but recommend to put the errors file off the web directory along
         * with this class.DB_eSession.php file.
         */
        $_errors_path = isSet($_param['errors_path']) ?
                              $_param['errors_path']  : './';


        $_errors_file = isSet($_param['errors_file']) ?
                              $_param['errors_file']  : 'errors.DB_eSession';

        $_filename = $_errors_path . $_errors_file . '.php';

        if (($this->pregMatches('/^[a-z0-9_.]+$/i', $_errors_file)) &&
            (file_exists($_filename))) {

            $_loaded = require_once($_filename);

        } else {

            $this->_errors = "xxxx --> " . $_filename . " <-- xxxx\n";
            $this->_handleErrors(STOP);     // Severe error - exit script
        }

        if ((0 === strcmp($_loaded, 'LOAD_OK')) &&
            (isSet($_ERR))  &&
            (isSet($_WRN))) {

            $this->_ERR_MSGS = $_ERR;
            $this->_WRN_MSGS = $_WRN;
            unset($_ERR, $_WRN);

        } else {

            $this->_errors = '$_ERR $_WRN xxxx --> ' . $_filename .
                              " <-- xxxx\n";
            $this->_handleErrors(STOP);     // Severe error - exit script
        }


        if (!empty($_not_array))
            // Warning: parameter passed to class is not an array
            $this->_setWrnMsg($_not_array);


        /**
         * Whether or not to encrypt/decrypt the WHOLE session data. This will
         * trigger the use of the mcrypt library or sessEncode/sessDecode.
         * This can be set on or off on the fly and it will work accordingly.
         * The default is off since encryption takes extra resources/time.
        */
        $this->_ENCRYPT = (bool) isSet($_param['encrypt']) ?
                                       $_param['encrypt']  : FALSE;

        /**
         * The key used to encrypt/decrypt individual field data or the whole
         * session data. Keep this key a secret (keep off the web directory).
         * Use readable characters and make at least 62 UNIQUE characters long.
         */
        $this->_ENCRYPT_KEY = isSet($_param['encrypt_key']) ?
                                    $_param['encrypt_key']  :
            "z1Mc6KRxAfNwZ0dGjY5qBXhtrPgJO7eCaUmHvQT3yW8nDsI2VkEpiS4blFoLu9";

        /**
         * Determine if libmcrypt is installed and if it's one of the
         * latest versions.
         */
        $this->_MCRYPT        = extension_loaded('mcrypt');
        $this->_MCRYPT_LATEST = FALSE;
        if ($this->_MCRYPT) {

            if (defined('MCRYPT_TRIPLEDES'))      // Only defined in >= 2.4.x
                $this->_MCRYPT_LATEST = TRUE;

            /**
             * The key field used to encrypt/decrypt using the mcrypt library.
             */
            $this->_ENC_KEY_HASHED = md5($this->_ENCRYPT_KEY);

            $this->_ENC_ALGO = isSet($_param['encrypt_cipher']) ?
                                     $_param['encrypt_cipher']  : MCRYPT_GOST;

            $_algo = mcrypt_list_algorithms();
            if (!in_array($this->_ENC_ALGO, $_algo)) {

                // Could not assign the encryption algorithm...
                $this->_setErrMsg('BAD_ALGO', NULL, $this->_ENC_ALGO);
                $this->_handleErrors();
                $this->_ENC_ALGO = NULL;
            }

            $this->_ENC_MODE = isSet($_param['encrypt_mode']) ?
                                     $_param['encrypt_mode']  : MCRYPT_MODE_CFB;

            $_modes = mcrypt_list_modes();
            if (!in_array($this->_ENC_MODE, $_modes)) {

                // Could not assign the encryption mode...
                $this->_setErrMsg('BAD_ENC_MODE', NULL, $this->_ENC_MODE);
                $this->_handleErrors();
                $this->_ENC_MODE = NULL;

            } else
            if (($this->_ENC_MODE != MCRYPT_MODE_ECB) &&
                ($this->_ENC_MODE != MCRYPT_MODE_CBC) &&
                ($this->_ENC_MODE != MCRYPT_MODE_CFB) &&
                ($this->_ENC_MODE != MCRYPT_MODE_OFB)) {

                // Could not assign the encryption mode...Use class supported
                $this->_setErrMsg('BAD_MODE_SUPP', NULL, $this->_ENC_MODE,
                                  'ECB, CBC, CFB, OFB.');
                $this->_handleErrors();
                $this->_ENC_MODE = NULL;
            }

        } else {

            $this->_ENC_KEY_HASHED = NULL;
            $this->_ENC_ALGO       = NULL;
            $this->_ENC_MODE       = NULL;
        }


        /**
         * As of PHP 4.2.0, there is no need to seed the random number
         * generator, however, we'll do it here for portability. This will be
         * needed for use with the encryption/decryption mcrypt routines and
         * generating of a new session ID.
         */
        mt_srand((double)microtime()*1000000);
        srand((double)microtime()*1000000);


        /**
         * See if MD5 hashing keys have been passed, otherwise set defaults.
         */
        $this->_KEY_PREFIX = isSet($_param['key_prefix']) ?
            $_param['key_prefix'] : 'O9R^3mp#i|34';

        $this->_KEY_SUFFIX = isSet($_param['key_suffix']) ?
            $_param['key_suffix'] : '+t97!u0K-2L5';

        /**
         * A password used to pass to the delete all session/lock functions as a
         * way to confirm the intent of modifying all rows in the sessions
         * table.
         */
        $this->_CONF_PSWD   = isSet($_param['confirm_pswd']) ?
            $_param['confirm_pswd'] : '!*CONFIRMED*!';


        /**
         * Database related variables with assigned default values when not set.
         * Assign these necessary fields to allow connection to the database.
         * Remember to give 'sess_user' access privileges to 'db_esessions'.
         * Make sure the password is correct (sess1234 is the default).
         */
        $this->_db['db_host']       =
            isSet($_param['db_host']) ? $_param['db_host'] : 'localhost';

        $this->_db['db_user']       =
            isSet($_param['db_user']) ? $_param['db_user'] : 'sess_user';

        $this->_db['db_pswd']       =
            isSet($_param['db_pswd']) ? $_param['db_pswd'] : 'sess1234';

        $this->_db['db_name']       =
            isSet($_param['db_name']) ? $_param['db_name'] : 'db_esessions';

        $this->_db['db_persistent'] =
            isSet($_param['db_persistent']) ?
                (bool) $_param['db_persistent'] : FALSE;

        $this->_db['db_resource']   =
            isSet($_param['db_resource']) ? $_param['db_resource'] : NULL;

        /**
         * Optionally supply a database resource link. This class will NOT
         * attempt to connect to MySQL and use the link instead.
         */
        if (is_resource($this->_db['db_resource']))
            $this->_dbh = $this->_db['db_resource'];
        else
            $this->_dbh = NULL;


        /**
         * Table related variables with assigned default values when not set.
         * Assign these necessary fields to allow connection to the 'sessions'
         * table. Specify what each column name is defined as in the table.
         */
        $this->_db['tb_name']       =
            isSet($_param['tb_name'])    ? $_param['tb_name']   : 'eSessions';

        $this->_db['tb_id_col']     =
            isSet($_param['tb_id_col'])  ? $_param['tb_id_col'] : 'sess_id';

        $this->_db['tb_sl_col']     =
            isSet($_param['tb_sl_col'])  ? $_param['tb_sl_col'] :
                'sess_sec_level';

        $this->_db['tb_cr_col']     =
            isSet($_param['tb_cr_col'])  ? $_param['tb_cr_col'] :
                'sess_created';

        $this->_db['tb_ex_col']     =
            isSet($_param['tb_ex_col'])  ? $_param['tb_ex_col'] : 'sess_expiry';

        $this->_db['tb_to_col']     =
            isSet($_param['tb_to_col'])  ? $_param['tb_to_col'] :
                'sess_timeout';

        $this->_db['tb_lk_col']     =
            isSet($_param['tb_lk_col'])  ? $_param['tb_lk_col'] : 'sess_locked';

        $this->_db['tb_vl_col']     =
            isSet($_param['tb_vl_col'])  ? $_param['tb_vl_col'] : 'sess_value';

        $this->_db['tb_iv_col']     =
            isSet($_param['tb_iv_col'])  ? $_param['tb_iv_col'] : 'sess_enc_iv';

        $this->_db['tb_si_col']     =
            isSet($_param['tb_si_col'])  ? $_param['tb_si_col'] : 'sess_sec_id';

        $this->_db['tb_tr_col']     =
            isSet($_param['tb_tr_col'])  ? $_param['tb_tr_col'] : 'sess_trace';


        /**
         * Set $_param['sess_id_len'] to be the length of the session ID.
         * Default of $this->_MAX_SESS_ID_LEN will be used.
         */
        $this->_sess_ID_len         = (int)
            isSet($_param['sess_id_len']) ? intval($_param['sess_id_len']) :
                                            $this->_MAX_SESS_ID_LEN;

        if ($this->_sess_ID_len < $this->_MIN_SESS_ID_LEN)
            $this->_sess_ID_len = $this->_MIN_SESS_ID_LEN;
        else
            if ($this->_sess_ID_len > $this->_MAX_SESS_ID_LEN)
                $this->_sess_ID_len = $this->_MAX_SESS_ID_LEN;

        /**
         * Set $_param['new_sid'] => TRUE to create a new session ID.
         * Default is FALSE. Takes effect before a session_start().
         * This can be set TRUE without setting $_param['sess_id'], in
         * which case, a session ID will be automatically generated.
         */
        $_new_sess_ID               = (bool)
            isSet($_param['new_sid']) ? $_param['new_sid'] : FALSE;

        /**
         * If desired, set $_param['sess_id'] to a valid custom session ID.
         * Works in conjunction with $_param['new_sid'] (must be set to TRUE).
         */
        $_sess_ID                   =
            isSet($_param['sess_id']) ? $_param['sess_id'] : NULL;

        if (!empty($_sess_ID)) {
            if (strlen($_sess_ID) != $this->_sess_ID_len) {

                // Warning: Custom session ID passed is not the right length
                $this->_setWrnMsg('SESS_LENGTH', NULL, $this->_sess_ID_len,
                                  $_param['sess_id']);

                $_sess_ID = NULL;

            } else
                if (!$this->pregMatches('/^[a-zA-Z0-9]+/', $_sess_ID)) {

                    // Warning: Custom session ID passed is invalid.
                    $this->_setWrnMsg('SESS_INVALID', NULL, $_param['sess_id']);

                    $_sess_ID = NULL;
                }
        }


        /**
         * Set $_param['ie_fix'] => TRUE (default) to send a header output to
         * fix the IE bug. See further comments below.
         */
        $_IE_fix                    = (bool)
            isSet($_param['ie_fix'])  ? $_param['ie_fix']  : TRUE;


        /**
         * When set to TRUE, locked session rows will be deleted right
         * away, regardless of their current expiry or timeout settings when
         * the Garbage Collection cleanup/delete function is invoked.
         */
        $this->_GC_DEL_LOCKED = (bool)
            isSet($_param['gc_del_locked']) ? $_param['gc_del_locked'] : FALSE;


        /**
         * Session Runtime Configurations. See:
         * http://us2.php.net/manual/en/ref.session.php
         *
         * Not all can be set or take effect outside of the php.ini
         * configuration file. Some options can be set at runtime without
         * an error produced, but have no effect. i.e. session.auto_start
         *
         * All session options are used here in case there is future support
         * to make option take effect at runtime. i.e. session.use_trans_sid
         *
         * When $_param['stop_on_warn'] is FALSE, check for warning messages
         * using warningsExist().
         */
        $this->_sess_opt['save_path'] =
            isSet($_param['save_path']) ? $_param['save_path'] : 'db_esessions';

        if (isSet($_param['name'])) {
            // Check to make sure name is only alphanumeric
            if (!$this->pregMatches('/^[a-zA-Z0-9]+/', $_param['name'])) {

                // Warning: Session configuration option session.name alpha
                $this->_setWrnMsg('NAME_INVALID', NULL, $_param['name']);

                $this->_sess_opt['name'] = 'eSESSION';

            } else {
                $this->_sess_opt['name'] = $_param['name'];
            }

        } else {

            $this->_sess_opt['name'] = 'eSESSION';
        }

        $this->_sess_opt['save_handler'] =
            isSet($_param['save_handler']) ? $_param['save_handler'] : 'user';

        if (isSet($_param['auto_start']))
            $this->_sess_opt['auto_start'] = (bool) $_param['auto_start'];

        if (isSet($_param['gc_probability']))
            $this->_sess_opt['gc_probability'] = (int)
                (0 == intval($_param['gc_probability'])) ?
                    10 : intval($_param['gc_probability']);

        if (isSet($_param['gc_divisor']))
            $this->_sess_opt['gc_divisor'] = (int)
                (0 == intval($_param['gc_divisor'])) ?
                    100 : intval($_param['gc_divisor']);

        /**
         * There maybe a bug with sessions lifetime under Windows and FAT32 in
         * PHP version 4.1.0/1/2. See: http://bugs.php.net/bug.php?id=14798
         */
        if (isSet($_param['gc_maxlifetime']))
            $this->_sess_opt['gc_maxlifetime'] =
               intval($_param['gc_maxlifetime']);

        if (isSet($_param['serialize_handler']))
            $this->_sess_opt['serialize_handler'] =
                $_param['serialize_handler'];

        if (isSet($_param['cookie_lifetime']))
            $this->_sess_opt['cookie_lifetime'] =
               intval($_param['cookie_lifetime']);

        if (isSet($_param['cookie_path']))
            $this->_sess_opt['cookie_path']   = $_param['cookie_path'];

        if (isSet($_param['cookie_domain']))
            $this->_sess_opt['cookie_domain'] = $_param['cookie_domain'];

        if (isSet($_param['cookie_secure'])) {
            $this->_sess_opt['cookie_secure'] = $_param['cookie_secure'];

            if ((0 === strcmp($this->_sess_opt['cookie_secure'], '1')) &&
                (!$this->secureConnection())) {

                // Warning: You are setting session.cookie_secure - not secure
                $this->_setWrnMsg('NOT_SECURE');

            }

        }

        if (isSet($_param['use_cookies']))
            $this->_sess_opt['use_cookies'] = (bool) $_param['use_cookies'];

        if ((isSet($_param['use_only_cookies'])) &&
            (version_compare(PHP_VERSION, '4.3.0', '>=')))
            $this->_sess_opt['use_only_cookies'] =
               (bool) $_param['use_only_cookies'];

        if (isSet($_param['referer_check']))
            $this->_sess_opt['referer_check'] = $_param['referer_check'];

        if (isSet($_param['entropy_file']))
            $this->_sess_opt['entropy_file'] = $_param['entropy_file'];

        if (isSet($_param['entropy_length']))
            $this->_sess_opt['entropy_length'] =
               intval($_param['entropy_length']);

        if (isSet($_param['cache_limiter']))
            $this->_sess_opt['cache_limiter'] = $_param['cache_limiter'];

        if (isSet($_param['cache_expire']))     // For PHP version >= 4.2.0
            $this->_sess_opt['cache_expire'] = intval($_param['cache_expire']);

        if (isSet($_param['bug_compat_42']))
            $this->_sess_opt['bug_compat_42'] = (bool) $_param['bug_compat_42'];

        if (isSet($_param['bug_compat_warn']))
            $this->_sess_opt['bug_compat_warn'] = (bool)
                $_param['bug_compat_warn'];

        if (version_compare(PHP_VERSION, '5.0.0', '>=')) {

           // session.use_trans_sid can be changed in a script from v5.0.0 on
           if (isSet($_param['use_trans_sid']))
               $this->_sess_opt['use_trans_sid'] = $_param['use_trans_sid'];

           if (isSet($_param['hash_function']))
               $this->_sess_opt['hash_function'] = $_param['hash_function'];

           if (isSet($_param['hash_bits_per_character']))
               $this->_sess_opt['hash_bits_per_character'] =
                   $_param['hash_bits_per_character'];
        }


        /**
         * Set session configuration options. Values will remain during the
         * script's execution, and will be restored at the script's ending.
         */
        foreach ($this->_sess_opt as $_key => $_value) {

            if (FALSE === $this->_setSessOption($_key, $_value))
                // Warning: Session configuration option ... not assigned
                $this->_setWrnMsg('SESS_OPTION', NULL, $_key, $_value);

        }

        /**
         * Support for url_rewriter.tags option since it relates to sessions.
         * Example: Like you might want to add the iframe=src to it, as in:
         * a=href,area=href,frame=src,iframe=src,form=,fieldset=,input=src
         */
        if (isSet($_param['tags'])) {
            if (FALSE === $this->_setSessOption('url_rewriter.tags',
                                                $_param['tags'],
                                                FALSE))
                // Warning: Configuration option [url_rewriter.tags] not assign
                $this->_setWrnMsg('URL_TAGS', NULL, $_param['tags']);

        }


        /**
         * Security Level: A numerical method to represent access authority for
         * current session/web page. The lower the number means the higher the
         * security clearance. In other words, security level 5 can only access
         * all level 5 or higher session/web pages, and nothing lower than 5.
         * Range 0-255. The default is 128. For administration or sensitive pages
         * use 0 (zero) or 1 (one) as a value. A security level can't be changed
         * after a session has been created. So, the first time the session
         * is created with a set security level, it dictates the access
         * authority for the rest of that active session.
         */
        $this->_SEC_LEVEL = isSet($_param['security_level']) ?
                                intval($_param['security_level']) : 128;


        /**
         * Get current setting of sessions life duration in seconds.
         * This is the number of seconds that is allowed to pass since
         * the last time the session data was accessed.
         * Otherwise, default it to 1440 seconds (24 minutes).
         */
        $this->_SESS_LIFE = intval(ini_get('session.gc_maxlifetime'));
        $this->_SESS_LIFE = (int) ($this->_SESS_LIFE < 1) ?
                                   1440 : $this->_SESS_LIFE;

        /**
         * Calculates maximum life of session in seconds. It's three times
         * the length of gc_maxlifetime (for the default). For example: if
         * gc_maxlifetime is 1440 seconds (24 minutes), then session
         * timeout maximum is set to 4320 seconds (72 minutes). The timeout
         * value can't be less than the gc_maxlifetime value.
         */
        if (isSet($_param['timeout'])) {
            $this->_SESS_TIMEOUT = (int)
                (intval($_param['timeout']) < $this->_SESS_LIFE) ?
                    $this->_SESS_LIFE * 3 : intval($_param['timeout']);
        } else {
            $this->_SESS_TIMEOUT = (int) $this->_SESS_LIFE * 3;
        }


        /**
         * Must not send any HTML output before session_start() is invoked.
         * Set a warning message if HTML headers have been sent to the browser.
         * Exception: ob_start() for buffering.
         */
        if (!$_buffer) {
            if (version_compare(PHP_VERSION, '4.3.0', '>=')) {
                $_filename = '';
                $_linenbr  = (int) 0;
                if (headers_sent($_filename, $_linenbr)) {
                    // Warning: HTTP headers already sent - with detail
                    $this->_setWrnMsg('HEADER_SENT_1', NULL, $_filename,
                                      $_linenbr);
                }

            } else
            if (headers_sent()) {
                // Warning: HTTP headers have already been sent - no detail
                $this->_setWrnMsg('HEADER_SENT_2');
            }
        }


        /**
         * Assign session storage tasks to methods in this class.
         */
        if (!session_set_save_handler(array(&$this, '_sessDBOpen'),
                                      array(&$this, '_sessDBClose'),
                                      array(&$this, '_sessDBRead'),
                                      array(&$this, '_sessDBWrite'),
                                      array(&$this, '_sessDBDestroy'),
                                      array(&$this, '_sessDBGC')
                                     )) {

            // execution of session_set_save_handler() failed
            $this->_setErrMsg('HANDLER_FAIL');
            $this->_handleErrors(STOP);     // Severe error - exit script

        }

        $this->_sess_name = session_name();


        /**
         * Set whether the magic quotes GPC that effects slashing quotes of
         * GET/POST/COOKIE data is set.
         */
        $this->_MAGIC_QUOTES_GPC = (bool) get_magic_quotes_gpc();


        /**
         * Set whether the magic quotes runtime that effects slashing quotes of
         * external data sources is set.
         */
        $this->_MAGIC_QUOTES_RUNTIME = (bool) get_magic_quotes_runtime();


        $this->_ARG_SEP = ('' == ini_get('arg_separator.output')) ? '&' :
                                 ini_get('arg_separator.output');


        /**
         * Set TRUE to force addslashes() to occur on session data regardless
         * of the magic quotes runtime option setting. Default is on (TRUE).
         * If you find that data has slashes incorrectly, then turn this off.
         */
        $this->_SLASH_ANYWAY = (bool) isSet($_param['slash_anyway']) ?
                                            $_param['slash_anyway']  : TRUE;

        /**
         * Set TRUE to force stripslashes() to occur on encrypted session data
         * regardless of the magic quotes runtime option setting. The default
         * is on (TRUE). If you find that data is saved incorrectly, then
         * turn this off.
         */
        $this->_STRIP_ANYWAY = (bool) isSet($_param['strip_anyway']) ?
                                            $_param['strip_anyway']  : TRUE;


        /**
         * Try and save the current session ID if one is defined already.
         */
        if (isSet($_COOKIE[$this->_sess_name]))
            $_sess_id_set = $_COOKIE[$this->_sess_name];
        else
        if (isSet($GLOBALS[$this->_sess_name]))
            $_sess_id_set = $GLOBALS[$this->_sess_name];
        else
            $_sess_id_set = NULL;


        /**
         * Create a new session ID when requested, or when the session ID length
         * is less than the standard maximum if a session hasn't been started
         * or created already ($_COOKIE or $GLOBALS[$this->_sess_name]).
         */
        if (($_new_sess_ID) ||
            (($this->_sess_ID_len < $this->_MAX_SESS_ID_LEN) &&
             (!isSet($_COOKIE[$this->_sess_name])) &&
             (!isSet($GLOBALS[$this->_sess_name])))) {
            $this->_setNewSessID($_sess_ID);
        }


        /**
         * When warning flag is set and there's warning messages, stop
         * execution here. No point in proceeding.
         */
        $this->_handleErrors();


        /**
         * By default this class will do a session_start(), however, you may
         * want to turn it off when using the maintenance type of functions.
         */
        $_do_sess_start = (bool) isSet($_param['session_start']) ?
                                       $_param['session_start']  : TRUE;

        /**
         * When session start is requested and $_SESSION doesn't exist, it
         * means that the auto start option is not on, and no session_start()
         * has been invoked yet. So, start a session. This is safer than
         * checking the 'session.auto_start' configuration setting with
         * ini_get(). Otherwise, just make a manual connection to the DB for
         * now (to make the maintenance type of member functions available for
         * use). You would then have to invoke the session_start() from within
        * your script (if desired). If the session is started in your script,
         * then another call to _sessDBOpen will be invoked but it will be
         * handled alright.
         */
        if (($_do_sess_start) &&
            (!isSet($_SESSION)))
            session_start();
        else
        if (!$_do_sess_start)
            $this->_sessDBOpen($this->_sess_opt['save_path'], $this->_sess_name);


        /**
         * If there was a previous session ID set and we now have a new one,
         * then delete the old session row right away without waiting for it to
         * expire first (for security reasons).
         */
        if (($_do_sess_start) &&
            (!empty($_sess_id_set))) {
            if (0 !== strcmp($_sess_id_set, session_id()))
                $this->deleteSession($_sess_id_set);
        }


        /**
         * There is a form bug in IE v6 while using PHP sessions which causes
         * the loss of filled-in information when returning to the form, after
         * already leaving the form page (by any means). A work around is to use
         * the HTTP 1.1 header "Cache-Control: private"
         */
        if ($_IE_fix)
            $this->sendCacheHeader('private');

    }   // End of DB_eSession Constructor



    /**
     * _formatFont - Formats the HTML font color and size attributes to the
     * text that's passed to it.
     *
     * @param  string $_text Text or the data to be enclosed in the font attr.
     * @param  string $_color The font color to use (any valid HTML syntax).
     * @param  string $_size The font size to use (any valid HTML syntax).
     * @return string Returns the text with the font and size attributes added.
     * @access private
     */
    function _formatFont($_text, $_color = 'BLACK', $_size = '+0')
    {
        if (empty($_color))
            $_color = 'BLACK';

        if (empty($_size))
            $_size  = '+0';

        return '<FONT COLOR="' . $_color . '"'  .
                     ' SIZE="' . $_size  . '">' .
                        $_text . '</FONT>';
    }


    /**
     * _setErrMsg - Sets an error message. Fills-in any passed values in order
     * to produce a formatted error message.
     *
     * @param  string $_errMsgKey Name of key to match against array of errors.
     * @param  string $_SQL The value of the last executed SQL command (if any).
     * @param  mixed  Pass one to many arguments to use as fill-in values for
     *                the error messages.
     * @return bool   Returns TRUE when error message set, or FALSE on failure.
     * @access private
     */
    function _setErrMsg ($_errMsgKey = '', $_SQL = NULL)
    {

        $_lang = $this->_CURRENT_LANG;

        if (!isSet($this->_ERR_MSGS[$_errMsgKey][$_lang])) {

            if (isSet($this->_ERR_MSGS[$_errMsgKey][$this->_DEFAULT_LANG])) {
                // Error message not found in current lang; switching to def.
                $_lang = $this->_DEFAULT_LANG;
            } else {
                // Could not find the supplied key of error message
                $this->_errors .= '$_ERR[\'' . $_errMsgKey . "']\n";
                return FALSE;
            }
        }

        if (@func_num_args() > 2) {     // Do we have extra argument values?

            $_arg = @func_get_args();

            array_shift($_arg);         // Remove $_errMsgKey value passed
            array_shift($_arg);         // Remove $_SQL value passed

            $_cnt = count($_arg);

            /**
             * Create a pattern for the number of arguments passed
             */
            $_patterns = str_repeat('/%s/i,', $_cnt);
            $_patterns = explode(',', $_patterns);
            array_pop($_patterns);      // Remove extra entry created by explode

            /**
             * When no detail requested, replace argument values with [xxx]
             */
            for ($i = 0; $i < $_cnt; $i++) {
                if ($this->_DETAIL_ERR_MSGS)
                    // Slash $ signs that's in the data for displaying correctly
                    $_arg[$i] = str_replace('$', '\$', $_arg[$i]);
                else
                    $_arg[$i] = '[xxx]';

            }

            /**
             * Replace the '%s' place holder with argument values passed
             * sprintf() doesn't allow array arguments.
             */
            $_err = @preg_replace($_patterns,
                                  $_arg,
                                  $this->_ERR_MSGS[$_errMsgKey][$_lang],
                                  1
                                 );

        } else {    // No extra arguments were passed

            $_err = $this->_ERR_MSGS[$_errMsgKey][$_lang];
        }

        if (!empty($_SQL)) {

            switch ($this->_DETAIL_ERR_MSGS) {

                case TRUE:

                    $_err .= "SQL: $_SQL\nErr # " .
                             @mysql_errno($this->_dbh) . ': '  .
                             @mysql_error($this->_dbh) . "\n";

                    break;

                default:

                    $_err .= "SQL Err # " .
                             @mysql_errno($this->_dbh) . ': '  .
                             @mysql_error($this->_dbh) . "\n";
            }

        }

        $this->_errors .= $_err;

        return TRUE;
    }


    /**
     * _setWrnMsg - Sets a warning message. Fills-in any passed values in order
     * to produce a formatted warning message.
     *
     * @param  string $_wrnMsgKey Name of key to match against array of warnings
     * @param  string $_SQL The value of the last executed SQL command (if any).
     * @param  mixed  Pass one to many arguments to use as fill-in values for
     *                the warning messages.
     * @return bool   Returns TRUE when warning message set, or FALSE on failure
     * @access private
     */
    function _setWrnMsg ($_wrnMsgKey = '', $_SQL = NULL)
    {

        $_lang = $this->_CURRENT_LANG;

        if (!isSet($this->_WRN_MSGS[$_wrnMsgKey][$_lang])) {

            if (isSet($this->_WRN_MSGS[$_wrnMsgKey][$this->_DEFAULT_LANG])) {
                // Warning message not found in current lang; switching to def.
                $_lang = $this->_DEFAULT_LANG;
            } else {
                // Could not find the supplied key of warning message
                $this->_warnings .= '$_WRN[\'' . $_wrnMsgKey . "']\n";
                return FALSE;
            }
        }

        if (@func_num_args() > 2) {     // Do we have extra argument values?

            $_arg = @func_get_args();

            array_shift($_arg);         // Remove $_wrnMsgKey value passed
            array_shift($_arg);         // Remove $_SQL value passed

            $_cnt = count($_arg);

            /**
             * Create a pattern for the number of arguments passed
             */
            $_patterns = str_repeat('/%s/i,', $_cnt);
            $_patterns = explode(',', $_patterns);
            array_pop($_patterns);      // Remove extra entry created by explode

            /**
             * When no detail requested, replace argument values with [xxx]
             */
            for ($i = 0; $i < $_cnt; $i++) {
                if ($this->_DETAIL_ERR_MSGS)
                    // Slash $ signs that's in the data for displaying correctly
                    $_arg[$i] = str_replace('$', '\$', $_arg[$i]);
                else
                    $_arg[$i] = '[xxx]';

            }

            /**
             * Replace the '%s' place holder with argument values passed
             * sprintf() doesn't allow array arguments.
             */
            $_wrn = @preg_replace($_patterns,
                                  $_arg,
                                  $this->_WRN_MSGS[$_wrnMsgKey][$_lang],
                                  1
                                 );

        } else {    // No extra arguments were passed

            $_wrn = $this->_WRN_MSGS[$_wrnMsgKey][$_lang];
        }

        if (!empty($_SQL)) {

            switch ($this->_DETAIL_ERR_MSGS) {

                case TRUE:

                    $_wrn .= "SQL: $_SQL\nErr # " .
                             @mysql_errno($this->_dbh) . ': '  .
                             @mysql_error($this->_dbh) . "\n";

                    break;

                default:

                    $_wrn .= "SQL Err # " .
                             @mysql_errno($this->_dbh) . ': '  .
                             @mysql_error($this->_dbh) . "\n";
            }

        }

        $this->_warnings .= $_wrn;

        return TRUE;
    }


    /**
     * _handleErrors - Detects if errors have occurred and ends the script when
     * the flag is set to stop. Errors are always displayed before warnings.
     *
     * @param  bool   $_stop Flags whether to stop script anyway (on severe
     *                errors.
     * @return bool   Always returns TRUE.
     * @access private
     */
    function _handleErrors($_stop = FALSE)
    {

        if (($this->warningsExist()) &&
            ($this->_stop_on_warn))  {

             if ($this->errorsExist())
                 echo $this->getErrors($this->_ERR_COLOR, $this->_ERR_SIZE);

             echo $this->getWarnings($this->_WRN_COLOR, $this->_WRN_SIZE);

            exit;
        }

        if (($this->errorsExist()) &&
            ($this->_stop_on_error)) {

            echo $this->getErrors($this->_ERR_COLOR, $this->_ERR_SIZE);

            if ($this->warningsExist())
                echo $this->getWarnings($this->_WRN_COLOR, $this->_WRN_SIZE);

            exit;
        }

        if (!is_bool($_stop))
            $_stop = FALSE;

        if ($_stop) {

            if ($this->errorsExist())
                echo $this->getErrors($this->_ERR_COLOR, $this->_ERR_SIZE);

            if ($this->warningsExist())
                echo $this->getWarnings($this->_WRN_COLOR, $this->_WRN_SIZE);

            exit;
        }

        return TRUE;
    }


    /**
     * _setSessOption - Sets the value of the given session configuration option
     *
     * @param  string $_config_option Session related configuration option
     * @param  mixed  $_value The value to assign the configuration option
     * @param  bool   $_check_sess Flags whether to verify 'session.' exists
     * @return mixed  Returns the old value on success, FALSE on failure.
     * @access private
     */
    function _setSessOption($_config_option, $_value, $_check_sess = TRUE)
    {

        $_config_option = trim($_config_option);

        if (empty($_config_option)) {

            return FALSE;

        } else {

            // When TRUE, check to see if 'session.' is included
            if ($_check_sess) {
                // Add 'session.' if not included in $_config_option
                if (0 !== strpos(strtolower($_config_option), 'session.'))
                    $_config_option = 'session.' . $_config_option;

            }

            return ini_set($_config_option, $_value);

        }
    }


    /**
     * _genString - Generates random characters from 1 to 32 in length.
     * 32 characters is the default when length not specified.
     *
     * @param  int    $_length The number of characters to generate.
     * @return string Returns a string of the requested number of characters.
     * @access private
     */
    function _genString($_length = 0)
    {

        $_length = intval($_length);

        if (($_length < 1) ||
            ($_length > $this->_MAX_SESS_ID_LEN))
             $_length = $this->_MAX_SESS_ID_LEN;

        /**
         * Random number seeding already performed in constructor.
         */
        $_string = md5(uniqid(mt_rand(), TRUE));

        return substr($_string, 0, $_length);

    }


    /**
     * _setNewSessID - Creates and sets a new session ID.
     * This is called before session_start() and before any output to the
     * browser.
     *
     *   Note: It's possible if you have PHP version 4.3.2 or higher and are
     *         using the default maximum session length (32), to call
     *         this member function, without an argument, & no output sent
     *         to the browser, after a session_start() has been executed.
     *         That will invoke session_regenerate_id(), which seems to work
     *         correctly (member could have been made public for that reason).
     *         If session_start() has been executed already, then doing
     *         session_id('somevalue') will NOT change the session ID properly.
     *         It's less problematic to keep as a private method (and call
     *         before a session_start()).
     *
     * @param  string $_sess_id An optional session ID to use (of _sess_ID_len)
     * @return string Returns the new session ID.
     * @access private
     */
    function _setNewSessID($_sess_id = NULL)
    {

        global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS;

        $_continue = TRUE;

        /**
         * If supplied with a session ID, validate it and use it when it's good.
         */
        if (strlen($_sess_id) == $this->_sess_ID_len) {
            if (!$this->pregMatches('/^[a-zA-Z0-9]+/', $_sess_id)) {
                // Warning: Custom session ID passed is invalid.
                $this->_setWrnMsg('SESS_INVALID', NULL, $_sess_id);

                $this->_handleErrors();

                // Ignoring value and assigning a new session ID.
                $this->_setWrnMsg('NEW_SESS_ID');

            } else {

                session_id($_sess_id);

                $_continue = FALSE;

            }

        }


        /**
         * Use session_regenerate_id() when the session ID length desired is the
         * same as the maximum allowed, because it generates the maximum length.
         * It is only available in PHP version 4.3.2 or higher. As of PHP 4.3.3,
         * if session cookies are enabled, use of session_regenerate_id() is
         * supposed to submit a new session cookie with the new session id.
         */
        if (($_continue) &&
            ($this->_sess_ID_len == $this->_MAX_SESS_ID_LEN) &&
            (version_compare(PHP_VERSION, '4.3.2', '>='))) {
            if (session_regenerate_id()) {

                $_sess_id  = session_id();

                $_continue = FALSE;

            }

        }


        if ($_continue) {

            $_sess_id = $this->_genString($this->_sess_ID_len);

            session_id($_sess_id);
        }

        // To be safe set...
        if (isSet($_REQUEST[$this->_sess_name]))
            $_REQUEST[$this->_sess_name] = $_sess_id;

        if (isSet($_GET[$this->_sess_name]))
            $_GET[$this->_sess_name] = $_sess_id;

        if (isSet($HTTP_GET_VARS[$this->_sess_name]))
            $HTTP_GET_VARS[$this->_sess_name] = $_sess_id;

        if (isSet($_POST[$this->_sess_name]))
            $_POST[$this->_sess_name] = $_sess_id;

        if (isSet($HTTP_POST_VARS[$this->_sess_name]))
            $HTTP_POST_VARS[$this->_sess_name] = $_sess_id;

        if (isSet($_COOKIE[$this->_sess_name]))
            $_COOKIE[$this->_sess_name]  = $_sess_id;

        // May not actually change until next refresh
        if (isSet($HTTP_COOKIE_VARS[$this->_sess_name]))
            $HTTP_COOKIE_VARS[$this->_sess_name] = $_sess_id;

        if (isSet($GLOBALS[$this->_sess_name]))
            $GLOBALS[$this->_sess_name] = $_sess_id;

        return $_sess_id;
    }


    /**
     * _getSecID - Creates an MD5 of a users trace information. Used to verify
     * session belongs to same user. Not full-proof but adequate.
     * Note: Not using HTTP_ACCEPT since results are inconsistent in IE6.
     *
     * @return string  An MD5 hash of secret keys plus server collected data.
     * @access private
     */
    function _getSecID()
    {

        $_type_used = NULL;
        $_IP = $this->getIPAddr($_type_used);

        $_agent    = isSet($_SERVER['HTTP_USER_AGENT']) ?
                           $_SERVER['HTTP_USER_AGENT']  : 'NO USER AGENT';

/* Rev 1.0.2: Found IE 6 to not return consistent results (under HTTPS)
        $_encoding = isSet($_SERVER['HTTP_ACCEPT_ENCODING']) ?
                           $_SERVER['HTTP_ACCEPT_ENCODING']  : 'NO ENCODING';
*/
        return md5($this->_KEY_PREFIX  .
                   $_IP                .
                   $_type_used         .
                   $_agent             .
//***              $_encoding          .    Rev 1.0.2: Found as unreliable
                   $this->_KEY_SUFFIX