aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes/session.php
diff options
context:
space:
mode:
authorOleg Pudeyev <oleg@bsdpower.com>2012-11-06 11:11:27 -0500
committerOleg Pudeyev <oleg@bsdpower.com>2012-11-06 11:11:27 -0500
commit87ea50948ea53c0d1beab5b44badebeae4292d1a (patch)
treedbc99fde4dfc62b84bae60c7e4ab5c02ddbe8a3c /phpBB/includes/session.php
parent5b48df41685da785b082612318ebe7a8012c4149 (diff)
parent44ff9d020fd218cbdb2f07a0d7f85a630367e3c2 (diff)
downloadforums-87ea50948ea53c0d1beab5b44badebeae4292d1a.tar
forums-87ea50948ea53c0d1beab5b44badebeae4292d1a.tar.gz
forums-87ea50948ea53c0d1beab5b44badebeae4292d1a.tar.bz2
forums-87ea50948ea53c0d1beab5b44badebeae4292d1a.tar.xz
forums-87ea50948ea53c0d1beab5b44badebeae4292d1a.zip
Merge remote-tracking branch 'upstream/develop' into feature/prune-users
* upstream/develop: (2171 commits) [ticket/11164] Update composer.phar [ticket/10933] Use inheritDoc, eliminate copy pasted docblocks. [ticket/10933] Dependency inject template context. [ticket/10933] Expanded prose documentation for phpbb_extension_provider. [ticket/10933] Specify empty template path for absolute includephp test. [ticket/10933] Useful documentation for template locate function [ticket/10933] Typo fixes [ticket/10933] Initialize template context when template is constructed. [ticket/11099] Mark acp_ban::display_ban_options() as static. [ticket/11158] Require acl_u_sig for ucp signature module. [ticket/11158] Revert old fix in PHPBB3-10186. [ticket/11159] static public is the currently approved order. [ticket/11157] static public is the currently approved order. [ticket/11157] Fix remaining captcha spam. [ticket/11157] get_captcha_types is an instance method. [ticket/11156] Delete "Misc" tab of forum based permissions + move items [ticket/10848] Move include up. [ticket/11014] Fix old pagination assignment [ticket/11018] Fix several paginations in ACP [ticket/11014] Fix IF statements for new template pagination ... Conflicts: phpBB/includes/functions_user.php
Diffstat (limited to 'phpBB/includes/session.php')
-rw-r--r--phpBB/includes/session.php990
1 files changed, 59 insertions, 931 deletions
diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php
index 893ec2c0cc..257ffb07f6 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();
@@ -41,16 +40,18 @@ class session
*/
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;
}
@@ -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);
@@ -212,9 +213,9 @@ class session
$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);
@@ -222,7 +223,7 @@ class session
// if the forwarded for header shall be checked we have to validate its contents
if ($config['forwarded_for_check'])
{
- $this->forwarded_for = preg_replace('#[ ]{2,}#', ' ', str_replace(array(',', ' '), ' ', $this->forwarded_for));
+ $this->forwarded_for = preg_replace('# {2,}#', ' ', str_replace(',', ' ', $this->forwarded_for));
// split the list of IPs
$ips = explode(' ', $this->forwarded_for);
@@ -268,11 +269,11 @@ 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'])) ? htmlspecialchars((string) $_SERVER['REMOTE_ADDR']) : '';
- $this->ip = preg_replace('#[ ]{2,}#', ' ', str_replace(array(',', ' '), ' ', $this->ip));
+ $this->ip = htmlspecialchars_decode($request->server('REMOTE_ADDR'));
+ $this->ip = preg_replace('# {2,}#', ' ', str_replace(',', ' ', $this->ip));
// split the list of IPs
- $ips = explode(' ', $this->ip);
+ $ips = explode(' ', trim($this->ip));
// Default IP if REMOTE_ADDR is invalid
$this->ip = '127.0.0.1';
@@ -297,26 +298,31 @@ class session
continue;
}
- // check IPv4 first, the IPv6 is hopefully only going to be used very seldomly
- if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip))
+ if (preg_match(get_preg_expression('ipv4'), $ip))
{
- // Just break
- break;
+ $this->ip = $ip;
}
-
- // Quick check for IPv4-mapped address in IPv6
- if (stripos($ip, '::ffff:') === 0)
+ else if (preg_match(get_preg_expression('ipv6'), $ip))
{
- $ipv4 = substr($ip, 7);
-
- if (preg_match(get_preg_expression('ipv4'), $ipv4))
+ // Quick check for IPv4-mapped address in IPv6
+ if (stripos($ip, '::ffff:') === 0)
{
- $ip = $ipv4;
+ $ipv4 = substr($ip, 7);
+
+ if (preg_match(get_preg_expression('ipv4'), $ipv4))
+ {
+ $ip = $ipv4;
+ }
}
- }
- // Use the last in chain
- $this->ip = $ip;
+ $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;
@@ -336,8 +342,16 @@ class session
}
}
- // 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 === request_var('sid', ''))))
+ // if no session id is set, redirect to index.php
+ $session_id = $request->variable('sid', '');
+ if (defined('NEED_SID') && (empty($session_id) || $this->session_id !== $session_id))
+ {
+ send_status_line(401, 'Not authorized');
+ 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
@@ -377,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);
}
@@ -602,6 +616,7 @@ class session
// 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')));
}
@@ -1013,6 +1028,10 @@ class session
include($phpbb_root_path . "includes/captcha/captcha_factory." . $phpEx);
}
phpbb_captcha_factory::garbage_collect($config['captcha_plugin']);
+
+ $sql = 'DELETE FROM ' . LOGIN_ATTEMPT_TABLE . '
+ WHERE attempt_time < ' . (time() - (int) $config['ip_login_limit_time']);
+ $db->sql_query($sql);
}
return;
@@ -1251,6 +1270,12 @@ class session
$ip = $this->ip;
}
+ // Neither Spamhaus nor Spamcop supports IPv6 addresses.
+ if (strpos($ip, ':') !== false)
+ {
+ return false;
+ }
+
$dnsbl_check = array(
'sbl.spamhaus.org' => 'http://www.spamhaus.org/query/bl?ip=',
);
@@ -1433,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))
@@ -1451,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)
{
@@ -1494,900 +1519,3 @@ class session
$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);
- var $keyvalues = array();
-
- /**
- * 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);
-
- $style_request = request_var('style', 0);
- if ($style_request && $auth->acl_get('a_styles') && !defined('ADMIN_START'))
- {
- global $SID, $_EXTRA_URL;
-
- $style = $style_request;
- $SID .= '&amp;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('Could not get 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&amp;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.
- *
- * 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);
- }
-
- /**
- * 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),
- 'lang' => $this->lang['datetime'],
- );
-
- // 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;
-
- $img_data['src'] = $root_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['width'] = $this->img_array[$img]['image_width'];
- $img_data['height'] = $this->img_array[$img]['image_height'];
- }
-
- $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
- */
- 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];
- }
-
- /**
- * Set option bit field for user options
- */
- function optionset($key, $value, $data = false)
- {
- $var = ($data) ? $data : $this->data['user_options'];
-
- if ($value && !($var & 1 << $this->keyoptions[$key]))
- {
- $var += 1 << $this->keyoptions[$key];
- }
- else if (!$value && ($var & 1 << $this->keyoptions[$key]))
- {
- $var -= 1 << $this->keyoptions[$key];
- }
- else
- {
- return ($data) ? $var : false;
- }
-
- if (!$data)
- {
- $this->data['user_options'] = $var;
- return true;
- }
- else
- {
- return $var;
- }
- }
-
- /**
- * Funtion to make the user leave the NEWLY_REGISTERED system group.
- * @access public
- */
- function leave_newly_registered()
- {
- 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;
- }
-}