Example #1
0
    /**
     * Create a new session
     *
     * If upon trying to start a session we discover there is nothing existing we
     * jump here. Additionally this method is called directly during login to regenerate
     * the session for the specific user. In this method we carry out a number of tasks;
     * garbage collection, (search)bot checking, banned user comparison. Basically
     * though this method will result in a new session for a specific user.
     */
    function session_create($user_id = false, $set_admin = false, $persist_login = false, $viewonline = true)
    {
        global $SID, $_SID, $db, $config, $cache, $phpbb_root_path, $phpEx, $phpbb_container;
        $this->data = array();
        /* Garbage collection ... remove old sessions updating user information
        		// if necessary. It means (potentially) 11 queries but only infrequently
        		if ($this->time_now > $config['session_last_gc'] + $config['session_gc'])
        		{
        			$this->session_gc();
        		}*/
        // Do we allow autologin on this board? No? Then override anything
        // that may be requested here
        if (!$config['allow_autologin']) {
            $this->cookie_data['k'] = $persist_login = false;
        }
        /**
         * Here we do a bot check, oh er saucy! No, not that kind of bot
         * check. We loop through the list of bots defined by the admin and
         * see if we have any useragent and/or IP matches. If we do, this is a
         * bot, act accordingly
         */
        $bot = false;
        $active_bots = $cache->obtain_bots();
        foreach ($active_bots as $row) {
            if ($row['bot_agent'] && preg_match('#' . str_replace('\\*', '.*?', preg_quote($row['bot_agent'], '#')) . '#i', $this->browser)) {
                $bot = $row['user_id'];
            }
            // If ip is supplied, we will make sure the ip is matching too...
            if ($row['bot_ip'] && ($bot || !$row['bot_agent'])) {
                // Set bot to false, then we only have to set it to true if it is matching
                $bot = false;
                foreach (explode(',', $row['bot_ip']) as $bot_ip) {
                    $bot_ip = trim($bot_ip);
                    if (!$bot_ip) {
                        continue;
                    }
                    if (strpos($this->ip, $bot_ip) === 0) {
                        $bot = (int) $row['user_id'];
                        break;
                    }
                }
            }
            if ($bot) {
                break;
            }
        }
        /* @var $provider_collection \phpbb\auth\provider_collection */
        $provider_collection = $phpbb_container->get('auth.provider_collection');
        $provider = $provider_collection->get_provider();
        $this->data = $provider->autologin();
        if ($user_id !== false && sizeof($this->data) && $this->data['user_id'] != $user_id) {
            $this->data = array();
        }
        if (sizeof($this->data)) {
            $this->cookie_data['k'] = '';
            $this->cookie_data['u'] = $this->data['user_id'];
        }
        // If we're presented with an autologin key we'll join against it.
        // Else if we've been passed a user_id we'll grab data based on that
        if (isset($this->cookie_data['k']) && $this->cookie_data['k'] && $this->cookie_data['u'] && !sizeof($this->data)) {
            $sql = 'SELECT u.*
				FROM ' . USERS_TABLE . ' u, ' . SESSIONS_KEYS_TABLE . ' k
				WHERE u.user_id = ' . (int) $this->cookie_data['u'] . '
					AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ")\n\t\t\t\t\tAND k.user_id = u.user_id\n\t\t\t\t\tAND k.key_id = '" . $db->sql_escape(md5($this->cookie_data['k'])) . "'";
            $result = $db->sql_query($sql);
            $user_data = $db->sql_fetchrow($result);
            if ($user_id === false || isset($user_data['user_id']) && $user_id == $user_data['user_id']) {
                $this->data = $user_data;
                $bot = false;
            }
            $db->sql_freeresult($result);
        }
        if ($user_id !== false && !sizeof($this->data)) {
            $this->cookie_data['k'] = '';
            $this->cookie_data['u'] = $user_id;
            $sql = 'SELECT *
				FROM ' . USERS_TABLE . '
				WHERE user_id = ' . (int) $this->cookie_data['u'] . '
					AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
            $result = $db->sql_query($sql);
            $this->data = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);
            $bot = false;
        }
        // Bot user, if they have a SID in the Request URI we need to get rid of it
        // otherwise they'll index this page with the SID, duplicate content oh my!
        if ($bot && isset($_GET['sid'])) {
            send_status_line(301, 'Moved Permanently');
            redirect(build_url(array('sid')));
        }
        // If no data was returned one or more of the following occurred:
        // Key didn't match one in the DB
        // User does not exist
        // User is inactive
        // User is bot
        if (!sizeof($this->data) || !is_array($this->data)) {
            $this->cookie_data['k'] = '';
            $this->cookie_data['u'] = $bot ? $bot : ANONYMOUS;
            if (!$bot) {
                $sql = 'SELECT *
					FROM ' . USERS_TABLE . '
					WHERE user_id = ' . (int) $this->cookie_data['u'];
            } else {
                // We give bots always the same session if it is not yet expired.
                $sql = 'SELECT u.*, s.*
					FROM ' . USERS_TABLE . ' u
					LEFT JOIN ' . SESSIONS_TABLE . ' s ON (s.session_user_id = u.user_id)
					WHERE u.user_id = ' . (int) $bot;
            }
            $result = $db->sql_query($sql);
            $this->data = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);
        }
        if ($this->data['user_id'] != ANONYMOUS && !$bot) {
            $this->data['session_last_visit'] = isset($this->data['session_time']) && $this->data['session_time'] ? $this->data['session_time'] : ($this->data['user_lastvisit'] ? $this->data['user_lastvisit'] : time());
        } else {
            $this->data['session_last_visit'] = $this->time_now;
        }
        // Force user id to be integer...
        $this->data['user_id'] = (int) $this->data['user_id'];
        // At this stage we should have a filled data array, defined cookie u and k data.
        // data array should contain recent session info if we're a real user and a recent
        // session exists in which case session_id will also be set
        // Is user banned? Are they excluded? Won't return on ban, exists within method
        if ($this->data['user_type'] != USER_FOUNDER) {
            if (!$config['forwarded_for_check']) {
                $this->check_ban($this->data['user_id'], $this->ip);
            } else {
                $ips = explode(' ', $this->forwarded_for);
                $ips[] = $this->ip;
                $this->check_ban($this->data['user_id'], $ips);
            }
        }
        $this->data['is_registered'] = !$bot && $this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == USER_NORMAL || $this->data['user_type'] == USER_FOUNDER) ? true : false;
        $this->data['is_bot'] = $bot ? true : false;
        // If our friend is a bot, we re-assign a previously assigned session
        if ($this->data['is_bot'] && $bot == $this->data['user_id'] && $this->data['session_id']) {
            // Only assign the current session if the ip, browser and forwarded_for match...
            if (strpos($this->ip, ':') !== false && strpos($this->data['session_ip'], ':') !== false) {
                $s_ip = short_ipv6($this->data['session_ip'], $config['ip_check']);
                $u_ip = short_ipv6($this->ip, $config['ip_check']);
            } else {
                $s_ip = implode('.', array_slice(explode('.', $this->data['session_ip']), 0, $config['ip_check']));
                $u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check']));
            }
            $s_browser = $config['browser_check'] ? trim(strtolower(substr($this->data['session_browser'], 0, 149))) : '';
            $u_browser = $config['browser_check'] ? trim(strtolower(substr($this->browser, 0, 149))) : '';
            $s_forwarded_for = $config['forwarded_for_check'] ? substr($this->data['session_forwarded_for'], 0, 254) : '';
            $u_forwarded_for = $config['forwarded_for_check'] ? substr($this->forwarded_for, 0, 254) : '';
            if ($u_ip === $s_ip && $s_browser === $u_browser && $s_forwarded_for === $u_forwarded_for) {
                $this->session_id = $this->data['session_id'];
                // Only update session DB a minute or so after last update or if page changes
                if ($this->time_now - $this->data['session_time'] > 60 || $this->update_session_page && $this->data['session_page'] != $this->page['page']) {
                    $this->data['session_time'] = $this->data['session_last_visit'] = $this->time_now;
                    $sql_ary = array('session_time' => $this->time_now, 'session_last_visit' => $this->time_now, 'session_admin' => 0);
                    if ($this->update_session_page) {
                        $sql_ary['session_page'] = substr($this->page['page'], 0, 199);
                        $sql_ary['session_forum_id'] = $this->page['forum'];
                    }
                    $this->update_session($sql_ary);
                    // Update the last visit time
                    $sql = 'UPDATE ' . USERS_TABLE . '
						SET user_lastvisit = ' . (int) $this->data['session_time'] . '
						WHERE user_id = ' . (int) $this->data['user_id'];
                    $db->sql_query($sql);
                }
                $SID = '?sid=';
                $_SID = '';
                return true;
            } else {
                // If the ip and browser does not match make sure we only have one bot assigned to one session
                $db->sql_query('DELETE FROM ' . SESSIONS_TABLE . ' WHERE session_user_id = ' . $this->data['user_id']);
            }
        }
        $session_autologin = ($this->cookie_data['k'] || $persist_login) && $this->data['is_registered'] ? true : false;
        $set_admin = $set_admin && $this->data['is_registered'] ? true : false;
        // Create or update the session
        $sql_ary = array('session_user_id' => (int) $this->data['user_id'], 'session_start' => (int) $this->time_now, 'session_last_visit' => (int) $this->data['session_last_visit'], 'session_time' => (int) $this->time_now, 'session_browser' => (string) trim(substr($this->browser, 0, 149)), 'session_forwarded_for' => (string) $this->forwarded_for, 'session_ip' => (string) $this->ip, 'session_autologin' => $session_autologin ? 1 : 0, 'session_admin' => $set_admin ? 1 : 0, 'session_viewonline' => $viewonline ? 1 : 0);
        if ($this->update_session_page) {
            $sql_ary['session_page'] = (string) substr($this->page['page'], 0, 199);
            $sql_ary['session_forum_id'] = $this->page['forum'];
        }
        $db->sql_return_on_error(true);
        $sql = 'DELETE
			FROM ' . SESSIONS_TABLE . '
			WHERE session_id = \'' . $db->sql_escape($this->session_id) . '\'
				AND session_user_id = ' . ANONYMOUS;
        if (!defined('IN_ERROR_HANDLER') && (!$this->session_id || !$db->sql_query($sql) || !$db->sql_affectedrows())) {
            // Limit new sessions in 1 minute period (if required)
            if (empty($this->data['session_time']) && $config['active_sessions']) {
                //				$db->sql_return_on_error(false);
                $sql = 'SELECT COUNT(session_id) AS sessions
					FROM ' . SESSIONS_TABLE . '
					WHERE session_time >= ' . ($this->time_now - 60);
                $result = $db->sql_query($sql);
                $row = $db->sql_fetchrow($result);
                $db->sql_freeresult($result);
                if ((int) $row['sessions'] > (int) $config['active_sessions']) {
                    send_status_line(503, 'Service Unavailable');
                    trigger_error('BOARD_UNAVAILABLE');
                }
            }
        }
        // Since we re-create the session id here, the inserted row must be unique. Therefore, we display potential errors.
        // Commented out because it will not allow forums to update correctly
        //		$db->sql_return_on_error(false);
        // Something quite important: session_page always holds the *last* page visited, except for the *first* visit.
        // We are not able to simply have an empty session_page btw, therefore we need to tell phpBB how to detect this special case.
        // If the session id is empty, we have a completely new one and will set an "identifier" here. This identifier is able to be checked later.
        if (empty($this->data['session_id'])) {
            // This is a temporary variable, only set for the very first visit
            $this->data['session_created'] = true;
        }
        $this->session_id = $this->data['session_id'] = md5(unique_id());
        $sql_ary['session_id'] = (string) $this->session_id;
        $sql_ary['session_page'] = (string) substr($this->page['page'], 0, 199);
        $sql_ary['session_forum_id'] = $this->page['forum'];
        $sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
        $db->sql_query($sql);
        $db->sql_return_on_error(false);
        // Regenerate autologin/persistent login key
        if ($session_autologin) {
            $this->set_login_key();
        }
        // refresh data
        $SID = '?sid=' . $this->session_id;
        $_SID = $this->session_id;
        $this->data = array_merge($this->data, $sql_ary);
        if (!$bot) {
            $cookie_expire = $this->time_now + ($config['max_autologin_time'] ? 86400 * (int) $config['max_autologin_time'] : 31536000);
            $this->set_cookie('u', $this->cookie_data['u'], $cookie_expire);
            $this->set_cookie('k', $this->cookie_data['k'], $cookie_expire);
            $this->set_cookie('sid', $this->session_id, $cookie_expire);
            unset($cookie_expire);
            $sql = 'SELECT COUNT(session_id) AS sessions
					FROM ' . SESSIONS_TABLE . '
					WHERE session_user_id = ' . (int) $this->data['user_id'] . '
					AND session_time >= ' . (int) ($this->time_now - max($config['session_length'], $config['form_token_lifetime']));
            $result = $db->sql_query($sql);
            $row = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);
            if ((int) $row['sessions'] <= 1 || empty($this->data['user_form_salt'])) {
                $this->data['user_form_salt'] = unique_id();
                // Update the form key
                $sql = 'UPDATE ' . USERS_TABLE . '
					SET user_form_salt = \'' . $db->sql_escape($this->data['user_form_salt']) . '\'
					WHERE user_id = ' . (int) $this->data['user_id'];
                $db->sql_query($sql);
            }
        } else {
            $this->data['session_time'] = $this->data['session_last_visit'] = $this->time_now;
            // Update the last visit time
            $sql = 'UPDATE ' . USERS_TABLE . '
				SET user_lastvisit = ' . (int) $this->data['session_time'] . '
				WHERE user_id = ' . (int) $this->data['user_id'];
            $db->sql_query($sql);
            $SID = '?sid=';
            $_SID = '';
        }
        return true;
    }
