/** * 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; }
/** * 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; }
/** * 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); } }
/** * 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(); }