phpBB

Code Changes

File: includes/session.php

  Unmodified   Added   Modified   Removed
Line 68Line 68

foreach ($args as $key => $argument)
{


foreach ($args as $key => $argument)
{

			if (strpos($argument, 'sid=') === 0 || strpos($argument, '_f_=') === 0)

			if (strpos($argument, 'sid=') === 0)

			{
continue;
}


			{
continue;
}


			$use_args[str_replace($find, $replace, $key)] = str_replace($find, $replace, $argument);

			$use_args[] = str_replace($find, $replace, $argument);

		}
unset($args);


		}
unset($args);


Line 83Line 83
		$query_string = trim(implode('&', $use_args));

// basenamed page name (for example: index.php)

		$query_string = trim(implode('&', $use_args));

// basenamed page name (for example: index.php)

		$page_name = basename($script_name);

		$page_name = (substr($script_name, -1, 1) == '/') ? '' : basename($script_name);

		$page_name = urlencode(htmlspecialchars($page_name));

// current directory within the phpBB root (for example: adm)

		$page_name = urlencode(htmlspecialchars($page_name));

// current directory within the phpBB root (for example: adm)

Line 120Line 120

$script_path .= (substr($script_path, -1, 1) == '/') ? '' : '/';
$root_script_path .= (substr($root_script_path, -1, 1) == '/') ? '' : '/';


$script_path .= (substr($script_path, -1, 1) == '/') ? '' : '/';
$root_script_path .= (substr($root_script_path, -1, 1) == '/') ? '' : '/';

 

$forum_id = (isset($_REQUEST['f']) && $_REQUEST['f'] > 0 && $_REQUEST['f'] < 16777215) ? (int) $_REQUEST['f'] : 0;


$page_array += array(
'page_name' => $page_name,


$page_array += array(
'page_name' => $page_name,

Line 129Line 131
			'script_path'		=> str_replace(' ', '%20', htmlspecialchars($script_path)),
'root_script_path' => str_replace(' ', '%20', htmlspecialchars($root_script_path)),


			'script_path'		=> str_replace(' ', '%20', htmlspecialchars($script_path)),
'root_script_path' => str_replace(' ', '%20', htmlspecialchars($root_script_path)),


			'page'				=> $page


			'page'				=> $page,
'forum' => $forum_id,

		);

return $page_array;

		);

return $page_array;

 
	}