Example #2
0
/**
* Check IPs for match
*
* Checks a portion (or the entire) IP to determine if they match
*
* @param    string  $stored_ip  source IP address
* @param    string  $remote_ip  remote IP address
* @param    int     $force      true - force IP check regardless of
*                               configuration setting
* @return   boolean true on match / false on mis-match
*
*/
function _ipCheck($stored_ip, $remote_ip, $force = 0)
{
    global $_CONF;
    if ($_CONF['session_ip_check'] == 0 && $force == 0) {
        return true;
    }
    if ($force) {
        $ipLength = 3;
    } else {
        $ipLength = $_CONF['session_ip_check'] + 1;
    }
    if (strpos($remote_ip, ':') !== false && strpos($stored_ip, ':') !== false) {
        $s_ip = short_ipv6($stored_ip, $ipLength);
        $r_ip = short_ipv6($remote_ip, $ipLength);
    } else {
        $s_ip = implode('.', array_slice(explode('.', $stored_ip), 0, $ipLength));
        $r_ip = implode('.', array_slice(explode('.', $remote_ip), 0, $ipLength));
    }
    if ($r_ip === $s_ip) {
        return true;
    }
    return false;
}
Example #3
0
/**
* Log IPs and optionally block and/or ban the "fake" IP
*
* Inserts "real" and "fake" IPs in SPECULATIVE_TABLE, blocks and/or bans the "fake" IP session if configured to do so.
* On External IPs (log) page, the first column shows the "fake IP address" and the third column shows the "real IP address".
* The reason we do it in this way is because when you're looking at the IP address of a post, you're going to see the "fake IP address".
*
* We use $db->sql_escape() in all our SQL statements rather than str_replace("\'","''",$_REQUEST['var']) on each var as it comes in.
* This is to avoid confusion and to avoid escaping the same text twice and ending up with too many backslshes in the final result.
*
* @param	string	$ip_masked		The "fake" IP address.
* @param	int		$mode		The test mode used (modes defined in constants.php).
* @param	string	$ip_direct		The "real" IP address.
* @param	string	$info			Additional info like User-Agent string or CGI-Proxy URL(s) - optional.
*/
function insert_ip($ip_masked, $mode, $ip_direct, $info = '')
{
    global $phpbb_root_path, $phpEx;
    global $db, $sid, $key, $config;
    // We don't check $ip_direct as it has just been validated (top of the script) in the case of plugins, or '0.0.0.0' for TOR_DNSEL/PROXY_DNSBL.
    // We also don't validate $ip_masked in the case of X_FORWARDED_FOR as that is actually the IP requesting this page (already validated up top)
    if ($mode != X_FORWARDED_FOR && !preg_match(get_preg_expression('ipv4'), $ip_masked) && !preg_match(get_preg_expression('ipv6'), $ip_masked)) {
        return;
        // contains invalid data, return and don't log anything
    }
    // Validate IP length according to admin ("Session IP Validation" in ACP->Server Configuration->Security Settings)
    // session_begin() looks at $config['ip_check'] to see which bits of an IP address to check and so shall we.
    // First, check if both addresses are IPv6, else we assume both are IPv4 ($f_ip is the fake, $r_ip is the real)
    if (strpos($ip_masked, ':') !== false && strpos($ip_direct, ':') !== false) {
        // short_ipv6() from includes/functions.php
        $f_ip = short_ipv6($ip_masked, $config['ip_check']);
        $r_ip = short_ipv6($ip_direct, $config['ip_check']);
    } else {
        $f_ip = implode('.', array_slice(explode('.', $ip_masked), 0, $config['ip_check']));
        $r_ip = implode('.', array_slice(explode('.', $ip_direct), 0, $config['ip_check']));
    }
    // If "Session IP Validation" is NOT set to None, and the validated length matches, we return and log nothing
    //  (see "Select ip validation" in includes/acp/acp_board.php for more info)
    if ($config['ip_check'] != 0 && $r_ip === $f_ip) {
        return;
    }
    /**
     * In Java, at least, there's a possibility that the main IP we're recording and the "masked" IP address are the same.
     * the reason this function would be called, in those cases, is to log $lan_ip.   $lan_ip, however, isn't reliable enough
     * to block people over (assuming any blocking is taking place).  As such, although we log it, we don't update phpbb_sessions.
     */
    if ($mode != JAVA_INTERNAL) {
        /**
         * session_speculative_test will eventually be used to determine whether or not this session ought to be blocked.
         * This check is done by performing a bitwise "and" against $config['ip_block'].  If the bits that represent the various
         * modes 'and' with any of the bits in the bitwise representation of session_speculative_test, a block is done.
         * To guarantee that each bit is unique to a specific mode, powers of two are used to represent the modes (see constants.php).
         */
        $sql = 'UPDATE ' . SESSIONS_TABLE . " \n\t\t\tSET session_speculative_test = session_speculative_test | " . $db->sql_escape($mode) . " \n\t\t\tWHERE session_id = '" . $db->sql_escape($sid) . "' \n\t\t\t\tAND session_speculative_key = '" . $db->sql_escape($key) . "'";
        if (!($result = $db->sql_query($sql))) {
            die;
        }
        // if neither the session_id or the session_speculative_key are valid (as would be revealed by $db->sql_affectedrows being 0),
        // we assume the information is not trustworthy and quit.
        if (!$db->sql_affectedrows($result)) {
            die;
        }
        // Ban if appropriate
        if ($config['ip_ban'] && $mode & $config['ip_block']) {
            // $ban_len takes precedence over $ban_len_other unless $ban_len is set to "-1" (other - until $ban_len_other)
            // see function user_ban() in functions_user.php for more info
            $ban_len = $config['ip_ban_length'];
            $ban_len_other = $config['ip_ban_length_other'];
            $ban_exclude = 0;
            $ban_reason = $config['ip_ban_reason'];
            $ban_give_reason = $config['ip_ban_give_reason'];
            // user_ban() function from includes/functions_user.php
            include $phpbb_root_path . 'includes/functions_user.' . $phpEx;
            user_ban('ip', $ip_masked, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason);
        }
    }
    // Fetch currently logged entries for the specified IPs/method. Prevent duplicate entries.
    $sql = 'SELECT * FROM ' . SPECULATIVE_TABLE . " \n\t\tWHERE ip_address = '" . $db->sql_escape($ip_masked) . "' \n\t\t\tAND method = " . $db->sql_escape($mode) . " \n\t\t\tAND real_ip = '" . $db->sql_escape($ip_direct) . "'";
    // Allows duplicate logs of Masked/Real-IP/Method combination if the User-Agent (Browser/Plugin info) differs.
    if ($config['ip_log_agent_check'] && $mode != XSS && !empty($info)) {
        $sql .= " AND info = '" . $db->sql_escape($info) . "'";
    }
    $result = $db->sql_query($sql);
    if (!($row = $db->sql_fetchrow($result))) {
        $sql_ary = array('ip_address' => $ip_masked, 'method' => $mode, 'discovered' => time(), 'real_ip' => $ip_direct, 'info' => $info);
        $sql = 'INSERT INTO ' . SPECULATIVE_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
        $db->sql_query($sql);
    }
}
Example #4
0
 /**
  * Start session management
  *
  * This is where all session activity begins. We gather various pieces of
  * information from the client and server. We test to see if a session already
  * exists. If it does, fine and dandy. If it doesn't we'll go on to create a
  * new one ... pretty logical heh? We also examine the system load (if we're
  * running on a system which makes such information readily available) and
  * halt if it's above an admin definable limit.
  *
  * @param bool $update_session_page if true the session page gets updated.
  *			This can be set to circumvent certain scripts to update the users last visited page.
  */
 function session_begin($update_session_page = true)
 {
     global $SID, $_SID, $_EXTRA_URL, $db, $config;
     // ICY PHOENIX - BEGIN
     global $lang;
     // ICY PHOENIX - END
     // Give us some basic information
     $this->time_now = time();
     $this->cookie_data = array('u' => 0, 'k' => '');
     $this->cookie_expire = $this->time_now + ($config['max_autologin_time'] ? 86400 * (int) $config['max_autologin_time'] : 31536000);
     $this->update_session_page = empty($update_session_page) || defined('IMG_THUMB') ? false : true;
     //$this->browser = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : '';
     $this->browser = !empty($_SERVER['HTTP_USER_AGENT']) ? (string) $_SERVER['HTTP_USER_AGENT'] : '';
     $this->referer = !empty($_SERVER['HTTP_REFERER']) ? htmlspecialchars((string) $_SERVER['HTTP_REFERER']) : '';
     $this->forwarded_for = !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? htmlspecialchars((string) $_SERVER['HTTP_X_FORWARDED_FOR']) : '';
     $this->host = extract_current_hostname();
     $this->page = extract_current_page(IP_ROOT_PATH);
     $session_cookie_empty = empty($_COOKIE[$config['cookie_name'] . '_sid']) ? true : false;
     $session_get_empty = empty($_GET['sid']) ? true : false;
     $session_empty = true;
     if (isset($_COOKIE[$config['cookie_name'] . '_sid']) || isset($_COOKIE[$config['cookie_name'] . '_u'])) {
         $this->cookie_data['u'] = request_var($config['cookie_name'] . '_u', 0, false, true);
         $this->cookie_data['k'] = request_var($config['cookie_name'] . '_k', '', false, true);
         $this->session_id = request_var($config['cookie_name'] . '_sid', '', false, true);
         // Mighty Gorgon: I'm still not sure if I want to keep 'sid=' in Icy Phoenix as well... maybe better removing it!!!
         //$SID = (defined('NEED_SID')) ? ('sid=' . $this->session_id) : 'sid=';
         $SID = defined('NEED_SID') ? 'sid=' . $this->session_id : '';
         $_SID = defined('NEED_SID') ? $this->session_id : '';
         $session_empty = empty($this->session_id) ? true : false;
     }
     // Mighty Gorgon: moved here this IF block... why it was so down in the code???
     // if no session id is set, redirect to index.php
     //if (defined('NEED_SID') && ($cookie_empty || (!isset($_GET['sid']) || ($this->session_id !== $_GET['sid']))))
     if (defined('NEED_SID') && !defined('IN_LOGIN') && ($session_cookie_empty || $session_empty || !isset($_GET['sid']) || isset($_GET['sid']) && $this->session_id !== $_GET['sid'])) {
         // Mighty Gorgon: I don't know why it isn't working properly, returning blank page!!!
         //send_status_line(401, 'Not authorized');
         // Mighty Gorgon: removed append_sid as it seems the user doesn't have a valid SID!
         redirect(IP_ROOT_PATH . 'index.' . PHP_EXT);
     }
     if ($session_empty) {
         $this->session_id = request_var('sid', '');
         $_SID = $this->session_id;
         $SID = 'sid=' . $this->session_id;
         $this->cookie_data = array('u' => 0, 'k' => '');
     }
     $_EXTRA_URL = array();
     // Why no forwarded_for et al? Well, too easily spoofed. With the results of my recent requests
     // it's pretty clear that in the majority of cases you'll at least be left with a proxy/cache ip.
     $this->ip = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : (!empty($_ENV['REMOTE_ADDR']) ? $_ENV['REMOTE_ADDR'] : getenv('REMOTE_ADDR'));
     $this->ip = preg_replace('#[ ]{2,}#', ' ', str_replace(array(',', ' '), ' ', $this->ip));
     // split the list of IPs
     $ips = explode(' ', $this->ip);
     // Default IP if REMOTE_ADDR is invalid
     $this->ip = '127.0.0.1';
     $format_ipv4 = get_preg_expression('ipv4');
     $format_ipv6 = get_preg_expression('ipv6');
     foreach ($ips as $ip) {
         if (preg_match($format_ipv4, $ip)) {
             $this->ip = $ip;
         } elseif (preg_match($format_ipv6, $ip)) {
             // Quick check for IPv4-mapped address in IPv6
             if (stripos($ip, '::ffff:') === 0) {
                 $ipv4 = substr($ip, 7);
                 if (preg_match($format_ipv4, $ipv4)) {
                     $ip = $ipv4;
                 }
             }
             $this->ip = $ip;
         } else {
             // We want to use the last valid address in the chain
             // Leave foreach loop when address is invalid
             break;
         }
     }
     $this->load = false;
     // Load limit check (if applicable)
     if ($config['limit_load'] || $config['limit_search_load']) {
         if (function_exists('sys_getloadavg') && ($load = sys_getloadavg()) || ($load = explode(' ', @file_get_contents('/proc/loadavg')))) {
             $this->load = array_slice($load, 0, 1);
             $this->load = floatval($this->load[0]);
         } else {
             set_config('limit_load', '0');
             set_config('limit_search_load', '0');
         }
     }
     // if session id is set
     if (!empty($this->session_id)) {
         $sql = "SELECT u.*, s.*\n\t\t\t\tFROM " . SESSIONS_TABLE . " s, " . USERS_TABLE . " u\n\t\t\t\tWHERE s.session_id = '" . $db->sql_escape($this->session_id) . "'\n\t\t\t\t\tAND u.user_id = s.session_user_id";
         $result = $db->sql_query($sql);
         $this->data = $db->sql_fetchrow($result);
         $db->sql_freeresult($result);
         // Did the session exist in the DB?
         if (isset($this->data['user_id'])) {
             if (strpos($this->ip, ':') !== false && strpos($this->data['session_ip'], ':') !== false) {
                 $s_ip = short_ipv6($this->data['session_ip'], $config['ip_check']);
                 $u_ip = short_ipv6($this->ip, $config['ip_check']);
             } else {
                 $s_ip = implode('.', array_slice(explode('.', $this->data['session_ip']), 0, $config['ip_check']));
                 $u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check']));
             }
             $s_browser = $config['browser_check'] ? trim(strtolower(substr($this->data['session_browser'], 0, 254))) : '';
             $u_browser = $config['browser_check'] ? trim(strtolower(substr($this->browser, 0, 254))) : '';
             // referer checks
             // The @ before $config['referer_validation'] suppresses notices present while running the updater
             $check_referer_path = @$config['referer_validation'] == REFERER_VALIDATE_PATH;
             $referer_valid = true;
             // we assume HEAD and TRACE to be foul play and thus only whitelist GET
             if (@$config['referer_validation'] && isset($_SERVER['REQUEST_METHOD']) && strtolower($_SERVER['REQUEST_METHOD']) !== 'get') {
                 $referer_valid = $this->validate_referer($check_referer_path);
             }
             if ($u_ip === $s_ip && $s_browser === $u_browser && $referer_valid) {
                 // Some useful boolean checks... defined here for future easy of use
                 $session_expired = false;
                 $session_refresh_time = (int) SESSION_REFRESH;
                 $autologin_expired = !empty($config['max_autologin_time']) && $this->data['session_time'] < $this->time_now - 86400 * (int) $config['max_autologin_time'] + $session_refresh_time ? true : false;
                 $session_time_expired = $this->data['session_time'] < $this->time_now - ((int) $config['session_length'] + $session_refresh_time) ? true : false;
                 $session_refresh = $this->data['session_time'] < $this->time_now - $session_refresh_time ? true : false;
                 if (!$session_expired) {
                     // Check the session length timeframe if autologin is not enabled.
                     // Else check the autologin length... and also removing those having autologin enabled but no longer allowed site-wide.
                     if (empty($this->data['session_autologin'])) {
                         if ($session_time_expired) {
                             $session_expired = true;
                         }
                     } elseif (empty($config['allow_autologin']) || $autologin_expired) {
                         $session_expired = true;
                     }
                 }
                 // ICY PHOENIX - BEGIN
                 // This portion of code needs to stay here (after isset($this->data['user_id']) )... otherwise we are potentially going to instantiate some $user->data even if $user->data is still empty
                 $this->bots_process();
                 if (isset($this->data['user_id']) && $this->data['user_id'] != ANONYMOUS && isset($this->data['user_level']) && $this->data['user_level'] == JUNIOR_ADMIN) {
                     define('IS_JUNIOR_ADMIN', true);
                     $this->data['user_level'] = !defined('IN_ADMIN') && !defined('IN_CMS') ? ADMIN : MOD;
                 }
                 // Refresh last visit time for those users having autologin enabled or those users with session time expired (only if config for this has been set)
                 if ($this->data['user_id'] != ANONYMOUS && (!empty($config['session_last_visit_reset']) && $session_time_expired || !empty($config['allow_autologin']) && $autologin_expired || empty($this->data['user_lastvisit']))) {
                     $sql = "UPDATE " . USERS_TABLE . "\n\t\t\t\t\t\t\tSET user_lastvisit = " . (int) $this->data['session_time'] . "\n\t\t\t\t\t\t\tWHERE user_id = " . (int) $this->data['user_id'];
                     $db->sql_query($sql);
                 }
                 // ICY PHOENIX - END
                 if (!$session_expired) {
                     // Only update session DB a minute or so after last update or if page changes
                     // Mighty Gorgon: in Icy Phoenix we give maximum priority to $this->update_session_page, because we don't want the session to be updated for thumbnails or other special features!
                     if ($this->update_session_page && ($session_refresh || $this->data['session_page'] != $this->page['page']) && empty($_REQUEST['explain'])) {
                         $sql_ary = array();
                         // ICY PHOENIX - BEGIN
                         // Update $user->data
                         $this->data['user_session_time'] = $this->time_now;
                         $this->data['user_session_page'] = (string) substr($this->page['page'], 0, 254);
                         $this->data['user_browser'] = (string) substr($this->browser, 0, 254);
                         $this->data['user_totalpages'] = (int) $this->data['user_totalpages'] + 1;
                         $this->data['user_totaltime'] = (int) $this->data['user_totaltime'] + $this->time_now - $this->data['session_time'];
                         // ICY PHOENIX - END
                         // A little trick to reset session_admin on session re-usage
                         if (!defined('IN_ADMIN') && !defined('IN_CMS') && $session_time_expired) {
                             $sql_ary['session_admin'] = 0;
                         }
                         $sql_ary['session_time'] = $this->time_now;
                         $sql_ary['session_page'] = $this->data['user_session_page'];
                         $sql_ary['session_browser'] = $this->data['user_browser'];
                         $sql_ary['session_forum_id'] = $this->page['forum'];
                         $sql_ary['session_topic_id'] = $this->page['topic'];
                         $db->sql_return_on_error(true);
                         $sql = "UPDATE " . SESSIONS_TABLE . " SET " . $db->sql_build_array('UPDATE', $sql_ary) . "\n\t\t\t\t\t\t\t\tWHERE session_id = '" . $db->sql_escape($this->session_id) . "'";
                         $result = $db->sql_query($sql);
                         // ICY PHOENIX - BEGIN
                         if ($this->data['user_id'] != ANONYMOUS) {
                             $sql_ary = array();
                             $sql_ary['user_ip'] = $this->ip;
                             $sql_ary['user_session_time'] = $this->data['user_session_time'];
                             $sql_ary['user_session_page'] = $this->data['user_session_page'];
                             $sql_ary['user_browser'] = $this->data['user_browser'];
                             $sql_ary['user_totalpages'] = $this->data['user_totalpages'];
                             $sql_ary['user_totaltime'] = $this->data['user_totaltime'];
                             $sql = "UPDATE " . USERS_TABLE . " SET " . $db->sql_build_array('UPDATE', $sql_ary) . "\n\t\t\t\t\t\t\t\t\tWHERE user_id = " . $this->data['user_id'];
                             $result = $db->sql_query($sql);
                         }
                         // ICY PHOENIX - END
                         $db->sql_return_on_error(false);
                     }
                     $this->data['is_registered'] = empty($this->data['is_bot']) && $this->data['user_id'] != ANONYMOUS && !empty($this->data['user_active']) ? true : false;
                     $this->data['session_logged_in'] = $this->data['is_registered'];
                     $this->data['user_lang'] = basename($this->data['user_lang']);
                     $this->upi2db();
                     return true;
                 }
             } else {
                 // Added logging temporarily to help debug bugs...
                 if (defined('DEBUG_EXTRA') && $this->data['user_id'] != ANONYMOUS) {
                     if ($referer_valid) {
                         add_log('critical', 'LOG_IP_BROWSER_FORWARDED_CHECK', $u_ip, $s_ip, $u_browser, $s_browser);
                     } else {
                         add_log('critical', 'LOG_REFERER_INVALID', $this->referer);
                     }
                 }
             }
         }
     }
     // If we reach here then no (valid) session exists. So we'll create a new one
     return $this->session_create();
 }