[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Oct 2 15:03:47 2013 | Cross-referenced by PHPXref 0.7.1 |