/**
* Get valid hostname/port. HTTP_HOST is used, SERVER_NAME if HTTP_HOST not present.
*/
function extract_current_hostname()
{
global $config;

// Get hostname
$host = (!empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME'));

// Should be a string and lowered
$host = (string) strtolower($host);

// If host is equal the cookie domain or the server name (if config is set), then we assume it is valid
if ((isset($config['cookie_domain']) && $host === $config['cookie_domain']) || (isset($config['server_name']) && $host === $config['server_name']))
{
return $host;
}

// Is the host actually a IP? If so, we use the IP... (IPv4)
if (long2ip(ip2long($host)) === $host)
{
return $host;
}

// Now return the hostname (this also removes any port definition). The http:// is prepended to construct a valid URL, hosts never have a scheme assigned
$host = @parse_url('http://' . $host);
$host = (!empty($host['host'])) ? $host['host'] : '';

// Remove any portions not removed by parse_url (#)
$host = str_replace('#', '', $host);

// If, by any means, the host is now empty, we will use a "best approach" way to guess one
if (empty($host))
{
if (!empty($config['server_name']))
{
$host = $config['server_name'];
}
else if (!empty($config['cookie_domain']))
{
$host = (strpos($config['cookie_domain'], '.') === 0) ? substr($config['cookie_domain'], 1) : $config['cookie_domain'];
}
else
{
// Set to OS hostname or localhost
$host = (function_exists('php_uname')) ? php_uname('n') : 'localhost';
}
}

// It may be still no valid host, but for sure only a hostname (we may further expand on the cookie domain... if set)
return $host;

	}

/**

	}

/**

Line 157Line 214
		$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->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->forwarded_for		= (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? (string) $_SERVER['HTTP_X_FORWARDED_FOR'] : '';
$this->host = (!empty($_SERVER['HTTP_HOST'])) ? (string) $_SERVER['HTTP_HOST'] : 'localhost';



		$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 = $this->extract_current_hostname();

		$this->page					= $this->extract_current_page($phpbb_root_path);

// if the forwarded for header shall be checked we have to validate its contents
if ($config['forwarded_for_check'])
{

		$this->page					= $this->extract_current_page($phpbb_root_path);

// if the forwarded for header shall be checked we have to validate its contents
if ($config['forwarded_for_check'])
{

			$this->forwarded_for = preg_replace('#, +#', ', ', $this->forwarded_for);

			$this->forwarded_for = preg_replace('# {2,}#', ' ', str_replace(',', ' ', $this->forwarded_for));


// split the list of IPs


// split the list of IPs

			$ips = explode(', ', $this->forwarded_for);

			$ips = explode(' ', $this->forwarded_for);

			foreach ($ips as $ip)
{
// check IPv4 first, the IPv6 is hopefully only going to be used very seldomly

			foreach ($ips as $ip)
{
// check IPv4 first, the IPv6 is hopefully only going to be used very seldomly

Line 179Line 238
				}
}
}

				}
}
}


// Add forum to the page for tracking online users - also adding a "x" to the end to properly identify the number
$this->page['page'] .= (isset($_REQUEST['f'])) ? ((strpos($this->page['page'], '?') !== false) ? '&' : '?') . '_f_=' . (int) $_REQUEST['f'] . 'x' : '';


		else
{
$this->forwarded_for = '';
}


if (isset($_COOKIE[$config['cookie_name'] . '_sid']) || isset($_COOKIE[$config['cookie_name'] . '_u']))
{


if (isset($_COOKIE[$config['cookie_name'] . '_sid']) || isset($_COOKIE[$config['cookie_name'] . '_u']))
{

Line 209Line 269

// 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.


// 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'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : '';






































		$this->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? (string) $_SERVER['REMOTE_ADDR'] : '';
$this->ip = preg_replace('# {2,}#', ' ', str_replace(',', ' ', $this->ip));

// split the list of IPs
$ips = explode(' ', trim($this->ip));

// Default IP if REMOTE_ADDR is invalid
$this->ip = '127.0.0.1';

foreach ($ips as $ip)
{
if (preg_match(get_preg_expression('ipv4'), $ip))
{
$this->ip = $ip;
}
else if (preg_match(get_preg_expression('ipv6'), $ip))
{
// Quick check for IPv4-mapped address in IPv6
if (stripos($ip, '::ffff:') === 0)
{
$ipv4 = substr($ip, 7);

if (preg_match(get_preg_expression('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'])
{

		$this->load = false;

// Load limit check (if applicable)
if ($config['limit_load'] || $config['limit_search_load'])
{

			if ($load = @file_get_contents('/proc/loadavg'))

			if ((function_exists('sys_getloadavg') && $load = sys_getloadavg()) || ($load = explode(' ', @file_get_contents('/proc/loadavg'))))

			{

			{

				$this->load = array_slice(explode(' ', $load), 0, 1);

				$this->load = array_slice($load, 0, 1);

				$this->load = floatval($this->load[0]);
}
else

				$this->load = floatval($this->load[0]);
}
else

Line 227Line 324
			}
}


			}
}


		// Is session_id is set or session_id is set and matches the url param if required
if (!empty($this->session_id) && (!defined('NEED_SID') || (isset($_GET['sid']) && $this->session_id === $_GET['sid'])))








		// if no session id is set, redirect to index.php
if (defined('NEED_SID') && (!isset($_GET['sid']) || $this->session_id !== $_GET['sid']))
{
send_status_line(401, 'Unauthorized');
redirect(append_sid("{$phpbb_root_path}index.$phpEx"));
}

// if session id is set
if (!empty($this->session_id))

		{
$sql = 'SELECT u.*, s.*
FROM ' . SESSIONS_TABLE . ' s, ' . USERS_TABLE . " u

		{
$sql = 'SELECT u.*, s.*
FROM ' . SESSIONS_TABLE . ' s, ' . USERS_TABLE . " u

Line 256Line 360
					$u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check']));
}


					$u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check']));
}


				$s_browser = ($config['browser_check']) ? strtolower(substr($this->data['session_browser'], 0, 149)) : '';
$u_browser = ($config['browser_check']) ? strtolower(substr($this->browser, 0, 149)) : '';

				$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) : '';



$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)












				// 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 && $s_forwarded_for === $u_forwarded_for && $referer_valid)

				{
$session_expired = false;


				{
$session_expired = false;


Line 306Line 421
							if ($this->update_session_page)
{
$sql_ary['session_page'] = substr($this->page['page'], 0, 199);

							if ($this->update_session_page)
{
$sql_ary['session_page'] = substr($this->page['page'], 0, 199);

 
								$sql_ary['session_forum_id'] = $this->page['forum'];

							}

							}

 

$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);

$db->sql_return_on_error(false);

// If the database is not yet updated, there will be an error due to the session_forum_id
// @todo REMOVE for 3.0.2
if ($result === false)
{
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);


$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);

 
							}

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'])
{
$this->leave_newly_registered();
}

						}

$this->data['is_registered'] = ($this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == USER_NORMAL || $this->data['user_type'] == USER_FOUNDER)) ? true : false;

						}

$this->data['is_registered'] = ($this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == USER_NORMAL || $this->data['user_type'] == USER_FOUNDER)) ? true : false;

Line 324Line 460
				{
// Added logging temporarly to help debug bugs...
if (defined('DEBUG_EXTRA') && $this->data['user_id'] != ANONYMOUS)

				{
// Added logging temporarly 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, htmlspecialchars($u_forwarded_for), htmlspecialchars($s_forwarded_for));

					{
add_log('critical', 'LOG_IP_BROWSER_FORWARDED_CHECK', $u_ip, $s_ip, $u_browser, $s_browser, htmlspecialchars($u_forwarded_for), htmlspecialchars($s_forwarded_for));

 
						}
else
{
add_log('critical', 'LOG_REFERER_INVALID', $this->referer);
}

					}
}
}

					}
}
}

Line 388Line 531

foreach (explode(',', $row['bot_ip']) as $bot_ip)
{


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'];

					if (strpos($this->ip, $bot_ip) === 0)
{
$bot = (int) $row['user_id'];

Line 408Line 558
		$method = 'autologin_' . $method;
if (function_exists($method))
{

		$method = 'autologin_' . $method;
if (function_exists($method))
{

			$this->data = $method();






			$user_data = $method();

if ($user_id === false || (isset($user_data['user_id']) && $user_id == $user_data['user_id']))
{
$this->data = $user_data;
}


if (sizeof($this->data))
{


if (sizeof($this->data))
{

Line 428Line 583
					AND k.user_id = u.user_id
AND k.key_id = '" . $db->sql_escape(md5($this->cookie_data['k'])) . "'";
$result = $db->sql_query($sql);

					AND k.user_id = u.user_id
AND k.key_id = '" . $db->sql_escape(md5($this->cookie_data['k'])) . "'";
$result = $db->sql_query($sql);

			$this->data = $db->sql_fetchrow($result);
$db->sql_freeresult($result);




			$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;
}

			$bot = false;
}

		else if ($user_id !== false && !sizeof($this->data))






$db->sql_freeresult($result);
}

if ($user_id !== false && !sizeof($this->data))

		{
$this->cookie_data['k'] = '';
$this->cookie_data['u'] = $user_id;

		{
$this->cookie_data['k'] = '';
$this->cookie_data['u'] = $user_id;

Line 445Line 607
			$this->data = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
$bot = false;

			$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:

		}

// If no data was returned one or more of the following occurred:

Line 502Line 672
			}
else
{

			}
else
{

				$ips = explode(', ', $this->forwarded_for);

				$ips = explode(' ', $this->forwarded_for);

				$ips[] = $this->ip;
$this->check_ban($this->data['user_id'], $ips);
}

				$ips[] = $this->ip;
$this->check_ban($this->data['user_id'], $ips);
}

Line 526Line 696
				$u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check']));
}


				$u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check']));
}


			$s_browser = ($config['browser_check']) ? strtolower(substr($this->data['session_browser'], 0, 149)) : '';
$u_browser = ($config['browser_check']) ? strtolower(substr($this->browser, 0, 149)) : '';

			$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) : '';


$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) : '';

Line 546Line 716
					if ($this->update_session_page)
{
$sql_ary['session_page'] = substr($this->page['page'], 0, 199);

					if ($this->update_session_page)
{
$sql_ary['session_page'] = substr($this->page['page'], 0, 199);

 
						$sql_ary['session_forum_id'] = $this->page['forum'];

					}

$sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "

					}

$sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "

Line 579Line 750
			'session_start'			=> (int) $this->time_now,
'session_last_visit' => (int) $this->data['session_last_visit'],
'session_time' => (int) $this->time_now,

			'session_start'			=> (int) $this->time_now,
'session_last_visit' => (int) $this->data['session_last_visit'],
'session_time' => (int) $this->time_now,

			'session_browser'		=> (string) substr($this->browser, 0, 149),

			'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_forwarded_for'	=> (string) $this->forwarded_for,
'session_ip' => (string) $this->ip,
'session_autologin' => ($session_autologin) ? 1 : 0,

Line 590Line 761
		if ($this->update_session_page)
{
$sql_ary['session_page'] = (string) substr($this->page['page'], 0, 199);

		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);

		}

$db->sql_return_on_error(true);

Line 604Line 776
			// Limit new sessions in 1 minute period (if required)
if (empty($this->data['session_time']) && $config['active_sessions'])
{

			// 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);

				$sql = 'SELECT COUNT(session_id) AS sessions
FROM ' . SESSIONS_TABLE . '
WHERE session_time >= ' . ($this->time_now - 60);

Line 613Line 787

if ((int) $row['sessions'] > (int) $config['active_sessions'])
{


if ((int) $row['sessions'] > (int) $config['active_sessions'])
{

					header('HTTP/1.1 503 Service Unavailable');

					send_status_line(503, 'Service Unavailable');

					trigger_error('BOARD_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);

		}

$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);


$sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
$db->sql_query($sql);

Line 653Line 841
			$sql = 'SELECT COUNT(session_id) AS sessions
FROM ' . SESSIONS_TABLE . '
WHERE session_user_id = ' . (int) $this->data['user_id'] . '

			$sql = 'SELECT COUNT(session_id) AS sessions
FROM ' . SESSIONS_TABLE . '
WHERE session_user_id = ' . (int) $this->data['user_id'] . '

					AND session_time >= ' . ($this->time_now - $config['form_token_lifetime']);

					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);

			$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);

Line 774Line 962
	*/
function session_gc()
{

	*/
function session_gc()
{

		global $db, $config;

		global $db, $config, $phpbb_root_path, $phpEx;


$batch_size = 10;



$batch_size = 10;


Line 831Line 1019
				$sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
WHERE last_login < ' . (time() - (86400 * (int) $config['max_autologin_time']));
$db->sql_query($sql);

				$sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
WHERE last_login < ' . (time() - (86400 * (int) $config['max_autologin_time']));
$db->sql_query($sql);

			}
$this->confirm_gc();
}

return;

 
	}


	}


	function confirm_gc($type = 0)


			// only called from CRON; should be a safe workaround until the infrastructure gets going
