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