Пример #1
0
    /**
     * Constructor
     *
     * If valid session cookie received: pull session from DB
     * Otherwise, INSERT a session into DB
     */
    function Session()
    {
        global $DB, $Debuglog, $current_User, $localtimenow, $Messages, $Settings, $UserSettings;
        global $Hit;
        global $cookie_session, $cookie_expires, $cookie_path, $cookie_domain;
        $Debuglog->add('Session: cookie_domain=' . $cookie_domain, 'request');
        $Debuglog->add('Session: cookie_path=' . $cookie_path, 'request');
        $session_cookie = param_cookie($cookie_session, 'string', '');
        if (empty($session_cookie)) {
            $Debuglog->add('Session: No session cookie received.', 'request');
        } else {
            // session ID sent by cookie
            if (!preg_match('~^(\\d+)_(\\w+)$~', $session_cookie, $match)) {
                $Debuglog->add('Session: Invalid session cookie format!', 'request');
            } else {
                // We have a valid session cookie:
                $session_id_by_cookie = $match[1];
                $session_key_by_cookie = $match[2];
                $Debuglog->add('Session: Session ID received from cookie: ' . $session_id_by_cookie, 'request');
                $timeout_sessions = NULL;
                if ($this->user_ID != NULL) {
                    // User is not anonymous, get custom session timeout (may return NULL):
                    $timeout_sessions = $UserSettings->get('timeout_sessions', $this->user_ID);
                }
                if (empty($timeout_sessions)) {
                    // User is anonymous or has no custom session timeout. So, we use default session timeout:
                    $timeout_sessions = $Settings->get('timeout_sessions');
                }
                $row = $DB->get_row('
					SELECT sess_ID, sess_key, sess_data, sess_user_ID, sess_start_ts, sess_lastseen_ts, sess_device
					  FROM T_sessions
					 WHERE sess_ID  = ' . $DB->quote($session_id_by_cookie) . '
					   AND sess_key = ' . $DB->quote($session_key_by_cookie) . '
					   AND UNIX_TIMESTAMP(sess_lastseen_ts) > ' . ($localtimenow - $timeout_sessions));
                if (empty($row)) {
                    $Debuglog->add('Session: Session ID/key combination is invalid!', 'request');
                } else {
                    // ID + key are valid: load data
                    $Debuglog->add('Session: Session ID is valid.', 'request');
                    $this->ID = $row->sess_ID;
                    $this->key = $row->sess_key;
                    $this->user_ID = $row->sess_user_ID;
                    $this->start_ts = mysql2timestamp($row->sess_start_ts);
                    $this->lastseen_ts = mysql2timestamp($row->sess_lastseen_ts);
                    $this->is_validated = true;
                    $this->sess_device = $row->sess_device;
                    $Debuglog->add('Session: Session user_ID: ' . var_export($this->user_ID, true), 'request');
                    if (empty($row->sess_data)) {
                        $Debuglog->add('Session: No session data available.', 'request');
                        $this->_data = array();
                    } else {
                        // Some session data has been previsouly stored:
                        // Unserialize session data (using an own callback that should provide class definitions):
                        $old_callback = ini_set('unserialize_callback_func', 'session_unserialize_callback');
                        if ($old_callback === false || is_null($old_callback)) {
                            // NULL if ini_set has been disabled for security reasons
                            // Brutally load all classes that we might need:
                            session_unserialize_load_all_classes();
                        }
                        // TODO: dh> This can fail, if there are special chars in sess_data:
                        //       It will be encoded in $evo_charset _after_ "SET NAMES", but
                        //       get retrieved here, _before_ any "SET NAMES" (if $db_config['connection_charset'] is not set (default))!
                        $this->_data = @unserialize($row->sess_data);
                        if ($old_callback !== false) {
                            // Restore the old callback if we changed it:
                            ini_set('unserialize_callback_func', $old_callback);
                        }
                        if (!is_array($this->_data)) {
                            $Debuglog->add('Session: Session data corrupted!<br />
								connection_charset: ' . var_export($DB->connection_charset, true) . '<br />
								Serialized data was: --[' . var_export($row->sess_data, true) . ']--', array('session', 'error'));
                            $this->_data = array();
                        } else {
                            $Debuglog->add('Session: Session data loaded.', 'request');
                            // Load a Messages object from session data, if available:
                            if (($sess_Messages = $this->get('Messages')) && is_a($sess_Messages, 'Messages')) {
                                // dh> TODO: "old" messages should rather get prepended to any existing ones from the current request, rather than appended
                                $Messages->add_messages($sess_Messages);
                                $Debuglog->add('Session: Added Messages from session data.', 'request');
                                $this->delete('Messages');
                            }
                        }
                    }
                }
            }
        }
        if ($this->ID) {
            // there was a valid session before
            if ($this->lastseen_ts < $localtimenow - 60) {
                // lastseen timestamp is older then a minute, it needs to be updated at page exit
                $this->session_needs_save(true);
            }
        } else {
            // create a new session! :
            $this->key = generate_random_key(32);
            // Detect user device
            global $user_devices;
            $this->sess_device = '';
            if (!empty($_SERVER['HTTP_USER_AGENT'])) {
                foreach ($user_devices as $device_name => $device_regexp) {
                    if (preg_match('~' . $device_regexp . '~i', $_SERVER['HTTP_USER_AGENT'])) {
                        $this->sess_device = $device_name;
                        break;
                    }
                }
            }
            // We need to INSERT now because we need an ID now! (for the cookie)
            $DB->query("\n\t\t\t\tINSERT INTO T_sessions( sess_key, sess_start_ts, sess_lastseen_ts, sess_ipaddress, sess_device )\n\t\t\t\tVALUES (\n\t\t\t\t\t'" . $this->key . "',\n\t\t\t\t\t'" . date('Y-m-d H:i:s', $localtimenow) . "',\n\t\t\t\t\t'" . date('Y-m-d H:i:s', $localtimenow) . "',\n\t\t\t\t\t" . $DB->quote($Hit->IP) . ",\n\t\t\t\t\t" . $DB->quote($this->sess_device) . "\n\t\t\t\t)");
            $this->ID = $DB->insert_id;
            // Set a cookie valid for ~ 10 years:
            setcookie($cookie_session, $this->ID . '_' . $this->key, time() + 315360000, $cookie_path, $cookie_domain);
            $Debuglog->add('Session: ID (generated): ' . $this->ID, 'request');
            $Debuglog->add('Session: Cookie sent.', 'request');
        }
    }
Пример #2
0
    /**
     * Constructor
     */
    function Session()
    {
        global $DB, $Debuglog, $current_User, $localtimenow, $Messages, $Settings;
        global $Hit;
        global $cookie_session, $cookie_expires, $cookie_path, $cookie_domain;
        $Debuglog->add('cookie_domain=' . $cookie_domain, 'session');
        $Debuglog->add('cookie_path=' . $cookie_path, 'session');
        $session_cookie = param_cookie($cookie_session, 'string', '');
        if (empty($session_cookie)) {
            $Debuglog->add('No session cookie received.', 'session');
        } else {
            // session ID sent by cookie
            if (!preg_match('~^(\\d+)_(\\w+)$~', $session_cookie, $match)) {
                $Debuglog->add('Invalid session cookie format!', 'session');
            } else {
                // We have a valid session cookie:
                $session_id_by_cookie = $match[1];
                $session_key_by_cookie = $match[2];
                $Debuglog->add('Session ID received from cookie: ' . $session_id_by_cookie, 'session');
                $row = $DB->get_row('
					SELECT sess_ID, sess_key, sess_data, sess_user_ID
					  FROM T_sessions
					 WHERE sess_ID  = ' . $DB->quote($session_id_by_cookie) . '
					   AND sess_key = ' . $DB->quote($session_key_by_cookie) . '
					   AND UNIX_TIMESTAMP(sess_lastseen) > ' . ($localtimenow - $Settings->get('timeout_sessions')));
                if (empty($row)) {
                    $Debuglog->add('Session ID/key combination is invalid!', 'session');
                } else {
                    // ID + key are valid: load data
                    $Debuglog->add('Session ID is valid.', 'session');
                    $this->ID = $row->sess_ID;
                    $this->key = $row->sess_key;
                    $this->user_ID = $row->sess_user_ID;
                    $this->is_validated = true;
                    $Debuglog->add('Session user_ID: ' . var_export($this->user_ID, true), 'session');
                    if (empty($row->sess_data)) {
                        $Debuglog->add('No session data available.', 'session');
                        $this->_data = array();
                    } else {
                        // Some session data has been previsouly stored:
                        // Unserialize session data (using an own callback that should provide class definitions):
                        $old_callback = ini_set('unserialize_callback_func', 'session_unserialize_callback');
                        if ($old_callback === false) {
                            // this can fail, if "ini_set" has been disabled for security reasons.. :/
                            // Brutally load add classes that we might need:
                            session_unserialize_load_all_classes();
                        }
                        // TODO: dh> This can fail, if there are special chars in sess_data:
                        //       It will be encoded in $evo_charset _after_ "SET NAMES", but
                        //       get retrieved here, _before_ any "SET NAMES" (if $db_config['connection_charset'] is not set (default))!
                        $this->_data = @unserialize($row->sess_data);
                        if ($old_callback !== false) {
                            // Restore the old callback if we changed it:
                            ini_set('unserialize_callback_func', $old_callback);
                        }
                        if (!is_array($this->_data)) {
                            $Debuglog->add('Session data corrupted!<br />
								connection_charset: ' . var_export($DB->connection_charset, true) . '<br />
								Serialized data was: --[' . var_export($row->sess_data, true) . ']--', array('session', 'error'));
                            $this->_data = array();
                        } else {
                            $Debuglog->add('Session data loaded.', 'session');
                            // Load a Messages object from session data, if available:
                            if (($sess_Messages = $this->get('Messages')) && is_a($sess_Messages, 'log')) {
                                // dh> TODO: "old" messages should rather get prepended to any existing ones from the current request, rather than appended
                                $Messages->add_messages($sess_Messages->messages);
                                $Debuglog->add('Added Messages from session data.', 'session');
                                $this->delete('Messages');
                            }
                        }
                    }
                }
            }
        }
        if ($this->ID) {
            // there was a valid session before; update data (lastseen)
            $this->_session_needs_save = true;
        } else {
            // create a new session
            $this->key = generate_random_key(32);
            // We need to INSERT now because we need an ID now! (for the cookie)
            $DB->query("\r\n\t\t\t\tINSERT INTO T_sessions( sess_key, sess_lastseen, sess_ipaddress )\r\n\t\t\t\tVALUES (\r\n\t\t\t\t\t'" . $this->key . "',\r\n\t\t\t\t\t'" . date('Y-m-d H:i:s', $localtimenow) . "',\r\n\t\t\t\t\t'" . $Hit->IP . "'\r\n\t\t\t\t)");
            $this->ID = $DB->insert_id;
            // Set a cookie valid for ~ 10 years:
            setcookie($cookie_session, $this->ID . '_' . $this->key, time() + 315360000, $cookie_path, $cookie_domain);
            $Debuglog->add('ID (generated): ' . $this->ID, 'session');
            $Debuglog->add('Cookie sent.', 'session');
        }
        register_shutdown_function(array(&$this, 'dbsave'));
    }