if (!class_exists('phpbb_captcha_factory'))

	{

	{

		global $db, $config;

$sql = 'SELECT DISTINCT c.session_id
FROM ' . CONFIRM_TABLE . ' c
LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id)
WHERE s.session_id IS NULL' .
((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type);
$result = $db->sql_query($sql);

if ($row = $db->sql_fetchrow($result))
{
$sql_in = array();
do
{
$sql_in[] = (string) $row['session_id'];

				include($phpbb_root_path . "includes/captcha/captcha_factory." . $phpEx);















			}

			}

			while ($row = $db->sql_fetchrow($result));

			phpbb_captcha_factory::garbage_collect($config['captcha_plugin']);





			if (sizeof($sql_in))
{
$sql = 'DELETE FROM ' . CONFIRM_TABLE . '
WHERE ' . $db->sql_in_set('session_id', $sql_in);

			$sql = 'DELETE FROM ' . LOGIN_ATTEMPT_TABLE . '
WHERE attempt_time < ' . (time() - (int) $config['ip_login_limit_time']);



				$db->sql_query($sql);
}

				$db->sql_query($sql);
}

		}
$db->sql_freeresult($result);


return;

	}

	}

	

 
	
/**
* Sets a cookie
*

	
/**
* Sets a cookie
*

	* Sets a cookie of the given name with the specified data for the given length of time.





	* Sets a cookie of the given name with the specified data for the given length of time. If no time is specified, a session cookie will be set.
*
* @param string $name Name of the cookie, will be automatically prefixed with the phpBB cookie name. track becomes [cookie_name]_track then.
* @param string $cookiedata The data to hold within the cookie
* @param int $cookietime The expiration time as UNIX timestamp. If 0 is provided, a session cookie is set.

	*/
