[ 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 * Obtain user_ids from usernames or vice versa. Returns false on 21 * success else the error string 22 * 23 * @param array &$user_id_ary The user ids to check or empty if usernames used 24 * @param array &$username_ary The usernames to check or empty if user ids used 25 * @param mixed $user_type Array of user types to check, false if not restricting by user type 26 */ 27 function user_get_id_name(&$user_id_ary, &$username_ary, $user_type = false) 28 { 29 global $db; 30 31 // Are both arrays already filled? Yep, return else 32 // are neither array filled? 33 if ($user_id_ary && $username_ary) 34 { 35 return false; 36 } 37 else if (!$user_id_ary && !$username_ary) 38 { 39 return 'NO_USERS'; 40 } 41 42 $which_ary = ($user_id_ary) ? 'user_id_ary' : 'username_ary'; 43 44 if ($$which_ary && !is_array($$which_ary)) 45 { 46 $$which_ary = array($$which_ary); 47 } 48 49 $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', $$which_ary) : array_map('utf8_clean_string', $$which_ary); 50 unset($$which_ary); 51 52 $user_id_ary = $username_ary = array(); 53 54 // Grab the user id/username records 55 $sql_where = ($which_ary == 'user_id_ary') ? 'user_id' : 'username_clean'; 56 $sql = 'SELECT user_id, username 57 FROM ' . USERS_TABLE . ' 58 WHERE ' . $db->sql_in_set($sql_where, $sql_in); 59 60 if ($user_type !== false && !empty($user_type)) 61 { 62 $sql .= ' AND ' . $db->sql_in_set('user_type', $user_type); 63 } 64 65 $result = $db->sql_query($sql); 66 67 if (!($row = $db->sql_fetchrow($result))) 68 { 69 $db->sql_freeresult($result); 70 return 'NO_USERS'; 71 } 72 73 do 74 { 75 $username_ary[$row['user_id']] = $row['username']; 76 $user_id_ary[] = $row['user_id']; 77 } 78 while ($row = $db->sql_fetchrow($result)); 79 $db->sql_freeresult($result); 80 81 return false; 82 } 83 84 /** 85 * Get latest registered username and update database to reflect it 86 */ 87 function update_last_username() 88 { 89 global $db; 90 91 // Get latest username 92 $sql = 'SELECT user_id, username, user_colour 93 FROM ' . USERS_TABLE . ' 94 WHERE user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') 95 ORDER BY user_id DESC'; 96 $result = $db->sql_query_limit($sql, 1); 97 $row = $db->sql_fetchrow($result); 98 $db->sql_freeresult($result); 99 100 if ($row) 101 { 102 set_config('newest_user_id', $row['user_id'], true); 103 set_config('newest_username', $row['username'], true); 104 set_config('newest_user_colour', $row['user_colour'], true); 105 } 106 } 107 108 /** 109 * Updates a username across all relevant tables/fields 110 * 111 * @param string $old_name the old/current username 112 * @param string $new_name the new username 113 */ 114 function user_update_name($old_name, $new_name) 115 { 116 global $config, $db, $cache; 117 118 $update_ary = array( 119 FORUMS_TABLE => array('forum_last_poster_name'), 120 MODERATOR_CACHE_TABLE => array('username'), 121 POSTS_TABLE => array('post_username'), 122 TOPICS_TABLE => array('topic_first_poster_name', 'topic_last_poster_name'), 123 ); 124 125 foreach ($update_ary as $table => $field_ary) 126 { 127 foreach ($field_ary as $field) 128 { 129 $sql = "UPDATE $table 130 SET $field = '" . $db->sql_escape($new_name) . "' 131 WHERE $field = '" . $db->sql_escape($old_name) . "'"; 132 $db->sql_query($sql); 133 } 134 } 135 136 if ($config['newest_username'] == $old_name) 137 { 138 set_config('newest_username', $new_name, true); 139 } 140 141 // Because some tables/caches use username-specific data we need to purge this here. 142 $cache->destroy('sql', MODERATOR_CACHE_TABLE); 143 } 144 145 /** 146 * Adds an user 147 * 148 * @param mixed $user_row An array containing the following keys (and the appropriate values): username, group_id (the group to place the user in), user_email and the user_type(usually 0). Additional entries not overridden by defaults will be forwarded. 149 * @param string $cp_data custom profile fields, see custom_profile::build_insert_sql_array 150 * @return the new user's ID. 151 */ 152 function user_add($user_row, $cp_data = false) 153 { 154 global $db, $user, $auth, $config, $phpbb_root_path, $phpEx; 155 156 if (empty($user_row['username']) || !isset($user_row['group_id']) || !isset($user_row['user_email']) || !isset($user_row['user_type'])) 157 { 158 return false; 159 } 160 161 $username_clean = utf8_clean_string($user_row['username']); 162 163 if (empty($username_clean)) 164 { 165 return false; 166 } 167 168 $sql_ary = array( 169 'username' => $user_row['username'], 170 'username_clean' => $username_clean, 171 'user_password' => (isset($user_row['user_password'])) ? $user_row['user_password'] : '', 172 'user_pass_convert' => 0, 173 'user_email' => strtolower($user_row['user_email']), 174 'user_email_hash' => phpbb_email_hash($user_row['user_email']), 175 'group_id' => $user_row['group_id'], 176 'user_type' => $user_row['user_type'], 177 ); 178 179 // These are the additional vars able to be specified 180 $additional_vars = array( 181 'user_permissions' => '', 182 'user_timezone' => $config['board_timezone'], 183 'user_dateformat' => $config['default_dateformat'], 184 'user_lang' => $config['default_lang'], 185 'user_style' => (int) $config['default_style'], 186 'user_actkey' => '', 187 'user_ip' => '', 188 'user_regdate' => time(), 189 'user_passchg' => time(), 190 'user_options' => 230271, 191 // We do not set the new flag here - registration scripts need to specify it 192 'user_new' => 0, 193 194 'user_inactive_reason' => 0, 195 'user_inactive_time' => 0, 196 'user_lastmark' => time(), 197 'user_lastvisit' => 0, 198 'user_lastpost_time' => 0, 199 'user_lastpage' => '', 200 'user_posts' => 0, 201 'user_dst' => (int) $config['board_dst'], 202 'user_colour' => '', 203 'user_occ' => '', 204 'user_interests' => '', 205 'user_avatar' => '', 206 'user_avatar_type' => 0, 207 'user_avatar_width' => 0, 208 'user_avatar_height' => 0, 209 'user_new_privmsg' => 0, 210 'user_unread_privmsg' => 0, 211 'user_last_privmsg' => 0, 212 'user_message_rules' => 0, 213 'user_full_folder' => PRIVMSGS_NO_BOX, 214 'user_emailtime' => 0, 215 216 'user_notify' => 0, 217 'user_notify_pm' => 1, 218 'user_notify_type' => NOTIFY_EMAIL, 219 'user_allow_pm' => 1, 220 'user_allow_viewonline' => 1, 221 'user_allow_viewemail' => 1, 222 'user_allow_massemail' => 1, 223 224 'user_sig' => '', 225 'user_sig_bbcode_uid' => '', 226 'user_sig_bbcode_bitfield' => '', 227 228 'user_form_salt' => unique_id(), 229 ); 230 231 // Now fill the sql array with not required variables 232 foreach ($additional_vars as $key => $default_value) 233 { 234 $sql_ary[$key] = (isset($user_row[$key])) ? $user_row[$key] : $default_value; 235 } 236 237 // Any additional variables in $user_row not covered above? 238 $remaining_vars = array_diff(array_keys($user_row), array_keys($sql_ary)); 239 240 // Now fill our sql array with the remaining vars 241 if (sizeof($remaining_vars)) 242 { 243 foreach ($remaining_vars as $key) 244 { 245 $sql_ary[$key] = $user_row[$key]; 246 } 247 } 248 249 $sql = 'INSERT INTO ' . USERS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); 250 $db->sql_query($sql); 251 252 $user_id = $db->sql_nextid(); 253 254 // Insert Custom Profile Fields 255 if ($cp_data !== false && sizeof($cp_data)) 256 { 257 $cp_data['user_id'] = (int) $user_id; 258 259 if (!class_exists('custom_profile')) 260 { 261 include_once($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx); 262 } 263 264 $sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' . 265 $db->sql_build_array('INSERT', custom_profile::build_insert_sql_array($cp_data)); 266 $db->sql_query($sql); 267 } 268 269 // Place into appropriate group... 270 $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' ' . $db->sql_build_array('INSERT', array( 271 'user_id' => (int) $user_id, 272 'group_id' => (int) $user_row['group_id'], 273 'user_pending' => 0) 274 ); 275 $db->sql_query($sql); 276 277 // Now make it the users default group... 278 group_set_user_default($user_row['group_id'], array($user_id), false); 279 280 // Add to newly registered users group if user_new is 1 281 if ($config['new_member_post_limit'] && $sql_ary['user_new']) 282 { 283 $sql = 'SELECT group_id 284 FROM ' . GROUPS_TABLE . " 285 WHERE group_name = 'NEWLY_REGISTERED' 286 AND group_type = " . GROUP_SPECIAL; 287 $result = $db->sql_query($sql); 288 $add_group_id = (int) $db->sql_fetchfield('group_id'); 289 $db->sql_freeresult($result); 290 291 if ($add_group_id) 292 { 293 // Because these actions only fill the log unneccessarily we skip the add_log() entry with a little hack. :/ 294 $GLOBALS['skip_add_log'] = true; 295 296 // Add user to "newly registered users" group and set to default group if admin specified so. 297 if ($config['new_member_group_default']) 298 { 299 group_user_add($add_group_id, $user_id, false, false, true); 300 $user_row['group_id'] = $add_group_id; 301 } 302 else 303 { 304 group_user_add($add_group_id, $user_id); 305 } 306 307 unset($GLOBALS['skip_add_log']); 308 } 309 } 310 311 // set the newest user and adjust the user count if the user is a normal user and no activation mail is sent 312 if ($user_row['user_type'] == USER_NORMAL || $user_row['user_type'] == USER_FOUNDER) 313 { 314 set_config('newest_user_id', $user_id, true); 315 set_config('newest_username', $user_row['username'], true); 316 set_config_count('num_users', 1, true); 317 318 $sql = 'SELECT group_colour 319 FROM ' . GROUPS_TABLE . ' 320 WHERE group_id = ' . (int) $user_row['group_id']; 321 $result = $db->sql_query_limit($sql, 1); 322 $row = $db->sql_fetchrow($result); 323 $db->sql_freeresult($result); 324 325 set_config('newest_user_colour', $row['group_colour'], true); 326 } 327 328 return $user_id; 329 } 330 331 /** 332 * Remove User 333 */ 334 function user_delete($mode, $user_id, $post_username = false) 335 { 336 global $cache, $config, $db, $user, $auth; 337 global $phpbb_root_path, $phpEx; 338 339 $sql = 'SELECT * 340 FROM ' . USERS_TABLE . ' 341 WHERE user_id = ' . $user_id; 342 $result = $db->sql_query($sql); 343 $user_row = $db->sql_fetchrow($result); 344 $db->sql_freeresult($result); 345 346 if (!$user_row) 347 { 348 return false; 349 } 350 351 // Before we begin, we will remove the reports the user issued. 352 $sql = 'SELECT r.post_id, p.topic_id 353 FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p 354 WHERE r.user_id = ' . $user_id . ' 355 AND p.post_id = r.post_id'; 356 $result = $db->sql_query($sql); 357 358 $report_posts = $report_topics = array(); 359 while ($row = $db->sql_fetchrow($result)) 360 { 361 $report_posts[] = $row['post_id']; 362 $report_topics[] = $row['topic_id']; 363 } 364 $db->sql_freeresult($result); 365 366 if (sizeof($report_posts)) 367 { 368 $report_posts = array_unique($report_posts); 369 $report_topics = array_unique($report_topics); 370 371 // Get a list of topics that still contain reported posts 372 $sql = 'SELECT DISTINCT topic_id 373 FROM ' . POSTS_TABLE . ' 374 WHERE ' . $db->sql_in_set('topic_id', $report_topics) . ' 375 AND post_reported = 1 376 AND ' . $db->sql_in_set('post_id', $report_posts, true); 377 $result = $db->sql_query($sql); 378 379 $keep_report_topics = array(); 380 while ($row = $db->sql_fetchrow($result)) 381 { 382 $keep_report_topics[] = $row['topic_id']; 383 } 384 $db->sql_freeresult($result); 385 386 if (sizeof($keep_report_topics)) 387 { 388 $report_topics = array_diff($report_topics, $keep_report_topics); 389 } 390 unset($keep_report_topics); 391 392 // Now set the flags back 393 $sql = 'UPDATE ' . POSTS_TABLE . ' 394 SET post_reported = 0 395 WHERE ' . $db->sql_in_set('post_id', $report_posts); 396 $db->sql_query($sql); 397 398 if (sizeof($report_topics)) 399 { 400 $sql = 'UPDATE ' . TOPICS_TABLE . ' 401 SET topic_reported = 0 402 WHERE ' . $db->sql_in_set('topic_id', $report_topics); 403 $db->sql_query($sql); 404 } 405 } 406 407 // Remove reports 408 $db->sql_query('DELETE FROM ' . REPORTS_TABLE . ' WHERE user_id = ' . $user_id); 409 410 if ($user_row['user_avatar'] && $user_row['user_avatar_type'] == AVATAR_UPLOAD) 411 { 412 avatar_delete('user', $user_row); 413 } 414 415 switch ($mode) 416 { 417 case 'retain': 418 419 $db->sql_transaction('begin'); 420 421 if ($post_username === false) 422 { 423 $post_username = $user->lang['GUEST']; 424 } 425 426 // If the user is inactive and newly registered we assume no posts from this user being there... 427 if ($user_row['user_type'] == USER_INACTIVE && $user_row['user_inactive_reason'] == INACTIVE_REGISTER && !$user_row['user_posts']) 428 { 429 } 430 else 431 { 432 $sql = 'UPDATE ' . FORUMS_TABLE . ' 433 SET forum_last_poster_id = ' . ANONYMOUS . ", forum_last_poster_name = '" . $db->sql_escape($post_username) . "', forum_last_poster_colour = '' 434 WHERE forum_last_poster_id = $user_id"; 435 $db->sql_query($sql); 436 437 $sql = 'UPDATE ' . POSTS_TABLE . ' 438 SET poster_id = ' . ANONYMOUS . ", post_username = '" . $db->sql_escape($post_username) . "' 439 WHERE poster_id = $user_id"; 440 $db->sql_query($sql); 441 442 $sql = 'UPDATE ' . POSTS_TABLE . ' 443 SET post_edit_user = ' . ANONYMOUS . " 444 WHERE post_edit_user = $user_id"; 445 $db->sql_query($sql); 446 447 $sql = 'UPDATE ' . TOPICS_TABLE . ' 448 SET topic_poster = ' . ANONYMOUS . ", topic_first_poster_name = '" . $db->sql_escape($post_username) . "', topic_first_poster_colour = '' 449 WHERE topic_poster = $user_id"; 450 $db->sql_query($sql); 451 452 $sql = 'UPDATE ' . TOPICS_TABLE . ' 453 SET topic_last_poster_id = ' . ANONYMOUS . ", topic_last_poster_name = '" . $db->sql_escape($post_username) . "', topic_last_poster_colour = '' 454 WHERE topic_last_poster_id = $user_id"; 455 $db->sql_query($sql); 456 457 $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' 458 SET poster_id = ' . ANONYMOUS . " 459 WHERE poster_id = $user_id"; 460 $db->sql_query($sql); 461 462 // Since we change every post by this author, we need to count this amount towards the anonymous user 463 464 // Update the post count for the anonymous user 465 if ($user_row['user_posts']) 466 { 467 $sql = 'UPDATE ' . USERS_TABLE . ' 468 SET user_posts = user_posts + ' . $user_row['user_posts'] . ' 469 WHERE user_id = ' . ANONYMOUS; 470 $db->sql_query($sql); 471 } 472 } 473 474 $db->sql_transaction('commit'); 475 476 break; 477 478 case 'remove': 479 480 if (!function_exists('delete_posts')) 481 { 482 include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); 483 } 484 485 // Delete posts, attachments, etc. 486 delete_posts('poster_id', $user_id); 487 488 break; 489 } 490 491 $db->sql_transaction('begin'); 492 493 $table_ary = array(USERS_TABLE, USER_GROUP_TABLE, TOPICS_WATCH_TABLE, FORUMS_WATCH_TABLE, ACL_USERS_TABLE, TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, FORUMS_TRACK_TABLE, PROFILE_FIELDS_DATA_TABLE, MODERATOR_CACHE_TABLE, DRAFTS_TABLE, BOOKMARKS_TABLE, SESSIONS_KEYS_TABLE, PRIVMSGS_FOLDER_TABLE, PRIVMSGS_RULES_TABLE); 494 495 foreach ($table_ary as $table) 496 { 497 $sql = "DELETE FROM $table 498 WHERE user_id = $user_id"; 499 $db->sql_query($sql); 500 } 501 502 $cache->destroy('sql', MODERATOR_CACHE_TABLE); 503 504 // Delete user log entries about this user 505 $sql = 'DELETE FROM ' . LOG_TABLE . ' 506 WHERE reportee_id = ' . $user_id; 507 $db->sql_query($sql); 508 509 // Change user_id to anonymous for this users triggered events 510 $sql = 'UPDATE ' . LOG_TABLE . ' 511 SET user_id = ' . ANONYMOUS . ' 512 WHERE user_id = ' . $user_id; 513 $db->sql_query($sql); 514 515 // Delete the user_id from the zebra table 516 $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' 517 WHERE user_id = ' . $user_id . ' 518 OR zebra_id = ' . $user_id; 519 $db->sql_query($sql); 520 521 // Delete the user_id from the banlist 522 $sql = 'DELETE FROM ' . BANLIST_TABLE . ' 523 WHERE ban_userid = ' . $user_id; 524 $db->sql_query($sql); 525 526 // Delete the user_id from the session table 527 $sql = 'DELETE FROM ' . SESSIONS_TABLE . ' 528 WHERE session_user_id = ' . $user_id; 529 $db->sql_query($sql); 530 531 // Clean the private messages tables from the user 532 if (!function_exists('phpbb_delete_user_pms')) 533 { 534 include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); 535 } 536 phpbb_delete_user_pms($user_id); 537 538 $db->sql_transaction('commit'); 539 540 // Reset newest user info if appropriate 541 if ($config['newest_user_id'] == $user_id) 542 { 543 update_last_username(); 544 } 545 546 // Decrement number of users if this user is active 547 if ($user_row['user_type'] != USER_INACTIVE && $user_row['user_type'] != USER_IGNORE) 548 { 549 set_config_count('num_users', -1, true); 550 } 551 552 return false; 553 } 554 555 /** 556 * Flips user_type from active to inactive and vice versa, handles group membership updates 557 * 558 * @param string $mode can be flip for flipping from active/inactive, activate or deactivate 559 */ 560 function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL) 561 { 562 global $config, $db, $user, $auth; 563 564 $deactivated = $activated = 0; 565 $sql_statements = array(); 566 567 if (!is_array($user_id_ary)) 568 { 569 $user_id_ary = array($user_id_ary); 570 } 571 572 if (!sizeof($user_id_ary)) 573 { 574 return; 575 } 576 577 $sql = 'SELECT user_id, group_id, user_type, user_inactive_reason 578 FROM ' . USERS_TABLE . ' 579 WHERE ' . $db->sql_in_set('user_id', $user_id_ary); 580 $result = $db->sql_query($sql); 581 582 while ($row = $db->sql_fetchrow($result)) 583 { 584 $sql_ary = array(); 585 586 if ($row['user_type'] == USER_IGNORE || $row['user_type'] == USER_FOUNDER || 587 ($mode == 'activate' && $row['user_type'] != USER_INACTIVE) || 588 ($mode == 'deactivate' && $row['user_type'] == USER_INACTIVE)) 589 { 590 continue; 591 } 592 593 if ($row['user_type'] == USER_INACTIVE) 594 { 595 $activated++; 596 } 597 else 598 { 599 $deactivated++; 600 601 // Remove the users session key... 602 $user->reset_login_keys($row['user_id']); 603 } 604 605 $sql_ary += array( 606 'user_type' => ($row['user_type'] == USER_NORMAL) ? USER_INACTIVE : USER_NORMAL, 607 'user_inactive_time' => ($row['user_type'] == USER_NORMAL) ? time() : 0, 608 'user_inactive_reason' => ($row['user_type'] == USER_NORMAL) ? $reason : 0, 609 ); 610 611 $sql_statements[$row['user_id']] = $sql_ary; 612 } 613 $db->sql_freeresult($result); 614 615 if (sizeof($sql_statements)) 616 { 617 foreach ($sql_statements as $user_id => $sql_ary) 618 { 619 $sql = 'UPDATE ' . USERS_TABLE . ' 620 SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' 621 WHERE user_id = ' . $user_id; 622 $db->sql_query($sql); 623 } 624 625 $auth->acl_clear_prefetch(array_keys($sql_statements)); 626 } 627 628 if ($deactivated) 629 { 630 set_config_count('num_users', $deactivated * (-1), true); 631 } 632 633 if ($activated) 634 { 635 set_config_count('num_users', $activated, true); 636 } 637 638 // Update latest username 639 update_last_username(); 640 } 641 642 /** 643 * Add a ban or ban exclusion to the banlist. Bans either a user, an IP or an email address 644 * 645 * @param string $mode Type of ban. One of the following: user, ip, email 646 * @param mixed $ban Banned entity. Either string or array with usernames, ips or email addresses 647 * @param int $ban_len Ban length in minutes 648 * @param string $ban_len_other Ban length as a date (YYYY-MM-DD) 649 * @param boolean $ban_exclude Exclude these entities from banning? 650 * @param string $ban_reason String describing the reason for this ban 651 * @return boolean 652 */ 653 function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason = '') 654 { 655 global $db, $user, $auth, $cache; 656 657 // Delete stale bans 658 $sql = 'DELETE FROM ' . BANLIST_TABLE . ' 659 WHERE ban_end < ' . time() . ' 660 AND ban_end <> 0'; 661 $db->sql_query($sql); 662 663 $ban_list = (!is_array($ban)) ? array_unique(explode("\n", $ban)) : $ban; 664 $ban_list_log = implode(', ', $ban_list); 665 666 $current_time = time(); 667 668 // Set $ban_end to the unix time when the ban should end. 0 is a permanent ban. 669 if ($ban_len) 670 { 671 if ($ban_len != -1 || !$ban_len_other) 672 { 673 $ban_end = max($current_time, $current_time + ($ban_len) * 60); 674 } 675 else 676 { 677 $ban_other = explode('-', $ban_len_other); 678 if (sizeof($ban_other) == 3 && ((int)$ban_other[0] < 9999) && 679 (strlen($ban_other[0]) == 4) && (strlen($ban_other[1]) == 2) && (strlen($ban_other[2]) == 2)) 680 { 681 $time_offset = (isset($user->timezone) && isset($user->dst)) ? (int) $user->timezone + (int) $user->dst : 0; 682 $ban_end = max($current_time, gmmktime(0, 0, 0, (int)$ban_other[1], (int)$ban_other[2], (int)$ban_other[0]) - $time_offset); 683 } 684 else 685 { 686 trigger_error('LENGTH_BAN_INVALID', E_USER_WARNING); 687 } 688 } 689 } 690 else 691 { 692 $ban_end = 0; 693 } 694 695 $founder = $founder_names = array(); 696 697 if (!$ban_exclude) 698 { 699 // Create a list of founder... 700 $sql = 'SELECT user_id, user_email, username_clean 701 FROM ' . USERS_TABLE . ' 702 WHERE user_type = ' . USER_FOUNDER; 703 $result = $db->sql_query($sql); 704 705 while ($row = $db->sql_fetchrow($result)) 706 { 707 $founder[$row['user_id']] = $row['user_email']; 708 $founder_names[$row['user_id']] = $row['username_clean']; 709 } 710 $db->sql_freeresult($result); 711 } 712 713 $banlist_ary = array(); 714 715 switch ($mode) 716 { 717 case 'user': 718 $type = 'ban_userid'; 719 720 // At the moment we do not support wildcard username banning 721 722 // Select the relevant user_ids. 723 $sql_usernames = array(); 724 725 foreach ($ban_list as $username) 726 { 727 $username = trim($username); 728 if ($username != '') 729 { 730 $clean_name = utf8_clean_string($username); 731 if ($clean_name == $user->data['username_clean']) 732 { 733 trigger_error('CANNOT_BAN_YOURSELF', E_USER_WARNING); 734 } 735 if (in_array($clean_name, $founder_names)) 736 { 737 trigger_error('CANNOT_BAN_FOUNDER', E_USER_WARNING); 738 } 739 $sql_usernames[] = $clean_name; 740 } 741 } 742 743 // Make sure we have been given someone to ban 744 if (!sizeof($sql_usernames)) 745 { 746 trigger_error('NO_USER_SPECIFIED', E_USER_WARNING); 747 } 748 749 $sql = 'SELECT user_id 750 FROM ' . USERS_TABLE . ' 751 WHERE ' . $db->sql_in_set('username_clean', $sql_usernames); 752 753 // Do not allow banning yourself, the guest account, or founders. 754 $non_bannable = array($user->data['user_id'], ANONYMOUS); 755 if (sizeof($founder)) 756 { 757 $sql .= ' AND ' . $db->sql_in_set('user_id', array_merge(array_keys($founder), $non_bannable), true); 758 } 759 else 760 { 761 $sql .= ' AND ' . $db->sql_in_set('user_id', $non_bannable, true); 762 } 763 764 $result = $db->sql_query($sql); 765 766 if ($row = $db->sql_fetchrow($result)) 767 { 768 do 769 { 770 $banlist_ary[] = (int) $row['user_id']; 771 } 772 while ($row = $db->sql_fetchrow($result)); 773 } 774 else 775 { 776 $db->sql_freeresult($result); 777 trigger_error('NO_USERS', E_USER_WARNING); 778 } 779 $db->sql_freeresult($result); 780 break; 781 782 case 'ip': 783 $type = 'ban_ip'; 784 785 foreach ($ban_list as $ban_item) 786 { 787 if (preg_match('#^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})[ ]*\-[ ]*([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$#', trim($ban_item), $ip_range_explode)) 788 { 789 // This is an IP range 790 // Don't ask about all this, just don't ask ... ! 791 $ip_1_counter = $ip_range_explode[1]; 792 $ip_1_end = $ip_range_explode[5]; 793 794 while ($ip_1_counter <= $ip_1_end) 795 { 796 $ip_2_counter = ($ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[2] : 0; 797 $ip_2_end = ($ip_1_counter < $ip_1_end) ? 254 : $ip_range_explode[6]; 798 799 if ($ip_2_counter == 0 && $ip_2_end == 254) 800 { 801 $ip_2_counter = 256; 802 $ip_2_fragment = 256; 803 804 $banlist_ary[] = "$ip_1_counter.*"; 805 } 806 807 while ($ip_2_counter <= $ip_2_end) 808 { 809 $ip_3_counter = ($ip_2_counter == $ip_range_explode[2] && $ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[3] : 0; 810 $ip_3_end = ($ip_2_counter < $ip_2_end || $ip_1_counter < $ip_1_end) ? 254 : $ip_range_explode[7]; 811 812 if ($ip_3_counter == 0 && $ip_3_end == 254) 813 { 814 $ip_3_counter = 256; 815 $ip_3_fragment = 256; 816 817 $banlist_ary[] = "$ip_1_counter.$ip_2_counter.*"; 818 } 819 820 while ($ip_3_counter <= $ip_3_end) 821 { 822 $ip_4_counter = ($ip_3_counter == $ip_range_explode[3] && $ip_2_counter == $ip_range_explode[2] && $ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[4] : 0; 823 $ip_4_end = ($ip_3_counter < $ip_3_end || $ip_2_counter < $ip_2_end) ? 254 : $ip_range_explode[8]; 824 825 if ($ip_4_counter == 0 && $ip_4_end == 254) 826 { 827 $ip_4_counter = 256; 828 $ip_4_fragment = 256; 829 830 $banlist_ary[] = "$ip_1_counter.$ip_2_counter.$ip_3_counter.*"; 831 } 832 833 while ($ip_4_counter <= $ip_4_end) 834 { 835 $banlist_ary[] = "$ip_1_counter.$ip_2_counter.$ip_3_counter.$ip_4_counter"; 836 $ip_4_counter++; 837 } 838 $ip_3_counter++; 839 } 840 $ip_2_counter++; 841 } 842 $ip_1_counter++; 843 } 844 } 845 else if (preg_match('#^([0-9]{1,3})\.([0-9\*]{1,3})\.([0-9\*]{1,3})\.([0-9\*]{1,3})$#', trim($ban_item)) || preg_match('#^[a-f0-9:]+\*?$#i', trim($ban_item))) 846 { 847 // Normal IP address 848 $banlist_ary[] = trim($ban_item); 849 } 850 else if (preg_match('#^\*$#', trim($ban_item))) 851 { 852 // Ban all IPs 853 $banlist_ary[] = '*'; 854 } 855 else if (preg_match('#^([\w\-_]\.?){2,}$#is', trim($ban_item))) 856 { 857 // hostname 858 $ip_ary = gethostbynamel(trim($ban_item)); 859 860 if (!empty($ip_ary)) 861 { 862 foreach ($ip_ary as $ip) 863 { 864 if ($ip) 865 { 866 if (strlen($ip) > 40) 867 { 868 continue; 869 } 870 871 $banlist_ary[] = $ip; 872 } 873 } 874 } 875 } 876 877 if (empty($banlist_ary)) 878 { 879 trigger_error('NO_IPS_DEFINED', E_USER_WARNING); 880 } 881 } 882 break; 883 884 case 'email': 885 $type = 'ban_email'; 886 887 foreach ($ban_list as $ban_item) 888 { 889 $ban_item = trim($ban_item); 890 891 if (preg_match('#^.*?@*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i', $ban_item)) 892 { 893 if (strlen($ban_item) > 100) 894 { 895 continue; 896 } 897 898 if (!sizeof($founder) || !in_array($ban_item, $founder)) 899 { 900 $banlist_ary[] = $ban_item; 901 } 902 } 903 } 904 905 if (sizeof($ban_list) == 0) 906 { 907 trigger_error('NO_EMAILS_DEFINED', E_USER_WARNING); 908 } 909 break; 910 911 default: 912 trigger_error('NO_MODE', E_USER_WARNING); 913 break; 914 } 915 916 // Fetch currently set bans of the specified type and exclude state. Prevent duplicate bans. 917 $sql_where = ($type == 'ban_userid') ? 'ban_userid <> 0' : "$type <> ''"; 918 919 $sql = "SELECT $type 920 FROM " . BANLIST_TABLE . " 921 WHERE $sql_where 922 AND ban_exclude = " . (int) $ban_exclude; 923 $result = $db->sql_query($sql); 924 925 // Reset $sql_where, because we use it later... 926 $sql_where = ''; 927 928 if ($row = $db->sql_fetchrow($result)) 929 { 930 $banlist_ary_tmp = array(); 931 do 932 { 933 switch ($mode) 934 { 935 case 'user': 936 $banlist_ary_tmp[] = $row['ban_userid']; 937 break; 938 939 case 'ip': 940 $banlist_ary_tmp[] = $row['ban_ip']; 941 break; 942 943 case 'email': 944 $banlist_ary_tmp[] = $row['ban_email']; 945 break; 946 } 947 } 948 while ($row = $db->sql_fetchrow($result)); 949 950 $banlist_ary_tmp = array_intersect($banlist_ary, $banlist_ary_tmp); 951 952 if (sizeof($banlist_ary_tmp)) 953 { 954 // One or more entities are already banned/excluded, delete the existing bans, so they can be re-inserted with the given new length 955 $sql = 'DELETE FROM ' . BANLIST_TABLE . ' 956 WHERE ' . $db->sql_in_set($type, $banlist_ary_tmp) . ' 957 AND ban_exclude = ' . (int) $ban_exclude; 958 $db->sql_query($sql); 959 } 960 961 unset($banlist_ary_tmp); 962 } 963 $db->sql_freeresult($result); 964 965 // We have some entities to ban 966 if (sizeof($banlist_ary)) 967 { 968 $sql_ary = array(); 969 970 foreach ($banlist_ary as $ban_entry) 971 { 972 $sql_ary[] = array( 973 $type => $ban_entry, 974 'ban_start' => (int) $current_time, 975 'ban_end' => (int) $ban_end, 976 'ban_exclude' => (int) $ban_exclude, 977 'ban_reason' => (string) $ban_reason, 978 'ban_give_reason' => (string) $ban_give_reason, 979 ); 980 } 981 982 $db->sql_multi_insert(BANLIST_TABLE, $sql_ary); 983 984 // If we are banning we want to logout anyone matching the ban 985 if (!$ban_exclude) 986 { 987 switch ($mode) 988 { 989 case 'user': 990 $sql_where = 'WHERE ' . $db->sql_in_set('session_user_id', $banlist_ary); 991 break; 992 993 case 'ip': 994 $sql_where = 'WHERE ' . $db->sql_in_set('session_ip', $banlist_ary); 995 break; 996 997 case 'email': 998 $banlist_ary_sql = array(); 999 1000 foreach ($banlist_ary as $ban_entry) 1001 { 1002 $banlist_ary_sql[] = (string) str_replace('*', '%', $ban_entry); 1003 } 1004 1005 $sql = 'SELECT user_id 1006 FROM ' . USERS_TABLE . ' 1007 WHERE ' . $db->sql_in_set('user_email', $banlist_ary_sql); 1008 $result = $db->sql_query($sql); 1009 1010 $sql_in = array(); 1011 1012 if ($row = $db->sql_fetchrow($result)) 1013 { 1014 do 1015 { 1016 $sql_in[] = $row['user_id']; 1017 } 1018 while ($row = $db->sql_fetchrow($result)); 1019 1020 $sql_where = 'WHERE ' . $db->sql_in_set('session_user_id', $sql_in); 1021 } 1022 $db->sql_freeresult($result); 1023 break; 1024 } 1025 1026 if (isset($sql_where) && $sql_where) 1027 { 1028 $sql = 'DELETE FROM ' . SESSIONS_TABLE . " 1029 $sql_where"; 1030 $db->sql_query($sql); 1031 1032 if ($mode == 'user') 1033 { 1034 $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' ' . ((in_array('*', $banlist_ary)) ? '' : 'WHERE ' . $db->sql_in_set('user_id', $banlist_ary)); 1035 $db->sql_query($sql); 1036 } 1037 } 1038 } 1039 1040 // Update log 1041 $log_entry = ($ban_exclude) ? 'LOG_BAN_EXCLUDE_' : 'LOG_BAN_'; 1042 1043 // Add to moderator log, admin log and user notes 1044 add_log('admin', $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); 1045 add_log('mod', 0, 0, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); 1046 if ($mode == 'user') 1047 { 1048 foreach ($banlist_ary as $user_id) 1049 { 1050 add_log('user', $user_id, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); 1051 } 1052 } 1053 1054 $cache->destroy('sql', BANLIST_TABLE); 1055 1056 return true; 1057 } 1058 1059 // There was nothing to ban/exclude. But destroying the cache because of the removal of stale bans. 1060 $cache->destroy('sql', BANLIST_TABLE); 1061 1062 return false; 1063 } 1064 1065 /** 1066 * Unban User 1067 */ 1068 function user_unban($mode, $ban) 1069 { 1070 global $db, $user, $auth, $cache; 1071 1072 // Delete stale bans 1073 $sql = 'DELETE FROM ' . BANLIST_TABLE . ' 1074 WHERE ban_end < ' . time() . ' 1075 AND ban_end <> 0'; 1076 $db->sql_query($sql); 1077 1078 if (!is_array($ban)) 1079 { 1080 $ban = array($ban); 1081 } 1082 1083 $unban_sql = array_map('intval', $ban); 1084 1085 if (sizeof($unban_sql)) 1086 { 1087 // Grab details of bans for logging information later 1088 switch ($mode) 1089 { 1090 case 'user': 1091 $sql = 'SELECT u.username AS unban_info, u.user_id 1092 FROM ' . USERS_TABLE . ' u, ' . BANLIST_TABLE . ' b 1093 WHERE ' . $db->sql_in_set('b.ban_id', $unban_sql) . ' 1094 AND u.user_id = b.ban_userid'; 1095 break; 1096 1097 case 'email': 1098 $sql = 'SELECT ban_email AS unban_info 1099 FROM ' . BANLIST_TABLE . ' 1100 WHERE ' . $db->sql_in_set('ban_id', $unban_sql); 1101 break; 1102 1103 case 'ip': 1104 $sql = 'SELECT ban_ip AS unban_info 1105 FROM ' . BANLIST_TABLE . ' 1106 WHERE ' . $db->sql_in_set('ban_id', $unban_sql); 1107 break; 1108 } 1109 $result = $db->sql_query($sql); 1110 1111 $l_unban_list = ''; 1112 $user_ids_ary = array(); 1113 while ($row = $db->sql_fetchrow($result)) 1114 { 1115 $l_unban_list .= (($l_unban_list != '') ? ', ' : '') . $row['unban_info']; 1116 if ($mode == 'user') 1117 { 1118 $user_ids_ary[] = $row['user_id']; 1119 } 1120 } 1121 $db->sql_freeresult($result); 1122 1123 $sql = 'DELETE FROM ' . BANLIST_TABLE . ' 1124 WHERE ' . $db->sql_in_set('ban_id', $unban_sql); 1125 $db->sql_query($sql); 1126 1127 // Add to moderator log, admin log and user notes 1128 add_log('admin', 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); 1129 add_log('mod', 0, 0, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); 1130 if ($mode == 'user') 1131 { 1132 foreach ($user_ids_ary as $user_id) 1133 { 1134 add_log('user', $user_id, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); 1135 } 1136 } 1137 } 1138 1139 $cache->destroy('sql', BANLIST_TABLE); 1140 1141 return false; 1142 } 1143 1144 /** 1145 * Internet Protocol Address Whois 1146 * RFC3912: WHOIS Protocol Specification 1147 * 1148 * @param string $ip Ip address, either IPv4 or IPv6. 1149 * 1150 * @return string Empty string if not a valid ip address. 1151 * Otherwise make_clickable()'ed whois result. 1152 */ 1153 function user_ipwhois($ip) 1154 { 1155 if (empty($ip)) 1156 { 1157 return ''; 1158 } 1159 1160 if (preg_match(get_preg_expression('ipv4'), $ip)) 1161 { 1162 // IPv4 address 1163 $whois_host = 'whois.arin.net.'; 1164 } 1165 else if (preg_match(get_preg_expression('ipv6'), $ip)) 1166 { 1167 // IPv6 address 1168 $whois_host = 'whois.sixxs.net.'; 1169 } 1170 else 1171 { 1172 return ''; 1173 } 1174 1175 $ipwhois = ''; 1176 1177 if (($fsk = @fsockopen($whois_host, 43))) 1178 { 1179 // CRLF as per RFC3912 1180 fputs($fsk, "$ip\r\n"); 1181 while (!feof($fsk)) 1182 { 1183 $ipwhois .= fgets($fsk, 1024); 1184 } 1185 @fclose($fsk); 1186 } 1187 1188 $match = array(); 1189 1190 // Test for referrals from $whois_host to other whois databases, roll on rwhois 1191 if (preg_match('#ReferralServer: whois://(.+)#im', $ipwhois, $match)) 1192 { 1193 if (strpos($match[1], ':') !== false) 1194 { 1195 $pos = strrpos($match[1], ':'); 1196 $server = substr($match[1], 0, $pos); 1197 $port = (int) substr($match[1], $pos + 1); 1198 unset($pos); 1199 } 1200 else 1201 { 1202 $server = $match[1]; 1203 $port = 43; 1204 } 1205 1206 $buffer = ''; 1207 1208 if (($fsk = @fsockopen($server, $port))) 1209 { 1210 fputs($fsk, "$ip\r\n"); 1211 while (!feof($fsk)) 1212 { 1213 $buffer .= fgets($fsk, 1024); 1214 } 1215 @fclose($fsk); 1216 } 1217 1218 // Use the result from $whois_host if we don't get any result here 1219 $ipwhois = (empty($buffer)) ? $ipwhois : $buffer; 1220 } 1221 1222 $ipwhois = htmlspecialchars($ipwhois); 1223 1224 // Magic URL ;) 1225 return trim(make_clickable($ipwhois, false, '')); 1226 } 1227 1228 /** 1229 * Data validation ... used primarily but not exclusively by ucp modules 1230 * 1231 * "Master" function for validating a range of data types 1232 */ 1233 function validate_data($data, $val_ary) 1234 { 1235 global $user; 1236 1237 $error = array(); 1238 1239 foreach ($val_ary as $var => $val_seq) 1240 { 1241 if (!is_array($val_seq[0])) 1242 { 1243 $val_seq = array($val_seq); 1244 } 1245 1246 foreach ($val_seq as $validate) 1247 { 1248 $function = array_shift($validate); 1249 array_unshift($validate, $data[$var]); 1250 $function_prefix = (function_exists('phpbb_validate_' . $function)) ? 'phpbb_validate_' : 'validate_'; 1251 1252 if ($result = call_user_func_array($function_prefix . $function, $validate)) 1253 { 1254 // Since errors are checked later for their language file existence, we need to make sure custom errors are not adjusted. 1255 $error[] = (empty($user->lang[$result . '_' . strtoupper($var)])) ? $result : $result . '_' . strtoupper($var); 1256 } 1257 } 1258 } 1259 1260 return $error; 1261 } 1262 1263 /** 1264 * Validate String 1265 * 1266 * @return boolean|string Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) 1267 */ 1268 function validate_string($string, $optional = false, $min = 0, $max = 0) 1269 { 1270 if (empty($string) && $optional) 1271 { 1272 return false; 1273 } 1274 1275 if ($min && utf8_strlen(htmlspecialchars_decode($string)) < $min) 1276 { 1277 return 'TOO_SHORT'; 1278 } 1279 else if ($max && utf8_strlen(htmlspecialchars_decode($string)) > $max) 1280 { 1281 return 'TOO_LONG'; 1282 } 1283 1284 return false; 1285 } 1286 1287 /** 1288 * Validate Number 1289 * 1290 * @return boolean|string Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) 1291 */ 1292 function validate_num($num, $optional = false, $min = 0, $max = 1E99) 1293 { 1294 if (empty($num) && $optional) 1295 { 1296 return false; 1297 } 1298 1299 if ($num < $min) 1300 { 1301 return 'TOO_SMALL'; 1302 } 1303 else if ($num > $max) 1304 { 1305 return 'TOO_LARGE'; 1306 } 1307 1308 return false; 1309 } 1310 1311 /** 1312 * Validate Date 1313 * @param String $string a date in the dd-mm-yyyy format 1314 * @return boolean 1315 */ 1316 function validate_date($date_string, $optional = false) 1317 { 1318 $date = explode('-', $date_string); 1319 if ((empty($date) || sizeof($date) != 3) && $optional) 1320 { 1321 return false; 1322 } 1323 else if ($optional) 1324 { 1325 for ($field = 0; $field <= 1; $field++) 1326 { 1327 $date[$field] = (int) $date[$field]; 1328 if (empty($date[$field])) 1329 { 1330 $date[$field] = 1; 1331 } 1332 } 1333 $date[2] = (int) $date[2]; 1334 // assume an arbitrary leap year 1335 if (empty($date[2])) 1336 { 1337 $date[2] = 1980; 1338 } 1339 } 1340 1341 if (sizeof($date) != 3 || !checkdate($date[1], $date[0], $date[2])) 1342 { 1343 return 'INVALID'; 1344 } 1345 1346 return false; 1347 } 1348 1349 1350 /** 1351 * Validate Match 1352 * 1353 * @return boolean|string Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) 1354 */ 1355 function validate_match($string, $optional = false, $match = '') 1356 { 1357 if (empty($string) && $optional) 1358 { 1359 return false; 1360 } 1361 1362 if (empty($match)) 1363 { 1364 return false; 1365 } 1366 1367 if (!preg_match($match, $string)) 1368 { 1369 return 'WRONG_DATA'; 1370 } 1371 1372 return false; 1373 } 1374 1375 /** 1376 * Validate Language Pack ISO Name 1377 * 1378 * Tests whether a language name is valid and installed 1379 * 1380 * @param string $lang_iso The language string to test 1381 * 1382 * @return bool|string Either false if validation succeeded or 1383 * a string which will be used as the error message 1384 * (with the variable name appended) 1385 */ 1386 function validate_language_iso_name($lang_iso) 1387 { 1388 global $db; 1389 1390 $sql = 'SELECT lang_id 1391 FROM ' . LANG_TABLE . " 1392 WHERE lang_iso = '" . $db->sql_escape($lang_iso) . "'"; 1393 $result = $db->sql_query($sql); 1394 $lang_id = (int) $db->sql_fetchfield('lang_id'); 1395 $db->sql_freeresult($result); 1396 1397 return ($lang_id) ? false : 'WRONG_DATA'; 1398 } 1399 1400 /** 1401 * Check to see if the username has been taken, or if it is disallowed. 1402 * Also checks if it includes the " character, which we don't allow in usernames. 1403 * Used for registering, changing names, and posting anonymously with a username 1404 * 1405 * @param string $username The username to check 1406 * @param string $allowed_username An allowed username, default being $user->data['username'] 1407 * 1408 * @return mixed Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) 1409 */ 1410 function validate_username($username, $allowed_username = false) 1411 { 1412 global $config, $db, $user, $cache; 1413 1414 $clean_username = utf8_clean_string($username); 1415 $allowed_username = ($allowed_username === false) ? $user->data['username_clean'] : utf8_clean_string($allowed_username); 1416 1417 if ($allowed_username == $clean_username) 1418 { 1419 return false; 1420 } 1421 1422 // ... fast checks first. 1423 if (strpos($username, '"') !== false || strpos($username, '"') !== false || empty($clean_username)) 1424 { 1425 return 'INVALID_CHARS'; 1426 } 1427 1428 $mbstring = $pcre = false; 1429 1430 // generic UTF-8 character types supported? 1431 if ((version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false) 1432 { 1433 $pcre = true; 1434 } 1435 else if (function_exists('mb_ereg_match')) 1436 { 1437 mb_regex_encoding('UTF-8'); 1438 $mbstring = true; 1439 } 1440 1441 switch ($config['allow_name_chars']) 1442 { 1443 case 'USERNAME_CHARS_ANY': 1444 $pcre = true; 1445 $regex = '.+'; 1446 break; 1447 1448 case 'USERNAME_ALPHA_ONLY': 1449 $pcre = true; 1450 $regex = '[A-Za-z0-9]+'; 1451 break; 1452 1453 case 'USERNAME_ALPHA_SPACERS': 1454 $pcre = true; 1455 $regex = '[A-Za-z0-9-[\]_+ ]+'; 1456 break; 1457 1458 case 'USERNAME_LETTER_NUM': 1459 if ($pcre) 1460 { 1461 $regex = '[\p{Lu}\p{Ll}\p{N}]+'; 1462 } 1463 else if ($mbstring) 1464 { 1465 $regex = '[[:upper:][:lower:][:digit:]]+'; 1466 } 1467 else 1468 { 1469 $pcre = true; 1470 $regex = '[a-zA-Z0-9]+'; 1471 } 1472 break; 1473 1474 case 'USERNAME_LETTER_NUM_SPACERS': 1475 if ($pcre) 1476 { 1477 $regex = '[-\]_+ [\p{Lu}\p{Ll}\p{N}]+'; 1478 } 1479 else if ($mbstring) 1480 { 1481 $regex = '[-\]_+ \[[:upper:][:lower:][:digit:]]+'; 1482 } 1483 else 1484 { 1485 $pcre = true; 1486 $regex = '[-\]_+ [a-zA-Z0-9]+'; 1487 } 1488 break; 1489 1490 case 'USERNAME_ASCII': 1491 default: 1492 $pcre = true; 1493 $regex = '[\x01-\x7F]+'; 1494 break; 1495 } 1496 1497 if ($pcre) 1498 { 1499 if (!preg_match('#^' . $regex . '$#u', $username)) 1500 { 1501 return 'INVALID_CHARS'; 1502 } 1503 } 1504 else if ($mbstring) 1505 { 1506 mb_ereg_search_init($username, '^' . $regex . '$'); 1507 if (!mb_ereg_search()) 1508 { 1509 return 'INVALID_CHARS'; 1510 } 1511 } 1512 1513 $sql = 'SELECT username 1514 FROM ' . USERS_TABLE . " 1515 WHERE username_clean = '" . $db->sql_escape($clean_username) . "'"; 1516 $result = $db->sql_query($sql); 1517 $row = $db->sql_fetchrow($result); 1518 $db->sql_freeresult($result); 1519 1520 if ($row) 1521 { 1522 return 'USERNAME_TAKEN'; 1523 } 1524 1525 $sql = 'SELECT group_name 1526 FROM ' . GROUPS_TABLE . " 1527 WHERE LOWER(group_name) = '" . $db->sql_escape(utf8_strtolower($username)) . "'"; 1528 $result = $db->sql_query($sql); 1529 $row = $db->sql_fetchrow($result); 1530 $db->sql_freeresult($result); 1531 1532 if ($row) 1533 { 1534 return 'USERNAME_TAKEN'; 1535 } 1536 1537 $bad_usernames = $cache->obtain_disallowed_usernames(); 1538 1539 foreach ($bad_usernames as $bad_username) 1540 { 1541 if (preg_match('#^' . $bad_username . '$#', $clean_username)) 1542 { 1543 return 'USERNAME_DISALLOWED'; 1544 } 1545 } 1546 1547 return false; 1548 } 1549 1550 /** 1551 * Check to see if the password meets the complexity settings 1552 * 1553 * @return boolean|string Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) 1554 */ 1555 function validate_password($password) 1556 { 1557 global $config; 1558 1559 if ($password === '' || $config['pass_complex'] === 'PASS_TYPE_ANY') 1560 { 1561 // Password empty or no password complexity required. 1562 return false; 1563 } 1564 1565 $pcre = $mbstring = false; 1566 1567 // generic UTF-8 character types supported? 1568 if ((version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false) 1569 { 1570 $upp = '\p{Lu}'; 1571 $low = '\p{Ll}'; 1572 $num = '\p{N}'; 1573 $sym = '[^\p{Lu}\p{Ll}\p{N}]'; 1574 $pcre = true; 1575 } 1576 else if (function_exists('mb_ereg_match')) 1577 { 1578 mb_regex_encoding('UTF-8'); 1579 $upp = '[[:upper:]]'; 1580 $low = '[[:lower:]]'; 1581 $num = '[[:digit:]]'; 1582 $sym = '[^[:upper:][:lower:][:digit:]]'; 1583 $mbstring = true; 1584 } 1585 else 1586 { 1587 $upp = '[A-Z]'; 1588 $low = '[a-z]'; 1589 $num = '[0-9]'; 1590 $sym = '[^A-Za-z0-9]'; 1591 $pcre = true; 1592 } 1593 1594 $chars = array(); 1595 1596 switch ($config['pass_complex']) 1597 { 1598 // No break statements below ... 1599 // We require strong passwords in case pass_complex is not set or is invalid 1600 default: 1601 1602 // Require mixed case letters, numbers and symbols 1603 case 'PASS_TYPE_SYMBOL': 1604 $chars[] = $sym; 1605 1606 // Require mixed case letters and numbers 1607 case 'PASS_TYPE_ALPHA': 1608 $chars[] = $num; 1609 1610 // Require mixed case letters 1611 case 'PASS_TYPE_CASE': 1612 $chars[] = $low; 1613 $chars[] = $upp; 1614 } 1615 1616 if ($pcre) 1617 { 1618 foreach ($chars as $char) 1619 { 1620 if (!preg_match('#' . $char . '#u', $password)) 1621 { 1622 return 'INVALID_CHARS'; 1623 } 1624 } 1625 } 1626 else if ($mbstring) 1627 { 1628 foreach ($chars as $char) 1629 { 1630 if (mb_ereg($char, $password) === false) 1631 { 1632 return 'INVALID_CHARS'; 1633 } 1634 } 1635 } 1636 1637 return false; 1638 } 1639 1640 /** 1641 * Check to see if email address is banned or already present in the DB 1642 * 1643 * @param string $email The email to check 1644 * @param string $allowed_email An allowed email, default being $user->data['user_email'] 1645 * 1646 * @return mixed Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) 1647 */ 1648 function validate_email($email, $allowed_email = false) 1649 { 1650 global $config, $db, $user; 1651 1652 $email = strtolower($email); 1653 $allowed_email = ($allowed_email === false) ? strtolower($user->data['user_email']) : strtolower($allowed_email); 1654 1655 if ($allowed_email == $email) 1656 { 1657 return false; 1658 } 1659 1660 if (!preg_match('/^' . get_preg_expression('email') . '$/i', $email)) 1661 { 1662 return 'EMAIL_INVALID'; 1663 } 1664 1665 // Check MX record. 1666 // The idea for this is from reading the UseBB blog/announcement. :) 1667 if ($config['email_check_mx']) 1668 { 1669 list(, $domain) = explode('@', $email); 1670 1671 if (phpbb_checkdnsrr($domain, 'A') === false && phpbb_checkdnsrr($domain, 'MX') === false) 1672 { 1673 return 'DOMAIN_NO_MX_RECORD'; 1674 } 1675 } 1676 1677 if (($ban_reason = $user->check_ban(false, false, $email, true)) !== false) 1678 { 1679 return ($ban_reason === true) ? 'EMAIL_BANNED' : $ban_reason; 1680 } 1681 1682 if (!$config['allow_emailreuse']) 1683 { 1684 $sql = 'SELECT user_email_hash 1685 FROM ' . USERS_TABLE . " 1686 WHERE user_email_hash = " . $db->sql_escape(phpbb_email_hash($email)); 1687 $result = $db->sql_query($sql); 1688 $row = $db->sql_fetchrow($result); 1689 $db->sql_freeresult($result); 1690 1691 if ($row) 1692 { 1693 return 'EMAIL_TAKEN'; 1694 } 1695 } 1696 1697 return false; 1698 } 1699 1700 /** 1701 * Validate jabber address 1702 * Taken from the jabber class within flyspray (see author notes) 1703 * 1704 * @author flyspray.org 1705 */ 1706 function validate_jabber($jid) 1707 { 1708 if (!$jid) 1709 { 1710 return false; 1711 } 1712 1713 $seperator_pos = strpos($jid, '@'); 1714 1715 if ($seperator_pos === false) 1716 { 1717 return 'WRONG_DATA'; 1718 } 1719 1720 $username = substr($jid, 0, $seperator_pos); 1721 $realm = substr($jid, $seperator_pos + 1); 1722 1723 if (strlen($username) == 0 || strlen($realm) < 3) 1724 { 1725 return 'WRONG_DATA'; 1726 } 1727 1728 $arr = explode('.', $realm); 1729 1730 if (sizeof($arr) == 0) 1731 { 1732 return 'WRONG_DATA'; 1733 } 1734 1735 foreach ($arr as $part) 1736 { 1737 if (substr($part, 0, 1) == '-' || substr($part, -1, 1) == '-') 1738 { 1739 return 'WRONG_DATA'; 1740 } 1741 1742 if (!preg_match("@^[a-zA-Z0-9-.]+$@", $part)) 1743 { 1744 return 'WRONG_DATA'; 1745 } 1746 } 1747 1748 $boundary = array(array(0, 127), array(192, 223), array(224, 239), array(240, 247), array(248, 251), array(252, 253)); 1749 1750 // Prohibited Characters RFC3454 + RFC3920 1751 $prohibited = array( 1752 // Table C.1.1 1753 array(0x0020, 0x0020), // SPACE 1754 // Table C.1.2 1755 array(0x00A0, 0x00A0), // NO-BREAK SPACE 1756 array(0x1680, 0x1680), // OGHAM SPACE MARK 1757 array(0x2000, 0x2001), // EN QUAD 1758 array(0x2001, 0x2001), // EM QUAD 1759 array(0x2002, 0x2002), // EN SPACE 1760 array(0x2003, 0x2003), // EM SPACE 1761 array(0x2004, 0x2004), // THREE-PER-EM SPACE 1762 array(0x2005, 0x2005), // FOUR-PER-EM SPACE 1763 array(0x2006, 0x2006), // SIX-PER-EM SPACE 1764 array(0x2007, 0x2007), // FIGURE SPACE 1765 array(0x2008, 0x2008), // PUNCTUATION SPACE 1766 array(0x2009, 0x2009), // THIN SPACE 1767 array(0x200A, 0x200A), // HAIR SPACE 1768 array(0x200B, 0x200B), // ZERO WIDTH SPACE 1769 array(0x202F, 0x202F), // NARROW NO-BREAK SPACE 1770 array(0x205F, 0x205F), // MEDIUM MATHEMATICAL SPACE 1771 array(0x3000, 0x3000), // IDEOGRAPHIC SPACE 1772 // Table C.2.1 1773 array(0x0000, 0x001F), // [CONTROL CHARACTERS] 1774 array(0x007F, 0x007F), // DELETE 1775 // Table C.2.2 1776 array(0x0080, 0x009F), // [CONTROL CHARACTERS] 1777 array(0x06DD, 0x06DD), // ARABIC END OF AYAH 1778 array(0x070F, 0x070F), // SYRIAC ABBREVIATION MARK 1779 array(0x180E, 0x180E), // MONGOLIAN VOWEL SEPARATOR 1780 array(0x200C, 0x200C), // ZERO WIDTH NON-JOINER 1781 array(0x200D, 0x200D), // ZERO WIDTH JOINER 1782 array(0x2028, 0x2028), // LINE SEPARATOR 1783 array(0x2029, 0x2029), // PARAGRAPH SEPARATOR 1784 array(0x2060, 0x2060), // WORD JOINER 1785 array(0x2061, 0x2061), // FUNCTION APPLICATION 1786 array(0x2062, 0x2062), // INVISIBLE TIMES 1787 array(0x2063, 0x2063), // INVISIBLE SEPARATOR 1788 array(0x206A, 0x206F), // [CONTROL CHARACTERS] 1789 array(0xFEFF, 0xFEFF), // ZERO WIDTH NO-BREAK SPACE 1790 array(0xFFF9, 0xFFFC), // [CONTROL CHARACTERS] 1791 array(0x1D173, 0x1D17A), // [MUSICAL CONTROL CHARACTERS] 1792 // Table C.3 1793 array(0xE000, 0xF8FF), // [PRIVATE USE, PLANE 0] 1794 array(0xF0000, 0xFFFFD), // [PRIVATE USE, PLANE 15] 1795 array(0x100000, 0x10FFFD), // [PRIVATE USE, PLANE 16] 1796 // Table C.4 1797 array(0xFDD0, 0xFDEF), // [NONCHARACTER CODE POINTS] 1798 array(0xFFFE, 0xFFFF), // [NONCHARACTER CODE POINTS] 1799 array(0x1FFFE, 0x1FFFF), // [NONCHARACTER CODE POINTS] 1800 array(0x2FFFE, 0x2FFFF), // [NONCHARACTER CODE POINTS] 1801 array(0x3FFFE, 0x3FFFF), // [NONCHARACTER CODE POINTS] 1802 array(0x4FFFE, 0x4FFFF), // [NONCHARACTER CODE POINTS] 1803 array(0x5FFFE, 0x5FFFF), // [NONCHARACTER CODE POINTS] 1804 array(0x6FFFE, 0x6FFFF), // [NONCHARACTER CODE POINTS] 1805 array(0x7FFFE, 0x7FFFF), // [NONCHARACTER CODE POINTS] 1806 array(0x8FFFE, 0x8FFFF), // [NONCHARACTER CODE POINTS] 1807 array(0x9FFFE, 0x9FFFF), // [NONCHARACTER CODE POINTS] 1808 array(0xAFFFE, 0xAFFFF), // [NONCHARACTER CODE POINTS] 1809 array(0xBFFFE, 0xBFFFF), // [NONCHARACTER CODE POINTS] 1810 array(0xCFFFE, 0xCFFFF), // [NONCHARACTER CODE POINTS] 1811 array(0xDFFFE, 0xDFFFF), // [NONCHARACTER CODE POINTS] 1812 array(0xEFFFE, 0xEFFFF), // [NONCHARACTER CODE POINTS] 1813 array(0xFFFFE, 0xFFFFF), // [NONCHARACTER CODE POINTS] 1814 array(0x10FFFE, 0x10FFFF), // [NONCHARACTER CODE POINTS] 1815 // Table C.5 1816 array(0xD800, 0xDFFF), // [SURROGATE CODES] 1817 // Table C.6 1818 array(0xFFF9, 0xFFF9), // INTERLINEAR ANNOTATION ANCHOR 1819 array(0xFFFA, 0xFFFA), // INTERLINEAR ANNOTATION SEPARATOR 1820 array(0xFFFB, 0xFFFB), // INTERLINEAR ANNOTATION TERMINATOR 1821 array(0xFFFC, 0xFFFC), // OBJECT REPLACEMENT CHARACTER 1822 array(0xFFFD, 0xFFFD), // REPLACEMENT CHARACTER 1823 // Table C.7 1824 array(0x2FF0, 0x2FFB), // [IDEOGRAPHIC DESCRIPTION CHARACTERS] 1825 // Table C.8 1826 array(0x0340, 0x0340), // COMBINING GRAVE TONE MARK 1827 array(0x0341, 0x0341), // COMBINING ACUTE TONE MARK 1828 array(0x200E, 0x200E), // LEFT-TO-RIGHT MARK 1829 array(0x200F, 0x200F), // RIGHT-TO-LEFT MARK 1830 array(0x202A, 0x202A), // LEFT-TO-RIGHT EMBEDDING 1831 array(0x202B, 0x202B), // RIGHT-TO-LEFT EMBEDDING 1832 array(0x202C, 0x202C), // POP DIRECTIONAL FORMATTING 1833 array(0x202D, 0x202D), // LEFT-TO-RIGHT OVERRIDE 1834 array(0x202E, 0x202E), // RIGHT-TO-LEFT OVERRIDE 1835 array(0x206A, 0x206A), // INHIBIT SYMMETRIC SWAPPING 1836 array(0x206B, 0x206B), // ACTIVATE SYMMETRIC SWAPPING 1837 array(0x206C, 0x206C), // INHIBIT ARABIC FORM SHAPING 1838 array(0x206D, 0x206D), // ACTIVATE ARABIC FORM SHAPING 1839 array(0x206E, 0x206E), // NATIONAL DIGIT SHAPES 1840 array(0x206F, 0x206F), // NOMINAL DIGIT SHAPES 1841 // Table C.9 1842 array(0xE0001, 0xE0001), // LANGUAGE TAG 1843 array(0xE0020, 0xE007F), // [TAGGING CHARACTERS] 1844 // RFC3920 1845 array(0x22, 0x22), // " 1846 array(0x26, 0x26), // & 1847 array(0x27, 0x27), // ' 1848 array(0x2F, 0x2F), // / 1849 array(0x3A, 0x3A), // : 1850 array(0x3C, 0x3C), // < 1851 array(0x3E, 0x3E), // > 1852 array(0x40, 0x40) // @ 1853 ); 1854 1855 $pos = 0; 1856 $result = true; 1857 1858 while ($pos < strlen($username)) 1859 { 1860 $len = $uni = 0; 1861 for ($i = 0; $i <= 5; $i++) 1862 { 1863 if (ord($username[$pos]) >= $boundary[$i][0] && ord($username[$pos]) <= $boundary[$i][1]) 1864 { 1865 $len = $i + 1; 1866 $uni = (ord($username[$pos]) - $boundary[$i][0]) * pow(2, $i * 6); 1867 1868 for ($k = 1; $k < $len; $k++) 1869 { 1870 $uni += (ord($username[$pos + $k]) - 128) * pow(2, ($i - $k) * 6); 1871 } 1872 1873 break; 1874 } 1875 } 1876 1877 if ($len == 0) 1878 { 1879 return 'WRONG_DATA'; 1880 } 1881 1882 foreach ($prohibited as $pval) 1883 { 1884 if ($uni >= $pval[0] && $uni <= $pval[1]) 1885 { 1886 $result = false; 1887 break 2; 1888 } 1889 } 1890 1891 $pos = $pos + $len; 1892 } 1893 1894 if (!$result) 1895 { 1896 return 'WRONG_DATA'; 1897 } 1898 1899 return false; 1900 } 1901 1902 /** 1903 * Validate hex colour value 1904 * 1905 * @param string $colour The hex colour value 1906 * @param bool $optional Whether the colour value is optional. True if an empty 1907 * string will be accepted as correct input, false if not. 1908 * @return bool|string Error message if colour value is incorrect, false if it 1909 * fits the hex colour code 1910 */ 1911 function phpbb_validate_hex_colour($colour, $optional = false) 1912 { 1913 if ($colour === '') 1914 { 1915 return (($optional) ? false : 'WRONG_DATA'); 1916 } 1917 1918 if (!preg_match('/^([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/', $colour)) 1919 { 1920 return 'WRONG_DATA'; 1921 } 1922 1923 return false; 1924 } 1925 1926 /** 1927 * Verifies whether a style ID corresponds to an active style. 1928 * 1929 * @param int $style_id The style_id of a style which should be checked if activated or not. 1930 * @return boolean 1931 */ 1932 function phpbb_style_is_active($style_id) 1933 { 1934 global $db; 1935 1936 $sql = 'SELECT style_active 1937 FROM ' . STYLES_TABLE . ' 1938 WHERE style_id = '. (int) $style_id; 1939 $result = $db->sql_query($sql); 1940 1941 $style_is_active = (bool) $db->sql_fetchfield('style_active'); 1942 $db->sql_freeresult($result); 1943 1944 return $style_is_active; 1945 } 1946 1947 /** 1948 * Remove avatar 1949 */ 1950 function avatar_delete($mode, $row, $clean_db = false) 1951 { 1952 global $phpbb_root_path, $config, $db, $user; 1953 1954 // Check if the users avatar is actually *not* a group avatar 1955 if ($mode == 'user') 1956 { 1957 if (strpos($row['user_avatar'], 'g') === 0 || (((int)$row['user_avatar'] !== 0) && ((int)$row['user_avatar'] !== (int)$row['user_id']))) 1958 { 1959 return false; 1960 } 1961 } 1962 1963 if ($clean_db) 1964 { 1965 avatar_remove_db($row[$mode . '_avatar']); 1966 } 1967 $filename = get_avatar_filename($row[$mode . '_avatar']); 1968 if (file_exists($phpbb_root_path . $config['avatar_path'] . '/' . $filename)) 1969 { 1970 @unlink($phpbb_root_path . $config['avatar_path'] . '/' . $filename); 1971 return true; 1972 } 1973 1974 return false; 1975 } 1976 1977 /** 1978 * Remote avatar linkage 1979 */ 1980 function avatar_remote($data, &$error) 1981 { 1982 global $config, $db, $user, $phpbb_root_path, $phpEx; 1983 1984 if (!preg_match('#^(http|https|ftp)://#i', $data['remotelink'])) 1985 { 1986 $data['remotelink'] = 'http://' . $data['remotelink']; 1987 } 1988 if (!preg_match('#^(http|https|ftp)://(?:(.*?\.)*?[a-z0-9\-]+?\.[a-z]{2,4}|(?:\d{1,3}\.){3,5}\d{1,3}):?([0-9]*?).*?\.(gif|jpg|jpeg|png)$#i', $data['remotelink'])) 1989 { 1990 $error[] = $user->lang['AVATAR_URL_INVALID']; 1991 return false; 1992 } 1993 1994 // Make sure getimagesize works... 1995 if (($image_data = @getimagesize($data['remotelink'])) === false && (empty($data['width']) || empty($data['height']))) 1996 { 1997 $error[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; 1998 return false; 1999 } 2000 2001 if (!empty($image_data) && ($image_data[0] < 2 || $image_data[1] < 2)) 2002 { 2003 $error[] = $user->lang['AVATAR_NO_SIZE']; 2004 return false; 2005 } 2006 2007 $width = ($data['width'] && $data['height']) ? $data['width'] : $image_data[0]; 2008 $height = ($data['width'] && $data['height']) ? $data['height'] : $image_data[1]; 2009 2010 if ($width < 2 || $height < 2) 2011 { 2012 $error[] = $user->lang['AVATAR_NO_SIZE']; 2013 return false; 2014 } 2015 2016 // Check image type 2017 include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); 2018 $types = fileupload::image_types(); 2019 $extension = strtolower(filespec::get_extension($data['remotelink'])); 2020 2021 if (!empty($image_data) && (!isset($types[$image_data[2]]) || !in_array($extension, $types[$image_data[2]]))) 2022 { 2023 if (!isset($types[$image_data[2]])) 2024 { 2025 $error[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; 2026 } 2027 else 2028 { 2029 $error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$image_data[2]][0], $extension); 2030 } 2031 return false; 2032 } 2033 2034 if ($config['avatar_max_width'] || $config['avatar_max_height']) 2035 { 2036 if ($width > $config['avatar_max_width'] || $height > $config['avatar_max_height']) 2037 { 2038 $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $width, $height); 2039 return false; 2040 } 2041 } 2042 2043 if ($config['avatar_min_width'] || $config['avatar_min_height']) 2044 { 2045 if ($width < $config['avatar_min_width'] || $height < $config['avatar_min_height']) 2046 { 2047 $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $width, $height); 2048 return false; 2049 } 2050 } 2051 2052 return array(AVATAR_REMOTE, $data['remotelink'], $width, $height); 2053 } 2054 2055 /** 2056 * Avatar upload using the upload class 2057 */ 2058 function avatar_upload($data, &$error) 2059 { 2060 global $phpbb_root_path, $config, $db, $user, $phpEx; 2061 2062 // Init upload class 2063 include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); 2064 $upload = new fileupload('AVATAR_', array('jpg', 'jpeg', 'gif', 'png'), $config['avatar_filesize'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], (isset($config['mime_triggers']) ? explode('|', $config['mime_triggers']) : false)); 2065 2066 if (!empty($_FILES['uploadfile']['name'])) 2067 { 2068 $file = $upload->form_upload('uploadfile'); 2069 } 2070 else 2071 { 2072 $file = $upload->remote_upload($data['uploadurl']); 2073 } 2074 2075 $prefix = $config['avatar_salt'] . '_'; 2076 $file->clean_filename('avatar', $prefix, $data['user_id']); 2077 2078 $destination = $config['avatar_path']; 2079 2080 // Adjust destination path (no trailing slash) 2081 if (substr($destination, -1, 1) == '/' || substr($destination, -1, 1) == '\\') 2082 { 2083 $destination = substr($destination, 0, -1); 2084 } 2085 2086 $destination = str_replace(array('../', '..\\', './', '.\\'), '', $destination); 2087 if ($destination && ($destination[0] == '/' || $destination[0] == "\\")) 2088 { 2089 $destination = ''; 2090 } 2091 2092 // Move file and overwrite any existing image 2093 $file->move_file($destination, true); 2094 2095 if (sizeof($file->error)) 2096 { 2097 $file->remove(); 2098 $error = array_merge($error, $file->error); 2099 } 2100 2101 return array(AVATAR_UPLOAD, $data['user_id'] . '_' . time() . '.' . $file->get('extension'), $file->get('width'), $file->get('height')); 2102 } 2103 2104 /** 2105 * Generates avatar filename from the database entry 2106 */ 2107 function get_avatar_filename($avatar_entry) 2108 { 2109 global $config; 2110 2111 2112 if ($avatar_entry[0] === 'g') 2113 { 2114 $avatar_group = true; 2115 $avatar_entry = substr($avatar_entry, 1); 2116 } 2117 else 2118 { 2119 $avatar_group = false; 2120 } 2121 $ext = substr(strrchr($avatar_entry, '.'), 1); 2122 $avatar_entry = intval($avatar_entry); 2123 return $config['avatar_salt'] . '_' . (($avatar_group) ? 'g' : '') . $avatar_entry . '.' . $ext; 2124 } 2125 2126 /** 2127 * Avatar Gallery 2128 */ 2129 function avatar_gallery($category, $avatar_select, $items_per_column, $block_var = 'avatar_row') 2130 { 2131 global $user, $cache, $template; 2132 global $config, $phpbb_root_path; 2133 2134 $avatar_list = array(); 2135 2136 $path = $phpbb_root_path . $config['avatar_gallery_path']; 2137 2138 if (!file_exists($path) || !is_dir($path)) 2139 { 2140 $avatar_list = array($user->lang['NO_AVATAR_CATEGORY'] => array()); 2141 } 2142 else 2143 { 2144 // Collect images 2145 $dp = @opendir($path); 2146 2147 if (!$dp) 2148 { 2149 return array($user->lang['NO_AVATAR_CATEGORY'] => array()); 2150 } 2151 2152 while (($file = readdir($dp)) !== false) 2153 { 2154 if ($file[0] != '.' && preg_match('#^[^&"\'<>]+$#i', $file) && is_dir("$path/$file")) 2155 { 2156 $avatar_row_count = $avatar_col_count = 0; 2157 2158 if ($dp2 = @opendir("$path/$file")) 2159 { 2160 while (($sub_file = readdir($dp2)) !== false) 2161 { 2162 if (preg_match('#^[^&\'"<>]+\.(?:gif|png|jpe?g)$#i', $sub_file)) 2163 { 2164 $avatar_list[$file][$avatar_row_count][$avatar_col_count] = array( 2165 'file' => rawurlencode($file) . '/' . rawurlencode($sub_file), 2166 'filename' => rawurlencode($sub_file), 2167 'name' => ucfirst(str_replace('_', ' ', preg_replace('#^(.*)\..*$#', '\1', $sub_file))), 2168 ); 2169 $avatar_col_count++; 2170 if ($avatar_col_count == $items_per_column) 2171 { 2172 $avatar_row_count++; 2173 $avatar_col_count = 0; 2174 } 2175 } 2176 } 2177 closedir($dp2); 2178 } 2179 } 2180 } 2181 closedir($dp); 2182 } 2183 2184 if (!sizeof($avatar_list)) 2185 { 2186 $avatar_list = array($user->lang['NO_AVATAR_CATEGORY'] => array()); 2187 } 2188 2189 @ksort($avatar_list); 2190 2191 $category = (!$category) ? key($avatar_list) : $category; 2192 $avatar_categories = array_keys($avatar_list); 2193 2194 $s_category_options = ''; 2195 foreach ($avatar_categories as $cat) 2196 { 2197 $s_category_options .= '<option value="' . $cat . '"' . (($cat == $category) ? ' selected="selected"' : '') . '>' . $cat . '</option>'; 2198 } 2199 2200 $template->assign_vars(array( 2201 'S_AVATARS_ENABLED' => true, 2202 'S_IN_AVATAR_GALLERY' => true, 2203 'S_CAT_OPTIONS' => $s_category_options) 2204 ); 2205 2206 $avatar_list = (isset($avatar_list[$category])) ? $avatar_list[$category] : array(); 2207 2208 foreach ($avatar_list as $avatar_row_ary) 2209 { 2210 $template->assign_block_vars($block_var, array()); 2211 2212 foreach ($avatar_row_ary as $avatar_col_ary) 2213 { 2214 $template->assign_block_vars($block_var . '.avatar_column', array( 2215 'AVATAR_IMAGE' => $phpbb_root_path . $config['avatar_gallery_path'] . '/' . $avatar_col_ary['file'], 2216 'AVATAR_NAME' => $avatar_col_ary['name'], 2217 'AVATAR_FILE' => $avatar_col_ary['filename']) 2218 ); 2219 2220 $template->assign_block_vars($block_var . '.avatar_option_column', array( 2221 'AVATAR_IMAGE' => $phpbb_root_path . $config['avatar_gallery_path'] . '/' . $avatar_col_ary['file'], 2222 'S_OPTIONS_AVATAR' => $avatar_col_ary['filename']) 2223 ); 2224 } 2225 } 2226 2227 return $avatar_list; 2228 } 2229 2230 2231 /** 2232 * Tries to (re-)establish avatar dimensions 2233 */ 2234 function avatar_get_dimensions($avatar, $avatar_type, &$error, $current_x = 0, $current_y = 0) 2235 { 2236 global $config, $phpbb_root_path, $user; 2237 2238 switch ($avatar_type) 2239 { 2240 case AVATAR_REMOTE : 2241 break; 2242 2243 case AVATAR_UPLOAD : 2244 $avatar = $phpbb_root_path . $config['avatar_path'] . '/' . get_avatar_filename($avatar); 2245 break; 2246 2247 case AVATAR_GALLERY : 2248 $avatar = $phpbb_root_path . $config['avatar_gallery_path'] . '/' . $avatar ; 2249 break; 2250 } 2251 2252 // Make sure getimagesize works... 2253 if (($image_data = @getimagesize($avatar)) === false) 2254 { 2255 $error[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; 2256 return false; 2257 } 2258 2259 if ($image_data[0] < 2 || $image_data[1] < 2) 2260 { 2261 $error[] = $user->lang['AVATAR_NO_SIZE']; 2262 return false; 2263 } 2264 2265 // try to maintain ratio 2266 if (!(empty($current_x) && empty($current_y))) 2267 { 2268 if ($current_x != 0) 2269 { 2270 $image_data[1] = (int) floor(($current_x / $image_data[0]) * $image_data[1]); 2271 $image_data[1] = min($config['avatar_max_height'], $image_data[1]); 2272 $image_data[1] = max($config['avatar_min_height'], $image_data[1]); 2273 } 2274 if ($current_y != 0) 2275 { 2276 $image_data[0] = (int) floor(($current_y / $image_data[1]) * $image_data[0]); 2277 $image_data[0] = min($config['avatar_max_width'], $image_data[1]); 2278 $image_data[0] = max($config['avatar_min_width'], $image_data[1]); 2279 } 2280 } 2281 return array($image_data[0], $image_data[1]); 2282 } 2283 2284 /** 2285 * Uploading/Changing user avatar 2286 */ 2287 function avatar_process_user(&$error, $custom_userdata = false, $can_upload = null) 2288 { 2289 global $config, $phpbb_root_path, $auth, $user, $db; 2290 2291 $data = array( 2292 'uploadurl' => request_var('uploadurl', ''), 2293 'remotelink' => request_var('remotelink', ''), 2294 'width' => request_var('width', 0), 2295 'height' => request_var('height', 0), 2296 ); 2297 2298 $error = validate_data($data, array( 2299 'uploadurl' => array('string', true, 5, 255), 2300 'remotelink' => array('string', true, 5, 255), 2301 'width' => array('string', true, 1, 3), 2302 'height' => array('string', true, 1, 3), 2303 )); 2304 2305 if (sizeof($error)) 2306 { 2307 return false; 2308 } 2309 2310 $sql_ary = array(); 2311 2312 if ($custom_userdata === false) 2313 { 2314 $userdata = &$user->data; 2315 } 2316 else 2317 { 2318 $userdata = &$custom_userdata; 2319 } 2320 2321 $data['user_id'] = $userdata['user_id']; 2322 $change_avatar = ($custom_userdata === false) ? $auth->acl_get('u_chgavatar') : true; 2323 $avatar_select = basename(request_var('avatar_select', '')); 2324 2325 // Can we upload? 2326 if (is_null($can_upload)) 2327 { 2328 $can_upload = ($config['allow_avatar_upload'] && file_exists($phpbb_root_path . $config['avatar_path']) && phpbb_is_writable($phpbb_root_path . $config['avatar_path']) && $change_avatar && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false; 2329 } 2330 2331 if ((!empty($_FILES['uploadfile']['name']) || $data['uploadurl']) && $can_upload) 2332 { 2333 list($sql_ary['user_avatar_type'], $sql_ary['user_avatar'], $sql_ary['user_avatar_width'], $sql_ary['user_avatar_height']) = avatar_upload($data, $error); 2334 } 2335 else if ($data['remotelink'] && $change_avatar && $config['allow_avatar_remote']) 2336 { 2337 list($sql_ary['user_avatar_type'], $sql_ary['user_avatar'], $sql_ary['user_avatar_width'], $sql_ary['user_avatar_height']) = avatar_remote($data, $error); 2338 } 2339 else if ($avatar_select && $change_avatar && $config['allow_avatar_local']) 2340 { 2341 $category = basename(request_var('category', '')); 2342 2343 $sql_ary['user_avatar_type'] = AVATAR_GALLERY; 2344 $sql_ary['user_avatar'] = $avatar_select; 2345 2346 // check avatar gallery 2347 if (!is_dir($phpbb_root_path . $config['avatar_gallery_path'] . '/' . $category)) 2348 { 2349 $sql_ary['user_avatar'] = ''; 2350 $sql_ary['user_avatar_type'] = $sql_ary['user_avatar_width'] = $sql_ary['user_avatar_height'] = 0; 2351 } 2352 else 2353 { 2354 list($sql_ary['user_avatar_width'], $sql_ary['user_avatar_height']) = getimagesize($phpbb_root_path . $config['avatar_gallery_path'] . '/' . $category . '/' . urldecode($sql_ary['user_avatar'])); 2355 $sql_ary['user_avatar'] = $category . '/' . $sql_ary['user_avatar']; 2356 } 2357 } 2358 else if (isset($_POST['delete']) && $change_avatar) 2359 { 2360 $sql_ary['user_avatar'] = ''; 2361 $sql_ary['user_avatar_type'] = $sql_ary['user_avatar_width'] = $sql_ary['user_avatar_height'] = 0; 2362 } 2363 else if (!empty($userdata['user_avatar'])) 2364 { 2365 // Only update the dimensions 2366 2367 if (empty($data['width']) || empty($data['height'])) 2368 { 2369 if ($dims = avatar_get_dimensions($userdata['user_avatar'], $userdata['user_avatar_type'], $error, $data['width'], $data['height'])) 2370 { 2371 list($guessed_x, $guessed_y) = $dims; 2372 if (empty($data['width'])) 2373 { 2374 $data['width'] = $guessed_x; 2375 } 2376 if (empty($data['height'])) 2377 { 2378 $data['height'] = $guessed_y; 2379 } 2380 } 2381 } 2382 if (($config['avatar_max_width'] || $config['avatar_max_height']) && 2383 (($data['width'] != $userdata['user_avatar_width']) || $data['height'] != $userdata['user_avatar_height'])) 2384 { 2385 if ($data['width'] > $config['avatar_max_width'] || $data['height'] > $config['avatar_max_height']) 2386 { 2387 $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); 2388 } 2389 } 2390 2391 if (!sizeof($error)) 2392 { 2393 if ($config['avatar_min_width'] || $config['avatar_min_height']) 2394 { 2395 if ($data['width'] < $config['avatar_min_width'] || $data['height'] < $config['avatar_min_height']) 2396 { 2397 $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); 2398 } 2399 } 2400 } 2401 2402 if (!sizeof($error)) 2403 { 2404 $sql_ary['user_avatar_width'] = $data['width']; 2405 $sql_ary['user_avatar_height'] = $data['height']; 2406 } 2407 } 2408 2409 if (!sizeof($error)) 2410 { 2411 // Do we actually have any data to update? 2412 if (sizeof($sql_ary)) 2413 { 2414 $ext_new = $ext_old = ''; 2415 if (isset($sql_ary['user_avatar'])) 2416 { 2417 $userdata = ($custom_userdata === false) ? $user->data : $custom_userdata; 2418 $ext_new = (empty($sql_ary['user_avatar'])) ? '' : substr(strrchr($sql_ary['user_avatar'], '.'), 1); 2419 $ext_old = (empty($userdata['user_avatar'])) ? '' : substr(strrchr($userdata['user_avatar'], '.'), 1); 2420 2421 if ($userdata['user_avatar_type'] == AVATAR_UPLOAD) 2422 { 2423 // Delete old avatar if present 2424 if ((!empty($userdata['user_avatar']) && empty($sql_ary['user_avatar'])) 2425 || ( !empty($userdata['user_avatar']) && !empty($sql_ary['user_avatar']) && $ext_new !== $ext_old)) 2426 { 2427 avatar_delete('user', $userdata); 2428 } 2429 } 2430 } 2431 2432 $sql = 'UPDATE ' . USERS_TABLE . ' 2433 SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' 2434 WHERE user_id = ' . (($custom_userdata === false) ? $user->data['user_id'] : $custom_userdata['user_id']); 2435 $db->sql_query($sql); 2436 2437 } 2438 } 2439 2440 return (sizeof($error)) ? false : true; 2441 } 2442 2443 // 2444 // Usergroup functions 2445 // 2446 2447 /** 2448 * Add or edit a group. If we're editing a group we only update user 2449 * parameters such as rank, etc. if they are changed 2450 */ 2451 function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow_desc_bbcode = false, $allow_desc_urls = false, $allow_desc_smilies = false) 2452 { 2453 global $phpbb_root_path, $config, $db, $user, $file_upload; 2454 2455 $error = array(); 2456 2457 // Attributes which also affect the users table 2458 $user_attribute_ary = array('group_colour', 'group_rank', 'group_avatar', 'group_avatar_type', 'group_avatar_width', 'group_avatar_height'); 2459 2460 // Check data. Limit group name length. 2461 if (!utf8_strlen($name) || utf8_strlen($name) > 60) 2462 { 2463 $error[] = (!utf8_strlen($name)) ? $user->lang['GROUP_ERR_USERNAME'] : $user->lang['GROUP_ERR_USER_LONG']; 2464 } 2465 2466 $err = group_validate_groupname($group_id, $name); 2467 if (!empty($err)) 2468 { 2469 $error[] = $user->lang[$err]; 2470 } 2471 2472 if (!in_array($type, array(GROUP_OPEN, GROUP_CLOSED, GROUP_HIDDEN, GROUP_SPECIAL, GROUP_FREE))) 2473 { 2474 $error[] = $user->lang['GROUP_ERR_TYPE']; 2475 } 2476 2477 if (!sizeof($error)) 2478 { 2479 $user_ary = array(); 2480 $sql_ary = array( 2481 'group_name' => (string) $name, 2482 'group_desc' => (string) $desc, 2483 'group_desc_uid' => '', 2484 'group_desc_bitfield' => '', 2485 'group_type' => (int) $type, 2486 ); 2487 2488 // Parse description 2489 if ($desc) 2490 { 2491 generate_text_for_storage($sql_ary['group_desc'], $sql_ary['group_desc_uid'], $sql_ary['group_desc_bitfield'], $sql_ary['group_desc_options'], $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies); 2492 } 2493 2494 if (sizeof($group_attributes)) 2495 { 2496 // Merge them with $sql_ary to properly update the group 2497 $sql_ary = array_merge($sql_ary, $group_attributes); 2498 } 2499 2500 // Setting the log message before we set the group id (if group gets added) 2501 $log = ($group_id) ? 'LOG_GROUP_UPDATED' : 'LOG_GROUP_CREATED'; 2502 2503 $query = ''; 2504 2505 if ($group_id) 2506 { 2507 $sql = 'SELECT user_id 2508 FROM ' . USERS_TABLE . ' 2509 WHERE group_id = ' . $group_id; 2510 $result = $db->sql_query($sql); 2511 2512 while ($row = $db->sql_fetchrow($result)) 2513 { 2514 $user_ary[] = $row['user_id']; 2515 } 2516 $db->sql_freeresult($result); 2517 2518 if (isset($sql_ary['group_avatar']) && !$sql_ary['group_avatar']) 2519 { 2520 remove_default_avatar($group_id, $user_ary); 2521 } 2522 2523 if (isset($sql_ary['group_rank']) && !$sql_ary['group_rank']) 2524 { 2525 remove_default_rank($group_id, $user_ary); 2526 } 2527 2528 $sql = 'UPDATE ' . GROUPS_TABLE . ' 2529 SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " 2530 WHERE group_id = $group_id"; 2531 $db->sql_query($sql); 2532 2533 // Since we may update the name too, we need to do this on other tables too... 2534 $sql = 'UPDATE ' . MODERATOR_CACHE_TABLE . " 2535 SET group_name = '" . $db->sql_escape($sql_ary['group_name']) . "' 2536 WHERE group_id = $group_id"; 2537 $db->sql_query($sql); 2538 2539 // One special case is the group skip auth setting. If this was changed we need to purge permissions for this group 2540 if (isset($group_attributes['group_skip_auth'])) 2541 { 2542 // Get users within this group... 2543 $sql = 'SELECT user_id 2544 FROM ' . USER_GROUP_TABLE . ' 2545 WHERE group_id = ' . $group_id . ' 2546 AND user_pending = 0'; 2547 $result = $db->sql_query($sql); 2548 2549 $user_id_ary = array(); 2550 while ($row = $db->sql_fetchrow($result)) 2551 { 2552 $user_id_ary[] = $row['user_id']; 2553 } 2554 $db->sql_freeresult($result); 2555 2556 if (!empty($user_id_ary)) 2557 { 2558 global $auth; 2559 2560 // Clear permissions cache of relevant users 2561 $auth->acl_clear_prefetch($user_id_ary); 2562 } 2563 } 2564 } 2565 else 2566 { 2567 $sql = 'INSERT INTO ' . GROUPS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); 2568 $db->sql_query($sql); 2569 } 2570 2571 if (!$group_id) 2572 { 2573 $group_id = $db->sql_nextid(); 2574 2575 if (isset($sql_ary['group_avatar_type']) && $sql_ary['group_avatar_type'] == AVATAR_UPLOAD) 2576 { 2577 group_correct_avatar($group_id, $sql_ary['group_avatar']); 2578 } 2579 } 2580 2581 // Set user attributes 2582 $sql_ary = array(); 2583 if (sizeof($group_attributes)) 2584 { 2585 // Go through the user attributes array, check if a group attribute matches it and then set it. ;) 2586 foreach ($user_attribute_ary as $attribute) 2587 { 2588 if (!isset($group_attributes[$attribute])) 2589 { 2590 continue; 2591 } 2592 2593 // If we are about to set an avatar, we will not overwrite user avatars if no group avatar is set... 2594 if (strpos($attribute, 'group_avatar') === 0 && !$group_attributes[$attribute]) 2595 { 2596 continue; 2597 } 2598 2599 $sql_ary[$attribute] = $group_attributes[$attribute]; 2600 } 2601 } 2602 2603 if (sizeof($sql_ary) && sizeof($user_ary)) 2604 { 2605 group_set_user_default($group_id, $user_ary, $sql_ary); 2606 } 2607 2608 $name = ($type == GROUP_SPECIAL) ? $user->lang['G_' . $name] : $name; 2609 add_log('admin', $log, $name); 2610 2611 group_update_listings($group_id); 2612 } 2613 2614 return (sizeof($error)) ? $error : false; 2615 } 2616 2617 2618 /** 2619 * Changes a group avatar's filename to conform to the naming scheme 2620 */ 2621 function group_correct_avatar($group_id, $old_entry) 2622 { 2623 global $config, $db, $phpbb_root_path; 2624 2625 $group_id = (int)$group_id; 2626 $ext = substr(strrchr($old_entry, '.'), 1); 2627 $old_filename = get_avatar_filename($old_entry); 2628 $new_filename = $config['avatar_salt'] . "_g$group_id.$ext"; 2629 $new_entry = 'g' . $group_id . '_' . substr(time(), -5) . ".$ext"; 2630 2631 $avatar_path = $phpbb_root_path . $config['avatar_path']; 2632 if (@rename($avatar_path . '/'. $old_filename, $avatar_path . '/' . $new_filename)) 2633 { 2634 $sql = 'UPDATE ' . GROUPS_TABLE . ' 2635 SET group_avatar = \'' . $db->sql_escape($new_entry) . "' 2636 WHERE group_id = $group_id"; 2637 $db->sql_query($sql); 2638 } 2639 } 2640 2641 2642 /** 2643 * Remove avatar also for users not having the group as default 2644 */ 2645 function avatar_remove_db($avatar_name) 2646 { 2647 global $config, $db; 2648 2649 $sql = 'UPDATE ' . USERS_TABLE . " 2650 SET user_avatar = '', 2651 user_avatar_type = 0 2652 WHERE user_avatar = '" . $db->sql_escape($avatar_name) . '\''; 2653 $db->sql_query($sql); 2654 } 2655 2656 2657 /** 2658 * Group Delete 2659 */ 2660 function group_delete($group_id, $group_name = false) 2661 { 2662 global $db, $phpbb_root_path, $phpEx; 2663 2664 if (!$group_name) 2665 { 2666 $group_name = get_group_name($group_id); 2667 } 2668 2669 $start = 0; 2670 2671 do 2672 { 2673 $user_id_ary = $username_ary = array(); 2674 2675 // Batch query for group members, call group_user_del 2676 $sql = 'SELECT u.user_id, u.username 2677 FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . " u 2678 WHERE ug.group_id = $group_id 2679 AND u.user_id = ug.user_id"; 2680 $result = $db->sql_query_limit($sql, 200, $start); 2681 2682 if ($row = $db->sql_fetchrow($result)) 2683 { 2684 do 2685 { 2686 $user_id_ary[] = $row['user_id']; 2687 $username_ary[] = $row['username']; 2688 2689 $start++; 2690 } 2691 while ($row = $db->sql_fetchrow($result)); 2692 2693 group_user_del($group_id, $user_id_ary, $username_ary, $group_name); 2694 } 2695 else 2696 { 2697 $start = 0; 2698 } 2699 $db->sql_freeresult($result); 2700 } 2701 while ($start); 2702 2703 // Delete group 2704 $sql = 'DELETE FROM ' . GROUPS_TABLE . " 2705 WHERE group_id = $group_id"; 2706 $db->sql_query($sql); 2707 2708 // Delete auth entries from the groups table 2709 $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . " 2710 WHERE group_id = $group_id"; 2711 $db->sql_query($sql); 2712 2713 // Re-cache moderators 2714 if (!function_exists('cache_moderators')) 2715 { 2716 include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); 2717 } 2718 2719 cache_moderators(); 2720 2721 add_log('admin', 'LOG_GROUP_DELETE', $group_name); 2722 2723 // Return false - no error 2724 return false; 2725 } 2726 2727 /** 2728 * Add user(s) to group 2729 * 2730 * @return mixed false if no errors occurred, else the user lang string for the relevant error, for example 'NO_USER' 2731 */ 2732 function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $default = false, $leader = 0, $pending = 0, $group_attributes = false) 2733 { 2734 global $db, $auth; 2735 2736 // We need both username and user_id info 2737 $result = user_get_id_name($user_id_ary, $username_ary); 2738 2739 if (!sizeof($user_id_ary) || $result !== false) 2740 { 2741 return 'NO_USER'; 2742 } 2743 2744 // Remove users who are already members of this group 2745 $sql = 'SELECT user_id, group_leader 2746 FROM ' . USER_GROUP_TABLE . ' 2747 WHERE ' . $db->sql_in_set('user_id', $user_id_ary) . " 2748 AND group_id = $group_id"; 2749 $result = $db->sql_query($sql); 2750 2751 $add_id_ary = $update_id_ary = array(); 2752 while ($row = $db->sql_fetchrow($result)) 2753 { 2754 $add_id_ary[] = (int) $row['user_id']; 2755 2756 if ($leader && !$row['group_leader']) 2757 { 2758 $update_id_ary[] = (int) $row['user_id']; 2759 } 2760 } 2761 $db->sql_freeresult($result); 2762 2763 // Do all the users exist in this group? 2764 $add_id_ary = array_diff($user_id_ary, $add_id_ary); 2765 2766 // If we have no users 2767 if (!sizeof($add_id_ary) && !sizeof($update_id_ary)) 2768 { 2769 return 'GROUP_USERS_EXIST'; 2770 } 2771 2772 $db->sql_transaction('begin'); 2773 2774 // Insert the new users 2775 if (sizeof($add_id_ary)) 2776 { 2777 $sql_ary = array(); 2778 2779 foreach ($add_id_ary as $user_id) 2780 { 2781 $sql_ary[] = array( 2782 'user_id' => (int) $user_id, 2783 'group_id' => (int) $group_id, 2784 'group_leader' => (int) $leader, 2785 'user_pending' => (int) $pending, 2786 ); 2787 } 2788 2789 $db->sql_multi_insert(USER_GROUP_TABLE, $sql_ary); 2790 } 2791 2792 if (sizeof($update_id_ary)) 2793 { 2794 $sql = 'UPDATE ' . USER_GROUP_TABLE . ' 2795 SET group_leader = 1 2796 WHERE ' . $db->sql_in_set('user_id', $update_id_ary) . " 2797 AND group_id = $group_id"; 2798 $db->sql_query($sql); 2799 } 2800 2801 if ($default) 2802 { 2803 group_user_attributes('default', $group_id, $user_id_ary, false, $group_name, $group_attributes); 2804 } 2805 2806 $db->sql_transaction('commit'); 2807 2808 // Clear permissions cache of relevant users 2809 $auth->acl_clear_prefetch($user_id_ary); 2810 2811 if (!$group_name) 2812 { 2813 $group_name = get_group_name($group_id); 2814 } 2815 2816 $log = ($leader) ? 'LOG_MODS_ADDED' : (($pending) ? 'LOG_USERS_PENDING' : 'LOG_USERS_ADDED'); 2817 2818 add_log('admin', $log, $group_name, implode(', ', $username_ary)); 2819 2820 group_update_listings($group_id); 2821 2822 // Return false - no error 2823 return false; 2824 } 2825 2826 /** 2827 * Remove a user/s from a given group. When we remove users we update their 2828 * default group_id. We do this by examining which "special" groups they belong 2829 * to. The selection is made based on a reasonable priority system 2830 * 2831 * @return false if no errors occurred, else the user lang string for the relevant error, for example 'NO_USER' 2832 */ 2833 function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_name = false) 2834 { 2835 global $db, $auth, $config; 2836 2837 if ($config['coppa_enable']) 2838 { 2839 $group_order = array('ADMINISTRATORS', 'GLOBAL_MODERATORS', 'NEWLY_REGISTERED', 'REGISTERED_COPPA', 'REGISTERED', 'BOTS', 'GUESTS'); 2840 } 2841 else 2842 { 2843 $group_order = array('ADMINISTRATORS', 'GLOBAL_MODERATORS', 'NEWLY_REGISTERED', 'REGISTERED', 'BOTS', 'GUESTS'); 2844 } 2845 2846 // We need both username and user_id info 2847 $result = user_get_id_name($user_id_ary, $username_ary); 2848 2849 if (!sizeof($user_id_ary) || $result !== false) 2850 { 2851 return 'NO_USER'; 2852 } 2853 2854 $sql = 'SELECT * 2855 FROM ' . GROUPS_TABLE . ' 2856 WHERE ' . $db->sql_in_set('group_name', $group_order); 2857 $result = $db->sql_query($sql); 2858 2859 $group_order_id = $special_group_data = array(); 2860 while ($row = $db->sql_fetchrow($result)) 2861 { 2862 $group_order_id[$row['group_name']] = $row['group_id']; 2863 2864 $special_group_data[$row['group_id']] = array( 2865 'group_colour' => $row['group_colour'], 2866 'group_rank' => $row['group_rank'], 2867 ); 2868 2869 // Only set the group avatar if one is defined... 2870 if ($row['group_avatar']) 2871 { 2872 $special_group_data[$row['group_id']] = array_merge($special_group_data[$row['group_id']], array( 2873 'group_avatar' => $row['group_avatar'], 2874 'group_avatar_type' => $row['group_avatar_type'], 2875 'group_avatar_width' => $row['group_avatar_width'], 2876 'group_avatar_height' => $row['group_avatar_height']) 2877 ); 2878 } 2879 } 2880 $db->sql_freeresult($result); 2881 2882 // Get users default groups - we only need to reset default group membership if the group from which the user gets removed is set as default 2883 $sql = 'SELECT user_id, group_id 2884 FROM ' . USERS_TABLE . ' 2885 WHERE ' . $db->sql_in_set('user_id', $user_id_ary); 2886 $result = $db->sql_query($sql); 2887 2888 $default_groups = array(); 2889 while ($row = $db->sql_fetchrow($result)) 2890 { 2891 $default_groups[$row['user_id']] = $row['group_id']; 2892 } 2893 $db->sql_freeresult($result); 2894 2895 // What special group memberships exist for these users? 2896 $sql = 'SELECT g.group_id, g.group_name, ug.user_id 2897 FROM ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g 2898 WHERE ' . $db->sql_in_set('ug.user_id', $user_id_ary) . " 2899 AND g.group_id = ug.group_id 2900 AND g.group_id <> $group_id 2901 AND g.group_type = " . GROUP_SPECIAL . ' 2902 ORDER BY ug.user_id, g.group_id'; 2903 $result = $db->sql_query($sql); 2904 2905 $temp_ary = array(); 2906 while ($row = $db->sql_fetchrow($result)) 2907 { 2908 if ($default_groups[$row['user_id']] == $group_id && (!isset($temp_ary[$row['user_id']]) || $group_order_id[$row['group_name']] < $temp_ary[$row['user_id']])) 2909 { 2910 $temp_ary[$row['user_id']] = $row['group_id']; 2911 } 2912 } 2913 $db->sql_freeresult($result); 2914 2915 // sql_where_ary holds the new default groups and their users 2916 $sql_where_ary = array(); 2917 foreach ($temp_ary as $uid => $gid) 2918 { 2919 $sql_where_ary[$gid][] = $uid; 2920 } 2921 unset($temp_ary); 2922 2923 foreach ($special_group_data as $gid => $default_data_ary) 2924 { 2925 if (isset($sql_where_ary[$gid]) && sizeof($sql_where_ary[$gid])) 2926 { 2927 remove_default_rank($group_id, $sql_where_ary[$gid]); 2928 remove_default_avatar($group_id, $sql_where_ary[$gid]); 2929 group_set_user_default($gid, $sql_where_ary[$gid], $default_data_ary); 2930 } 2931 } 2932 unset($special_group_data); 2933 2934 $sql = 'DELETE FROM ' . USER_GROUP_TABLE . " 2935 WHERE group_id = $group_id 2936 AND " . $db->sql_in_set('user_id', $user_id_ary); 2937 $db->sql_query($sql); 2938 2939 // Clear permissions cache of relevant users 2940 $auth->acl_clear_prefetch($user_id_ary); 2941 2942 if (!$group_name) 2943 { 2944 $group_name = get_group_name($group_id); 2945 } 2946 2947 $log = 'LOG_GROUP_REMOVE'; 2948 2949 if ($group_name) 2950 { 2951 add_log('admin', $log, $group_name, implode(', ', $username_ary)); 2952 } 2953 2954 group_update_listings($group_id); 2955 2956 // Return false - no error 2957 return false; 2958 } 2959 2960 2961 /** 2962 * Removes the group avatar of the default group from the users in user_ids who have that group as default. 2963 */ 2964 function remove_default_avatar($group_id, $user_ids) 2965 { 2966 global $db; 2967 2968 if (!is_array($user_ids)) 2969 { 2970 $user_ids = array($user_ids); 2971 } 2972 if (empty($user_ids)) 2973 { 2974 return false; 2975 } 2976 2977 $user_ids = array_map('intval', $user_ids); 2978 2979 $sql = 'SELECT * 2980 FROM ' . GROUPS_TABLE . ' 2981 WHERE group_id = ' . (int)$group_id; 2982 $result = $db->sql_query($sql); 2983 if (!$row = $db->sql_fetchrow($result)) 2984 { 2985 $db->sql_freeresult($result); 2986 return false; 2987 } 2988 $db->sql_freeresult($result); 2989 2990 $sql = 'UPDATE ' . USERS_TABLE . " 2991 SET user_avatar = '', 2992 user_avatar_type = 0, 2993 user_avatar_width = 0, 2994 user_avatar_height = 0 2995 WHERE group_id = " . (int) $group_id . " 2996 AND user_avatar = '" . $db->sql_escape($row['group_avatar']) . "' 2997 AND " . $db->sql_in_set('user_id', $user_ids); 2998 2999 $db->sql_query($sql); 3000 } 3001 3002 /** 3003 * Removes the group rank of the default group from the users in user_ids who have that group as default. 3004 */ 3005 function remove_default_rank($group_id, $user_ids) 3006 { 3007 global $db; 3008 3009 if (!is_array($user_ids)) 3010 { 3011 $user_ids = array($user_ids); 3012 } 3013 if (empty($user_ids)) 3014 { 3015 return false; 3016 } 3017 3018 $user_ids = array_map('intval', $user_ids); 3019 3020 $sql = 'SELECT * 3021 FROM ' . GROUPS_TABLE . ' 3022 WHERE group_id = ' . (int)$group_id; 3023 $result = $db->sql_query($sql); 3024 if (!$row = $db->sql_fetchrow($result)) 3025 { 3026 $db->sql_freeresult($result); 3027 return false; 3028 } 3029 $db->sql_freeresult($result); 3030 3031 $sql = 'UPDATE ' . USERS_TABLE . ' 3032 SET user_rank = 0 3033 WHERE group_id = ' . (int)$group_id . ' 3034 AND user_rank <> 0 3035 AND user_rank = ' . (int)$row['group_rank'] . ' 3036 AND ' . $db->sql_in_set('user_id', $user_ids); 3037 $db->sql_query($sql); 3038 } 3039 3040 /** 3041 * This is used to promote (to leader), demote or set as default a member/s 3042 */ 3043 function group_user_attributes($action, $group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $group_attributes = false) 3044 { 3045 global $db, $auth, $phpbb_root_path, $phpEx, $config; 3046 3047 // We need both username and user_id info 3048 $result = user_get_id_name($user_id_ary, $username_ary); 3049 3050 if (!sizeof($user_id_ary) || $result !== false) 3051 { 3052 return 'NO_USERS'; 3053 } 3054 3055 if (!$group_name) 3056 { 3057 $group_name = get_group_name($group_id); 3058 } 3059 3060 switch ($action) 3061 { 3062 case 'demote': 3063 case 'promote': 3064 3065 $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . " 3066 WHERE group_id = $group_id 3067 AND user_pending = 1 3068 AND " . $db->sql_in_set('user_id', $user_id_ary); 3069 $result = $db->sql_query_limit($sql, 1); 3070 $not_empty = ($db->sql_fetchrow($result)); 3071 $db->sql_freeresult($result); 3072 if ($not_empty) 3073 { 3074 return 'NO_VALID_USERS'; 3075 } 3076 3077 $sql = 'UPDATE ' . USER_GROUP_TABLE . ' 3078 SET group_leader = ' . (($action == 'promote') ? 1 : 0) . " 3079 WHERE group_id = $group_id 3080 AND user_pending = 0 3081 AND " . $db->sql_in_set('user_id', $user_id_ary); 3082 $db->sql_query($sql); 3083 3084 $log = ($action == 'promote') ? 'LOG_GROUP_PROMOTED' : 'LOG_GROUP_DEMOTED'; 3085 break; 3086 3087 case 'approve': 3088 // Make sure we only approve those which are pending ;) 3089 $sql = 'SELECT u.user_id, u.user_email, u.username, u.username_clean, u.user_notify_type, u.user_jabber, u.user_lang 3090 FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug 3091 WHERE ug.group_id = ' . $group_id . ' 3092 AND ug.user_pending = 1 3093 AND ug.user_id = u.user_id 3094 AND ' . $db->sql_in_set('ug.user_id', $user_id_ary); 3095 $result = $db->sql_query($sql); 3096 3097 $user_id_ary = $email_users = array(); 3098 while ($row = $db->sql_fetchrow($result)) 3099 { 3100 $user_id_ary[] = $row['user_id']; 3101 $email_users[] = $row; 3102 } 3103 $db->sql_freeresult($result); 3104 3105 if (!sizeof($user_id_ary)) 3106 { 3107 return false; 3108 } 3109 3110 $sql = 'UPDATE ' . USER_GROUP_TABLE . " 3111 SET user_pending = 0 3112 WHERE group_id = $group_id 3113 AND " . $db->sql_in_set('user_id', $user_id_ary); 3114 $db->sql_query($sql); 3115 3116 // Send approved email to users... 3117 include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); 3118 $messenger = new messenger(); 3119 3120 foreach ($email_users as $row) 3121 { 3122 $messenger->template('group_approved', $row['user_lang']); 3123 3124 $messenger->to($row['user_email'], $row['username']); 3125 $messenger->im($row['user_jabber'], $row['username']); 3126 3127 $messenger->assign_vars(array( 3128 'USERNAME' => htmlspecialchars_decode($row['username']), 3129 'GROUP_NAME' => htmlspecialchars_decode($group_name), 3130 'U_GROUP' => generate_board_url() . "/ucp.$phpEx?i=groups&mode=membership") 3131 ); 3132 3133 $messenger->send($row['user_notify_type']); 3134 } 3135 3136 $messenger->save_queue(); 3137 3138 $log = 'LOG_USERS_APPROVED'; 3139 break; 3140 3141 case 'default': 3142 // We only set default group for approved members of the group 3143 $sql = 'SELECT user_id 3144 FROM ' . USER_GROUP_TABLE . " 3145 WHERE group_id = $group_id 3146 AND user_pending = 0 3147 AND " . $db->sql_in_set('user_id', $user_id_ary); 3148 $result = $db->sql_query($sql); 3149 3150 $user_id_ary = $username_ary = array(); 3151 while ($row = $db->sql_fetchrow($result)) 3152 { 3153 $user_id_ary[] = $row['user_id']; 3154 } 3155 $db->sql_freeresult($result); 3156 3157 $result = user_get_id_name($user_id_ary, $username_ary); 3158 if (!sizeof($user_id_ary) || $result !== false) 3159 { 3160 return 'NO_USERS'; 3161 } 3162 3163 $sql = 'SELECT user_id, group_id FROM ' . USERS_TABLE . ' 3164 WHERE ' . $db->sql_in_set('user_id', $user_id_ary, false, true); 3165 $result = $db->sql_query($sql); 3166 3167 $groups = array(); 3168 while ($row = $db->sql_fetchrow($result)) 3169 { 3170 if (!isset($groups[$row['group_id']])) 3171 { 3172 $groups[$row['group_id']] = array(); 3173 } 3174 $groups[$row['group_id']][] = $row['user_id']; 3175 } 3176 $db->sql_freeresult($result); 3177 3178 foreach ($groups as $gid => $uids) 3179 { 3180 remove_default_rank($gid, $uids); 3181 remove_default_avatar($gid, $uids); 3182 } 3183 group_set_user_default($group_id, $user_id_ary, $group_attributes); 3184 $log = 'LOG_GROUP_DEFAULTS'; 3185 break; 3186 } 3187 3188 // Clear permissions cache of relevant users 3189 $auth->acl_clear_prefetch($user_id_ary); 3190 3191 add_log('admin', $log, $group_name, implode(', ', $username_ary)); 3192 3193 group_update_listings($group_id); 3194 3195 return false; 3196 } 3197 3198 /** 3199 * A small version of validate_username to check for a group name's existence. To be called directly. 3200 */ 3201 function group_validate_groupname($group_id, $group_name) 3202 { 3203 global $config, $db; 3204 3205 $group_name = utf8_clean_string($group_name); 3206 3207 if (!empty($group_id)) 3208 { 3209 $sql = 'SELECT group_name 3210 FROM ' . GROUPS_TABLE . ' 3211 WHERE group_id = ' . (int) $group_id; 3212 $result = $db->sql_query($sql); 3213 $row = $db->sql_fetchrow($result); 3214 $db->sql_freeresult($result); 3215 3216 if (!$row) 3217 { 3218 return false; 3219 } 3220 3221 $allowed_groupname = utf8_clean_string($row['group_name']); 3222 3223 if ($allowed_groupname == $group_name) 3224 { 3225 return false; 3226 } 3227 } 3228 3229 $sql = 'SELECT group_name 3230 FROM ' . GROUPS_TABLE . " 3231 WHERE LOWER(group_name) = '" . $db->sql_escape(utf8_strtolower($group_name)) . "'"; 3232 $result = $db->sql_query($sql); 3233 $row = $db->sql_fetchrow($result); 3234 $db->sql_freeresult($result); 3235 3236 if ($row) 3237 { 3238 return 'GROUP_NAME_TAKEN'; 3239 } 3240 3241 return false; 3242 } 3243 3244 /** 3245 * Set users default group 3246 * 3247 * @access private 3248 */ 3249 function group_set_user_default($group_id, $user_id_ary, $group_attributes = false, $update_listing = false) 3250 { 3251 global $cache, $db; 3252 3253 if (empty($user_id_ary)) 3254 { 3255 return; 3256 } 3257 3258 $attribute_ary = array( 3259 'group_colour' => 'string', 3260 'group_rank' => 'int', 3261 'group_avatar' => 'string', 3262 'group_avatar_type' => 'int', 3263 'group_avatar_width' => 'int', 3264 'group_avatar_height' => 'int', 3265 ); 3266 3267 $sql_ary = array( 3268 'group_id' => $group_id 3269 ); 3270 3271 // Were group attributes passed to the function? If not we need to obtain them 3272 if ($group_attributes === false) 3273 { 3274 $sql = 'SELECT ' . implode(', ', array_keys($attribute_ary)) . ' 3275 FROM ' . GROUPS_TABLE . " 3276 WHERE group_id = $group_id"; 3277 $result = $db->sql_query($sql); 3278 $group_attributes = $db->sql_fetchrow($result); 3279 $db->sql_freeresult($result); 3280 } 3281 3282 foreach ($attribute_ary as $attribute => $type) 3283 { 3284 if (isset($group_attributes[$attribute])) 3285 { 3286 // If we are about to set an avatar or rank, we will not overwrite with empty, unless we are not actually changing the default group 3287 if ((strpos($attribute, 'group_avatar') === 0 || strpos($attribute, 'group_rank') === 0) && !$group_attributes[$attribute]) 3288 { 3289 continue; 3290 } 3291 3292 settype($group_attributes[$attribute], $type); 3293 $sql_ary[str_replace('group_', 'user_', $attribute)] = $group_attributes[$attribute]; 3294 } 3295 } 3296 3297 // Before we update the user attributes, we will make a list of those having now the group avatar assigned 3298 if (isset($sql_ary['user_avatar'])) 3299 { 3300 // Ok, get the original avatar data from users having an uploaded one (we need to remove these from the filesystem) 3301 $sql = 'SELECT user_id, group_id, user_avatar 3302 FROM ' . USERS_TABLE . ' 3303 WHERE ' . $db->sql_in_set('user_id', $user_id_ary) . ' 3304 AND user_avatar_type = ' . AVATAR_UPLOAD; 3305 $result = $db->sql_query($sql); 3306 3307 while ($row = $db->sql_fetchrow($result)) 3308 { 3309 avatar_delete('user', $row); 3310 } 3311 $db->sql_freeresult($result); 3312 } 3313 else 3314 { 3315 unset($sql_ary['user_avatar_type']); 3316 unset($sql_ary['user_avatar_height']); 3317 unset($sql_ary['user_avatar_width']); 3318 } 3319 3320 $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' 3321 WHERE ' . $db->sql_in_set('user_id', $user_id_ary); 3322 $db->sql_query($sql); 3323 3324 if (isset($sql_ary['user_colour'])) 3325 { 3326 // Update any cached colour information for these users 3327 $sql = 'UPDATE ' . FORUMS_TABLE . " SET forum_last_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "' 3328 WHERE " . $db->sql_in_set('forum_last_poster_id', $user_id_ary); 3329 $db->sql_query($sql); 3330 3331 $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_first_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "' 3332 WHERE " . $db->sql_in_set('topic_poster', $user_id_ary); 3333 $db->sql_query($sql); 3334 3335 $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_last_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "' 3336 WHERE " . $db->sql_in_set('topic_last_poster_id', $user_id_ary); 3337 $db->sql_query($sql); 3338 3339 global $config; 3340 3341 if (in_array($config['newest_user_id'], $user_id_ary)) 3342 { 3343 set_config('newest_user_colour', $sql_ary['user_colour'], true); 3344 } 3345 } 3346 3347 if ($update_listing) 3348 { 3349 group_update_listings($group_id); 3350 } 3351 3352 // Because some tables/caches use usercolour-specific data we need to purge this here. 3353 $cache->destroy('sql', MODERATOR_CACHE_TABLE); 3354 } 3355 3356 /** 3357 * Get group name 3358 */ 3359 function get_group_name($group_id) 3360 { 3361 global $db, $user; 3362 3363 $sql = 'SELECT group_name, group_type 3364 FROM ' . GROUPS_TABLE . ' 3365 WHERE group_id = ' . (int) $group_id; 3366 $result = $db->sql_query($sql); 3367 $row = $db->sql_fetchrow($result); 3368 $db->sql_freeresult($result); 3369 3370 if (!$row || ($row['group_type'] == GROUP_SPECIAL && empty($user->lang))) 3371 { 3372 return ''; 3373 } 3374 3375 return ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; 3376 } 3377 3378 /** 3379 * Obtain either the members of a specified group, the groups the specified user is subscribed to 3380 * or checking if a specified user is in a specified group. This function does not return pending memberships. 3381 * 3382 * Note: Never use this more than once... first group your users/groups 3383 */ 3384 function group_memberships($group_id_ary = false, $user_id_ary = false, $return_bool = false) 3385 { 3386 global $db; 3387 3388 if (!$group_id_ary && !$user_id_ary) 3389 { 3390 return true; 3391 } 3392 3393 if ($user_id_ary) 3394 { 3395 $user_id_ary = (!is_array($user_id_ary)) ? array($user_id_ary) : $user_id_ary; 3396 } 3397 3398 if ($group_id_ary) 3399 { 3400 $group_id_ary = (!is_array($group_id_ary)) ? array($group_id_ary) : $group_id_ary; 3401 } 3402 3403 $sql = 'SELECT ug.*, u.username, u.username_clean, u.user_email 3404 FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u 3405 WHERE ug.user_id = u.user_id 3406 AND ug.user_pending = 0 AND '; 3407 3408 if ($group_id_ary) 3409 { 3410 $sql .= ' ' . $db->sql_in_set('ug.group_id', $group_id_ary); 3411 } 3412 3413 if ($user_id_ary) 3414 { 3415 $sql .= ($group_id_ary) ? ' AND ' : ' '; 3416 $sql .= $db->sql_in_set('ug.user_id', $user_id_ary); 3417 } 3418 3419 $result = ($return_bool) ? $db->sql_query_limit($sql, 1) : $db->sql_query($sql); 3420 3421 $row = $db->sql_fetchrow($result); 3422 3423 if ($return_bool) 3424 { 3425 $db->sql_freeresult($result); 3426 return ($row) ? true : false; 3427 } 3428 3429 if (!$row) 3430 { 3431 return false; 3432 } 3433 3434 $return = array(); 3435 3436 do 3437 { 3438 $return[] = $row; 3439 } 3440 while ($row = $db->sql_fetchrow($result)); 3441 3442 $db->sql_freeresult($result); 3443 3444 return $return; 3445 } 3446 3447 /** 3448 * Re-cache moderators and foes if group has a_ or m_ permissions 3449 */ 3450 function group_update_listings($group_id) 3451 { 3452 global $auth; 3453 3454 $hold_ary = $auth->acl_group_raw_data($group_id, array('a_', 'm_')); 3455 3456 if (!sizeof($hold_ary)) 3457 { 3458 return; 3459 } 3460 3461 $mod_permissions = $admin_permissions = false; 3462 3463 foreach ($hold_ary as $g_id => $forum_ary) 3464 { 3465 foreach ($forum_ary as $forum_id => $auth_ary) 3466 { 3467 foreach ($auth_ary as $auth_option => $setting) 3468 { 3469 if ($mod_permissions && $admin_permissions) 3470 { 3471 break 3; 3472 } 3473 3474 if ($setting != ACL_YES) 3475 { 3476 continue; 3477 } 3478 3479 if ($auth_option == 'm_') 3480 { 3481 $mod_permissions = true; 3482 } 3483 3484 if ($auth_option == 'a_') 3485 { 3486 $admin_permissions = true; 3487 } 3488 } 3489 } 3490 } 3491 3492 if ($mod_permissions) 3493 { 3494 if (!function_exists('cache_moderators')) 3495 { 3496 global $phpbb_root_path, $phpEx; 3497 include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); 3498 } 3499 cache_moderators(); 3500 } 3501 3502 if ($mod_permissions || $admin_permissions) 3503 { 3504 if (!function_exists('update_foes')) 3505 { 3506 global $phpbb_root_path, $phpEx; 3507 include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); 3508 } 3509 update_foes(array($group_id)); 3510 } 3511 } 3512 3513 3514 3515 /** 3516 * Funtion to make a user leave the NEWLY_REGISTERED system group. 3517 * @access public 3518 * @param $user_id The id of the user to remove from the group 3519 */ 3520 function remove_newly_registered($user_id, $user_data = false) 3521 { 3522 global $db; 3523 3524 if ($user_data === false) 3525 { 3526 $sql = 'SELECT * 3527 FROM ' . USERS_TABLE . ' 3528 WHERE user_id = ' . $user_id; 3529 $result = $db->sql_query($sql); 3530 $user_row = $db->sql_fetchrow($result); 3531 $db->sql_freeresult($result); 3532 3533 if (!$user_row) 3534 { 3535 return false; 3536 } 3537 else 3538 { 3539 $user_data = $user_row; 3540 } 3541 } 3542 3543 if (empty($user_data['user_new'])) 3544 { 3545 return false; 3546 } 3547 3548 $sql = 'SELECT group_id 3549 FROM ' . GROUPS_TABLE . " 3550 WHERE group_name = 'NEWLY_REGISTERED' 3551 AND group_type = " . GROUP_SPECIAL; 3552 $result = $db->sql_query($sql); 3553 $group_id = (int) $db->sql_fetchfield('group_id'); 3554 $db->sql_freeresult($result); 3555 3556 if (!$group_id) 3557 { 3558 return false; 3559 } 3560 3561 // We need to call group_user_del here, because this function makes sure everything is correctly changed. 3562 // A downside for a call within the session handler is that the language is not set up yet - so no log entry 3563 group_user_del($group_id, $user_id); 3564 3565 // Set user_new to 0 to let this not be triggered again 3566 $sql = 'UPDATE ' . USERS_TABLE . ' 3567 SET user_new = 0 3568 WHERE user_id = ' . $user_id; 3569 $db->sql_query($sql); 3570 3571 // The new users group was the users default group? 3572 if ($user_data['group_id'] == $group_id) 3573 { 3574 // Which group is now the users default one? 3575 $sql = 'SELECT group_id 3576 FROM ' . USERS_TABLE . ' 3577 WHERE user_id = ' . $user_id; 3578 $result = $db->sql_query($sql); 3579 $user_data['group_id'] = $db->sql_fetchfield('group_id'); 3580 $db->sql_freeresult($result); 3581 } 3582 3583 return $user_data['group_id']; 3584 } 3585 3586 /** 3587 * Gets user ids of currently banned registered users. 3588 * 3589 * @param array $user_ids Array of users' ids to check for banning, 3590 * leave empty to get complete list of banned ids 3591 * @return array Array of banned users' ids if any, empty array otherwise 3592 */ 3593 function phpbb_get_banned_user_ids($user_ids = array()) 3594 { 3595 global $db; 3596 3597 $sql_user_ids = (!empty($user_ids)) ? $db->sql_in_set('ban_userid', $user_ids) : 'ban_userid <> 0'; 3598 3599 // Get banned User ID's 3600 // Ignore stale bans which were not wiped yet 3601 $banned_ids_list = array(); 3602 $sql = 'SELECT ban_userid 3603 FROM ' . BANLIST_TABLE . " 3604 WHERE $sql_user_ids 3605 AND ban_exclude <> 1 3606 AND (ban_end > " . time() . ' 3607 OR ban_end = 0)'; 3608 $result = $db->sql_query($sql); 3609 while ($row = $db->sql_fetchrow($result)) 3610 { 3611 $user_id = (int) $row['ban_userid']; 3612 $banned_ids_list[$user_id] = $user_id; 3613 } 3614 $db->sql_freeresult($result); 3615 3616 return $banned_ids_list; 3617 } 3618 3619 ?>
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 |