[ Index ] |
PHP Cross Reference of MyBB |
[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$ 10 */ 11 12 /** 13 * Build a select box list of forums the current user has permission to search 14 * 15 * @param int The parent forum ID to start at 16 * @param int The selected forum ID 17 * @param int Add select boxes at this call or not 18 * @param int The current depth 19 * @return string The forum select boxes 20 */ 21 function make_searchable_forums($pid="0", $selitem='', $addselect="1", $depth='') 22 { 23 global $db, $pforumcache, $permissioncache, $mybb, $selecteddone, $forumlist, $forumlistbits, $theme, $templates, $lang, $forumpass; 24 $pid = intval($pid); 25 26 if(!is_array($pforumcache)) 27 { 28 // Get Forums 29 $query = $db->simple_select("forums", "pid,disporder,fid,password,name", "linkto='' AND active!=0", array('order_by' => "pid, disporder")); 30 while($forum = $db->fetch_array($query)) 31 { 32 $pforumcache[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; 33 } 34 } 35 if(!is_array($permissioncache)) 36 { 37 $permissioncache = forum_permissions(); 38 } 39 if(is_array($pforumcache[$pid])) 40 { 41 foreach($pforumcache[$pid] as $key => $main) 42 { 43 foreach($main as $key => $forum) 44 { 45 $perms = $permissioncache[$forum['fid']]; 46 if(($perms['canview'] == 1 || $mybb->settings['hideprivateforums'] == 0) && $perms['cansearch'] != 0) 47 { 48 if($selitem == $forum['fid']) 49 { 50 $optionselected = "selected"; 51 $selecteddone = "1"; 52 } 53 else 54 { 55 $optionselected = ''; 56 $selecteddone = "0"; 57 } 58 if($forum['password'] != '') 59 { 60 if($mybb->cookies['forumpass'][$forum['fid']] == md5($mybb->user['uid'].$forum['password'])) 61 { 62 $pwverified = 1; 63 } 64 else 65 { 66 $pwverified = 0; 67 } 68 } 69 if(empty($forum['password']) || $pwverified == 1) 70 { 71 $forumlistbits .= "<option value=\"{$forum['fid']}\">$depth {$forum['name']}</option>\n"; 72 } 73 if($pforumcache[$forum['fid']]) 74 { 75 $newdepth = $depth." "; 76 $forumlistbits .= make_searchable_forums($forum['fid'], $selitem, 0, $newdepth); 77 } 78 } 79 } 80 } 81 } 82 if($addselect) 83 { 84 $forumlist = "<select name=\"forums[]\" size=\"20\" multiple=\"multiple\">\n<option value=\"all\" selected=\"selected\">$lang->search_all_forums</option>\n<option value=\"all\">----------------------</option>\n$forumlistbits\n</select>"; 85 } 86 return $forumlist; 87 } 88 89 /** 90 * Build a comma separated list of the forums this user cannot search 91 * 92 * @param int The parent ID to build from 93 * @param int First rotation or not (leave at default) 94 * @return return a CSV list of forums the user cannot search 95 */ 96 function get_unsearchable_forums($pid="0", $first=1) 97 { 98 global $db, $forum_cache, $permissioncache, $mybb, $unsearchableforums, $unsearchable, $templates, $forumpass; 99 100 $pid = intval($pid); 101 102 if(!is_array($forum_cache)) 103 { 104 // Get Forums 105 $query = $db->simple_select("forums", "fid,parentlist,password,active", '', array('order_by' => 'pid, disporder')); 106 while($forum = $db->fetch_array($query)) 107 { 108 $forum_cache[$forum['fid']] = $forum; 109 } 110 } 111 if(!is_array($permissioncache)) 112 { 113 $permissioncache = forum_permissions(); 114 } 115 foreach($forum_cache as $fid => $forum) 116 { 117 if($permissioncache[$forum['fid']]) 118 { 119 $perms = $permissioncache[$forum['fid']]; 120 } 121 else 122 { 123 $perms = $mybb->usergroup; 124 } 125 126 $pwverified = 1; 127 if($forum['password'] != '') 128 { 129 if($mybb->cookies['forumpass'][$forum['fid']] != md5($mybb->user['uid'].$forum['password'])) 130 { 131 $pwverified = 0; 132 } 133 } 134 135 $parents = explode(",", $forum['parentlist']); 136 if(is_array($parents)) 137 { 138 foreach($parents as $parent) 139 { 140 if($forum_cache[$parent]['active'] == 0) 141 { 142 $forum['active'] = 0; 143 } 144 } 145 } 146 147 if($perms['canview'] != 1 || $perms['cansearch'] != 1 || $pwverified == 0 || $forum['active'] == 0) 148 { 149 if($unsearchableforums) 150 { 151 $unsearchableforums .= ","; 152 } 153 $unsearchableforums .= "'{$forum['fid']}'"; 154 } 155 } 156 $unsearchable = $unsearchableforums; 157 158 // Get our unsearchable password protected forums 159 $pass_protected_forums = get_password_protected_forums(); 160 161 if($unsearchable && $pass_protected_forums) 162 { 163 $unsearchable .= ","; 164 } 165 166 if($pass_protected_forums) 167 { 168 $unsearchable .= implode(",", $pass_protected_forums); 169 } 170 171 return $unsearchable; 172 } 173 174 /** 175 * Build a array list of the forums this user cannot search due to password protection 176 * 177 * @param int the fids to check (leave null to check all forums) 178 * @return return a array list of password protected forums the user cannot search 179 */ 180 function get_password_protected_forums($fids=array()) 181 { 182 global $forum_cache, $mybb; 183 184 if(!is_array($fids)) 185 { 186 return false; 187 } 188 189 if(!is_array($forum_cache)) 190 { 191 $forum_cache = cache_forums(); 192 if(!$forum_cache) 193 { 194 return false; 195 } 196 } 197 198 if(empty($fids)) 199 { 200 $fids = array_keys($forum_cache); 201 } 202 203 $pass_fids = array(); 204 foreach($fids as $fid) 205 { 206 if(empty($forum_cache[$fid]['password'])) 207 { 208 continue; 209 } 210 211 if(md5($mybb->user['uid'].$forum_cache[$fid]['password']) != $mybb->cookies['forumpass'][$fid]) 212 { 213 $pass_fids[] = $fid; 214 $child_list = get_child_list($fid); 215 } 216 217 if(is_array($child_list)) 218 { 219 $pass_fids = array_merge($pass_fids, $child_list); 220 } 221 } 222 return array_unique($pass_fids); 223 } 224 225 /** 226 * Clean search keywords and make them safe for querying 227 * 228 * @param string The keywords to be cleaned 229 * @return string The cleaned keywords 230 */ 231 function clean_keywords($keywords) 232 { 233 $keywords = my_strtolower($keywords); 234 $keywords = str_replace("%", "\\%", $keywords); 235 $keywords = preg_replace("#\*{2,}#s", "*", $keywords); 236 $keywords = str_replace("*", "%", $keywords); 237 $keywords = preg_replace("#([\[\]\|\.\,:'])#s", " ", $keywords); 238 $keywords = preg_replace("#\s+#s", " ", $keywords); 239 240 // Search for "and" or "or" and remove if it's at the beginning 241 $keywords = trim($keywords); 242 if(my_strpos($keywords, "or") === 0) 243 { 244 $keywords = substr_replace($keywords, "", 0, 2); 245 } 246 247 if(my_strpos($keywords, "and") === 0) 248 { 249 $keywords = substr_replace($keywords, "", 0, 3); 250 } 251 252 return $keywords; 253 } 254 255 /** 256 * Clean search keywords for fulltext searching, making them safe for querying 257 * 258 * @param string The keywords to be cleaned 259 * @return string The cleaned keywords 260 */ 261 function clean_keywords_ft($keywords) 262 { 263 if(!$keywords) 264 { 265 return false; 266 } 267 $keywords = my_strtolower($keywords); 268 $keywords = str_replace("%", "\\%", $keywords); 269 $keywords = preg_replace("#\*{2,}#s", "*", $keywords); 270 $keywords = preg_replace("#([\[\]\|\.\,:])#s", " ", $keywords); 271 $keywords = preg_replace("#\s+#s", " ", $keywords); 272 273 $words = array(); 274 275 if(my_strpos($keywords, "\"") !== false) 276 { 277 $inquote = false; 278 $keywords = explode("\"", $keywords); 279 foreach($keywords as $phrase) 280 { 281 if($phrase != '') 282 { 283 if($inquote) 284 { 285 $words[] = "\"".trim($phrase)."\""; 286 } 287 else 288 { 289 $split_words = preg_split("#\s{1,}#", $phrase, -1); 290 if(!is_array($split_words)) 291 { 292 continue; 293 } 294 foreach($split_words as $word) 295 { 296 if(!$word) 297 { 298 continue; 299 } 300 $words[] = trim($word); 301 } 302 } 303 } 304 $inquote = !$inquote; 305 } 306 } 307 else 308 { 309 $split_words = preg_split("#\s{1,}#", $keywords, -1); 310 if(!is_array($split_words)) 311 { 312 continue; 313 } 314 foreach($split_words as $word) 315 { 316 if(!$word) 317 { 318 continue; 319 } 320 $words[] = trim($word); 321 } 322 323 } 324 $keywords = ''; 325 foreach($words as $word) 326 { 327 if($word == "or") 328 { 329 $boolean = ''; 330 } 331 elseif($word == "and") 332 { 333 $boolean = "+"; 334 } 335 elseif($word == "not") 336 { 337 $boolean = "-"; 338 } 339 else 340 { 341 $keywords .= " ".$boolean.$word; 342 $boolean = ''; 343 } 344 } 345 $keywords = "+".trim($keywords); 346 return $keywords; 347 } 348 349 /* Database engine specific search functions */ 350 351 /** 352 * Perform a thread and post search under MySQL or MySQLi 353 * 354 * @param array Array of search data 355 * @return array Array of search data with results mixed in 356 */ 357 function privatemessage_perform_search_mysql($search) 358 { 359 global $mybb, $db, $lang; 360 361 $keywords = clean_keywords($search['keywords']); 362 if(!$keywords && !$search['sender']) 363 { 364 error($lang->error_nosearchterms); 365 } 366 367 if($mybb->settings['minsearchword'] < 1) 368 { 369 $mybb->settings['minsearchword'] = 3; 370 } 371 372 $subject_lookin = ""; 373 $message_lookin = ""; 374 $searchsql = "uid='{$mybb->user['uid']}'"; 375 376 if($keywords) 377 { 378 // Complex search 379 $keywords = " {$keywords} "; 380 if(preg_match("# and|or #", $keywords)) 381 { 382 $string = "AND"; 383 if($search['subject'] == 1) 384 { 385 $string = "OR"; 386 $subject_lookin = " AND ("; 387 } 388 389 if($search['message'] == 1) 390 { 391 $message_lookin = " {$string} ("; 392 } 393 394 // Expand the string by double quotes 395 $keywords_exp = explode("\"", $keywords); 396 $inquote = false; 397 398 foreach($keywords_exp as $phrase) 399 { 400 // If we're not in a double quoted section 401 if(!$inquote) 402 { 403 // Expand out based on search operators (and, or) 404 $matches = preg_split("#\s{1,}(and|or)\s{1,}#", $phrase, -1, PREG_SPLIT_DELIM_CAPTURE); 405 $count_matches = count($matches); 406 407 for($i=0; $i < $count_matches; ++$i) 408 { 409 $word = trim($matches[$i]); 410 if(empty($word)) 411 { 412 continue; 413 } 414 // If this word is a search operator set the boolean 415 if($i % 2 && ($word == "and" || $word == "or")) 416 { 417 if($i <= 1) 418 { 419 if($search['subject'] && $search['message'] && $subject_lookin == " AND (") 420 { 421 // We're looking for anything, check for a subject lookin 422 continue; 423 } 424 elseif($search['subject'] && !$search['message'] && $subject_lookin == " AND (") 425 { 426 // Just in a subject? 427 continue; 428 } 429 elseif(!$search['subject'] && $search['message'] && $message_lookin == " {$string} (") 430 { 431 // Just in a message? 432 continue; 433 } 434 } 435 436 $boolean = $word; 437 } 438 // Otherwise check the length of the word as it is a normal search term 439 else 440 { 441 $word = trim($word); 442 // Word is too short - show error message 443 if(my_strlen($word) < $mybb->settings['minsearchword']) 444 { 445 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 446 error($lang->error_minsearchlength); 447 } 448 // Add terms to search query 449 if($search['subject'] == 1) 450 { 451 $subject_lookin .= " $boolean LOWER(subject) LIKE '%{$word}%'"; 452 } 453 if($search['message'] == 1) 454 { 455 $message_lookin .= " $boolean LOWER(message) LIKE '%{$word}%'"; 456 } 457 } 458 } 459 } 460 // In the middle of a quote (phrase) 461 else 462 { 463 $phrase = str_replace(array("+", "-", "*"), '', trim($phrase)); 464 if(my_strlen($phrase) < $mybb->settings['minsearchword']) 465 { 466 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 467 error($lang->error_minsearchlength); 468 } 469 // Add phrase to search query 470 $subject_lookin .= " $boolean LOWER(subject) LIKE '%{$phrase}%'"; 471 if($search['message'] == 1) 472 { 473 $message_lookin .= " $boolean LOWER(message) LIKE '%{$phrase}%'"; 474 } 475 } 476 477 // Check to see if we have any search terms and not a malformed SQL string 478 $error = false; 479 if($search['subject'] && $search['message'] && $subject_lookin == " AND (") 480 { 481 // We're looking for anything, check for a subject lookin 482 $error = true; 483 } 484 elseif($search['subject'] && !$search['message'] && $subject_lookin == " AND (") 485 { 486 // Just in a subject? 487 $error = true; 488 } 489 elseif(!$search['subject'] && $search['message'] && $message_lookin == " {$string} (") 490 { 491 // Just in a message? 492 $error = true; 493 } 494 495 if($error == true) 496 { 497 // There are no search keywords to look for 498 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 499 error($lang->error_minsearchlength); 500 } 501 502 $inquote = !$inquote; 503 } 504 505 if($search['subject'] == 1) 506 { 507 $subject_lookin .= ")"; 508 } 509 510 if($search['message'] == 1) 511 { 512 $message_lookin .= ")"; 513 } 514 515 $searchsql .= "{$subject_lookin} {$message_lookin}"; 516 } 517 else 518 { 519 $keywords = str_replace("\"", '', trim($keywords)); 520 if(my_strlen($keywords) < $mybb->settings['minsearchword']) 521 { 522 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 523 error($lang->error_minsearchlength); 524 } 525 526 // If we're looking in both, then find matches in either the subject or the message 527 if($search['subject'] == 1 && $search['message'] == 1) 528 { 529 $searchsql .= " AND (LOWER(subject) LIKE '%{$keywords}%' OR LOWER(message) LIKE '%{$keywords}%')"; 530 } 531 else 532 { 533 if($search['subject'] == 1) 534 { 535 $searchsql .= " AND LOWER(subject) LIKE '%{$keywords}%'"; 536 } 537 538 if($search['message'] == 1) 539 { 540 $searchsql .= " AND LOWER(message) LIKE '%{$keywords}%'"; 541 } 542 } 543 } 544 } 545 546 if($search['sender']) 547 { 548 $userids = array(); 549 $search['sender'] = my_strtolower($search['sender']); 550 551 $query = $db->simple_select("users", "uid", "LOWER(username) LIKE '%".$db->escape_string_like($db->escape_string($search['sender']))."%'"); 552 while($user = $db->fetch_array($query)) 553 { 554 $userids[] = $user['uid']; 555 } 556 557 if(count($userids) < 1) 558 { 559 error($lang->error_nosearchresults); 560 } 561 else 562 { 563 $userids = implode(',', $userids); 564 $searchsql .= " AND fromid IN (".$userids.")"; 565 } 566 } 567 568 if(!is_array($search['folder'])) 569 { 570 $search['folder'] = array($search['folder']); 571 } 572 573 if(!empty($search['folder'])) 574 { 575 $folderids = array(); 576 577 $search['folder'] = array_map("intval", $search['folder']); 578 579 $folderids = implode(',', $search['folder']); 580 581 if($folderids) 582 { 583 $searchsql .= " AND folder IN (".$folderids.")"; 584 } 585 } 586 587 if($search['status']) 588 { 589 $searchsql .= " AND ("; 590 if($search['status']['new']) 591 { 592 $statussql[] = " status='0' "; 593 } 594 if($search['status']['replied']) 595 { 596 $statussql[] = " status='3' "; 597 } 598 if($search['status']['forwarded']) 599 { 600 $statussql[] = " status='4' "; 601 } 602 if($search['status']['read']) 603 { 604 $statussql[] = " (status != '0' AND readtime > '0') "; 605 } 606 // Sent Folder 607 if(in_array(2, $search['folder'])) 608 { 609 $statussql[] = " status='1' "; 610 } 611 $statussql = implode("OR", $statussql); 612 $searchsql .= $statussql.")"; 613 } 614 615 // Run the search 616 $pms = array(); 617 $query = $db->simple_select("privatemessages", "pmid", $searchsql); 618 while($pm = $db->fetch_array($query)) 619 { 620 $pms[$pm['pmid']] = $pm['pmid']; 621 } 622 623 if(count($pms) < 1) 624 { 625 error($lang->error_nosearchresults); 626 } 627 $pms = implode(',', $pms); 628 629 return array( 630 "querycache" => $pms 631 ); 632 } 633 634 /** 635 * Perform a thread and post search under MySQL or MySQLi 636 * 637 * @param array Array of search data 638 * @return array Array of search data with results mixed in 639 */ 640 function perform_search_mysql($search) 641 { 642 global $mybb, $db, $lang, $cache; 643 644 $keywords = clean_keywords($search['keywords']); 645 if(!$keywords && !$search['author']) 646 { 647 error($lang->error_nosearchterms); 648 } 649 650 if($mybb->settings['minsearchword'] < 1) 651 { 652 $mybb->settings['minsearchword'] = 3; 653 } 654 655 if($keywords) 656 { 657 // Complex search 658 $keywords = " {$keywords} "; 659 if(preg_match("# and|or #", $keywords)) 660 { 661 $subject_lookin = " AND ("; 662 $message_lookin = " AND ("; 663 664 // Expand the string by double quotes 665 $keywords_exp = explode("\"", $keywords); 666 $inquote = false; 667 668 foreach($keywords_exp as $phrase) 669 { 670 // If we're not in a double quoted section 671 if(!$inquote) 672 { 673 // Expand out based on search operators (and, or) 674 $matches = preg_split("#\s{1,}(and|or)\s{1,}#", $phrase, -1, PREG_SPLIT_DELIM_CAPTURE); 675 $count_matches = count($matches); 676 677 for($i=0; $i < $count_matches; ++$i) 678 { 679 $word = trim($matches[$i]); 680 if(empty($word)) 681 { 682 continue; 683 } 684 // If this word is a search operator set the boolean 685 if($i % 2 && ($word == "and" || $word == "or")) 686 { 687 if($i <= 1 && $subject_lookin == " AND (") 688 { 689 continue; 690 } 691 692 $boolean = $word; 693 } 694 // Otherwise check the length of the word as it is a normal search term 695 else 696 { 697 $word = trim($word); 698 // Word is too short - show error message 699 if(my_strlen($word) < $mybb->settings['minsearchword']) 700 { 701 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 702 error($lang->error_minsearchlength); 703 } 704 // Add terms to search query 705 $subject_lookin .= " $boolean LOWER(t.subject) LIKE '%{$word}%'"; 706 if($search['postthread'] == 1) 707 { 708 $message_lookin .= " $boolean LOWER(p.message) LIKE '%{$word}%'"; 709 } 710 } 711 } 712 } 713 // In the middle of a quote (phrase) 714 else 715 { 716 $phrase = str_replace(array("+", "-", "*"), '', trim($phrase)); 717 if(my_strlen($phrase) < $mybb->settings['minsearchword']) 718 { 719 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 720 error($lang->error_minsearchlength); 721 } 722 // Add phrase to search query 723 $subject_lookin .= " $boolean LOWER(t.subject) LIKE '%{$phrase}%'"; 724 if($search['postthread'] == 1) 725 { 726 $message_lookin .= " $boolean LOWER(p.message) LIKE '%{$phrase}%'"; 727 } 728 } 729 730 if($subject_lookin == " AND (") 731 { 732 // There are no search keywords to look for 733 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 734 error($lang->error_minsearchlength); 735 } 736 737 $inquote = !$inquote; 738 } 739 $subject_lookin .= ")"; 740 $message_lookin .= ")"; 741 } 742 else 743 { 744 $keywords = str_replace("\"", '', trim($keywords)); 745 if(my_strlen($keywords) < $mybb->settings['minsearchword']) 746 { 747 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 748 error($lang->error_minsearchlength); 749 } 750 $subject_lookin = " AND LOWER(t.subject) LIKE '%{$keywords}%'"; 751 if($search['postthread'] == 1) 752 { 753 $message_lookin = " AND LOWER(p.message) LIKE '%{$keywords}%'"; 754 } 755 } 756 } 757 $post_usersql = ''; 758 $thread_usersql = ''; 759 if($search['author']) 760 { 761 $userids = array(); 762 if($search['matchusername']) 763 { 764 $query = $db->simple_select("users", "uid", "username='".$db->escape_string($search['author'])."'"); 765 } 766 else 767 { 768 $search['author'] = my_strtolower($search['author']); 769 $query = $db->simple_select("users", "uid", "LOWER(username) LIKE '%".$db->escape_string_like($db->escape_string($search['author']))."%'"); 770 } 771 while($user = $db->fetch_array($query)) 772 { 773 $userids[] = $user['uid']; 774 } 775 if(count($userids) < 1) 776 { 777 error($lang->error_nosearchresults); 778 } 779 else 780 { 781 $userids = implode(',', $userids); 782 $post_usersql = " AND p.uid IN (".$userids.")"; 783 $thread_usersql = " AND t.uid IN (".$userids.")"; 784 } 785 } 786 $datecut = ''; 787 if($search['postdate']) 788 { 789 if($search['pddir'] == 0) 790 { 791 $datecut = "<="; 792 } 793 else 794 { 795 $datecut = ">="; 796 } 797 $now = TIME_NOW; 798 $datelimit = $now-(86400 * $search['postdate']); 799 $datecut .= "'$datelimit'"; 800 $post_datecut = " AND p.dateline $datecut"; 801 $thread_datecut = " AND t.dateline $datecut"; 802 } 803 804 $thread_replycut = ''; 805 if($search['numreplies'] != '' && $search['findthreadst']) 806 { 807 if(intval($search['findthreadst']) == 1) 808 { 809 $thread_replycut = " AND t.replies >= '".intval($search['numreplies'])."'"; 810 } 811 else 812 { 813 $thread_replycut = " AND t.replies <= '".intval($search['numreplies'])."'"; 814 } 815 } 816 817 $thread_prefixcut = ''; 818 if($search['threadprefix'] && $search['threadprefix'] != 'any') 819 { 820 $thread_prefixcut = " AND t.prefix='".intval($search['threadprefix'])."'"; 821 } 822 823 $forumin = ''; 824 $fidlist = array(); 825 $searchin = array(); 826 if($search['forums'][0] != "all") 827 { 828 if(!is_array($search['forums'])) 829 { 830 $search['forums'] = array(intval($search['forums'])); 831 } 832 // Generate a comma separated list of all groups the user belongs to 833 $user_groups = $mybb->user['usergroup']; 834 if($mybb->user['additionalgroups']) 835 { 836 $user_groups .= ",".$mybb->user['additionalgroups']; 837 838 // Setup some quick permissions for us 839 $fcache = $cache->read("forumpermissions"); 840 $add_groups = explode(",", $mybb->user['additionalgroups']); 841 } 842 foreach($search['forums'] as $forum) 843 { 844 $forum = intval($forum); 845 if(!$searchin[$forum]) 846 { 847 if(is_array($add_groups)) 848 { 849 $can_search = 0; 850 foreach($add_groups as $add_group) 851 { 852 // Check to make sure that we have sufficient permissions to search this forum 853 if(!is_array($fcache[$forum][$add_group]) || $fcache[$forum][$add_group]['cansearch'] == 1 || $mybb->usergroup['cansearch'] == 1) 854 { 855 $can_search = 1; 856 } 857 } 858 859 if($can_search == 0) 860 { 861 // We can't search this forum... 862 continue; 863 } 864 } 865 866 switch($db->type) 867 { 868 case "pgsql": 869 $query = $db->simple_select("forums", "DISTINCT fid", "(','||parentlist||',' LIKE ',%{$forum}%,') = true AND active != 0"); 870 break; 871 case "sqlite": 872 $query = $db->simple_select("forums", "DISTINCT fid", "(','||parentlist||',' LIKE ',%{$forum}%,') > 0 AND active != 0"); 873 break; 874 default: 875 $query = $db->simple_select("forums", "DISTINCT fid", "INSTR(CONCAT(',',parentlist,','),',{$forum},') > 0 AND active != 0"); 876 } 877 878 while($sforum = $db->fetch_array($query)) 879 { 880 $fidlist[] = $sforum['fid']; 881 } 882 } 883 } 884 if(count($fidlist) == 1) 885 { 886 $forumin .= " AND t.fid='$forum' "; 887 $searchin[$fid] = 1; 888 } 889 else 890 { 891 if(count($fidlist) > 1) 892 { 893 $forumin = " AND t.fid IN (".implode(',', $fidlist).")"; 894 } 895 } 896 } 897 898 $permsql = ""; 899 $onlyusfids = array(); 900 901 // Check group permissions if we can't view threads not started by us 902 if($group_permissions = forum_permissions()) 903 { 904 foreach($group_permissions as $fid => $forum_permissions) 905 { 906 if($forum_permissions['canonlyviewownthreads'] == 1) 907 { 908 $onlyusfids[] = $fid; 909 } 910 } 911 } 912 if(!empty($onlyusfids)) 913 { 914 $permsql .= "AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; 915 } 916 917 $unsearchforums = get_unsearchable_forums(); 918 if($unsearchforums) 919 { 920 $permsql .= " AND t.fid NOT IN ($unsearchforums)"; 921 } 922 $inactiveforums = get_inactive_forums(); 923 if($inactiveforums) 924 { 925 $permsql .= " AND t.fid NOT IN ($inactiveforums)"; 926 } 927 928 $visiblesql = $post_visiblesql = $plain_post_visiblesql = ""; 929 if(isset($search['visible'])) 930 { 931 if($search['visible'] == 1) 932 { 933 $visiblesql = " AND t.visible = '1'"; 934 935 if($search['postthread'] == 1) 936 { 937 $post_visiblesql = " AND p.visible = '1'"; 938 $plain_post_visiblesql = " AND visible = '1'"; 939 } 940 } 941 else 942 { 943 $visiblesql = " AND t.visible != '1'"; 944 945 if($search['postthread'] == 1) 946 { 947 $post_visiblesql = " AND p.visible != '1'"; 948 $plain_post_visiblesql = " AND visible != '1'"; 949 } 950 } 951 } 952 953 // Searching a specific thread? 954 if($search['tid']) 955 { 956 $tidsql = " AND t.tid='".intval($search['tid'])."'"; 957 } 958 959 $limitsql = ''; 960 if(intval($mybb->settings['searchhardlimit']) > 0) 961 { 962 $limitsql = "LIMIT ".intval($mybb->settings['searchhardlimit']); 963 } 964 965 // Searching both posts and thread titles 966 $threads = array(); 967 $posts = array(); 968 $firstposts = array(); 969 if($search['postthread'] == 1) 970 { 971 // No need to search subjects when looking for results within a specific thread 972 if(!$search['tid']) 973 { 974 $query = $db->query(" 975 SELECT t.tid, t.firstpost 976 FROM ".TABLE_PREFIX."threads t 977 WHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} AND t.closed NOT LIKE 'moved|%' {$subject_lookin} 978 {$limitsql} 979 "); 980 while($thread = $db->fetch_array($query)) 981 { 982 $threads[$thread['tid']] = $thread['tid']; 983 if($thread['firstpost']) 984 { 985 $posts[$thread['tid']] = $thread['firstpost']; 986 } 987 } 988 } 989 990 $query = $db->query(" 991 SELECT p.pid, p.tid 992 FROM ".TABLE_PREFIX."posts p 993 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) 994 WHERE 1=1 {$post_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$post_usersql} {$permsql} {$tidsql} {$visiblesql} {$post_visiblesql} AND t.closed NOT LIKE 'moved|%' {$message_lookin} 995 {$limitsql} 996 "); 997 while($post = $db->fetch_array($query)) 998 { 999 $posts[$post['pid']] = $post['pid']; 1000 $threads[$post['tid']] = $post['tid']; 1001 } 1002 1003 if(count($posts) < 1 && count($threads) < 1) 1004 { 1005 error($lang->error_nosearchresults); 1006 } 1007 $threads = implode(',', $threads); 1008 $posts = implode(',', $posts); 1009 1010 } 1011 // Searching only thread titles 1012 else 1013 { 1014 $query = $db->query(" 1015 SELECT t.tid, t.firstpost 1016 FROM ".TABLE_PREFIX."threads t 1017 WHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} {$subject_lookin} 1018 {$limitsql} 1019 "); 1020 while($thread = $db->fetch_array($query)) 1021 { 1022 $threads[$thread['tid']] = $thread['tid']; 1023 if($thread['firstpost']) 1024 { 1025 $firstposts[$thread['tid']] = $thread['firstpost']; 1026 } 1027 } 1028 if(count($threads) < 1) 1029 { 1030 error($lang->error_nosearchresults); 1031 } 1032 1033 $threads = implode(',', $threads); 1034 $firstposts = implode(',', $firstposts); 1035 if($firstposts) 1036 { 1037 $query = $db->simple_select("posts", "pid", "pid IN ($firstposts) {$plain_post_visiblesql} {$limitsql}"); 1038 while($post = $db->fetch_array($query)) 1039 { 1040 $posts[$post['pid']] = $post['pid']; 1041 } 1042 $posts = implode(',', $posts); 1043 } 1044 } 1045 return array( 1046 "threads" => $threads, 1047 "posts" => $posts, 1048 "querycache" => '' 1049 ); 1050 } 1051 1052 /** 1053 * Perform a thread and post search under MySQL or MySQLi using boolean fulltext capabilities 1054 * 1055 * @param array Array of search data 1056 * @return array Array of search data with results mixed in 1057 */ 1058 function perform_search_mysql_ft($search) 1059 { 1060 global $mybb, $db, $lang; 1061 1062 $keywords = clean_keywords_ft($search['keywords']); 1063 if(!$keywords && !$search['author']) 1064 { 1065 error($lang->error_nosearchterms); 1066 } 1067 1068 // Attempt to determine minimum word length from MySQL for fulltext searches 1069 $query = $db->query("SHOW VARIABLES LIKE 'ft_min_word_len';"); 1070 $min_length = $db->fetch_field($query, 'Value'); 1071 if(is_numeric($min_length)) 1072 { 1073 $mybb->settings['minsearchword'] = $min_length; 1074 } 1075 // Otherwise, could not fetch - default back to MySQL fulltext default setting 1076 else 1077 { 1078 $mybb->settings['minsearchword'] = 4; 1079 } 1080 1081 if($keywords) 1082 { 1083 $keywords_exp = explode("\"", $keywords); 1084 $inquote = false; 1085 foreach($keywords_exp as $phrase) 1086 { 1087 if(!$inquote) 1088 { 1089 $split_words = preg_split("#\s{1,}#", $phrase, -1); 1090 foreach($split_words as $word) 1091 { 1092 $word = str_replace(array("+", "-", "*"), '', $word); 1093 if(!$word) 1094 { 1095 continue; 1096 } 1097 if(my_strlen($word) < $mybb->settings['minsearchword']) 1098 { 1099 $all_too_short = true; 1100 } 1101 else 1102 { 1103 $all_too_short = false; 1104 break; 1105 } 1106 } 1107 } 1108 else 1109 { 1110 $phrase = str_replace(array("+", "-", "*"), '', $phrase); 1111 if(my_strlen($phrase) < $mybb->settings['minsearchword']) 1112 { 1113 $all_too_short = true; 1114 } 1115 else 1116 { 1117 $all_too_short = false; 1118 break; 1119 } 1120 } 1121 $inquote = !$inquote; 1122 } 1123 // Show the minimum search term error only if all search terms are too short 1124 if($all_too_short == true) 1125 { 1126 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 1127 error($lang->error_minsearchlength); 1128 } 1129 $message_lookin = "AND MATCH(message) AGAINST('".$db->escape_string($keywords)."' IN BOOLEAN MODE)"; 1130 $subject_lookin = "AND MATCH(subject) AGAINST('".$db->escape_string($keywords)."' IN BOOLEAN MODE)"; 1131 } 1132 $post_usersql = ''; 1133 $thread_usersql = ''; 1134 if($search['author']) 1135 { 1136 $userids = array(); 1137 if($search['matchusername']) 1138 { 1139 $query = $db->simple_select("users", "uid", "username='".$db->escape_string($search['author'])."'"); 1140 } 1141 else 1142 { 1143 $search['author'] = my_strtolower($search['author']); 1144 $query = $db->simple_select("users", "uid", "LOWER(username) LIKE '%".$db->escape_string_like($db->escape_string($search['author']))."%'"); 1145 } 1146 1147 while($user = $db->fetch_array($query)) 1148 { 1149 $userids[] = $user['uid']; 1150 } 1151 1152 if(count($userids) < 1) 1153 { 1154 error($lang->error_nosearchresults); 1155 } 1156 else 1157 { 1158 $userids = implode(',', $userids); 1159 $post_usersql = " AND p.uid IN (".$userids.")"; 1160 $thread_usersql = " AND t.uid IN (".$userids.")"; 1161 } 1162 } 1163 $datecut = ''; 1164 if($search['postdate']) 1165 { 1166 if($search['pddir'] == 0) 1167 { 1168 $datecut = "<="; 1169 } 1170 else 1171 { 1172 $datecut = ">="; 1173 } 1174 $now = TIME_NOW; 1175 $datelimit = $now-(86400 * $search['postdate']); 1176 $datecut .= "'$datelimit'"; 1177 $post_datecut = " AND p.dateline $datecut"; 1178 $thread_datecut = " AND t.dateline $datecut"; 1179 } 1180 1181 $thread_replycut = ''; 1182 if($search['numreplies'] != '' && $search['findthreadst']) 1183 { 1184 if(intval($search['findthreadst']) == 1) 1185 { 1186 $thread_replycut = " AND t.replies >= '".intval($search['numreplies'])."'"; 1187 } 1188 else 1189 { 1190 $thread_replycut = " AND t.replies <= '".intval($search['numreplies'])."'"; 1191 } 1192 } 1193 1194 $thread_prefixcut = ''; 1195 if($search['threadprefix'] && $search['threadprefix'] != 'any') 1196 { 1197 $thread_prefixcut = " AND t.prefix='".intval($search['threadprefix'])."'"; 1198 } 1199 1200 $forumin = ''; 1201 $fidlist = array(); 1202 $searchin = array(); 1203 if($search['forums'][0] != "all") 1204 { 1205 if(!is_array($search['forums'])) 1206 { 1207 $search['forums'] = array(intval($search['forums'])); 1208 } 1209 // Generate a comma separated list of all groups the user belongs to 1210 $user_groups = $mybb->user['usergroup']; 1211 if($mybb->user['additionalgroups']) 1212 { 1213 $user_groups .= ",".$mybb->user['additionalgroups']; 1214 } 1215 foreach($search['forums'] as $forum) 1216 { 1217 $forum = intval($forum); 1218 if(!$searchin[$forum]) 1219 { 1220 switch($db->type) 1221 { 1222 case "pgsql": 1223 case "sqlite": 1224 $query = $db->query(" 1225 SELECT f.fid 1226 FROM ".TABLE_PREFIX."forums f 1227 LEFT JOIN ".TABLE_PREFIX."forumpermissions p ON (f.fid=p.fid AND p.gid IN (".$user_groups.")) 1228 WHERE INSTR(','||parentlist||',',',$forum,') > 0 AND active!=0 AND (ISNULL(p.fid) OR p.cansearch=1) 1229 "); 1230 break; 1231 default: 1232 $query = $db->query(" 1233 SELECT f.fid 1234 FROM ".TABLE_PREFIX."forums f 1235 LEFT JOIN ".TABLE_PREFIX."forumpermissions p ON (f.fid=p.fid AND p.gid IN (".$user_groups.")) 1236 WHERE INSTR(CONCAT(',',parentlist,','),',$forum,') > 0 AND active!=0 AND (ISNULL(p.fid) OR p.cansearch=1) 1237 "); 1238 } 1239 while($sforum = $db->fetch_array($query)) 1240 { 1241 $fidlist[] = $sforum['fid']; 1242 } 1243 } 1244 } 1245 if(count($fidlist) == 1) 1246 { 1247 $forumin .= " AND t.fid='$forum' "; 1248 $searchin[$fid] = 1; 1249 } 1250 else 1251 { 1252 1253 if(count($fidlist) > 1) 1254 { 1255 $forumin = " AND t.fid IN (".implode(',', $fidlist).")"; 1256 } 1257 } 1258 } 1259 $permsql = ""; 1260 $onlyusfids = array(); 1261 1262 // Check group permissions if we can't view threads not started by us 1263 $group_permissions = forum_permissions(); 1264 foreach($group_permissions as $fid => $forum_permissions) 1265 { 1266 if($forum_permissions['canonlyviewownthreads'] == 1) 1267 { 1268 $onlyusfids[] = $fid; 1269 } 1270 } 1271 if(!empty($onlyusfids)) 1272 { 1273 $permsql .= "AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; 1274 } 1275 1276 $unsearchforums = get_unsearchable_forums(); 1277 if($unsearchforums) 1278 { 1279 $permsql .= " AND t.fid NOT IN ($unsearchforums)"; 1280 } 1281 $inactiveforums = get_inactive_forums(); 1282 if($inactiveforums) 1283 { 1284 $permsql .= " AND t.fid NOT IN ($inactiveforums)"; 1285 } 1286 1287 $visiblesql = $post_visiblesql = $plain_post_visiblesql = ""; 1288 if(isset($search['visible'])) 1289 { 1290 if($search['visible'] == 1) 1291 { 1292 $visiblesql = " AND t.visible = '1'"; 1293 1294 if($search['postthread'] == 1) 1295 { 1296 $post_visiblesql = " AND p.visible = '1'"; 1297 $plain_post_visiblesql = " AND visible = '1'"; 1298 } 1299 } 1300 else 1301 { 1302 $visiblesql = " AND t.visible != '1'"; 1303 1304 if($search['postthread'] == 1) 1305 { 1306 $post_visiblesql = " AND p.visible != '1'"; 1307 $plain_post_visiblesql = " AND visible != '1'"; 1308 } 1309 } 1310 } 1311 1312 // Searching a specific thread? 1313 if($search['tid']) 1314 { 1315 $tidsql = " AND t.tid='".intval($search['tid'])."'"; 1316 } 1317 1318 $limitsql = ''; 1319 if(intval($mybb->settings['searchhardlimit']) > 0) 1320 { 1321 $limitsql = "LIMIT ".intval($mybb->settings['searchhardlimit']); 1322 } 1323 1324 // Searching both posts and thread titles 1325 $threads = array(); 1326 $posts = array(); 1327 $firstposts = array(); 1328 if($search['postthread'] == 1) 1329 { 1330 // No need to search subjects when looking for results within a specific thread 1331 if(!$search['tid']) 1332 { 1333 $query = $db->query(" 1334 SELECT t.tid, t.firstpost 1335 FROM ".TABLE_PREFIX."threads t 1336 WHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} AND t.closed NOT LIKE 'moved|%' {$subject_lookin} 1337 {$limitsql} 1338 "); 1339 while($thread = $db->fetch_array($query)) 1340 { 1341 $threads[$thread['tid']] = $thread['tid']; 1342 if($thread['firstpost']) 1343 { 1344 $posts[$thread['tid']] = $thread['firstpost']; 1345 } 1346 } 1347 } 1348 1349 $query = $db->query(" 1350 SELECT p.pid, p.tid 1351 FROM ".TABLE_PREFIX."posts p 1352 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) 1353 WHERE 1=1 {$post_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$post_usersql} {$permsql} {$tidsql} {$post_visiblesql} {$visiblesql} AND t.closed NOT LIKE 'moved|%' {$message_lookin} 1354 {$limitsql} 1355 "); 1356 while($post = $db->fetch_array($query)) 1357 { 1358 $posts[$post['pid']] = $post['pid']; 1359 $threads[$post['tid']] = $post['tid']; 1360 } 1361 if(count($posts) < 1 && count($threads) < 1) 1362 { 1363 error($lang->error_nosearchresults); 1364 } 1365 $threads = implode(',', $threads); 1366 $posts = implode(',', $posts); 1367 1368 } 1369 // Searching only thread titles 1370 else 1371 { 1372 $query = $db->query(" 1373 SELECT t.tid, t.firstpost 1374 FROM ".TABLE_PREFIX."threads t 1375 WHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} {$subject_lookin} 1376 {$limitsql} 1377 "); 1378 while($thread = $db->fetch_array($query)) 1379 { 1380 $threads[$thread['tid']] = $thread['tid']; 1381 if($thread['firstpost']) 1382 { 1383 $firstposts[$thread['tid']] = $thread['firstpost']; 1384 } 1385 } 1386 if(count($threads) < 1) 1387 { 1388 error($lang->error_nosearchresults); 1389 } 1390 1391 $threads = implode(',', $threads); 1392 $firstposts = implode(',', $firstposts); 1393 if($firstposts) 1394 { 1395 $query = $db->simple_select("posts", "pid", "pid IN ($firstposts) {$plain_post_visiblesql} {$limitsql}"); 1396 while($post = $db->fetch_array($query)) 1397 { 1398 $posts[$post['pid']] = $post['pid']; 1399 } 1400 $posts = implode(',', $posts); 1401 } 1402 } 1403 return array( 1404 "threads" => $threads, 1405 "posts" => $posts, 1406 "querycache" => '' 1407 ); 1408 } 1409 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Oct 8 19:19:50 2013 | Cross-referenced by PHPXref 0.7.1 |