function set_cookie($name, $cookiedata, $cookietime)
{

	*/
function set_cookie($name, $cookiedata, $cookietime)
{

Line 880Line 1051

$name_data = rawurlencode($config['cookie_name'] . '_' . $name) . '=' . rawurlencode($cookiedata);
$expire = gmdate('D, d-M-Y H:i:s \\G\\M\\T', $cookietime);


$name_data = rawurlencode($config['cookie_name'] . '_' . $name) . '=' . rawurlencode($cookiedata);
$expire = gmdate('D, d-M-Y H:i:s \\G\\M\\T', $cookietime);

		$domain = (!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain'];

		$domain = (!$config['cookie_domain'] || $config['cookie_domain'] == '127.0.0.1' || strpos($config['cookie_domain'], '.') === false) ? '' : '; domain=' . $config['cookie_domain'];





		header('Set-Cookie: ' . $name_data . '; expires=' . $expire . '; path=' . $config['cookie_path'] . $domain . ((!$config['cookie_secure']) ? '' : '; secure') . '; HttpOnly', false);

		header('Set-Cookie: ' . $name_data . (($cookietime) ? '; expires=' . $expire : '') . '; path=' . $config['cookie_path'] . $domain . ((!$config['cookie_secure']) ? '' : '; secure') . '; HttpOnly', false);

	}

/**

	}

/**

Line 1066Line 1237

// To circumvent session_begin returning a valid value and the check_ban() not called on second page view, we kill the session again
$this->session_kill(false);


// To circumvent session_begin returning a valid value and the check_ban() not called on second page view, we kill the session again
$this->session_kill(false);

 

// A very special case... we are within the cron script which is not supposed to print out the ban message... show blank page
if (defined('IN_CRON'))
{
garbage_collection();
exit_handler();
exit;
}


trigger_error($message);
}



trigger_error($message);
}


		return ($banned) ? true : false;

		return ($banned && $ban_row['ban_give_reason']) ? $ban_row['ban_give_reason'] : $banned;

	}

/**

	}

/**

Line 1088Line 1267
		if ($ip === false)
{
$ip = $this->ip;

		if ($ip === false)
{
$ip = $this->ip;

 
		}

// Neither Spamhaus nor Spamcop supports IPv6 addresses.
if (strpos($ip, ':') !== false)
{
return false;

		}

$dnsbl_check = array(

		}

$dnsbl_check = array(

			'list.dsbl.org'			=> 'http://dsbl.org/listing?',
'sbl-xbl.spamhaus.org' => 'http://www.spamhaus.org/query/bl?ip=',

			'sbl.spamhaus.org'	=> 'http://www.spamhaus.org/query/bl?ip=',


		);

if ($mode == 'register')

		);

if ($mode == 'register')

Line 1226Line 1410
	{
global $config, $db;


	{
global $config, $db;


		$user_id = ($user_id === false) ? $this->data['user_id'] : $user_id;

		$user_id = ($user_id === false) ? (int) $this->data['user_id'] : (int) $user_id;


$sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
WHERE user_id = ' . (int) $user_id;
$db->sql_query($sql);


$sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
WHERE user_id = ' . (int) $user_id;
$db->sql_query($sql);

 

// If the user is logged in, update last visit info first before deleting sessions
$sql = 'SELECT session_time, session_page
FROM ' . SESSIONS_TABLE . '
WHERE session_user_id = ' . (int) $user_id . '
ORDER BY session_time DESC';
$result = $db->sql_query_limit($sql, 1);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);

if ($row)
{
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_lastvisit = ' . (int) $row['session_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "'
WHERE user_id = " . (int) $user_id;
$db->sql_query($sql);
}


// Let's also clear any current sessions for the specified user_id
// If it's the current user then we'll leave this session intact
$sql_where = 'session_user_id = ' . (int) $user_id;


// Let's also clear any current sessions for the specified user_id
// If it's the current user then we'll leave this session intact
$sql_where = 'session_user_id = ' . (int) $user_id;

		$sql_where .= ($user_id === $this->data['user_id']) ? " AND session_id <> '" . $db->sql_escape($this->session_id) . "'" : '';

		$sql_where .= ($user_id === (int) $this->data['user_id']) ? " AND session_id <> '" . $db->sql_escape($this->session_id) . "'" : '';


$sql = 'DELETE FROM ' . SESSIONS_TABLE . "
WHERE $sql_where";


$sql = 'DELETE FROM ' . SESSIONS_TABLE . "
WHERE $sql_where";

Line 1243Line 1444

// We're changing the password of the current user and they have a key
// Lets regenerate it to be safe


// We're changing the password of the current user and they have a key
// Lets regenerate it to be safe

		if ($user_id === $this->data['user_id'] && $this->cookie_data['k'])

		if ($user_id === (int) $this->data['user_id'] && $this->cookie_data['k'])

		{
$this->set_login_key($user_id);
}

		{
$this->set_login_key($user_id);
}

 
	}


/**
* Check if the request originated from the same page.
* @param bool $check_script_path If true, the path will be checked as well
*/
function validate_referer($check_script_path = false)
{
global $config;

// 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))
{
return true;
}

$host = htmlspecialchars($this->host);
$ref = substr($this->referer, strpos($this->referer, '://') + 3);

if (!(stripos($ref, $host) === 0) && (!$config['force_server_vars'] || !(stripos($ref, $config['server_name']) === 0)))
{
return false;
}
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');

if ($server_port !== 80 && $server_port !== 443 && stripos($ref, ":$server_port") === 0)
{
$ref = substr($ref, strlen(":$server_port"));
}

if (!(stripos(rtrim($ref, '/'), rtrim($this->page['root_script_path'], '/')) === 0))
{
return false;
}
}

return true;
}


function unset_admin()
{
global $db;
$sql = 'UPDATE ' . SESSIONS_TABLE . '
SET session_admin = 0
WHERE session_id = \'' . $db->sql_escape($this->session_id) . '\'';
$db->sql_query($sql);

	}
}


	}
}


