| [ Index ] |
PHP Cross Reference of MyBB 1.6.5 |
[Summary view] [Print] [Text view]
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 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Sun Dec 11 14:16:27 2011 | Cross-referenced by PHPXref 0.7.1 |