[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/includes/ -> auth.php (source)

   1  <?php
   2  /**
   3  *
   4  * @package phpBB3
   5  * @version $Id$
   6  * @copyright (c) 2005 phpBB Group
   7  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
   8  *
   9  */
  10  
  11  /**
  12  * @ignore
  13  */
  14  if (!defined('IN_PHPBB'))
  15  {
  16      exit;
  17  }
  18  
  19  /**
  20  * Permission/Auth class
  21  * @package phpBB3
  22  */
  23  class auth
  24  {
  25      var $acl = array();
  26      var $cache = array();
  27      var $acl_options = array();
  28      var $acl_forum_ids = false;
  29  
  30      /**
  31      * Init permissions
  32      */
  33  	function acl(&$userdata)
  34      {
  35          global $db, $cache;
  36  
  37          $this->acl = $this->cache = $this->acl_options = array();
  38          $this->acl_forum_ids = false;
  39  
  40          if (($this->acl_options = $cache->get('_acl_options')) === false)
  41          {
  42              $sql = 'SELECT auth_option_id, auth_option, is_global, is_local
  43                  FROM ' . ACL_OPTIONS_TABLE . '
  44                  ORDER BY auth_option_id';
  45              $result = $db->sql_query($sql);
  46  
  47              $global = $local = 0;
  48              $this->acl_options = array();
  49              while ($row = $db->sql_fetchrow($result))
  50              {
  51                  if ($row['is_global'])
  52                  {
  53                      $this->acl_options['global'][$row['auth_option']] = $global++;
  54                  }
  55  
  56                  if ($row['is_local'])
  57                  {
  58                      $this->acl_options['local'][$row['auth_option']] = $local++;
  59                  }
  60  
  61                  $this->acl_options['id'][$row['auth_option']] = (int) $row['auth_option_id'];
  62                  $this->acl_options['option'][(int) $row['auth_option_id']] = $row['auth_option'];
  63              }
  64              $db->sql_freeresult($result);
  65  
  66              $cache->put('_acl_options', $this->acl_options);
  67          }
  68  
  69          if (!trim($userdata['user_permissions']))
  70          {
  71              $this->acl_cache($userdata);
  72          }
  73  
  74          // Fill ACL array
  75          $this->_fill_acl($userdata['user_permissions']);
  76  
  77          // Verify bitstring length with options provided...
  78          $renew = false;
  79          $global_length = sizeof($this->acl_options['global']);
  80          $local_length = sizeof($this->acl_options['local']);
  81  
  82          // Specify comparing length (bitstring is padded to 31 bits)
  83          $global_length = ($global_length % 31) ? ($global_length - ($global_length % 31) + 31) : $global_length;
  84          $local_length = ($local_length % 31) ? ($local_length - ($local_length % 31) + 31) : $local_length;
  85  
  86          // You thought we are finished now? Noooo... now compare them.
  87          foreach ($this->acl as $forum_id => $bitstring)
  88          {
  89              if (($forum_id && strlen($bitstring) != $local_length) || (!$forum_id && strlen($bitstring) != $global_length))
  90              {
  91                  $renew = true;
  92                  break;
  93              }
  94          }
  95  
  96          // If a bitstring within the list does not match the options, we have a user with incorrect permissions set and need to renew them
  97          if ($renew)
  98          {
  99              $this->acl_cache($userdata);
 100              $this->_fill_acl($userdata['user_permissions']);
 101          }
 102  
 103          return;
 104      }
 105  
 106      /**
 107      * Fill ACL array with relevant bitstrings from user_permissions column
 108      * @access private
 109      */
 110  	function _fill_acl($user_permissions)
 111      {
 112          $seq_cache = array();
 113          $this->acl = array();
 114          $user_permissions = explode("\n", $user_permissions);
 115  
 116          foreach ($user_permissions as $f => $seq)
 117          {
 118              if ($seq)
 119              {
 120                  $i = 0;
 121  
 122                  if (!isset($this->acl[$f]))
 123                  {
 124                      $this->acl[$f] = '';
 125                  }
 126  
 127                  while ($subseq = substr($seq, $i, 6))
 128                  {
 129                      if (isset($seq_cache[$subseq]))
 130                      {
 131                          $converted = $seq_cache[$subseq];
 132                      }
 133                      else
 134                      {
 135                          $converted = $seq_cache[$subseq] = str_pad(base_convert($subseq, 36, 2), 31, 0, STR_PAD_LEFT);
 136                      }
 137  
 138                      // We put the original bitstring into the acl array
 139                      $this->acl[$f] .= $converted;
 140                      $i += 6;
 141                  }
 142              }
 143          }
 144      }
 145  
 146      /**
 147      * Look up an option
 148      * if the option is prefixed with !, then the result becomes negated
 149      *
 150      * If a forum id is specified the local option will be combined with a global option if one exist.
 151      * If a forum id is not specified, only the global option will be checked.
 152      */
 153  	function acl_get($opt, $f = 0)
 154      {
 155          $negate = false;
 156  
 157          if (strpos($opt, '!') === 0)
 158          {
 159              $negate = true;
 160              $opt = substr($opt, 1);
 161          }
 162  
 163          if (!isset($this->cache[$f][$opt]))
 164          {
 165              // We combine the global/local option with an OR because some options are global and local.
 166              // If the user has the global permission the local one is true too and vice versa
 167              $this->cache[$f][$opt] = false;
 168  
 169              // Is this option a global permission setting?
 170              if (isset($this->acl_options['global'][$opt]))
 171              {
 172                  if (isset($this->acl[0]))
 173                  {
 174                      $this->cache[$f][$opt] = $this->acl[0][$this->acl_options['global'][$opt]];
 175                  }
 176              }
 177  
 178              // Is this option a local permission setting?
 179              // But if we check for a global option only, we won't combine the options...
 180              if ($f != 0 && isset($this->acl_options['local'][$opt]))
 181              {
 182                  if (isset($this->acl[$f]) && isset($this->acl[$f][$this->acl_options['local'][$opt]]))
 183                  {
 184                      $this->cache[$f][$opt] |= $this->acl[$f][$this->acl_options['local'][$opt]];
 185                  }
 186              }
 187          }
 188  
 189          // Founder always has all global options set to true...
 190          return ($negate) ? !$this->cache[$f][$opt] : $this->cache[$f][$opt];
 191      }
 192  
 193      /**
 194      * Get forums with the specified permission setting
 195      * if the option is prefixed with !, then the result becomes nagated
 196      *
 197      * @param bool $clean set to true if only values needs to be returned which are set/unset
 198      */
 199  	function acl_getf($opt, $clean = false)
 200      {
 201          $acl_f = array();
 202          $negate = false;
 203  
 204          if (strpos($opt, '!') === 0)
 205          {
 206              $negate = true;
 207              $opt = substr($opt, 1);
 208          }
 209  
 210          // If we retrieve a list of forums not having permissions in, we need to get every forum_id
 211          if ($negate)
 212          {
 213              if ($this->acl_forum_ids === false)
 214              {
 215                  global $db;
 216  
 217                  $sql = 'SELECT forum_id
 218                      FROM ' . FORUMS_TABLE;
 219  
 220                  if (sizeof($this->acl))
 221                  {
 222                      $sql .= ' WHERE ' . $db->sql_in_set('forum_id', array_keys($this->acl), true);
 223                  }
 224                  $result = $db->sql_query($sql);
 225  
 226                  $this->acl_forum_ids = array();
 227                  while ($row = $db->sql_fetchrow($result))
 228                  {
 229                      $this->acl_forum_ids[] = $row['forum_id'];
 230                  }
 231                  $db->sql_freeresult($result);
 232              }
 233          }
 234  
 235          if (isset($this->acl_options['local'][$opt]))
 236          {
 237              foreach ($this->acl as $f => $bitstring)
 238              {
 239                  // Skip global settings
 240                  if (!$f)
 241                  {
 242                      continue;
 243                  }
 244  
 245                  $allowed = (!isset($this->cache[$f][$opt])) ? $this->acl_get($opt, $f) : $this->cache[$f][$opt];
 246  
 247                  if (!$clean)
 248                  {
 249                      $acl_f[$f][$opt] = ($negate) ? !$allowed : $allowed;
 250                  }
 251                  else
 252                  {
 253                      if (($negate && !$allowed) || (!$negate && $allowed))
 254                      {
 255                          $acl_f[$f][$opt] = 1;
 256                      }
 257                  }
 258              }
 259          }
 260  
 261          // If we get forum_ids not having this permission, we need to fill the remaining parts
 262          if ($negate && sizeof($this->acl_forum_ids))
 263          {
 264              foreach ($this->acl_forum_ids as $f)
 265              {
 266                  $acl_f[$f][$opt] = 1;
 267              }
 268          }
 269  
 270          return $acl_f;
 271      }
 272  
 273      /**
 274      * Get local permission state for any forum.
 275      *
 276      * Returns true if user has the permission in one or more forums, false if in no forum.
 277      * If global option is checked it returns the global state (same as acl_get($opt))
 278      * Local option has precedence...
 279      */
 280  	function acl_getf_global($opt)
 281      {
 282          if (is_array($opt))
 283          {
 284              // evaluates to true as soon as acl_getf_global is true for one option
 285              foreach ($opt as $check_option)
 286              {
 287                  if ($this->acl_getf_global($check_option))
 288                  {
 289                      return true;
 290                  }
 291              }
 292  
 293              return false;
 294          }
 295  
 296          if (isset($this->acl_options['local'][$opt]))
 297          {
 298              foreach ($this->acl as $f => $bitstring)
 299              {
 300                  // Skip global settings
 301                  if (!$f)
 302                  {
 303                      continue;
 304                  }
 305  
 306                  // as soon as the user has any permission we're done so return true
 307                  if ((!isset($this->cache[$f][$opt])) ? $this->acl_get($opt, $f) : $this->cache[$f][$opt])
 308                  {
 309                      return true;
 310                  }
 311              }
 312          }
 313          else if (isset($this->acl_options['global'][$opt]))
 314          {
 315              return $this->acl_get($opt);
 316          }
 317  
 318          return false;
 319      }
 320  
 321      /**
 322      * Get permission settings (more than one)
 323      */
 324  	function acl_gets()
 325      {
 326          $args = func_get_args();
 327          $f = array_pop($args);
 328  
 329          if (!is_numeric($f))
 330          {
 331              $args[] = $f;
 332              $f = 0;
 333          }
 334  
 335          // alternate syntax: acl_gets(array('m_', 'a_'), $forum_id)
 336          if (is_array($args[0]))
 337          {
 338              $args = $args[0];
 339          }
 340  
 341          $acl = 0;
 342          foreach ($args as $opt)
 343          {
 344              $acl |= $this->acl_get($opt, $f);
 345          }
 346  
 347          return $acl;
 348      }
 349  
 350      /**
 351      * Get permission listing based on user_id/options/forum_ids
 352      *
 353      * Be careful when using this function with permissions a_, m_, u_ and f_ !
 354      * It may not work correctly. When a user group grants an a_* permission,
 355      * e.g. a_foo, but the user's a_foo permission is set to "Never", then
 356      * the user does not in fact have the a_ permission.
 357      * But the user will still be listed as having the a_ permission.
 358      *
 359      * For more information see: http://tracker.phpbb.com/browse/PHPBB3-10252
 360      */
 361  	function acl_get_list($user_id = false, $opts = false, $forum_id = false)
 362      {
 363          if ($user_id !== false && !is_array($user_id) && $opts === false && $forum_id === false)
 364          {
 365              $hold_ary = array($user_id => $this->acl_raw_data_single_user($user_id));
 366          }
 367          else
 368          {
 369              $hold_ary = $this->acl_raw_data($user_id, $opts, $forum_id);
 370          }
 371  
 372          $auth_ary = array();
 373          foreach ($hold_ary as $user_id => $forum_ary)
 374          {
 375              foreach ($forum_ary as $forum_id => $auth_option_ary)
 376              {
 377                  foreach ($auth_option_ary as $auth_option => $auth_setting)
 378                  {
 379                      if ($auth_setting)
 380                      {
 381                          $auth_ary[$forum_id][$auth_option][] = $user_id;
 382                      }
 383                  }
 384              }
 385          }
 386  
 387          return $auth_ary;
 388      }
 389  
 390      /**
 391      * Cache data to user_permissions row
 392      */
 393  	function acl_cache(&$userdata)
 394      {
 395          global $db;
 396  
 397          // Empty user_permissions
 398          $userdata['user_permissions'] = '';
 399  
 400          $hold_ary = $this->acl_raw_data_single_user($userdata['user_id']);
 401  
 402          // Key 0 in $hold_ary are global options, all others are forum_ids
 403  
 404          // If this user is founder we're going to force fill the admin options ...
 405          if ($userdata['user_type'] == USER_FOUNDER)
 406          {
 407              foreach ($this->acl_options['global'] as $opt => $id)
 408              {
 409                  if (strpos($opt, 'a_') === 0)
 410                  {
 411                      $hold_ary[0][$this->acl_options['id'][$opt]] = ACL_YES;
 412                  }
 413              }
 414          }
 415  
 416          $hold_str = $this->build_bitstring($hold_ary);
 417  
 418          if ($hold_str)
 419          {
 420              $userdata['user_permissions'] = $hold_str;
 421  
 422              $sql = 'UPDATE ' . USERS_TABLE . "
 423                  SET user_permissions = '" . $db->sql_escape($userdata['user_permissions']) . "',
 424                      user_perm_from = 0
 425                  WHERE user_id = " . $userdata['user_id'];
 426              $db->sql_query($sql);
 427          }
 428  
 429          return;
 430      }
 431  
 432      /**
 433      * Build bitstring from permission set
 434      */
 435  	function build_bitstring(&$hold_ary)
 436      {
 437          $hold_str = '';
 438  
 439          if (sizeof($hold_ary))
 440          {
 441              ksort($hold_ary);
 442  
 443              $last_f = 0;
 444  
 445              foreach ($hold_ary as $f => $auth_ary)
 446              {
 447                  $ary_key = (!$f) ? 'global' : 'local';
 448  
 449                  $bitstring = array();
 450                  foreach ($this->acl_options[$ary_key] as $opt => $id)
 451                  {
 452                      if (isset($auth_ary[$this->acl_options['id'][$opt]]))
 453                      {
 454                          $bitstring[$id] = $auth_ary[$this->acl_options['id'][$opt]];
 455  
 456                          $option_key = substr($opt, 0, strpos($opt, '_') + 1);
 457  
 458                          // If one option is allowed, the global permission for this option has to be allowed too
 459                          // example: if the user has the a_ permission this means he has one or more a_* permissions
 460                          if ($auth_ary[$this->acl_options['id'][$opt]] == ACL_YES && (!isset($bitstring[$this->acl_options[$ary_key][$option_key]]) || $bitstring[$this->acl_options[$ary_key][$option_key]] == ACL_NEVER))
 461                          {
 462                              $bitstring[$this->acl_options[$ary_key][$option_key]] = ACL_YES;
 463                          }
 464                      }
 465                      else
 466                      {
 467                          $bitstring[$id] = ACL_NEVER;
 468                      }
 469                  }
 470  
 471                  // Now this bitstring defines the permission setting for the current forum $f (or global setting)
 472                  $bitstring = implode('', $bitstring);
 473  
 474                  // The line number indicates the id, therefore we have to add empty lines for those ids not present
 475                  $hold_str .= str_repeat("\n", $f - $last_f);
 476  
 477                  // Convert bitstring for storage - we do not use binary/bytes because PHP's string functions are not fully binary safe
 478                  for ($i = 0, $bit_length = strlen($bitstring); $i < $bit_length; $i += 31)
 479                  {
 480                      $hold_str .= str_pad(base_convert(str_pad(substr($bitstring, $i, 31), 31, 0, STR_PAD_RIGHT), 2, 36), 6, 0, STR_PAD_LEFT);
 481                  }
 482  
 483                  $last_f = $f;
 484              }
 485              unset($bitstring);
 486  
 487              $hold_str = rtrim($hold_str);
 488          }
 489  
 490          return $hold_str;
 491      }
 492  
 493      /**
 494      * Clear one or all users cached permission settings
 495      */
 496  	function acl_clear_prefetch($user_id = false)
 497      {
 498          global $db, $cache;
 499  
 500          // Rebuild options cache
 501          $cache->destroy('_role_cache');
 502  
 503          $sql = 'SELECT *
 504              FROM ' . ACL_ROLES_DATA_TABLE . '
 505              ORDER BY role_id ASC';
 506          $result = $db->sql_query($sql);
 507  
 508          $this->role_cache = array();
 509          while ($row = $db->sql_fetchrow($result))
 510          {
 511              $this->role_cache[$row['role_id']][$row['auth_option_id']] = (int) $row['auth_setting'];
 512          }
 513          $db->sql_freeresult($result);
 514  
 515          foreach ($this->role_cache as $role_id => $role_options)
 516          {
 517              $this->role_cache[$role_id] = serialize($role_options);
 518          }
 519  
 520          $cache->put('_role_cache', $this->role_cache);
 521  
 522          // Now empty user permissions
 523          $where_sql = '';
 524  
 525          if ($user_id !== false)
 526          {
 527              $user_id = (!is_array($user_id)) ? $user_id = array((int) $user_id) : array_map('intval', $user_id);
 528              $where_sql = ' WHERE ' . $db->sql_in_set('user_id', $user_id);
 529          }
 530  
 531          $sql = 'UPDATE ' . USERS_TABLE . "
 532              SET user_permissions = '',
 533                  user_perm_from = 0
 534              $where_sql";
 535          $db->sql_query($sql);
 536  
 537          return;
 538      }
 539  
 540      /**
 541      * Get assigned roles
 542      */
 543  	function acl_role_data($user_type, $role_type, $ug_id = false, $forum_id = false)
 544      {
 545          global $db;
 546  
 547          $roles = array();
 548  
 549          $sql_id = ($user_type == 'user') ? 'user_id' : 'group_id';
 550  
 551          $sql_ug = ($ug_id !== false) ? ((!is_array($ug_id)) ? "AND a.$sql_id = $ug_id" : 'AND ' . $db->sql_in_set("a.$sql_id", $ug_id)) : '';
 552          $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? "AND a.forum_id = $forum_id" : 'AND ' . $db->sql_in_set('a.forum_id', $forum_id)) : '';
 553  
 554          // Grab assigned roles...
 555          $sql = 'SELECT a.auth_role_id, a.' . $sql_id . ', a.forum_id
 556              FROM ' . (($user_type == 'user') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE) . ' a, ' . ACL_ROLES_TABLE . " r
 557              WHERE a.auth_role_id = r.role_id
 558                  AND r.role_type = '" . $db->sql_escape($role_type) . "'
 559                  $sql_ug
 560                  $sql_forum
 561              ORDER BY r.role_order ASC";
 562          $result = $db->sql_query($sql);
 563  
 564          while ($row = $db->sql_fetchrow($result))
 565          {
 566              $roles[$row[$sql_id]][$row['forum_id']] = $row['auth_role_id'];
 567          }
 568          $db->sql_freeresult($result);
 569  
 570          return $roles;
 571      }
 572  
 573      /**
 574      * Get raw acl data based on user/option/forum
 575      */
 576  	function acl_raw_data($user_id = false, $opts = false, $forum_id = false)
 577      {
 578          global $db;
 579  
 580          $sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? 'user_id = ' . (int) $user_id : $db->sql_in_set('user_id', array_map('intval', $user_id))) : '';
 581          $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? 'AND a.forum_id = ' . (int) $forum_id : 'AND ' . $db->sql_in_set('a.forum_id', array_map('intval', $forum_id))) : '';
 582  
 583          $sql_opts = $sql_opts_select = $sql_opts_from = '';
 584          $hold_ary = array();
 585  
 586          if ($opts !== false)
 587          {
 588              $sql_opts_select = ', ao.auth_option';
 589              $sql_opts_from = ', ' . ACL_OPTIONS_TABLE . ' ao';
 590              $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts);
 591          }
 592  
 593          $sql_ary = array();
 594  
 595          // Grab non-role settings - user-specific
 596          $sql_ary[] = 'SELECT a.user_id, a.forum_id, a.auth_setting, a.auth_option_id' . $sql_opts_select . '
 597              FROM ' . ACL_USERS_TABLE . ' a' . $sql_opts_from . '
 598              WHERE a.auth_role_id = 0 ' .
 599                  (($sql_opts_from) ? 'AND a.auth_option_id = ao.auth_option_id ' : '') .
 600                  (($sql_user) ? 'AND a.' . $sql_user : '') . "
 601                  $sql_forum
 602                  $sql_opts";
 603  
 604          // Now the role settings - user-specific
 605          $sql_ary[] = 'SELECT a.user_id, a.forum_id, r.auth_option_id, r.auth_setting, r.auth_option_id' . $sql_opts_select . '
 606              FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . '
 607              WHERE a.auth_role_id = r.role_id ' .
 608                  (($sql_opts_from) ? 'AND r.auth_option_id = ao.auth_option_id ' : '') .
 609                  (($sql_user) ? 'AND a.' . $sql_user : '') . "
 610                  $sql_forum
 611                  $sql_opts";
 612  
 613          foreach ($sql_ary as $sql)
 614          {
 615              $result = $db->sql_query($sql);
 616  
 617              while ($row = $db->sql_fetchrow($result))
 618              {
 619                  $option = ($sql_opts_select) ? $row['auth_option'] : $this->acl_options['option'][$row['auth_option_id']];
 620                  $hold_ary[$row['user_id']][$row['forum_id']][$option] = $row['auth_setting'];
 621              }
 622              $db->sql_freeresult($result);
 623          }
 624  
 625          $sql_ary = array();
 626  
 627          // Now grab group settings - non-role specific...
 628          $sql_ary[] = 'SELECT ug.user_id, a.forum_id, a.auth_setting, a.auth_option_id' . $sql_opts_select . '
 629              FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g' . $sql_opts_from . '
 630              WHERE a.auth_role_id = 0 ' .
 631                  (($sql_opts_from) ? 'AND a.auth_option_id = ao.auth_option_id ' : '') . '
 632                  AND a.group_id = ug.group_id
 633                  AND g.group_id = ug.group_id
 634                  AND ug.user_pending = 0
 635                  AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
 636                  ' . (($sql_user) ? 'AND ug.' . $sql_user : '') . "
 637                  $sql_forum
 638                  $sql_opts";
 639  
 640          // Now grab group settings - role specific...
 641          $sql_ary[] = 'SELECT ug.user_id, a.forum_id, r.auth_setting, r.auth_option_id' . $sql_opts_select . '
 642              FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . '
 643              WHERE a.auth_role_id = r.role_id ' .
 644                  (($sql_opts_from) ? 'AND r.auth_option_id = ao.auth_option_id ' : '') . '
 645                  AND a.group_id = ug.group_id
 646                  AND g.group_id = ug.group_id
 647                  AND ug.user_pending = 0
 648                  AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
 649                  ' . (($sql_user) ? 'AND ug.' . $sql_user : '') . "
 650                  $sql_forum
 651                  $sql_opts";
 652  
 653          foreach ($sql_ary as $sql)
 654          {
 655              $result = $db->sql_query($sql);
 656  
 657              while ($row = $db->sql_fetchrow($result))
 658              {
 659                  $option = ($sql_opts_select) ? $row['auth_option'] : $this->acl_options['option'][$row['auth_option_id']];
 660  
 661                  if (!isset($hold_ary[$row['user_id']][$row['forum_id']][$option]) || (isset($hold_ary[$row['user_id']][$row['forum_id']][$option]) && $hold_ary[$row['user_id']][$row['forum_id']][$option] != ACL_NEVER))
 662                  {
 663                      $hold_ary[$row['user_id']][$row['forum_id']][$option] = $row['auth_setting'];
 664  
 665                      // If we detect ACL_NEVER, we will unset the flag option (within building the bitstring it is correctly set again)
 666                      if ($row['auth_setting'] == ACL_NEVER)
 667                      {
 668                          $flag = substr($option, 0, strpos($option, '_') + 1);
 669  
 670                          if (isset($hold_ary[$row['user_id']][$row['forum_id']][$flag]) && $hold_ary[$row['user_id']][$row['forum_id']][$flag] == ACL_YES)
 671                          {
 672                              unset($hold_ary[$row['user_id']][$row['forum_id']][$flag]);
 673  
 674  /*                            if (in_array(ACL_YES, $hold_ary[$row['user_id']][$row['forum_id']]))
 675                              {
 676                                  $hold_ary[$row['user_id']][$row['forum_id']][$flag] = ACL_YES;
 677                              }
 678  */
 679                          }
 680                      }
 681                  }
 682              }
 683              $db->sql_freeresult($result);
 684          }
 685  
 686          return $hold_ary;
 687      }
 688  
 689      /**
 690      * Get raw user based permission settings
 691      */
 692  	function acl_user_raw_data($user_id = false, $opts = false, $forum_id = false)
 693      {
 694          global $db;
 695  
 696          $sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? 'user_id = ' . (int) $user_id : $db->sql_in_set('user_id', array_map('intval', $user_id))) : '';
 697          $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? 'AND a.forum_id = ' . (int) $forum_id : 'AND ' . $db->sql_in_set('a.forum_id', array_map('intval', $forum_id))) : '';
 698  
 699          $sql_opts = '';
 700          $hold_ary = $sql_ary = array();
 701  
 702          if ($opts !== false)
 703          {
 704              $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts);
 705          }
 706  
 707          // Grab user settings - non-role specific...
 708          $sql_ary[] = 'SELECT a.user_id, a.forum_id, a.auth_setting, a.auth_option_id, ao.auth_option
 709              FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_OPTIONS_TABLE . ' ao
 710              WHERE a.auth_role_id = 0
 711                  AND a.auth_option_id = ao.auth_option_id ' .
 712                  (($sql_user) ? 'AND a.' . $sql_user : '') . "
 713                  $sql_forum
 714                  $sql_opts
 715              ORDER BY a.forum_id, ao.auth_option";
 716  
 717          // Now the role settings - user-specific
 718          $sql_ary[] = 'SELECT a.user_id, a.forum_id, r.auth_option_id, r.auth_setting, r.auth_option_id, ao.auth_option
 719              FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' ao
 720              WHERE a.auth_role_id = r.role_id
 721                  AND r.auth_option_id = ao.auth_option_id ' .
 722                  (($sql_user) ? 'AND a.' . $sql_user : '') . "
 723                  $sql_forum
 724                  $sql_opts
 725              ORDER BY a.forum_id, ao.auth_option";
 726  
 727          foreach ($sql_ary as $sql)
 728          {
 729              $result = $db->sql_query($sql);
 730  
 731              while ($row = $db->sql_fetchrow($result))
 732              {
 733                  $hold_ary[$row['user_id']][$row['forum_id']][$row['auth_option']] = $row['auth_setting'];
 734              }
 735              $db->sql_freeresult($result);
 736          }
 737  
 738          return $hold_ary;
 739      }
 740  
 741      /**
 742      * Get raw group based permission settings
 743      */
 744  	function acl_group_raw_data($group_id = false, $opts = false, $forum_id = false)
 745      {
 746          global $db;
 747  
 748          $sql_group = ($group_id !== false) ? ((!is_array($group_id)) ? 'group_id = ' . (int) $group_id : $db->sql_in_set('group_id', array_map('intval', $group_id))) : '';
 749          $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? 'AND a.forum_id = ' . (int) $forum_id : 'AND ' . $db->sql_in_set('a.forum_id', array_map('intval', $forum_id))) : '';
 750  
 751          $sql_opts = '';
 752          $hold_ary = $sql_ary = array();
 753  
 754          if ($opts !== false)
 755          {
 756              $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts);
 757          }
 758  
 759          // Grab group settings - non-role specific...
 760          $sql_ary[] = 'SELECT a.group_id, a.forum_id, a.auth_setting, a.auth_option_id, ao.auth_option
 761              FROM ' . ACL_GROUPS_TABLE . ' a, ' . ACL_OPTIONS_TABLE . ' ao
 762              WHERE a.auth_role_id = 0
 763                  AND a.auth_option_id = ao.auth_option_id ' .
 764                  (($sql_group) ? 'AND a.' . $sql_group : '') . "
 765                  $sql_forum
 766                  $sql_opts
 767              ORDER BY a.forum_id, ao.auth_option";
 768  
 769          // Now grab group settings - role specific...
 770          $sql_ary[] = 'SELECT a.group_id, a.forum_id, r.auth_setting, r.auth_option_id, ao.auth_option
 771              FROM ' . ACL_GROUPS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' ao
 772              WHERE a.auth_role_id = r.role_id
 773                  AND r.auth_option_id = ao.auth_option_id ' .
 774                  (($sql_group) ? 'AND a.' . $sql_group : '') . "
 775                  $sql_forum
 776                  $sql_opts
 777              ORDER BY a.forum_id, ao.auth_option";
 778  
 779          foreach ($sql_ary as $sql)
 780          {
 781              $result = $db->sql_query($sql);
 782  
 783              while ($row = $db->sql_fetchrow($result))
 784              {
 785                  $hold_ary[$row['group_id']][$row['forum_id']][$row['auth_option']] = $row['auth_setting'];
 786              }
 787              $db->sql_freeresult($result);
 788          }
 789  
 790          return $hold_ary;
 791      }
 792  
 793      /**
 794      * Get raw acl data based on user for caching user_permissions
 795      * This function returns the same data as acl_raw_data(), but without the user id as the first key within the array.
 796      */
 797  	function acl_raw_data_single_user($user_id)
 798      {
 799          global $db, $cache;
 800  
 801          // Check if the role-cache is there
 802          if (($this->role_cache = $cache->get('_role_cache')) === false)
 803          {
 804              $this->role_cache = array();
 805  
 806              // We pre-fetch roles
 807              $sql = 'SELECT *
 808                  FROM ' . ACL_ROLES_DATA_TABLE . '
 809                  ORDER BY role_id ASC';
 810              $result = $db->sql_query($sql);
 811  
 812              while ($row = $db->sql_fetchrow($result))
 813              {
 814                  $this->role_cache[$row['role_id']][$row['auth_option_id']] = (int) $row['auth_setting'];
 815              }
 816              $db->sql_freeresult($result);
 817  
 818              foreach ($this->role_cache as $role_id => $role_options)
 819              {
 820                  $this->role_cache[$role_id] = serialize($role_options);
 821              }
 822  
 823              $cache->put('_role_cache', $this->role_cache);
 824          }
 825  
 826          $hold_ary = array();
 827  
 828          // Grab user-specific permission settings
 829          $sql = 'SELECT forum_id, auth_option_id, auth_role_id, auth_setting
 830              FROM ' . ACL_USERS_TABLE . '
 831              WHERE user_id = ' . $user_id;
 832          $result = $db->sql_query($sql);
 833  
 834          while ($row = $db->sql_fetchrow($result))
 835          {
 836              // If a role is assigned, assign all options included within this role. Else, only set this one option.
 837              if ($row['auth_role_id'])
 838              {
 839                  $hold_ary[$row['forum_id']] = (empty($hold_ary[$row['forum_id']])) ? unserialize($this->role_cache[$row['auth_role_id']]) : $hold_ary[$row['forum_id']] + unserialize($this->role_cache[$row['auth_role_id']]);
 840              }
 841              else
 842              {
 843                  $hold_ary[$row['forum_id']][$row['auth_option_id']] = $row['auth_setting'];
 844              }
 845          }
 846          $db->sql_freeresult($result);
 847  
 848          // Now grab group-specific permission settings
 849          $sql = 'SELECT a.forum_id, a.auth_option_id, a.auth_role_id, a.auth_setting
 850              FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g
 851              WHERE a.group_id = ug.group_id
 852                  AND g.group_id = ug.group_id
 853                  AND ug.user_pending = 0
 854                  AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
 855                  AND ug.user_id = ' . $user_id;
 856          $result = $db->sql_query($sql);
 857  
 858          while ($row = $db->sql_fetchrow($result))
 859          {
 860              if (!$row['auth_role_id'])
 861              {
 862                  $this->_set_group_hold_ary($hold_ary[$row['forum_id']], $row['auth_option_id'], $row['auth_setting']);
 863              }
 864              else if (!empty($this->role_cache[$row['auth_role_id']]))
 865              {
 866                  foreach (unserialize($this->role_cache[$row['auth_role_id']]) as $option_id => $setting)
 867                  {
 868                      $this->_set_group_hold_ary($hold_ary[$row['forum_id']], $option_id, $setting);
 869                  }
 870              }
 871          }
 872          $db->sql_freeresult($result);
 873  
 874          return $hold_ary;
 875      }
 876  
 877      /**
 878      * Private function snippet for setting a specific piece of the hold_ary
 879      */
 880  	function _set_group_hold_ary(&$hold_ary, $option_id, $setting)
 881      {
 882          if (!isset($hold_ary[$option_id]) || (isset($hold_ary[$option_id]) && $hold_ary[$option_id] != ACL_NEVER))
 883          {
 884              $hold_ary[$option_id] = $setting;
 885  
 886              // If we detect ACL_NEVER, we will unset the flag option (within building the bitstring it is correctly set again)
 887              if ($setting == ACL_NEVER)
 888              {
 889                  $flag = substr($this->acl_options['option'][$option_id], 0, strpos($this->acl_options['option'][$option_id], '_') + 1);
 890                  $flag = (int) $this->acl_options['id'][$flag];
 891  
 892                  if (isset($hold_ary[$flag]) && $hold_ary[$flag] == ACL_YES)
 893                  {
 894                      unset($hold_ary[$flag]);
 895  
 896  /*                    This is uncommented, because i suspect this being slightly wrong due to mixed permission classes being possible
 897                      if (in_array(ACL_YES, $hold_ary))
 898                      {
 899                          $hold_ary[$flag] = ACL_YES;
 900                      }*/
 901                  }
 902              }
 903          }
 904      }
 905  
 906      /**
 907      * Authentication plug-ins is largely down to Sergey Kanareykin, our thanks to him.
 908      */
 909  	function login($username, $password, $autologin = false, $viewonline = 1, $admin = 0)
 910      {
 911          global $config, $db, $user, $phpbb_root_path, $phpEx;
 912  
 913          $method = trim(basename($config['auth_method']));
 914          include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
 915  
 916          $method = 'login_' . $method;
 917          if (function_exists($method))
 918          {
 919              $login = $method($username, $password, $user->ip, $user->browser, $user->forwarded_for);
 920  
 921              // If the auth module wants us to create an empty profile do so and then treat the status as LOGIN_SUCCESS
 922              if ($login['status'] == LOGIN_SUCCESS_CREATE_PROFILE)
 923              {
 924                  // we are going to use the user_add function so include functions_user.php if it wasn't defined yet
 925                  if (!function_exists('user_add'))
 926                  {
 927                      include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
 928                  }
 929  
 930                  user_add($login['user_row'], (isset($login['cp_data'])) ? $login['cp_data'] : false);
 931  
 932                  $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type
 933                      FROM ' . USERS_TABLE . "
 934                      WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
 935                  $result = $db->sql_query($sql);
 936                  $row = $db->sql_fetchrow($result);
 937                  $db->sql_freeresult($result);
 938  
 939                  if (!$row)
 940                  {
 941                      return array(
 942                          'status'        => LOGIN_ERROR_EXTERNAL_AUTH,
 943                          'error_msg'        => 'AUTH_NO_PROFILE_CREATED',
 944                          'user_row'        => array('user_id' => ANONYMOUS),
 945                      );
 946                  }
 947  
 948                  $login = array(
 949                      'status'    => LOGIN_SUCCESS,
 950                      'error_msg'    => false,
 951                      'user_row'    => $row,
 952                  );
 953              }
 954  
 955              // If login succeeded, we will log the user in... else we pass the login array through...
 956              if ($login['status'] == LOGIN_SUCCESS)
 957              {
 958                  $old_session_id = $user->session_id;
 959  
 960                  if ($admin)
 961                  {
 962                      global $SID, $_SID;
 963  
 964                      $cookie_expire = time() - 31536000;
 965                      $user->set_cookie('u', '', $cookie_expire);
 966                      $user->set_cookie('sid', '', $cookie_expire);
 967                      unset($cookie_expire);
 968  
 969                      $SID = '?sid=';
 970                      $user->session_id = $_SID = '';
 971                  }
 972  
 973                  $result = $user->session_create($login['user_row']['user_id'], $admin, $autologin, $viewonline);
 974  
 975                  // Successful session creation
 976                  if ($result === true)
 977                  {
 978                      // If admin re-authentication we remove the old session entry because a new one has been created...
 979                      if ($admin)
 980                      {
 981                          // the login array is used because the user ids do not differ for re-authentication
 982                          $sql = 'DELETE FROM ' . SESSIONS_TABLE . "
 983                              WHERE session_id = '" . $db->sql_escape($old_session_id) . "'
 984                              AND session_user_id = {$login['user_row']['user_id']}";
 985                          $db->sql_query($sql);
 986                      }
 987  
 988                      return array(
 989                          'status'        => LOGIN_SUCCESS,
 990                          'error_msg'        => false,
 991                          'user_row'        => $login['user_row'],
 992                      );
 993                  }
 994  
 995                  return array(
 996                      'status'        => LOGIN_BREAK,
 997                      'error_msg'        => $result,
 998                      'user_row'        => $login['user_row'],
 999                  );
1000              }
1001  
1002              return $login;
1003          }
1004  
1005          trigger_error('Authentication method not found', E_USER_ERROR);
1006      }
1007  
1008      /**
1009      * Fill auth_option statement for later querying based on the supplied options
1010      */
1011  	function build_auth_option_statement($key, $auth_options, &$sql_opts)
1012      {
1013          global $db;
1014  
1015          if (!is_array($auth_options))
1016          {
1017              if (strpos($auth_options, '%') !== false)
1018              {
1019                  $sql_opts = "AND $key " . $db->sql_like_expression(str_replace('%', $db->any_char, $auth_options));
1020              }
1021              else
1022              {
1023                  $sql_opts = "AND $key = '" . $db->sql_escape($auth_options) . "'";
1024              }
1025          }
1026          else
1027          {
1028              $is_like_expression = false;
1029  
1030              foreach ($auth_options as $option)
1031              {
1032                  if (strpos($option, '%') !== false)
1033                  {
1034                      $is_like_expression = true;
1035                  }
1036              }
1037  
1038              if (!$is_like_expression)
1039              {
1040                  $sql_opts = 'AND ' . $db->sql_in_set($key, $auth_options);
1041              }
1042              else
1043              {
1044                  $sql = array();
1045  
1046                  foreach ($auth_options as $option)
1047                  {
1048                      if (strpos($option, '%') !== false)
1049                      {
1050                          $sql[] = $key . ' ' . $db->sql_like_expression(str_replace('%', $db->any_char, $option));
1051                      }
1052                      else
1053                      {
1054                          $sql[] = $key . " = '" . $db->sql_escape($option) . "'";
1055                      }
1056                  }
1057  
1058                  $sql_opts = 'AND (' . implode(' OR ', $sql) . ')';
1059              }
1060          }
1061      }
1062  }
1063  
1064  ?>


Generated: Wed Oct 2 15:03:47 2013 Cross-referenced by PHPXref 0.7.1