Line 1268Line 1520
	var $timezone;
var $dst;


	var $timezone;
var $dst;


	var $lang_name;

	var $lang_name = false;

	var $lang_id = false;
var $lang_path;
var $img_lang;
var $img_array = array();


	var $lang_id = false;
var $lang_path;
var $img_lang;
var $img_array = array();


	// Able to add new option (id 7)
var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10);
var $keyvalues = 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, ...)


/**
* Setup basic user-specific items (style, language, ...)

Line 1287Line 1564

if ($this->data['user_id'] != ANONYMOUS)
{


if ($this->data['user_id'] != ANONYMOUS)
{

			$this->lang_name = (file_exists($phpbb_root_path . 'language/' . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
$this->lang_path = $phpbb_root_path . 'language/' . $this->lang_name . '/';

			$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->date_format = $this->data['user_dateformat'];
$this->timezone = $this->data['user_timezone'] * 3600;

Line 1297Line 1573
		else
{
$this->lang_name = basename($config['default_lang']);

		else
{
$this->lang_name = basename($config['default_lang']);

			$this->lang_path = $phpbb_root_path . 'language/' . $this->lang_name . '/';

 
			$this->date_format = $config['default_dateformat'];
$this->timezone = $config['board_timezone'] * 3600;
$this->dst = $config['board_dst'] * 3600;

			$this->date_format = $config['default_dateformat'];
$this->timezone = $config['board_timezone'] * 3600;
$this->dst = $config['board_dst'] * 3600;

Line 1317Line 1592
					$accept_lang = substr($accept_lang, 0, 2) . '_' . strtoupper(substr($accept_lang, 3, 2));
$accept_lang = basename($accept_lang);


					$accept_lang = substr($accept_lang, 0, 2) . '_' . strtoupper(substr($accept_lang, 3, 2));
$accept_lang = basename($accept_lang);


					if (file_exists($phpbb_root_path . 'language/' . $accept_lang . "/common.$phpEx"))

					if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx"))

					{
$this->lang_name = $config['default_lang'] = $accept_lang;

					{
$this->lang_name = $config['default_lang'] = $accept_lang;

						$this->lang_path = $phpbb_root_path . 'language/' . $accept_lang . '/';

 
						break;
}
else

						break;
}
else

Line 1329Line 1603
						$accept_lang = substr($accept_lang, 0, 2);
$accept_lang = basename($accept_lang);


						$accept_lang = substr($accept_lang, 0, 2);
$accept_lang = basename($accept_lang);


						if (file_exists($phpbb_root_path . 'language/' . $accept_lang . "/common.$phpEx"))

						if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx"))

						{
$this->lang_name = $config['default_lang'] = $accept_lang;

						{
$this->lang_name = $config['default_lang'] = $accept_lang;

							$this->lang_path = $phpbb_root_path . 'language/' . $accept_lang . '/';

 
							break;
}
}

							break;
}
}

Line 1344Line 1617
		// We include common language file here to not load it every time a custom language file is included
$lang = &$this->lang;


		// We include common language file here to not load it every time a custom language file is included
$lang = &$this->lang;


		if ((@include $this->lang_path . "common.$phpEx") === false)




		// 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_name . "/common.$phpEx" . " couldn't be opened.");

			die('Language file ' . $this->lang_path . $this->lang_name . "/common.$phpEx" . " couldn't be opened.");

		}

$this->add_lang($lang_set);
unset($lang_set);


		}

$this->add_lang($lang_set);
unset($lang_set);


		if (!empty($_GET['style']) && $auth->acl_get('a_styles'))

		if (!empty($_GET['style']) && $auth->acl_get('a_styles') && !defined('ADMIN_START'))

		{
global $SID, $_EXTRA_URL;


		{
global $SID, $_EXTRA_URL;


Line 1366Line 1642
			$style = ($style) ? $style : ((!$config['override_user_style']) ? $this->data['user_style'] : $config['default_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, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name

		$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

			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

Line 1399Line 1675

if (!$this->theme)
{


if (!$this->theme)
{

			trigger_error('Could not get style data', E_USER_ERROR);

			trigger_error('NO_STYLE_DATA', E_USER_ERROR);

		}

// Now parse the cfg file and cache it

		}

// Now parse the cfg file and cache it

Line 1474Line 1750

$this->img_lang = (file_exists($phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . $this->lang_name)) ? $this->lang_name : $config['default_lang'];



$this->img_lang = (file_exists($phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . $this->lang_name)) ? $this->lang_name : $config['default_lang'];


		$sql = 'SELECT image_name, image_filename, image_lang, image_height, image_width


		// Same query in style.php
$sql = 'SELECT *

			FROM ' . STYLES_IMAGESET_DATA_TABLE . '
WHERE imageset_id = ' . $this->theme['imageset_id'] . "

			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);


			AND image_lang IN ('" . $db->sql_escape($this->img_lang) . "', '')";
$result = $db->sql_query($sql, 3600);


Line 1488Line 1766
				$localised_images = true;
}


				$localised_images = true;
}


 
			$row['image_filename'] = rawurlencode($row['image_filename']);

			$this->img_array[$row['image_name']] = $row;
}
$db->sql_freeresult($result);

			$this->img_array[$row['image_name']] = $row;
}
$db->sql_freeresult($result);

Line 1571Line 1850

// 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


// 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'))

		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_'))

		{
// Adjust the message slightly according to the permissions
if ($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))

Line 1588Line 1867
		// 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_'))
{

		// 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_'))
{

			header('HTTP/1.1 503 Service Unavailable');




			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);


$message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE';
trigger_error($message);

Line 1597Line 1879
		// Is load exceeded?
if ($config['limit_load'] && $this->load !== false)
{

		// Is load exceeded?
if ($config['limit_load'] && $this->load !== false)
{

			if ($this->load > floatval($config['limit_load']) && !defined('IN_LOGIN'))

			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_'))
{

			{
// 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_'))
{

					header('HTTP/1.1 503 Service Unavailable');




					if ($this->data['is_bot'])
{
send_status_line(503, 'Service Unavailable');
}

					trigger_error('BOARD_UNAVAILABLE');
}
}

					trigger_error('BOARD_UNAVAILABLE');
}
}

Line 1642Line 1927

// 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


// 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'] && $this->data['is_registered'] && $auth->acl_get('u_chgpasswd') && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400))

		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")
{

		{
if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != "ucp.$phpEx")
{

Line 1651Line 1936
		}

return;

		}

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.
*
* Example call: <samp>$user->lang('NUM_POSTS_IN_QUEUE', 1);</samp>
*/
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);

	}

