diff options
Diffstat (limited to 'phpBB/includes/session.php')
| -rw-r--r-- | phpBB/includes/session.php | 1044 | 
1 files changed, 53 insertions, 991 deletions
| diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index fe5357f32e..6bc71da0c1 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -2,9 +2,8 @@  /**  *  * @package phpBB3 -* @version $Id$  * @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2  *  */ @@ -20,7 +19,7 @@ if (!defined('IN_PHPBB'))  * Session class  * @package phpBB3  */ -class session +class phpbb_session  {  	var $cookie_data = array();  	var $page = array(); @@ -39,18 +38,20 @@ class session  	*  	* @param string $root_path current root path (phpbb_root_path)  	*/ -	function extract_current_page($root_path) +	static function extract_current_page($root_path)  	{ +		global $request; +  		$page_array = array();  		// First of all, get the request uri... -		$script_name = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : getenv('PHP_SELF'); -		$args = (!empty($_SERVER['QUERY_STRING'])) ? explode('&', $_SERVER['QUERY_STRING']) : explode('&', getenv('QUERY_STRING')); +		$script_name = htmlspecialchars_decode($request->server('PHP_SELF')); +		$args = explode('&', htmlspecialchars_decode($request->server('QUERY_STRING')));  		// If we are unable to get the script name we use REQUEST_URI as a failover and note it within the page array for easier support...  		if (!$script_name)  		{ -			$script_name = (!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : getenv('REQUEST_URI'); +			$script_name = htmlspecialchars_decode($request->server('REQUEST_URI'));  			$script_name = (($pos = strpos($script_name, '?')) !== false) ? substr($script_name, 0, $pos) : $script_name;  			$page_array['failover'] = 1;  		} @@ -130,7 +131,7 @@ class session  			'root_script_path'	=> str_replace(' ', '%20', htmlspecialchars($root_script_path)),  			'page'				=> $page, -			'forum'				=> (isset($_REQUEST['f']) && $_REQUEST['f'] > 0) ? (int) $_REQUEST['f'] : 0, +			'forum'				=> request_var('f', 0),  		);  		return $page_array; @@ -141,10 +142,10 @@ class session  	*/  	function extract_current_hostname()  	{ -		global $config; +		global $config, $request;  		// Get hostname -		$host = (!empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME')); +		$host = htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME')));  		// Should be a string and lowered  		$host = (string) strtolower($host); @@ -206,14 +207,15 @@ class session  	function session_begin($update_session_page = true)  	{  		global $phpEx, $SID, $_SID, $_EXTRA_URL, $db, $config, $phpbb_root_path; +		global $request;  		// Give us some basic information  		$this->time_now				= time();  		$this->cookie_data			= array('u' => 0, 'k' => '');  		$this->update_session_page	= $update_session_page; -		$this->browser				= (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((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->browser				= $request->header('User-Agent'); +		$this->referer				= $request->header('Referer'); +		$this->forwarded_for		= $request->header('X-Forwarded-For');  		$this->host					= $this->extract_current_hostname();  		$this->page					= $this->extract_current_page($phpbb_root_path); @@ -241,7 +243,7 @@ class session  			$this->forwarded_for = '';  		} -		if (isset($_COOKIE[$config['cookie_name'] . '_sid']) || isset($_COOKIE[$config['cookie_name'] . '_u'])) +		if ($request->is_set($config['cookie_name'] . '_sid', phpbb_request_interface::COOKIE) || $request->is_set($config['cookie_name'] . '_u', phpbb_request_interface::COOKIE))  		{  			$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); @@ -267,7 +269,7 @@ class session  		// 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'])) ? (string) $_SERVER['REMOTE_ADDR'] : ''; +		$this->ip = htmlspecialchars_decode($request->server('REMOTE_ADDR'));  		$this->ip = preg_replace('# {2,}#', ' ', str_replace(',', ' ', $this->ip));  		// split the list of IPs @@ -278,6 +280,24 @@ class session  		foreach ($ips as $ip)  		{ +			if (function_exists('phpbb_ip_normalise')) +			{ +				// Normalise IP address +				$ip = phpbb_ip_normalise($ip); + +				if (empty($ip)) +				{ +					// IP address is invalid. +					break; +				} + +				// IP address is valid. +				$this->ip = $ip; + +				// Skip legacy code. +				continue; +			} +  			if (preg_match(get_preg_expression('ipv4'), $ip))  			{  				$this->ip = $ip; @@ -323,7 +343,8 @@ class session  		}  		// if no session id is set, redirect to index.php -		if (defined('NEED_SID') && (!isset($_GET['sid']) || $this->session_id !== $_GET['sid'])) +		$session_id = $request->variable('sid', ''); +		if (defined('NEED_SID') && (empty($session_id) || $this->session_id !== $session_id))  		{  			send_status_line(401, 'Unauthorized');  			redirect(append_sid("{$phpbb_root_path}index.$phpEx")); @@ -370,7 +391,7 @@ class session  				$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') +				if (@$config['referer_validation'] && strtolower($request->server('REQUEST_METHOD')) !== 'get')  				{  					$referer_valid = $this->validate_referer($check_referer_path);  				} @@ -424,9 +445,7 @@ class session  							$db->sql_return_on_error(true); -							$sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " -								WHERE session_id = '" . $db->sql_escape($this->session_id) . "'"; -							$result = $db->sql_query($sql); +							$this->update_session($sql_ary);  							$db->sql_return_on_error(false); @@ -436,9 +455,7 @@ class session  							{  								unset($sql_ary['session_forum_id']); -								$sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " -									WHERE session_id = '" . $db->sql_escape($this->session_id) . "'"; -								$db->sql_query($sql); +								$this->update_session($sql_ary);  							}  							if ($this->data['user_id'] != ANONYMOUS && !empty($config['new_member_post_limit']) && $this->data['user_new'] && $config['new_member_post_limit'] <= $this->data['user_posts']) @@ -457,7 +474,7 @@ class session  				else  				{  					// Added logging temporarly to help debug bugs... -					if (defined('DEBUG_EXTRA') && $this->data['user_id'] != ANONYMOUS) +					if (defined('DEBUG') && $this->data['user_id'] != ANONYMOUS)  					{  						if ($referer_valid)  						{ @@ -705,9 +722,7 @@ class session  						$sql_ary['session_forum_id'] = $this->page['forum'];  					} -					$sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " -						WHERE session_id = '" . $db->sql_escape($this->session_id) . "'"; -					$db->sql_query($sql); +					$this->update_session($sql_ary);  					// Update the last visit time  					$sql = 'UPDATE ' . USERS_TABLE . ' @@ -1008,7 +1023,7 @@ class session  			}  			// only called from CRON; should be a safe workaround until the infrastructure gets going -			if (!class_exists('phpbb_captcha_factory')) +			if (!class_exists('phpbb_captcha_factory', false))  			{  				include($phpbb_root_path . "includes/captcha/captcha_factory." . $phpEx);  			} @@ -1443,7 +1458,7 @@ class session  	*/  	function validate_referer($check_script_path = false)  	{ -		global $config; +		global $config, $request;  		// no referer - nothing to validate, user's fault for turning it off (we only check on POST; so meta can't be the reason)  		if (empty($this->referer) || empty($this->host)) @@ -1461,7 +1476,7 @@ class session  		else if ($check_script_path && rtrim($this->page['root_script_path'], '/') !== '')  		{  			$ref = substr($ref, strlen($host)); -			$server_port = (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT'); +			$server_port = $request->server('SERVER_PORT', 0);  			if ($server_port !== 80 && $server_port !== 443 && stripos($ref, ":$server_port") === 0)  			{ @@ -1486,974 +1501,21 @@ class session  			WHERE session_id = \'' . $db->sql_escape($this->session_id) . '\'';  		$db->sql_query($sql);  	} -} - - -/** -* Base user class -* -* This is the overarching class which contains (through session extend) -* all methods utilised for user functionality during a session. -* -* @package phpBB3 -*/ -class user extends session -{ -	var $lang = array(); -	var $help = array(); -	var $theme = array(); -	var $date_format; -	var $timezone; -	var $dst; - -	var $lang_name = false; -	var $lang_id = false; -	var $lang_path; -	var $img_lang; -	var $img_array = array(); - -	// Able to add new options (up to id 31) -	var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10, 'sig_bbcode' => 15, 'sig_smilies' => 16, 'sig_links' => 17); - -	/** -	* Constructor to set the lang path -	*/ -	function user() -	{ -		global $phpbb_root_path; - -		$this->lang_path = $phpbb_root_path . 'language/'; -	} - -	/** -	* Function to set custom language path (able to use directory outside of phpBB) -	* -	* @param string $lang_path New language path used. -	* @access public -	*/ -	function set_custom_lang_path($lang_path) -	{ -		$this->lang_path = $lang_path; - -		if (substr($this->lang_path, -1) != '/') -		{ -			$this->lang_path .= '/'; -		} -	} - -	/** -	* Setup basic user-specific items (style, language, ...) -	*/ -	function setup($lang_set = false, $style = false) -	{ -		global $db, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache; - -		if ($this->data['user_id'] != ANONYMOUS) -		{ -			$this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']); - -			$this->date_format = $this->data['user_dateformat']; -			$this->timezone = $this->data['user_timezone'] * 3600; -			$this->dst = $this->data['user_dst'] * 3600; -		} -		else -		{ -			$this->lang_name = basename($config['default_lang']); -			$this->date_format = $config['default_dateformat']; -			$this->timezone = $config['board_timezone'] * 3600; -			$this->dst = $config['board_dst'] * 3600; - -			/** -			* If a guest user is surfing, we try to guess his/her language first by obtaining the browser language -			* If re-enabled we need to make sure only those languages installed are checked -			* Commented out so we do not loose the code. - -			if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) -			{ -				$accept_lang_ary = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); - -				foreach ($accept_lang_ary as $accept_lang) -				{ -					// Set correct format ... guess full xx_YY form -					$accept_lang = substr($accept_lang, 0, 2) . '_' . strtoupper(substr($accept_lang, 3, 2)); -					$accept_lang = basename($accept_lang); - -					if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx")) -					{ -						$this->lang_name = $config['default_lang'] = $accept_lang; -						break; -					} -					else -					{ -						// No match on xx_YY so try xx -						$accept_lang = substr($accept_lang, 0, 2); -						$accept_lang = basename($accept_lang); - -						if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx")) -						{ -							$this->lang_name = $config['default_lang'] = $accept_lang; -							break; -						} -					} -				} -			} -			*/ -		} - -		// We include common language file here to not load it every time a custom language file is included -		$lang = &$this->lang; - -		// Do not suppress error if in DEBUG_EXTRA mode -		$include_result = (defined('DEBUG_EXTRA')) ? (include $this->lang_path . $this->lang_name . "/common.$phpEx") : (@include $this->lang_path . $this->lang_name . "/common.$phpEx"); - -		if ($include_result === false) -		{ -			die('Language file ' . $this->lang_path . $this->lang_name . "/common.$phpEx" . " couldn't be opened."); -		} - -		$this->add_lang($lang_set); -		unset($lang_set); - -		if (!empty($_GET['style']) && $auth->acl_get('a_styles') && !defined('ADMIN_START')) -		{ -			global $SID, $_EXTRA_URL; - -			$style = request_var('style', 0); -			$SID .= '&style=' . $style; -			$_EXTRA_URL = array('style=' . $style); -		} -		else -		{ -			// Set up style -			$style = ($style) ? $style : ((!$config['override_user_style']) ? $this->data['user_style'] : $config['default_style']); -		} - -		$sql = 'SELECT s.style_id, t.template_storedb, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name -			FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . " i -			WHERE s.style_id = $style -				AND t.template_id = s.template_id -				AND c.theme_id = s.theme_id -				AND i.imageset_id = s.imageset_id"; -		$result = $db->sql_query($sql, 3600); -		$this->theme = $db->sql_fetchrow($result); -		$db->sql_freeresult($result); - -		// User has wrong style -		if (!$this->theme && $style == $this->data['user_style']) -		{ -			$style = $this->data['user_style'] = $config['default_style']; - -			$sql = 'UPDATE ' . USERS_TABLE . " -				SET user_style = $style -				WHERE user_id = {$this->data['user_id']}"; -			$db->sql_query($sql); - -			$sql = 'SELECT s.style_id, t.template_storedb, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name -				FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . " i -				WHERE s.style_id = $style -					AND t.template_id = s.template_id -					AND c.theme_id = s.theme_id -					AND i.imageset_id = s.imageset_id"; -			$result = $db->sql_query($sql, 3600); -			$this->theme = $db->sql_fetchrow($result); -			$db->sql_freeresult($result); -		} - -		if (!$this->theme) -		{ -			trigger_error('NO_STYLE_DATA', E_USER_ERROR); -		} - -		// Now parse the cfg file and cache it -		$parsed_items = $cache->obtain_cfg_items($this->theme); - -		// We are only interested in the theme configuration for now -		$parsed_items = $parsed_items['theme']; - -		$check_for = array( -			'parse_css_file'	=> (int) 0, -			'pagination_sep'	=> (string) ', ' -		); - -		foreach ($check_for as $key => $default_value) -		{ -			$this->theme[$key] = (isset($parsed_items[$key])) ? $parsed_items[$key] : $default_value; -			settype($this->theme[$key], gettype($default_value)); - -			if (is_string($default_value)) -			{ -				$this->theme[$key] = htmlspecialchars($this->theme[$key]); -			} -		} - -		// If the style author specified the theme needs to be cached -		// (because of the used paths and variables) than make sure it is the case. -		// For example, if the theme uses language-specific images it needs to be stored in db. -		if (!$this->theme['theme_storedb'] && $this->theme['parse_css_file']) -		{ -			$this->theme['theme_storedb'] = 1; - -			$stylesheet = file_get_contents("{$phpbb_root_path}styles/{$this->theme['theme_path']}/theme/stylesheet.css"); -			// Match CSS imports -			$matches = array(); -			preg_match_all('/@import url\(["\'](.*)["\']\);/i', $stylesheet, $matches); - -			if (sizeof($matches)) -			{ -				$content = ''; -				foreach ($matches[0] as $idx => $match) -				{ -					if ($content = @file_get_contents("{$phpbb_root_path}styles/{$this->theme['theme_path']}/theme/" . $matches[1][$idx])) -					{ -						$content = trim($content); -					} -					else -					{ -						$content = ''; -					} -					$stylesheet = str_replace($match, $content, $stylesheet); -				} -				unset($content); -			} - -			$stylesheet = str_replace('./', 'styles/' . $this->theme['theme_path'] . '/theme/', $stylesheet); - -			$sql_ary = array( -				'theme_data'	=> $stylesheet, -				'theme_mtime'	=> time(), -				'theme_storedb'	=> 1 -			); - -			$sql = 'UPDATE ' . STYLES_THEME_TABLE . ' -				SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' -				WHERE theme_id = ' . $this->theme['theme_id']; -			$db->sql_query($sql); - -			unset($sql_ary); -		} - -		$template->set_template(); - -		$this->img_lang = (file_exists($phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . $this->lang_name)) ? $this->lang_name : $config['default_lang']; - -		// Same query in style.php -		$sql = 'SELECT * -			FROM ' . STYLES_IMAGESET_DATA_TABLE . ' -			WHERE imageset_id = ' . $this->theme['imageset_id'] . " -			AND image_filename <> '' -			AND image_lang IN ('" . $db->sql_escape($this->img_lang) . "', '')"; -		$result = $db->sql_query($sql, 3600); - -		$localised_images = false; -		while ($row = $db->sql_fetchrow($result)) -		{ -			if ($row['image_lang']) -			{ -				$localised_images = true; -			} - -			$row['image_filename'] = rawurlencode($row['image_filename']); -			$this->img_array[$row['image_name']] = $row; -		} -		$db->sql_freeresult($result); - -		// there were no localised images, try to refresh the localised imageset for the user's language -		if (!$localised_images) -		{ -			// Attention: this code ignores the image definition list from acp_styles and just takes everything -			// that the config file contains -			$sql_ary = array(); - -			$db->sql_transaction('begin'); - -			$sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . ' -				WHERE imageset_id = ' . $this->theme['imageset_id'] . ' -					AND image_lang = \'' . $db->sql_escape($this->img_lang) . '\''; -			$result = $db->sql_query($sql); - -			if (@file_exists("{$phpbb_root_path}styles/{$this->theme['imageset_path']}/imageset/{$this->img_lang}/imageset.cfg")) -			{ -				$cfg_data_imageset_data = parse_cfg_file("{$phpbb_root_path}styles/{$this->theme['imageset_path']}/imageset/{$this->img_lang}/imageset.cfg"); -				foreach ($cfg_data_imageset_data as $image_name => $value) -				{ -					if (strpos($value, '*') !== false) -					{ -						if (substr($value, -1, 1) === '*') -						{ -							list($image_filename, $image_height) = explode('*', $value); -							$image_width = 0; -						} -						else -						{ -							list($image_filename, $image_height, $image_width) = explode('*', $value); -						} -					} -					else -					{ -						$image_filename = $value; -						$image_height = $image_width = 0; -					} - -					if (strpos($image_name, 'img_') === 0 && $image_filename) -					{ -						$image_name = substr($image_name, 4); -						$sql_ary[] = array( -							'image_name'		=> (string) $image_name, -							'image_filename'	=> (string) $image_filename, -							'image_height'		=> (int) $image_height, -							'image_width'		=> (int) $image_width, -							'imageset_id'		=> (int) $this->theme['imageset_id'], -							'image_lang'		=> (string) $this->img_lang, -						); -					} -				} -			} - -			if (sizeof($sql_ary)) -			{ -				$db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); -				$db->sql_transaction('commit'); -				$cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); - -				add_log('admin', 'LOG_IMAGESET_LANG_REFRESHED', $this->theme['imageset_name'], $this->img_lang); -			} -			else -			{ -				$db->sql_transaction('commit'); -				add_log('admin', 'LOG_IMAGESET_LANG_MISSING', $this->theme['imageset_name'], $this->img_lang); -			} -		} - -		// Call phpbb_user_session_handler() in case external application want to "bend" some variables or replace classes... -		// After calling it we continue script execution... -		phpbb_user_session_handler(); - -		// If this function got called from the error handler we are finished here. -		if (defined('IN_ERROR_HANDLER')) -		{ -			return; -		} - -		// Disable board if the install/ directory is still present -		// For the brave development army we do not care about this, else we need to comment out this everytime we develop locally -		if (!defined('DEBUG_EXTRA') && !defined('ADMIN_START') && !defined('IN_INSTALL') && !defined('IN_LOGIN') && file_exists($phpbb_root_path . 'install') && !is_file($phpbb_root_path . 'install')) -		{ -			// Adjust the message slightly according to the permissions -			if ($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_')) -			{ -				$message = 'REMOVE_INSTALL'; -			} -			else -			{ -				$message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE'; -			} -			trigger_error($message); -		} - -		// Is board disabled and user not an admin or moderator? -		if ($config['board_disable'] && !defined('IN_LOGIN') && !$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) -		{ -			if ($this->data['is_bot']) -			{ -				send_status_line(503, 'Service Unavailable'); -			} - -			$message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE'; -			trigger_error($message); -		} - -		// Is load exceeded? -		if ($config['limit_load'] && $this->load !== false) -		{ -			if ($this->load > floatval($config['limit_load']) && !defined('IN_LOGIN') && !defined('IN_ADMIN')) -			{ -				// Set board disabled to true to let the admins/mods get the proper notification -				$config['board_disable'] = '1'; - -				if (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) -				{ -					if ($this->data['is_bot']) -					{ -						send_status_line(503, 'Service Unavailable'); -					} -					trigger_error('BOARD_UNAVAILABLE'); -				} -			} -		} - -		if (isset($this->data['session_viewonline'])) -		{ -			// Make sure the user is able to hide his session -			if (!$this->data['session_viewonline']) -			{ -				// Reset online status if not allowed to hide the session... -				if (!$auth->acl_get('u_hideonline')) -				{ -					$sql = 'UPDATE ' . SESSIONS_TABLE . ' -						SET session_viewonline = 1 -						WHERE session_user_id = ' . $this->data['user_id']; -					$db->sql_query($sql); -					$this->data['session_viewonline'] = 1; -				} -			} -			else if (!$this->data['user_allow_viewonline']) -			{ -				// the user wants to hide and is allowed to  -> cloaking device on. -				if ($auth->acl_get('u_hideonline')) -				{ -					$sql = 'UPDATE ' . SESSIONS_TABLE . ' -						SET session_viewonline = 0 -						WHERE session_user_id = ' . $this->data['user_id']; -					$db->sql_query($sql); -					$this->data['session_viewonline'] = 0; -				} -			} -		} - - -		// Does the user need to change their password? If so, redirect to the -		// ucp profile reg_details page ... of course do not redirect if we're already in the ucp -		if (!defined('IN_ADMIN') && !defined('ADMIN_START') && $config['chg_passforce'] && !empty($this->data['is_registered']) && $auth->acl_get('u_chgpasswd') && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400)) -		{ -			if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != "ucp.$phpEx") -			{ -				redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=profile&mode=reg_details')); -			} -		} - -		return; -	}  	/** -	* More advanced language substitution -	* Function to mimic sprintf() with the possibility of using phpBB's language system to substitute nullar/singular/plural forms. -	* Params are the language key and the parameters to be substituted. -	* This function/functionality is inspired by SHS` and Ashe. +	* Update the session data  	* -	* Example call: <samp>$user->lang('NUM_POSTS_IN_QUEUE', 1);</samp> +	* @param array $session_data associative array of session keys to be updated +	* @param string $session_id optional session_id, defaults to current user's session_id  	*/ -	function lang() -	{ -		$args = func_get_args(); -		$key = $args[0]; - -		if (is_array($key)) -		{ -			$lang = &$this->lang[array_shift($key)]; - -			foreach ($key as $_key) -			{ -				$lang = &$lang[$_key]; -			} -		} -		else -		{ -			$lang = &$this->lang[$key]; -		} - -		// Return if language string does not exist -		if (!isset($lang) || (!is_string($lang) && !is_array($lang))) -		{ -			return $key; -		} - -		// If the language entry is a string, we simply mimic sprintf() behaviour -		if (is_string($lang)) -		{ -			if (sizeof($args) == 1) -			{ -				return $lang; -			} - -			// Replace key with language entry and simply pass along... -			$args[0] = $lang; -			return call_user_func_array('sprintf', $args); -		} - -		// It is an array... now handle different nullar/singular/plural forms -		$key_found = false; - -		// We now get the first number passed and will select the key based upon this number -		for ($i = 1, $num_args = sizeof($args); $i < $num_args; $i++) -		{ -			if (is_int($args[$i])) -			{ -				$numbers = array_keys($lang); - -				foreach ($numbers as $num) -				{ -					if ($num > $args[$i]) -					{ -						break; -					} - -					$key_found = $num; -				} -				break; -			} -		} - -		// Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form) -		if ($key_found === false) -		{ -			$numbers = array_keys($lang); -			$key_found = end($numbers); -		} - -		// Use the language string we determined and pass it to sprintf() -		$args[0] = $lang[$key_found]; -		return call_user_func_array('sprintf', $args); -	} - -	/** -	* Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion) -	* -	* @param mixed $lang_set specifies the language entries to include -	* @param bool $use_db internal variable for recursion, do not use -	* @param bool $use_help internal variable for recursion, do not use -	* -	* Examples: -	* <code> -	* $lang_set = array('posting', 'help' => 'faq'); -	* $lang_set = array('posting', 'viewtopic', 'help' => array('bbcode', 'faq')) -	* $lang_set = array(array('posting', 'viewtopic'), 'help' => array('bbcode', 'faq')) -	* $lang_set = 'posting' -	* $lang_set = array('help' => 'faq', 'db' => array('help:faq', 'posting')) -	* </code> -	*/ -	function add_lang($lang_set, $use_db = false, $use_help = false) -	{ -		global $phpEx; - -		if (is_array($lang_set)) -		{ -			foreach ($lang_set as $key => $lang_file) -			{ -				// Please do not delete this line. -				// We have to force the type here, else [array] language inclusion will not work -				$key = (string) $key; - -				if ($key == 'db') -				{ -					$this->add_lang($lang_file, true, $use_help); -				} -				else if ($key == 'help') -				{ -					$this->add_lang($lang_file, $use_db, true); -				} -				else if (!is_array($lang_file)) -				{ -					$this->set_lang($this->lang, $this->help, $lang_file, $use_db, $use_help); -				} -				else -				{ -					$this->add_lang($lang_file, $use_db, $use_help); -				} -			} -			unset($lang_set); -		} -		else if ($lang_set) -		{ -			$this->set_lang($this->lang, $this->help, $lang_set, $use_db, $use_help); -		} -	} - -	/** -	* Set language entry (called by add_lang) -	* @access private -	*/ -	function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false) -	{ -		global $phpEx; - -		// Make sure the language name is set (if the user setup did not happen it is not set) -		if (!$this->lang_name) -		{ -			global $config; -			$this->lang_name = basename($config['default_lang']); -		} - -		// $lang == $this->lang -		// $help == $this->help -		// - add appropriate variables here, name them as they are used within the language file... -		if (!$use_db) -		{ -			if ($use_help && strpos($lang_file, '/') !== false) -			{ -				$language_filename = $this->lang_path . $this->lang_name . '/' . substr($lang_file, 0, stripos($lang_file, '/') + 1) . 'help_' . substr($lang_file, stripos($lang_file, '/') + 1) . '.' . $phpEx; -			} -			else -			{ -				$language_filename = $this->lang_path . $this->lang_name . '/' . (($use_help) ? 'help_' : '') . $lang_file . '.' . $phpEx; -			} - -			if (!file_exists($language_filename)) -			{ -				global $config; - -				if ($this->lang_name == 'en') -				{ -					// The user's selected language is missing the file, the board default's language is missing the file, and the file doesn't exist in /en. -					$language_filename = str_replace($this->lang_path . 'en', $this->lang_path . $this->data['user_lang'], $language_filename); -					trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR); -				} -				else if ($this->lang_name == basename($config['default_lang'])) -				{ -					// Fall back to the English Language -					$this->lang_name = 'en'; -					$this->set_lang($lang, $help, $lang_file, $use_db, $use_help); -				} -				else if ($this->lang_name == $this->data['user_lang']) -				{ -					// Fall back to the board default language -					$this->lang_name = basename($config['default_lang']); -					$this->set_lang($lang, $help, $lang_file, $use_db, $use_help); -				} - -				// Reset the lang name -				$this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']); -				return; -			} - -			// Do not suppress error if in DEBUG_EXTRA mode -			$include_result = (defined('DEBUG_EXTRA')) ? (include $language_filename) : (@include $language_filename); - -			if ($include_result === false) -			{ -				trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR); -			} -		} -		else if ($use_db) -		{ -			// Get Database Language Strings -			// Put them into $lang if nothing is prefixed, put them into $help if help: is prefixed -			// For example: help:faq, posting -		} -	} - -	/** -	* Format user date -	* -	* @param int $gmepoch unix timestamp -	* @param string $format date format in date() notation. | used to indicate relative dates, for example |d m Y|, h:i is translated to Today, h:i. -	* @param bool $forcedate force non-relative date format. -	* -	* @return mixed translated date -	*/ -	function format_date($gmepoch, $format = false, $forcedate = false) -	{ -		static $midnight; -		static $date_cache; - -		$format = (!$format) ? $this->date_format : $format; -		$now = time(); -		$delta = $now - $gmepoch; - -		if (!isset($date_cache[$format])) -		{ -			// Is the user requesting a friendly date format (i.e. 'Today 12:42')? -			$date_cache[$format] = array( -				'is_short'		=> strpos($format, '|'), -				'format_short'	=> substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1), -				'format_long'	=> str_replace('|', '', $format), -				// Filter out values that are not strings (e.g. arrays) for strtr(). -				'lang'			=> array_filter($this->lang['datetime'], 'is_string'), -			); - -			// Short representation of month in format? Some languages use different terms for the long and short format of May -			if ((strpos($format, '\M') === false && strpos($format, 'M') !== false) || (strpos($format, '\r') === false && strpos($format, 'r') !== false)) -			{ -				$date_cache[$format]['lang']['May'] = $this->lang['datetime']['May_short']; -			} -		} - -		// Zone offset -		$zone_offset = $this->timezone + $this->dst; - -		// Show date <= 1 hour ago as 'xx min ago' but not greater than 60 seconds in the future -		// A small tolerence is given for times in the future but in the same minute are displayed as '< than a minute ago' -		if ($delta <= 3600 && $delta > -60 && ($delta >= -5 || (($now / 60) % 60) == (($gmepoch / 60) % 60)) && $date_cache[$format]['is_short'] !== false && !$forcedate && isset($this->lang['datetime']['AGO'])) -		{ -			return $this->lang(array('datetime', 'AGO'), max(0, (int) floor($delta / 60))); -		} - -		if (!$midnight) -		{ -			list($d, $m, $y) = explode(' ', gmdate('j n Y', time() + $zone_offset)); -			$midnight = gmmktime(0, 0, 0, $m, $d, $y) - $zone_offset; -		} - -		if ($date_cache[$format]['is_short'] !== false && !$forcedate && !($gmepoch < $midnight - 86400 || $gmepoch > $midnight + 172800)) -		{ -			$day = false; - -			if ($gmepoch > $midnight + 86400) -			{ -				$day = 'TOMORROW'; -			} -			else if ($gmepoch > $midnight) -			{ -				$day = 'TODAY'; -			} -			else if ($gmepoch > $midnight - 86400) -			{ -				$day = 'YESTERDAY'; -			} - -			if ($day !== false) -			{ -				return str_replace('||', $this->lang['datetime'][$day], strtr(@gmdate($date_cache[$format]['format_short'], $gmepoch + $zone_offset), $date_cache[$format]['lang'])); -			} -		} - -		return strtr(@gmdate($date_cache[$format]['format_long'], $gmepoch + $zone_offset), $date_cache[$format]['lang']); -	} - -	/** -	* Get language id currently used by the user -	*/ -	function get_iso_lang_id() -	{ -		global $config, $db; - -		if (!empty($this->lang_id)) -		{ -			return $this->lang_id; -		} - -		if (!$this->lang_name) -		{ -			$this->lang_name = $config['default_lang']; -		} - -		$sql = 'SELECT lang_id -			FROM ' . LANG_TABLE . " -			WHERE lang_iso = '" . $db->sql_escape($this->lang_name) . "'"; -		$result = $db->sql_query($sql); -		$this->lang_id = (int) $db->sql_fetchfield('lang_id'); -		$db->sql_freeresult($result); - -		return $this->lang_id; -	} - -	/** -	* Get users profile fields -	*/ -	function get_profile_fields($user_id) -	{ -		global $db; - -		if (isset($this->profile_fields)) -		{ -			return; -		} - -		$sql = 'SELECT * -			FROM ' . PROFILE_FIELDS_DATA_TABLE . " -			WHERE user_id = $user_id"; -		$result = $db->sql_query_limit($sql, 1); -		$this->profile_fields = (!($row = $db->sql_fetchrow($result))) ? array() : $row; -		$db->sql_freeresult($result); -	} - -	/** -	* Specify/Get image -	* $suffix is no longer used - we know it. ;) It is there for backward compatibility. -	*/ -	function img($img, $alt = '', $width = false, $suffix = '', $type = 'full_tag') -	{ -		static $imgs; -		global $phpbb_root_path; - -		$img_data = &$imgs[$img]; - -		if (empty($img_data)) -		{ -			if (!isset($this->img_array[$img])) -			{ -				// Do not fill the image to let designers decide what to do if the image is empty -				$img_data = ''; -				return $img_data; -			} - -			// Use URL if told so -			$root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; - -			$path = 'styles/' . rawurlencode($this->theme['imageset_path']) . '/imageset/' . ($this->img_array[$img]['image_lang'] ? $this->img_array[$img]['image_lang'] .'/' : '') . $this->img_array[$img]['image_filename']; - -			$img_data['src'] = $root_path . $path; -			$img_data['width'] = $this->img_array[$img]['image_width']; -			$img_data['height'] = $this->img_array[$img]['image_height']; - -			// We overwrite the width and height to the phpbb logo's width -			// and height here if the contents of the site_logo file are -			// really equal to the phpbb_logo -			// This allows us to change the dimensions of the phpbb_logo without -			// modifying the imageset.cfg and causing a conflict for everyone -			// who modified it for their custom logo on updating -			if ($img == 'site_logo' && file_exists($phpbb_root_path . $path)) -			{ -				global $cache; - -				$img_file_hashes = $cache->get('imageset_site_logo_md5'); - -				if ($img_file_hashes === false) -				{ -					$img_file_hashes = array(); -				} - -				$key = $this->theme['imageset_path'] . '::' . $this->img_array[$img]['image_lang']; -				if (!isset($img_file_hashes[$key])) -				{ -					$img_file_hashes[$key] = md5(file_get_contents($phpbb_root_path . $path)); -					$cache->put('imageset_site_logo_md5', $img_file_hashes); -				} - -				$phpbb_logo_hash = '0c461a32cd3621643105f0d02a772c10'; - -				if ($phpbb_logo_hash == $img_file_hashes[$key]) -				{ -					$img_data['width'] = '149'; -					$img_data['height'] = '52'; -				} -			} -		} - -		$alt = (!empty($this->lang[$alt])) ? $this->lang[$alt] : $alt; - -		switch ($type) -		{ -			case 'src': -				return $img_data['src']; -			break; - -			case 'width': -				return ($width === false) ? $img_data['width'] : $width; -			break; - -			case 'height': -				return $img_data['height']; -			break; - -			default: -				$use_width = ($width === false) ? $img_data['width'] : $width; - -				return '<img src="' . $img_data['src'] . '"' . (($use_width) ? ' width="' . $use_width . '"' : '') . (($img_data['height']) ? ' height="' . $img_data['height'] . '"' : '') . ' alt="' . $alt . '" title="' . $alt . '" />'; -			break; -		} -	} - -	/** -	* Get option bit field from user options. -	* -	* @param int $key option key, as defined in $keyoptions property. -	* @param int $data bit field value to use, or false to use $this->data['user_options'] -	* @return bool true if the option is set in the bit field, false otherwise -	*/ -	function optionget($key, $data = false) -	{ -		$var = ($data !== false) ? $data : $this->data['user_options']; -		return phpbb_optionget($this->keyoptions[$key], $var); -	} - -	/** -	* Set option bit field for user options. -	* -	* @param int $key Option key, as defined in $keyoptions property. -	* @param bool $value True to set the option, false to clear the option. -	* @param int $data Current bit field value, or false to use $this->data['user_options'] -	* @return int|bool If $data is false, the bit field is modified and -	*                  written back to $this->data['user_options'], and -	*                  return value is true if the bit field changed and -	*                  false otherwise. If $data is not false, the new -	*                  bitfield value is returned. -	*/ -	function optionset($key, $value, $data = false) -	{ -		$var = ($data !== false) ? $data : $this->data['user_options']; - -		$new_var = phpbb_optionset($this->keyoptions[$key], $value, $var); - -		if ($data === false) -		{ -			if ($new_var != $var) -			{ -				$this->data['user_options'] = $new_var; -				return true; -			} -			else -			{ -				return false; -			} -		} -		else -		{ -			return $new_var; -		} -	} - -	/** -	* Funtion to make the user leave the NEWLY_REGISTERED system group. -	* @access public -	*/ -	function leave_newly_registered() +	public function update_session($session_data, $session_id = null)  	{  		global $db; -		if (empty($this->data['user_new'])) -		{ -			return false; -		} - -		if (!function_exists('remove_newly_registered')) -		{ -			global $phpbb_root_path, $phpEx; +		$session_id = ($session_id) ? $session_id : $this->session_id; -			include($phpbb_root_path . 'includes/functions_user.' . $phpEx); -		} -		if ($group = remove_newly_registered($this->data['user_id'], $this->data)) -		{ -			$this->data['group_id'] = $group; - -		} -		$this->data['user_permissions'] = ''; -		$this->data['user_new'] = 0; - -		return true; -	} - -	/** -	* Returns all password protected forum ids the user is currently NOT authenticated for. -	* -	* @return array		Array of forum ids -	* @access public -	*/ -	function get_passworded_forums() -	{ -		global $db; - -		$sql = 'SELECT f.forum_id, fa.user_id -			FROM ' . FORUMS_TABLE . ' f -			LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa -				ON (fa.forum_id = f.forum_id -					AND fa.session_id = '" . $db->sql_escape($this->session_id) . "') -			WHERE f.forum_password <> ''"; -		$result = $db->sql_query($sql); - -		$forum_ids = array(); -		while ($row = $db->sql_fetchrow($result)) -		{ -			$forum_id = (int) $row['forum_id']; - -			if ($row['user_id'] != $this->data['user_id']) -			{ -				$forum_ids[$forum_id] = $forum_id; -			} -		} -		$db->sql_freeresult($result); - -		return $forum_ids; +		$sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $session_data) . " +			WHERE session_id = '" . $db->sql_escape($session_id) . "'"; +		$db->sql_query($sql);  	}  } - -?>
\ No newline at end of file | 
