[ Index ] |
PHP Cross Reference of MyBB 1.8.33 |
[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 EXAMPLE USE: 19 20 $post = get from POST data 21 $thread = get from DB using POST data id 22 23 $postHandler = new postDataHandler(); 24 if($postHandler->validate_post($post)) 25 { 26 $postHandler->insert_post($post); 27 } 28 29 */ 30 31 /** 32 * Post handling class, provides common structure to handle post data. 33 * 34 */ 35 class PostDataHandler extends DataHandler 36 { 37 /** 38 * The language file used in the data handler. 39 * 40 * @var string 41 */ 42 public $language_file = 'datahandler_post'; 43 44 /** 45 * The prefix for the language variables used in the data handler. 46 * 47 * @var string 48 */ 49 public $language_prefix = 'postdata'; 50 51 /** 52 * What are we performing? 53 * post = New post 54 * thread = New thread 55 * edit = Editing a thread or post 56 * 57 * @var string 58 */ 59 public $action; 60 61 /** 62 * Array of data inserted in to a post. 63 * 64 * @var array 65 */ 66 public $post_insert_data = array(); 67 68 /** 69 * Array of data used to update a post. 70 * 71 * @var array 72 */ 73 public $post_update_data = array(); 74 75 /** 76 * Post ID currently being manipulated by the datahandlers. 77 * 78 * @var int 79 */ 80 public $pid = 0; 81 82 /** 83 * Array of data inserted in to a thread. 84 * 85 * @var array 86 */ 87 public $thread_insert_data = array(); 88 89 /** 90 * Array of data used to update a thread. 91 * 92 * @var array 93 */ 94 public $thread_update_data = array(); 95 96 /** 97 * Thread ID currently being manipulated by the datahandlers. 98 * 99 * @var int 100 */ 101 public $tid = 0; 102 103 /** 104 * Values to be returned after inserting/updating a post/thread. 105 * 106 * @var array 107 */ 108 public $return_values = array(); 109 110 /** 111 * Is this the first post of a thread when editing 112 * 113 * @var boolean 114 */ 115 public $first_post = false; 116 117 /** 118 * Verifies the author of a post and fetches the username if necessary. 119 * 120 * @return boolean True if the author information is valid, false if invalid. 121 */ 122 function verify_author() 123 { 124 global $mybb, $lang; 125 126 $post = &$this->data; 127 128 // Don't have a user ID at all - not good (note, a user id of 0 will still work). 129 if(!isset($post['uid'])) 130 { 131 $this->set_error("invalid_user_id"); 132 return false; 133 } 134 // If we have a user id but no username then fetch the username. 135 else if($post['uid'] > 0 && empty($post['username'])) 136 { 137 $user = get_user($post['uid']); 138 $post['username'] = $user['username']; 139 } 140 // if the uid is 0 verify the username 141 else if($post['uid'] == 0 && $post['username'] != '') 142 { 143 // Set up user handler 144 require_once MYBB_ROOT."inc/datahandlers/user.php"; 145 $userhandler = new UserDataHandler(); 146 147 $data_array = array('username' => $post['username']); 148 $userhandler->set_data($data_array); 149 150 if(!$userhandler->verify_username()) 151 { 152 // invalid username 153 $this->errors = array_merge($this->errors, $userhandler->get_errors()); 154 return false; 155 } 156 157 if($userhandler->verify_username_exists()) 158 { 159 // username is in use 160 $this->errors = array_merge($this->errors, $userhandler->get_errors()); 161 return false; 162 } 163 } 164 165 return true; 166 } 167 168 /** 169 * Verifies a post subject. 170 * 171 * @return boolean True when valid, false when not valid. 172 */ 173 function verify_subject() 174 { 175 global $db; 176 $post = &$this->data; 177 $subject = &$post['subject']; 178 $subject = trim_blank_chrs($subject); 179 180 if($this->method == "update" && $post['pid']) 181 { 182 // If this is the first post there needs to be a subject, else make it the default one. 183 if(my_strlen($subject) == 0 && $this->first_post) 184 { 185 $this->set_error("firstpost_no_subject"); 186 return false; 187 } 188 elseif(my_strlen($subject) == 0) 189 { 190 $thread = get_thread($post['tid']); 191 $subject = "RE: ".$thread['subject']; 192 } 193 } 194 195 // This is a new post 196 else if($this->action == "post") 197 { 198 if(my_strlen($subject) == 0) 199 { 200 $thread = get_thread($post['tid']); 201 $subject = "RE: ".$thread['subject']; 202 } 203 } 204 205 // This is a new thread and we require that a subject is present. 206 else 207 { 208 if(my_strlen($subject) == 0) 209 { 210 $this->set_error("missing_subject"); 211 return false; 212 } 213 } 214 215 // If post is reply and begins with "RE: ", remove 4 from subject length. 216 $subject_length = my_strlen($subject); 217 if($this->action == "post") 218 { 219 $position_re = my_strpos($subject, "RE: "); 220 if($position_re !== false && $position_re == 0) 221 { 222 $subject_length = $subject_length - 4; 223 } 224 } 225 226 if($subject_length > 85) 227 { 228 // Subject is too long 229 $this->set_error('subject_too_long', my_strlen($subject)); 230 return false; 231 } 232 233 // Subject is valid - return true. 234 return true; 235 } 236 237 /** 238 * Verifies a post message. 239 * 240 * @return bool 241 */ 242 function verify_message() 243 { 244 global $db, $mybb; 245 246 $post = &$this->data; 247 $post['message'] = trim_blank_chrs($post['message']); 248 249 // Do we even have a message at all? 250 if(my_strlen($post['message']) == 0) 251 { 252 $this->set_error("missing_message"); 253 return false; 254 } 255 else 256 { 257 $limit = (int)$mybb->settings['maxmessagelength']; 258 $dblimit = 0; 259 260 // If database is mysql or mysqli check field type and set max database limit 261 if(stripos($db->type, 'my') !== false) 262 { 263 $fields = $db->show_fields_from("posts"); 264 $type = $fields[array_search('message', array_column($fields, 'Field'))]['Type']; 265 switch(strtolower($type)) 266 { 267 case 'longtext': 268 $dblimit = 4294967295; 269 break; 270 case 'mediumtext': 271 $dblimit = 16777215; 272 break; 273 case 'text': 274 default: 275 $dblimit = 65535; 276 break; 277 } 278 } 279 280 if($limit > 0 || $dblimit > 0) 281 { 282 if(isset($post['fid'])) 283 { 284 $fid = $post['fid']; 285 } 286 else 287 { 288 $fid = 0; 289 } 290 if(isset($post['uid'])) 291 { 292 $uid = $post['uid']; 293 } 294 else 295 { 296 $uid = 0; 297 } 298 299 $is_moderator = is_moderator($fid, "", $uid); 300 // Consider minimum in user defined and database limit other than 0 301 if($limit > 0 && $dblimit > 0) 302 { 303 $limit = $is_moderator ? $dblimit : min($limit, $dblimit); 304 } 305 else 306 { 307 $limit = max($limit, $dblimit); 308 } 309 310 if(strlen($post['message']) > $limit && (!$is_moderator || $limit == $dblimit)) 311 { 312 $this->set_error("message_too_long", array($limit, strlen($post['message']))); 313 return false; 314 } 315 } 316 317 if(!isset($post['fid'])) 318 { 319 $post['fid'] = 0; 320 } 321 322 if(!$mybb->settings['mycodemessagelength']) 323 { 324 // Check to see of the text is full of MyCode 325 require_once MYBB_ROOT."inc/class_parser.php"; 326 $parser = new postParser; 327 328 $message = $parser->text_parse_message($post['message']); 329 330 if(my_strlen($message) < $mybb->settings['minmessagelength'] && $mybb->settings['minmessagelength'] > 0 && !is_moderator($post['fid'], "", $post['uid'])) 331 { 332 $this->set_error("message_too_short", array($mybb->settings['minmessagelength'])); 333 return false; 334 } 335 } 336 else if(my_strlen($post['message']) < $mybb->settings['minmessagelength'] && $mybb->settings['minmessagelength'] > 0 && !is_moderator($post['fid'], "", $post['uid'])) 337 { 338 $this->set_error("message_too_short", array($mybb->settings['minmessagelength'])); 339 return false; 340 } 341 } 342 return true; 343 } 344 345 /** 346 * Verifies the specified post options are correct. 347 * 348 * @return boolean True 349 */ 350 function verify_options() 351 { 352 $options = &$this->data['options']; 353 354 // Verify yes/no options. 355 $this->verify_yesno_option($options, 'signature', 0); 356 $this->verify_yesno_option($options, 'disablesmilies', 0); 357 358 return true; 359 } 360 361 /** 362 * Verify that the user is not flooding the system. 363 * 364 * @return boolean 365 */ 366 function verify_post_flooding() 367 { 368 global $mybb; 369 370 $post = &$this->data; 371 372 // Check if post flooding is enabled within MyBB or if the admin override option is specified. 373 if($mybb->settings['postfloodcheck'] == 1 && $post['uid'] != 0 && $this->admin_override == false) 374 { 375 if($this->verify_post_merge(true) !== true) 376 { 377 return true; 378 } 379 380 // Fetch the user information for this post - used to check their last post date. 381 $user = get_user($post['uid']); 382 383 // A little bit of calculation magic and moderator status checking. 384 if(TIME_NOW-$user['lastpost'] <= $mybb->settings['postfloodsecs'] && !is_moderator($post['fid'], "", $user['uid'])) 385 { 386 // Oops, user has been flooding - throw back error message. 387 $time_to_wait = ($mybb->settings['postfloodsecs'] - (TIME_NOW-$user['lastpost'])) + 1; 388 if($time_to_wait == 1) 389 { 390 $this->set_error("post_flooding_one_second"); 391 } 392 else 393 { 394 $this->set_error("post_flooding", array($time_to_wait)); 395 } 396 return false; 397 } 398 } 399 // All is well that ends well - return true. 400 return true; 401 } 402 403 /** 404 * @param bool $simple_mode 405 * 406 * @return array|bool 407 */ 408 function verify_post_merge($simple_mode=false) 409 { 410 global $mybb, $db, $session; 411 412 $post = &$this->data; 413 414 // Are we starting a new thread? 415 if(empty($post['tid'])) 416 { 417 return true; 418 } 419 420 // Are we even turned on? 421 if(empty($mybb->settings['postmergemins'])) 422 { 423 return true; 424 } 425 426 // Assign a default separator if none is specified 427 if(trim($mybb->settings['postmergesep']) == "") 428 { 429 $mybb->settings['postmergesep'] = "[hr]"; 430 } 431 432 // Check to see if this person is in a usergroup that is excluded 433 if(is_member($mybb->settings['postmergeuignore'], $post['uid'])) 434 { 435 return true; 436 } 437 438 // Select the lastpost and fid information for this thread 439 $query = $db->simple_select("threads", "lastpost,fid", "lastposteruid='".$post['uid']."' AND tid='".$post['tid']."'", array('limit' => '1')); 440 $thread = $db->fetch_array($query); 441 442 // Check to see if the same author has posted within the merge post time limit 443 if( 444 !$thread || ( 445 ((int)$mybb->settings['postmergemins'] != 0 && trim($mybb->settings['postmergemins']) != "") && 446 (TIME_NOW-$thread['lastpost']) > ((int)$mybb->settings['postmergemins']*60) 447 ) 448 ) 449 { 450 return true; 451 } 452 453 if($mybb->settings['postmergefignore'] == -1) 454 { 455 return true; 456 } 457 elseif($mybb->settings['postmergefignore'] != '') 458 { 459 $fids = explode(',', (string)$mybb->settings['postmergefignore']); 460 461 if(is_array($fids)) 462 { 463 foreach($fids as &$fid) 464 { 465 $fid = (int)$fid; 466 } 467 unset($fid); 468 469 if(in_array($thread['fid'], $fids)) 470 { 471 return true; 472 } 473 } 474 } 475 476 if($simple_mode == true) 477 { 478 return false; 479 } 480 481 if(!empty($post['uid'])) 482 { 483 $user_check = "uid='".$post['uid']."'"; 484 } 485 else 486 { 487 $user_check = "ipaddress=".$db->escape_binary($session->packedip); 488 } 489 490 $query = $db->simple_select("posts", "pid,message,visible", "{$user_check} AND tid='".$post['tid']."' AND dateline='".$thread['lastpost']."'", array('order_by' => 'pid', 'order_dir' => 'DESC', 'limit' => 1)); 491 return $db->fetch_array($query); 492 } 493 494 /** 495 * Verifies the image count. 496 * 497 * @return boolean True when valid, false when not valid. 498 */ 499 function verify_image_count() 500 { 501 global $mybb, $db; 502 503 $post = &$this->data; 504 505 if(isset($post['uid'])) 506 { 507 $uid = $post['uid']; 508 } 509 else 510 { 511 $uid = null; 512 } 513 514 // Get the permissions of the user who is making this post or thread 515 $permissions = user_permissions($uid); 516 517 // Fetch the forum this post is being made in 518 if(!$post['fid']) 519 { 520 $query = $db->simple_select('posts', 'fid', "pid = '{$post['pid']}'"); 521 $post['fid'] = $db->fetch_field($query, 'fid'); 522 } 523 $forum = get_forum($post['fid']); 524 525 // Check if this post contains more images than the forum allows 526 if((!isset($post['savedraft']) || $post['savedraft'] != 1) && $mybb->settings['maxpostimages'] != 0 && $permissions['cancp'] != 1) 527 { 528 require_once MYBB_ROOT."inc/class_parser.php"; 529 $parser = new postParser; 530 531 // Parse the message. 532 $parser_options = array( 533 "allow_html" => $forum['allowhtml'], 534 "allow_mycode" => $forum['allowmycode'], 535 "allow_imgcode" => $forum['allowimgcode'], 536 "allow_videocode" => $forum['allowvideocode'], 537 "filter_badwords" => 1 538 ); 539 540 if(empty($post['options']['disablesmilies'])) 541 { 542 $parser_options['allow_smilies'] = $forum['allowsmilies']; 543 } 544 else 545 { 546 $parser_options['allow_smilies'] = 0; 547 } 548 549 $image_check = $parser->parse_message($post['message'], $parser_options); 550 551 // And count the number of image tags in the message. 552 $image_count = substr_count($image_check, "<img"); 553 if($image_count > $mybb->settings['maxpostimages']) 554 { 555 // Throw back a message if over the count with the number of images as well as the maximum number of images per post. 556 $this->set_error("too_many_images", array(1 => $image_count, 2 => $mybb->settings['maxpostimages'])); 557 return false; 558 } 559 } 560 561 return true; 562 } 563 564 /** 565 * Verifies the video count. 566 * 567 * @return boolean True when valid, false when not valid. 568 */ 569 function verify_video_count() 570 { 571 global $mybb, $db; 572 573 $post = &$this->data; 574 575 if(isset($post['uid'])) 576 { 577 $uid = $post['uid']; 578 } 579 else 580 { 581 $uid = null; 582 } 583 584 // Get the permissions of the user who is making this post or thread 585 $permissions = user_permissions($uid); 586 587 // Check if this post contains more videos than the forum allows 588 if((!isset($post['savedraft']) || $post['savedraft'] != 1) && $mybb->settings['maxpostvideos'] != 0 && $permissions['cancp'] != 1) 589 { 590 // And count the number of video tags in the message. 591 $video_count = substr_count($post['message'], "[video="); 592 if($video_count > $mybb->settings['maxpostvideos']) 593 { 594 // Throw back a message if over the count with the number of images as well as the maximum number of images per post. 595 $this->set_error("too_many_videos", array(1 => $video_count, 2 => $mybb->settings['maxpostvideos'])); 596 return false; 597 } 598 } 599 600 return true; 601 } 602 603 /** 604 * Verify the reply-to post. 605 * 606 * @return boolean True when valid, false when not valid. 607 */ 608 function verify_reply_to() 609 { 610 global $db; 611 $post = &$this->data; 612 613 // Check if the post being replied to actually exists in this thread. 614 if($post['replyto']) 615 { 616 $query = $db->simple_select("posts", "pid", "pid='".(int)$post['replyto']."'"); 617 $valid_post = $db->fetch_array($query); 618 if(!$valid_post['pid']) 619 { 620 $post['replyto'] = 0; 621 } 622 else 623 { 624 return true; 625 } 626 } 627 628 // If this post isn't a reply to a specific post, attach it to the first post. 629 if(!$post['replyto']) 630 { 631 $options = array( 632 "limit_start" => 0, 633 "limit" => 1, 634 "order_by" => "dateline, pid", 635 ); 636 $query = $db->simple_select("posts", "pid", "tid='{$post['tid']}'", $options); 637 $reply_to = $db->fetch_array($query); 638 $post['replyto'] = $reply_to['pid']; 639 } 640 641 return true; 642 } 643 644 /** 645 * Verify the post icon. 646 * 647 * @return boolean True when valid, false when not valid. 648 */ 649 function verify_post_icon() 650 { 651 global $cache; 652 653 $post = &$this->data; 654 655 $posticons_cache = $cache->read("posticons"); 656 657 // If we don't have a post icon assign it as 0. 658 if(empty($post['icon']) || !isset($posticons_cache[$post['icon']])) 659 { 660 $post['icon'] = 0; 661 } 662 return true; 663 } 664 665 /** 666 * Verify the dateline. 667 * 668 * @return boolean True when valid, false when not valid. 669 */ 670 function verify_dateline() 671 { 672 $dateline = &$this->data['dateline']; 673 674 // The date has to be numeric and > 0. 675 if($dateline < 0 || is_numeric($dateline) == false) 676 { 677 $dateline = TIME_NOW; 678 } 679 } 680 681 /** 682 * Verify thread prefix. 683 * 684 * @return boolean True when valid, false when not valid. 685 */ 686 function verify_prefix() 687 { 688 $prefix = &$this->data['prefix']; 689 690 // If a valid prefix isn't supplied, don't assign one. 691 if(empty($prefix)) 692 { 693 $prefix = 0; 694 } 695 else 696 { 697 if(!empty($this->data['tid'])) 698 { 699 // Fetch the thread 700 $thread = get_thread($this->data['tid']); 701 } 702 703 $prefix_cache = build_prefixes($prefix); 704 705 if(empty($prefix_cache)) 706 { 707 $this->set_error('invalid_prefix'); 708 return false; 709 } 710 if($prefix_cache['groups'] != "-1") 711 { 712 if(!empty($this->data['edit_uid'])) 713 { 714 // Post is being edited 715 $user = get_user($this->data['edit_uid']); 716 } 717 else 718 { 719 $user = get_user($this->data['uid']); 720 } 721 722 if(!is_member($prefix_cache['groups'], array('usergroup' => $user['usergroup'], 'additionalgroups' => $user['additionalgroups'])) && (empty($this->data['tid']) || $prefix != $thread['prefix'])) 723 { 724 $this->set_error('invalid_prefix'); 725 return false; 726 } 727 } 728 if($prefix_cache['forums'] != "-1") 729 { 730 // Decide whether this prefix can be used in our forum 731 $forums = explode(",", $prefix_cache['forums']); 732 733 if(!in_array($this->data['fid'], $forums) && (empty($this->data['tid']) || $prefix != $thread['prefix'])) 734 { 735 $this->set_error('invalid_prefix'); 736 return false; 737 } 738 } 739 } 740 741 // Does this forum require a prefix? 742 $forum = get_forum($this->data['fid']); 743 744 if($forum['requireprefix'] == 1) 745 { 746 $num_prefixes = false; 747 748 // Go through each of our prefixes and decide if there are any possible prefixes to use. 749 if(!empty($this->data['edit_uid'])) 750 { 751 // Post is being edited 752 $user = get_user($this->data['edit_uid']); 753 } 754 else 755 { 756 $user = get_user($this->data['uid']); 757 } 758 759 $prefix_cache = build_prefixes(); 760 761 if(!empty($prefix_cache)) 762 { 763 foreach($prefix_cache as $required) 764 { 765 if($required['forums'] != "-1") 766 { 767 // Decide whether this prefix can be used in our forum 768 $forums = explode(",", $required['forums']); 769 770 if(!in_array($forum['fid'], $forums)) 771 { 772 continue; 773 } 774 } 775 776 if(is_member($required['groups'], array('usergroup' => $user['usergroup'], 'additionalgroups' => $user['additionalgroups']))) 777 { 778 $num_prefixes = true; 779 } 780 } 781 } 782 783 if($prefix == 0 && $num_prefixes) 784 { 785 $this->set_error('require_prefix'); 786 return false; 787 } 788 } 789 790 return true; 791 } 792 793 /** 794 * Validate a post. 795 * 796 * @return boolean True when valid, false when invalid. 797 */ 798 function validate_post() 799 { 800 global $mybb, $db, $plugins; 801 802 $post = &$this->data; 803 $time = TIME_NOW; 804 805 $this->action = "post"; 806 807 if($this->method != "update" && !$post['savedraft']) 808 { 809 $this->verify_post_flooding(); 810 } 811 812 // Are we editing an existing thread or post? 813 if($this->method == "update") 814 { 815 if(empty($post['tid'])) 816 { 817 $query = $db->simple_select("posts", "tid", "pid='".(int)$post['pid']."'"); 818 $post['tid'] = $db->fetch_field($query, "tid"); 819 } 820 // Here we determine if we're editing the first post of a thread or not. 821 $options = array( 822 "limit" => 1, 823 "limit_start" => 0, 824 "order_by" => "dateline, pid", 825 ); 826 $query = $db->simple_select("posts", "pid", "tid='".$post['tid']."'", $options); 827 $first_check = $db->fetch_array($query); 828 if($first_check['pid'] == $post['pid']) 829 { 830 $this->first_post = true; 831 } 832 } 833 834 // Verify all post assets. 835 836 if($this->method == "insert" || array_key_exists('uid', $post)) 837 { 838 $this->verify_author(); 839 } 840 841 if($this->method == "insert" || array_key_exists('subject', $post)) 842 { 843 $this->verify_subject(); 844 } 845 846 if($this->method == "insert" || array_key_exists('message', $post)) 847 { 848 $this->verify_message(); 849 $this->verify_image_count(); 850 $this->verify_video_count(); 851 } 852 853 if($this->method == "insert" || array_key_exists('dateline', $post)) 854 { 855 $this->verify_dateline(); 856 } 857 858 if($this->method == "insert" || array_key_exists('replyto', $post)) 859 { 860 $this->verify_reply_to(); 861 } 862 863 if($this->method == "insert" || array_key_exists('icon', $post)) 864 { 865 $this->verify_post_icon(); 866 } 867 868 if($this->method == "insert" || array_key_exists('options', $post)) 869 { 870 $this->verify_options(); 871 } 872 873 if($this->method == "update" && $this->first_post) 874 { 875 $this->verify_prefix(); 876 } 877 878 $plugins->run_hooks("datahandler_post_validate_post", $this); 879 880 // We are done validating, return. 881 $this->set_validated(true); 882 if(count($this->get_errors()) > 0) 883 { 884 return false; 885 } 886 else 887 { 888 return true; 889 } 890 } 891 892 /** 893 * Insert a post into the database. 894 * 895 * @return array Array of new post details, pid and visibility. 896 */ 897 function insert_post() 898 { 899 global $db, $mybb, $plugins, $cache, $lang; 900 901 $post = &$this->data; 902 903 // Yes, validating is required. 904 if(!$this->get_validated()) 905 { 906 die("The post needs to be validated before inserting it into the DB."); 907 } 908 if(count($this->get_errors()) > 0) 909 { 910 die("The post is not valid."); 911 } 912 913 // Fetch the thread 914 $thread = get_thread($post['tid']); 915 916 $closed = $thread['closed']; 917 918 // This post is being saved as a draft. 919 if($post['savedraft']) 920 { 921 $visible = -2; 922 } 923 924 // Otherwise this post is being made now and we have a bit to do. 925 else 926 { 927 // Automatic subscription to the thread 928 if($post['uid'] > 0) 929 { 930 require_once MYBB_ROOT."inc/functions_user.php"; 931 if($post['options']['subscriptionmethod'] == "") 932 { 933 remove_subscribed_thread($post['tid'], $post['uid']); 934 } 935 else 936 { 937 switch($post['options']['subscriptionmethod']) 938 { 939 case "pm": 940 $notification = 2; 941 break; 942 case "email": 943 $notification = 1; 944 break; 945 default: 946 $notification = 0; 947 } 948 add_subscribed_thread($post['tid'], $notification, $post['uid']); 949 } 950 } 951 952 // Perform any selected moderation tools. 953 $ismod = is_moderator($post['fid'], "", $post['uid']); 954 if($ismod && isset($post['modoptions'])) 955 { 956 $lang->load($this->language_file, true); 957 958 $modoptions = $post['modoptions']; 959 $modlogdata['fid'] = $thread['fid']; 960 $modlogdata['tid'] = $thread['tid']; 961 962 $modoptions_update = array(); 963 964 // Close the thread. 965 if(!empty($modoptions['closethread']) && $thread['closed'] != 1 && is_moderator($post['fid'], "canopenclosethreads", $post['uid'])) 966 { 967 $modoptions_update['closed'] = $closed = 1; 968 log_moderator_action($modlogdata, $lang->thread_closed); 969 } 970 971 // Open the thread. 972 if(empty($modoptions['closethread']) && $thread['closed'] == 1 && is_moderator($post['fid'], "canopenclosethreads", $post['uid'])) 973 { 974 $modoptions_update['closed'] = $closed = 0; 975 log_moderator_action($modlogdata, $lang->thread_opened); 976 } 977 978 // Stick the thread. 979 if(!empty($modoptions['stickthread']) && $thread['sticky'] != 1 && is_moderator($post['fid'], "canstickunstickthreads", $post['uid'])) 980 { 981 $modoptions_update['sticky'] = 1; 982 log_moderator_action($modlogdata, $lang->thread_stuck); 983 } 984 985 // Unstick the thread. 986 if(empty($modoptions['stickthread']) && $thread['sticky'] == 1 && is_moderator($post['fid'], "canstickunstickthreads", $post['uid'])) 987 { 988 $modoptions_update['sticky'] = 0; 989 log_moderator_action($modlogdata, $lang->thread_unstuck); 990 } 991 992 // Execute moderation options. 993 if($modoptions_update) 994 { 995 $db->update_query('threads', $modoptions_update, "tid='{$thread['tid']}'"); 996 } 997 } 998 999 // Fetch the forum this post is being made in 1000 $forum = get_forum($post['fid']); 1001 1002 // Decide on the visibility of this post. 1003 $forumpermissions = forum_permissions($post['fid'], $post['uid']); 1004 if($forumpermissions['modposts'] == 1 && !$ismod) 1005 { 1006 $visible = 0; 1007 } 1008 else 1009 { 1010 $visible = 1; 1011 } 1012 1013 // Are posts from this user being moderated? Change visibility 1014 if($mybb->user['uid'] == $post['uid'] && $mybb->user['moderateposts'] == 1) 1015 { 1016 $visible = 0; 1017 } 1018 } 1019 1020 if(!isset($post['pid'])) 1021 { 1022 $post['pid'] = 0; 1023 } 1024 1025 $post['pid'] = (int)$post['pid']; 1026 $post['uid'] = (int)$post['uid']; 1027 1028 if($post['pid'] > 0) 1029 { 1030 $query = $db->simple_select("posts", "tid", "pid='{$post['pid']}' AND uid='{$post['uid']}' AND visible='-2'"); 1031 $draft_check = $db->fetch_field($query, "tid"); 1032 } 1033 else 1034 { 1035 $draft_check = false; 1036 } 1037 1038 if($this->method != "update" && $visible == 1) 1039 { 1040 $double_post = $this->verify_post_merge(); 1041 1042 // Only combine if they are both invisible (mod queue'd forum) or both visible 1043 if($double_post !== true && $double_post['visible'] == $visible) 1044 { 1045 $_message = $post['message']; 1046 1047 $post['message'] = $double_post['message'] .= "\n".$mybb->settings['postmergesep']."\n".$post['message']; 1048 1049 if ($this->validate_post()) 1050 { 1051 $this->pid = $double_post['pid']; 1052 1053 $update_query = array( 1054 "message" => $db->escape_string($double_post['message']) 1055 ); 1056 $update_query['edituid'] = (int)$post['uid']; 1057 $update_query['edittime'] = TIME_NOW; 1058 $db->update_query("posts", $update_query, "pid='".$double_post['pid']."'"); 1059 1060 if($draft_check) 1061 { 1062 $db->delete_query("posts", "pid='".$post['pid']."'"); 1063 } 1064 1065 if($post['posthash']) 1066 { 1067 // Assign any uploaded attachments with the specific posthash to the merged post. 1068 $post['posthash'] = $db->escape_string($post['posthash']); 1069 1070 $query = $db->simple_select("attachments", "COUNT(aid) AS attachmentcount", "pid='0' AND visible='1' AND posthash='{$post['posthash']}'"); 1071 $attachmentcount = $db->fetch_field($query, "attachmentcount"); 1072 1073 if($attachmentcount > 0) 1074 { 1075 // Update forum count 1076 update_thread_counters($post['tid'], array('attachmentcount' => "+{$attachmentcount}")); 1077 } 1078 1079 $attachmentassign = array( 1080 "pid" => $double_post['pid'], 1081 "posthash" => '' 1082 ); 1083 $db->update_query("attachments", $attachmentassign, "posthash='{$post['posthash']}' AND pid='0'"); 1084 } 1085 1086 // Return the post's pid and whether or not it is visible. 1087 $this->return_values = array( 1088 "pid" => $double_post['pid'], 1089 "visible" => $visible, 1090 "merge" => true 1091 ); 1092 1093 $plugins->run_hooks("datahandler_post_insert_merge", $this); 1094 1095 return $this->return_values; 1096 } 1097 else 1098 { 1099 $post['message'] = $_message; 1100 } 1101 } 1102 } 1103 1104 if($visible == 1) 1105 { 1106 $now = TIME_NOW; 1107 1108 // Yes, the value to the lastpost key in this array has single quotes within double quotes. It's not a bug. 1109 $update_array = array( 1110 'lastpost' => "'{$now}'" 1111 ); 1112 if($forum['usepostcounts'] != 0 && $thread['visible'] == 1) 1113 { 1114 $update_array['postnum'] = 'postnum+1'; 1115 } 1116 1117 $db->update_query("users", $update_array, "uid='{$post['uid']}'", 1, true); 1118 } 1119 1120 // Are we updating a post which is already a draft? Perhaps changing it into a visible post? 1121 if($draft_check) 1122 { 1123 // Update a post that is a draft 1124 $this->post_update_data = array( 1125 "subject" => $db->escape_string($post['subject']), 1126 "icon" => (int)$post['icon'], 1127 "uid" => $post['uid'], 1128 "username" => $db->escape_string($post['username']), 1129 "dateline" => (int)$post['dateline'], 1130 "message" => $db->escape_string($post['message']), 1131 "ipaddress" => $db->escape_binary($post['ipaddress']), 1132 "includesig" => $post['options']['signature'], 1133 "smilieoff" => $post['options']['disablesmilies'], 1134 "visible" => $visible 1135 ); 1136 1137 $plugins->run_hooks("datahandler_post_insert_post", $this); 1138 1139 $db->update_query("posts", $this->post_update_data, "pid='{$post['pid']}'"); 1140 $this->pid = $post['pid']; 1141 } 1142 else 1143 { 1144 // Insert the post. 1145 $this->post_insert_data = array( 1146 "tid" => (int)$post['tid'], 1147 "replyto" => (int)$post['replyto'], 1148 "fid" => (int)$post['fid'], 1149 "subject" => $db->escape_string($post['subject']), 1150 "icon" => (int)$post['icon'], 1151 "uid" => $post['uid'], 1152 "username" => $db->escape_string($post['username']), 1153 "dateline" => $post['dateline'], 1154 "message" => $db->escape_string($post['message']), 1155 "ipaddress" => $db->escape_binary($post['ipaddress']), 1156 "includesig" => $post['options']['signature'], 1157 "smilieoff" => $post['options']['disablesmilies'], 1158 "visible" => $visible 1159 ); 1160 1161 $plugins->run_hooks("datahandler_post_insert_post", $this); 1162 1163 $this->pid = $db->insert_query("posts", $this->post_insert_data); 1164 } 1165 1166 // Assign any uploaded attachments with the specific posthash to the newly created post. 1167 if($post['posthash']) 1168 { 1169 $post['posthash'] = $db->escape_string($post['posthash']); 1170 $attachmentassign = array( 1171 "pid" => $this->pid, 1172 "posthash" => '' 1173 ); 1174 $db->update_query("attachments", $attachmentassign, "posthash='{$post['posthash']}' AND pid='0'"); 1175 } 1176 1177 $thread_update = array(); 1178 if($visible == 1 && $thread['visible'] == 1) 1179 { 1180 require_once MYBB_ROOT.'inc/class_parser.php'; 1181 $parser = new Postparser; 1182 1183 $done_users = array(); 1184 1185 $subject = $parser->parse_badwords($thread['subject']); 1186 1187 $parser_options = array( 1188 'me_username' => $post['username'], 1189 'filter_badwords' => 1 1190 ); 1191 1192 $excerpt = $parser->text_parse_message($post['message'], $parser_options); 1193 $excerpt = my_substr($excerpt, 0, $mybb->settings['subscribeexcerpt']).$lang->emailbit_viewthread; 1194 1195 // Fetch any users subscribed to this thread receiving instant notification and queue up their subscription notices 1196 $query = $db->query(" 1197 SELECT u.username, u.email, u.uid, u.language, u.loginkey, u.salt, u.regdate, s.notification 1198 FROM ".TABLE_PREFIX."threadsubscriptions s 1199 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=s.uid) 1200 WHERE (s.notification='1' OR s.notification='2') AND s.tid='{$post['tid']}' 1201 AND s.uid != '{$post['uid']}' 1202 AND u.lastactive>'{$thread['lastpost']}' 1203 "); 1204 1205 $args = array( 1206 'this' => &$this, 1207 'done_users' => &$done_users, 1208 'users' => array() 1209 ); 1210 1211 while($subscribedmember = $db->fetch_array($query)) 1212 { 1213 if($done_users[$subscribedmember['uid']]) 1214 { 1215 continue; 1216 } 1217 1218 $args['users'][$subscribedmember['uid']] = (int)$subscribedmember['uid']; 1219 1220 $done_users[$subscribedmember['uid']] = 1; 1221 1222 $forumpermissions = forum_permissions($thread['fid'], $subscribedmember['uid']); 1223 if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0) 1224 { 1225 continue; 1226 } 1227 1228 if($thread['uid'] != $subscribedmember['uid'] && $forumpermissions['canonlyviewownthread'] == 1 && !is_moderator($thread['fid'], "", $subscribedmember['uid'])) 1229 { 1230 // User isn't a moderator or the author of the thread... 1231 continue; 1232 } 1233 1234 if($subscribedmember['language'] != '' && $lang->language_exists($subscribedmember['language'])) 1235 { 1236 $uselang = $subscribedmember['language']; 1237 } 1238 elseif($mybb->settings['orig_bblanguage']) 1239 { 1240 $uselang = $mybb->settings['orig_bblanguage']; 1241 } 1242 else 1243 { 1244 $uselang = "english"; 1245 } 1246 1247 if($uselang == $mybb->settings['bblanguage']) 1248 { 1249 if($subscribedmember['notification'] == 1) 1250 { 1251 $emailsubject = $lang->emailsubject_subscription; 1252 $emailmessage = $lang->email_subscription; 1253 } 1254 1255 // If the poster is unregistered and hasn't set a username, call them Guest 1256 if(!$post['uid'] && !$post['username']) 1257 { 1258 $post['username'] = htmlspecialchars_uni($lang->guest); 1259 } 1260 } 1261 else 1262 { 1263 1264 if(($subscribedmember['notification'] == 1 && !isset($langcache[$uselang]['emailsubject_subscription'])) || !isset($langcache[$uselang]['guest'])) 1265 { 1266 $userlang = new MyLanguage; 1267 $userlang->set_path(MYBB_ROOT."inc/languages"); 1268 $userlang->set_language($uselang); 1269 if($subscribedmember['notification'] == 1) 1270 { 1271 $userlang->load("messages"); 1272 $langcache[$uselang]['emailsubject_subscription'] = $userlang->emailsubject_subscription; 1273 $langcache[$uselang]['email_subscription'] = $userlang->email_subscription; 1274 } 1275 $userlang->load("global"); 1276 1277 $langcache[$uselang]['guest'] = $userlang->guest; 1278 unset($userlang); 1279 } 1280 if($subscribedmember['notification'] == 1) 1281 { 1282 $emailsubject = $langcache[$uselang]['emailsubject_subscription']; 1283 $emailmessage = $langcache[$uselang]['email_subscription']; 1284 } 1285 1286 // If the poster is unregistered and hasn't set a username, call them Guest 1287 if(!$post['uid'] && !$post['username']) 1288 { 1289 $post['username'] = $langcache[$uselang]['guest']; 1290 } 1291 } 1292 1293 if($subscribedmember['notification'] == 1) 1294 { 1295 $emailsubject = $lang->sprintf($emailsubject, $subject); 1296 1297 $emailmessage = $lang->sprintf($emailmessage, $subscribedmember['username'], $post['username'], $mybb->settings['bbname'], $subject, $excerpt, $mybb->settings['bburl'], str_replace("&", "&", get_thread_link($thread['tid'], 0, "newpost")), $thread['tid']); 1298 $new_email = array( 1299 "mailto" => $db->escape_string($subscribedmember['email']), 1300 "mailfrom" => '', 1301 "subject" => $db->escape_string($emailsubject), 1302 "message" => $db->escape_string($emailmessage), 1303 "headers" => '' 1304 ); 1305 $db->insert_query("mailqueue", $new_email); 1306 unset($userlang); 1307 $queued_email = 1; 1308 } 1309 elseif($subscribedmember['notification'] == 2) 1310 { 1311 $pm = array( 1312 'subject' => array('pmsubject_subscription', $subject), 1313 'message' => array('pm_subscription', $subscribedmember['username'], $post['username'], $subject, $excerpt, $mybb->settings['bburl'], str_replace("&", "&", get_thread_link($thread['tid'], 0, "newpost")), $thread['tid']), 1314 'touid' => $subscribedmember['uid'], 1315 'language' => $subscribedmember['language'], 1316 'language_file' => 'messages' 1317 ); 1318 send_pm($pm, -1, true); 1319 } 1320 } 1321 1322 $plugins->run_hooks('datahandler_post_insert_subscribed', $args); 1323 1324 // Have one or more emails been queued? Update the queue count 1325 if(isset($queued_email) && $queued_email == 1) 1326 { 1327 $cache->update_mailqueue(); 1328 } 1329 1330 $thread_update = array('replies' => '+1'); 1331 1332 // Update counters 1333 update_last_post($post['tid']); 1334 update_forum_counters($post['fid'], array("posts" => "+1")); 1335 update_forum_lastpost($thread['fid']); 1336 } 1337 // Post is stuck in moderation queue 1338 else if($visible == 0) 1339 { 1340 // Update the unapproved posts count for the current thread and current forum 1341 $thread_update = array('unapprovedposts' => '+1'); 1342 update_thread_counters($post['tid'], array("unapprovedposts" => "+1")); 1343 update_forum_counters($post['fid'], array("unapprovedposts" => "+1")); 1344 } 1345 else if($thread['visible'] == 0) 1346 { 1347 // Update the unapproved posts count for the current forum 1348 $thread_update = array('replies' => '+1'); 1349 update_forum_counters($post['fid'], array("unapprovedposts" => "+1")); 1350 } 1351 else if($thread['visible'] == -1) 1352 { 1353 // Update the unapproved posts count for the current forum 1354 $thread_update = array('replies' => '+1'); 1355 update_forum_counters($post['fid'], array("deletedposts" => "+1")); 1356 } 1357 1358 // Update last poster 1359 if($visible == 1 && $thread['visible'] != 1) 1360 { 1361 update_last_post($post['tid']); 1362 } 1363 1364 $query = $db->simple_select("attachments", "COUNT(aid) AS attachmentcount", "pid='{$this->pid}' AND visible='1'"); 1365 $attachmentcount = $db->fetch_field($query, "attachmentcount"); 1366 if($attachmentcount > 0) 1367 { 1368 $thread_update['attachmentcount'] = "+{$attachmentcount}"; 1369 } 1370 update_thread_counters($post['tid'], $thread_update); 1371 1372 // Return the post's pid and whether or not it is visible. 1373 $this->return_values = array( 1374 "pid" => $this->pid, 1375 "visible" => $visible, 1376 "closed" => $closed 1377 ); 1378 1379 $plugins->run_hooks("datahandler_post_insert_post_end", $this); 1380 1381 return $this->return_values; 1382 } 1383 1384 /** 1385 * Validate a thread. 1386 * 1387 * @return boolean True when valid, false when invalid. 1388 */ 1389 function validate_thread() 1390 { 1391 global $mybb, $db, $plugins; 1392 1393 $thread = &$this->data; 1394 1395 // Validate all thread assets. 1396 1397 if(!$thread['savedraft']) 1398 { 1399 $this->verify_post_flooding(); 1400 } 1401 1402 if($this->method == "insert" || array_key_exists('uid', $thread)) 1403 { 1404 $this->verify_author(); 1405 } 1406 1407 if($this->method == "insert" || array_key_exists('prefix', $thread)) 1408 { 1409 $this->verify_prefix(); 1410 } 1411 1412 if($this->method == "insert" || array_key_exists('subject', $thread)) 1413 { 1414 $this->verify_subject(); 1415 } 1416 1417 if($this->method == "insert" || array_key_exists('message', $thread)) 1418 { 1419 $this->verify_message(); 1420 $this->verify_image_count(); 1421 $this->verify_video_count(); 1422 } 1423 1424 if($this->method == "insert" || array_key_exists('dateline', $thread)) 1425 { 1426 $this->verify_dateline(); 1427 } 1428 1429 if($this->method == "insert" || array_key_exists('icon', $thread)) 1430 { 1431 $this->verify_post_icon(); 1432 } 1433 1434 if($this->method == "insert" || array_key_exists('options', $thread)) 1435 { 1436 $this->verify_options(); 1437 } 1438 1439 $plugins->run_hooks("datahandler_post_validate_thread", $this); 1440 1441 // We are done validating, return. 1442 $this->set_validated(true); 1443 if(count($this->get_errors()) > 0) 1444 { 1445 return false; 1446 } 1447 else 1448 { 1449 return true; 1450 } 1451 } 1452 1453 /** 1454 * Insert a thread into the database. 1455 * 1456 * @return array Array of new thread details, tid and visibility. 1457 */ 1458 function insert_thread() 1459 { 1460 global $db, $mybb, $plugins, $cache, $lang; 1461 1462 // Yes, validating is required. 1463 if(!$this->get_validated()) 1464 { 1465 die("The thread needs to be validated before inserting it into the DB."); 1466 } 1467 if(count($this->get_errors()) > 0) 1468 { 1469 die("The thread is not valid."); 1470 } 1471 1472 $thread = &$this->data; 1473 1474 // Fetch the forum this thread is being made in 1475 $query = $db->simple_select("forums", "*", "fid='{$thread['fid']}'"); 1476 $forum = $db->fetch_array($query); 1477 1478 // This thread is being saved as a draft. 1479 if($thread['savedraft']) 1480 { 1481 $visible = -2; 1482 } 1483 1484 // Thread is being made now and we have a bit to do. 1485 else 1486 { 1487 $forumpermissions = forum_permissions($thread['fid'], $thread['uid']); 1488 // Decide on the visibility of this post. 1489 if($forumpermissions['modthreads'] == 1 && !is_moderator($thread['fid'], "", $thread['uid'])) 1490 { 1491 $visible = 0; 1492 } 1493 else 1494 { 1495 $visible = 1; 1496 } 1497 1498 // Are posts from this user being moderated? Change visibility 1499 if($mybb->user['uid'] == $thread['uid'] && $mybb->user['moderateposts'] == 1) 1500 { 1501 $visible = 0; 1502 } 1503 } 1504 1505 // Have a post ID but not a thread ID - fetch thread ID 1506 if(!empty($thread['pid']) && !$thread['tid']) 1507 { 1508 $query = $db->simple_select("posts", "tid", "pid='{$thread['pid']}"); 1509 $thread['tid'] = $db->fetch_field($query, "tid"); 1510 } 1511 1512 if(isset($thread['pid']) && $thread['pid'] > 0) 1513 { 1514 $query = $db->simple_select("posts", "pid", "pid='{$thread['pid']}' AND uid='{$thread['uid']}' AND visible='-2'"); 1515 $draft_check = $db->fetch_field($query, "pid"); 1516 } 1517 else 1518 { 1519 $draft_check = false; 1520 } 1521 1522 // Are we updating a post which is already a draft? Perhaps changing it into a visible post? 1523 if($draft_check) 1524 { 1525 $this->thread_insert_data = array( 1526 "subject" => $db->escape_string($thread['subject']), 1527 "icon" => (int)$thread['icon'], 1528 "username" => $db->escape_string($thread['username']), 1529 "dateline" => (int)$thread['dateline'], 1530 "lastpost" => (int)$thread['dateline'], 1531 "lastposter" => $db->escape_string($thread['username']), 1532 "visible" => $visible 1533 ); 1534 1535 $plugins->run_hooks("datahandler_post_insert_thread", $this); 1536 1537 $db->update_query("threads", $this->thread_insert_data, "tid='{$thread['tid']}'"); 1538 1539 $this->post_insert_data = array( 1540 "subject" => $db->escape_string($thread['subject']), 1541 "icon" => (int)$thread['icon'], 1542 "username" => $db->escape_string($thread['username']), 1543 "dateline" => (int)$thread['dateline'], 1544 "message" => $db->escape_string($thread['message']), 1545 "ipaddress" => $db->escape_binary(my_inet_pton(get_ip())), 1546 "includesig" => $thread['options']['signature'], 1547 "smilieoff" => $thread['options']['disablesmilies'], 1548 "visible" => $visible 1549 ); 1550 $plugins->run_hooks("datahandler_post_insert_thread_post", $this); 1551 1552 $db->update_query("posts", $this->post_insert_data, "pid='{$thread['pid']}'"); 1553 $this->tid = $thread['tid']; 1554 $this->pid = $thread['pid']; 1555 } 1556 1557 // Inserting a new thread into the database. 1558 else 1559 { 1560 $this->thread_insert_data = array( 1561 "fid" => $thread['fid'], 1562 "subject" => $db->escape_string($thread['subject']), 1563 "prefix" => (int)$thread['prefix'], 1564 "icon" => (int)$thread['icon'], 1565 "uid" => $thread['uid'], 1566 "username" => $db->escape_string($thread['username']), 1567 "dateline" => (int)$thread['dateline'], 1568 "lastpost" => (int)$thread['dateline'], 1569 "lastposter" => $db->escape_string($thread['username']), 1570 "lastposteruid" => $thread['uid'], 1571 "views" => 0, 1572 "replies" => 0, 1573 "visible" => $visible, 1574 "notes" => '' 1575 ); 1576 1577 $plugins->run_hooks("datahandler_post_insert_thread", $this); 1578 1579 $this->tid = $db->insert_query("threads", $this->thread_insert_data); 1580 1581 $this->post_insert_data = array( 1582 "tid" => $this->tid, 1583 "fid" => $thread['fid'], 1584 "subject" => $db->escape_string($thread['subject']), 1585 "icon" => (int)$thread['icon'], 1586 "uid" => $thread['uid'], 1587 "username" => $db->escape_string($thread['username']), 1588 "dateline" => (int)$thread['dateline'], 1589 "message" => $db->escape_string($thread['message']), 1590 "ipaddress" => $db->escape_binary(my_inet_pton(get_ip())), 1591 "includesig" => $thread['options']['signature'], 1592 "smilieoff" => $thread['options']['disablesmilies'], 1593 "visible" => $visible 1594 ); 1595 $plugins->run_hooks("datahandler_post_insert_thread_post", $this); 1596 1597 $this->pid = $db->insert_query("posts", $this->post_insert_data); 1598 1599 // Now that we have the post id for this first post, update the threads table. 1600 $firstpostup = array("firstpost" => $this->pid); 1601 $db->update_query("threads", $firstpostup, "tid='{$this->tid}'"); 1602 } 1603 1604 // If we're not saving a draft there are some things we need to check now 1605 if(!$thread['savedraft']) 1606 { 1607 if($thread['options']['subscriptionmethod'] != "" && $thread['uid'] > 0) 1608 { 1609 switch($thread['options']['subscriptionmethod']) 1610 { 1611 case "pm": 1612 $notification = 2; 1613 break; 1614 case "email": 1615 $notification = 1; 1616 break; 1617 default: 1618 $notification = 0; 1619 } 1620 1621 require_once MYBB_ROOT."inc/functions_user.php"; 1622 add_subscribed_thread($this->tid, $notification, $thread['uid']); 1623 } 1624 1625 // Perform any selected moderation tools. 1626 if(is_moderator($thread['fid'], "", $thread['uid']) && isset($thread['modoptions'])) 1627 { 1628 $lang->load($this->language_file, true); 1629 1630 $modoptions = $thread['modoptions']; 1631 $modlogdata['fid'] = $thread['fid']; 1632 if(isset($thread['tid'])) 1633 { 1634 $modlogdata['tid'] = $thread['tid']; 1635 } 1636 1637 $modoptions_update = array(); 1638 1639 // Close the thread. 1640 if(!empty($modoptions['closethread']) && is_moderator($thread['fid'], "canopenclosethreads", $thread['uid'])) 1641 { 1642 $modoptions_update['closed'] = 1; 1643 log_moderator_action($modlogdata, $lang->thread_closed); 1644 } 1645 1646 // Stick the thread. 1647 if(!empty($modoptions['stickthread']) && is_moderator($thread['fid'], "canstickunstickthreads", $thread['uid'])) 1648 { 1649 $modoptions_update['sticky'] = 1; 1650 log_moderator_action($modlogdata, $lang->thread_stuck); 1651 } 1652 1653 // Execute moderation options. 1654 if($modoptions_update) 1655 { 1656 $db->update_query('threads', $modoptions_update, "tid='{$this->tid}'"); 1657 } 1658 } 1659 if($visible == 1) 1660 { 1661 // If we have a registered user then update their post count and last post times. 1662 if($thread['uid'] > 0) 1663 { 1664 $user = get_user($thread['uid']); 1665 $update_query = array(); 1666 // Only update the lastpost column of the user if the date of the thread is newer than their last post. 1667 if($thread['dateline'] > $user['lastpost']) 1668 { 1669 // Yes this has a single quote within a double quote. It's not a bug. 1670 $update_query['lastpost'] = "'{$thread['dateline']}'"; 1671 } 1672 // Update the post count if this forum allows post counts to be tracked 1673 if($forum['usepostcounts'] != 0) 1674 { 1675 $update_query['postnum'] = "postnum+1"; 1676 } 1677 if($forum['usethreadcounts'] != 0) 1678 { 1679 $update_query['threadnum'] = 'threadnum+1'; 1680 } 1681 1682 // Only update the table if we need to. 1683 if(!empty($update_query)) 1684 { 1685 $db->update_query("users", $update_query, "uid='{$thread['uid']}'", 1, true); 1686 } 1687 } 1688 1689 $done_users = array(); 1690 1691 // Queue up any forum subscription notices to users who are subscribed to this forum. 1692 $excerpt = $thread['message']; 1693 1694 // Parse badwords 1695 require_once MYBB_ROOT."inc/class_parser.php"; 1696 $parser = new postParser; 1697 $excerpt = $parser->parse_badwords($excerpt); 1698 $excerpt = $parser->text_parse_message($excerpt); 1699 if(strlen($excerpt) > $mybb->settings['subscribeexcerpt']) 1700 { 1701 $excerpt = my_substr($excerpt, 0, $mybb->settings['subscribeexcerpt']).$lang->emailbit_viewthread; 1702 } 1703 $query = $db->query(" 1704 SELECT u.username, u.email, u.uid, u.language, u.loginkey, u.salt, u.regdate 1705 FROM ".TABLE_PREFIX."forumsubscriptions fs 1706 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=fs.uid) 1707 LEFT JOIN ".TABLE_PREFIX."usergroups g ON (g.gid=u.usergroup) 1708 WHERE fs.fid='".(int)$thread['fid']."' 1709 AND fs.uid != '".(int)$thread['uid']."' 1710 AND u.lastactive > '{$forum['lastpost']}' 1711 AND g.isbannedgroup != 1 1712 "); 1713 while($subscribedmember = $db->fetch_array($query)) 1714 { 1715 if(!empty($done_users[$subscribedmember['uid']])) 1716 { 1717 continue; 1718 } 1719 $done_users[$subscribedmember['uid']] = 1; 1720 1721 $forumpermissions = forum_permissions($thread['fid'], $subscribedmember['uid']); 1722 if($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0) 1723 { 1724 continue; 1725 } 1726 1727 if(!is_moderator($thread['fid'], "", $subscribedmember['uid']) && $forumpermissions['canonlyviewownthreads'] == 1) 1728 { 1729 // In a 'view own only' forum and not a moderator 1730 continue; 1731 } 1732 1733 // Determine the language pack we'll be using to send this email in and load it if it isn't already. 1734 if($subscribedmember['language'] != '' && $lang->language_exists($subscribedmember['language'])) 1735 { 1736 $uselang = $subscribedmember['language']; 1737 } 1738 else if($mybb->settings['bblanguage']) 1739 { 1740 $uselang = $mybb->settings['bblanguage']; 1741 } 1742 else 1743 { 1744 $uselang = "english"; 1745 } 1746 1747 if($uselang == $mybb->settings['bblanguage']) 1748 { 1749 $emailsubject = $lang->emailsubject_forumsubscription; 1750 $emailmessage = $lang->email_forumsubscription; 1751 1752 // If the poster is unregistered and hasn't set a username, call them Guest 1753 if(!$thread['uid'] && !$thread['username']) 1754 { 1755 $thread['username'] = htmlspecialchars_uni($lang->guest); 1756 } 1757 } 1758 else 1759 { 1760 if(!isset($langcache[$uselang]['emailsubject_forumsubscription'])) 1761 { 1762 $userlang = new MyLanguage; 1763 $userlang->set_path(MYBB_ROOT."inc/languages"); 1764 $userlang->set_language($uselang); 1765 $userlang->load("messages"); 1766 $userlang->load("global"); 1767 $langcache[$uselang]['emailsubject_forumsubscription'] = $userlang->emailsubject_forumsubscription; 1768 $langcache[$uselang]['email_forumsubscription'] = $userlang->email_forumsubscription; 1769 $langcache[$uselang]['guest'] = $userlang->guest; 1770 unset($userlang); 1771 } 1772 $emailsubject = $langcache[$uselang]['emailsubject_forumsubscription']; 1773 $emailmessage = $langcache[$uselang]['email_forumsubscription']; 1774 1775 // If the poster is unregistered and hasn't set a username, call them Guest 1776 if(!$thread['uid'] && !$thread['username']) 1777 { 1778 $thread['username'] = $langcache[$uselang]['guest']; 1779 } 1780 } 1781 $emailsubject = $lang->sprintf($emailsubject, $forum['name']); 1782 1783 $emailmessage = $lang->sprintf($emailmessage, $subscribedmember['username'], $thread['username'], $forum['name'], $mybb->settings['bbname'], $thread['subject'], $excerpt, $mybb->settings['bburl'], get_thread_link($this->tid), $thread['fid']); 1784 $new_email = array( 1785 "mailto" => $db->escape_string($subscribedmember['email']), 1786 "mailfrom" => '', 1787 "subject" => $db->escape_string($emailsubject), 1788 "message" => $db->escape_string($emailmessage), 1789 "headers" => '' 1790 ); 1791 $db->insert_query("mailqueue", $new_email); 1792 unset($userlang); 1793 $queued_email = 1; 1794 } 1795 // Have one or more emails been queued? Update the queue count 1796 if(isset($queued_email) && $queued_email == 1) 1797 { 1798 $cache->update_mailqueue(); 1799 } 1800 } 1801 } 1802 1803 // Assign any uploaded attachments with the specific posthash to the newly created post. 1804 if($thread['posthash']) 1805 { 1806 $thread['posthash'] = $db->escape_string($thread['posthash']); 1807 $attachmentassign = array( 1808 "pid" => $this->pid, 1809 "posthash" => '' 1810 ); 1811 $db->update_query("attachments", $attachmentassign, "posthash='{$thread['posthash']}' AND pid='0'"); 1812 } 1813 1814 if($visible == 1) 1815 { 1816 update_last_post($this->tid); 1817 update_forum_counters($thread['fid'], array("threads" => "+1", "posts" => "+1")); 1818 update_forum_lastpost($thread['fid']); 1819 } 1820 else if($visible == 0) 1821 { 1822 update_forum_counters($thread['fid'], array("unapprovedthreads" => "+1", "unapprovedposts" => "+1")); 1823 } 1824 1825 $query = $db->simple_select("attachments", "COUNT(aid) AS attachmentcount", "pid='{$this->pid}' AND visible='1'"); 1826 $attachmentcount = $db->fetch_field($query, "attachmentcount"); 1827 if($attachmentcount > 0) 1828 { 1829 update_thread_counters($this->tid, array("attachmentcount" => "+{$attachmentcount}")); 1830 } 1831 1832 // Return the post's pid and whether or not it is visible. 1833 $this->return_values = array( 1834 "pid" => $this->pid, 1835 "tid" => $this->tid, 1836 "visible" => $visible 1837 ); 1838 1839 $plugins->run_hooks("datahandler_post_insert_thread_end", $this); 1840 1841 return $this->return_values; 1842 } 1843 1844 /** 1845 * Updates a post that is already in the database. 1846 * 1847 * @return array 1848 */ 1849 function update_post() 1850 { 1851 global $db, $mybb, $plugins; 1852 1853 // Yes, validating is required. 1854 if($this->get_validated() != true) 1855 { 1856 die("The post needs to be validated before inserting it into the DB."); 1857 } 1858 if(count($this->get_errors()) > 0) 1859 { 1860 die("The post is not valid."); 1861 } 1862 1863 $post = &$this->data; 1864 1865 $post['pid'] = (int)$post['pid']; 1866 1867 $existing_post = get_post($post['pid']); 1868 $post['tid'] = $existing_post['tid']; 1869 $post['fid'] = $existing_post['fid']; 1870 1871 if(isset($post['uid'])) 1872 { 1873 $uid = $post['uid']; 1874 } 1875 else 1876 { 1877 $uid = 0; 1878 } 1879 1880 $forum = get_forum($post['fid']); 1881 $forumpermissions = forum_permissions($post['fid'], $uid); 1882 1883 // Decide on the visibility of this post. 1884 $ismod = is_moderator($post['fid'], "", $uid); 1885 1886 // Keep visibility for unapproved and deleted posts 1887 if($existing_post['visible'] == 0) 1888 { 1889 $visible = 0; 1890 } 1891 elseif($existing_post['visible'] == -1) 1892 { 1893 $visible = -1; 1894 } 1895 elseif($forumpermissions['mod_edit_posts'] == 1 && !$ismod) 1896 { 1897 $visible = 0; 1898 require_once MYBB_ROOT."inc/class_moderation.php"; 1899 $moderation = new Moderation; 1900 $moderation->unapprove_posts(array($post['pid'])); 1901 } 1902 else 1903 { 1904 $visible = 1; 1905 } 1906 1907 // Update the thread details that might have been changed first. 1908 if($this->first_post) 1909 { 1910 $this->tid = $post['tid']; 1911 1912 if(isset($post['prefix'])) 1913 { 1914 $this->thread_update_data['prefix'] = (int)$post['prefix']; 1915 } 1916 1917 if(isset($post['subject'])) 1918 { 1919 $this->thread_update_data['subject'] = $db->escape_string($post['subject']); 1920 } 1921 1922 if(isset($post['icon'])) 1923 { 1924 $this->thread_update_data['icon'] = (int)$post['icon']; 1925 } 1926 if(count($this->thread_update_data) > 0) 1927 { 1928 $plugins->run_hooks("datahandler_post_update_thread", $this); 1929 1930 $db->update_query("threads", $this->thread_update_data, "tid='".(int)$post['tid']."'"); 1931 } 1932 1933 // Update any moved thread links to have corresponding new subject. 1934 if(isset($post['subject'])) 1935 { 1936 $query = $db->simple_select("threads", "tid, closed", "closed='moved|".$this->tid."'"); 1937 if($db->num_rows($query) > 0) 1938 { 1939 $update_data['subject'] = $db->escape_string($post['subject']); 1940 while($result = $db->fetch_array($query)) 1941 { 1942 $db->update_query("threads", $update_data, "tid='".(int)$result['tid']."'"); 1943 } 1944 } 1945 } 1946 } 1947 1948 // Prepare array for post updating. 1949 1950 $this->pid = $post['pid']; 1951 1952 if(isset($post['subject'])) 1953 { 1954 $this->post_update_data['subject'] = $db->escape_string($post['subject']); 1955 } 1956 1957 if(isset($post['message'])) 1958 { 1959 $this->post_update_data['message'] = $db->escape_string($post['message']); 1960 } 1961 1962 if(isset($post['editreason']) && trim($post['editreason']) != '') 1963 { 1964 $this->post_update_data['editreason'] = $db->escape_string(trim($post['editreason'])); 1965 } 1966 elseif(empty($post['editreason'])) 1967 { 1968 $this->post_update_data['editreason'] = ''; 1969 } 1970 1971 if(isset($post['icon'])) 1972 { 1973 $this->post_update_data['icon'] = (int)$post['icon']; 1974 } 1975 1976 if(isset($post['options'])) 1977 { 1978 if(isset($post['options']['disablesmilies'])) 1979 { 1980 $this->post_update_data['smilieoff'] = $db->escape_string($post['options']['disablesmilies']); 1981 } 1982 if(isset($post['options']['signature'])) 1983 { 1984 $this->post_update_data['includesig'] = $db->escape_string($post['options']['signature']); 1985 } 1986 } 1987 1988 // If we need to show the edited by, let's do so. 1989 if(($mybb->settings['showeditedby'] == 1 && !is_moderator($post['fid'], "caneditposts", $post['edit_uid'])) || ($mybb->settings['showeditedbyadmin'] == 1 && is_moderator($post['fid'], "caneditposts", $post['edit_uid']))) 1990 { 1991 $this->post_update_data['edituid'] = (int)$post['edit_uid']; 1992 $this->post_update_data['edittime'] = TIME_NOW; 1993 } 1994 1995 $plugins->run_hooks("datahandler_post_update", $this); 1996 1997 $db->update_query("posts", $this->post_update_data, "pid='".(int)$post['pid']."'"); 1998 1999 // Automatic subscription to the thread 2000 if($post && !empty($post['options']['subscriptionmethod']) && $uid > 0) 2001 { 2002 switch($post['options']['subscriptionmethod']) 2003 { 2004 case "pm": 2005 $notification = 2; 2006 break; 2007 case "email": 2008 $notification = 1; 2009 break; 2010 default: 2011 $notification = 0; 2012 } 2013 require_once MYBB_ROOT."inc/functions_user.php"; 2014 add_subscribed_thread($post['tid'], $notification, $post['uid']); 2015 } 2016 else 2017 { 2018 $db->delete_query("threadsubscriptions", "uid='".(int)$uid."' AND tid='".(int)$post['tid']."'"); 2019 } 2020 2021 update_forum_lastpost($post['fid']); 2022 update_last_post($post['tid']); 2023 2024 // Return the thread's first post id and whether or not it is visible. 2025 $this->return_values = array( 2026 'visible' => $visible, 2027 'first_post' => $this->first_post 2028 ); 2029 2030 $plugins->run_hooks("datahandler_post_update_end", $this); 2031 2032 return $this->return_values; 2033 } 2034 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup | Cross-referenced by PHPXref |