/**

	}

/**

Line 1714Line 2080
	{
global $phpEx;


	{
global $phpEx;


		// Make sure the language path is set (if the user setup did not happen it is not set)
if (!$this->lang_path)

		// Make sure the language name is set (if the user setup did not happen it is not set)
if (!$this->lang_name)

		{

		{

			global $phpbb_root_path, $config;

$this->lang_path = $phpbb_root_path . 'language/' . basename($config['default_lang']) . '/';

			global $config;
$this->lang_name = basename($config['default_lang']);


		}

// $lang == $this->lang

		}

// $lang == $this->lang

Line 1729Line 2094
		{
if ($use_help && strpos($lang_file, '/') !== false)
{

		{
if ($use_help && strpos($lang_file, '/') !== false)
{

				$language_filename = $this->lang_path . substr($lang_file, 0, stripos($lang_file, '/') + 1) . 'help_' . substr($lang_file, stripos($lang_file, '/') + 1) . '.' . $phpEx;

				$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
{

			}
else
{

				$language_filename = $this->lang_path . (($use_help) ? 'help_' : '') . $lang_file . '.' . $phpEx;

				$language_filename = $this->lang_path . $this->lang_name . '/' . (($use_help) ? 'help_' : '') . $lang_file . '.' . $phpEx;

			}


			}


			if ((@include $language_filename) === false)
































			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 ' . basename($language_filename) . ' couldn\'t be opened.', E_USER_ERROR);

				trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR);

			}
}
else if ($use_db)

			}
}
else if ($use_db)

Line 1751Line 2147

/**
* Format user date


/**
* 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;

	*/
