Verzeichnisstruktur phpBB-3.1.0
- Veröffentlicht
- 27.10.2014
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
auth.php
0001 <?php
0002 /**
0003 *
0004 * This file is part of the phpBB Forum Software package.
0005 *
0006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
0007 * @license GNU General Public License, version 2 (GPL-2.0)
0008 *
0009 * For full copyright and license information, please see
0010 * the docs/CREDITS.txt file.
0011 *
0012 */
0013
0014 namespace phpbb\auth;
0015
0016 /**
0017 * Permission/Auth class
0018 */
0019 class auth
0020 {
0021 var $acl = array();
0022 var $cache = array();
0023 var $acl_options = array();
0024 var $acl_forum_ids = false;
0025
0026 /**
0027 * Init permissions
0028 */
0029 function acl(&$userdata)
0030 {
0031 global $db, $cache;
0032
0033 $this->acl = $this->cache = $this->acl_options = array();
0034 $this->acl_forum_ids = false;
0035
0036 if (($this->acl_options = $cache->get('_acl_options')) === false)
0037 {
0038 $sql = 'SELECT auth_option_id, auth_option, is_global, is_local
0039 FROM ' . ACL_OPTIONS_TABLE . '
0040 ORDER BY auth_option_id';
0041 $result = $db->sql_query($sql);
0042
0043 $global = $local = 0;
0044 $this->acl_options = array();
0045 while ($row = $db->sql_fetchrow($result))
0046 {
0047 if ($row['is_global'])
0048 {
0049 $this->acl_options['global'][$row['auth_option']] = $global++;
0050 }
0051
0052 if ($row['is_local'])
0053 {
0054 $this->acl_options['local'][$row['auth_option']] = $local++;
0055 }
0056
0057 $this->acl_options['id'][$row['auth_option']] = (int) $row['auth_option_id'];
0058 $this->acl_options['option'][(int) $row['auth_option_id']] = $row['auth_option'];
0059 }
0060 $db->sql_freeresult($result);
0061
0062 $cache->put('_acl_options', $this->acl_options);
0063 }
0064
0065 if (!trim($userdata['user_permissions']))
0066 {
0067 $this->acl_cache($userdata);
0068 }
0069
0070 // Fill ACL array
0071 $this->_fill_acl($userdata['user_permissions']);
0072
0073 // Verify bitstring length with options provided...
0074 $renew = false;
0075 $global_length = sizeof($this->acl_options['global']);
0076 $local_length = sizeof($this->acl_options['local']);
0077
0078 // Specify comparing length (bitstring is padded to 31 bits)
0079 $global_length = ($global_length % 31) ? ($global_length - ($global_length % 31) + 31) : $global_length;
0080 $local_length = ($local_length % 31) ? ($local_length - ($local_length % 31) + 31) : $local_length;
0081
0082 // You thought we are finished now? Noooo... now compare them.
0083 foreach ($this->acl as $forum_id => $bitstring)
0084 {
0085 if (($forum_id && strlen($bitstring) != $local_length) || (!$forum_id && strlen($bitstring) != $global_length))
0086 {
0087 $renew = true;
0088 break;
0089 }
0090 }
0091
0092 // If a bitstring within the list does not match the options, we have a user with incorrect permissions set and need to renew them
0093 if ($renew)
0094 {
0095 $this->acl_cache($userdata);
0096 $this->_fill_acl($userdata['user_permissions']);
0097 }
0098
0099 return;
0100 }
0101
0102 /**
0103 * Retrieves data wanted by acl function from the database for the
0104 * specified user.
0105 *
0106 * @param int $user_id User ID
0107 * @return array User attributes
0108 */
0109 public function obtain_user_data($user_id)
0110 {
0111 global $db;
0112
0113 $sql = 'SELECT user_id, username, user_permissions, user_type
0114 FROM ' . USERS_TABLE . '
0115 WHERE user_id = ' . $user_id;
0116 $result = $db->sql_query($sql);
0117 $user_data = $db->sql_fetchrow($result);
0118 $db->sql_freeresult($result);
0119 return $user_data;
0120 }
0121
0122 /**
0123 * Fill ACL array with relevant bitstrings from user_permissions column
0124 * @access private
0125 */
0126 function _fill_acl($user_permissions)
0127 {
0128 $seq_cache = array();
0129 $this->acl = array();
0130 $user_permissions = explode("\n", $user_permissions);
0131
0132 foreach ($user_permissions as $f => $seq)
0133 {
0134 if ($seq)
0135 {
0136 $i = 0;
0137
0138 if (!isset($this->acl[$f]))
0139 {
0140 $this->acl[$f] = '';
0141 }
0142
0143 while ($subseq = substr($seq, $i, 6))
0144 {
0145 if (isset($seq_cache[$subseq]))
0146 {
0147 $converted = $seq_cache[$subseq];
0148 }
0149 else
0150 {
0151 $converted = $seq_cache[$subseq] = str_pad(base_convert($subseq, 36, 2), 31, 0, STR_PAD_LEFT);
0152 }
0153
0154 // We put the original bitstring into the acl array
0155 $this->acl[$f] .= $converted;
0156 $i += 6;
0157 }
0158 }
0159 }
0160 }
0161
0162 /**
0163 * Look up an option
0164 * if the option is prefixed with !, then the result becomes negated
0165 *
0166 * If a forum id is specified the local option will be combined with a global option if one exist.
0167 * If a forum id is not specified, only the global option will be checked.
0168 */
0169 function acl_get($opt, $f = 0)
0170 {
0171 $negate = false;
0172
0173 if (strpos($opt, '!') === 0)
0174 {
0175 $negate = true;
0176 $opt = substr($opt, 1);
0177 }
0178
0179 if (!isset($this->cache[$f][$opt]))
0180 {
0181 // We combine the global/local option with an OR because some options are global and local.
0182 // If the user has the global permission the local one is true too and vice versa
0183 $this->cache[$f][$opt] = false;
0184
0185 // Is this option a global permission setting?
0186 if (isset($this->acl_options['global'][$opt]))
0187 {
0188 if (isset($this->acl[0]))
0189 {
0190 $this->cache[$f][$opt] = $this->acl[0][$this->acl_options['global'][$opt]];
0191 }
0192 }
0193
0194 // Is this option a local permission setting?
0195 // But if we check for a global option only, we won't combine the options...
0196 if ($f != 0 && isset($this->acl_options['local'][$opt]))
0197 {
0198 if (isset($this->acl[$f]) && isset($this->acl[$f][$this->acl_options['local'][$opt]]))
0199 {
0200 $this->cache[$f][$opt] |= $this->acl[$f][$this->acl_options['local'][$opt]];
0201 }
0202 }
0203 }
0204
0205 // Founder always has all global options set to true...
0206 return ($negate) ? !$this->cache[$f][$opt] : $this->cache[$f][$opt];
0207 }
0208
0209 /**
0210 * Get forums with the specified permission setting
0211 *
0212 * @param string $opt The permission name to lookup. If prefixed with !, the result is negated.
0213 * @param bool $clean set to true if only values needs to be returned which are set/unset
0214 *
0215 * @return array Contains the forum ids with the specified permission set to true.
0216 This is a nested array: array => forum_id => permission => true
0217 */
0218 function acl_getf($opt, $clean = false)
0219 {
0220 $acl_f = array();
0221 $negate = false;
0222
0223 if (strpos($opt, '!') === 0)
0224 {
0225 $negate = true;
0226 $opt = substr($opt, 1);
0227 }
0228
0229 // If we retrieve a list of forums not having permissions in, we need to get every forum_id
0230 if ($negate)
0231 {
0232 if ($this->acl_forum_ids === false)
0233 {
0234 global $db;
0235
0236 $sql = 'SELECT forum_id
0237 FROM ' . FORUMS_TABLE;
0238
0239 if (sizeof($this->acl))
0240 {
0241 $sql .= ' WHERE ' . $db->sql_in_set('forum_id', array_keys($this->acl), true);
0242 }
0243 $result = $db->sql_query($sql);
0244
0245 $this->acl_forum_ids = array();
0246 while ($row = $db->sql_fetchrow($result))
0247 {
0248 $this->acl_forum_ids[] = $row['forum_id'];
0249 }
0250 $db->sql_freeresult($result);
0251 }
0252 }
0253
0254 if (isset($this->acl_options['local'][$opt]))
0255 {
0256 foreach ($this->acl as $f => $bitstring)
0257 {
0258 // Skip global settings
0259 if (!$f)
0260 {
0261 continue;
0262 }
0263
0264 $allowed = (!isset($this->cache[$f][$opt])) ? $this->acl_get($opt, $f) : $this->cache[$f][$opt];
0265
0266 if (!$clean)
0267 {
0268 $acl_f[$f][$opt] = ($negate) ? !$allowed : $allowed;
0269 }
0270 else
0271 {
0272 if (($negate && !$allowed) || (!$negate && $allowed))
0273 {
0274 $acl_f[$f][$opt] = 1;
0275 }
0276 }
0277 }
0278 }
0279
0280 // If we get forum_ids not having this permission, we need to fill the remaining parts
0281 if ($negate && sizeof($this->acl_forum_ids))
0282 {
0283 foreach ($this->acl_forum_ids as $f)
0284 {
0285 $acl_f[$f][$opt] = 1;
0286 }
0287 }
0288
0289 return $acl_f;
0290 }
0291
0292 /**
0293 * Get local permission state for any forum.
0294 *
0295 * Returns true if user has the permission in one or more forums, false if in no forum.
0296 * If global option is checked it returns the global state (same as acl_get($opt))
0297 * Local option has precedence...
0298 */
0299 function acl_getf_global($opt)
0300 {
0301 if (is_array($opt))
0302 {
0303 // evaluates to true as soon as acl_getf_global is true for one option
0304 foreach ($opt as $check_option)
0305 {
0306 if ($this->acl_getf_global($check_option))
0307 {
0308 return true;
0309 }
0310 }
0311
0312 return false;
0313 }
0314
0315 if (isset($this->acl_options['local'][$opt]))
0316 {
0317 foreach ($this->acl as $f => $bitstring)
0318 {
0319 // Skip global settings
0320 if (!$f)
0321 {
0322 continue;
0323 }
0324
0325 // as soon as the user has any permission we're done so return true
0326 if ((!isset($this->cache[$f][$opt])) ? $this->acl_get($opt, $f) : $this->cache[$f][$opt])
0327 {
0328 return true;
0329 }
0330 }
0331 }
0332 else if (isset($this->acl_options['global'][$opt]))
0333 {
0334 return $this->acl_get($opt);
0335 }
0336
0337 return false;
0338 }
0339
0340 /**
0341 * Get permission settings (more than one)
0342 */
0343 function acl_gets()
0344 {
0345 $args = func_get_args();
0346 $f = array_pop($args);
0347
0348 if (!is_numeric($f))
0349 {
0350 $args[] = $f;
0351 $f = 0;
0352 }
0353
0354 // alternate syntax: acl_gets(array('m_', 'a_'), $forum_id)
0355 if (is_array($args[0]))
0356 {
0357 $args = $args[0];
0358 }
0359
0360 $acl = 0;
0361 foreach ($args as $opt)
0362 {
0363 $acl |= $this->acl_get($opt, $f);
0364 }
0365
0366 return $acl;
0367 }
0368
0369 /**
0370 * Get permission listing based on user_id/options/forum_ids
0371 *
0372 * Be careful when using this function with permissions a_, m_, u_ and f_ !
0373 * It may not work correctly. When a user group grants an a_* permission,
0374 * e.g. a_foo, but the user's a_foo permission is set to "Never", then
0375 * the user does not in fact have the a_ permission.
0376 * But the user will still be listed as having the a_ permission.
0377 *
0378 * For more information see: http://tracker.phpbb.com/browse/PHPBB3-10252
0379 */
0380 function acl_get_list($user_id = false, $opts = false, $forum_id = false)
0381 {
0382 if ($user_id !== false && !is_array($user_id) && $opts === false && $forum_id === false)
0383 {
0384 $hold_ary = array($user_id => $this->acl_raw_data_single_user($user_id));
0385 }
0386 else
0387 {
0388 $hold_ary = $this->acl_raw_data($user_id, $opts, $forum_id);
0389 }
0390
0391 $auth_ary = array();
0392 foreach ($hold_ary as $user_id => $forum_ary)
0393 {
0394 foreach ($forum_ary as $forum_id => $auth_option_ary)
0395 {
0396 foreach ($auth_option_ary as $auth_option => $auth_setting)
0397 {
0398 if ($auth_setting)
0399 {
0400 $auth_ary[$forum_id][$auth_option][] = $user_id;
0401 }
0402 }
0403 }
0404 }
0405
0406 return $auth_ary;
0407 }
0408
0409 /**
0410 * Cache data to user_permissions row
0411 */
0412 function acl_cache(&$userdata)
0413 {
0414 global $db;
0415
0416 // Empty user_permissions
0417 $userdata['user_permissions'] = '';
0418
0419 $hold_ary = $this->acl_raw_data_single_user($userdata['user_id']);
0420
0421 // Key 0 in $hold_ary are global options, all others are forum_ids
0422
0423 // If this user is founder we're going to force fill the admin options ...
0424 if ($userdata['user_type'] == USER_FOUNDER)
0425 {
0426 foreach ($this->acl_options['global'] as $opt => $id)
0427 {
0428 if (strpos($opt, 'a_') === 0)
0429 {
0430 $hold_ary[0][$this->acl_options['id'][$opt]] = ACL_YES;
0431 }
0432 }
0433 }
0434
0435 $hold_str = $this->build_bitstring($hold_ary);
0436
0437 if ($hold_str)
0438 {
0439 $userdata['user_permissions'] = $hold_str;
0440
0441 $sql = 'UPDATE ' . USERS_TABLE . "
0442 SET user_permissions = '" . $db->sql_escape($userdata['user_permissions']) . "',
0443 user_perm_from = 0
0444 WHERE user_id = " . $userdata['user_id'];
0445 $db->sql_query($sql);
0446 }
0447
0448 return;
0449 }
0450
0451 /**
0452 * Build bitstring from permission set
0453 */
0454 function build_bitstring(&$hold_ary)
0455 {
0456 $hold_str = '';
0457
0458 if (sizeof($hold_ary))
0459 {
0460 ksort($hold_ary);
0461
0462 $last_f = 0;
0463
0464 foreach ($hold_ary as $f => $auth_ary)
0465 {
0466 $ary_key = (!$f) ? 'global' : 'local';
0467
0468 $bitstring = array();
0469 foreach ($this->acl_options[$ary_key] as $opt => $id)
0470 {
0471 if (isset($auth_ary[$this->acl_options['id'][$opt]]))
0472 {
0473 $bitstring[$id] = $auth_ary[$this->acl_options['id'][$opt]];
0474
0475 $option_key = substr($opt, 0, strpos($opt, '_') + 1);
0476
0477 // If one option is allowed, the global permission for this option has to be allowed too
0478 // example: if the user has the a_ permission this means he has one or more a_* permissions
0479 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))
0480 {
0481 $bitstring[$this->acl_options[$ary_key][$option_key]] = ACL_YES;
0482 }
0483 }
0484 else
0485 {
0486 $bitstring[$id] = ACL_NEVER;
0487 }
0488 }
0489
0490 // Now this bitstring defines the permission setting for the current forum $f (or global setting)
0491 $bitstring = implode('', $bitstring);
0492
0493 // The line number indicates the id, therefore we have to add empty lines for those ids not present
0494 $hold_str .= str_repeat("\n", $f - $last_f);
0495
0496 // Convert bitstring for storage - we do not use binary/bytes because PHP's string functions are not fully binary safe
0497 for ($i = 0, $bit_length = strlen($bitstring); $i < $bit_length; $i += 31)
0498 {
0499 $hold_str .= str_pad(base_convert(str_pad(substr($bitstring, $i, 31), 31, 0, STR_PAD_RIGHT), 2, 36), 6, 0, STR_PAD_LEFT);
0500 }
0501
0502 $last_f = $f;
0503 }
0504 unset($bitstring);
0505
0506 $hold_str = rtrim($hold_str);
0507 }
0508
0509 return $hold_str;
0510 }
0511
0512 /**
0513 * Clear one or all users cached permission settings
0514 */
0515 function acl_clear_prefetch($user_id = false)
0516 {
0517 global $db, $cache;
0518
0519 // Rebuild options cache
0520 $cache->destroy('_role_cache');
0521
0522 $sql = 'SELECT *
0523 FROM ' . ACL_ROLES_DATA_TABLE . '
0524 ORDER BY role_id ASC';
0525 $result = $db->sql_query($sql);
0526
0527 $this->role_cache = array();
0528 while ($row = $db->sql_fetchrow($result))
0529 {
0530 $this->role_cache[$row['role_id']][$row['auth_option_id']] = (int) $row['auth_setting'];
0531 }
0532 $db->sql_freeresult($result);
0533
0534 foreach ($this->role_cache as $role_id => $role_options)
0535 {
0536 $this->role_cache[$role_id] = serialize($role_options);
0537 }
0538
0539 $cache->put('_role_cache', $this->role_cache);
0540
0541 // Now empty user permissions
0542 $where_sql = '';
0543
0544 if ($user_id !== false)
0545 {
0546 $user_id = (!is_array($user_id)) ? $user_id = array((int) $user_id) : array_map('intval', $user_id);
0547 $where_sql = ' WHERE ' . $db->sql_in_set('user_id', $user_id);
0548 }
0549
0550 $sql = 'UPDATE ' . USERS_TABLE . "
0551 SET user_permissions = '',
0552 user_perm_from = 0
0553 $where_sql";
0554 $db->sql_query($sql);
0555
0556 return;
0557 }
0558
0559 /**
0560 * Get assigned roles
0561 */
0562 function acl_role_data($user_type, $role_type, $ug_id = false, $forum_id = false)
0563 {
0564 global $db;
0565
0566 $roles = array();
0567
0568 $sql_id = ($user_type == 'user') ? 'user_id' : 'group_id';
0569
0570 $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)) : '';
0571 $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)) : '';
0572
0573 // Grab assigned roles...
0574 $sql = 'SELECT a.auth_role_id, a.' . $sql_id . ', a.forum_id
0575 FROM ' . (($user_type == 'user') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE) . ' a, ' . ACL_ROLES_TABLE . " r
0576 WHERE a.auth_role_id = r.role_id
0577 AND r.role_type = '" . $db->sql_escape($role_type) . "'
0578 $sql_ug
0579 $sql_forum
0580 ORDER BY r.role_order ASC";
0581 $result = $db->sql_query($sql);
0582
0583 while ($row = $db->sql_fetchrow($result))
0584 {
0585 $roles[$row[$sql_id]][$row['forum_id']] = $row['auth_role_id'];
0586 }
0587 $db->sql_freeresult($result);
0588
0589 return $roles;
0590 }
0591
0592 /**
0593 * Get raw acl data based on user/option/forum
0594 */
0595 function acl_raw_data($user_id = false, $opts = false, $forum_id = false)
0596 {
0597 global $db;
0598
0599 $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))) : '';
0600 $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))) : '';
0601
0602 $sql_opts = $sql_opts_select = $sql_opts_from = '';
0603 $hold_ary = array();
0604
0605 if ($opts !== false)
0606 {
0607 $sql_opts_select = ', ao.auth_option';
0608 $sql_opts_from = ', ' . ACL_OPTIONS_TABLE . ' ao';
0609 $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts);
0610 }
0611
0612 $sql_ary = array();
0613
0614 // Grab non-role settings - user-specific
0615 $sql_ary[] = 'SELECT a.user_id, a.forum_id, a.auth_setting, a.auth_option_id' . $sql_opts_select . '
0616 FROM ' . ACL_USERS_TABLE . ' a' . $sql_opts_from . '
0617 WHERE a.auth_role_id = 0 ' .
0618 (($sql_opts_from) ? 'AND a.auth_option_id = ao.auth_option_id ' : '') .
0619 (($sql_user) ? 'AND a.' . $sql_user : '') . "
0620 $sql_forum
0621 $sql_opts";
0622
0623 // Now the role settings - user-specific
0624 $sql_ary[] = 'SELECT a.user_id, a.forum_id, r.auth_option_id, r.auth_setting, r.auth_option_id' . $sql_opts_select . '
0625 FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . '
0626 WHERE a.auth_role_id = r.role_id ' .
0627 (($sql_opts_from) ? 'AND r.auth_option_id = ao.auth_option_id ' : '') .
0628 (($sql_user) ? 'AND a.' . $sql_user : '') . "
0629 $sql_forum
0630 $sql_opts";
0631
0632 foreach ($sql_ary as $sql)
0633 {
0634 $result = $db->sql_query($sql);
0635
0636 while ($row = $db->sql_fetchrow($result))
0637 {
0638 $option = ($sql_opts_select) ? $row['auth_option'] : $this->acl_options['option'][$row['auth_option_id']];
0639 $hold_ary[$row['user_id']][$row['forum_id']][$option] = $row['auth_setting'];
0640 }
0641 $db->sql_freeresult($result);
0642 }
0643
0644 $sql_ary = array();
0645
0646 // Now grab group settings - non-role specific...
0647 $sql_ary[] = 'SELECT ug.user_id, a.forum_id, a.auth_setting, a.auth_option_id' . $sql_opts_select . '
0648 FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g' . $sql_opts_from . '
0649 WHERE a.auth_role_id = 0 ' .
0650 (($sql_opts_from) ? 'AND a.auth_option_id = ao.auth_option_id ' : '') . '
0651 AND a.group_id = ug.group_id
0652 AND g.group_id = ug.group_id
0653 AND ug.user_pending = 0
0654 AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
0655 ' . (($sql_user) ? 'AND ug.' . $sql_user : '') . "
0656 $sql_forum
0657 $sql_opts";
0658
0659 // Now grab group settings - role specific...
0660 $sql_ary[] = 'SELECT ug.user_id, a.forum_id, r.auth_setting, r.auth_option_id' . $sql_opts_select . '
0661 FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . '
0662 WHERE a.auth_role_id = r.role_id ' .
0663 (($sql_opts_from) ? 'AND r.auth_option_id = ao.auth_option_id ' : '') . '
0664 AND a.group_id = ug.group_id
0665 AND g.group_id = ug.group_id
0666 AND ug.user_pending = 0
0667 AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
0668 ' . (($sql_user) ? 'AND ug.' . $sql_user : '') . "
0669 $sql_forum
0670 $sql_opts";
0671
0672 foreach ($sql_ary as $sql)
0673 {
0674 $result = $db->sql_query($sql);
0675
0676 while ($row = $db->sql_fetchrow($result))
0677 {
0678 $option = ($sql_opts_select) ? $row['auth_option'] : $this->acl_options['option'][$row['auth_option_id']];
0679
0680 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))
0681 {
0682 $hold_ary[$row['user_id']][$row['forum_id']][$option] = $row['auth_setting'];
0683
0684 // If we detect ACL_NEVER, we will unset the flag option (within building the bitstring it is correctly set again)
0685 if ($row['auth_setting'] == ACL_NEVER)
0686 {
0687 $flag = substr($option, 0, strpos($option, '_') + 1);
0688
0689 if (isset($hold_ary[$row['user_id']][$row['forum_id']][$flag]) && $hold_ary[$row['user_id']][$row['forum_id']][$flag] == ACL_YES)
0690 {
0691 unset($hold_ary[$row['user_id']][$row['forum_id']][$flag]);
0692
0693 /* if (in_array(ACL_YES, $hold_ary[$row['user_id']][$row['forum_id']]))
0694 {
0695 $hold_ary[$row['user_id']][$row['forum_id']][$flag] = ACL_YES;
0696 }
0697 */
0698 }
0699 }
0700 }
0701 }
0702 $db->sql_freeresult($result);
0703 }
0704
0705 return $hold_ary;
0706 }
0707
0708 /**
0709 * Get raw user based permission settings
0710 */
0711 function acl_user_raw_data($user_id = false, $opts = false, $forum_id = false)
0712 {
0713 global $db;
0714
0715 $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))) : '';
0716 $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))) : '';
0717
0718 $sql_opts = '';
0719 $hold_ary = $sql_ary = array();
0720
0721 if ($opts !== false)
0722 {
0723 $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts);
0724 }
0725
0726 // Grab user settings - non-role specific...
0727 $sql_ary[] = 'SELECT a.user_id, a.forum_id, a.auth_setting, a.auth_option_id, ao.auth_option
0728 FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_OPTIONS_TABLE . ' ao
0729 WHERE a.auth_role_id = 0
0730 AND a.auth_option_id = ao.auth_option_id ' .
0731 (($sql_user) ? 'AND a.' . $sql_user : '') . "
0732 $sql_forum
0733 $sql_opts
0734 ORDER BY a.forum_id, ao.auth_option";
0735
0736 // Now the role settings - user-specific
0737 $sql_ary[] = 'SELECT a.user_id, a.forum_id, r.auth_option_id, r.auth_setting, r.auth_option_id, ao.auth_option
0738 FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' ao
0739 WHERE a.auth_role_id = r.role_id
0740 AND r.auth_option_id = ao.auth_option_id ' .
0741 (($sql_user) ? 'AND a.' . $sql_user : '') . "
0742 $sql_forum
0743 $sql_opts
0744 ORDER BY a.forum_id, ao.auth_option";
0745
0746 foreach ($sql_ary as $sql)
0747 {
0748 $result = $db->sql_query($sql);
0749
0750 while ($row = $db->sql_fetchrow($result))
0751 {
0752 $hold_ary[$row['user_id']][$row['forum_id']][$row['auth_option']] = $row['auth_setting'];
0753 }
0754 $db->sql_freeresult($result);
0755 }
0756
0757 return $hold_ary;
0758 }
0759
0760 /**
0761 * Get raw group based permission settings
0762 */
0763 function acl_group_raw_data($group_id = false, $opts = false, $forum_id = false)
0764 {
0765 global $db;
0766
0767 $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))) : '';
0768 $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))) : '';
0769
0770 $sql_opts = '';
0771 $hold_ary = $sql_ary = array();
0772
0773 if ($opts !== false)
0774 {
0775 $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts);
0776 }
0777
0778 // Grab group settings - non-role specific...
0779 $sql_ary[] = 'SELECT a.group_id, a.forum_id, a.auth_setting, a.auth_option_id, ao.auth_option
0780 FROM ' . ACL_GROUPS_TABLE . ' a, ' . ACL_OPTIONS_TABLE . ' ao
0781 WHERE a.auth_role_id = 0
0782 AND a.auth_option_id = ao.auth_option_id ' .
0783 (($sql_group) ? 'AND a.' . $sql_group : '') . "
0784 $sql_forum
0785 $sql_opts
0786 ORDER BY a.forum_id, ao.auth_option";
0787
0788 // Now grab group settings - role specific...
0789 $sql_ary[] = 'SELECT a.group_id, a.forum_id, r.auth_setting, r.auth_option_id, ao.auth_option
0790 FROM ' . ACL_GROUPS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' ao
0791 WHERE a.auth_role_id = r.role_id
0792 AND r.auth_option_id = ao.auth_option_id ' .
0793 (($sql_group) ? 'AND a.' . $sql_group : '') . "
0794 $sql_forum
0795 $sql_opts
0796 ORDER BY a.forum_id, ao.auth_option";
0797
0798 foreach ($sql_ary as $sql)
0799 {
0800 $result = $db->sql_query($sql);
0801
0802 while ($row = $db->sql_fetchrow($result))
0803 {
0804 $hold_ary[$row['group_id']][$row['forum_id']][$row['auth_option']] = $row['auth_setting'];
0805 }
0806 $db->sql_freeresult($result);
0807 }
0808
0809 return $hold_ary;
0810 }
0811
0812 /**
0813 * Get raw acl data based on user for caching user_permissions
0814 * This function returns the same data as acl_raw_data(), but without the user id as the first key within the array.
0815 */
0816 function acl_raw_data_single_user($user_id)
0817 {
0818 global $db, $cache;
0819
0820 // Check if the role-cache is there
0821 if (($this->role_cache = $cache->get('_role_cache')) === false)
0822 {
0823 $this->role_cache = array();
0824
0825 // We pre-fetch roles
0826 $sql = 'SELECT *
0827 FROM ' . ACL_ROLES_DATA_TABLE . '
0828 ORDER BY role_id ASC';
0829 $result = $db->sql_query($sql);
0830
0831 while ($row = $db->sql_fetchrow($result))
0832 {
0833 $this->role_cache[$row['role_id']][$row['auth_option_id']] = (int) $row['auth_setting'];
0834 }
0835 $db->sql_freeresult($result);
0836
0837 foreach ($this->role_cache as $role_id => $role_options)
0838 {
0839 $this->role_cache[$role_id] = serialize($role_options);
0840 }
0841
0842 $cache->put('_role_cache', $this->role_cache);
0843 }
0844
0845 $hold_ary = array();
0846
0847 // Grab user-specific permission settings
0848 $sql = 'SELECT forum_id, auth_option_id, auth_role_id, auth_setting
0849 FROM ' . ACL_USERS_TABLE . '
0850 WHERE user_id = ' . $user_id;
0851 $result = $db->sql_query($sql);
0852
0853 while ($row = $db->sql_fetchrow($result))
0854 {
0855 // If a role is assigned, assign all options included within this role. Else, only set this one option.
0856 if ($row['auth_role_id'])
0857 {
0858 $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']]);
0859 }
0860 else
0861 {
0862 $hold_ary[$row['forum_id']][$row['auth_option_id']] = $row['auth_setting'];
0863 }
0864 }
0865 $db->sql_freeresult($result);
0866
0867 // Now grab group-specific permission settings
0868 $sql = 'SELECT a.forum_id, a.auth_option_id, a.auth_role_id, a.auth_setting
0869 FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g
0870 WHERE a.group_id = ug.group_id
0871 AND g.group_id = ug.group_id
0872 AND ug.user_pending = 0
0873 AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
0874 AND ug.user_id = ' . $user_id;
0875 $result = $db->sql_query($sql);
0876
0877 while ($row = $db->sql_fetchrow($result))
0878 {
0879 if (!$row['auth_role_id'])
0880 {
0881 $this->_set_group_hold_ary($hold_ary[$row['forum_id']], $row['auth_option_id'], $row['auth_setting']);
0882 }
0883 else if (!empty($this->role_cache[$row['auth_role_id']]))
0884 {
0885 foreach (unserialize($this->role_cache[$row['auth_role_id']]) as $option_id => $setting)
0886 {
0887 $this->_set_group_hold_ary($hold_ary[$row['forum_id']], $option_id, $setting);
0888 }
0889 }
0890 }
0891 $db->sql_freeresult($result);
0892
0893 return $hold_ary;
0894 }
0895
0896 /**
0897 * Private function snippet for setting a specific piece of the hold_ary
0898 */
0899 function _set_group_hold_ary(&$hold_ary, $option_id, $setting)
0900 {
0901 if (!isset($hold_ary[$option_id]) || (isset($hold_ary[$option_id]) && $hold_ary[$option_id] != ACL_NEVER))
0902 {
0903 $hold_ary[$option_id] = $setting;
0904
0905 // If we detect ACL_NEVER, we will unset the flag option (within building the bitstring it is correctly set again)
0906 if ($setting == ACL_NEVER)
0907 {
0908 $flag = substr($this->acl_options['option'][$option_id], 0, strpos($this->acl_options['option'][$option_id], '_') + 1);
0909 $flag = (int) $this->acl_options['id'][$flag];
0910
0911 if (isset($hold_ary[$flag]) && $hold_ary[$flag] == ACL_YES)
0912 {
0913 unset($hold_ary[$flag]);
0914
0915 /* This is uncommented, because i suspect this being slightly wrong due to mixed permission classes being possible
0916 if (in_array(ACL_YES, $hold_ary))
0917 {
0918 $hold_ary[$flag] = ACL_YES;
0919 }*/
0920 }
0921 }
0922 }
0923 }
0924
0925 /**
0926 * Authentication plug-ins is largely down to Sergey Kanareykin, our thanks to him.
0927 */
0928 function login($username, $password, $autologin = false, $viewonline = 1, $admin = 0)
0929 {
0930 global $config, $db, $user, $phpbb_root_path, $phpEx, $phpbb_container;
0931
0932 $method = trim(basename($config['auth_method']));
0933
0934 $provider = $phpbb_container->get('auth.provider.' . $method);
0935 if ($provider)
0936 {
0937 $login = $provider->login($username, $password);
0938
0939 // If the auth module wants us to create an empty profile do so and then treat the status as LOGIN_SUCCESS
0940 if ($login['status'] == LOGIN_SUCCESS_CREATE_PROFILE)
0941 {
0942 // we are going to use the user_add function so include functions_user.php if it wasn't defined yet
0943 if (!function_exists('user_add'))
0944 {
0945 include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
0946 }
0947
0948 user_add($login['user_row'], (isset($login['cp_data'])) ? $login['cp_data'] : false);
0949
0950 $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type
0951 FROM ' . USERS_TABLE . "
0952 WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
0953 $result = $db->sql_query($sql);
0954 $row = $db->sql_fetchrow($result);
0955 $db->sql_freeresult($result);
0956
0957 if (!$row)
0958 {
0959 return array(
0960 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
0961 'error_msg' => 'AUTH_NO_PROFILE_CREATED',
0962 'user_row' => array('user_id' => ANONYMOUS),
0963 );
0964 }
0965
0966 $login = array(
0967 'status' => LOGIN_SUCCESS,
0968 'error_msg' => false,
0969 'user_row' => $row,
0970 );
0971 }
0972
0973 // If the auth provider wants us to link an empty account do so and redirect
0974 if ($login['status'] == LOGIN_SUCCESS_LINK_PROFILE)
0975 {
0976 // If this status exists a fourth field is in the $login array called 'redirect_data'
0977 // This data is passed along as GET data to the next page allow the account to be linked
0978
0979 $params = array('mode' => 'login_link');
0980 $url = append_sid($phpbb_root_path . 'ucp.' . $phpEx, array_merge($params, $login['redirect_data']));
0981
0982 redirect($url);
0983 }
0984
0985 // If login succeeded, we will log the user in... else we pass the login array through...
0986 if ($login['status'] == LOGIN_SUCCESS)
0987 {
0988 $old_session_id = $user->session_id;
0989
0990 if ($admin)
0991 {
0992 global $SID, $_SID;
0993
0994 $cookie_expire = time() - 31536000;
0995 $user->set_cookie('u', '', $cookie_expire);
0996 $user->set_cookie('sid', '', $cookie_expire);
0997 unset($cookie_expire);
0998
0999 $SID = '?sid=';
1000 $user->session_id = $_SID = '';
1001 }
1002
1003 $result = $user->session_create($login['user_row']['user_id'], $admin, $autologin, $viewonline);
1004
1005 // Successful session creation
1006 if ($result === true)
1007 {
1008 // If admin re-authentication we remove the old session entry because a new one has been created...
1009 if ($admin)
1010 {
1011 // the login array is used because the user ids do not differ for re-authentication
1012 $sql = 'DELETE FROM ' . SESSIONS_TABLE . "
1013 WHERE session_id = '" . $db->sql_escape($old_session_id) . "'
1014 AND session_user_id = {$login['user_row']['user_id']}";
1015 $db->sql_query($sql);
1016 }
1017
1018 return array(
1019 'status' => LOGIN_SUCCESS,
1020 'error_msg' => false,
1021 'user_row' => $login['user_row'],
1022 );
1023 }
1024
1025 return array(
1026 'status' => LOGIN_BREAK,
1027 'error_msg' => $result,
1028 'user_row' => $login['user_row'],
1029 );
1030 }
1031
1032 return $login;
1033 }
1034
1035 trigger_error('Authentication method not found', E_USER_ERROR);
1036 }
1037
1038 /**
1039 * Fill auth_option statement for later querying based on the supplied options
1040 */
1041 function build_auth_option_statement($key, $auth_options, &$sql_opts)
1042 {
1043 global $db;
1044
1045 if (!is_array($auth_options))
1046 {
1047 if (strpos($auth_options, '%') !== false)
1048 {
1049 $sql_opts = "AND $key " . $db->sql_like_expression(str_replace('%', $db->get_any_char(), $auth_options));
1050 }
1051 else
1052 {
1053 $sql_opts = "AND $key = '" . $db->sql_escape($auth_options) . "'";
1054 }
1055 }
1056 else
1057 {
1058 $is_like_expression = false;
1059
1060 foreach ($auth_options as $option)
1061 {
1062 if (strpos($option, '%') !== false)
1063 {
1064 $is_like_expression = true;
1065 }
1066 }
1067
1068 if (!$is_like_expression)
1069 {
1070 $sql_opts = 'AND ' . $db->sql_in_set($key, $auth_options);
1071 }
1072 else
1073 {
1074 $sql = array();
1075
1076 foreach ($auth_options as $option)
1077 {
1078 if (strpos($option, '%') !== false)
1079 {
1080 $sql[] = $key . ' ' . $db->sql_like_expression(str_replace('%', $db->get_any_char(), $option));
1081 }
1082 else
1083 {
1084 $sql[] = $key . " = '" . $db->sql_escape($option) . "'";
1085 }
1086 }
1087
1088 $sql_opts = 'AND (' . implode(' OR ', $sql) . ')';
1089 }
1090 }
1091 }
1092 }
1093