Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

user.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 26.46 KiB


 001  <?php
 002  /**
 003  *
 004  * This file is part of the phpBB Forum Software package.
 005  *
 006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
 007  * @license GNU General Public License, version 2 (GPL-2.0)
 008  *
 009  * For full copyright and license information, please see
 010  * the docs/CREDITS.txt file.
 011  *
 012  */
 013   
 014  namespace phpbb;
 015   
 016  /**
 017  * Base user class
 018  *
 019  * This is the overarching class which contains (through session extend)
 020  * all methods utilised for user functionality during a session.
 021  */
 022  class user extends \phpbb\session
 023  {
 024      var $lang = array();
 025      var $help = array();
 026      var $style = array();
 027      var $date_format;
 028   
 029      /**
 030      * DateTimeZone object holding the timezone of the user
 031      */
 032      public $timezone;
 033   
 034      /**
 035      * @var string Class name of datetime object
 036      */
 037      protected $datetime;
 038   
 039      var $lang_name = false;
 040      var $lang_id = false;
 041      var $lang_path;
 042      var $img_lang;
 043      var $img_array = array();
 044   
 045      // Able to add new options (up to id 31)
 046      var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'sig_bbcode' => 15, 'sig_smilies' => 16, 'sig_links' => 17);
 047   
 048      /**
 049      * Constructor to set the lang path
 050      * @param string $datetime_class Class name of datetime class
 051      */
 052      function __construct($datetime_class)
 053      {
 054          global $phpbb_root_path;
 055   
 056          $this->lang_path = $phpbb_root_path . 'language/';
 057          $this->datetime = $datetime_class;
 058      }
 059   
 060      /**
 061      * Function to set custom language path (able to use directory outside of phpBB)
 062      *
 063      * @param string $lang_path New language path used.
 064      * @access public
 065      */
 066      function set_custom_lang_path($lang_path)
 067      {
 068          $this->lang_path = $lang_path;
 069   
 070          if (substr($this->lang_path, -1) != '/')
 071          {
 072              $this->lang_path .= '/';
 073          }
 074      }
 075   
 076      /**
 077      * Setup basic user-specific items (style, language, ...)
 078      */
 079      function setup($lang_set = false, $style_id = false)
 080      {
 081          global $db, $request, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache;
 082          global $phpbb_dispatcher;
 083   
 084          if ($this->data['user_id'] != ANONYMOUS)
 085          {
 086              $user_lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
 087              $user_date_format = $this->data['user_dateformat'];
 088              $user_timezone = $this->data['user_timezone'];
 089          }
 090          else
 091          {
 092              $lang_override = $request->variable('language', '');
 093              if ($lang_override)
 094              {
 095                  $this->set_cookie('lang', $lang_override, 0, false);
 096              }
 097              else
 098              {
 099                  $lang_override = $request->variable($config['cookie_name'] . '_lang', '', true, \phpbb\request\request_interface::COOKIE);
 100              }
 101              if ($lang_override)
 102              {
 103                  $use_lang = basename($lang_override);
 104                  $user_lang_name = (file_exists($this->lang_path . $use_lang . "/common.$phpEx")) ? $use_lang : basename($config['default_lang']);
 105                  $this->data['user_lang'] = $user_lang_name;
 106              }
 107              else
 108              {
 109                  $user_lang_name = basename($config['default_lang']);
 110              }
 111              $user_date_format = $config['default_dateformat'];
 112              $user_timezone = $config['board_timezone'];
 113   
 114              /**
 115              * If a guest user is surfing, we try to guess his/her language first by obtaining the browser language
 116              * If re-enabled we need to make sure only those languages installed are checked
 117              * Commented out so we do not loose the code.
 118   
 119              if ($request->header('Accept-Language'))
 120              {
 121                  $accept_lang_ary = explode(',', $request->header('Accept-Language'));
 122   
 123                  foreach ($accept_lang_ary as $accept_lang)
 124                  {
 125                      // Set correct format ... guess full xx_YY form
 126                      $accept_lang = substr($accept_lang, 0, 2) . '_' . strtoupper(substr($accept_lang, 3, 2));
 127                      $accept_lang = basename($accept_lang);
 128   
 129                      if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx"))
 130                      {
 131                          $user_lang_name = $config['default_lang'] = $accept_lang;
 132                          break;
 133                      }
 134                      else
 135                      {
 136                          // No match on xx_YY so try xx
 137                          $accept_lang = substr($accept_lang, 0, 2);
 138                          $accept_lang = basename($accept_lang);
 139   
 140                          if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx"))
 141                          {
 142                              $user_lang_name = $config['default_lang'] = $accept_lang;
 143                              break;
 144                          }
 145                      }
 146                  }
 147              }
 148              */
 149          }
 150   
 151          $user_data = $this->data;
 152          $lang_set_ext = array();
 153   
 154          /**
 155          * Event to load language files and modify user data on every page
 156          *
 157          * @event core.user_setup
 158          * @var    array    user_data            Array with user's data row
 159          * @var    string    user_lang_name        Basename of the user's langauge
 160          * @var    string    user_date_format    User's date/time format
 161          * @var    string    user_timezone        User's timezone, should be one of
 162          *                            http://www.php.net/manual/en/timezones.php
 163          * @var    mixed    lang_set            String or array of language files
 164          * @var    array    lang_set_ext        Array containing entries of format
 165          *                     array(
 166          *                         'ext_name' => (string) [extension name],
 167          *                         'lang_set' => (string|array) [language files],
 168          *                     )
 169          *                     For performance reasons, only load translations
 170          *                     that are absolutely needed globally using this
 171          *                     event. Use local events otherwise.
 172          * @var    mixed    style_id            Style we are going to display
 173          * @since 3.1.0-a1
 174          */
 175          $vars = array(
 176              'user_data',
 177              'user_lang_name',
 178              'user_date_format',
 179              'user_timezone',
 180              'lang_set',
 181              'lang_set_ext',
 182              'style_id',
 183          );
 184          extract($phpbb_dispatcher->trigger_event('core.user_setup', compact($vars)));
 185   
 186          $this->data = $user_data;
 187          $this->lang_name = $user_lang_name;
 188          $this->date_format = $user_date_format;
 189   
 190          try
 191          {
 192              $this->timezone = new \DateTimeZone($user_timezone);
 193          }
 194          catch (\Exception $e)
 195          {
 196              // If the timezone the user has selected is invalid, we fall back to UTC.
 197              $this->timezone = new \DateTimeZone('UTC');
 198          }
 199   
 200          // We include common language file here to not load it every time a custom language file is included
 201          $lang = &$this->lang;
 202   
 203          // Do not suppress error if in DEBUG mode
 204          $include_result = (defined('DEBUG')) ? (include $this->lang_path . $this->lang_name . "/common.$phpEx") : (@include $this->lang_path . $this->lang_name . "/common.$phpEx");
 205   
 206          if ($include_result === false)
 207          {
 208              die('Language file ' . $this->lang_path . $this->lang_name . "/common.$phpEx" . " couldn't be opened.");
 209          }
 210   
 211          $this->add_lang($lang_set);
 212          unset($lang_set);
 213   
 214          foreach ($lang_set_ext as $ext_lang_pair)
 215          {
 216              $this->add_lang_ext($ext_lang_pair['ext_name'], $ext_lang_pair['lang_set']);
 217          }
 218          unset($lang_set_ext);
 219   
 220          $style_request = $request->variable('style', 0);
 221          if ($style_request && (!$config['override_user_style'] || $auth->acl_get('a_styles')) && !defined('ADMIN_START'))
 222          {
 223              global $SID, $_EXTRA_URL;
 224   
 225              $style_id = $style_request;
 226              $SID .= '&amp;style=' . $style_id;
 227              $_EXTRA_URL = array('style=' . $style_id);
 228          }
 229          else
 230          {
 231              // Set up style
 232              $style_id = ($style_id) ? $style_id : ((!$config['override_user_style']) ? $this->data['user_style'] : $config['default_style']);
 233          }
 234   
 235          $sql = 'SELECT *
 236              FROM ' . STYLES_TABLE . " s
 237              WHERE s.style_id = $style_id";
 238          $result = $db->sql_query($sql, 3600);
 239          $this->style = $db->sql_fetchrow($result);
 240          $db->sql_freeresult($result);
 241   
 242          // Fallback to user's standard style
 243          if (!$this->style && $style_id != $this->data['user_style'])
 244          {
 245              $style_id = $this->data['user_style'];
 246   
 247              $sql = 'SELECT *
 248                  FROM ' . STYLES_TABLE . " s
 249                  WHERE s.style_id = $style_id";
 250              $result = $db->sql_query($sql, 3600);
 251              $this->style = $db->sql_fetchrow($result);
 252              $db->sql_freeresult($result);
 253          }
 254   
 255          // User has wrong style
 256          if (!$this->style && $style_id == $this->data['user_style'])
 257          {
 258              $style_id = $this->data['user_style'] = $config['default_style'];
 259   
 260              $sql = 'UPDATE ' . USERS_TABLE . "
 261                  SET user_style = $style_id
 262                  WHERE user_id = {$this->data['user_id']}";
 263              $db->sql_query($sql);
 264   
 265              $sql = 'SELECT *
 266                  FROM ' . STYLES_TABLE . " s
 267                  WHERE s.style_id = $style_id";
 268              $result = $db->sql_query($sql, 3600);
 269              $this->style = $db->sql_fetchrow($result);
 270              $db->sql_freeresult($result);
 271          }
 272   
 273          if (!$this->style)
 274          {
 275              trigger_error('NO_STYLE_DATA', E_USER_ERROR);
 276          }
 277   
 278          // Now parse the cfg file and cache it
 279          $parsed_items = $cache->obtain_cfg_items($this->style);
 280   
 281          $check_for = array(
 282              'pagination_sep'    => (string) ', '
 283          );
 284   
 285          foreach ($check_for as $key => $default_value)
 286          {
 287              $this->style[$key] = (isset($parsed_items[$key])) ? $parsed_items[$key] : $default_value;
 288              settype($this->style[$key], gettype($default_value));
 289   
 290              if (is_string($default_value))
 291              {
 292                  $this->style[$key] = htmlspecialchars($this->style[$key]);
 293              }
 294          }
 295   
 296          $template->set_style();
 297   
 298          $this->img_lang = $this->lang_name;
 299   
 300          // Call phpbb_user_session_handler() in case external application want to "bend" some variables or replace classes...
 301          // After calling it we continue script execution...
 302          phpbb_user_session_handler();
 303   
 304          // If this function got called from the error handler we are finished here.
 305          if (defined('IN_ERROR_HANDLER'))
 306          {
 307              return;
 308          }
 309   
 310          // Disable board if the install/ directory is still present
 311          // For the brave development army we do not care about this, else we need to comment out this everytime we develop locally
 312          if (!defined('DEBUG') && !defined('ADMIN_START') && !defined('IN_INSTALL') && !defined('IN_LOGIN') && file_exists($phpbb_root_path . 'install') && !is_file($phpbb_root_path . 'install'))
 313          {
 314              // Adjust the message slightly according to the permissions
 315              if ($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))
 316              {
 317                  $message = 'REMOVE_INSTALL';
 318              }
 319              else
 320              {
 321                  $message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE';
 322              }
 323              trigger_error($message);
 324          }
 325   
 326          // Is board disabled and user not an admin or moderator?
 327          if ($config['board_disable'] && !defined('IN_LOGIN') && !defined('SKIP_CHECK_DISABLED') && !$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_'))
 328          {
 329              if ($this->data['is_bot'])
 330              {
 331                  send_status_line(503, 'Service Unavailable');
 332              }
 333   
 334              $message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE';
 335              trigger_error($message);
 336          }
 337   
 338          // Is load exceeded?
 339          if ($config['limit_load'] && $this->load !== false)
 340          {
 341              if ($this->load > floatval($config['limit_load']) && !defined('IN_LOGIN') && !defined('IN_ADMIN'))
 342              {
 343                  // Set board disabled to true to let the admins/mods get the proper notification
 344                  $config['board_disable'] = '1';
 345   
 346                  if (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_'))
 347                  {
 348                      if ($this->data['is_bot'])
 349                      {
 350                          send_status_line(503, 'Service Unavailable');
 351                      }
 352                      trigger_error('BOARD_UNAVAILABLE');
 353                  }
 354              }
 355          }
 356   
 357          if (isset($this->data['session_viewonline']))
 358          {
 359              // Make sure the user is able to hide his session
 360              if (!$this->data['session_viewonline'])
 361              {
 362                  // Reset online status if not allowed to hide the session...
 363                  if (!$auth->acl_get('u_hideonline'))
 364                  {
 365                      $sql = 'UPDATE ' . SESSIONS_TABLE . '
 366                          SET session_viewonline = 1
 367                          WHERE session_user_id = ' . $this->data['user_id'];
 368                      $db->sql_query($sql);
 369                      $this->data['session_viewonline'] = 1;
 370                  }
 371              }
 372              else if (!$this->data['user_allow_viewonline'])
 373              {
 374                  // the user wants to hide and is allowed to  -> cloaking device on.
 375                  if ($auth->acl_get('u_hideonline'))
 376                  {
 377                      $sql = 'UPDATE ' . SESSIONS_TABLE . '
 378                          SET session_viewonline = 0
 379                          WHERE session_user_id = ' . $this->data['user_id'];
 380                      $db->sql_query($sql);
 381                      $this->data['session_viewonline'] = 0;
 382                  }
 383              }
 384          }
 385   
 386          // Does the user need to change their password? If so, redirect to the
 387          // ucp profile reg_details page ... of course do not redirect if we're already in the ucp
 388          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))
 389          {
 390              if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != "ucp.$phpEx")
 391              {
 392                  redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=profile&amp;mode=reg_details'));
 393              }
 394          }
 395   
 396          return;
 397      }
 398   
 399      /**
 400      * More advanced language substitution
 401      * Function to mimic sprintf() with the possibility of using phpBB's language system to substitute nullar/singular/plural forms.
 402      * Params are the language key and the parameters to be substituted.
 403      * This function/functionality is inspired by SHS` and Ashe.
 404      *
 405      * Example call: <samp>$user->lang('NUM_POSTS_IN_QUEUE', 1);</samp>
 406      *
 407      * If the first parameter is an array, the elements are used as keys and subkeys to get the language entry:
 408      * Example: <samp>$user->lang(array('datetime', 'AGO'), 1)</samp> uses $user->lang['datetime']['AGO'] as language entry.
 409      */
 410      function lang()
 411      {
 412          $args = func_get_args();
 413          $key = $args[0];
 414   
 415          if (is_array($key))
 416          {
 417              $lang = &$this->lang[array_shift($key)];
 418   
 419              foreach ($key as $_key)
 420              {
 421                  $lang = &$lang[$_key];
 422              }
 423          }
 424          else
 425          {
 426              $lang = &$this->lang[$key];
 427          }
 428   
 429          // Return if language string does not exist
 430          if (!isset($lang) || (!is_string($lang) && !is_array($lang)))
 431          {
 432              return $key;
 433          }
 434   
 435          // If the language entry is a string, we simply mimic sprintf() behaviour
 436          if (is_string($lang))
 437          {
 438              if (sizeof($args) == 1)
 439              {
 440                  return $lang;
 441              }
 442   
 443              // Replace key with language entry and simply pass along...
 444              $args[0] = $lang;
 445              return call_user_func_array('sprintf', $args);
 446          }
 447          else if (sizeof($lang) == 0)
 448          {
 449              // If the language entry is an empty array, we just return the language key
 450              return $args[0];
 451          }
 452   
 453          // It is an array... now handle different nullar/singular/plural forms
 454          $key_found = false;
 455   
 456          // We now get the first number passed and will select the key based upon this number
 457          for ($i = 1, $num_args = sizeof($args); $i < $num_args; $i++)
 458          {
 459              if (is_int($args[$i]) || is_float($args[$i]))
 460              {
 461                  if ($args[$i] == 0 && isset($lang[0]))
 462                  {
 463                      // We allow each translation using plural forms to specify a version for the case of 0 things,
 464                      // so that "0 users" may be displayed as "No users".
 465                      $key_found = 0;
 466                      break;
 467                  }
 468                  else
 469                  {
 470                      $use_plural_form = $this->get_plural_form($args[$i]);
 471                      if (isset($lang[$use_plural_form]))
 472                      {
 473                          // The key we should use exists, so we use it.
 474                          $key_found = $use_plural_form;
 475                      }
 476                      else
 477                      {
 478                          // If the key we need to use does not exist, we fall back to the previous one.
 479                          $numbers = array_keys($lang);
 480   
 481                          foreach ($numbers as $num)
 482                          {
 483                              if ($num > $use_plural_form)
 484                              {
 485                                  break;
 486                              }
 487   
 488                              $key_found = $num;
 489                          }
 490                      }
 491                      break;
 492                  }
 493              }
 494          }
 495   
 496          // Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form)
 497          if ($key_found === false)
 498          {
 499              $numbers = array_keys($lang);
 500              $key_found = end($numbers);
 501          }
 502   
 503          // Use the language string we determined and pass it to sprintf()
 504          $args[0] = $lang[$key_found];
 505          return call_user_func_array('sprintf', $args);
 506      }
 507   
 508      /**
 509      * Determine which plural form we should use.
 510      * For some languages this is not as simple as for English.
 511      *
 512      * @param $number        int|float   The number we want to get the plural case for. Float numbers are floored.
 513      * @param $force_rule    mixed   False to use the plural rule of the language package
 514      *                               or an integer to force a certain plural rule
 515      * @return   int     The plural-case we need to use for the number plural-rule combination
 516      */
 517      function get_plural_form($number, $force_rule = false)
 518      {
 519          $number = (int) $number;
 520   
 521          // Default to English system
 522          $plural_rule = ($force_rule !== false) ? $force_rule : ((isset($this->lang['PLURAL_RULE'])) ? $this->lang['PLURAL_RULE'] : 1);
 523   
 524          return phpbb_get_plural_form($plural_rule, $number);
 525      }
 526   
 527      /**
 528      * Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion)
 529      *
 530      * @param mixed $lang_set specifies the language entries to include
 531      * @param bool $use_db internal variable for recursion, do not use
 532      * @param bool $use_help internal variable for recursion, do not use
 533      * @param string $ext_name The extension to load language from, or empty for core files
 534      *
 535      * Examples:
 536      * <code>
 537      * $lang_set = array('posting', 'help' => 'faq');
 538      * $lang_set = array('posting', 'viewtopic', 'help' => array('bbcode', 'faq'))
 539      * $lang_set = array(array('posting', 'viewtopic'), 'help' => array('bbcode', 'faq'))
 540      * $lang_set = 'posting'
 541      * $lang_set = array('help' => 'faq', 'db' => array('help:faq', 'posting'))
 542      * </code>
 543      */
 544      function add_lang($lang_set, $use_db = false, $use_help = false, $ext_name = '')
 545      {
 546          global $phpEx;
 547   
 548          if (is_array($lang_set))
 549          {
 550              foreach ($lang_set as $key => $lang_file)
 551              {
 552                  // Please do not delete this line.
 553                  // We have to force the type here, else [array] language inclusion will not work
 554                  $key = (string) $key;
 555   
 556                  if ($key == 'db')
 557                  {
 558                      $this->add_lang($lang_file, true, $use_help, $ext_name);
 559                  }
 560                  else if ($key == 'help')
 561                  {
 562                      $this->add_lang($lang_file, $use_db, true, $ext_name);
 563                  }
 564                  else if (!is_array($lang_file))
 565                  {
 566                      $this->set_lang($this->lang, $this->help, $lang_file, $use_db, $use_help, $ext_name);
 567                  }
 568                  else
 569                  {
 570                      $this->add_lang($lang_file, $use_db, $use_help, $ext_name);
 571                  }
 572              }
 573              unset($lang_set);
 574          }
 575          else if ($lang_set)
 576          {
 577              $this->set_lang($this->lang, $this->help, $lang_set, $use_db, $use_help, $ext_name);
 578          }
 579      }
 580   
 581      /**
 582      * Add Language Items from an extension - use_db and use_help are assigned where needed (only use them to force inclusion)
 583      *
 584      * @param string $ext_name The extension to load language from, or empty for core files
 585      * @param mixed $lang_set specifies the language entries to include
 586      * @param bool $use_db internal variable for recursion, do not use
 587      * @param bool $use_help internal variable for recursion, do not use
 588      */
 589      function add_lang_ext($ext_name, $lang_set, $use_db = false, $use_help = false)
 590      {
 591          if ($ext_name === '/')
 592          {
 593              $ext_name = '';
 594          }
 595   
 596          $this->add_lang($lang_set, $use_db, $use_help, $ext_name);
 597      }
 598   
 599      /**
 600      * Set language entry (called by add_lang)
 601      * @access private
 602      */
 603      function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false, $ext_name = '')
 604      {
 605          global $phpbb_root_path, $phpEx;
 606   
 607          // Make sure the language name is set (if the user setup did not happen it is not set)
 608          if (!$this->lang_name)
 609          {
 610              global $config;
 611              $this->lang_name = basename($config['default_lang']);
 612          }
 613   
 614          // $lang == $this->lang
 615          // $help == $this->help
 616          // - add appropriate variables here, name them as they are used within the language file...
 617          if (!$use_db)
 618          {
 619              if ($use_help && strpos($lang_file, '/') !== false)
 620              {
 621                  $filename = dirname($lang_file) . '/help_' . basename($lang_file);
 622              }
 623              else
 624              {
 625                  $filename = (($use_help) ? 'help_' : '') . $lang_file;
 626              }
 627   
 628              if ($ext_name)
 629              {
 630                  global $phpbb_extension_manager;
 631                  $ext_path = $phpbb_extension_manager->get_extension_path($ext_name, true);
 632   
 633                  $lang_path = $ext_path . 'language/';
 634              }
 635              else
 636              {
 637                  $lang_path = $this->lang_path;
 638              }
 639   
 640              if (strpos($phpbb_root_path . $filename, $lang_path . $this->lang_name . '/') === 0)
 641              {
 642                  $language_filename = $phpbb_root_path . $filename;
 643              }
 644              else
 645              {
 646                  $language_filename = $lang_path . $this->lang_name . '/' . $filename . '.' . $phpEx;
 647              }
 648   
 649              // If we are in install, try to use the updated version, when available
 650              $install_language_filename = str_replace('language/', 'install/update/new/language/', $language_filename);
 651              if (defined('IN_INSTALL') && file_exists($install_language_filename))
 652              {
 653                  $language_filename = $install_language_filename;
 654              }
 655   
 656              if (!file_exists($language_filename))
 657              {
 658                  global $config;
 659   
 660                  if ($this->lang_name == 'en')
 661                  {
 662                      // 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.
 663                      $language_filename = str_replace($lang_path . 'en', $lang_path . $this->data['user_lang'], $language_filename);
 664                      trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR);
 665                  }
 666                  else if ($this->lang_name == basename($config['default_lang']))
 667                  {
 668                      // Fall back to the English Language
 669                      $reset_lang_name = $this->lang_name;
 670                      $this->lang_name = 'en';
 671                      $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name);
 672                      $this->lang_name = $reset_lang_name;
 673                  }
 674                  else if ($this->lang_name == $this->data['user_lang'])
 675                  {
 676                      // Fall back to the board default language
 677                      $reset_lang_name = $this->lang_name;
 678                      $this->lang_name = basename($config['default_lang']);
 679                      $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name);
 680                      $this->lang_name = $reset_lang_name;
 681                  }
 682   
 683                  return;
 684              }
 685   
 686              // Do not suppress error if in DEBUG mode
 687              $include_result = (defined('DEBUG')) ? (include $language_filename) : (@include $language_filename);
 688   
 689              if ($include_result === false)
 690              {
 691                  trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR);
 692              }
 693          }
 694          else if ($use_db)
 695          {
 696              // Get Database Language Strings
 697              // Put them into $lang if nothing is prefixed, put them into $help if help: is prefixed
 698              // For example: help:faq, posting
 699          }
 700      }
 701   
 702      /**
 703      * Format user date
 704      *
 705      * @param int $gmepoch unix timestamp
 706      * @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.
 707      * @param bool $forcedate force non-relative date format.
 708      *
 709      * @return mixed translated date
 710      */
 711      function format_date($gmepoch, $format = false, $forcedate = false)
 712      {
 713          static $utc;
 714   
 715          if (!isset($utc))
 716          {
 717              $utc = new \DateTimeZone('UTC');
 718          }
 719   
 720          $time = new $this->datetime($this, "@$gmepoch", $utc);
 721          $time->setTimezone($this->timezone);
 722   
 723          return $time->format($format, $forcedate);
 724      }
 725   
 726      /**
 727      * Create a \phpbb\datetime object in the context of the current user
 728      *
 729      * @since 3.1
 730      * @param string $time String in a format accepted by strtotime().
 731      * @param DateTimeZone $timezone Time zone of the time.
 732      * @return \phpbb\datetime Date time object linked to the current users locale
 733      */
 734      public function create_datetime($time = 'now', \DateTimeZone $timezone = null)
 735      {
 736          $timezone = $timezone ?: $this->timezone;
 737          return new $this->datetime($this, $time, $timezone);
 738      }
 739   
 740      /**
 741      * Get the UNIX timestamp for a datetime in the users timezone, so we can store it in the database.
 742      *
 743      * @param    string            $format        Format of the entered date/time
 744      * @param    string            $time        Date/time with the timezone applied
 745      * @param    DateTimeZone    $timezone    Timezone of the date/time, falls back to timezone of current user
 746      * @return    int            Returns the unix timestamp
 747      */
 748      public function get_timestamp_from_format($format, $time, \DateTimeZone $timezone = null)
 749      {
 750          $timezone = $timezone ?: $this->timezone;
 751          $date = \DateTime::createFromFormat($format, $time, $timezone);
 752          return ($date !== false) ? $date->format('U') : false;
 753      }
 754   
 755      /**
 756      * Get language id currently used by the user
 757      */
 758      function get_iso_lang_id()
 759      {
 760          global $config, $db;
 761   
 762          if (!empty($this->lang_id))
 763          {
 764              return $this->lang_id;
 765          }
 766   
 767          if (!$this->lang_name)
 768          {
 769              $this->lang_name = $config['default_lang'];
 770          }
 771   
 772          $sql = 'SELECT lang_id
 773              FROM ' . LANG_TABLE . "
 774              WHERE lang_iso = '" . $db->sql_escape($this->lang_name) . "'";
 775          $result = $db->sql_query($sql);
 776          $this->lang_id = (int) $db->sql_fetchfield('lang_id');
 777          $db->sql_freeresult($result);
 778   
 779          return $this->lang_id;
 780      }
 781   
 782      /**
 783      * Get users profile fields
 784      */
 785      function get_profile_fields($user_id)
 786      {
 787          global $db;
 788   
 789          if (isset($this->profile_fields))
 790          {
 791              return;
 792          }
 793   
 794          $sql = 'SELECT *
 795              FROM ' . PROFILE_FIELDS_DATA_TABLE . "
 796              WHERE user_id = $user_id";
 797          $result = $db->sql_query_limit($sql, 1);
 798          $this->profile_fields = (!($row = $db->sql_fetchrow($result))) ? array() : $row;
 799          $db->sql_freeresult($result);
 800      }
 801   
 802      /**
 803      * Specify/Get image
 804      */
 805      function img($img, $alt = '')
 806      {
 807          $title = '';
 808   
 809          if ($alt)
 810          {
 811              $alt = $this->lang($alt);
 812              $title = ' title="' . $alt . '"';
 813          }
 814          return '<span class="imageset ' . $img . '"' . $title . '>' . $alt . '</span>';
 815      }
 816   
 817      /**
 818      * Get option bit field from user options.
 819      *
 820      * @param int $key option key, as defined in $keyoptions property.
 821      * @param int $data bit field value to use, or false to use $this->data['user_options']
 822      * @return bool true if the option is set in the bit field, false otherwise
 823      */
 824      function optionget($key, $data = false)
 825      {
 826          $var = ($data !== false) ? $data : $this->data['user_options'];
 827          return phpbb_optionget($this->keyoptions[$key], $var);
 828      }
 829   
 830      /**
 831      * Set option bit field for user options.
 832      *
 833      * @param int $key Option key, as defined in $keyoptions property.
 834      * @param bool $value True to set the option, false to clear the option.
 835      * @param int $data Current bit field value, or false to use $this->data['user_options']
 836      * @return int|bool If $data is false, the bit field is modified and
 837      *                  written back to $this->data['user_options'], and
 838      *                  return value is true if the bit field changed and
 839      *                  false otherwise. If $data is not false, the new
 840      *                  bitfield value is returned.
 841      */
 842      function optionset($key, $value, $data = false)
 843      {
 844          $var = ($data !== false) ? $data : $this->data['user_options'];
 845   
 846          $new_var = phpbb_optionset($this->keyoptions[$key], $value, $var);
 847   
 848          if ($data === false)
 849          {
 850              if ($new_var != $var)
 851              {
 852                  $this->data['user_options'] = $new_var;
 853                  return true;
 854              }
 855              else
 856              {
 857                  return false;
 858              }
 859          }
 860          else
 861          {
 862              return $new_var;
 863          }
 864      }
 865   
 866      /**
 867      * Funtion to make the user leave the NEWLY_REGISTERED system group.
 868      * @access public
 869      */
 870      function leave_newly_registered()
 871      {
 872          global $db;
 873   
 874          if (empty($this->data['user_new']))
 875          {
 876              return false;
 877          }
 878   
 879          if (!function_exists('remove_newly_registered'))
 880          {
 881              global $phpbb_root_path, $phpEx;
 882   
 883              include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
 884          }
 885          if ($group = remove_newly_registered($this->data['user_id'], $this->data))
 886          {
 887              $this->data['group_id'] = $group;
 888   
 889          }
 890          $this->data['user_permissions'] = '';
 891          $this->data['user_new'] = 0;
 892   
 893          return true;
 894      }
 895   
 896      /**
 897      * Returns all password protected forum ids the user is currently NOT authenticated for.
 898      *
 899      * @return array     Array of forum ids
 900      * @access public
 901      */
 902      function get_passworded_forums()
 903      {
 904          global $db;
 905   
 906          $sql = 'SELECT f.forum_id, fa.user_id
 907              FROM ' . FORUMS_TABLE . ' f
 908              LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa
 909                  ON (fa.forum_id = f.forum_id
 910                      AND fa.session_id = '" . $db->sql_escape($this->session_id) . "')
 911              WHERE f.forum_password <> ''";
 912          $result = $db->sql_query($sql);
 913   
 914          $forum_ids = array();
 915          while ($row = $db->sql_fetchrow($result))
 916          {
 917              $forum_id = (int) $row['forum_id'];
 918   
 919              if ($row['user_id'] != $this->data['user_id'])
 920              {
 921                  $forum_ids[$forum_id] = $forum_id;
 922              }
 923          }
 924          $db->sql_freeresult($result);
 925   
 926          return $forum_ids;
 927      }
 928  }
 929