function format_date($gmepoch, $format = false, $forcedate = false)
{
static $midnight;

 
		static $date_cache;





		$lang_dates = $this->lang['datetime'];

 
		$format = (!$format) ? $this->date_format : $format;

		$format = (!$format) ? $this->date_format : $format;

 
		$now = time();
$delta = $now - $gmepoch;





		// Short representation of month in format












		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))
{

		if ((strpos($format, '\M') === false && strpos($format, 'M') !== false) || (strpos($format, '\r') === false && strpos($format, 'r') !== false))
{

			$lang_dates['May'] = $lang_dates['May_short'];


				$date_cache[$format]['lang']['May'] = $this->lang['datetime']['May_short'];
}

		}


		}


		unset($lang_dates['May_short']);


		// Zone offset
$zone_offset = $this->timezone + $this->dst;





		if (!$midnight)



		// 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']))

		{

		{

			list($d, $m, $y) = explode(' ', gmdate('j n Y', time() + $this->timezone + $this->dst));
$midnight = gmmktime(0, 0, 0, $m, $d, $y) - $this->timezone - $this->dst;

			return $this->lang(array('datetime', 'AGO'), max(0, (int) floor($delta / 60)));


		}


		}


		if (strpos($format, '|') === false || ($gmepoch < $midnight - 86400 && !$forcedate) || ($gmepoch > $midnight + 172800 && !$forcedate))

		if (!$midnight)

		{

		{

			return strtr(@gmdate(str_replace('|', '', $format), $gmepoch + $this->timezone + $this->dst), $lang_dates);


			list($d, $m, $y) = explode(' ', gmdate('j n Y', time() + $zone_offset));
$midnight = gmmktime(0, 0, 0, $m, $d, $y) - $zone_offset;

		}


		}


		if ($gmepoch > $midnight + 86400 && !$forcedate)

		if ($date_cache[$format]['is_short'] !== false && !$forcedate && !($gmepoch < $midnight - 86400 || $gmepoch > $midnight + 172800))

		{

		{

			$format = substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1);
return str_replace('||', $this->lang['datetime']['TOMORROW'], strtr(@gmdate($format, $gmepoch + $this->timezone + $this->dst), $lang_dates));




			$day = false;

if ($gmepoch > $midnight + 86400)
{
$day = 'TOMORROW';

		}

		}

		else if ($gmepoch > $midnight && !$forcedate)

			else if ($gmepoch > $midnight)

		{

		{

			$format = substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1);
return str_replace('||', $this->lang['datetime']['TODAY'], strtr(@gmdate($format, $gmepoch + $this->timezone + $this->dst), $lang_dates));

				$day = 'TODAY';


		}

		}

		else if ($gmepoch > $midnight - 86400 && !$forcedate)

			else if ($gmepoch > $midnight - 86400)

		{

		{

			$format = substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1);
return str_replace('||', $this->lang['datetime']['YESTERDAY'], strtr(@gmdate($format, $gmepoch + $this->timezone + $this->dst), $lang_dates));






				$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(str_replace('|', '', $format), $gmepoch + $this->timezone + $this->dst), $lang_dates);

		return strtr(@gmdate($date_cache[$format]['format_long'], $gmepoch + $zone_offset), $date_cache[$format]['lang']);

	}

