[ Index ]

PHP Cross Reference of phpBB 3.0 Beta 3

title

Body

[close]

/includes/ -> session.php (source)

   1  <?php
   2  /** 
   3  *
   4  * @package phpBB3
   5  * @version $Id: session.php,v 1.242 2006/11/12 15:35:43 acydburn Exp $ 
   6  * @copyright (c) 2005 phpBB Group 
   7  * @license http://opensource.org/licenses/gpl-license.php GNU Public License 
   8  *
   9  */
  10  
  11  /**
  12  * Session class
  13  * @package phpBB3
  14  */
  15  class session
  16  {
  17      var $cookie_data = array();
  18      var $page = array();
  19      var $data = array();
  20      var $browser = '';
  21      var $host = '';
  22      var $session_id = '';
  23      var $ip = '';
  24      var $load = 0;
  25      var $time_now = 0;
  26      var $update_session_page = true;
  27  
  28      /**
  29      * Extract current session page
  30      *
  31      * @param string $root_path current root path (phpbb_root_path)
  32      */
  33  	function extract_current_page($root_path)
  34      {
  35          $page_array = array();
  36  
  37          // First of all, get the request uri...
  38          $script_name = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : getenv('PHP_SELF');
  39          $args = (!empty($_SERVER['QUERY_STRING'])) ? explode('&', $_SERVER['QUERY_STRING']) : explode('&', getenv('QUERY_STRING'));
  40  
  41          // 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...
  42          if (!$script_name)
  43          {
  44              $script_name = (!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : getenv('REQUEST_URI');
  45              $page_array['failover'] = 1;
  46          }
  47  
  48          // Replace backslashes and doubled slashes (could happen on some proxy setups)
  49          $script_name = str_replace(array('\\', '//'), '/', $script_name);
  50  
  51          // Now, remove the sid and let us get a clean query string...
  52          foreach ($args as $key => $argument)
  53          {
  54              if (strpos($argument, 'sid=') === 0 || strpos($argument, '_f_=') === 0)
  55              {
  56                  unset($args[$key]);
  57                  break;
  58              }
  59          }
  60  
  61          // The following examples given are for an request uri of {path to the phpbb directory}/adm/index.php?i=10&b=2
  62  
  63          // The current query string
  64          $query_string = trim(implode('&', $args));
  65  
  66          // basenamed page name (for example: index.php)
  67          $page_name = basename($script_name);
  68          $page_name = urlencode(htmlspecialchars($page_name));
  69  
  70          // current directory within the phpBB root (for example: adm)
  71          $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($root_path)));
  72          $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath('./')));
  73          $intersection = array_intersect_assoc($root_dirs, $page_dirs);
  74  
  75          $root_dirs = array_diff_assoc($root_dirs, $intersection);
  76          $page_dirs = array_diff_assoc($page_dirs, $intersection);
  77  
  78          $page_dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs);
  79  
  80          if ($page_dir && substr($page_dir, -1, 1) == '/')
  81          {
  82              $page_dir = substr($page_dir, 0, -1);
  83          }
  84  
  85          // Current page from phpBB root (for example: adm/index.php?i=10&b=2)
  86          $page = (($page_dir) ? $page_dir . '/' : '') . $page_name . (($query_string) ? "?$query_string" : '');
  87  
  88          // The script path from the webroot to the current directory (for example: /phpBB2/adm/) : always prefixed with / and ends in /
  89          $script_path = trim(str_replace('\\', '/', dirname($script_name)));
  90  
  91          // The script path from the webroot to the phpBB root (for example: /phpBB2/)
  92          $script_dirs = explode('/', $script_path);
  93          array_splice($script_dirs, -sizeof($page_dirs));
  94          $root_script_path = implode('/', $script_dirs) . (sizeof($root_dirs) ?  '/' . implode('/', $root_dirs) : '');
  95  
  96          // We are on the base level (phpBB root == webroot), lets adjust the variables a bit...
  97          if (!$root_script_path)
  98          {
  99              $root_script_path = ($page_dir) ? str_replace($page_dir, '', $script_path) : $script_path;
 100          }
 101  
 102          $script_path .= (substr($script_path, -1, 1) == '/') ? '' : '/';
 103          $root_script_path .= (substr($root_script_path, -1, 1) == '/') ? '' : '/';
 104  
 105          $page_array += array(
 106              'page_name'            => $page_name,
 107              'page_dir'            => $page_dir,
 108  
 109              'query_string'        => $query_string,
 110              'script_path'        => str_replace(' ', '%20', htmlspecialchars($script_path)),
 111              'root_script_path'    => str_replace(' ', '%20', htmlspecialchars($root_script_path)),
 112  
 113              'page'                => $page
 114          );
 115  
 116  /*
 117          if (!file_exists($page_name))
 118          {
 119              trigger_error('You are on a page that does not exist!', E_USER_ERROR);
 120          }
 121  */
 122  
 123          return $page_array;
 124      }
 125  
 126      /**
 127      * Start session management
 128      *
 129      * This is where all session activity begins. We gather various pieces of
 130      * information from the client and server. We test to see if a session already
 131      * exists. If it does, fine and dandy. If it doesn't we'll go on to create a 
 132      * new one ... pretty logical heh? We also examine the system load (if we're
 133      * running on a system which makes such information readily available) and
 134      * halt if it's above an admin definable limit.
 135      *
 136      * @param bool $update_session_page if true the session page gets updated.
 137      *            This can be set to circumvent certain scripts to update the users last visited page.
 138      */
 139  	function session_begin($update_session_page = true)
 140      {
 141          global $phpEx, $SID, $_SID, $db, $config, $phpbb_root_path;
 142  
 143          // Give us some basic informations
 144          $this->time_now                = time();
 145          $this->cookie_data            = array('u' => 0, 'k' => '');
 146          $this->update_session_page    = $update_session_page;
 147          $this->browser                = (!empty($_SERVER['HTTP_USER_AGENT'])) ? (string) $_SERVER['HTTP_USER_AGENT'] : '';
 148          $this->host                    = (!empty($_SERVER['HTTP_HOST'])) ? (string) $_SERVER['HTTP_HOST'] : 'localhost';
 149          $this->page                    = $this->extract_current_page($phpbb_root_path);
 150  
 151          // Add forum to the page for tracking online users - also adding a "x" to the end to properly identify the number
 152          $this->page['page'] .= (isset($_REQUEST['f'])) ? ((strpos($this->page['page'], '?') !== false) ? '&' : '?') . '_f_=' . (int) $_REQUEST['f'] . 'x' : '';
 153  
 154          if (isset($_COOKIE[$config['cookie_name'] . '_sid']) || isset($_COOKIE[$config['cookie_name'] . '_u']))
 155          {
 156              $this->cookie_data['u'] = request_var($config['cookie_name'] . '_u', 0, false, true);
 157              $this->cookie_data['k'] = request_var($config['cookie_name'] . '_k', '', false, true);
 158              $this->session_id         = request_var($config['cookie_name'] . '_sid', '', false, true);
 159  
 160              $SID = (defined('NEED_SID')) ? '?sid=' . $this->session_id : '?sid=';
 161              $_SID = (defined('NEED_SID')) ? $this->session_id : '';
 162  
 163              if (empty($this->session_id))
 164              {
 165                  $this->session_id = $_SID = request_var('sid', '');
 166                  $SID = '?sid=' . $this->session_id;
 167                  $this->cookie_data = array('u' => 0, 'k' => '');
 168              }
 169          }
 170          else
 171          {
 172              $this->session_id = $_SID = request_var('sid', '');
 173              $SID = '?sid=' . $this->session_id;
 174          }
 175  
 176          // Why no forwarded_for et al? Well, too easily spoofed. With the results of my recent requests
 177          // it's pretty clear that in the majority of cases you'll at least be left with a proxy/cache ip.
 178          $this->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : '';
 179          $this->load = false;
 180  
 181          // Load limit check (if applicable)
 182          if ($config['limit_load'])
 183          {
 184              if ($load = @file_get_contents('/proc/loadavg'))
 185              {
 186                  $this->load = array_slice(explode(' ', $load), 0, 1);
 187                  $this->load = floatval($this->load[0]);
 188              }
 189              else
 190              {
 191                  set_config('limit_load', '0');
 192              }
 193          }
 194  
 195          // Is session_id is set or session_id is set and matches the url param if required
 196          if (!empty($this->session_id) && (!defined('NEED_SID') || (isset($_GET['sid']) && $this->session_id === $_GET['sid'])))
 197          {
 198              $sql = 'SELECT u.*, s.*
 199                  FROM ' . SESSIONS_TABLE . ' s, ' . USERS_TABLE . " u
 200                  WHERE s.session_id = '" . $db->sql_escape($this->session_id) . "'
 201                      AND u.user_id = s.session_user_id";
 202              $result = $db->sql_query($sql);
 203              $this->data = $db->sql_fetchrow($result);
 204              $db->sql_freeresult($result);
 205  
 206              // Did the session exist in the DB?
 207              if (isset($this->data['user_id']))
 208              {
 209                  // Validate IP length according to admin ... enforces an IP
 210                  // check on bots if admin requires this
 211  //                $quadcheck = ($config['ip_check_bot'] && $this->data['user_type'] & USER_BOT) ? 4 : $config['ip_check'];
 212                  
 213                  $s_ip = implode('.', array_slice(explode('.', $this->data['session_ip']), 0, $config['ip_check']));
 214                  $u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check']));
 215  
 216                  $s_browser = ($config['browser_check']) ? strtolower(substr($this->data['session_browser'], 0, 149)) : '';
 217                  $u_browser = ($config['browser_check']) ? strtolower(substr($this->browser, 0, 149)) : '';
 218  
 219                  if ($u_ip === $s_ip && $s_browser === $u_browser)
 220                  {
 221                      $session_expired = false;
 222  
 223                      // Check whether the session is still valid if we have one
 224                      $method = basename(trim($config['auth_method']));
 225                      include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
 226  
 227                      $method = 'validate_session_' . $method;
 228                      if (function_exists($method))
 229                      {
 230                          if (!$method($this->data))
 231                          {
 232                              $session_expired = true;
 233                          }
 234                      }
 235  
 236                      if (!$session_expired)
 237                      {
 238                          // Check the session length timeframe if autologin is not enabled.
 239                          // Else check the autologin length... and also removing those having autologin enabled but no longer allowed board-wide.
 240                          if (!$this->data['session_autologin'])
 241                          {
 242                              if ($this->data['session_time'] < $this->time_now - ($config['session_length'] + 60))
 243                              {
 244                                  $session_expired = true;
 245                              }
 246                          }
 247                          else if (!$config['allow_autologin'] || ($config['max_autologin_time'] && $this->data['session_time'] < $this->time_now - (86400 * (int) $config['max_autologin_time']) + 60))
 248                          {
 249                              $session_expired = true;
 250                          }
 251                      }
 252  
 253                      if (!$session_expired)
 254                      {
 255                          // Only update session DB a minute or so after last update or if page changes
 256                          if ($this->time_now - $this->data['session_time'] > 60 || ($this->update_session_page && $this->data['session_page'] != $this->page['page']))
 257                          {
 258                              $sql_ary = array('session_time' => $this->time_now);
 259  
 260                              if ($this->update_session_page)
 261                              {
 262                                  $sql_ary['session_page'] = substr($this->page['page'], 0, 199);
 263                              }
 264  
 265                              $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
 266                                  WHERE session_id = '" . $db->sql_escape($this->session_id) . "'";
 267                              $db->sql_query($sql);
 268                          }
 269  
 270                          $this->data['is_registered'] = ($this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == USER_NORMAL || $this->data['user_type'] == USER_FOUNDER)) ? true : false;
 271                          $this->data['is_bot'] = (!$this->data['is_registered'] && $this->data['user_id'] != ANONYMOUS) ? true : false;
 272  
 273                          return true;
 274                      }
 275                  }
 276                  else
 277                  {
 278                      // Added logging temporarly to help debug bugs...
 279                      if (defined('DEBUG_EXTRA'))
 280                      {
 281                          add_log('critical', 'LOG_IP_BROWSER_CHECK', $u_ip, $s_ip, $u_browser, $s_browser);
 282                      }
 283                  }
 284              }
 285          }
 286  
 287          // If we reach here then no (valid) session exists. So we'll create a new one
 288          return $this->session_create();
 289      }
 290      
 291      /**
 292      * Create a new session
 293      *
 294      * If upon trying to start a session we discover there is nothing existing we
 295      * jump here. Additionally this method is called directly during login to regenerate
 296      * the session for the specific user. In this method we carry out a number of tasks;
 297      * garbage collection, (search)bot checking, banned user comparison. Basically
 298      * though this method will result in a new session for a specific user.
 299      */
 300  	function session_create($user_id = false, $set_admin = false, $persist_login = false, $viewonline = true)
 301      {
 302          global $SID, $_SID, $db, $config, $cache, $phpbb_root_path, $phpEx;
 303  
 304          $this->data = array();
 305  
 306          /* Garbage collection ... remove old sessions updating user information
 307          // if necessary. It means (potentially) 11 queries but only infrequently
 308          if ($this->time_now > $config['session_last_gc'] + $config['session_gc'])
 309          {
 310              $this->session_gc();
 311          }*/
 312  
 313          // Do we allow autologin on this board? No? Then override anything
 314          // that may be requested here
 315          if (!$config['allow_autologin'])
 316          {
 317              $this->cookie_data['k'] = $persist_login = false;
 318          }
 319  
 320          /**
 321          * Here we do a bot check, oh er saucy! No, not that kind of bot
 322          * check. We loop through the list of bots defined by the admin and
 323          * see if we have any useragent and/or IP matches. If we do, this is a
 324          * bot, act accordingly
 325          */        
 326          $bot = false;
 327          $active_bots = $cache->obtain_bots();
 328  
 329          foreach ($active_bots as $row)
 330          {
 331              if ($row['bot_agent'] && strpos(strtolower($this->browser), strtolower($row['bot_agent'])) !== false)
 332              {
 333                  $bot = $row['user_id'];
 334              }
 335  
 336              // If ip is supplied, we will make sure the ip is matching too...
 337              if ($row['bot_ip'] && ($bot || !$row['bot_agent']))
 338              {
 339                  // Set bot to false, then we only have to set it to true if it is matching
 340                  $bot = false;
 341  
 342                  foreach (explode(',', $row['bot_ip']) as $bot_ip)
 343                  {
 344                      if (strpos($this->ip, $bot_ip) === 0)
 345                      {
 346                          $bot = (int) $row['user_id'];
 347                          break;
 348                      }
 349                  }
 350              }
 351  
 352              if ($bot)
 353              {
 354                  break;
 355              }
 356          }
 357  
 358          $method = basename(trim($config['auth_method']));
 359          include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
 360  
 361          $method = 'autologin_' . $method;
 362          if (function_exists($method))
 363          {
 364              $this->data = $method();
 365  
 366              if (sizeof($this->data))
 367              {
 368                  $this->cookie_data['k'] = '';
 369                  $this->cookie_data['u'] = $this->data['user_id'];
 370              }
 371          }
 372  
 373          // If we're presented with an autologin key we'll join against it.
 374          // Else if we've been passed a user_id we'll grab data based on that
 375          if (isset($this->cookie_data['k']) && $this->cookie_data['k'] && $this->cookie_data['u'] && !sizeof($this->data))
 376          {
 377              $sql = 'SELECT u.* 
 378                  FROM ' . USERS_TABLE . ' u, ' . SESSIONS_KEYS_TABLE . ' k
 379                  WHERE u.user_id = ' . (int) $this->cookie_data['u'] . '
 380                      AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ")
 381                      AND k.user_id = u.user_id
 382                      AND k.key_id = '" . $db->sql_escape(md5($this->cookie_data['k'])) . "'";
 383              $result = $db->sql_query($sql);
 384              $this->data = $db->sql_fetchrow($result);
 385              $db->sql_freeresult($result);
 386          }
 387          else if ($user_id !== false && !sizeof($this->data))
 388          {
 389              $this->cookie_data['k'] = '';
 390              $this->cookie_data['u'] = $user_id;
 391  
 392              $sql = 'SELECT *
 393                  FROM ' . USERS_TABLE . '
 394                  WHERE user_id = ' . (int) $this->cookie_data['u'] . '
 395                      AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
 396              $result = $db->sql_query($sql);
 397              $this->data = $db->sql_fetchrow($result);
 398              $db->sql_freeresult($result);
 399          }
 400  
 401          // If no data was returned one or more of the following occured:
 402          // Key didn't match one in the DB
 403          // User does not exist
 404          // User is inactive
 405          // User is bot
 406          if (!sizeof($this->data) || !is_array($this->data))
 407          {
 408              $this->cookie_data['k'] = '';
 409              $this->cookie_data['u'] = ($bot) ? $bot : ANONYMOUS;
 410  
 411              if (!$bot)
 412              {
 413                  $sql = 'SELECT *
 414                      FROM ' . USERS_TABLE . '
 415                      WHERE user_id = ' . (int) $this->cookie_data['u'];
 416              }
 417              else
 418              {
 419                  // We give bots always the same session if it is not yet expired.
 420                  $sql = 'SELECT u.*, s.*
 421                      FROM ' . USERS_TABLE . ' u
 422                      LEFT JOIN ' . SESSIONS_TABLE . ' s ON (s.session_user_id = u.user_id)
 423                      WHERE u.user_id = ' . (int) $bot;
 424              }
 425  
 426              $result = $db->sql_query($sql);
 427              $this->data = $db->sql_fetchrow($result);
 428              $db->sql_freeresult($result);
 429          }
 430  
 431          if ($this->data['user_id'] != ANONYMOUS && !$bot)
 432          {
 433              $this->data['session_last_visit'] = (isset($this->data['session_time']) && $this->data['session_time']) ? $this->data['session_time'] : (($this->data['user_lastvisit']) ? $this->data['user_lastvisit'] : time());
 434          }
 435          else
 436          {
 437              $this->data['session_last_visit'] = $this->time_now;
 438          }
 439  
 440          // Force user id to be integer...
 441          $this->data['user_id'] = (int) $this->data['user_id'];
 442  
 443          // At this stage we should have a filled data array, defined cookie u and k data.
 444          // data array should contain recent session info if we're a real user and a recent
 445          // session exists in which case session_id will also be set
 446  
 447          // Is user banned? Are they excluded? Won't return on ban, exists within method
 448          if ($this->data['user_type'] != USER_FOUNDER)
 449          {
 450              $this->check_ban($this->data['user_id'], $this->ip);
 451          }
 452  
 453  
 454          $this->data['is_registered'] = (!$bot && $this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == USER_NORMAL || $this->data['user_type'] == USER_FOUNDER)) ? true : false;
 455          $this->data['is_bot'] = ($bot) ? true : false;
 456  
 457          // If our friend is a bot, we re-assign a previously assigned session
 458          if ($this->data['is_bot'] && $bot == $this->data['user_id'] && $this->data['session_id'])
 459          {
 460              // Only assign the current session if the ip and browser match...
 461              $s_ip = implode('.', array_slice(explode('.', $this->data['session_ip']), 0, $config['ip_check']));
 462              $u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check']));
 463  
 464              $s_browser = ($config['browser_check']) ? strtolower(substr($this->data['session_browser'], 0, 149)) : '';
 465              $u_browser = ($config['browser_check']) ? strtolower(substr($this->browser, 0, 149)) : '';
 466  
 467              if ($u_ip === $s_ip && $s_browser === $u_browser)
 468              {
 469                  $this->session_id = $this->data['session_id'];
 470  
 471                  // Only update session DB a minute or so after last update or if page changes
 472                  if ($this->time_now - $this->data['session_time'] > 60 || ($this->update_session_page && $this->data['session_page'] != $this->page['page']))
 473                  {
 474                      $sql_ary = array('session_time' => $this->time_now, 'session_last_visit' => $this->time_now, 'session_admin' => 0);
 475  
 476                      if ($this->update_session_page)
 477                      {
 478                          $sql_ary['session_page'] = substr($this->page['page'], 0, 199);
 479                      }
 480  
 481                      $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
 482                          WHERE session_id = '" . $db->sql_escape($this->session_id) . "'";
 483                      $db->sql_query($sql);
 484                  }
 485  
 486                  $SID = '?sid=';
 487                  $_SID = '';
 488  
 489                  return true;
 490              }
 491              else
 492              {
 493                  // If the ip and browser does not match make sure we only have one bot assigned to one session
 494                  $db->sql_query('DELETE FROM ' . SESSIONS_TABLE . ' WHERE session_user_id = ' . $this->data['user_id']);
 495              }
 496          }
 497  
 498          $session_autologin = (($this->cookie_data['k'] || $persist_login) && $this->data['is_registered']) ? true : false;
 499          $set_admin = ($set_admin && $this->data['is_registered']) ? true : false;
 500  
 501          // Create or update the session
 502          $sql_ary = array(
 503              'session_user_id'        => (int) $this->data['user_id'],
 504              'session_start'            => (int) $this->time_now,
 505              'session_last_visit'    => (int) $this->data['session_last_visit'],
 506              'session_time'            => (int) $this->time_now,
 507              'session_browser'        => (string) $this->browser,
 508              'session_ip'            => (string) $this->ip,
 509              'session_autologin'        => ($session_autologin) ? 1 : 0,
 510              'session_admin'            => ($set_admin) ? 1 : 0,
 511              'session_viewonline'    => ($viewonline) ? 1 : 0,
 512          );
 513  
 514          if ($this->update_session_page)
 515          {
 516              $sql_ary['session_page'] = (string) substr($this->page['page'], 0, 199);
 517          }
 518  
 519          $db->sql_return_on_error(true);
 520  
 521          $sql = 'DELETE
 522              FROM ' . SESSIONS_TABLE . '
 523              WHERE session_id = \'' . $db->sql_escape($this->session_id) . '\'
 524                  AND session_user_id = ' . ANONYMOUS;
 525  
 526          if (!$this->session_id || !$db->sql_query($sql) || !$db->sql_affectedrows())
 527          {
 528              // Limit new sessions in 1 minute period (if required)
 529              if ((!isset($this->data['session_time']) || !$this->data['session_time']) && $config['active_sessions'])
 530              {
 531                  $sql = 'SELECT COUNT(session_id) AS sessions
 532                      FROM ' . SESSIONS_TABLE . '
 533                      WHERE session_time >= ' . ($this->time_now - 60);
 534                  $result = $db->sql_query($sql);
 535                  $row = $db->sql_fetchrow($result);
 536                  $db->sql_freeresult($result);
 537  
 538                  if ((int) $row['sessions'] > (int) $config['active_sessions'])
 539                  {
 540                      trigger_error('BOARD_UNAVAILABLE');
 541                  }
 542              }
 543          }
 544  
 545          $this->session_id = $this->data['session_id'] = md5(unique_id());
 546  
 547          $sql_ary['session_id'] = (string) $this->session_id;
 548          $sql_ary['session_page'] = (string) substr($this->page['page'], 0, 199);
 549  
 550          $sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
 551          $db->sql_query($sql);
 552  
 553          $db->sql_return_on_error(false);
 554  
 555          // Regenerate autologin/persistent login key
 556          if ($session_autologin)
 557          {
 558              $this->set_login_key();
 559          }
 560  
 561          $SID = '?sid=' . $this->session_id;
 562          $_SID = $this->session_id;
 563  
 564          if (!$bot)
 565          {
 566              $cookie_expire = $this->time_now + (($config['max_autologin_time']) ? 86400 * (int) $config['max_autologin_time'] : 31536000);
 567  
 568              $this->set_cookie('u', $this->cookie_data['u'], $cookie_expire);
 569              $this->set_cookie('k', $this->cookie_data['k'], $cookie_expire);
 570              $this->set_cookie('sid', $this->session_id, $cookie_expire);
 571  
 572              unset($cookie_expire);
 573          }
 574          else
 575          {
 576              $SID = '?sid=';
 577              $_SID = '';
 578          }
 579  
 580          return true;
 581      }
 582  
 583      /**
 584      * Kills a session
 585      *
 586      * This method does what it says on the tin. It will delete a pre-existing session.
 587      * It resets cookie information (destroying any autologin key within that cookie data)
 588      * and update the users information from the relevant session data. It will then
 589      * grab guest user information.
 590      */
 591  	function session_kill()
 592      {
 593          global $SID, $_SID, $db, $config, $phpbb_root_path, $phpEx;
 594  
 595          $sql = 'DELETE FROM ' . SESSIONS_TABLE . "
 596              WHERE session_id = '" . $db->sql_escape($this->session_id) . "'
 597                  AND session_user_id = " . (int) $this->data['user_id'];
 598          $db->sql_query($sql);
 599  
 600          // Allow connecting logout with external auth method logout
 601          $method = basename(trim($config['auth_method']));
 602          include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
 603  
 604          $method = 'logout_' . $method;
 605          if (function_exists($method))
 606          {
 607              $method($this->data);
 608          }
 609  
 610          if ($this->data['user_id'] != ANONYMOUS)
 611          {
 612              // Delete existing session, update last visit info first!
 613              if (!isset($this->data['session_time']))
 614              {
 615                  $this->data['session_time'] = time();
 616              }
 617  
 618              $sql = 'UPDATE ' . USERS_TABLE . '
 619                  SET user_lastvisit = ' . (int) $this->data['session_time'] . '
 620                  WHERE user_id = ' . (int) $this->data['user_id'];
 621              $db->sql_query($sql);
 622  
 623              if ($this->cookie_data['k'])
 624              {
 625                  $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
 626                      WHERE user_id = ' . (int) $this->data['user_id'] . "
 627                          AND key_id = '" . $db->sql_escape(md5($this->cookie_data['k'])) . "'";
 628                  $db->sql_query($sql);
 629              }
 630  
 631              // Reset the data array
 632              $this->data = array();
 633  
 634              $sql = 'SELECT *
 635                  FROM ' . USERS_TABLE . '
 636                  WHERE user_id = ' . ANONYMOUS;
 637              $result = $db->sql_query($sql);
 638              $this->data = $db->sql_fetchrow($result);
 639              $db->sql_freeresult($result);
 640          }
 641  
 642          $cookie_expire = $this->time_now - 31536000;
 643          $this->set_cookie('u', '', $cookie_expire);
 644          $this->set_cookie('k', '', $cookie_expire);
 645          $this->set_cookie('sid', '', $cookie_expire);
 646          unset($cookie_expire);
 647  
 648          $SID = '?sid=';
 649          $this->session_id = $_SID = '';
 650  
 651          // To make sure a valid session is created we create one for the anonymous user
 652          $this->session_create(ANONYMOUS);
 653  
 654          return true;
 655      }
 656  
 657      /**
 658      * Session garbage collection
 659      *
 660      * This looks a lot more complex than it really is. Effectively we are
 661      * deleting any sessions older than an admin definable limit. Due to the
 662      * way in which we maintain session data we have to ensure we update user
 663      * data before those sessions are destroyed. In addition this method
 664      * removes autologin key information that is older than an admin defined
 665      * limit.
 666      */
 667  	function session_gc()
 668      {
 669          global $db, $config;
 670  
 671          if (!$this->time_now)
 672          {
 673              $this->time_now = time();
 674          }
 675  
 676          // Firstly, delete guest sessions
 677          $sql = 'DELETE FROM ' . SESSIONS_TABLE . '
 678              WHERE session_user_id = ' . ANONYMOUS . '
 679                  AND session_time < ' . (int) ($this->time_now - $config['session_length']);
 680          $db->sql_query($sql);
 681  
 682          // Get expired sessions, only most recent for each user
 683          $sql = 'SELECT session_user_id, session_page, MAX(session_time) AS recent_time
 684              FROM ' . SESSIONS_TABLE . '
 685              WHERE session_time < ' . ($this->time_now - $config['session_length']) . '
 686              GROUP BY session_user_id, session_page';
 687          $result = $db->sql_query_limit($sql, 10);
 688  
 689          $del_user_id = array();
 690          $del_sessions = 0;
 691  
 692          while ($row = $db->sql_fetchrow($result))
 693          {
 694              $sql = 'UPDATE ' . USERS_TABLE . '
 695                  SET user_lastvisit = ' . (int) $row['recent_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "'
 696                  WHERE user_id = " . (int) $row['session_user_id'];
 697              $db->sql_query($sql);
 698  
 699              $del_user_id[] = (int) $row['session_user_id'];
 700              $del_sessions++;
 701          }
 702          $db->sql_freeresult($result);
 703  
 704          if (sizeof($del_user_id))
 705          {
 706              // Delete expired sessions
 707              $sql = 'DELETE FROM ' . SESSIONS_TABLE . '
 708                  WHERE ' . $db->sql_in_set('session_user_id', $del_user_id) . '
 709                      AND session_time < ' . ($this->time_now - $config['session_length']);
 710              $db->sql_query($sql);
 711          }
 712  
 713          if ($del_sessions < 10)
 714          {
 715              // Less than 10 sessions, update gc timer ... else we want gc
 716              // called again to delete other sessions
 717              set_config('session_last_gc', $this->time_now, true);
 718          }
 719  
 720          if ($config['max_autologin_time'])
 721          {
 722              $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
 723                  WHERE last_login < ' . (time() - (86400 * (int) $config['max_autologin_time']));
 724              $db->sql_query($sql);
 725          }
 726  
 727          return;
 728      }
 729  
 730      /**
 731      * Sets a cookie
 732      *
 733      * Sets a cookie of the given name with the specified data for the given length of time.
 734      */
 735  	function set_cookie($name, $cookiedata, $cookietime)
 736      {
 737          global $config;
 738  
 739          $name_data = rawurlencode($config['cookie_name'] . '_' . $name) . '=' . rawurlencode($cookiedata);
 740          $expire = gmdate('D, d-M-Y H:i:s \\G\\M\\T', $cookietime);
 741          $domain = (!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain'];
 742  
 743          header('Set-Cookie: ' . $name_data . '; expires=' . $expire . '; path=' . $config['cookie_path'] . $domain . ((!$config['cookie_secure']) ? '' : '; secure') . '; HttpOnly', false);
 744      }
 745  
 746      /**
 747      * Check for banned user
 748      *
 749      * Checks whether the supplied user is banned by id, ip or email. If no parameters
 750      * are passed to the method pre-existing session data is used. If $return is false
 751      * this routine does not return on finding a banned user, it outputs a relevant 
 752      * message and stops execution.
 753      */
 754  	function check_ban($user_id = false, $user_ip = false, $user_email = false, $return = false)
 755      {
 756          global $config, $db;
 757  
 758          $banned = false;
 759  
 760          $sql = 'SELECT ban_ip, ban_userid, ban_email, ban_exclude, ban_give_reason, ban_end
 761              FROM ' . BANLIST_TABLE . '
 762              WHERE (ban_end >= ' . time() . ' OR ban_end = 0)';
 763  
 764          // Determine which entries to check, only return those
 765          if ($user_email === false)
 766          {
 767              $sql .= " AND ban_email = ''";
 768          }
 769  
 770          if ($user_ip === false)
 771          {
 772              $sql .= " AND (ban_ip = '' OR (ban_ip <> '' AND ban_exclude = 1))";
 773          }
 774  
 775          if ($user_id === false)
 776          {
 777              $sql .= ' AND (ban_userid = 0 OR (ban_userid <> 0 AND ban_exclude = 1))';
 778          }
 779          else
 780          {
 781              $sql .= ' AND (ban_userid = ' . $user_id;
 782  
 783              if ($user_email !== false)
 784              {
 785                  $sql .= " OR ban_email <> ''";
 786              }
 787  
 788              if ($user_ip !== false)
 789              {
 790                  $sql .= " OR ban_ip <> ''";
 791              }
 792  
 793              $sql .= ')';
 794          }
 795  
 796          $result = $db->sql_query($sql);
 797  
 798          $ban_triggered_by = 'user';
 799          while ($row = $db->sql_fetchrow($result))
 800          {
 801              if ((!empty($row['ban_userid']) && intval($row['ban_userid']) == $user_id) ||
 802                  (!empty($row['ban_ip']) && preg_match('#^' . str_replace('*', '.*?', $row['ban_ip']) . '$#i', $user_ip)) ||
 803                  (!empty($row['ban_email']) && preg_match('#^' . str_replace('*', '.*?', $row['ban_email']) . '$#i', $user_email)))
 804              {
 805                  if (!empty($row['ban_exclude']))
 806                  {
 807                      $banned = false;
 808                      break;
 809                  }
 810                  else
 811                  {
 812                      $banned = true;
 813                      $ban_row = $row;
 814  
 815                      if (!empty($row['ban_userid']) && intval($row['ban_userid']) == $user_id)
 816                      {
 817                          $ban_triggered_by = 'user';
 818                      }
 819                      else if (!empty($row['ban_ip']) && preg_match('#^' . str_replace('*', '.*?', $row['ban_ip']) . '$#i', $user_ip))
 820                      {
 821                          $ban_triggered_by = 'ip';
 822                      }
 823                      else
 824                      {
 825                          $ban_triggered_by = 'email';
 826                      }
 827  
 828                      // Don't break. Check if there is an exclude rule for this user
 829                  }
 830              }
 831          }
 832          $db->sql_freeresult($result);
 833  
 834          if ($banned && !$return)
 835          {
 836              // Initiate environment ... since it won't be set at this stage
 837              $this->setup();
 838  
 839              // Logout the user, banned users are unable to use the normal 'logout' link
 840              if ($this->data['user_id'] != ANONYMOUS)
 841              {
 842                  $this->session_kill();
 843              }
 844  
 845              // Determine which message to output
 846              $till_date = ($ban_row['ban_end']) ? $this->format_date($ban_row['ban_end']) : '';
 847              $message = ($ban_row['ban_end']) ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM';
 848  
 849              $message = sprintf($this->lang[$message], $till_date, '<a href="mailto:' . $config['board_contact'] . '">', '</a>');
 850              $message .= ($ban_row['ban_give_reason']) ? '<br /><br />' . sprintf($this->lang['BOARD_BAN_REASON'], $ban_row['ban_give_reason']) : '';
 851              $message .= '<br /><br /><em>' . $this->lang['BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)] . '</em>';
 852  
 853              trigger_error($message);
 854          }
 855  
 856          return ($banned) ? true : false;
 857      }
 858  
 859      /**
 860      * Check if ip is blacklisted
 861      * This should be called only where absolutly necessary
 862      *
 863      * Only IPv4 (rbldns does not support AAAA records/IPv6 lookups)
 864      *
 865      * @author satmd (from the php manual)
 866      * @return false if ip is not blacklisted, else an array([checked server], [lookup])
 867      */
 868  	function check_dnsbl($ip = false)
 869      {
 870          if ($ip === false)
 871          {
 872              $ip = $this->ip;
 873          }
 874  
 875          $dnsbl_check = array(
 876              'bl.spamcop.net'        => 'http://spamcop.net/bl.shtml?',
 877              'list.dsbl.org'            => 'http://dsbl.org/listing?',
 878              'sbl-xbl.spamhaus.org'    => 'http://www.spamhaus.org/query/bl?ip=',
 879          );
 880  
 881          if ($ip)
 882          {
 883              $quads = explode('.', $ip);
 884              $reverse_ip = $quads[3] . '.' . $quads[2] . '.' . $quads[1] . '.' . $quads[0];
 885  
 886              foreach ($dnsbl_check as $dnsbl => $lookup)
 887              {
 888                  if (phpbb_checkdnsrr($reverse_ip . '.' . $dnsbl . '.', 'A') === true)
 889                  {
 890                      return array($dnsbl, $lookup . $ip);
 891                  }
 892              }
 893          }
 894  
 895          return false;
 896      }
 897  
 898      /**
 899      * Set/Update a persistent login key
 900      *
 901      * This method creates or updates a persistent session key. When a user makes
 902      * use of persistent (formerly auto-) logins a key is generated and stored in the
 903      * DB. When they revisit with the same key it's automatically updated in both the
 904      * DB and cookie. Multiple keys may exist for each user representing different
 905      * browsers or locations. As with _any_ non-secure-socket no passphrase login this
 906      * remains vulnerable to exploit.
 907      */
 908  	function set_login_key($user_id = false, $key = false, $user_ip = false)
 909      {
 910          global $config, $db;
 911  
 912          $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id;
 913          $user_ip = ($user_ip === false) ? $this->ip : $user_ip;
 914          $key = ($key === false) ? (($this->cookie_data['k']) ? $this->cookie_data['k'] : false) : $key;
 915  
 916          $key_id = unique_id(hexdec(substr($this->session_id, 0, 8)));
 917  
 918          $sql_ary = array(
 919              'key_id'        => (string) md5($key_id),
 920              'last_ip'        => (string) $this->ip,
 921              'last_login'    => (int) time()
 922          );
 923  
 924          if (!$key)
 925          {
 926              $sql_ary += array(
 927                  'user_id'    => (int) $user_id
 928              );
 929          }
 930  
 931          if ($key)
 932          {
 933              $sql = 'UPDATE ' . SESSIONS_KEYS_TABLE . '
 934                  SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
 935                  WHERE user_id = ' . (int) $user_id . "
 936                      AND key_id = '" . $db->sql_escape(md5($key)) . "'";
 937          }
 938          else
 939          {
 940              $sql = 'INSERT INTO ' . SESSIONS_KEYS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
 941          }
 942          $db->sql_query($sql);
 943  
 944          $this->cookie_data['k'] = $key_id;
 945  
 946          return false;
 947      }
 948  
 949      /**
 950      * Reset all login keys for the specified user
 951      *
 952      * This method removes all current login keys for a specified (or the current)
 953      * user. It will be called on password change to render old keys unusable
 954      */
 955  	function reset_login_keys($user_id = false)
 956      {
 957          global $config, $db;
 958  
 959          $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id;
 960  
 961          $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
 962              WHERE user_id = ' . (int) $user_id;
 963          $db->sql_query($sql);
 964  
 965          // Let's also clear any current sessions for the specified user_id
 966          // If it's the current user then we'll leave this session intact
 967          $sql_where = 'session_user_id = ' . (int) $user_id;
 968          $sql_where .= ($user_id === $this->data['user_id']) ? " AND session_id <> '" . $db->sql_escape($this->session_id) . "'" : '';
 969  
 970          $sql = 'DELETE FROM ' . SESSIONS_TABLE . " 
 971              WHERE $sql_where";
 972          $db->sql_query($sql);
 973  
 974          // We're changing the password of the current user and they have a key
 975          // Lets regenerate it to be safe
 976          if ($user_id === $this->data['user_id'] && $this->cookie_data['k'])
 977          {
 978              $this->set_login_key($user_id);
 979          }
 980      }
 981  }
 982  
 983  
 984  /**
 985  * Base user class
 986  *
 987  * This is the overarching class which contains (through session extend)
 988  * all methods utilised for user functionality during a session.
 989  *
 990  * @package phpBB3
 991  */
 992  class user extends session
 993  {
 994      var $lang = array();
 995      var $help = array();
 996      var $theme = array();
 997      var $date_format;
 998      var $timezone;
 999      var $dst;
1000  
1001      var $lang_name;
1002      var $lang_path;
1003      var $img_lang;
1004  
1005      // Able to add new option (id 7)
1006      var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10);
1007      var $keyvalues = array();
1008  
1009      /**
1010      * Setup basic user-specific items (style, language, ...)
1011      */
1012  	function setup($lang_set = false, $style = false)
1013      {
1014          global $db, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache;
1015  
1016          if ($this->data['user_id'] != ANONYMOUS)
1017          {
1018              $this->lang_name = (file_exists($phpbb_root_path . 'language/' . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : $config['default_lang'];
1019              $this->lang_path = $phpbb_root_path . 'language/' . $this->lang_name . '/';
1020  
1021              $this->date_format = $this->data['user_dateformat'];
1022              $this->timezone = $this->data['user_timezone'] * 3600;
1023              $this->dst = $this->data['user_dst'] * 3600;
1024          }
1025          else
1026          {
1027              $this->lang_name = $config['default_lang'];
1028              $this->lang_path = $phpbb_root_path . 'language/' . $this->lang_name . '/';
1029              $this->date_format = $config['default_dateformat'];
1030              $this->timezone = $config['board_timezone'] * 3600;
1031              $this->dst = $config['board_dst'] * 3600;
1032  
1033              /**
1034              * If a guest user is surfing, we try to guess his/her language first by obtaining the browser language
1035              * @todo if re-enabled we need to make sure only those languages installed are checked
1036  
1037              if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
1038              {
1039                  $accept_lang_ary = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
1040  
1041                  foreach ($accept_lang_ary as $accept_lang)
1042                  {
1043                      // Set correct format ... guess full xx_YY form
1044                      $accept_lang = substr($accept_lang, 0, 2) . '_' . strtoupper(substr($accept_lang, 3, 2));
1045                      $accept_lang = basename($accept_lang);
1046  
1047                      if (file_exists($phpbb_root_path . 'language/' . $accept_lang . "/common.$phpEx"))
1048                      {
1049                          $this->lang_name = $config['default_lang'] = $accept_lang;
1050                          $this->lang_path = $phpbb_root_path . 'language/' . $accept_lang . '/';
1051                          break;
1052                      }
1053                      else
1054                      {
1055                          // No match on xx_YY so try xx
1056                          $accept_lang = substr($accept_lang, 0, 2);
1057                          $accept_lang = basename($accept_lang);
1058  
1059                          if (file_exists($phpbb_root_path . 'language/' . $accept_lang . "/common.$phpEx"))
1060                          {
1061                              $this->lang_name = $config['default_lang'] = $accept_lang;
1062                              $this->lang_path = $phpbb_root_path . 'language/' . $accept_lang . '/';
1063                              break;
1064                          }
1065                      }
1066                  }
1067              }
1068              */
1069          }
1070  
1071          // We include common language file here to not load it every time a custom language file is included
1072          $lang = &$this->lang;
1073          if ((include $this->lang_path . "common.$phpEx") === false)
1074          {
1075              die("Language file " . $this->lang_path . "common.$phpEx" . " couldn't be opened.");
1076          }
1077  
1078          $this->add_lang($lang_set);
1079          unset($lang_set);
1080  
1081          if (!empty($_GET['style']) && $auth->acl_get('a_styles'))
1082          {
1083              global $SID, $_EXTRA_URL;
1084  
1085              $style = request_var('style', 0);
1086              $SID .= '&amp;style=' . $style;
1087              $_EXTRA_URL = array('style=' . $style);
1088          }
1089          else
1090          {
1091              // Set up style
1092              $style = ($style) ? $style : ((!$config['override_user_style'] && $this->data['user_id'] != ANONYMOUS) ? $this->data['user_style'] : $config['default_style']);
1093          }
1094  
1095          $sql = 'SELECT s.style_id, t.*, c.*, i.*
1096              FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . " i
1097              WHERE s.style_id = $style
1098                  AND t.template_id = s.template_id
1099                  AND c.theme_id = s.theme_id
1100                  AND i.imageset_id = s.imageset_id";
1101          $result = $db->sql_query($sql, 3600);
1102          $this->theme = $db->sql_fetchrow($result);
1103          $db->sql_freeresult($result);
1104  
1105          // User has wrong style
1106          if (!$this->theme && $style == $this->data['user_style'])
1107          {
1108              $style = $this->data['user_style'] = $config['default_style'];
1109  
1110              $sql = 'UPDATE ' . USERS_TABLE . " 
1111                  SET user_style = $style 
1112                  WHERE user_id = {$this->data['user_id']}";
1113              $db->sql_query($sql);
1114  
1115              $sql = 'SELECT s.style_id, t.*, c.*, i.*
1116                  FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . " i
1117                  WHERE s.style_id = $style
1118                      AND t.template_id = s.template_id
1119                      AND c.theme_id = s.theme_id
1120                      AND i.imageset_id = s.imageset_id";
1121              $result = $db->sql_query($sql, 3600);
1122              $this->theme = $db->sql_fetchrow($result);
1123              $db->sql_freeresult($result);
1124          }
1125  
1126          if (!$this->theme)
1127          {
1128              trigger_error('Could not get style data', E_USER_ERROR);
1129          }
1130  
1131          // Now parse the cfg file and cache it
1132          $parsed_items = $cache->obtain_cfg_items($this->theme);
1133  
1134          // We are only interested in the theme configuration for now
1135          $parsed_items = $parsed_items['theme'];
1136  
1137          $check_for = array(
1138              'parse_css_file'    => (int) 0,
1139              'pagination_sep'    => (string) ', '
1140          );
1141  
1142          foreach ($check_for as $key => $default_value)
1143          {
1144              $this->theme[$key] = (isset($parsed_items[$key])) ? $parsed_items[$key] : $default_value;
1145              settype($this->theme[$key], gettype($default_value));
1146  
1147              if (is_string($default_value))
1148              {
1149                  $this->theme[$key] = htmlspecialchars($this->theme[$key]);
1150              }
1151          }
1152  
1153          // If the style author specified the theme needs to be cached
1154          // (because of the used paths and variables) than make sure it is the case.
1155          // For example, if the theme uses language-specific images it needs to be stored in db.
1156          if (!$this->theme['theme_storedb'] && $this->theme['parse_css_file'])
1157          {
1158              $this->theme['theme_storedb'] = 1;
1159  
1160              $stylesheet = file_get_contents("{$phpbb_root_path}styles/{$this->theme['theme_path']}/theme/stylesheet.css");
1161              // Match CSS imports
1162              $matches = array();
1163              preg_match_all('/@import url\(["\'](.*)["\']\);/i', $stylesheet, $matches);
1164      
1165              if (sizeof($matches))
1166              {
1167                  $content = '';
1168                  foreach ($matches[0] as $idx => $match)
1169                  {
1170                      if ($content = @file_get_contents("{$phpbb_root_path}styles/{$this->theme['theme_path']}/theme/" . $matches[1][$idx]))
1171                      {
1172                          $content = trim($content);
1173                      }
1174                      else
1175                      {
1176                          $content = '';
1177                      }
1178                      $stylesheet = str_replace($match, $content, $stylesheet);
1179                  }
1180                  unset ($content);
1181              }
1182  
1183              $stylesheet = str_replace('./', 'styles/' . $this->theme['theme_path'] . '/theme/', $stylesheet);
1184  
1185              $sql_ary = array(
1186                  'theme_data'    => $stylesheet,
1187                  'theme_mtime'    => time(),
1188                  'theme_storedb'    => 1
1189              );
1190  
1191              $sql = 'UPDATE ' . STYLES_THEME_TABLE . '
1192                  SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
1193                  WHERE theme_id = ' . $this->theme['theme_id'];
1194              $db->sql_query($sql);
1195  
1196              unset($sql_ary);
1197          }
1198  
1199          $template->set_template();
1200  
1201          $this->img_lang = (file_exists($phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . $this->lang_name)) ? $this->lang_name : $config['default_lang'];
1202  
1203          // Is board disabled and user not an admin or moderator?
1204          if ($config['board_disable'] && !defined('IN_LOGIN') && !$auth->acl_gets('a_', 'm_'))
1205          {
1206              $message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE';
1207              trigger_error($message);
1208          }
1209  
1210          // Is load exceeded?
1211          if ($config['limit_load'] && $this->load !== false)
1212          {
1213              if ($this->load > floatval($config['limit_load']) && !defined('IN_LOGIN') && !$auth->acl_gets('a_', 'm_'))
1214              {
1215                  trigger_error('BOARD_UNAVAILABLE');
1216              }
1217          }
1218  
1219          // Does the user need to change their password? If so, redirect to the
1220          // ucp profile reg_details page ... of course do not redirect if we're already in the ucp
1221          if (!defined('IN_ADMIN') && !defined('ADMIN_START') && $config['chg_passforce'] && $this->data['is_registered'] && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400))
1222          {
1223              if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != "ucp.$phpEx")
1224              {
1225                  redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=profile&amp;mode=reg_details'));
1226              }
1227          }
1228  
1229          return;
1230      }
1231  
1232      /**
1233      * Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion)
1234      *
1235      * @param mixed $lang_set specifies the language entries to include
1236      * @param bool $use_db internal variable for recursion, do not use
1237      * @param bool $use_help internal variable for recursion, do not use
1238      *
1239      * Examples:
1240      * <code>
1241      * $lang_set = array('posting', 'help' => 'faq');
1242      * $lang_set = array('posting', 'viewtopic', 'help' => array('bbcode', 'faq'))
1243      * $lang_set = array(array('posting', 'viewtopic'), 'help' => array('bbcode', 'faq'))
1244      * $lang_set = 'posting'
1245      * $lang_set = array('help' => 'faq', 'db' => array('help:faq', 'posting'))
1246      * </code>
1247      */
1248  	function add_lang($lang_set, $use_db = false, $use_help = false)
1249      {
1250          global $phpEx;
1251  
1252          if (is_array($lang_set))
1253          {
1254              foreach ($lang_set as $key => $lang_file)
1255              {
1256                  // Please do not delete this line.
1257                  // We have to force the type here, else [array] language inclusion will not work
1258                  $key = (string) $key;
1259  
1260                  if ($key == 'db')
1261                  {
1262                      $this->add_lang($lang_file, true, $use_help);
1263                  }
1264                  else if ($key == 'help')
1265                  {
1266                      $this->add_lang($lang_file, $use_db, true);
1267                  }
1268                  else if (!is_array($lang_file))
1269                  {
1270                      $this->set_lang($this->lang, $this->help, $lang_file, $use_db, $use_help);
1271                  }
1272                  else
1273                  {
1274                      $this->add_lang($lang_file, $use_db, $use_help);
1275                  }
1276              }
1277              unset($lang_set);
1278          }
1279          else if ($lang_set)
1280          {
1281              $this->set_lang($this->lang, $this->help, $lang_set, $use_db, $use_help);
1282          }
1283      }
1284  
1285      /**
1286      * Set language entry (called by add_lang)
1287      * @access private
1288      */
1289  	function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false)
1290      {
1291          global $phpEx;
1292  
1293          // Make sure the language path is set (if the user setup did not happen it is not set)
1294          if (!$this->lang_path)
1295          {
1296              global $phpbb_root_path, $config;
1297              
1298              $this->lang_path = $phpbb_root_path . 'language/' . $config['default_lang'] . '/';
1299          }
1300  
1301          // $lang == $this->lang
1302          // $help == $this->help
1303          // - add appropiate variables here, name them as they are used within the language file...
1304          if (!$use_db)
1305          {
1306              if ((include($this->lang_path . (($use_help) ? 'help_' : '') . "$lang_file.$phpEx")) === false)
1307              {
1308                  trigger_error("Language file {$this->lang_path}" . (($use_help) ? 'help_' : '') . "$lang_file.$phpEx couldn't be opened.", E_USER_ERROR);
1309              }
1310          }
1311          else if ($use_db)
1312          {
1313              // Get Database Language Strings
1314              // Put them into $lang if nothing is prefixed, put them into $help if help: is prefixed
1315              // For example: help:faq, posting
1316          }
1317      }
1318  
1319      /**
1320      * Format user date
1321      */
1322  	function format_date($gmepoch, $format = false, $forcedate = false)
1323      {
1324          static $midnight;
1325  
1326          $lang_dates = $this->lang['datetime'];
1327          $format = (!$format) ? $this->date_format : $format;
1328  
1329          // Short representation of month in format
1330          if ((strpos($format, '\M') === false && strpos($format, 'M') !== false) || (strpos($format, '\r') === false && strpos($format, 'r') !== false))
1331          {
1332              $lang_dates['May'] = $lang_dates['May_short'];
1333          }
1334  
1335          unset($lang_dates['May_short']);
1336  
1337          if (!$midnight)
1338          {
1339              list($d, $m, $y) = explode(' ', gmdate('j n Y', time() + $this->timezone + $this->dst));
1340              $midnight = gmmktime(0, 0, 0, $m, $d, $y) - $this->timezone - $this->dst;
1341          }
1342  
1343          if (strpos($format, '|') === false || ($gmepoch < $midnight - 86400 && !$forcedate) || ($gmepoch > $midnight + 172800 && !$forcedate))
1344          {
1345              return strtr(@gmdate(str_replace('|', '', $format), $gmepoch + $this->timezone + $this->dst), $lang_dates);
1346          }
1347  
1348          if ($gmepoch > $midnight + 86400 && !$forcedate)
1349          {
1350              $format = substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1);
1351              return str_replace('||', $this->lang['datetime']['TOMORROW'], strtr(@gmdate($format, $gmepoch + $this->timezone + $this->dst), $lang_dates));
1352          }
1353          else if ($gmepoch > $midnight && !$forcedate)
1354          {
1355              $format = substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1);
1356              return str_replace('||', $this->lang['datetime']['TODAY'], strtr(@gmdate($format, $gmepoch + $this->timezone + $this->dst), $lang_dates));
1357          }
1358          else if ($gmepoch > $midnight - 86400 && !$forcedate)
1359          {
1360              $format = substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1);
1361              return str_replace('||', $this->lang['datetime']['YESTERDAY'], strtr(@gmdate($format, $gmepoch + $this->timezone + $this->dst), $lang_dates));
1362          }
1363  
1364          return strtr(@gmdate(str_replace('|', '', $format), $gmepoch + $this->timezone + $this->dst), $lang_dates);
1365      }
1366  
1367      /**
1368      * Get language id currently used by the user
1369      */
1370  	function get_iso_lang_id()
1371      {
1372          global $config, $db;
1373  
1374          if (isset($this->lang_id))
1375          {
1376              return $this->lang_id;
1377          }
1378  
1379          if (!$this->lang_name)
1380          {
1381              $this->lang_name = $config['default_lang'];
1382          }
1383  
1384          $sql = 'SELECT lang_id
1385              FROM ' . LANG_TABLE . "
1386              WHERE lang_iso = '" . $db->sql_escape($this->lang_name) . "'";
1387          $result = $db->sql_query($sql);
1388          $lang_id = (int) $db->sql_fetchfield('lang_id');
1389          $db->sql_freeresult($result);
1390  
1391          return $lang_id;
1392      }
1393  
1394      /**
1395      * Get users profile fields
1396      */
1397  	function get_profile_fields($user_id)
1398      {
1399          global $db;
1400  
1401          if (isset($this->profile_fields))
1402          {
1403              return;
1404          }
1405  
1406          $sql = 'SELECT *
1407              FROM ' . PROFILE_FIELDS_DATA_TABLE . "
1408              WHERE user_id = $user_id";
1409          $result = $db->sql_query_limit($sql, 1);
1410          $this->profile_fields = (!($row = $db->sql_fetchrow($result))) ? array() : $row;
1411          $db->sql_freeresult($result);
1412      }
1413  
1414      /**
1415      * Specify/Get image
1416      */
1417  	function img($img, $alt = '', $width = false, $suffix = '', $type = 'full_tag')
1418      {
1419          static $imgs;
1420          global $phpbb_root_path;
1421  
1422          $img_data = &$imgs[$img . $suffix];
1423  
1424          if (empty($img_data) || $width !== false)
1425          {
1426              if (!isset($this->theme[$img]) || !$this->theme[$img])
1427              {
1428                  // Do not fill the image to let designers decide what to do if the image is empty
1429                  $img_data = '';
1430                  return $img_data;
1431              }
1432  
1433              // Do not include dimensions?
1434              if (strpos($this->theme[$img], '*') === false)
1435              {
1436                  $imgsrc = trim($this->theme[$img]);
1437                  $width = $height = false;
1438              }
1439              else
1440              {
1441                  if ($width === false)
1442                  {
1443                      list($imgsrc, $height, $width) = explode('*', $this->theme[$img]);
1444                  }
1445                  else
1446                  {
1447                      list($imgsrc, $height) = explode('*', $this->theme[$img]);
1448                  }
1449              }
1450  
1451              if ($suffix !== '')
1452              {
1453                  $imgsrc = str_replace('{SUFFIX}', $suffix, $imgsrc);
1454              }
1455  
1456              $img_data['src'] = $phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . str_replace('{LANG}', $this->img_lang, $imgsrc);
1457              $img_data['width'] = $width;
1458              $img_data['height'] = $height;
1459          }
1460  
1461          $alt = (!empty($this->lang[$alt])) ? $this->lang[$alt] : $alt;
1462  
1463          switch ($type)
1464          {
1465              case 'src':
1466                  return $img_data['src'];
1467              break;
1468              
1469              case 'width':
1470                  return $img_data['width'];
1471              break;
1472  
1473              case 'height':
1474                  return $img_data['height'];
1475              break;
1476  
1477              default:
1478                  return '<img src="' . $img_data['src'] . '"' . (($img_data['width']) ? ' width="' . $img_data['width'] . '"' : '') . (($img_data['height']) ? ' height="' . $img_data['height'] . '"' : '') . ' alt="' . $alt . '" title="' . $alt . '" />';
1479              break;
1480          }
1481      }
1482  
1483      /**
1484      * Get option bit field from user options
1485      */
1486  	function optionget($key, $data = false)
1487      {
1488          if (!isset($this->keyvalues[$key]))
1489          {
1490              $var = ($data) ? $data : $this->data['user_options'];
1491              $this->keyvalues[$key] = ($var & 1 << $this->keyoptions[$key]) ? true : false;
1492          }
1493  
1494          return $this->keyvalues[$key];
1495      }
1496  
1497      /**
1498      * Set option bit field for user options
1499      */
1500  	function optionset($key, $value, $data = false)
1501      {
1502          $var = ($data) ? $data : $this->data['user_options'];
1503  
1504          if ($value && !($var & 1 << $this->keyoptions[$key]))
1505          {
1506              $var += 1 << $this->keyoptions[$key];
1507          }
1508          else if (!$value && ($var & 1 << $this->keyoptions[$key]))
1509          {
1510              $var -= 1 << $this->keyoptions[$key];
1511          }
1512          else
1513          {
1514              return ($data) ? $var : false;
1515          }
1516  
1517          if (!$data)
1518          {
1519              $this->data['user_options'] = $var;
1520              return true;
1521          }
1522          else
1523          {
1524              return $var;
1525          }
1526      }
1527  }
1528  
1529  ?>


Generated: Wed Nov 22 00:35:05 2006 Cross-referenced by PHPXref 0.6