cb.session.php
上传用户:stephen_wu
上传日期:2008-07-05
资源大小:1757k
文件大小:17k
- <?php
- /**
- * @version $Id: cb.session.php 444 2008-04-24 18:25:39Z beat $
- * @package Community Builder
- * @subpackage cb.session.php
- * @author Beat
- * @copyright (C) 2008 Beat, www.joomlapolis.com
- * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU/GPL version 2
- */
- // no direct access
- if ( ! ( defined( '_VALID_CB' ) || defined( '_JEXEC' ) || defined( '_VALID_MOS' ) ) ) { die( 'Direct Access to this location is not allowed.' ); }
- /**
- * CB 1.x SESSIONS functions:
- */
- /**
- * Checks that all globals are safe to known PHP and Zend bugs:
- */
- function cbCheckSafeGlobals() {
- static $banned = array( '_files', '_env', '_get', '_post', '_cookie', '_server', '_session', 'globals' );
- $check = array( &$_FILES, &$_ENV, &$_GET, &$_POST, &$_COOKIE, &$_SERVER );
- for ( $i = 0, $n = count( $check ) ; $i < $n ; $i++ ) {
- foreach ( $check[$i] as $k => $v ) {
- // check for PHP globals injection bug and for PHP Zend_Hash_Del_Key_Or_Index bug:
- if ( in_array( strtolower( $k ), $banned ) || is_numeric( $k ) ) {
- die( sprintf( 'Illegal variable %s.', addslashes( htmlspecialchars( $k ) ) ) );
- }
- }
- }
- }
- /**
- * Unregister super-globals if register_globals is set
- */
- function cbUnregisterGlobals() {
- if ( ini_get( 'register_globals' ) ) {
- $check = array( &$_SERVER, &$_ENV, &$_FILES, &$_COOKIE, &$_POST, &$_GET );
- if ( isset( $_SESSION ) ) {
- array_unshift ( $check, $_SESSION );
- }
- for ( $i = 0, $n = count( $check ) ; $i < $n ; $i++ ) {
- foreach ($check[$i] as $key => $value) {
- if ( $key != 'GLOBALS' ) {
- unset( $GLOBALS[$key] );
- }
- }
- }
- }
- }
- /**
- * CLASS implements a minimal database connection working with CB database when present
- * and with MySql directly if not.
- */
- class CBSessionStorage {
- var $_db;
- var $_table_prefix;
- var $_resource;
- var $_cursor;
- var $_sql;
- /**
- * Constructor
- *
- * @return CBSessionStorage
- */
- function CBSessionStorage( ) {
- }
- /**
- * Connects to database layer or to mysql database
- *
- * @return CBSessionStorage or $_CB_database
- */
- function & connect() {
- if ( ! $this->_db ) {
- global $_CB_database;
- if ( $_CB_database ) {
- $this->_db =& $_CB_database;
- } else {
- $config = file_get_contents( dirname( __FILE__ ) . '/../../../../../configuration.php' );
- $db_host = $this->_parseConfig( $config, 'host' );
- $db_user = $this->_parseConfig( $config, 'user' );
- $db_password = $this->_parseConfig( $config, 'password' );
- $db_db = $this->_parseConfig( $config, 'db' );
- $this->_db = new CBSessionStorage();
- $this->_db->_resource = mysql_connect( $db_host, $db_user, $db_password ) or die( 'Session connect error!' );
- mysql_select_db( $db_db, $this->_db->_resource ) or die( 'Session database error!' );
- $this->_db->_table_prefix = $this->_parseConfig( $config, 'dbprefix' );
- }
- }
- return $this->_db;
- }
- /**
- * Parses a mambo/joomla/compatibles configuration file content
- * @access private
- *
- * @param string $config Content of config file
- * @param string $varName Name of variable to fetch
- * @return string Content of variable or NULL
- */
- function _parseConfig( $config, $varName ) {
- preg_match( '/$(?:mosConfig_)?' . $varName . 's*=s*'([^']*)'/', $config, $matches );
- if ( isset($matches[1]) ) {
- return $matches[1];
- } else {
- return null;
- }
- }
- /**
- * Sets the SQL query string for later execution.
- *
- * This function replaces a string identifier $prefix with the
- * string held is the _table_prefix class variable.
- *
- * @param string $sql The SQL query
- * @param int $offset The offset to start selection
- * @param int $limit The number of results to return
- * @param string $prefix The common table prefix search for replacement string
- */
- function setQuery( $sql, $offset = 0, $limit = 0, $prefix='#__' ) {
- if ( $offset || $limit ) {
- $sql .= " LIMIT ";
- if ( $offset ) {
- $sql .= ( (int) $offset ) . ', ';
- }
- $sql .= ( (int) $limit );
- }
- $this->_sql = $this->replacePrefix( $sql, $prefix );
- }
- /**
- * Replace $prefix with $this->_table_prefix (simplified method)
- * @access private
- *
- * @param string $sql SQL query
- * @param string $prefix Common table prefix
- */
- function replacePrefix( $sql, $prefix = '#__' ) {
- return str_replace( $prefix, $this->_table_prefix, $sql );
- }
- /**
- * Execute the query
- *
- * @param string the query (optional, it will use the setQuery one otherwise)
- * @return mixed A database resource if successful, FALSE if not.
- */
- function query( $sql = null ) {
- $this->_cursor = mysql_query( $this->_sql, $this->_resource );
- return $this->_cursor;
- }
- /**
- * Fetch a result row as an associative array
- *
- * @return array
- */
- function loadAssoc( ) {
- if ( ! ( $cur = $this->query() ) ) {
- $result = null;
- } else {
- $result = mysql_fetch_assoc( $cur );
- if ( ! $result ) {
- $result = null;
- }
- mysql_free_result( $cur );
- }
- return $result;
- }
- /**
- * Get a database escaped string
- *
- * @param string $text
- * @return string
- */
- function getEscaped( $text ) {
- return mysql_real_escape_string( $text, $this->_resource );
- }
- /**
- * Get a quoted database escaped string
- *
- * @param string $text
- * @return string
- */
- function Quote( $text ) {
- return ''' . $this->getEscaped( $text ) . ''';
- }
- /**
- * Quote an identifier name (field, table, etc)
- *
- * @param string $s The name
- * @return string The quoted name
- */
- function NameQuote( $s ) {
- return '`' . $s . '`';
- }
- }
- /**
- * This class implements CB independant database-based scalable cookies-only-based secure sessions.
- *
- */
- class CBSession {
- var $_session_id = null;
- var $_session_var = null;
- var $_cookie_name = 'cb_web_session';
- var $_cookie_verify = 'cb_web_session_verify';
- var $_life_time = null;
- var $_sessionRecord = null;
- var $_mode;
- /**
- * Mini-db
- * @var CBSessionStorage
- */
- var $_db = null;
- /**
- * Constructor
- * @access private
- *
- * @param string $mode 'cookie' for most secure way (requires cookies enabled), 'sessionid': set id by session
- * @return CBSession
- */
- function CBSession( $mode = 'cookie' ) {
- $this->_mode = $mode;
- // Read the maxlifetime setting from PHP:
- $this->_life_time = max( get_cfg_var( 'session.gc_maxlifetime' ), 43200 ); // 12 hours minimum
- $dbConnect = new CBSessionStorage();
- $this->_db = $dbConnect->connect();
- }
- /**
- * Gets singleton
- *
- * @param string $mode 'cookie' for most secure way (requires cookies enabled), 'sessionid': set id by session
- * @return CBSession
- */
- function & getInstance( $mode = 'cookie' ) {
- static $session = array();
- if ( ! isset( $session[$mode] ) ) {
- $session[$mode] = new CBSession( $mode );
- }
- return $session[$mode];
- }
- /**
- * session_start() creates a session or resumes the current one based on the current session id
- * that's being passed via a cookie.
- *
- * If you want to use a named session, you must call session_name() before calling session_start().
- *
- * session_start() will register internal output handler for URL rewriting when trans-sid is enabled.
- * If a user uses ob_gzhandler or like with ob_start(), the order of output handler is important for proper output.
- * For example, user must register ob_gzhandler before session start.
- *
- * @param string $mode 'cookie' for most secure way (requires cookies enabled), 'sessionid': set id by session
- * @return bool True: ok, False: already started
- */
- function session_start( $_noNewSession = false ) {
- if ( $this->_session_var !== null ) {
- // session already started:
- return false;
- }
- if ( $this->_mode == 'cookie' ) {
- global $_COOKIE;
- if ( isset( $_COOKIE[$this->_cookie_name] ) ) {
- // session existing in browser:
- $session_id = substr( $_COOKIE[$this->_cookie_name], 0, 32 );
- } else {
- $session_id = null;
- }
- } elseif ( $this->_mode == 'sessionid' ) {
- $session_id = $this->_session_id;
- } else {
- return false;
- }
- if ( $session_id ) {
- $session_data = $this->read( $session_id );
- if ( $session_data ) {
- // session found in database:
- $session_var = unserialize( $session_data );
- if ( ( $session_var !== false ) && ( $this->_validateSession( $session_id, $session_data ) ) ) {
- // valid session has been retrieved:
- $this->_session_id = $session_id;
- $this->_session_var = $session_var;
- return true;
- }
- }
- }
- if ( $_noNewSession ) {
- return false;
- }
- // no valid session has been found: create a new one:
- $this->_session_id = $this->generateRandSessionid( 32 );
- $this->_session_var = array( 'cbsessions.verify' => $this->generateRandSessionid( 32 ) );
- $this->_validateSession(); // set the session
- if ( $this->_mode == 'cookie' ) {
- $this->_sendSessionCookies();
- }
- return true;
- }
- /**
- * Sends out the session cookies
- * @access private
- */
- function _sendSessionCookies() {
- header('P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"'); // needed for IE6 to accept this cookie in higher security setting.
- $sp = session_get_cookie_params();
- if ( isset( $sp['secure'] ) ) {
- if ( isset( $sp['httponly'] ) ) {
- // php >= 5.2.0:
- setcookie( $this->_cookie_name, $this->_session_id, false, $sp['path'], $sp['domain'], $sp['secure'], true );
- } else {
- // php < 5.2.0, but > 4.0.4:
- setcookie( $this->_cookie_name, $this->_session_id, false, $sp['path'], $sp['domain'], $sp['secure'] );
- }
- } else {
- setcookie( $this->_cookie_name, $this->_session_id, false, $sp['path'], $sp['domain'] );
- }
- // setcookie( $this->_cookie_name, $this->_session_id, false, '/' );
- }
- /**
- * Regenerates a new session id, keeping session data
- *
- */
- function session_regenerate( ) {
- if ( ! $this->_session_id ) {
- // tries to load existing session:
- $this->session_start( true );
- }
- if ( $this->_session_id ) {
- $this->destroy( $this->_session_id );
- }
- $this->_session_id = $this->generateRandSessionid( 32 );
- $this->_sendSessionCookies();
- }
- /**
- * End the current session and store session data.
- *
- * @return bool
- */
- function session_write_close( ) {
- // store:
- if ( ! $this->write( $this->_session_id, serialize( $this->_session_var ) ) ) {
- die( 'Session write error!' );
- }
- // timeout old sessions:
- $this->gc();
- return true;
- }
- /**
- * Gets value of the session variable, change it with $this->set()
- * (not a reference, use $this->get_reference() for reference)
- *
- * @param string $name
- * @return mixed NULL if not set
- */
- function get( $name ) {
- if ( isset( $this->_session_var[$name] ) ) {
- return $this->_session_var[$name];
- } else {
- $null = null;
- return $null;
- }
- }
- /**
- * Sets a value to the session variable $name (Not a reference)
- *
- * @param string $name
- * @param mixed $value
- */
- function set( $name, $value ) {
- $this->_session_var[$name] = $value;
- }
- /**
- * Gets a reference to the session variable (which can be changed)
- *
- * @param string $name
- * @return mixed If empty/new: NULL
- */
- function & getReference( $name ) {
- if ( ! isset( $this->_session_var[$name] ) ) {
- $this->_session_var[$name] = null;
- }
- return $this->_session_var[$name];
- }
- /**
- * Unset current session
- *
- * @return bool True success, False failed
- */
- function session_unset() {
- if ( $this->_session_id ) {
- $this->destroy( $this->_session_id );
- $this->_session_id = null;
- $this->_session_var = null;
- }
- }
- /**
- * Sets/Gets current session id for get (warning: lower security)
- *
- * @param string $id new if change
- * @return string current if no change ( $id = null ) if session started already
- */
- function session_id( $id = null ) {
- if ( $id == null ) {
- if ( $this->_session_var !== null ) {
- // session started, can return id:
- return $this->_session_id;
- } else {
- return '';
- }
- } else {
- $current = $this->_session_id;
- if ( $id ) {
- $this->_session_id = $id;
- }
- return $current;
- }
- }
- /**
- * Generates a random session_id of chars and numbers
- * (Similar to cbMakeRandomString)
- * @access private
- *
- * @param int $stringLength
- * @return string
- */
- function generateRandSessionid( $stringLength = 32 ) {
- $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
- $len = strlen( $chars );
- $rndString = '';
- mt_srand( 10000000 * (double) microtime() );
- for ( $i = 0; $i < $stringLength; $i++ ) {
- $rndString .= $chars[mt_rand( 0, $len - 1 )];
- }
- return $rndString;
- }
- /**
- * Validate the session id with internal records of the browser and check values.
- * @access private
- *
- * @return bool
- */
- function _validateSession( ) {
- global $_COOKIE;
- // check if browser user agent has changed:
- if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
- $browser = $this->get( 'cbsession.agent' );
- if ( $browser === null ) {
- $this->set( 'cbsession.agent', $_SERVER['HTTP_USER_AGENT']);
- } elseif ( $_SERVER['HTTP_USER_AGENT'] !== $browser ) {
- return false;
- }
- }
- /* PROBLEM: COMMENTED OUT FOR NOW:
- // check if client IP received (could be fake through proxy) matches:
- if ( $this->_getClientIp() != $this->_sessionRecord['client_ip'] ) {
- return false;
- }
- // check if initial session connection had no proxy and now suddenly we have one:
- $incoming_ip = $this->_getIcomingIp();
- if ( ( $incoming_ip != $this->_sessionRecord['client_ip'] )
- && ( $this->_sessionRecord['incoming_ip'] == $this->_sessionRecord['client_ip'] ) )
- {
- return false;
- }
- */
- // Things seem to match, check the validation cookie: //TBD later
- return true;
- }
- function _getIcomingIp() {
- global $_SERVER;
-
- return $_SERVER['REMOTE_ADDR'];
- }
- function _getClientIp() {
- global $_SERVER;
-
- if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
- $forwarded_ip_array = explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']);
- $client_ip = $forwarded_ip_array[count($forwarded_ip_array) - 1];
- } else {
- $client_ip = $_SERVER['REMOTE_ADDR'];
- }
- return $client_ip;
- }
- /**
- * Reads session record from database
- *
- * @param string $id
- * @return string or NULL if record innexistant or expired
- */
- function read( $id ) {
- // Fetch session data from the selected database
- $sql = 'SELECT * FROM `#__comprofiler_sessions`'
- . ' WHERE `session_id` = ' . $this->_db->Quote( $id )
- . ' AND `expiry_time` >= UNIX_TIMESTAMP()'
- ;
- $this->_db->setQuery( $sql );
- $this->_sessionRecord = $this->_db->loadAssoc();
- if ( $this->_sessionRecord !== null ) {
- return $this->_sessionRecord['session_data'];
- }
- return null;
- }
- /**
- * Writes session record to database
- *
- * @param string $id
- * @param string $data
- * @return bool
- */
- function write( $id, $data ) {
- global $_CB_framework;
- // Prepare new values:
- $v = array();
- $v['session_id'] = $this->_db->Quote( $id );
- $v['session_data'] = $this->_db->Quote( $data );
- $v['expiry_time'] = 'UNIX_TIMESTAMP()+' . (int) $this->_life_time;
- if ( $_CB_framework ) {
- $v['ui'] = (int) $_CB_framework->getUi();
- if ( $_CB_framework->myId() ) {
- $v['username'] = $this->_db->Quote( $_CB_framework->myUsername() );
- $v['userid'] = (int) $_CB_framework->myId();
- }
- }
- if ( $this->_sessionRecord !== null ) {
- // UPDATE existing:
- $sets = array();
- foreach ( $v as $col => $escapedVal ) {
- $sets[] = $this->_db->NameQuote( $col ) . ' = ' . $escapedVal;
- }
- $where = array_shift( $sets );
- $sql = 'UPDATE `#__comprofiler_sessions` SET ' . implode( ', ', $sets )
- . ' WHERE ' . $where;
- $this->_db->setQuery( $sql );
- $okUpdate = $this->_db->query();
- if ( $okUpdate ) {
- return $okUpdate;
- }
- }
- // INSERT new: add IP address for first record:
- $v['client_ip'] = $this->_db->Quote( $this->_getClientIp() );
- $v['incoming_ip'] = $this->_db->Quote( $this->_getIcomingIp() );
- $columns = array();
- $escValues = array();
- foreach ( $v as $col => $escapedVal ) {
- $columns[] = $this->_db->NameQuote( $col );
- $escValues[] = $escapedVal;
- }
- $sql = 'INSERT INTO `#__comprofiler_sessions`'
- . ' (' . implode( ',', $columns ) . ')'
- . ' VALUES(' . implode( ',', $escValues ) . ')'
- ;
- $this->_db->setQuery( $sql );
- return $this->_db->query();
- }
- /**
- * Removes session $id from database
- *
- * @param string $id
- * @return bool
- */
- function destroy( $id ) {
- $sql = 'DELETE FROM `#__comprofiler_sessions`'
- . ' WHERE `session_id` = ' . $this->_db->Quote( $id )
- ;
- $this->_db->setQuery( $sql );
- return $this->_db->query();
- }
- /**
- * Garbage Collection
- * Delete all records who have passed the expiration time
- *
- * @return bool
- */
- function gc() {
- $sql = 'DELETE FROM `#__comprofiler_sessions` WHERE `expiry_time` < UNIX_TIMESTAMP();';
- $this->_db->setQuery( $sql );
- return $this->_db->query();
- }
- }
- // ----- NO MORE CLASSES OR FUNCTIONS PASSED THIS POINT -----
- // Post class declaration initialisations
- // some version of PHP don't allow the instantiation of classes
- // before they are defined
- ?>