[ Index ]

PHP Cross Reference of MyBB 1.8.27

title

Body

[close]

/inc/datahandlers/ -> warnings.php (source)

   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['uid'])
  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['pid'])
 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" => (int)$warning['pid'],
 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  


2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup Cross-referenced by PHPXref