[ Index ] |
PHP Cross Reference of MyBB 1.8.38 |
[Summary view] [Print] [Text view]
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 12 if(!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 * Login handling class, provides common structure to handle login events. 19 * 20 */ 21 class WarningsHandler extends DataHandler 22 { 23 /** 24 * The language file used in the data handler. 25 * 26 * @var string 27 */ 28 public $language_file = 'datahandler_warnings'; 29 30 /** 31 * The prefix for the language variables used in the data handler. 32 * 33 * @var string 34 */ 35 public $language_prefix = 'warnings'; 36 37 /** 38 * The stored data for the warning being written. 39 * 40 * @var array 41 */ 42 public $write_warning_data = array(); 43 44 /** 45 * The stored data for the warning being retrieved. 46 * 47 * @var array 48 */ 49 private $read_warning_data = array(); 50 51 /** 52 * Friendly redirect action after inserting a new warning. 53 * 54 * @var string 55 */ 56 public $friendly_action = ''; 57 58 /** 59 * Validate a warning user assets. 60 * 61 * @return boolean True when valid, false when invalid. 62 */ 63 function validate_user() 64 { 65 global $mybb; 66 67 $warning = &$this->data; 68 69 $user = get_user($warning['uid']); 70 71 if(!$user) 72 { 73 $this->set_error('error_invalid_user'); 74 return false; 75 } 76 77 if($user['uid'] == $mybb->user['uid']) 78 { 79 $this->set_error('error_cannot_warn_self'); 80 return false; 81 } 82 83 if($user['warningpoints'] >= $mybb->settings['maxwarningpoints']) 84 { 85 $this->set_error('error_user_reached_max_warning'); 86 return false; 87 } 88 89 return true; 90 } 91 92 /** 93 * Validate a warning post. 94 * 95 * @return boolean True when valid, false when invalid. 96 */ 97 function validate_post() 98 { 99 $warning = &$this->data; 100 101 $post = get_post($warning['pid']); 102 103 if(!$post) 104 { 105 $this->set_error('error_invalid_post'); 106 return false; 107 } 108 109 return true; 110 } 111 112 /** 113 * Validate a warning notes. 114 * 115 * @return boolean True when valid, false when invalid. 116 */ 117 function validate_notes() 118 { 119 $warning = &$this->data; 120 121 if(!trim($warning['notes'])) 122 { 123 $this->set_error('error_no_note'); 124 return false; 125 } 126 127 return true; 128 } 129 130 /** 131 * Validate maximum warnings per day for current user. 132 * 133 * @return boolean True when valid, false when invalid. 134 */ 135 function validate_maximum() 136 { 137 global $mybb, $db, $lang; 138 139 if($mybb->usergroup['maxwarningsday'] != 0) 140 { 141 $timecut = TIME_NOW-60*60*24; 142 $query = $db->simple_select("warnings", "COUNT(wid) AS given_today", "issuedby='{$mybb->user['uid']}' AND dateline>'$timecut'"); 143 $given_today = $db->fetch_field($query, "given_today"); 144 if($given_today >= $mybb->usergroup['maxwarningsday']) 145 { 146 $this->set_error('reached_max_warnings_day', array(my_number_format($mybb->usergroup['maxwarningsday']))); 147 return false; 148 } 149 } 150 151 return true; 152 } 153 154 /** 155 * Validate warnings type. 156 * 157 * @return boolean True when valid, false when invalid. 158 */ 159 function validate_type() 160 { 161 global $mybb, $db; 162 163 $warning = &$this->data; 164 165 // Issuing a custom warning 166 if($warning['type'] == 'custom') 167 { 168 if($mybb->settings['allowcustomwarnings'] == 0) 169 { 170 $this->set_error('error_cant_custom_warn'); 171 return false; 172 } 173 174 if(!$warning['custom_reason']) 175 { 176 $this->set_error('error_no_custom_reason'); 177 return false; 178 } 179 180 $warning['title'] = $warning['custom_reason']; 181 182 if(!$warning['custom_points'] || $warning['custom_points'] > $mybb->settings['maxwarningpoints'] || $warning['custom_points'] < 0) 183 { 184 $this->set_error('error_invalid_custom_points', array(my_number_format($mybb->settings['maxwarningpoints']))); 185 return false; 186 } 187 188 $warning['points'] = round($warning['custom_points']); 189 190 // Build expiry date 191 if($warning['expires_period'] == "hours") 192 { 193 $warning['expires'] = $warning['expires']*3600 + TIME_NOW; 194 } 195 else if($warning['expires_period'] == "days") 196 { 197 $warning['expires'] = $warning['expires']*86400 + TIME_NOW; 198 } 199 else if($warning['expires_period'] == "weeks") 200 { 201 $warning['expires'] = $warning['expires']*604800 + TIME_NOW; 202 } 203 else if($warning['expires_period'] == "months") 204 { 205 $warning['expires'] = $warning['expires']*2592000 + TIME_NOW; 206 } 207 else if($warning['expires_period'] == "never") 208 { 209 $warning['expires'] = 0; 210 } 211 else 212 { 213 // unkown expires_period 214 $this->set_error('error_invalid_expires_period'); 215 return false; 216 } 217 } 218 // Using a predefined warning type 219 else 220 { 221 $query = $db->simple_select("warningtypes", "*", "tid='".(int)$warning['type']."'"); 222 $this->warning_type = $db->fetch_array($query); 223 224 if(!$this->warning_type) 225 { 226 $this->set_error('error_invalid_type'); 227 return false; 228 } 229 230 $warning['points'] = $this->warning_type['points']; 231 $warning['title'] = ''; 232 $warning['expires'] = 0; 233 234 if($this->warning_type['expirationtime']) 235 { 236 $warning['expires'] = TIME_NOW+$this->warning_type['expirationtime']; 237 } 238 } 239 240 return true; 241 } 242 243 /** 244 * Validate a warning. 245 * 246 * @return boolean True when valid, false when invalid. 247 */ 248 function validate_warning() 249 { 250 global $plugins; 251 252 $warning = &$this->data; 253 254 // Verify all warning assets. 255 $this->validate_user(); 256 $this->validate_maximum(); 257 $this->validate_notes(); 258 259 if(array_key_exists('pid', $warning)) 260 { 261 $this->validate_post(); 262 } 263 if(array_key_exists('type', $warning)) 264 { 265 $this->validate_type(); 266 } 267 268 $plugins->run_hooks("datahandler_warnings_validate_warning", $this); 269 270 // We are done validating, return. 271 $this->set_validated(true); 272 273 if(count($this->get_errors()) > 0) 274 { 275 return false; 276 } 277 278 return true; 279 } 280 281 /** 282 * Gets a valid warning from the DB engine. 283 * 284 * @param int $wid 285 * @return array|bool array when valid, boolean false when invalid. 286 */ 287 function get($wid) 288 { 289 global $db; 290 291 $wid = (int)$wid; 292 if($wid <= 0) 293 { 294 return false; 295 } 296 297 $query = $db->simple_select("warnings", "*", "wid='".$wid."'"); 298 $this->read_warning_data = $db->fetch_array($query); 299 300 if(!$this->read_warning_data['wid']) 301 { 302 return false; 303 } 304 305 return $this->read_warning_data; 306 } 307 308 /** 309 * Expire old warnings in the database. 310 * 311 * @return boolean True when finished. 312 */ 313 function expire_warnings() 314 { 315 global $db; 316 317 $users = array(); 318 319 $query = $db->query(" 320 SELECT w.wid, w.uid, w.points, u.warningpoints 321 FROM ".TABLE_PREFIX."warnings w 322 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=w.uid) 323 WHERE expires<".TIME_NOW." AND expires!=0 AND expired!=1 324 "); 325 while($warning = $db->fetch_array($query)) 326 { 327 $updated_warning = array( 328 "expired" => 1 329 ); 330 $db->update_query("warnings", $updated_warning, "wid='{$warning['wid']}'"); 331 332 if(array_key_exists($warning['uid'], $users)) 333 { 334 $users[$warning['uid']] -= $warning['points']; 335 } 336 else 337 { 338 $users[$warning['uid']] = $warning['warningpoints']-$warning['points']; 339 } 340 } 341 342 foreach($users as $uid => $warningpoints) 343 { 344 if($warningpoints < 0) 345 { 346 $warningpoints = 0; 347 } 348 349 $updated_user = array( 350 "warningpoints" => (int)$warningpoints 351 ); 352 $db->update_query("users", $updated_user, "uid='".(int)$uid."'"); 353 } 354 355 return true; 356 } 357 358 /** 359 * Updates an user warning details. 360 * 361 * @return array Updated user details. 362 */ 363 function update_user($method='insert') 364 { 365 global $db, $mybb, $lang, $cache, $groupscache; 366 367 if($mybb->settings['maxwarningpoints'] < 1) 368 { 369 $mybb->settings['maxwarningpoints'] = 10; 370 } 371 372 if(!is_array($groupscache)) 373 { 374 $groupscache = $cache->read("usergroups"); 375 } 376 377 $warning = &$this->data; 378 379 $user = get_user($warning['uid']); 380 381 if($method == 'insert') 382 { 383 // Build warning level & ensure it doesn't go over 100. 384 $current_level = round($user['warningpoints']/$mybb->settings['maxwarningpoints']*100); 385 $this->new_warning_level = round(($user['warningpoints']+$warning['points'])/$mybb->settings['maxwarningpoints']*100); 386 if($this->new_warning_level > 100) 387 { 388 $this->new_warning_level = 100; 389 } 390 391 // Update user 392 $this->updated_user = array( 393 "warningpoints" => $user['warningpoints']+$warning['points'] 394 ); 395 396 // Fetch warning level 397 $query = $db->simple_select("warninglevels", "*", "percentage<={$this->new_warning_level}", array("order_by" => "percentage", "order_dir" => "desc")); 398 $new_level = $db->fetch_array($query); 399 400 if(!empty($new_level) && $new_level['lid']) 401 { 402 $expiration = 0; 403 $action = my_unserialize($new_level['action']); 404 405 if($action['length'] > 0) 406 { 407 $expiration = TIME_NOW+$action['length']; 408 } 409 410 switch($action['type']) 411 { 412 // Ban the user for a specified time 413 case 1: 414 // Fetch any previous bans for this user 415 $query = $db->simple_select("banned", "*", "uid='{$user['uid']}' AND gid='{$action['usergroup']}' AND lifted>".TIME_NOW); 416 $existing_ban = $db->fetch_array($query); 417 418 // Only perform if no previous ban or new ban expires later than existing ban 419 if(($expiration > $existing_ban['lifted'] && $existing_ban['lifted'] != 0) || $expiration == 0 || !$existing_ban['uid']) 420 { 421 if(!$warning['title']) 422 { 423 $warning['title'] = $this->warning_type['title']; 424 } 425 426 // Never lift the ban? 427 if($action['length'] <= 0) 428 { 429 $bantime = '---'; 430 } 431 else 432 { 433 $bantimes = fetch_ban_times(); 434 foreach($bantimes as $date => $string) 435 { 436 if($date == '---') 437 { 438 continue; 439 } 440 441 $time = 0; 442 list($day, $month, $year) = explode('-', $date); 443 if($day > 0) 444 { 445 $time += 60*60*24*$day; 446 } 447 448 if($month > 0) 449 { 450 $time += 60*60*24*30*$month; 451 } 452 453 if($year > 0) 454 { 455 $time += 60*60*24*365*$year; 456 } 457 458 if($time == $action['length']) 459 { 460 $bantime = $date; 461 break; 462 } 463 } 464 } 465 466 $new_ban = array( 467 "uid" => $user['uid'], 468 "gid" => $action['usergroup'], 469 "oldgroup" => $user['usergroup'], 470 "oldadditionalgroups" => $db->escape_string($user['additionalgroups']), 471 "olddisplaygroup" => $user['displaygroup'], 472 "admin" => $mybb->user['uid'], 473 "dateline" => TIME_NOW, 474 "bantime" => $db->escape_string($bantime), 475 "lifted" => $expiration, 476 "reason" => $db->escape_string($warning['title']) 477 ); 478 // Delete old ban for this user, taking details 479 if($existing_ban['uid']) 480 { 481 $db->delete_query("banned", "uid='{$user['uid']}' AND gid='{$action['usergroup']}'"); 482 // Override new ban details with old group info 483 $new_ban['oldgroup'] = $existing_ban['oldgroup']; 484 $new_ban['oldadditionalgroups'] = $db->escape_string($existing_ban['oldadditionalgroups']); 485 $new_ban['olddisplaygroup'] = $existing_ban['olddisplaygroup']; 486 } 487 488 $period = $lang->expiration_never; 489 $ban_length = fetch_friendly_expiration($action['length']); 490 491 if($ban_length['time']) 492 { 493 $lang_str = "expiration_".$ban_length['period']; 494 $period = $lang->sprintf($lang->result_period, $ban_length['time'], $lang->$lang_str); 495 } 496 497 $group_name = $groupscache[$action['usergroup']]['title']; 498 $this->friendly_action = $lang->sprintf($lang->redirect_warned_banned, $group_name, $period); 499 500 $db->insert_query("banned", $new_ban); 501 $this->updated_user['usergroup'] = $action['usergroup']; 502 $this->updated_user['additionalgroups'] = ''; 503 $this->updated_user['displaygroup'] = 0; 504 } 505 break; 506 // Suspend posting privileges 507 case 2: 508 // Only perform if the expiration time is greater than the users current suspension period 509 if($expiration == 0 || $expiration > $user['suspensiontime']) 510 { 511 if(($user['suspensiontime'] != 0 && $user['suspendposting']) || !$user['suspendposting']) 512 { 513 $period = $lang->expiration_never; 514 $ban_length = fetch_friendly_expiration($action['length']); 515 516 if($ban_length['time']) 517 { 518 $lang_str = "expiration_".$ban_length['period']; 519 $period = $lang->sprintf($lang->result_period, $ban_length['time'], $lang->$lang_str); 520 } 521 522 $this->friendly_action = $lang->sprintf($lang->redirect_warned_suspended, $period); 523 524 $this->updated_user['suspensiontime'] = $expiration; 525 $this->updated_user['suspendposting'] = 1; 526 } 527 } 528 break; 529 // Moderate new posts 530 case 3: 531 // Only perform if the expiration time is greater than the users current suspension period 532 if($expiration == 0 || $expiration > $user['moderationtime']) 533 { 534 if(($user['moderationtime'] != 0 && $user['moderateposts']) || !$user['suspendposting']) 535 { 536 $period = $lang->expiration_never; 537 $ban_length = fetch_friendly_expiration($action['length']); 538 539 if($ban_length['time']) 540 { 541 $lang_str = "expiration_".$ban_length['period']; 542 $period = $lang->sprintf($lang->result_period, $ban_length['time'], $lang->$lang_str); 543 } 544 545 $this->friendly_action = $lang->sprintf($lang->redirect_warned_moderate, $period); 546 547 $this->updated_user['moderationtime'] = $expiration; 548 $this->updated_user['moderateposts'] = 1; 549 } 550 } 551 break; 552 } 553 } 554 } 555 else 556 { 557 // Warning is still active, lower users point count 558 if($warning['expired'] != 1) 559 { 560 $new_warning_points = $user['warningpoints']-$warning['points']; 561 if($new_warning_points < 0) 562 { 563 $new_warning_points = 0; 564 } 565 566 $this->updated_user = array( 567 "warningpoints" => $new_warning_points 568 ); 569 570 571 // check if we need to revoke any consequences with this warning 572 $current_level = round($user['warningpoints']/$mybb->settings['maxwarningpoints']*100); 573 $this->new_warning_level = round($new_warning_points/$mybb->settings['maxwarningpoints']*100); 574 $query = $db->simple_select("warninglevels", "action", "percentage>{$this->new_warning_level} AND percentage<=$current_level"); 575 if($db->num_rows($query)) 576 { 577 // we have some warning levels we need to revoke 578 $max_expiration_times = $check_levels = array(); 579 find_warnlevels_to_check($query, $max_expiration_times, $check_levels); 580 581 // now check warning levels already applied to this user to see if we need to lower any expiration times 582 $query = $db->simple_select("warninglevels", "action", "percentage<={$this->new_warning_level}"); 583 $lower_expiration_times = $lower_levels = array(); 584 find_warnlevels_to_check($query, $lower_expiration_times, $lower_levels); 585 586 // now that we've got all the info, do necessary stuff 587 for($i = 1; $i <= 3; ++$i) 588 { 589 if($check_levels[$i]) 590 { 591 switch($i) 592 { 593 case 1: // Ban 594 // we'll have to resort to letting the admin/mod remove the ban manually, since there's an issue if stacked bans are in force... 595 continue 2; 596 case 2: // Revoke posting 597 $current_expiry_field = 'suspensiontime'; 598 $current_inforce_field = 'suspendposting'; 599 break; 600 case 3: 601 $current_expiry_field = 'moderationtime'; 602 $current_inforce_field = 'moderateposts'; 603 break; 604 } 605 606 // if the thing isn't in force, don't bother with trying to update anything 607 if(!$user[$current_inforce_field]) 608 { 609 continue; 610 } 611 612 if($lower_levels[$i]) 613 { 614 // lessen the expiration time if necessary 615 616 if(!$lower_expiration_times[$i]) 617 { 618 // doesn't expire - enforce this 619 $this->updated_user[$current_expiry_field] = 0; 620 continue; 621 } 622 623 if($max_expiration_times[$i]) 624 { 625 // if the old level did have an expiry time... 626 if($max_expiration_times[$i] <= $lower_expiration_times[$i]) 627 { 628 // if the lower expiration time is actually higher than the upper expiration time -> skip 629 continue; 630 } 631 // both new and old max expiry times aren't infinite, so we can take a difference 632 $expire_offset = ($lower_expiration_times[$i] - $max_expiration_times[$i]); 633 } 634 else 635 { 636 // the old level never expired, not much we can do but try to estimate a new expiry time... which will just happen to be starting from today... 637 $expire_offset = TIME_NOW + $lower_expiration_times[$i]; 638 // if the user's expiry time is already less than what we're going to set it to, skip 639 if($user[$current_expiry_field] <= $expire_offset) 640 { 641 continue; 642 } 643 } 644 645 $this->updated_user[$current_expiry_field] = $user[$current_expiry_field] + $expire_offset; 646 // double-check if it's expired already 647 if($this->updated_user[$current_expiry_field] < TIME_NOW) 648 { 649 $this->updated_user[$current_expiry_field] = 0; 650 $this->updated_user[$current_inforce_field] = 0; 651 } 652 } 653 else 654 { 655 // there's no lower level for this type - remove the consequence entirely 656 $this->updated_user[$current_expiry_field] = 0; 657 $this->updated_user[$current_inforce_field] = 0; 658 } 659 } 660 } 661 } 662 } 663 } 664 665 // Save updated details 666 $db->update_query("users", $this->updated_user, "uid='{$user['uid']}'"); 667 668 $mybb->cache->update_moderators(); 669 670 return $this->updated_user; 671 } 672 673 /** 674 * Inserts a warning into the database 675 * 676 * @return array Warning database details. 677 */ 678 function insert_warning() 679 { 680 global $db, $mybb, $plugins; 681 682 $warning = &$this->data; 683 684 $this->write_warning_data = array( 685 "uid" => (int)$warning['uid'], 686 "tid" => (int)$warning['type'], 687 "pid" => isset($warning['pid']) ? (int)$warning['pid'] : 0, 688 "title" => $db->escape_string($warning['title']), 689 "points" => (int)$warning['points'], 690 "dateline" => TIME_NOW, 691 "issuedby" => $mybb->user['uid'], 692 "expires" => (int)$warning['expires'], 693 "expired" => 0, 694 "revokereason" => '', 695 "notes" => $db->escape_string($warning['notes']) 696 ); 697 698 $this->write_warning_data['wid'] = $db->insert_query("warnings", $this->write_warning_data); 699 700 $this->update_user(); 701 702 $plugins->run_hooks("datahandler_warnings_insert_warning", $this); 703 704 return $this->write_warning_data; 705 } 706 707 /** 708 * Updates a warning in the database 709 * 710 * @return array Warning database details. 711 */ 712 function update_warning() 713 { 714 global $db, $mybb, $plugins; 715 716 $warning = &$this->data; 717 718 $warning['wid'] = (int)$warning['wid']; 719 if($warning['wid'] <= 0) 720 { 721 return false; 722 } 723 724 $this->write_warning_data = array( 725 "expired" => 1, 726 "daterevoked" => TIME_NOW, 727 "revokedby" => $mybb->user['uid'], 728 "revokereason" => $db->escape_string($warning['reason']) 729 ); 730 731 $plugins->run_hooks("datahandler_warnings_update_warning", $this); 732 733 $db->update_query("warnings", $this->write_warning_data, "wid='{$warning['wid']}'"); 734 735 $this->update_user('update'); 736 737 return $this->write_warning_data; 738 } 739 740 } 741
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup | Cross-referenced by PHPXref |