diff options
author | Meik Sievertsen <acydburn@phpbb.com> | 2008-12-25 12:34:24 +0000 |
---|---|---|
committer | Meik Sievertsen <acydburn@phpbb.com> | 2008-12-25 12:34:24 +0000 |
commit | 7396cf6dd4f5f562a01e2ec56a713324d9a5521a (patch) | |
tree | 250d068ad1445d4a8c5704903aa5064b20739d41 /phpBB/includes/classes/user.php | |
parent | 77198630ee26ae8c423ec0d671508a4b18bd7bda (diff) | |
download | forums-7396cf6dd4f5f562a01e2ec56a713324d9a5521a.tar forums-7396cf6dd4f5f562a01e2ec56a713324d9a5521a.tar.gz forums-7396cf6dd4f5f562a01e2ec56a713324d9a5521a.tar.bz2 forums-7396cf6dd4f5f562a01e2ec56a713324d9a5521a.tar.xz forums-7396cf6dd4f5f562a01e2ec56a713324d9a5521a.zip |
changed documentation for the session abstract
add phpbb_user class (what we had in includes/session.php before)
git-svn-id: file:///svn/phpbb/trunk@9228 89ea8834-ac86-4346-8a33-228a782c2dd0
Diffstat (limited to 'phpBB/includes/classes/user.php')
-rw-r--r-- | phpBB/includes/classes/user.php | 1062 |
1 files changed, 1062 insertions, 0 deletions
diff --git a/phpBB/includes/classes/user.php b/phpBB/includes/classes/user.php new file mode 100644 index 0000000000..7a6124136d --- /dev/null +++ b/phpBB/includes/classes/user.php @@ -0,0 +1,1062 @@ +<?php +/** +* +* @package phpBB3 +* @version $Id: user.php 9205 2008-12-18 18:08:57Z acydburn $ +* @copyright (c) 2005, 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* 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 phpbb_user extends phpbb_session +{ + /** + * @var array required phpBB objects + */ + public $phpbb_required = array('config', 'acl', 'db', 'template', 'security', 'system', 'acm', 'api:user'); + + /** + * @var array Optional phpBB objects + */ + public $phpbb_optional = array(); + + /** + * @var array language entries + */ + public $lang = array(); + + /** + * @var array help entries + */ + public $help = array(); + + /** + * @var array theme entries + */ + public $theme = array(); + + /** + * @var string users date format + */ + public $date_format; + + /** + * @var double users time zone + */ + public $timezone; + + /** + * @var int users summer time setting. 0 if not in DST, else DST offset. + */ + public $dst; + + /** + * @var string language name, for example 'en' + */ + public $lang_name = false; + + /** + * @var int the language id for the specified language name + */ + public $lang_id = false; + + /** + * @var string the language path phpBB can find installed languages + */ + public $lang_path; + + /** + * @var string Imageset language name. If no fallback happens it is the same as {@link lang_name lang_name}. + */ + public $img_lang; + + /** + * @var array Holds information about the imageset to build {@link img() images}. + */ + public $img_array = array(); + + /** + * Ablility to add new option (id 7). Enabled user options is stored in $data['user_options']. + * @var array user options defining their possibilities to view flash, images, etc. User options only supports set/unset (true/false) + */ + public $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10); + + /** + * @var array The respective true/false values for the {@link keyoptions keyoptions}. + */ + public $keyvalues = array(); + + /** + * Constructor to set the lang path. Calls parrent::__construct() + * + * @param string $auth_method The authentication method to use, for example 'db' + * @param string $custom_lang_path An optional language pack path. + */ + public function __construct($auth_method, $custom_lang_path = false) + { + parent::__construct(); + + // Init auth object + $method = basename(trim($auth_method)); + $class = 'phpbb_auth_' . $method; + + if (class_exists($class)) + { + $this->auth = new $class(); + } + + // Set language path + $this->lang_path = ($custom_lang_path === false) ? PHPBB_ROOT_PATH . 'language/' : $this->set_custom_lang_path($custom_lang_path); + } + + /** + * Initialize user session + * + * @param bool $update_session_page If true the session page gets updated. This can be set to false to circumvent certain scripts to update the users last visited page. + * @access public + */ + public function init($update_session_page = true) + { + $this->session_begin($update_session_page); + phpbb::$acl->init($this->data); + } + + /** + * Function to set custom language path (able to use directory outside of phpBB) + * + * @param string $lang_path New language path used. + * @access public + */ + 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, ...) + * + * @param string|array $lang_set Language set to setup. Can be a string or an array of language files without a path and extension. Format must match {@link add_lang() add_lang}. + * @param int $style If not set to false this specifies the style id to use. The page will then use the specified style id instead of the default one. + * @access public + */ + public function setup($lang_set = false, $style = false) + { + if ($this->data['user_id'] != ANONYMOUS) + { + $this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common." . PHP_EXT)) ? $this->data['user_lang'] : basename(phpbb::$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(phpbb::$config['default_lang']); + $this->date_format = phpbb::$config['default_dateformat']; + $this->timezone = phpbb::$config['board_timezone'] * 3600; + $this->dst = phpbb::$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." . PHP_EXT)) + { + $this->lang_name = phpbb::$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." . PHP_EXT)) + { + $this->lang_name = phpbb::$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; + + if ((include $this->lang_path . $this->lang_name . "/common." . PHP_EXT) === false) + { + die('Language file ' . $this->lang_path . $this->lang_name . "/common." . PHP_EXT . " couldn't be opened."); + } + + $this->add_lang($lang_set); + unset($lang_set); + + if (request::variable('style', false, false, request::GET) && phpbb::$acl->acl_get('a_styles')) + { + $style = request_var('style', 0); + $this->extra_url = array('style=' . $style); + } + else + { + // Set up style + $style = ($style) ? $style : ((!phpbb::$config['override_user_style']) ? $this->data['user_style'] : phpbb::$config['default_style']); + } + + $sql = 'SELECT s.style_id, 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 = phpbb::$db->sql_query($sql, 3600); + $this->theme = phpbb::$db->sql_fetchrow($result); + phpbb::$db->sql_freeresult($result); + + // User has wrong style + if (!$this->theme && $style == $this->data['user_style']) + { + $style = $this->data['user_style'] = phpbb::$config['default_style']; + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_style = $style + WHERE user_id = {$this->data['user_id']}"; + phpbb::$db->sql_query($sql); + + $sql = 'SELECT s.style_id, 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 = phpbb::$db->sql_query($sql, 3600); + $this->theme = phpbb::$db->sql_fetchrow($result); + phpbb::$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, + // we are only interested in the theme configuration for now + $parsed_items = phpbb_cache::obtain_cfg_item($this->theme, '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 ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE theme_id = ' . $this->theme['theme_id']; + phpbb::$db->sql_query($sql); + + unset($sql_ary); + } + + phpbb::$template->set_template(); + + $this->img_lang = (file_exists(PHPBB_ROOT_PATH . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . $this->lang_name)) ? $this->lang_name : phpbb::$config['default_lang']; + + $sql = 'SELECT image_name, image_filename, image_lang, image_height, image_width + FROM ' . STYLES_IMAGESET_DATA_TABLE . ' + WHERE imageset_id = ' . $this->theme['imageset_id'] . " + AND image_filename <> '' + AND image_lang IN ('" . phpbb::$db->sql_escape($this->img_lang) . "', '')"; + $result = phpbb::$db->sql_query($sql, 3600); + + $localised_images = false; + while ($row = phpbb::$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; + } + phpbb::$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(); + + phpbb::$db->sql_transaction('begin'); + + $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . ' + WHERE imageset_id = ' . $this->theme['imageset_id'] . ' + AND image_lang = \'' . phpbb::$db->sql_escape($this->img_lang) . '\''; + $result = phpbb::$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)) + { + phpbb::$db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); + phpbb::$db->sql_transaction('commit'); + phpbb::$acm->destroy('sql', STYLES_IMAGESET_DATA_TABLE); + + add_log('admin', 'LOG_IMAGESET_LANG_REFRESHED', $this->theme['imageset_name'], $this->img_lang); + } + else + { + phpbb::$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')) + { + // Adjust the message slightly according to the permissions + if (phpbb::$acl->acl_gets('a_', 'm_') || phpbb::$acl->acl_getf_global('m_')) + { + $message = 'REMOVE_INSTALL'; + } + else + { + $message = (!empty(phpbb::$config['board_disable_msg'])) ? phpbb::$config['board_disable_msg'] : 'BOARD_DISABLE'; + } + trigger_error($message); + } + + // Is board disabled and user not an admin or moderator? + if (phpbb::$config['board_disable'] && !defined('IN_LOGIN') && !phpbb::$acl->acl_gets('a_', 'm_') && !phpbb::$acl->acl_getf_global('m_')) + { + header('HTTP/1.1 503 Service Unavailable'); + + $message = (!empty(phpbb::$config['board_disable_msg'])) ? phpbb::$config['board_disable_msg'] : 'BOARD_DISABLE'; + trigger_error($message); + } + + // Is load exceeded? + if (phpbb::$config['limit_load'] && $this->load !== false) + { + if ($this->load > floatval(phpbb::$config['limit_load']) && !defined('IN_LOGIN')) + { + // Set board disabled to true to let the admins/mods get the proper notification + phpbb::$config['board_disable'] = '1'; + + if (!phpbb::$acl->acl_gets('a_', 'm_') && !phpbb::$acl->acl_getf_global('m_')) + { + header('HTTP/1.1 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 (!phpbb::$acl->acl_get('u_hideonline')) + { + $sql = 'UPDATE ' . SESSIONS_TABLE . ' + SET session_viewonline = 1 + WHERE session_user_id = ' . $this->data['user_id']; + phpbb::$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 (phpbb::$acl->acl_get('u_hideonline')) + { + $sql = 'UPDATE ' . SESSIONS_TABLE . ' + SET session_viewonline = 0 + WHERE session_user_id = ' . $this->data['user_id']; + phpbb::$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') && phpbb::$config['chg_passforce'] && $this->data['is_registered'] && phpbb::$acl->acl_get('u_chgpasswd') && $this->data['user_passchg'] < time() - (phpbb::$config['chg_passforce'] * 86400)) + { + if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != 'ucp.' . PHP_EXT) + { + redirect(append_sid('ucp', 'i=profile&mode=reg_details')); + } + } + + return; + } + + /** + * More advanced language substitution + * + * Function to mimic sprintf() with the possibility of using phpBB's language system to substitute nullar/singular/plural forms. + * Params are the language key and the parameters to be substituted. + * This function/functionality was inspired by SHS` and Ashe. + * + * For example: + * <code> + * phpbb::$user->lang('NUM_POSTS_IN_QUEUE', 1); + * </code> + * + * @param string $key The language key to use + * @param mixed $parameter,... An unlimited number of parameter to apply. + * + * @return string Substituted language string + * @see sprintf() + * @access public + */ + public 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; + } + } + } + + // 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) + * + * 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> + * + * @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 + * @access public + */ + public function add_lang($lang_set, $use_db = false, $use_help = false) + { + 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 {@link add_lang() add_lang}) + * + * @param array &$lang A reference to the language array phpbb::$user->lang + * @param array &$help A reference to the language help array phpbb::$user->help + * @param string $lang_file Language filename + * @param bool $use_db True if the database is used for obtaining the information + * @param bool $use_help True if we fetch help entries instead of language entries + * @access private + */ + private function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false) + { + // Make sure the language name is set (if the user setup did not happen it is not set) + if (!$this->lang_name) + { + $this->lang_name = basename(phpbb::$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) . '.' . PHP_EXT; + } + else + { + $language_filename = $this->lang_path . $this->lang_name . '/' . (($use_help) ? 'help_' : '') . $lang_file . '.' . PHP_EXT; + } + + if (!file_exists($language_filename)) + { + 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(phpbb::$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 (file_exists($this->lang_path . $this->data['user_lang'] . '/common.' . PHP_EXT)) + { + // Fall back to the board default language + $this->lang_name = basename(phpbb::$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.' . PHP_EXT)) ? $this->data['user_lang'] : basename(phpbb::$config['default_lang']); + return; + } + + if ((include $language_filename) === 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 to format + * @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. + * @staticvar int $midnight Midnight time offset + * @staticvar array $date_cache array to cache commonly needed structures within this function + * + * @return mixed translated date + * @access public + */ + public 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, '|'), + 'zone_offset' => $this->timezone + $this->dst, + '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']; + } + } + + // Show date <= 1 hour ago as 'xx min ago' + // A small tolerence is given for times in the future and times in the future but in the same minute are displayed as '< than a minute ago' + if ($delta <= 3600 && ($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() + $date_cache[$format]['zone_offset'])); + $midnight = gmmktime(0, 0, 0, $m, $d, $y) - $date_cache[$format]['zone_offset']; + } + + if ($date_cache[$format]['is_short'] !== false && !$forcedate) + { + $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 + $date_cache[$format]['zone_offset']), $date_cache[$format]['lang'])); + } + } + + return strtr(@gmdate($date_cache[$format]['format_long'], $gmepoch + $date_cache[$format]['zone_offset']), $date_cache[$format]['lang']); + } + + /** + * Get language id currently used by the user + * @return int language id + * @access public + */ + public function get_iso_lang_id() + { + if (!empty($this->lang_id)) + { + return $this->lang_id; + } + + if (!$this->lang_name) + { + $this->lang_name = phpbb::$config['default_lang']; + } + + $sql = 'SELECT lang_id + FROM ' . LANG_TABLE . " + WHERE lang_iso = '" . phpbb::$db->sql_escape($this->lang_name) . "'"; + $result = phpbb::$db->sql_query($sql); + $this->lang_id = (int) phpbb::$db->sql_fetchfield('lang_id'); + phpbb::$db->sql_freeresult($result); + + return $this->lang_id; + } + + /** + * Get users profile fields + * + * @param int $user_id user id. If not specified the current users profile fields are grabbed. + * @return array profile fields. If the current user then they are also stored as property $profile_fields. + * @access public + */ + public function get_profile_fields($user_id = false) + { + $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id; + + if (isset($this->profile_fields) && $user_id === $this->data['user_id']) + { + return $this->profile_fields; + } + + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_DATA_TABLE . " + WHERE user_id = $user_id"; + $result = phpbb::$db->sql_query_limit($sql, 1); + $row = phpbb::$db->sql_fetchrow($result); + phpbb::$db->sql_freeresult($result); + + if ($user_id === $this->data['user_id']) + { + $this->profile_fields = (!$row) ? array() : $row; + } + + return $row; + } + + /** + * Specify/Get image from style imageset + * + * @param string $img the imageset image key name + * @param string $alt an optional alternative image attribute. If a corresponding language key exist it will be used: phpbb::$user->lang[$alt] + * @param string $type the preferred type to return. Allowed types are: full_tag, src, width, height + * @param int $width set image width + * @return mixed returns the preferred type from $type + * @access public + */ + public function img($img, $alt = '', $type = 'full_tag', $width = false) + { + static $imgs; + + $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; + } + + $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']; + $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. + * + * @param string $key the option key from {@link $keyoptions keyoptions} + * @param int $data optional user options bitfield. If not specified then {@link $data $data['user_options']} is used. + * @return bool corresponding option value returned. Is the option enabled or disabled. + * @access public + */ + public function optionget($key, $data = false) + { + if ($data !== false) + { + return $data & 1 << $this->keyoptions[$key]; + } + + if (!isset($this->keyvalues[$key])) + { + $this->keyvalues[$key] = $this->data['user_options'] & 1 << $this->keyoptions[$key]; + } + + return $this->keyvalues[$key]; + } + + /** + * Set option bit field for user options. + * + * @param string $key the option key from {@link $keyoptions keyoptions} + * @param bool $value true to enable the option, false to disable it + * @param int $data optional user options bitfield. If not specified then {@link $data $data['user_options']} is used. + * @return bool the new user options bitfield is returned if $data is specified, else: false is returned if user options not changed, true if changed. + * @access public + */ + public 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'] = $this->keyvalues[$key] = $var; + return true; + } + + return $var; + } + + /** + * User login. Log the user in. + * + * @param string $username the specified user name + * @param string $password the specified password + * @param bool $autologin enable/disable persistent login + * @param bool $viewonline If false then the user will be logged in as hidden + * @param bool $admin If true the user requests an admin login + * @return array login result array. This array returns results to the login script to show errors, notices, confirmations. + * @access public + */ + public function login($username, $password, $autologin = false, $viewonline = 1, $admin = 0) + { + if ($this->auth === false || !method_exists($this->auth, 'login')) + { + trigger_error('Authentication method not found', E_USER_ERROR); + } + + $login = $this->auth->login($username, $password); + + // If the auth module wants us to create an empty profile do so and then treat the status as LOGIN_SUCCESS + if ($login['status'] == LOGIN_SUCCESS_CREATE_PROFILE) + { + phpbb::$api->user->add($login['user_row'], (isset($login['cp_data'])) ? $login['cp_data'] : false); + + $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type + FROM ' . USERS_TABLE . " + WHERE username_clean = '" . phpbb::$db->sql_escape(utf8_clean_string($username)) . "'"; + $result = phpbb::$db->sql_query($sql); + $row = phpbb::$db->sql_fetchrow($result); + phpbb::$db->sql_freeresult($result); + + if (!$row) + { + return array( + 'status' => LOGIN_ERROR_EXTERNAL_AUTH, + 'error_msg' => 'AUTH_NO_PROFILE_CREATED', + 'user_row' => array('user_id' => ANONYMOUS), + ); + } + + $login = array( + 'status' => LOGIN_SUCCESS, + 'error_msg' => false, + 'user_row' => $row, + ); + } + + // If login succeeded, we will log the user in... else we pass the login array through... + if ($login['status'] == LOGIN_SUCCESS) + { + // We create a new session. The session creation makes sure the old session is killed if there was one. + $result = $this->session_create($login['user_row']['user_id'], $admin, $autologin, $viewonline); + + // Successful session creation + if ($result === true) + { + return array( + 'status' => LOGIN_SUCCESS, + 'error_msg' => false, + 'user_row' => $login['user_row'], + ); + } + + return array( + 'status' => LOGIN_BREAK, + 'error_msg' => $result, + 'user_row' => $login['user_row'], + ); + } + + return $login; + } +} + +?>
\ No newline at end of file |