[ Index ]

PHP Cross Reference of MyBB 1.6.5

title

Body

[close]

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

   1  <?php
   2  /**
   3   * MyBB 1.6
   4   * Copyright 2010 MyBB Group, All Rights Reserved
   5   *
   6   * Website: http://mybb.com
   7   * License: http://mybb.com/about/license
   8   *
   9   * $Id: pm.php 5625 2011-10-02 19:16:35Z ralgith $
  10   */
  11  
  12  // Disallow direct access to this file for security reasons
  13  if(!defined("IN_MYBB"))
  14  {
  15      die("Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined.");
  16  }
  17  
  18  /**
  19   * PM handling class, provides common structure to handle private messaging data.
  20   *
  21   */
  22  class PMDataHandler extends DataHandler
  23  {
  24      /**
  25      * The language file used in the data handler.
  26      *
  27      * @var string
  28      */
  29      public $language_file = 'datahandler_pm';
  30  
  31      /**
  32      * The prefix for the language variables used in the data handler.
  33      *
  34      * @var string
  35      */
  36      public $language_prefix = 'pmdata';
  37      
  38      /**
  39       * Array of data inserted in to a private message.
  40       *
  41       * @var array
  42       */
  43      public $pm_insert_data = array();
  44  
  45      /**
  46       * Array of data used to update a private message.
  47       *
  48       * @var array
  49       */
  50      public $pm_update_data = array();
  51      
  52      /**
  53       * PM ID currently being manipulated by the datahandlers.
  54       */
  55      public $pmid = 0;    
  56  
  57      /**
  58       * Verifies a private message subject.
  59       *
  60       * @return boolean True when valid, false when invalid.
  61       */
  62  	function verify_subject()
  63      {
  64          $subject = &$this->data['subject'];
  65  
  66          // Subject is over 85 characters, too long.
  67          if(my_strlen($subject) > 85)
  68          {
  69              $this->set_error("too_long_subject");
  70              return false;
  71          }
  72          // No subject, apply the default [no subject]
  73          if(!trim_blank_chrs($subject))
  74          {
  75              $this->set_error("missing_subject");
  76              return false;
  77          }
  78          return true;
  79      }
  80  
  81      /**
  82       * Verifies if a message for a PM is valid.
  83       *
  84       * @return boolean True when valid, false when invalid.
  85       */
  86  	function verify_message()
  87      {
  88          $message = &$this->data['message'];
  89  
  90          // No message, return an error.
  91          if(trim_blank_chrs($message) == '')
  92          {
  93              $this->set_error("missing_message");
  94              return false;
  95          }
  96          return true;
  97      }
  98  
  99      /**
 100       * Verifies if the specified sender is valid or not.
 101       *
 102       * @return boolean True when valid, false when invalid.
 103       */
 104  	function verify_sender()
 105      {
 106          global $db, $mybb, $lang;
 107  
 108          $pm = &$this->data;
 109  
 110          // Return if we've already validated
 111          if($pm['sender']) return true;
 112  
 113          // Fetch the senders profile data.
 114          $sender = get_user($pm['fromid']);
 115  
 116          // Collect user permissions for the sender.
 117          $sender_permissions = user_permissions($pm['fromid']);
 118  
 119          // Check if the sender is over their quota or not - if they are, disable draft sending
 120          if($pm['options']['savecopy'] != 0 && !$pm['saveasdraft'])
 121          {
 122              if($sender_permissions['pmquota'] != "0" && $sender['totalpms'] >= $sender_permissions['pmquota'] && $this->admin_override != true)
 123              {
 124                  $pm['options']['savecopy'] = 0;
 125              }
 126          }
 127  
 128          // Assign the sender information to the data.
 129          $pm['sender'] = array(
 130              "uid" => $sender['uid'],
 131              "username" => $sender['username']
 132          );
 133  
 134          return true;
 135      }
 136  
 137      /**
 138       * Verifies if an array of recipients for a private message are valid
 139       *
 140       * @return boolean True when valid, false when invalid.
 141       */
 142  	function verify_recipient()
 143      {
 144          global $db, $mybb, $lang;
 145  
 146          $pm = &$this->data;
 147  
 148          $recipients = array();
 149  
 150          $invalid_recipients = array();
 151          // We have our recipient usernames but need to fetch user IDs
 152          if(array_key_exists("to", $pm))
 153          {
 154              if((count($pm['to']) <= 0 || trim(implode("", $pm['to'])) == "") && !$pm['saveasdraft'])
 155              {
 156                  $this->set_error("no_recipients");
 157                  return false;
 158              }
 159  
 160              foreach(array("to", "bcc") as $recipient_type)
 161              {
 162                  if(!is_array($pm[$recipient_type]))
 163                  {
 164                      $pm[$recipient_type] = array($pm[$recipient_type]);
 165                  }
 166                  foreach($pm[$recipient_type] as $username)
 167                  {
 168                      $username = trim($username);
 169                      if(empty($username))
 170                      {
 171                          continue;
 172                      }
 173                      // Check that this recipient actually exists
 174                      $query = $db->simple_select("users", "*", "username='".$db->escape_string($username)."'");
 175                      $user = $db->fetch_array($query);
 176                      if($recipient_type == "bcc")
 177                      {
 178                          $user['bcc'] = 1;
 179                      }
 180                      if($user['uid'])
 181                      {
 182                          $recipients[] = $user;
 183                      }
 184                      else
 185                      {
 186                          $invalid_recipients[] = $username;
 187                      }
 188                  }
 189              }
 190          }
 191          // We have recipient IDs
 192          else
 193          {
 194              foreach(array("toid", "bccid") as $recipient_type)
 195              {
 196                  if(count($pm['toid']) <= 0)
 197                  {
 198                      $this->set_error("no_recipients");
 199                      return false;
 200                  }
 201                  if(is_array($pm[$recipient_type]))
 202                  {
 203                      foreach($pm[$recipient_type] as $uid)
 204                      {
 205                          // Check that this recipient actually exists
 206                          $query = $db->simple_select("users", "*", "uid='".intval($uid)."'");
 207                          $user = $db->fetch_array($query);
 208                          if($recipient_type == "bccid")
 209                          {
 210                              $user['bcc'] = 1;
 211                          }
 212                          if($user['uid'])
 213                          {
 214                              $recipients[] = $user;
 215                          }
 216                          else
 217                          {
 218                              $invalid_recipients[] = $uid;
 219                          }
 220                      }
 221                  }
 222              }
 223          }
 224  
 225          // If we have one or more invalid recipients and we're not saving a draft, error
 226          if(count($invalid_recipients) > 0)
 227          {
 228              $invalid_recipients = implode(", ", array_map("htmlspecialchars_uni", $invalid_recipients));
 229              $this->set_error("invalid_recipients", array($invalid_recipients));
 230              return false;
 231          }
 232  
 233          $sender_permissions = user_permissions($pm['fromid']);
 234  
 235          // Are we trying to send this message to more users than the permissions allow?
 236          if($sender_permissions['maxpmrecipients'] > 0 && count($recipients) > $sender_permissions['maxpmrecipients'] && $this->admin_override != true)
 237          {
 238              $this->set_error("too_many_recipients", array($sender_permissions['maxpmrecipients']));
 239          }
 240  
 241          // Now we're done with that we loop through each recipient
 242          foreach($recipients as $user)
 243          {
 244              // Collect group permissions for this recipient.
 245              $recipient_permissions = user_permissions($user['uid']);
 246      
 247              // See if the sender is on the recipients ignore list and that either
 248              // - admin_override is set or
 249              // - sender is an administrator
 250              if(($this->admin_override != true && $sender_permissions['cancp'] != 1) && $sender_permissions['canoverridepm'] != 1)
 251              {
 252                  $ignorelist = explode(",", $user['ignorelist']);
 253                  if(!empty($ignorelist) && in_array($pm['fromid'], $ignorelist))
 254                  {
 255                      $this->set_error("recipient_is_ignoring", array($user['username']));
 256                  }
 257                  
 258                  // Is the recipient only allowing private messages from their buddy list?
 259                  if($mybb->settings['allowbuddyonly'] == 1 && $user['receivefrombuddy'] == 1)
 260                  {
 261                      $buddylist = explode(",", $user['buddylist']);
 262                      if(!empty($buddylist) && !in_array($pm['fromid'], $buddylist))
 263                      {
 264                          $this->set_error("recipient_has_buddy_only", array(htmlspecialchars_uni($user['username'])));
 265                      }
 266                  }
 267                  
 268                  // Can the recipient actually receive private messages based on their permissions or user setting?
 269                  if(($user['receivepms'] == 0 || $recipient_permissions['canusepms'] == 0) && !$pm['saveasdraft'])
 270                  {
 271                      $this->set_error("recipient_pms_disabled", array($user['username']));
 272                      return false;
 273                  }
 274              }
 275      
 276              // Check to see if the user has reached their private message quota - if they have, email them.
 277              if($recipient_permissions['pmquota'] != "0" && $user['totalpms'] >= $recipient_permissions['pmquota'] && $recipient_permissions['cancp'] != 1 && $sender_permissions['cancp'] != 1 && !$pm['saveasdraft'] && !$this->admin_override)
 278              {
 279                  if(trim($user['language']) != '' && $lang->language_exists($user['language']))
 280                  {
 281                      $uselang = trim($user['language']);
 282                  }
 283                  elseif($mybb->settings['bblanguage'])
 284                  {
 285                      $uselang = $mybb->settings['bblanguage'];
 286                  }
 287                  else
 288                  {
 289                      $uselang = "english";
 290                  }
 291                  if($uselang == $mybb->settings['bblanguage'] || !$uselang)
 292                  {
 293                      $emailsubject = $lang->emailsubject_reachedpmquota;
 294                      $emailmessage = $lang->email_reachedpmquota;
 295                  }
 296                  else
 297                  {
 298                      $userlang = new MyLanguage;
 299                      $userlang->set_path(MYBB_ROOT."inc/languages");
 300                      $userlang->set_language($uselang);
 301                      $userlang->load("messages");
 302                      $emailsubject = $userlang->emailsubject_reachedpmquota;
 303                      $emailmessage = $userlang->email_reachedpmquota;
 304                  }
 305                  $emailmessage = $lang->sprintf($emailmessage, $user['username'], $mybb->settings['bbname'], $mybb->settings['bburl']);
 306                  $emailsubject = $lang->sprintf($emailsubject, $mybb->settings['bbname']);
 307                  my_mail($user['email'], $emailsubject, $emailmessage);
 308      
 309                  if($this->admin_override != true)
 310                  {
 311                      $this->set_error("recipient_reached_quota", array($user['username']));
 312                  }
 313              }
 314      
 315              // Everything looks good, assign some specifics about the recipient
 316              $pm['recipients'][$user['uid']] = array(
 317                  "uid" => $user['uid'],
 318                  "username" => $user['username'],
 319                  "email" => $user['email'],
 320                  "lastactive" => $user['lastactive'],
 321                  "pmnotice" => $user['pmnotice'],
 322                  "pmnotify" => $user['pmnotify'],
 323                  "language" => $user['language']
 324              );
 325              
 326              // If this recipient is defined as a BCC recipient, save it
 327              if($user['bcc'] == 1)
 328              {
 329                  $pm['recipients'][$user['uid']]['bcc'] = 1;
 330              }
 331          }
 332          return true;
 333      }
 334      
 335      /**
 336      * Verify that the user is not flooding the system.
 337      *
 338      * @return boolean True
 339      */
 340  	function verify_pm_flooding()
 341      {
 342          global $mybb, $db;
 343  
 344          $pm = &$this->data;
 345          
 346          // Check if post flooding is enabled within MyBB or if the admin override option is specified.
 347          if($mybb->settings['pmfloodsecs'] > 0 && $pm['fromid'] != 0 && $this->admin_override == false)
 348          {
 349              // Fetch the senders profile data.
 350              $sender = get_user($pm['fromid']);
 351              
 352              // Calculate last post
 353              $query = $db->simple_select("privatemessages", "dateline", "fromid='".$db->escape_string($pm['fromid'])."' AND toid != '0'", array('order_by' => 'dateline', 'order_dir' => 'desc', 'limit' => 1));
 354              $sender['lastpm'] = $db->fetch_field($query, "dateline");
 355  
 356              // A little bit of calculation magic and moderator status checking.
 357              if(TIME_NOW-$sender['lastpm'] <= $mybb->settings['pmfloodsecs'] && !is_moderator("", "", $pm['fromid']))
 358              {
 359                  // Oops, user has been flooding - throw back error message.
 360                  $time_to_wait = ($mybb->settings['pmfloodsecs'] - (TIME_NOW-$sender['lastpm'])) + 1;
 361                  if($time_to_wait == 1)
 362                  {
 363                      $this->set_error("pm_flooding_one_second");
 364                  }
 365                  else
 366                  {
 367                      $this->set_error("pm_flooding", array($time_to_wait));
 368                  }
 369                  return false;
 370              }
 371          }
 372          // All is well that ends well - return true.
 373          return true;
 374      }
 375  
 376      /**
 377       * Verifies if the various 'options' for sending PMs are valid.
 378       *
 379       * @return boolean True when valid, false when invalid.
 380       */
 381  	function verify_options()
 382      {
 383          $options = &$this->data['options'];
 384  
 385          $this->verify_yesno_option($options, 'signature', 1);
 386          $this->verify_yesno_option($options, 'savecopy', 1);
 387          $this->verify_yesno_option($options, 'disablesmilies', 0);
 388  
 389          // Requesting a read receipt?
 390          if(isset($options['readreceipt']) && $options['readreceipt'] == 1)
 391          {
 392              $options['readreceipt'] = 1;
 393          }
 394          else
 395          {
 396              $options['readreceipt'] = 0;
 397          }
 398          return true;
 399      }
 400  
 401      /**
 402       * Validate an entire private message.
 403       *
 404       * @return boolean True when valid, false when invalid.
 405       */
 406  	function validate_pm()
 407      {
 408          global $plugins;
 409  
 410          $pm = &$this->data;
 411          
 412          if(!$pm['savedraft'])
 413          {
 414              $this->verify_pm_flooding();
 415          }
 416  
 417          // Verify all PM assets.
 418          $this->verify_subject();
 419  
 420          $this->verify_sender();
 421  
 422          $this->verify_recipient();
 423          
 424          $this->verify_message();
 425  
 426          $this->verify_options();
 427  
 428          $plugins->run_hooks_by_ref("datahandler_pm_validate", $this);
 429  
 430          // Choose the appropriate folder to save in.
 431          if($pm['saveasdraft'])
 432          {
 433              $pm['folder'] = 3;
 434          }
 435          else
 436          {
 437              $pm['folder'] = 1;
 438          }
 439  
 440          // We are done validating, return.
 441          $this->set_validated(true);
 442          if(count($this->get_errors()) > 0)
 443          {
 444              return false;
 445          }
 446          else
 447          {
 448              return true;
 449          }
 450      }
 451  
 452      /**
 453       * Insert a new private message.
 454       *
 455       * @return array Array of PM useful data.
 456       */
 457  	function insert_pm()
 458      {
 459          global $db, $mybb, $plugins, $lang;
 460  
 461          // Yes, validating is required.
 462          if(!$this->get_validated())
 463          {
 464              die("The PM needs to be validated before inserting it into the DB.");
 465          }
 466          if(count($this->get_errors()) > 0)
 467          {
 468              die("The PM is not valid.");
 469          }
 470  
 471          // Assign data to common variable
 472          $pm = &$this->data;
 473  
 474          $pm['pmid'] = intval($pm['pmid']);
 475  
 476          if(!$pm['icon'] || $pm['icon'] < 0)
 477          {
 478              $pm['icon'] = 0;
 479          }
 480  
 481          $uid = 0;
 482  
 483          if(!is_array($pm['recipients']))
 484          {
 485              $recipient_list = array();
 486          }
 487          else
 488          {
 489              // Build recipient list
 490              foreach($pm['recipients'] as $recipient)
 491              {
 492                  if($recipient['bcc'])
 493                  {
 494                      $recipient_list['bcc'][] = $recipient['uid'];
 495                  }
 496                  else
 497                  {
 498                      $recipient_list['to'][] = $recipient['uid'];
 499                      $uid = $recipient['uid'];
 500                  }
 501              }
 502          }
 503          $recipient_list = serialize($recipient_list);
 504  
 505          $this->pm_insert_data = array(
 506              'fromid' => intval($pm['sender']['uid']),
 507              'folder' => $pm['folder'],
 508              'subject' => $db->escape_string($pm['subject']),
 509              'icon' => intval($pm['icon']),
 510              'message' => $db->escape_string($pm['message']),
 511              'dateline' => TIME_NOW,
 512              'status' => 0,
 513              'includesig' => $pm['options']['signature'],
 514              'smilieoff' => $pm['options']['disablesmilies'],
 515              'receipt' => intval($pm['options']['readreceipt']),
 516              'readtime' => 0,
 517              'recipients' => $db->escape_string($recipient_list)
 518          );
 519  
 520          // Check if we're updating a draft or not.
 521          $query = $db->simple_select("privatemessages", "pmid, deletetime", "folder='3' AND uid='".intval($pm['sender']['uid'])."' AND pmid='{$pm['pmid']}'");
 522          $draftcheck = $db->fetch_array($query);
 523  
 524          // This PM was previously a draft
 525          if($draftcheck['pmid'])
 526          {
 527              if($draftcheck['deletetime'])
 528              {
 529                  // This draft was a reply to a PM
 530                  $pm['pmid'] = $draftcheck['deletetime'];
 531                  $pm['do'] = "reply";
 532              }
 533  
 534              // Delete the old draft as we no longer need it
 535              $db->delete_query("privatemessages", "pmid='{$draftcheck['pmid']}'");
 536          }
 537  
 538          // Saving this message as a draft
 539          if($pm['saveasdraft'])
 540          {
 541              $this->pm_insert_data['uid'] = $pm['sender']['uid'];
 542  
 543              // If this is a reply, then piggyback into the deletetime to let us know in the future
 544              if($pm['do'] == "reply" || $pm['do'] == "replyall")
 545              {
 546                  $this->pm_insert_data['deletetime'] = $pm['pmid'];
 547              }
 548  
 549              $plugins->run_hooks_by_ref("datahandler_pm_insert_updatedraft", $this);
 550              $db->insert_query("privatemessages", $this->pm_insert_data);
 551  
 552              // If this is a draft, end it here - below deals with complete messages
 553              return array(
 554                  "draftsaved" => 1
 555              );
 556          }
 557  
 558          // Save a copy of the PM for each of our recipients
 559          foreach($pm['recipients'] as $recipient)
 560          {
 561              // Send email notification of new PM if it is enabled for the recipient
 562              $query = $db->simple_select("privatemessages", "dateline", "uid='".$recipient['uid']."' AND folder='1'", array('order_by' => 'dateline', 'order_dir' => 'desc', 'limit' => 1));
 563              $lastpm = $db->fetch_array($query);
 564              if($recipient['pmnotify'] == 1 && $recipient['lastactive'] > $lastpm['dateline'])
 565              {
 566                  if($recipient['language'] != "" && $lang->language_exists($recipient['language']))
 567                  {
 568                      $uselang = $recipient['language'];
 569                  }
 570                  elseif($mybb->settings['bblanguage'])
 571                  {
 572                      $uselang = $mybb->settings['bblanguage'];
 573                  }
 574                  else
 575                  {
 576                      $uselang = "english";
 577                  }
 578                  if($uselang == $mybb->settings['bblanguage'] && !empty($lang->emailsubject_newpm))
 579                  {
 580                      $emailsubject = $lang->emailsubject_newpm;
 581                      $emailmessage = $lang->email_newpm;
 582                  }
 583                  else
 584                  {
 585                      $userlang = new MyLanguage;
 586                      $userlang->set_path(MYBB_ROOT."inc/languages");
 587                      $userlang->set_language($uselang);
 588                      $userlang->load("messages");
 589                      $emailsubject = $userlang->emailsubject_newpm;
 590                      $emailmessage = $userlang->email_newpm;
 591                  }
 592                  
 593                  if(!$pm['sender']['username'])
 594                  {
 595                      $pm['sender']['username'] = $lang->mybb_engine;
 596                  }
 597                  
 598                  $emailmessage = $lang->sprintf($emailmessage, $recipient['username'], $pm['sender']['username'], $mybb->settings['bbname'], $mybb->settings['bburl']);
 599                  $emailsubject = $lang->sprintf($emailsubject, $mybb->settings['bbname']);
 600                  my_mail($recipient['email'], $emailsubject, $emailmessage);
 601              }
 602  
 603              $this->pm_insert_data['uid'] = $recipient['uid'];
 604              $this->pm_insert_data['toid'] = $recipient['uid'];
 605  
 606              $plugins->run_hooks_by_ref("datahandler_pm_insert", $this);
 607              $this->pmid = $db->insert_query("privatemessages", $this->pm_insert_data);
 608  
 609              // If PM noices/alerts are on, show!
 610              if($recipient['pmnotice'] == 1)
 611              {
 612                  $updated_user = array(
 613                      "pmnotice" => 2
 614                  );
 615                  $db->update_query("users", $updated_user, "uid='{$recipient['uid']}'");
 616              }
 617  
 618              // Update private message count (total, new and unread) for recipient
 619              require_once  MYBB_ROOT."/inc/functions_user.php";
 620              update_pm_count($recipient['uid'], 7, $recipient['lastactive']);
 621          }
 622  
 623          // Are we replying or forwarding an existing PM?
 624          if($pm['pmid'])
 625          {
 626              if($pm['do'] == "reply" || $pm['do'] == "replyall")
 627              {
 628                  $sql_array = array(
 629                      'status' => 3,
 630                      'statustime' => TIME_NOW
 631                  );
 632                  $db->update_query("privatemessages", $sql_array, "pmid={$pm['pmid']} AND uid={$pm['sender']['uid']}");
 633              }
 634              elseif($pm['do'] == "forward")
 635              {
 636                  $sql_array = array(
 637                      'status' => 4,
 638                      'statustime' => TIME_NOW
 639                  );
 640                  $db->update_query("privatemessages", $sql_array, "pmid={$pm['pmid']} AND uid={$pm['sender']['uid']}");
 641              }
 642          }
 643  
 644          // If we're saving a copy
 645          if($pm['options']['savecopy'] != 0)
 646          {
 647              if(count($recipient_list['to']) == 1)
 648              {
 649                  $this->pm_insert_data['toid'] = $uid;
 650              }
 651              else
 652              {
 653                  $this->pm_insert_data['toid'] = 0;
 654              }
 655              $this->pm_insert_data['uid'] = intval($pm['sender']['uid']);
 656              $this->pm_insert_data['folder'] = 2;
 657              $this->pm_insert_data['status'] = 1;
 658              $this->pm_insert_data['receipt'] = 0;
 659  
 660              $plugins->run_hooks_by_ref("datahandler_pm_insert_savedcopy", $this);
 661              $db->insert_query("privatemessages", $this->pm_insert_data);
 662  
 663              // Because the sender saved a copy, update their total pm count
 664              require_once  MYBB_ROOT."/inc/functions_user.php";
 665              update_pm_count($pm['sender']['uid'], 1);
 666          }
 667  
 668          // Return back with appropriate data
 669          return array(
 670              "messagesent" => 1
 671          );
 672      }
 673  }
 674  ?>


Generated: Sun Dec 11 14:16:27 2011 Cross-referenced by PHPXref 0.7.1