/**

	}

/**

Line 1846Line 2272

/**
* Specify/Get image


/**
* 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')
{

	*/
function img($img, $alt = '', $width = false, $suffix = '', $type = 'full_tag')
{

Line 1863Line 2290
				return $img_data;
}


				return $img_data;
}


			$img_data['src'] = $phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . ($this->img_array[$img]['image_lang'] ? $this->img_array[$img]['image_lang'] .'/' : '') . $this->img_array[$img]['image_filename'];






			// 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'];

			$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;

		}

$alt = (!empty($this->lang[$alt])) ? $this->lang[$alt] : $alt;

Line 1893Line 2358
	}

/**

	}

/**

	* Get option bit field from user options





	* 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)
{

	*/
function optionget($key, $data = false)
{

		if (!isset($this->keyvalues[$key]))
{
$var = ($data) ? $data : $this->data['user_options'];
$this->keyvalues[$key] = ($var & 1 << $this->keyoptions[$key]) ? true : false;
}

return $this->keyvalues[$key];

		$var = ($data !== false) ? $data : $this->data['user_options'];
return phpbb_optionget($this->keyoptions[$key], $var);






	}

/**

	}

/**

	* Set option bit field for user options










	* 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)
{

	*/
function optionset($key, $value, $data = false)
{

		$var = ($data) ? $data : $this->data['user_options'];

		$var = ($data !== false) ? $data : $this->data['user_options'];





		if ($value && !($var & 1 << $this->keyoptions[$key]))



		$new_var = phpbb_optionset($this->keyoptions[$key], $value, $var);

if ($data === false)

		{

		{

			$var += 1 << $this->keyoptions[$key];




			if ($new_var != $var)
{
$this->data['user_options'] = $new_var;
return true;

		}

		}

		else if (!$value && ($var & 1 << $this->keyoptions[$key]))

			else

		{

		{

			$var -= 1 << $this->keyoptions[$key];


				return false;
}

		}
else
{

		}
else
{

			return ($data) ? $var : false;


			return $new_var;
}

		}


		}


		if (!$data)





	/**
* Funtion to make the user leave the NEWLY_REGISTERED system group.
* @access public
*/
function leave_newly_registered()

		{

		{

			$this->data['user_options'] = $var;





















		global $db;

if (empty($this->data['user_new']))
{
return false;
}

if (!function_exists('remove_newly_registered'))
{
global $phpbb_root_path, $phpEx;

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;
}

			return true;
}

		else









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

		{

		{

			return $var;


















		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;

	}
}


	}
}