1<?php 2/** 3 * MyBB 1.8 4 * Copyright 2014 MyBB Group, All Rights Reserved 5 * 6 * Website: http://www.mybb.com 7 * License: http://www.mybb.com/about/license 8 * 9 */ 10 11// Disallow direct access to this file for security reasons 12if(!defined("IN_MYBB")) 13{ 14 die("Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined."); 15} 16 17/** 18 * User handling class, provides common structure to handle user data. 19 * 20 */ 21class UserDataHandler extends DataHandler 22{ 23 /** 24 * The language file used in the data handler. 25 * 26 * @var string 27 */ 28 public $language_file = 'datahandler_user'; 29 30 /** 31 * The prefix for the language variables used in the data handler. 32 * 33 * @var string 34 */ 35 public $language_prefix = 'userdata'; 36 37 /** 38 * Array of data inserted in to a user. 39 * 40 * @var array 41 */ 42 public $user_insert_data = array(); 43 44 /** 45 * Array of data used to update a user. 46 * 47 * @var array 48 */ 49 public $user_update_data = array(); 50 51 /** 52 * User ID currently being manipulated by the datahandlers. 53 * 54 * @var int 55 */ 56 public $uid = 0; 57 58 /** 59 * Values to be returned after inserting/deleting an user. 60 * 61 * @var array 62 */ 63 public $return_values = array(); 64 65 /** 66 * @var array 67 */ 68 var $delete_uids = array(); 69 70 /** 71 * @var int 72 */ 73 var $deleted_users = 0; 74 75 /** 76 * Verifies if a username is valid or invalid. 77 * 78 * @return boolean True when valid, false when invalid. 79 */ 80 function verify_username() 81 { 82 global $mybb; 83 84 $username = &$this->data['username']; 85 require_once MYBB_ROOT.'inc/functions_user.php'; 86 87 // Fix bad characters 88 $username = trim_blank_chrs($username); 89 $username = str_replace(array(unichr(160), unichr(173), unichr(0xCA), dec_to_utf8(8238), dec_to_utf8(8237), dec_to_utf8(8203)), array(" ", "-", "", "", "", ""), $username); 90 91 // Remove multiple spaces from the username 92 $username = preg_replace("#\s{2,}#", " ", $username); 93 94 // Check if the username is not empty. 95 if($username == '') 96 { 97 $this->set_error('missing_username'); 98 return false; 99 } 100 101 // Check if the username belongs to the list of banned usernames. 102 if(is_banned_username($username, true)) 103 { 104 $this->set_error('banned_username'); 105 return false; 106 } 107 108 // Check for certain characters in username (<, >, &, commas and slashes) 109 if(strpos($username, "<") !== false || strpos($username, ">") !== false || strpos($username, "&") !== false || my_strpos($username, "\\") !== false || strpos($username, ";") !== false || strpos($username, ",") !== false || !validate_utf8_string($username, false, false)) 110 { 111 $this->set_error("bad_characters_username"); 112 return false; 113 } 114 115 // Check if the username is of the correct length. 116 if(($mybb->settings['maxnamelength'] != 0 && my_strlen($username) > $mybb->settings['maxnamelength']) || ($mybb->settings['minnamelength'] != 0 && my_strlen($username) < $mybb->settings['minnamelength'])) 117 { 118 $this->set_error('invalid_username_length', array($mybb->settings['minnamelength'], $mybb->settings['maxnamelength'])); 119 return false; 120 } 121 122 return true; 123 } 124 125 /** 126 * Verifies if a usertitle is valid or invalid. 127 * 128 * @return boolean True when valid, false when invalid. 129 */ 130 function verify_usertitle() 131 { 132 global $mybb; 133 134 $usertitle = &$this->data['usertitle']; 135 136 // Check if the usertitle is of the correct length. 137 if($mybb->settings['customtitlemaxlength'] != 0 && my_strlen($usertitle) > $mybb->settings['customtitlemaxlength']) 138 { 139 $this->set_error('invalid_usertitle_length', $mybb->settings['customtitlemaxlength']); 140 return false; 141 } 142 143 return true; 144 } 145 146 /** 147 * Verifies if a username is already in use or not. 148 * 149 * @return boolean False when the username is not in use, true when it is. 150 */ 151 function verify_username_exists() 152 { 153 $username = &$this->data['username']; 154 155 $user = get_user_by_username(trim($username)); 156 157 if(!empty($this->data['uid']) && !empty($user['uid']) && $user['uid'] == $this->data['uid']) 158 { 159 unset($user); 160 } 161 162 if(!empty($user['uid'])) 163 { 164 $this->set_error("username_exists", array($username)); 165 return true; 166 } 167 168 return false; 169 } 170 171 /** 172 * Verifies if a new password is valid or not. 173 * 174 * @return boolean True when valid, false when invalid. 175 */ 176 function verify_password() 177 { 178 global $mybb; 179 180 $user = &$this->data; 181 182 // Always check for the length of the password. 183 if(my_strlen($user['password']) < $mybb->settings['minpasswordlength'] || my_strlen($user['password']) > $mybb->settings['maxpasswordlength']) 184 { 185 $this->set_error('invalid_password_length', array($mybb->settings['minpasswordlength'], $mybb->settings['maxpasswordlength'])); 186 return false; 187 } 188 189 // Has the user tried to use their email address or username as a password? 190 if(!empty($user['email']) && !empty($user['username'])) 191 { 192 if($user['email'] === $user['password'] || $user['username'] === $user['password'] 193 || strpos($user['password'], $user['email']) !== false || strpos($user['password'], $user['username']) !== false 194 || strpos($user['email'], $user['password']) !== false || strpos($user['username'], $user['password']) !== false) 195 { 196 $this->set_error('bad_password_security'); 197 return false; 198 } 199 } 200 201 // See if the board has "require complex passwords" enabled. 202 if($mybb->settings['requirecomplexpasswords'] == 1) 203 { 204 // Complex passwords required, do some extra checks. 205 // First, see if there is one or more complex character(s) in the password. 206 if(!preg_match("/^.*(?=.{".$mybb->settings['minpasswordlength'].",})(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/", $user['password'])) 207 { 208 $this->set_error('no_complex_characters', array($mybb->settings['minpasswordlength'])); 209 return false; 210 } 211 } 212 213 // If we have a "password2" check if they both match 214 if(isset($user['password2']) && $user['password'] !== $user['password2']) 215 { 216 $this->set_error("passwords_dont_match"); 217 return false; 218 } 219 220 // Generate the user login key 221 $user['loginkey'] = generate_loginkey(); 222 223 // Combine the password and salt 224 $password_fields = create_password($user['password'], false, $user); 225 $user = array_merge($user, $password_fields); 226 227 return true; 228 } 229 230 /** 231 * Verifies usergroup selections and other group details. 232 * 233 * @return boolean True when valid, false when invalid. 234 */ 235 function verify_usergroup() 236 { 237 return true; 238 } 239 /** 240 * Verifies if an email address is valid or not. 241 * 242 * @return boolean True when valid, false when invalid. 243 */ 244 function verify_email() 245 { 246 global $mybb; 247 248 $user = &$this->data; 249 250 // Check if an email address has actually been entered. 251 if(trim_blank_chrs($user['email']) == '') 252 { 253 $this->set_error('missing_email'); 254 return false; 255 } 256 257 // Check if this is a proper email address. 258 if(!validate_email_format($user['email'])) 259 { 260 $this->set_error('invalid_email_format'); 261 return false; 262 } 263 264 // Check banned emails 265 if(is_banned_email($user['email'], true)) 266 { 267 $this->set_error('banned_email'); 268 return false; 269 } 270 271 // Check signed up emails 272 // Ignore the ACP because the Merge System sometimes produces users with duplicate email addresses (Not A Bug) 273 if($mybb->settings['allowmultipleemails'] == 0 && !defined("IN_ADMINCP")) 274 { 275 $uid = 0; 276 if(isset($user['uid'])) 277 { 278 $uid = $user['uid']; 279 } 280 if(email_already_in_use($user['email'], $uid)) 281 { 282 $this->set_error('email_already_in_use'); 283 return false; 284 } 285 } 286 287 // If we have an "email2", verify it matches the existing email 288 if(isset($user['email2']) && $user['email'] != $user['email2']) 289 { 290 $this->set_error("emails_dont_match"); 291 return false; 292 } 293 294 return true; 295 } 296 297 /** 298 * Verifies if a website is valid or not. 299 * 300 * @return boolean True when valid, false when invalid. 301 */ 302 function verify_website() 303 { 304 $website = &$this->data['website']; 305 306 if(!empty($website) && !my_validate_url($website)) 307 { 308 $website = 'http://'.$website; 309 } 310 311 if(!empty($website) && !my_validate_url($website)) 312 { 313 $this->set_error('invalid_website'); 314 return false; 315 } 316 317 return true; 318 } 319 320 /** 321 * Verifies if an ICQ number is valid or not. 322 * 323 * @return boolean True when valid, false when invalid. 324 */ 325 function verify_icq() 326 { 327 $icq = &$this->data['icq']; 328 329 if($icq != '' && !is_numeric($icq)) 330 { 331 $this->set_error("invalid_icq_number"); 332 return false; 333 } 334 $icq = (int)$icq; 335 return true; 336 } 337 338 /** 339 * Verifies if a birthday is valid or not. 340 * 341 * @return boolean True when valid, false when invalid. 342 */ 343 function verify_birthday() 344 { 345 global $mybb; 346 347 $user = &$this->data; 348 $birthday = &$user['birthday']; 349 350 if(!is_array($birthday)) 351 { 352 return true; 353 } 354 355 // Sanitize any input we have 356 $birthday['day'] = (int)$birthday['day']; 357 $birthday['month'] = (int)$birthday['month']; 358 $birthday['year'] = (int)$birthday['year']; 359 360 // Error if a day and month exists, and the birthday day and range is not in range 361 if($birthday['day'] != 0 || $birthday['month'] != 0) 362 { 363 if($birthday['day'] < 1 || $birthday['day'] > 31 || $birthday['month'] < 1 || $birthday['month'] > 12 || ($birthday['month'] == 2 && $birthday['day'] > 29)) 364 { 365 $this->set_error("invalid_birthday"); 366 return false; 367 } 368 } 369 370 // Check if the day actually exists. 371 $months = get_bdays($birthday['year']); 372 if($birthday['month'] != 0 && $birthday['day'] > $months[$birthday['month']-1]) 373 { 374 $this->set_error("invalid_birthday"); 375 return false; 376 } 377 378 // Error if a year exists and the year is out of range 379 if($birthday['year'] != 0 && ($birthday['year'] < (date("Y")-100)) || $birthday['year'] > date("Y")) 380 { 381 $this->set_error("invalid_birthday"); 382 return false; 383 } 384 elseif($birthday['year'] == date("Y")) 385 { 386 // Error if birth date is in future 387 if($birthday['month'] > date("m") || ($birthday['month'] == date("m") && $birthday['day'] > date("d"))) 388 { 389 $this->set_error("invalid_birthday"); 390 return false; 391 } 392 } 393 394 // Error if COPPA is on, and the user hasn't verified their age / under 13 395 if($mybb->settings['coppa'] == "enabled" && ($birthday['year'] == 0 || !$birthday['year'])) 396 { 397 $this->set_error("invalid_birthday_coppa"); 398 return false; 399 } 400 elseif(($mybb->settings['coppa'] == "deny" && $birthday['year'] > (date("Y")-13)) && !is_moderator()) 401 { 402 $this->set_error("invalid_birthday_coppa2"); 403 return false; 404 } 405 406 // Make the user's birthday field 407 if($birthday['year'] != 0) 408 { 409 // If the year is specified, put together a d-m-y string 410 $user['bday'] = $birthday['day']."-".$birthday['month']."-".$birthday['year']; 411 } 412 elseif($birthday['day'] && $birthday['month']) 413 { 414 // If only a day and month are specified, put together a d-m string 415 $user['bday'] = $birthday['day']."-".$birthday['month']."-"; 416 } 417 else 418 { 419 // No field is specified, so return an empty string for an unknown birthday 420 $user['bday'] = ''; 421 } 422 return true; 423 } 424 425 /** 426 * Verifies if the birthday privacy option is valid or not. 427 * 428 * @return boolean True when valid, false when invalid. 429 */ 430 function verify_birthday_privacy() 431 { 432 $birthdayprivacy = &$this->data['birthdayprivacy']; 433 $accepted = array( 434 'none', 435 'age', 436 'all'); 437 438 if(!in_array($birthdayprivacy, $accepted)) 439 { 440 $this->set_error("invalid_birthday_privacy"); 441 return false; 442 } 443 else if ($birthdayprivacy == 'age') 444 { 445 $birthdayyear = &$this->data['birthday']['year']; 446 if(empty($birthdayyear)) 447 { 448 $this->set_error("conflicted_birthday_privacy"); 449 return false; 450 } 451 } 452 return true; 453 } 454 455 /** 456 * Verifies if the post count field is filled in correctly. 457 * 458 * @return boolean True when valid, false when invalid. 459 */ 460 function verify_postnum() 461 { 462 $user = &$this->data; 463 464 if(isset($user['postnum']) && $user['postnum'] < 0) 465 { 466 $this->set_error("invalid_postnum"); 467 return false; 468 } 469 470 return true; 471 } 472 473 /** 474 * Verifies if the thread count field is filled in correctly. 475 * 476 * @return boolean True when valid, false when invalid. 477 */ 478 function verify_threadnum() 479 { 480 $user = &$this->data; 481 482 if(isset($user['threadnum']) && $user['threadnum'] < 0) 483 { 484 $this->set_error("invalid_threadnum"); 485 return false; 486 } 487 488 return true; 489 } 490 491 /** 492 * Verifies if a profile fields are filled in correctly. 493 * 494 * @return boolean True when valid, false when invalid. 495 */ 496 function verify_profile_fields() 497 { 498 global $db, $cache; 499 500 $user = &$this->data; 501 $profile_fields = &$this->data['profile_fields']; 502 503 // Loop through profile fields checking if they exist or not and are filled in. 504 505 // Fetch all profile fields first. 506 $pfcache = $cache->read('profilefields'); 507 508 if(is_array($pfcache)) 509 { 510 // Then loop through the profile fields. 511 foreach($pfcache as $profilefield) 512 { 513 if(isset($this->data['profile_fields_editable']) || isset($this->data['registration']) && ($profilefield['required'] == 1 || $profilefield['registration'] == 1)) 514 { 515 $profilefield['editableby'] = -1; 516 } 517 518 if(isset($user['usergroup'])) 519 { 520 $usergroup = $user['usergroup']; 521 } 522 else 523 { 524 $usergroup = ''; 525 } 526 if(isset($user['additionalgroups'])) 527 { 528 $additionalgroups = $user['additionalgroups']; 529 } 530 else 531 { 532 $additionalgroups = ''; 533 } 534 535 if(!is_member($profilefield['editableby'], array('usergroup' => $usergroup, 'additionalgroups' => $additionalgroups))) 536 { 537 continue; 538 } 539 540 // Does this field have a minimum post count? 541 if(!isset($this->data['profile_fields_editable']) && !empty($profilefield['postnum']) && $profilefield['postnum'] > $user['postnum']) 542 { 543 continue; 544 } 545 546 $profilefield['type'] = htmlspecialchars_uni($profilefield['type']); 547 $profilefield['name'] = htmlspecialchars_uni($profilefield['name']); 548 $thing = explode("\n", $profilefield['type'], "2"); 549 $type = trim($thing[0]); 550 $field = "fid{$profilefield['fid']}"; 551 552 if(!isset($profile_fields[$field])) 553 { 554 $profile_fields[$field] = ''; 555 } 556 557 // If the profile field is required, but not filled in, present error. 558 if($type != "multiselect" && $type != "checkbox") 559 { 560 if(trim($profile_fields[$field]) == "" && $profilefield['required'] == 1 && !defined('IN_ADMINCP') && THIS_SCRIPT != "modcp.php") 561 { 562 $this->set_error('missing_required_profile_field', array($profilefield['name'])); 563 } 564 } 565 elseif(($type == "multiselect" || $type == "checkbox") && $profile_fields[$field] == "" && $profilefield['required'] == 1 && !defined('IN_ADMINCP') && THIS_SCRIPT != "modcp.php") 566 { 567 $this->set_error('missing_required_profile_field', array($profilefield['name'])); 568 } 569 570 // Sort out multiselect/checkbox profile fields. 571 $options = ''; 572 if(($type == "multiselect" || $type == "checkbox") && is_array($profile_fields[$field])) 573 { 574 $expoptions = explode("\n", $thing[1]); 575 $expoptions = array_map('trim', $expoptions); 576 foreach($profile_fields[$field] as $value) 577 { 578 if(!in_array(htmlspecialchars_uni($value), $expoptions)) 579 { 580 $this->set_error('bad_profile_field_values', array($profilefield['name'])); 581 } 582 if($options) 583 { 584 $options .= "\n"; 585 } 586 $options .= $db->escape_string($value); 587 } 588 } 589 elseif($type == "select" || $type == "radio") 590 { 591 $expoptions = explode("\n", $thing[1]); 592 $expoptions = array_map('trim', $expoptions); 593 if(!in_array(htmlspecialchars_uni($profile_fields[$field]), $expoptions) && trim($profile_fields[$field]) != "") 594 { 595 $this->set_error('bad_profile_field_values', array($profilefield['name'])); 596 } 597 $options = $db->escape_string($profile_fields[$field]); 598 } 599 else 600 { 601 if($profilefield['maxlength'] > 0 && my_strlen($profile_fields[$field]) > $profilefield['maxlength']) 602 { 603 $this->set_error('max_limit_reached', array($profilefield['name'], $profilefield['maxlength'])); 604 } 605 606 if(!empty($profilefield['regex']) && !empty($profile_fields[$field]) && !preg_match("#".$profilefield['regex']."#i", $profile_fields[$field])) 607 { 608 $this->set_error('bad_profile_field_value', array($profilefield['name'])); 609 } 610 611 $options = $db->escape_string($profile_fields[$field]); 612 } 613 $user['user_fields'][$field] = $options; 614 } 615 } 616 617 return true; 618 } 619 620 /** 621 * Verifies if an optionally entered referrer exists or not. 622 * 623 * @return boolean True when valid, false when invalid. 624 */ 625 function verify_referrer() 626 { 627 global $db, $mybb; 628 629 $user = &$this->data; 630 631 // Does the referrer exist or not? 632 if($mybb->settings['usereferrals'] == 1 && !empty($user['referrer'])) 633 { 634 $referrer = get_user_by_username($user['referrer']); 635 636 if(empty($referrer['uid'])) 637 { 638 $this->set_error('invalid_referrer', array($user['referrer'])); 639 return false; 640 } 641 642 $user['referrer_uid'] = $referrer['uid']; 643 } 644 else 645 { 646 $user['referrer_uid'] = 0; 647 } 648 649 return true; 650 } 651 652 /** 653 * Verifies user options. 654 * 655 * @return boolean True when valid, false when invalid. 656 */ 657 function verify_options() 658 { 659 global $mybb; 660 661 $options = &$this->data['options']; 662 663 if(!is_array($options)) 664 { 665 $options = array(); 666 } 667 668 // Verify yes/no options. 669 $this->verify_yesno_option($options, 'allownotices', 1); 670 $this->verify_yesno_option($options, 'hideemail', 0); 671 $this->verify_yesno_option($options, 'receivepms', 1); 672 $this->verify_yesno_option($options, 'receivefrombuddy', 0); 673 $this->verify_yesno_option($options, 'pmnotice', 1); 674 $this->verify_yesno_option($options, 'pmnotify', 1); 675 $this->verify_yesno_option($options, 'invisible', 0); 676 $this->verify_yesno_option($options, 'showimages', 1); 677 $this->verify_yesno_option($options, 'showvideos', 1); 678 $this->verify_yesno_option($options, 'showsigs', 1); 679 $this->verify_yesno_option($options, 'showavatars', 1); 680 $this->verify_yesno_option($options, 'showquickreply', 1); 681 $this->verify_yesno_option($options, 'showredirect', 1); 682 $this->verify_yesno_option($options, 'showcodebuttons', 1); 683 $this->verify_yesno_option($options, 'sourceeditor', 0); 684 $this->verify_yesno_option($options, 'buddyrequestspm', 1); 685 $this->verify_yesno_option($options, 'buddyrequestsauto', 0); 686 687 if($mybb->settings['postlayout'] == 'classic') 688 { 689 $this->verify_yesno_option($options, 'classicpostbit', 1); 690 } 691 else 692 { 693 $this->verify_yesno_option($options, 'classicpostbit', 0); 694 } 695 696 if(array_key_exists('subscriptionmethod', $options)) 697 { 698 // Value out of range 699 $options['subscriptionmethod'] = (int)$options['subscriptionmethod']; 700 if($options['subscriptionmethod'] < 0 || $options['subscriptionmethod'] > 3) 701 { 702 $options['subscriptionmethod'] = 0; 703 } 704 } 705 706 if(array_key_exists('dstcorrection', $options)) 707 { 708 // Value out of range 709 $options['dstcorrection'] = (int)$options['dstcorrection']; 710 if($options['dstcorrection'] < 0 || $options['dstcorrection'] > 2) 711 { 712 $options['dstcorrection'] = 0; 713 } 714 715 if($options['dstcorrection'] == 1) 716 { 717 $options['dst'] = 1; 718 } 719 elseif($options['dstcorrection'] == 0) 720 { 721 $options['dst'] = 0; 722 } 723 } 724 725 if($this->method == "insert" || (isset($options['threadmode']) && $options['threadmode'] != "linear" && $options['threadmode'] != "threaded" && $options['threadmode'] != '')) 726 { 727 $options['threadmode'] = ''; 728 } 729 730 // Verify the "threads per page" option. 731 if($this->method == "insert" || (array_key_exists('tpp', $options) && $mybb->settings['usertppoptions'])) 732 { 733 if(!isset($options['tpp'])) 734 { 735 $options['tpp'] = 0; 736 } 737 $explodedtpp = explode(",", $mybb->settings['usertppoptions']); 738 if(is_array($explodedtpp)) 739 { 740 @asort($explodedtpp); 741 $biggest = $explodedtpp[count($explodedtpp)-1]; 742 // Is the selected option greater than the allowed options? 743 if($options['tpp'] > $biggest) 744 { 745 $options['tpp'] = $biggest; 746 } 747 } 748 $options['tpp'] = (int)$options['tpp']; 749 } 750 // Verify the "posts per page" option. 751 if($this->method == "insert" || (array_key_exists('ppp', $options) && $mybb->settings['userpppoptions'])) 752 { 753 if(!isset($options['ppp'])) 754 { 755 $options['ppp'] = 0; 756 } 757 $explodedppp = explode(",", $mybb->settings['userpppoptions']); 758 if(is_array($explodedppp)) 759 { 760 @asort($explodedppp); 761 $biggest = $explodedppp[count($explodedppp)-1]; 762 // Is the selected option greater than the allowed options? 763 if($options['ppp'] > $biggest) 764 { 765 $options['ppp'] = $biggest; 766 } 767 } 768 $options['ppp'] = (int)$options['ppp']; 769 } 770 // Is our selected "days prune" option valid or not? 771 if($this->method == "insert" || array_key_exists('daysprune', $options)) 772 { 773 if(!isset($options['daysprune'])) 774 { 775 $options['daysprune'] = 0; 776 } 777 $options['daysprune'] = (int)$options['daysprune']; 778 if($options['daysprune'] < 0) 779 { 780 $options['daysprune'] = 0; 781 } 782 } 783 $this->data['options'] = $options; 784 } 785 786 /** 787 * Verifies if a registration date is valid or not. 788 * 789 * @return boolean True when valid, false when invalid. 790 */ 791 function verify_regdate() 792 { 793 $regdate = &$this->data['regdate']; 794 795 $regdate = (int)$regdate; 796 // If the timestamp is below 0, set it to the current time. 797 if($regdate <= 0) 798 { 799 $regdate = TIME_NOW; 800 } 801 return true; 802 } 803 804 /** 805 * Verifies if a last visit date is valid or not. 806 * 807 * @return boolean True when valid, false when invalid. 808 */ 809 function verify_lastvisit() 810 { 811 $lastvisit = &$this->data['lastvisit']; 812 813 $lastvisit = (int)$lastvisit; 814 // If the timestamp is below 0, set it to the current time. 815 if($lastvisit <= 0) 816 { 817 $lastvisit = TIME_NOW; 818 } 819 return true; 820 821 } 822 823 /** 824 * Verifies if a last active date is valid or not. 825 * 826 * @return boolean True when valid, false when invalid. 827 */ 828 function verify_lastactive() 829 { 830 $lastactive = &$this->data['lastactive']; 831 832 $lastactive = (int)$lastactive; 833 // If the timestamp is below 0, set it to the current time. 834 if($lastactive <= 0) 835 { 836 $lastactive = TIME_NOW; 837 } 838 return true; 839 840 } 841 842 /** 843 * Verifies if an away mode status is valid or not. 844 * 845 * @return boolean True when valid, false when invalid. 846 */ 847 function verify_away() 848 { 849 global $mybb; 850 851 $user = &$this->data; 852 // If the board does not allow "away mode" or the user is marking as not away, set defaults. 853 if($mybb->settings['allowaway'] == 0 || !isset($user['away']['away']) || $user['away']['away'] != 1) 854 { 855 $user['away']['away'] = 0; 856 $user['away']['date'] = 0; 857 $user['away']['returndate'] = 0; 858 $user['away']['awayreason'] = ''; 859 return true; 860 } 861 elseif($user['away']['returndate']) 862 { 863 // Validate the awayreason length, since the db holds 200 chars for this field 864 $reasonlength = my_strlen($user['away']['awayreason']); 865 if($reasonlength > 200) 866 { 867 $this->set_error("away_too_long", array($reasonlength - 200)); 868 return false; 869 } 870 871 list($returnday, $returnmonth, $returnyear) = explode('-', $user['away']['returndate']); 872 if(!$returnday || !$returnmonth || !$returnyear) 873 { 874 $this->set_error("missing_returndate"); 875 return false; 876 } 877 878 // Validate the return date lengths 879 $user['away']['returndate'] = substr($returnday, 0, 2).'-'.substr($returnmonth, 0, 2).'-'.substr($returnyear, 0, 4); 880 } 881 return true; 882 } 883 884 /** 885 * Verifies if a language is valid for this user or not. 886 * 887 * @return boolean True when valid, false when invalid. 888 */ 889 function verify_language() 890 { 891 global $lang; 892 893 $language = &$this->data['language']; 894 895 // An invalid language has been specified? 896 if($language != '' && !$lang->language_exists($language)) 897 { 898 $this->set_error("invalid_language"); 899 return false; 900 } 901 return true; 902 } 903 904 /** 905 * Verifies if a style is valid for this user or not. 906 * 907 * @return boolean True when valid, false when invalid. 908 */ 909 function verify_style() 910 { 911 global $lang; 912 913 $user = &$this->data; 914 915 if(!empty($user['style'])) 916 { 917 $theme = get_theme($user['style']); 918 919 if(empty($theme) || !is_member($theme['allowedgroups'], $user) && $theme['allowedgroups'] != 'all') 920 { 921 $this->set_error('invalid_style'); 922 return false; 923 } 924 } 925 926 return true; 927 } 928 929 /** 930 * Verifies if this is coming from a spam bot or not 931 * 932 * @return boolean True when valid, false when invalid. 933 */ 934 function verify_checkfields() 935 { 936 $user = &$this->data; 937 938 // An invalid language has been specified? 939 if($user['regcheck1'] !== "" || $user['regcheck2'] !== "true") 940 { 941 $this->set_error("invalid_checkfield"); 942 return false; 943 } 944 return true; 945 } 946 947 /** 948 * Verifies if the user timezone is valid. 949 * If the timezone is invalid, the board default is used. 950 * 951 * @return boolean True when timezone was valid, false otherwise 952 */ 953 function verify_timezone() 954 { 955 global $mybb; 956 957 $user = &$this->data; 958 959 $timezones = get_supported_timezones(); 960 961 if(!isset($user['timezone']) || !array_key_exists($user['timezone'], $timezones)) 962 { 963 $user['timezone'] = $mybb->settings['timezoneoffset']; 964 return false; 965 } 966 967 return true; 968 } 969 970 /** 971 * Validate all user assets. 972 * 973 * @return boolean True when valid, false when invalid. 974 */ 975 function validate_user() 976 { 977 global $mybb, $plugins; 978 979 $user = &$this->data; 980 981 // First, grab the old user details if this user exists 982 if(!empty($user['uid'])) 983 { 984 $old_user = get_user($user['uid']); 985 } 986 987 if($this->method == "insert" || array_key_exists('username', $user)) 988 { 989 // If the username is the same - no need to verify 990 if(!isset($old_user['username']) || $user['username'] != $old_user['username']) 991 { 992 $this->verify_username(); 993 $this->verify_username_exists(); 994 } 995 else 996 { 997 unset($user['username']); 998 } 999 } 1000 if($this->method == "insert" || array_key_exists('usertitle', $user)) 1001 { 1002 $this->verify_usertitle(); 1003 } 1004 if($this->method == "insert" || array_key_exists('password', $user)) 1005 { 1006 $this->verify_password(); 1007 } 1008 if($this->method == "insert" || array_key_exists('usergroup', $user)) 1009 { 1010 $this->verify_usergroup(); 1011 } 1012 if($this->method == "insert" || array_key_exists('email', $user)) 1013 { 1014 $this->verify_email(); 1015 } 1016 if($this->method == "insert" || array_key_exists('website', $user)) 1017 { 1018 $this->verify_website(); 1019 } 1020 if($this->method == "insert" || array_key_exists('icq', $user)) 1021 { 1022 $this->verify_icq(); 1023 } 1024 if($this->method == "insert" || (isset($user['birthday']) && is_array($user['birthday']))) 1025 { 1026 $this->verify_birthday(); 1027 } 1028 if($this->method == "insert" || array_key_exists('postnum', $user)) 1029 { 1030 $this->verify_postnum(); 1031 } 1032 if($this->method == "insert" || array_key_exists('threadnum', $user)) 1033 { 1034 $this->verify_threadnum(); 1035 } 1036 if($this->method == "insert" || array_key_exists('profile_fields', $user)) 1037 { 1038 $this->verify_profile_fields(); 1039 } 1040 if($this->method == "insert" || array_key_exists('referrer', $user)) 1041 { 1042 $this->verify_referrer(); 1043 } 1044 if($this->method == "insert" || array_key_exists('options', $user)) 1045 { 1046 $this->verify_options(); 1047 } 1048 if($this->method == "insert" || array_key_exists('regdate', $user)) 1049 { 1050 $this->verify_regdate(); 1051 } 1052 if($this->method == "insert" || array_key_exists('lastvisit', $user)) 1053 { 1054 $this->verify_lastvisit(); 1055 } 1056 if($this->method == "insert" || array_key_exists('lastactive', $user)) 1057 { 1058 $this->verify_lastactive(); 1059 } 1060 if($this->method == "insert" || array_key_exists('away', $user)) 1061 { 1062 $this->verify_away(); 1063 } 1064 if($this->method == "insert" || array_key_exists('language', $user)) 1065 { 1066 $this->verify_language(); 1067 } 1068 if($this->method == "insert" || array_key_exists('timezone', $user)) 1069 { 1070 $this->verify_timezone(); 1071 } 1072 if($this->method == "insert" && array_key_exists('regcheck1', $user) && array_key_exists('regcheck2', $user)) 1073 { 1074 $this->verify_checkfields(); 1075 } 1076 if(array_key_exists('birthdayprivacy', $user)) 1077 { 1078 $this->verify_birthday_privacy(); 1079 } 1080 if($this->method == "insert" || array_key_exists('style', $user)) 1081 { 1082 $this->verify_style(); 1083 } 1084 if($this->method == "insert" || array_key_exists('signature', $user)) 1085 { 1086 $this->verify_signature(); 1087 } 1088 1089 $plugins->run_hooks("datahandler_user_validate", $this); 1090 1091 // We are done validating, return. 1092 $this->set_validated(true); 1093 if(count($this->get_errors()) > 0) 1094 { 1095 return false; 1096 } 1097 else 1098 { 1099 return true; 1100 } 1101 } 1102 1103 /** 1104 * Inserts a user into the database. 1105 * 1106 * @return array 1107 */ 1108 function insert_user() 1109 { 1110 global $db, $cache, $plugins; 1111 1112 // Yes, validating is required. 1113 if(!$this->get_validated()) 1114 { 1115 die("The user needs to be validated before inserting it into the DB."); 1116 } 1117 if(count($this->get_errors()) > 0) 1118 { 1119 die("The user is not valid."); 1120 } 1121 1122 $user = &$this->data; 1123 1124 $array = array('postnum', 'threadnum', 'avatar', 'avatartype', 'additionalgroups', 'displaygroup', 'icq', 'skype', 'google', 'bday', 'signature', 'style', 'dateformat', 'timeformat', 'notepad', 'regip', 'lastip', 'coppa_user'); 1125 foreach($array as $value) 1126 { 1127 if(!isset($user[$value])) 1128 { 1129 $user[$value] = ''; 1130 } 1131 } 1132 1133 $array = array('subscriptionmethod', 'dstcorrection'); 1134 foreach($array as $value) 1135 { 1136 if(!isset($user['options'][$value])) 1137 { 1138 $user['options'][$value] = ''; 1139 } 1140 } 1141 1142 // If user is being created from ACP, there is no last visit or last active 1143 if(defined('IN_ADMINCP')) 1144 { 1145 $user['lastvisit'] = $user['lastactive'] = 0; 1146 } 1147 1148 $this->user_insert_data = array( 1149 "username" => $db->escape_string($user['username']), 1150 "password" => $user['password'], 1151 "salt" => $user['salt'], 1152 "loginkey" => $user['loginkey'], 1153 "email" => $db->escape_string($user['email']), 1154 "postnum" => (int)$user['postnum'], 1155 "threadnum" => (int)$user['threadnum'], 1156 "avatar" => $db->escape_string($user['avatar']), 1157 "avatartype" => $db->escape_string($user['avatartype']), 1158 "usergroup" => (int)$user['usergroup'], 1159 "additionalgroups" => $db->escape_string($user['additionalgroups']), 1160 "displaygroup" => (int)$user['displaygroup'], 1161 "usertitle" => $db->escape_string(htmlspecialchars_uni($user['usertitle'])), 1162 "regdate" => (int)$user['regdate'], 1163 "lastactive" => (int)$user['lastactive'], 1164 "lastvisit" => (int)$user['lastvisit'], 1165 "website" => $db->escape_string($user['website']), 1166 "icq" => (int)$user['icq'], 1167 "skype" => $db->escape_string($user['skype']), 1168 "google" => $db->escape_string($user['google']), 1169 "birthday" => $user['bday'], 1170 "signature" => $db->escape_string($user['signature']), 1171 "allownotices" => (int)$user['options']['allownotices'], 1172 "hideemail" => (int)$user['options']['hideemail'], 1173 "subscriptionmethod" => (int)$user['options']['subscriptionmethod'], 1174 "receivepms" => (int)$user['options']['receivepms'], 1175 "receivefrombuddy" => (int)$user['options']['receivefrombuddy'], 1176 "pmnotice" => (int)$user['options']['pmnotice'], 1177 "pmnotify" => (int)$user['options']['pmnotify'], 1178 "showimages" => (int)$user['options']['showimages'], 1179 "showvideos" => (int)$user['options']['showvideos'], 1180 "showsigs" => (int)$user['options']['showsigs'], 1181 "showavatars" => (int)$user['options']['showavatars'], 1182 "showquickreply" => (int)$user['options']['showquickreply'], 1183 "showredirect" => (int)$user['options']['showredirect'], 1184 "tpp" => (int)$user['options']['tpp'], 1185 "ppp" => (int)$user['options']['ppp'], 1186 "invisible" => (int)$user['options']['invisible'], 1187 "style" => (int)$user['style'], 1188 "timezone" => $db->escape_string($user['timezone']), 1189 "dstcorrection" => (int)$user['options']['dstcorrection'], 1190 "threadmode" => $user['options']['threadmode'], 1191 "daysprune" => (int)$user['options']['daysprune'], 1192 "dateformat" => $db->escape_string($user['dateformat']), 1193 "timeformat" => $db->escape_string($user['timeformat']), 1194 "regip" => $db->escape_binary($user['regip']), 1195 "lastip" => $db->escape_binary($user['lastip']), 1196 "language" => $db->escape_string($user['language']), 1197 "showcodebuttons" => (int)$user['options']['showcodebuttons'], 1198 "sourceeditor" => (int)$user['options']['sourceeditor'], 1199 "buddyrequestspm" => (int)$user['options']['buddyrequestspm'], 1200 "buddyrequestsauto" => (int)$user['options']['buddyrequestsauto'], 1201 "away" => (int)$user['away']['away'], 1202 "awaydate" => (int)$user['away']['date'], 1203 "returndate" => $user['away']['returndate'], 1204 "awayreason" => $db->escape_string($user['away']['awayreason']), 1205 "referrer" => (int)$user['referrer_uid'], 1206 "referrals" => 0, 1207 "buddylist" => '', 1208 "ignorelist" => '', 1209 "pmfolders" => "0**$%%$1**$%%$2**$%%$3**$%%$4**", 1210 "notepad" => '', 1211 "warningpoints" => 0, 1212 "moderateposts" => 0, 1213 "moderationtime" => 0, 1214 "suspendposting" => 0, 1215 "suspensiontime" => 0, 1216 "coppauser" => (int)$user['coppa_user'], 1217 "classicpostbit" => (int)$user['options']['classicpostbit'], 1218 "usernotes" => '' 1219 ); 1220 1221 if($user['options']['dstcorrection'] == 1) 1222 { 1223 $this->user_insert_data['dst'] = 1; 1224 } 1225 elseif($user['options']['dstcorrection'] == 0) 1226 { 1227 $this->user_insert_data['dst'] = 0; 1228 } 1229 1230 $plugins->run_hooks("datahandler_user_insert", $this); 1231 1232 $this->uid = $db->insert_query("users", $this->user_insert_data); 1233 1234 $user['user_fields']['ufid'] = $this->uid; 1235 1236 $pfcache = $cache->read('profilefields'); 1237 1238 if(is_array($pfcache)) 1239 { 1240 foreach($pfcache as $profile_field) 1241 { 1242 if(array_key_exists("fid{$profile_field['fid']}", $user['user_fields'])) 1243 { 1244 continue; 1245 } 1246 $user['user_fields']["fid{$profile_field['fid']}"] = ''; 1247 } 1248 } 1249 1250 $db->insert_query("userfields", $user['user_fields'], false); 1251 1252 if($this->user_insert_data['referrer'] != 0) 1253 { 1254 $db->write_query(" 1255 UPDATE ".TABLE_PREFIX."users 1256 SET referrals=referrals+1 1257 WHERE uid='{$this->user_insert_data['referrer']}' 1258 "); 1259 } 1260 1261 // Update forum stats 1262 update_stats(array('numusers' => '+1')); 1263 1264 if((int)$user['usergroup'] == 5) 1265 { 1266 $cache->update_awaitingactivation(); 1267 } 1268 1269 $this->return_values = array( 1270 "uid" => $this->uid, 1271 "username" => $user['username'], 1272 "loginkey" => $user['loginkey'], 1273 "email" => $user['email'], 1274 "password" => $user['password'], 1275 "usergroup" => $user['usergroup'] 1276 ); 1277 1278 $plugins->run_hooks("datahandler_user_insert_end", $this); 1279 1280 return $this->return_values; 1281 } 1282 1283 /** 1284 * Updates a user in the database. 1285 * 1286 * @return bool 1287 */ 1288 function update_user() 1289 { 1290 global $db, $plugins, $cache; 1291 1292 // Yes, validating is required. 1293 if(!$this->get_validated()) 1294 { 1295 die("The user needs to be validated before inserting it into the DB."); 1296 } 1297 if(count($this->get_errors()) > 0) 1298 { 1299 die("The user is not valid."); 1300 } 1301 1302 $user = &$this->data; 1303 $user['uid'] = (int)$user['uid']; 1304 $this->uid = $user['uid']; 1305 1306 // Set up the update data. 1307 if(isset($user['username'])) 1308 { 1309 $this->user_update_data['username'] = $db->escape_string($user['username']); 1310 } 1311 if(isset($user['password'])) 1312 { 1313 $this->user_update_data['password'] = $user['password']; 1314 } 1315 if(isset($user['salt'])) 1316 { 1317 $this->user_update_data['salt'] = $user['salt']; 1318 } 1319 if(isset($user['loginkey'])) 1320 { 1321 $this->user_update_data['loginkey'] = $user['loginkey']; 1322 } 1323 if(isset($user['email'])) 1324 { 1325 $this->user_update_data['email'] = $db->escape_string($user['email']); 1326 } 1327 if(isset($user['postnum'])) 1328 { 1329 $this->user_update_data['postnum'] = (int)$user['postnum']; 1330 } 1331 if(isset($user['threadnum'])) 1332 { 1333 $this->user_update_data['threadnum'] = (int)$user['threadnum']; 1334 } 1335 if(isset($user['avatar'])) 1336 { 1337 $this->user_update_data['avatar'] = $db->escape_string($user['avatar']); 1338 $this->user_update_data['avatartype'] = $db->escape_string($user['avatartype']); 1339 } 1340 if(isset($user['usergroup'])) 1341 { 1342 $this->user_update_data['usergroup'] = (int)$user['usergroup']; 1343 } 1344 if(isset($user['additionalgroups'])) 1345 { 1346 $this->user_update_data['additionalgroups'] = $db->escape_string($user['additionalgroups']); 1347 } 1348 if(isset($user['displaygroup'])) 1349 { 1350 $this->user_update_data['displaygroup'] = (int)$user['displaygroup']; 1351 } 1352 if(isset($user['usertitle'])) 1353 { 1354 $this->user_update_data['usertitle'] = $db->escape_string($user['usertitle']); 1355 } 1356 if(isset($user['regdate'])) 1357 { 1358 $this->user_update_data['regdate'] = (int)$user['regdate']; 1359 } 1360 if(isset($user['lastactive'])) 1361 { 1362 $this->user_update_data['lastactive'] = (int)$user['lastactive']; 1363 } 1364 if(isset($user['lastvisit'])) 1365 { 1366 $this->user_update_data['lastvisit'] = (int)$user['lastvisit']; 1367 } 1368 if(isset($user['signature'])) 1369 { 1370 $this->user_update_data['signature'] = $db->escape_string($user['signature']); 1371 } 1372 if(isset($user['website'])) 1373 { 1374 $this->user_update_data['website'] = $db->escape_string($user['website']); 1375 } 1376 if(isset($user['icq'])) 1377 { 1378 $this->user_update_data['icq'] = (int)$user['icq']; 1379 } 1380 if(isset($user['skype'])) 1381 { 1382 $this->user_update_data['skype'] = $db->escape_string($user['skype']); 1383 } 1384 if(isset($user['google'])) 1385 { 1386 $this->user_update_data['google'] = $db->escape_string($user['google']); 1387 } 1388 if(isset($user['bday'])) 1389 { 1390 $this->user_update_data['birthday'] = $user['bday']; 1391 } 1392 if(isset($user['birthdayprivacy'])) 1393 { 1394 $this->user_update_data['birthdayprivacy'] = $db->escape_string($user['birthdayprivacy']); 1395 } 1396 if(isset($user['style'])) 1397 { 1398 $this->user_update_data['style'] = (int)$user['style']; 1399 } 1400 if(isset($user['timezone'])) 1401 { 1402 $this->user_update_data['timezone'] = $db->escape_string($user['timezone']); 1403 } 1404 if(isset($user['dateformat'])) 1405 { 1406 $this->user_update_data['dateformat'] = $db->escape_string($user['dateformat']); 1407 } 1408 if(isset($user['timeformat'])) 1409 { 1410 $this->user_update_data['timeformat'] = $db->escape_string($user['timeformat']); 1411 } 1412 if(isset($user['regip'])) 1413 { 1414 $this->user_update_data['regip'] = $db->escape_string($user['regip']); 1415 } 1416 if(isset($user['lastip'])) 1417 { 1418 $this->user_update_data['lastip'] = $db->escape_string($user['lastip']); 1419 } 1420 if(isset($user['language'])) 1421 { 1422 $this->user_update_data['language'] = $db->escape_string($user['language']); 1423 } 1424 if(isset($user['away'])) 1425 { 1426 $this->user_update_data['away'] = (int)$user['away']['away']; 1427 $this->user_update_data['awaydate'] = $db->escape_string($user['away']['date']); 1428 $this->user_update_data['returndate'] = $db->escape_string($user['away']['returndate']); 1429 $this->user_update_data['awayreason'] = $db->escape_string($user['away']['awayreason']); 1430 } 1431 if(isset($user['notepad'])) 1432 { 1433 $this->user_update_data['notepad'] = $db->escape_string($user['notepad']); 1434 } 1435 if(isset($user['usernotes'])) 1436 { 1437 $this->user_update_data['usernotes'] = $db->escape_string($user['usernotes']); 1438 } 1439 if(isset($user['options']) && is_array($user['options'])) 1440 { 1441 foreach($user['options'] as $option => $value) 1442 { 1443 $this->user_update_data[$option] = $value; 1444 } 1445 } 1446 if(array_key_exists('coppa_user', $user)) 1447 { 1448 $this->user_update_data['coppauser'] = (int)$user['coppa_user']; 1449 } 1450 // First, grab the old user details for later use. 1451 $old_user = get_user($user['uid']); 1452 1453 // If old user has new pmnotice and new user has = yes, keep old value 1454 if($old_user['pmnotice'] == "2" && $this->user_update_data['pmnotice'] == 1) 1455 { 1456 unset($this->user_update_data['pmnotice']); 1457 } 1458 1459 $plugins->run_hooks("datahandler_user_update", $this); 1460 1461 if(count($this->user_update_data) < 1 && empty($user['user_fields'])) 1462 { 1463 return false; 1464 } 1465 1466 if(count($this->user_update_data) > 0) 1467 { 1468 // Actual updating happens here. 1469 $db->update_query("users", $this->user_update_data, "uid='{$user['uid']}'"); 1470 } 1471 1472 $cache->update_moderators(); 1473 if(isset($user['bday']) || isset($user['username'])) 1474 { 1475 $cache->update_birthdays(); 1476 } 1477 1478 if(isset($user['usergroup']) && (int)$user['usergroup'] == 5) 1479 { 1480 $cache->update_awaitingactivation(); 1481 } 1482 1483 // Maybe some userfields need to be updated? 1484 if(isset($user['user_fields']) && is_array($user['user_fields'])) 1485 { 1486 $query = $db->simple_select("userfields", "*", "ufid='{$user['uid']}'"); 1487 $fields = $db->fetch_array($query); 1488 if(empty($fields['ufid'])) 1489 { 1490 $user_fields = array( 1491 'ufid' => $user['uid'] 1492 ); 1493 1494 $fields_array = $db->show_fields_from("userfields"); 1495 foreach($fields_array as $field) 1496 { 1497 if($field['Field'] == 'ufid') 1498 { 1499 continue; 1500 } 1501 $user_fields[$field['Field']] = ''; 1502 } 1503 $db->insert_query("userfields", $user_fields); 1504 } 1505 $db->update_query("userfields", $user['user_fields'], "ufid='{$user['uid']}'", false); 1506 } 1507 1508 // Let's make sure the user's name gets changed everywhere in the db if it changed. 1509 if(!empty($this->user_update_data['username']) && $this->user_update_data['username'] != $old_user['username']) 1510 { 1511 $username_update = array( 1512 "username" => $this->user_update_data['username'] 1513 ); 1514 $lastposter_update = array( 1515 "lastposter" => $this->user_update_data['username'] 1516 ); 1517 1518 $db->update_query("posts", $username_update, "uid='{$user['uid']}'"); 1519 $db->update_query("threads", $username_update, "uid='{$user['uid']}'"); 1520 $db->update_query("threads", $lastposter_update, "lastposteruid='{$user['uid']}'"); 1521 $db->update_query("forums", $lastposter_update, "lastposteruid='{$user['uid']}'"); 1522 1523 $stats = $cache->read("stats"); 1524 if($stats['lastuid'] == $user['uid']) 1525 { 1526 // User was latest to register, update stats 1527 update_stats(array("numusers" => "+0")); 1528 } 1529 } 1530 1531 return true; 1532 } 1533 1534 /** 1535 * Provides a method to completely delete a user. 1536 * 1537 * @param array $delete_uids Array of user information 1538 * @param integer $prunecontent Whether if delete threads/posts or not 1539 * @return array 1540 */ 1541 function delete_user($delete_uids, $prunecontent=0) 1542 { 1543 global $db, $plugins, $mybb, $cache; 1544 1545 // Yes, validating is required. 1546 if(count($this->get_errors()) > 0) 1547 { 1548 die('The user is not valid.'); 1549 } 1550 1551 $this->delete_uids = array_map('intval', (array)$delete_uids); 1552 1553 foreach($this->delete_uids as $key => $uid) 1554 { 1555 if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid']) 1556 { 1557 // Remove super admins 1558 unset($this->delete_uids[$key]); 1559 } 1560 } 1561 1562 $plugins->run_hooks('datahandler_user_delete_start', $this); 1563 1564 $this->delete_uids = implode(',', $this->delete_uids); 1565 1566 if(empty($this->delete_uids)) 1567 { 1568 $this->deleted_users = 0; 1569 $this->return_values = array( 1570 "deleted_users" => $this->deleted_users 1571 ); 1572 1573 return $this->return_values; 1574 } 1575 1576 $this->delete_content(); 1577 1578 // Delete the user 1579 $query = $db->delete_query('users', "uid IN({$this->delete_uids})"); 1580 $this->deleted_users = $db->affected_rows($query); 1581 1582 // Are we removing the posts/threads of a user? 1583 if((int)$prunecontent == 1) 1584 { 1585 $this->delete_posts(); 1586 $db->delete_query('announcements', "uid IN({$this->delete_uids})"); 1587 } 1588 else 1589 { 1590 // We're just updating the UID 1591 $db->update_query('pollvotes', array('uid' => 0), "uid IN({$this->delete_uids})"); 1592 $db->update_query('posts', array('uid' => 0), "uid IN({$this->delete_uids})"); 1593 $db->update_query('threads', array('uid' => 0), "uid IN({$this->delete_uids})"); 1594 $db->update_query('attachments', array('uid' => 0), "uid IN({$this->delete_uids})"); 1595 $db->update_query('announcements', array('uid' => 0), "uid IN({$this->delete_uids})"); 1596 } 1597 1598 $db->update_query('privatemessages', array('fromid' => 0), "fromid IN({$this->delete_uids})"); 1599 $db->update_query('users', array('referrer' => 0), "referrer IN({$this->delete_uids})"); 1600 1601 // Update thread ratings 1602 $query = $db->query(" 1603 SELECT r.*, t.numratings, t.totalratings 1604 FROM ".TABLE_PREFIX."threadratings r 1605 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=r.tid) 1606 WHERE r.uid IN({$this->delete_uids}) 1607 "); 1608 while($rating = $db->fetch_array($query)) 1609 { 1610 $update_thread = array( 1611 "numratings" => $rating['numratings'] - 1, 1612 "totalratings" => $rating['totalratings'] - $rating['rating'] 1613 ); 1614 $db->update_query("threads", $update_thread, "tid='{$rating['tid']}'"); 1615 } 1616 1617 $db->delete_query('threadratings', "uid IN({$this->delete_uids})"); 1618 1619 // Update forums & threads if user is the lastposter 1620 $db->update_query('forums', array('lastposteruid' => 0), "lastposteruid IN({$this->delete_uids})"); 1621 $db->update_query('threads', array('lastposteruid' => 0), "lastposteruid IN({$this->delete_uids})"); 1622 1623 // Update forum stats 1624 update_stats(array('numusers' => '-'.$this->deleted_users)); 1625 1626 $this->return_values = array( 1627 "deleted_users" => $this->deleted_users 1628 ); 1629 1630 $plugins->run_hooks("datahandler_user_delete_end", $this); 1631 1632 // Update cache 1633 $cache->update_moderators(); 1634 $cache->update_forumsdisplay(); 1635 $cache->update_reportedcontent(); 1636 $cache->update_awaitingactivation(); 1637 $cache->update_birthdays(); 1638 1639 return $this->return_values; 1640 } 1641 1642 /** 1643 * Provides a method to delete users' content 1644 * 1645 * @param array|bool $delete_uids Array of user ids, false if they're already set (eg when using the delete_user function) 1646 */ 1647 function delete_content($delete_uids=false) 1648 { 1649 global $db, $plugins, $mybb; 1650 1651 if($delete_uids != false) 1652 { 1653 $this->delete_uids = array_map('intval', (array)$delete_uids); 1654 1655 foreach($this->delete_uids as $key => $uid) 1656 { 1657 if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid']) 1658 { 1659 // Remove super admins 1660 unset($this->delete_uids[$key]); 1661 } 1662 } 1663 1664 $this->delete_uids = implode(',', $this->delete_uids); 1665 } 1666 1667 $plugins->run_hooks('datahandler_user_delete_content', $this); 1668 1669 if(empty($this->delete_uids)) 1670 { 1671 return; 1672 } 1673 1674 $db->delete_query('userfields', "ufid IN({$this->delete_uids})"); 1675 $db->delete_query('privatemessages', "uid IN({$this->delete_uids})"); 1676 $db->delete_query('events', "uid IN({$this->delete_uids})"); 1677 $db->delete_query('moderators', "id IN({$this->delete_uids}) AND isgroup = 0"); 1678 $db->delete_query('forumsubscriptions', "uid IN({$this->delete_uids})"); 1679 $db->delete_query('threadsubscriptions', "uid IN({$this->delete_uids})"); 1680 $db->delete_query('forumsread', "uid IN({$this->delete_uids})"); 1681 $db->delete_query('threadsread', "uid IN({$this->delete_uids})"); 1682 $db->delete_query('adminviews', "uid IN({$this->delete_uids})"); 1683 $db->delete_query('adminoptions', "uid IN({$this->delete_uids})"); 1684 $db->delete_query('adminsessions', "uid IN({$this->delete_uids})"); 1685 $db->delete_query('sessions', "uid IN({$this->delete_uids})"); 1686 $db->delete_query('banned', "uid IN({$this->delete_uids})"); 1687 $db->delete_query('joinrequests', "uid IN({$this->delete_uids})"); 1688 $db->delete_query('groupleaders', "uid IN({$this->delete_uids})"); 1689 $db->delete_query('awaitingactivation', "uid IN({$this->delete_uids})"); 1690 $db->delete_query('warnings', "uid IN({$this->delete_uids})"); 1691 $db->delete_query('reputation', "uid IN({$this->delete_uids}) OR adduid IN({$this->delete_uids})"); 1692 $db->delete_query('buddyrequests', "uid IN({$this->delete_uids}) OR touid IN({$this->delete_uids})"); 1693 $db->delete_query('posts', "uid IN({$this->delete_uids}) AND visible = -2"); 1694 $db->delete_query('threads', "uid IN({$this->delete_uids}) AND visible = -2"); 1695 1696 // Delete reports made to the profile or reputation of the deleted users (i.e. made by them) 1697 $db->delete_query('reportedcontent', "type='reputation' AND id3 IN({$this->delete_uids}) OR type='reputation' AND id2 IN({$this->delete_uids})"); 1698 $db->delete_query('reportedcontent', "type='profile' AND id IN({$this->delete_uids})"); 1699 1700 // Update the reports made by the deleted users by setting the uid to 0 1701 $db->update_query('reportedcontent', array('uid' => 0), "uid IN({$this->delete_uids})"); 1702 1703 // Remove any of the user(s) uploaded avatars 1704 require_once MYBB_ROOT.'inc/functions_upload.php'; 1705 foreach(explode(',', $this->delete_uids) as $uid) 1706 { 1707 remove_avatars($uid); 1708 } 1709 } 1710 1711 /** 1712 * Provides a method to delete an users posts and threads 1713 * 1714 * @param array|bool $delete_uids Array of user ids, false if they're already set (eg when using the delete_user function) 1715 */ 1716 function delete_posts($delete_uids=false) 1717 { 1718 global $db, $plugins, $mybb; 1719 1720 if($delete_uids != false) 1721 { 1722 $this->delete_uids = array_map('intval', (array)$delete_uids); 1723 1724 foreach($this->delete_uids as $key => $uid) 1725 { 1726 if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid']) 1727 { 1728 // Remove super admins 1729 unset($this->delete_uids[$key]); 1730 } 1731 } 1732 1733 $this->delete_uids = implode(',', $this->delete_uids); 1734 } 1735 1736 require_once MYBB_ROOT.'inc/class_moderation.php'; 1737 $moderation = new Moderation(); 1738 1739 $plugins->run_hooks('datahandler_user_delete_posts', $this); 1740 1741 if(empty($this->delete_uids)) 1742 { 1743 return; 1744 } 1745 1746 // Threads 1747 $query = $db->simple_select('threads', 'tid', "uid IN({$this->delete_uids})"); 1748 while($tid = $db->fetch_field($query, 'tid')) 1749 { 1750 $moderation->delete_thread($tid); 1751 } 1752 1753 // Posts 1754 $query = $db->simple_select('posts', 'pid', "uid IN({$this->delete_uids})"); 1755 while($pid = $db->fetch_field($query, 'pid')) 1756 { 1757 $moderation->delete_post($pid); 1758 } 1759 } 1760 1761 /** 1762 * Provides a method to clear an users profile 1763 * 1764 * @param array|bool $delete_uids Array of user ids, false if they're already set (eg when using the delete_user function) 1765 * @param int $gid The new usergroup if the users should be moved (additional usergroups are always removed) 1766 */ 1767 function clear_profile($delete_uids=false, $gid=0) 1768 { 1769 global $db, $plugins, $mybb; 1770 1771 // delete_uids isn't a nice name, but it's used as the functions above use the same 1772 if($delete_uids != false) 1773 { 1774 $this->delete_uids = array_map('intval', (array)$delete_uids); 1775 1776 foreach($this->delete_uids as $key => $uid) 1777 { 1778 if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid']) 1779 { 1780 // Remove super admins 1781 unset($this->delete_uids[$key]); 1782 } 1783 } 1784 1785 $this->delete_uids = implode(',', $this->delete_uids); 1786 } 1787 1788 $update = array( 1789 "website" => "", 1790 "birthday" => "", 1791 "icq" => "", 1792 "skype" => "", 1793 "google" => "", 1794 "usertitle" => "", 1795 "away" => 0, 1796 "awaydate" => 0, 1797 "returndate" => "", 1798 "awayreason" => "", 1799 "additionalgroups" => "", 1800 "displaygroup" => 0, 1801 "signature" => "", 1802 "avatar" => "", 1803 'avatardimensions' => '', 1804 'avatartype' => '' 1805 ); 1806 1807 if($gid > 0) 1808 { 1809 $update["usergroup"] = (int)$gid; 1810 } 1811 1812 $plugins->run_hooks('datahandler_user_clear_profile', $this); 1813 1814 if(empty($this->delete_uids)) 1815 { 1816 return; 1817 } 1818 1819 $db->update_query("users", $update, "uid IN({$this->delete_uids})"); 1820 $db->delete_query('userfields', "ufid IN({$this->delete_uids})"); 1821 1822 // Remove any of the user(s) uploaded avatars 1823 require_once MYBB_ROOT.'inc/functions_upload.php'; 1824 foreach(explode(',', $this->delete_uids) as $uid) 1825 { 1826 remove_avatars($uid); 1827 } 1828 } 1829 1830 public function verify_signature() 1831 { 1832 global $mybb, $parser; 1833 1834 if(!isset($this->data['signature'])) 1835 { 1836 return true; 1837 } 1838 1839 if(!isset($parser)) 1840 { 1841 require_once MYBB_ROOT."inc/class_parser.php"; 1842 $parser = new postParser; 1843 } 1844 1845 $parser_options = array( 1846 'allow_html' => $mybb->settings['sightml'], 1847 'allow_mycode' => $mybb->settings['sigmycode'], 1848 'allow_smilies' => $mybb->settings['sigsmilies'], 1849 'allow_imgcode' => $mybb->settings['sigimgcode'], 1850 "filter_badwords" => 1 1851 ); 1852 1853 $parsed_sig = $parser->parse_message($this->data['signature'], $parser_options); 1854 1855 if((($mybb->settings['sigimgcode'] == 0 && $mybb->settings['sigsmilies'] != 1) && 1856 substr_count($parsed_sig, "<img") > 0) || 1857 (($mybb->settings['sigimgcode'] == 1 || $mybb->settings['sigsmilies'] == 1) && 1858 substr_count($parsed_sig, "<img") > $mybb->settings['maxsigimages']) 1859 ) 1860 { 1861 $imgsallowed = 0; 1862 1863 if($mybb->settings['sigimgcode'] == 1) 1864 { 1865 $imgsallowed = $mybb->settings['maxsigimages']; 1866 } 1867 1868 $this->set_error('too_many_sig_images2', array($imgsallowed)); 1869 } 1870 1871 if($mybb->settings['sigcountmycode'] == 0) 1872 { 1873 $parsed_sig = $parser->text_parse_message($this->data['signature'], array('signature_parse' => '1')); 1874 } 1875 else 1876 { 1877 $parsed_sig = $this->data['signature']; 1878 } 1879 1880 if($mybb->settings['siglength'] > 0) 1881 { 1882 $parsed_sig = preg_replace("#\s#", "", $parsed_sig); 1883 $sig_length = my_strlen($parsed_sig); 1884 1885 if($sig_length > $mybb->settings['siglength']) 1886 { 1887 $this->set_error('sig_too_long', array($mybb->settings['siglength'])); 1888 1889 if($sig_length - $mybb->settings['siglength'] > 1) 1890 { 1891 $this->set_error('sig_remove_chars_plural', array($sig_length-$mybb->settings['siglength'])); 1892 } 1893 else 1894 { 1895 $this->set_error('sig_remove_chars_singular'); 1896 } 1897 } 1898 } 1899 1900 if(count($this->get_errors()) > 0) 1901 { 1902 return false; 1903 } 1904 return true; 1905 } 1906} 1907