[ Index ] |
PHP Cross Reference of MyBB 1.8.30 |
[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 /** 12 * Build a select box list of forums the current user has permission to search 13 * 14 * @param int $pid The parent forum ID to start at 15 * @param int $selitem The selected forum ID 16 * @param int $addselect Add select boxes at this call or not 17 * @param string $depth The current depth 18 * @return string The forum select boxes 19 */ 20 function make_searchable_forums($pid=0, $selitem=0, $addselect=1, $depth='') 21 { 22 global $db, $pforumcache, $permissioncache, $mybb, $selecteddone, $forumlist, $forumlistbits, $theme, $templates, $lang, $forumpass; 23 $pid = (int)$pid; 24 25 if(!is_array($pforumcache)) 26 { 27 // Get Forums 28 $query = $db->simple_select("forums", "pid,disporder,fid,password,name", "linkto='' AND active!=0", array('order_by' => "pid, disporder")); 29 while($forum = $db->fetch_array($query)) 30 { 31 $pforumcache[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum; 32 } 33 } 34 if(!is_array($permissioncache)) 35 { 36 $permissioncache = forum_permissions(); 37 } 38 if(is_array($pforumcache[$pid])) 39 { 40 foreach($pforumcache[$pid] as $key => $main) 41 { 42 foreach($main as $key => $forum) 43 { 44 $perms = $permissioncache[$forum['fid']]; 45 if(($perms['canview'] == 1 || $mybb->settings['hideprivateforums'] == 0) && $perms['cansearch'] != 0) 46 { 47 if($selitem == $forum['fid']) 48 { 49 $optionselected = "selected"; 50 $selecteddone = "1"; 51 } 52 else 53 { 54 $optionselected = ''; 55 $selecteddone = "0"; 56 } 57 if(forum_password_validated($forum, true)) 58 { 59 eval("\$forumlistbits .= \"".$templates->get("search_forumlist_forum")."\";"); 60 } 61 if(!empty($pforumcache[$forum['fid']])) 62 { 63 $newdepth = $depth." "; 64 $forumlistbits .= make_searchable_forums($forum['fid'], $selitem, 0, $newdepth); 65 } 66 } 67 } 68 } 69 } 70 if($addselect) 71 { 72 eval("\$forumlist = \"".$templates->get("search_forumlist")."\";"); 73 } 74 return $forumlist; 75 } 76 77 /** 78 * Build a comma separated list of the forums this user cannot search 79 * 80 * @param int $pid The parent ID to build from 81 * @param int $first First rotation or not (leave at default) 82 * @return string return a CSV list of forums the user cannot search 83 */ 84 function get_unsearchable_forums($pid=0, $first=1) 85 { 86 global $db, $forum_cache, $permissioncache, $mybb, $unsearchableforums, $unsearchable, $templates, $forumpass; 87 88 $pid = (int)$pid; 89 90 if(!is_array($forum_cache)) 91 { 92 // Get Forums 93 $query = $db->simple_select("forums", "fid,parentlist,password,active", '', array('order_by' => 'pid, disporder')); 94 while($forum = $db->fetch_array($query)) 95 { 96 $forum_cache[$forum['fid']] = $forum; 97 } 98 } 99 if(!is_array($permissioncache)) 100 { 101 $permissioncache = forum_permissions(); 102 } 103 foreach($forum_cache as $fid => $forum) 104 { 105 if($permissioncache[$forum['fid']]) 106 { 107 $perms = $permissioncache[$forum['fid']]; 108 } 109 else 110 { 111 $perms = $mybb->usergroup; 112 } 113 114 $parents = explode(",", $forum['parentlist']); 115 if(is_array($parents)) 116 { 117 foreach($parents as $parent) 118 { 119 if($forum_cache[$parent]['active'] == 0) 120 { 121 $forum['active'] = 0; 122 } 123 } 124 } 125 126 if($perms['canview'] != 1 || $perms['cansearch'] != 1 || !forum_password_validated($forum, true) || $forum['active'] == 0) 127 { 128 if($unsearchableforums) 129 { 130 $unsearchableforums .= ","; 131 } 132 $unsearchableforums .= "'{$forum['fid']}'"; 133 } 134 } 135 $unsearchable = $unsearchableforums; 136 137 // Get our unsearchable password protected forums 138 $pass_protected_forums = get_password_protected_forums(); 139 140 if($unsearchable && $pass_protected_forums) 141 { 142 $unsearchable .= ","; 143 } 144 145 if($pass_protected_forums) 146 { 147 $unsearchable .= implode(",", $pass_protected_forums); 148 } 149 150 return $unsearchable; 151 } 152 153 /** 154 * Build query condition for threads/posts the user is allowed to see. 155 * Will return for example: 156 * - visible = 1 - for normal users 157 * - visible >= -1 - for admins & super mods 158 * - (visible = 1 OR (visible = ? AND fid IN ...)) - for forum moderators 159 * 160 * @param string $table_alias The alias of the table eg t to use t.visible instead of visible 161 * @return string the query condition 162 */ 163 function get_visible_where($table_alias = null) 164 { 165 global $db, $mybb; 166 167 $aliasdot = ''; 168 if(!empty($table_alias)) 169 { 170 $aliasdot = $table_alias.'.'; 171 } 172 173 if($mybb->usergroup['issupermod'] == 1) 174 { 175 // Super moderators (and admins) 176 return "{$aliasdot}visible >= -1"; 177 } 178 elseif(is_moderator()) 179 { 180 // Normal moderators 181 $unapprove_forums = array(); 182 $deleted_forums = array(); 183 $unapproved_where = "({$aliasdot}visible = 1"; 184 185 $moderated_fids = get_moderated_fids($mybb->user['uid']); 186 187 if($moderated_fids !== false) 188 { 189 foreach($moderated_fids as $fid) 190 { 191 if(!is_moderator($fid)) 192 { 193 // Shouldn't occur. 194 continue; 195 } 196 197 // Use moderates this forum 198 $modperms = get_moderator_permissions($fid, $mybb->user['uid']); 199 200 if($modperms['canviewunapprove'] == 1) 201 { 202 $unapprove_forums[] = $fid; 203 } 204 205 if($modperms['canviewdeleted'] == 1) 206 { 207 $deleted_forums[] = $fid; 208 } 209 } 210 211 if(!empty($unapprove_forums)) 212 { 213 $unapproved_where .= " OR ({$aliasdot}visible = 0 AND {$aliasdot}fid IN(".implode(',', $unapprove_forums)."))"; 214 } 215 if(!empty($deleted_forums)) 216 { 217 $unapproved_where .= " OR ({$aliasdot}visible = -1 AND {$aliasdot}fid IN(".implode(',', $deleted_forums)."))"; 218 } 219 $unapproved_where .= ')'; 220 221 return $unapproved_where; 222 } 223 } 224 225 // Normal users 226 if($mybb->user['uid'] > 0 && $mybb->settings['showownunapproved'] == 1) 227 { 228 return "({$aliasdot}visible = 1 OR ({$aliasdot}visible = 0 AND {$aliasdot}uid = {$mybb->user['uid']}))"; 229 } 230 return "{$aliasdot}visible = 1"; 231 } 232 233 /** 234 * Build a array list of the forums this user cannot search due to password protection 235 * 236 * @param array $fids the fids to check (leave blank to check all forums) 237 * @return array return a array list of password protected forums the user cannot search 238 */ 239 function get_password_protected_forums($fids=array()) 240 { 241 global $forum_cache, $mybb; 242 243 if(!is_array($fids)) 244 { 245 return false; 246 } 247 248 if(!is_array($forum_cache)) 249 { 250 $forum_cache = cache_forums(); 251 if(!$forum_cache) 252 { 253 return false; 254 } 255 } 256 257 if(empty($fids)) 258 { 259 $fids = array_keys($forum_cache); 260 } 261 262 $pass_fids = array(); 263 foreach($fids as $fid) 264 { 265 if(!forum_password_validated($forum_cache[$fid], true)) 266 { 267 $pass_fids[] = $fid; 268 $pass_fids = array_merge($pass_fids, get_child_list($fid)); 269 } 270 } 271 return array_unique($pass_fids); 272 } 273 274 /** 275 * Clean search keywords and make them safe for querying 276 * 277 * @param string $keywords The keywords to be cleaned 278 * @return string The cleaned keywords 279 */ 280 function clean_keywords($keywords) 281 { 282 global $db, $lang; 283 284 $keywords = my_strtolower($keywords); 285 $keywords = $db->escape_string_like($keywords); 286 $keywords = preg_replace("#\*{2,}#s", "*", $keywords); 287 $keywords = str_replace("*", "%", $keywords); 288 $keywords = preg_replace("#\s+#s", " ", $keywords); 289 $keywords = str_replace('\\"', '"', $keywords); 290 291 // Search for "and" or "or" and remove if it's at the beginning 292 $keywords = trim($keywords); 293 if(my_strpos($keywords, "or") === 0) 294 { 295 $keywords = substr_replace($keywords, "", 0, 2); 296 $keywords = " ".$keywords; 297 } 298 299 if(my_strpos($keywords, "and") === 0) 300 { 301 $keywords = substr_replace($keywords, "", 0, 3); 302 $keywords = " ".$keywords; 303 } 304 305 if(!$keywords) 306 { 307 error($lang->error_nosearchterms); 308 } 309 310 return $keywords; 311 } 312 313 /** 314 * Clean search keywords for fulltext searching, making them safe for querying 315 * 316 * @param string $keywords The keywords to be cleaned 317 * @return string|bool The cleaned keywords or false on failure 318 */ 319 function clean_keywords_ft($keywords) 320 { 321 if(!$keywords) 322 { 323 return false; 324 } 325 $keywords = my_strtolower($keywords); 326 $keywords = str_replace("%", "\\%", $keywords); 327 $keywords = preg_replace("#\*{2,}#s", "*", $keywords); 328 $keywords = preg_replace("#([\[\]\|\.\,:])#s", " ", $keywords); 329 // Separate braces for further processing 330 $keywords = preg_replace("#((\+|-|<|>|~)?\(|\))#s", " $1 ", $keywords); 331 $keywords = preg_replace("#\s+#s", " ", $keywords); 332 333 global $mybb; 334 335 $min_word_length = (int) $mybb->settings['minsearchword']; 336 if($min_word_length <= 0) 337 { 338 $min_word_length = 3; 339 } 340 $min_word_length -= 1; 341 342 $word_length_regex = ''; 343 if($min_word_length > 1) 344 { 345 $word_length_regex = "{1,{$min_word_length}}"; 346 } 347 348 // Replaces less than 3 characters 349 $keywords = preg_replace("/(\b.{$word_length_regex})(\s)|(\b.{$word_length_regex}$)/u", '$2', $keywords); 350 // Collapse multiple spaces 351 $keywords = preg_replace('/(\s)+/', '$1', $keywords); 352 $keywords = trim($keywords); 353 354 $words = array(array()); 355 356 // Fulltext search syntax validation: http://dev.mysql.com/doc/refman/5.6/en/fulltext-boolean.html 357 // Search for phrases 358 $keywords = explode("\"", $keywords); 359 $boolean = array('+'); 360 // Brace depth 361 $depth = 0; 362 $phrase_operator = '+'; 363 foreach($keywords as $phrase) 364 { 365 $phrase = trim($phrase); 366 if($phrase != '') 367 { 368 if($inquote) 369 { 370 if($phrase_operator) 371 { 372 $boolean[$depth] = $phrase_operator; 373 } 374 // Phrases do not need further processing 375 $words[$depth][] = "{$boolean[$depth]}\"{$phrase}\""; 376 $boolean[$depth] = $phrase_operator = '+'; 377 } 378 else 379 { 380 // Split words 381 $split_words = preg_split("#\s{1,}#", $phrase, -1); 382 if(!is_array($split_words)) 383 { 384 continue; 385 } 386 if(!$inquote) 387 { 388 // Save possible operator in front of phrase 389 $last_char = substr($phrase, -1); 390 if($last_char == '+' || $last_char == '-' || $last_char == '<' || $last_char == '>' || $last_char == '~') 391 { 392 $phrase_operator = $last_char; 393 } 394 } 395 foreach($split_words as $word) 396 { 397 $word = trim($word); 398 if($word == "or") 399 { 400 $boolean[$depth] = ''; 401 // Remove "and" operator from previous element 402 $last = array_pop($words[$depth]); 403 if($last) 404 { 405 if(substr($last, 0, 1) == '+') 406 { 407 $last = substr($last, 1); 408 } 409 $words[$depth][] = $last; 410 } 411 } 412 elseif($word == "and") 413 { 414 $boolean[$depth] = "+"; 415 } 416 elseif($word == "not") 417 { 418 $boolean[$depth] = "-"; 419 } 420 // Closing braces 421 elseif($word == ")") 422 { 423 // Ignore when no brace was opened 424 if($depth > 0) 425 { 426 $words[$depth-1][] = $boolean[$depth-1].'('.implode(' ', $words[$depth]).')'; 427 --$depth; 428 } 429 } 430 // Valid operators for opening braces 431 elseif($word == '+(' || $word == '-(' || $word == '<(' || $word == '>(' || $word == '~(' || $word == '(') 432 { 433 if(strlen($word) == 2) 434 { 435 $boolean[$depth] = substr($word, 0, 1); 436 } 437 $words[++$depth] = array(); 438 $boolean[$depth] = '+'; 439 } 440 else 441 { 442 $operator = substr($word, 0, 1); 443 switch($operator) 444 { 445 // Allowed operators 446 case '-': 447 case '+': 448 case '>': 449 case '<': 450 case '~': 451 $word = substr($word, 1); 452 break; 453 default: 454 $operator = $boolean[$depth]; 455 break; 456 } 457 // Removed operators that are only allowed at the beginning 458 $word = preg_replace("#(-|\+|<|>|~|@)#s", '', $word); 459 // Removing wildcards at the beginning http://bugs.mysql.com/bug.php?id=72605 460 $word = preg_replace("#^\*#s", '', $word); 461 $word = $operator.$word; 462 if(strlen($word) <= 1) 463 { 464 continue; 465 } 466 $words[$depth][] = $word; 467 $boolean[$depth] = '+'; 468 } 469 } 470 } 471 } 472 $inquote = !$inquote; 473 } 474 475 // Close mismatching braces 476 while($depth > 0) 477 { 478 $words[$depth-1][] = $boolean[$depth-1].'('.implode(' ', $words[$depth]).')'; 479 --$depth; 480 } 481 482 $keywords = implode(' ', $words[0]); 483 return $keywords; 484 } 485 486 /* Database engine specific search functions */ 487 488 /** 489 * Perform a thread and post search under MySQL or MySQLi 490 * 491 * @param array $search Array of search data 492 * @return array Array of search data with results mixed in 493 */ 494 function privatemessage_perform_search_mysql($search) 495 { 496 global $mybb, $db, $lang; 497 498 $keywords = clean_keywords($search['keywords']); 499 if(!$keywords && !$search['sender']) 500 { 501 error($lang->error_nosearchterms); 502 } 503 504 if($mybb->settings['minsearchword'] < 1) 505 { 506 $mybb->settings['minsearchword'] = 3; 507 } 508 509 $subject_lookin = ""; 510 $message_lookin = ""; 511 $searchsql = "uid='{$mybb->user['uid']}'"; 512 513 if($keywords) 514 { 515 // Complex search 516 $keywords = " {$keywords} "; 517 518 switch($db->type) 519 { 520 case 'mysql': 521 case 'mysqli': 522 $sfield = 'subject'; 523 $mfield = 'message'; 524 break; 525 default: 526 $sfield = 'LOWER(subject)'; 527 $mfield = 'LOWER(message)'; 528 break; 529 } 530 531 if(preg_match("#\s(and|or)\s#", $keywords)) 532 { 533 $string = "AND"; 534 if($search['subject'] == 1) 535 { 536 $string = "OR"; 537 $subject_lookin = " AND ("; 538 } 539 540 if($search['message'] == 1) 541 { 542 $message_lookin = " {$string} ("; 543 } 544 545 // Expand the string by double quotes 546 $keywords_exp = explode("\"", $keywords); 547 $inquote = false; 548 $boolean = ''; 549 550 foreach($keywords_exp as $phrase) 551 { 552 // If we're not in a double quoted section 553 if(!$inquote) 554 { 555 // Expand out based on search operators (and, or) 556 $matches = preg_split("#\s{1,}(and|or)\s{1,}#", $phrase, -1, PREG_SPLIT_DELIM_CAPTURE); 557 $count_matches = count($matches); 558 559 for($i=0; $i < $count_matches; ++$i) 560 { 561 $word = trim($matches[$i]); 562 if(empty($word)) 563 { 564 continue; 565 } 566 // If this word is a search operator set the boolean 567 if($i % 2 && ($word == "and" || $word == "or")) 568 { 569 if($i <= 1) 570 { 571 if($search['subject'] && $search['message'] && $subject_lookin == " AND (") 572 { 573 // We're looking for anything, check for a subject lookin 574 continue; 575 } 576 elseif($search['subject'] && !$search['message'] && $subject_lookin == " AND (") 577 { 578 // Just in a subject? 579 continue; 580 } 581 elseif(!$search['subject'] && $search['message'] && $message_lookin == " {$string} (") 582 { 583 // Just in a message? 584 continue; 585 } 586 } 587 588 $boolean = $word; 589 } 590 // Otherwise check the length of the word as it is a normal search term 591 else 592 { 593 $word = trim($word); 594 // Word is too short - show error message 595 if(my_strlen($word) < $mybb->settings['minsearchword']) 596 { 597 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 598 error($lang->error_minsearchlength); 599 } 600 601 // Add terms to search query 602 if($search['subject'] == 1) 603 { 604 $subject_lookin .= " $boolean {$sfield} LIKE '%{$word}%'"; 605 } 606 if($search['message'] == 1) 607 { 608 $message_lookin .= " $boolean {$mfield} LIKE '%{$word}%'"; 609 } 610 $boolean = 'AND'; 611 } 612 } 613 } 614 // In the middle of a quote (phrase) 615 else 616 { 617 $phrase = str_replace(array("+", "-", "*"), '', trim($phrase)); 618 if(my_strlen($phrase) < $mybb->settings['minsearchword']) 619 { 620 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 621 error($lang->error_minsearchlength); 622 } 623 // Add phrase to search query 624 $subject_lookin .= " $boolean {$sfield} LIKE '%{$phrase}%'"; 625 if($search['message'] == 1) 626 { 627 $message_lookin .= " $boolean {$mfield} LIKE '%{$phrase}%'"; 628 } 629 $boolean = 'AND'; 630 } 631 632 // Check to see if we have any search terms and not a malformed SQL string 633 $error = false; 634 if($search['subject'] && $search['message'] && $subject_lookin == " AND (") 635 { 636 // We're looking for anything, check for a subject lookin 637 $error = true; 638 } 639 elseif($search['subject'] && !$search['message'] && $subject_lookin == " AND (") 640 { 641 // Just in a subject? 642 $error = true; 643 } 644 elseif(!$search['subject'] && $search['message'] && $message_lookin == " {$string} (") 645 { 646 // Just in a message? 647 $error = true; 648 } 649 650 if($error == true) 651 { 652 // There are no search keywords to look for 653 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 654 error($lang->error_minsearchlength); 655 } 656 657 $inquote = !$inquote; 658 } 659 660 if($search['subject'] == 1) 661 { 662 $subject_lookin .= ")"; 663 } 664 665 if($search['message'] == 1) 666 { 667 $message_lookin .= ")"; 668 } 669 670 $searchsql .= "{$subject_lookin} {$message_lookin}"; 671 } 672 else 673 { 674 $keywords = str_replace("\"", '', trim($keywords)); 675 if(my_strlen($keywords) < $mybb->settings['minsearchword']) 676 { 677 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 678 error($lang->error_minsearchlength); 679 } 680 681 // If we're looking in both, then find matches in either the subject or the message 682 if($search['subject'] == 1 && $search['message'] == 1) 683 { 684 $searchsql .= " AND ({$sfield} LIKE '%{$keywords}%' OR {$mfield} LIKE '%{$keywords}%')"; 685 } 686 else 687 { 688 if($search['subject'] == 1) 689 { 690 $searchsql .= " AND {$sfield} LIKE '%{$keywords}%'"; 691 } 692 693 if($search['message'] == 1) 694 { 695 $searchsql .= " AND {$mfield} LIKE '%{$keywords}%'"; 696 } 697 } 698 } 699 } 700 701 if($search['sender']) 702 { 703 $userids = array(); 704 $search['sender'] = my_strtolower($search['sender']); 705 706 switch($db->type) 707 { 708 case 'mysql': 709 case 'mysqli': 710 $field = 'username'; 711 break; 712 default: 713 $field = 'LOWER(username)'; 714 break; 715 } 716 $query = $db->simple_select("users", "uid", "{$field} LIKE '%".$db->escape_string_like($search['sender'])."%'"); 717 while($user = $db->fetch_array($query)) 718 { 719 $userids[] = $user['uid']; 720 } 721 722 if(count($userids) < 1) 723 { 724 error($lang->error_nosearchresults); 725 } 726 else 727 { 728 $userids = implode(',', $userids); 729 $searchsql .= " AND fromid IN (".$userids.")"; 730 } 731 } 732 733 if(!is_array($search['folder'])) 734 { 735 $search['folder'] = array($search['folder']); 736 } 737 738 if(!empty($search['folder'])) 739 { 740 $folderids = array(); 741 742 $search['folder'] = array_map("intval", $search['folder']); 743 744 $folderids = implode(',', $search['folder']); 745 746 if($folderids) 747 { 748 $searchsql .= " AND folder IN (".$folderids.")"; 749 } 750 } 751 752 if($search['status']) 753 { 754 $searchsql .= " AND ("; 755 if($search['status']['new']) 756 { 757 $statussql[] = " status='0' "; 758 } 759 if($search['status']['replied']) 760 { 761 $statussql[] = " status='3' "; 762 } 763 if($search['status']['forwarded']) 764 { 765 $statussql[] = " status='4' "; 766 } 767 if($search['status']['read']) 768 { 769 $statussql[] = " (status != '0' AND readtime > '0') "; 770 } 771 // Sent Folder 772 if(in_array(2, $search['folder'])) 773 { 774 $statussql[] = " status='1' "; 775 } 776 $statussql = implode("OR", $statussql); 777 $searchsql .= $statussql.")"; 778 } 779 780 $limitsql = ""; 781 if((int)$mybb->settings['searchhardlimit'] > 0) 782 { 783 $limitsql = " LIMIT ".(int)$mybb->settings['searchhardlimit']; 784 } 785 $searchsql .= $limitsql; 786 787 // Run the search 788 $pms = array(); 789 $query = $db->simple_select("privatemessages", "pmid", $searchsql); 790 while($pm = $db->fetch_array($query)) 791 { 792 $pms[$pm['pmid']] = $pm['pmid']; 793 } 794 795 if(count($pms) < 1) 796 { 797 error($lang->error_nosearchresults); 798 } 799 $pms = implode(',', $pms); 800 801 return array( 802 "querycache" => $pms 803 ); 804 } 805 806 /** 807 * Perform a help document search under MySQL or MySQLi 808 * 809 * @param array $search Array of search data 810 * @return array Array of search data with results mixed in 811 */ 812 function helpdocument_perform_search_mysql($search) 813 { 814 global $mybb, $db, $lang; 815 816 $keywords = clean_keywords($search['keywords']); 817 if(!$keywords && !$search['sender']) 818 { 819 error($lang->error_nosearchterms); 820 } 821 822 if($mybb->settings['minsearchword'] < 1) 823 { 824 $mybb->settings['minsearchword'] = 3; 825 } 826 827 $name_lookin = ""; 828 $document_lookin = ""; 829 $searchsql = "enabled='1'"; 830 831 if($keywords) 832 { 833 switch($db->type) 834 { 835 case 'mysql': 836 case 'mysqli': 837 $nfield = 'name'; 838 $dfield = 'document'; 839 break; 840 default: 841 $nfield = 'LOWER(name)'; 842 $dfield = 'LOWER(document)'; 843 break; 844 } 845 846 // Complex search 847 $keywords = " {$keywords} "; 848 if(preg_match("#\s(and|or)\s#", $keywords)) 849 { 850 $string = "AND"; 851 if($search['name'] == 1) 852 { 853 $string = "OR"; 854 $name_lookin = " AND ("; 855 } 856 857 if($search['document'] == 1) 858 { 859 $document_lookin = " {$string} ("; 860 } 861 862 // Expand the string by double quotes 863 $keywords_exp = explode("\"", $keywords); 864 $inquote = false; 865 866 foreach($keywords_exp as $phrase) 867 { 868 // If we're not in a double quoted section 869 if(!$inquote) 870 { 871 // Expand out based on search operators (and, or) 872 $matches = preg_split("#\s{1,}(and|or)\s{1,}#", $phrase, -1, PREG_SPLIT_DELIM_CAPTURE); 873 $count_matches = count($matches); 874 875 for($i=0; $i < $count_matches; ++$i) 876 { 877 $word = trim($matches[$i]); 878 if(empty($word)) 879 { 880 continue; 881 } 882 // If this word is a search operator set the boolean 883 if($i % 2 && ($word == "and" || $word == "or")) 884 { 885 if($i <= 1) 886 { 887 if($search['name'] && $search['document'] && $name_lookin == " AND (") 888 { 889 // We're looking for anything, check for a name lookin 890 continue; 891 } 892 elseif($search['name'] && !$search['document'] && $name_lookin == " AND (") 893 { 894 // Just in a name? 895 continue; 896 } 897 elseif(!$search['name'] && $search['document'] && $document_lookin == " {$string} (") 898 { 899 // Just in a document? 900 continue; 901 } 902 } 903 904 $boolean = $word; 905 } 906 // Otherwise check the length of the word as it is a normal search term 907 else 908 { 909 $word = trim($word); 910 // Word is too short - show error message 911 if(my_strlen($word) < $mybb->settings['minsearchword']) 912 { 913 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 914 error($lang->error_minsearchlength); 915 } 916 // Add terms to search query 917 if($search['name'] == 1) 918 { 919 $name_lookin .= " $boolean {$nfield} LIKE '%{$word}%'"; 920 } 921 if($search['document'] == 1) 922 { 923 $document_lookin .= " $boolean {$dfield} LIKE '%{$word}%'"; 924 } 925 } 926 } 927 } 928 // In the middle of a quote (phrase) 929 else 930 { 931 $phrase = str_replace(array("+", "-", "*"), '', trim($phrase)); 932 if(my_strlen($phrase) < $mybb->settings['minsearchword']) 933 { 934 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 935 error($lang->error_minsearchlength); 936 } 937 // Add phrase to search query 938 $name_lookin .= " $boolean {$nfield} LIKE '%{$phrase}%'"; 939 if($search['document'] == 1) 940 { 941 $document_lookin .= " $boolean {$dfield} LIKE '%{$phrase}%'"; 942 } 943 } 944 945 // Check to see if we have any search terms and not a malformed SQL string 946 $error = false; 947 if($search['name'] && $search['document'] && $name_lookin == " AND (") 948 { 949 // We're looking for anything, check for a name lookin 950 $error = true; 951 } 952 elseif($search['name'] && !$search['document'] && $name_lookin == " AND (") 953 { 954 // Just in a name? 955 $error = true; 956 } 957 elseif(!$search['name'] && $search['document'] && $document_lookin == " {$string} (") 958 { 959 // Just in a document? 960 $error = true; 961 } 962 963 if($error == true) 964 { 965 // There are no search keywords to look for 966 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 967 error($lang->error_minsearchlength); 968 } 969 970 $inquote = !$inquote; 971 } 972 973 if($search['name'] == 1) 974 { 975 $name_lookin .= ")"; 976 } 977 978 if($search['document'] == 1) 979 { 980 $document_lookin .= ")"; 981 } 982 983 $searchsql .= "{$name_lookin} {$document_lookin}"; 984 } 985 else 986 { 987 $keywords = str_replace("\"", '', trim($keywords)); 988 if(my_strlen($keywords) < $mybb->settings['minsearchword']) 989 { 990 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 991 error($lang->error_minsearchlength); 992 } 993 994 // If we're looking in both, then find matches in either the name or the document 995 if($search['name'] == 1 && $search['document'] == 1) 996 { 997 $searchsql .= " AND ({$nfield} LIKE '%{$keywords}%' OR {$dfield} LIKE '%{$keywords}%')"; 998 } 999 else 1000 { 1001 if($search['name'] == 1) 1002 { 1003 $searchsql .= " AND {$nfield} LIKE '%{$keywords}%'"; 1004 } 1005 1006 if($search['document'] == 1) 1007 { 1008 $searchsql .= " AND {$dfield} LIKE '%{$keywords}%'"; 1009 } 1010 } 1011 } 1012 } 1013 1014 // Run the search 1015 $helpdocs = array(); 1016 $query = $db->simple_select("helpdocs", "hid", $searchsql); 1017 while($help = $db->fetch_array($query)) 1018 { 1019 $helpdocs[$help['hid']] = $help['hid']; 1020 } 1021 1022 if(count($helpdocs) < 1) 1023 { 1024 error($lang->error_nosearchresults); 1025 } 1026 $helpdocs = implode(',', $helpdocs); 1027 1028 return array( 1029 "querycache" => $helpdocs 1030 ); 1031 } 1032 1033 /** 1034 * Perform a thread and post search under MySQL or MySQLi 1035 * 1036 * @param array $search Array of search data 1037 * @return array Array of search data with results mixed in 1038 */ 1039 function perform_search_mysql($search) 1040 { 1041 global $mybb, $db, $lang, $cache; 1042 1043 $keywords = clean_keywords($search['keywords']); 1044 1045 if($mybb->settings['minsearchword'] < 1) 1046 { 1047 $mybb->settings['minsearchword'] = 3; 1048 } 1049 1050 $subject_lookin = $message_lookin = ''; 1051 if($keywords) 1052 { 1053 switch($db->type) 1054 { 1055 case 'mysql': 1056 case 'mysqli': 1057 $tfield = 't.subject'; 1058 $pfield = 'p.message'; 1059 break; 1060 default: 1061 $tfield = 'LOWER(t.subject)'; 1062 $pfield = 'LOWER(p.message)'; 1063 break; 1064 } 1065 1066 // Complex search 1067 $keywords = " {$keywords} "; 1068 if(preg_match("#\s(and|or)\s#", $keywords)) 1069 { 1070 $subject_lookin = " AND ("; 1071 $message_lookin = " AND ("; 1072 1073 // Expand the string by double quotes 1074 $keywords_exp = explode("\"", $keywords); 1075 $inquote = false; 1076 $boolean = ''; 1077 1078 foreach($keywords_exp as $phrase) 1079 { 1080 // If we're not in a double quoted section 1081 if(!$inquote) 1082 { 1083 // Expand out based on search operators (and, or) 1084 $matches = preg_split("#\s{1,}(and|or)\s{1,}#", $phrase, -1, PREG_SPLIT_DELIM_CAPTURE); 1085 $count_matches = count($matches); 1086 1087 for($i=0; $i < $count_matches; ++$i) 1088 { 1089 $word = trim($matches[$i]); 1090 if(empty($word)) 1091 { 1092 continue; 1093 } 1094 // If this word is a search operator set the boolean 1095 if($i % 2 && ($word == "and" || $word == "or")) 1096 { 1097 if($i <= 1 && $subject_lookin == " AND (") 1098 { 1099 continue; 1100 } 1101 1102 $boolean = $word; 1103 } 1104 // Otherwise check the length of the word as it is a normal search term 1105 else 1106 { 1107 $word = trim($word); 1108 // Word is too short - show error message 1109 if(my_strlen($word) < $mybb->settings['minsearchword']) 1110 { 1111 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 1112 error($lang->error_minsearchlength); 1113 } 1114 // Add terms to search query 1115 $subject_lookin .= " $boolean {$tfield} LIKE '%{$word}%'"; 1116 if($search['postthread'] == 1) 1117 { 1118 $message_lookin .= " $boolean {$pfield} LIKE '%{$word}%'"; 1119 } 1120 $boolean = 'AND'; 1121 } 1122 } 1123 } 1124 // In the middle of a quote (phrase) 1125 else 1126 { 1127 $phrase = str_replace(array("+", "-", "*"), '', trim($phrase)); 1128 if(my_strlen($phrase) < $mybb->settings['minsearchword']) 1129 { 1130 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 1131 error($lang->error_minsearchlength); 1132 } 1133 // Add phrase to search query 1134 $subject_lookin .= " $boolean {$tfield} LIKE '%{$phrase}%'"; 1135 if($search['postthread'] == 1) 1136 { 1137 $message_lookin .= " $boolean {$pfield} LIKE '%{$phrase}%'"; 1138 } 1139 $boolean = 'AND'; 1140 } 1141 1142 if($subject_lookin == " AND (") 1143 { 1144 // There are no search keywords to look for 1145 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 1146 error($lang->error_minsearchlength); 1147 } 1148 1149 $inquote = !$inquote; 1150 } 1151 $subject_lookin .= ")"; 1152 $message_lookin .= ")"; 1153 } 1154 else 1155 { 1156 $keywords = str_replace("\"", '', trim($keywords)); 1157 if(my_strlen($keywords) < $mybb->settings['minsearchword']) 1158 { 1159 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 1160 error($lang->error_minsearchlength); 1161 } 1162 $subject_lookin = " AND {$tfield} LIKE '%{$keywords}%'"; 1163 if($search['postthread'] == 1) 1164 { 1165 $message_lookin = " AND {$pfield} LIKE '%{$keywords}%'"; 1166 } 1167 } 1168 } 1169 $post_usersql = ''; 1170 $thread_usersql = ''; 1171 if($search['author']) 1172 { 1173 $userids = array(); 1174 $search['author'] = my_strtolower($search['author']); 1175 if($search['matchusername']) 1176 { 1177 $user = get_user_by_username($search['author']); 1178 if($user) 1179 { 1180 $userids[] = $user['uid']; 1181 } 1182 } 1183 else 1184 { 1185 switch($db->type) 1186 { 1187 case 'mysql': 1188 case 'mysqli': 1189 $field = 'username'; 1190 break; 1191 default: 1192 $field = 'LOWER(username)'; 1193 break; 1194 } 1195 $query = $db->simple_select("users", "uid", "{$field} LIKE '%".$db->escape_string_like($search['author'])."%'"); 1196 while($user = $db->fetch_array($query)) 1197 { 1198 $userids[] = $user['uid']; 1199 } 1200 } 1201 1202 if(count($userids) < 1) 1203 { 1204 error($lang->error_nosearchresults); 1205 } 1206 else 1207 { 1208 $userids = implode(',', $userids); 1209 $post_usersql = " AND p.uid IN (".$userids.")"; 1210 $thread_usersql = " AND t.uid IN (".$userids.")"; 1211 } 1212 } 1213 $datecut = $post_datecut = $thread_datecut = ''; 1214 if($search['postdate']) 1215 { 1216 if($search['pddir'] == 0) 1217 { 1218 $datecut = "<="; 1219 } 1220 else 1221 { 1222 $datecut = ">="; 1223 } 1224 $now = TIME_NOW; 1225 $datelimit = $now-(86400 * $search['postdate']); 1226 $datecut .= "'$datelimit'"; 1227 $post_datecut = " AND p.dateline $datecut"; 1228 $thread_datecut = " AND t.dateline $datecut"; 1229 } 1230 1231 $thread_replycut = ''; 1232 if($search['numreplies'] != '' && $search['findthreadst']) 1233 { 1234 if((int)$search['findthreadst'] == 1) 1235 { 1236 $thread_replycut = " AND t.replies >= '".(int)$search['numreplies']."'"; 1237 } 1238 else 1239 { 1240 $thread_replycut = " AND t.replies <= '".(int)$search['numreplies']."'"; 1241 } 1242 } 1243 1244 $thread_prefixcut = ''; 1245 $prefixlist = array(); 1246 if($search['threadprefix'] && $search['threadprefix'][0] != 'any') 1247 { 1248 foreach($search['threadprefix'] as $threadprefix) 1249 { 1250 $threadprefix = (int)$threadprefix; 1251 $prefixlist[] = $threadprefix; 1252 } 1253 } 1254 if(count($prefixlist) == 1) 1255 { 1256 $thread_prefixcut .= " AND t.prefix='$threadprefix' "; 1257 } 1258 else 1259 { 1260 if(count($prefixlist) > 1) 1261 { 1262 $thread_prefixcut = " AND t.prefix IN (".implode(',', $prefixlist).")"; 1263 } 1264 } 1265 1266 $forumin = ''; 1267 $fidlist = array(); 1268 if(!empty($search['forums']) && (!is_array($search['forums']) || $search['forums'][0] != "all")) 1269 { 1270 if(!is_array($search['forums'])) 1271 { 1272 $search['forums'] = array((int)$search['forums']); 1273 } 1274 foreach($search['forums'] as $forum) 1275 { 1276 $forum = (int)$forum; 1277 if($forum > 0) 1278 { 1279 $fidlist[] = $forum; 1280 $child_list = get_child_list($forum); 1281 if(is_array($child_list)) 1282 { 1283 $fidlist = array_merge($fidlist, $child_list); 1284 } 1285 } 1286 } 1287 $fidlist = array_unique($fidlist); 1288 if(count($fidlist) >= 1) 1289 { 1290 $forumin = " AND t.fid IN (".implode(',', $fidlist).")"; 1291 } 1292 } 1293 1294 $permsql = ""; 1295 $onlyusfids = array(); 1296 1297 // Check group permissions if we can't view threads not started by us 1298 if($group_permissions = forum_permissions()) 1299 { 1300 foreach($group_permissions as $fid => $forum_permissions) 1301 { 1302 if(isset($forum_permissions['canonlyviewownthreads']) && $forum_permissions['canonlyviewownthreads'] == 1) 1303 { 1304 $onlyusfids[] = $fid; 1305 } 1306 } 1307 } 1308 if(!empty($onlyusfids)) 1309 { 1310 $permsql .= "AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; 1311 } 1312 1313 $unsearchforums = get_unsearchable_forums(); 1314 if($unsearchforums) 1315 { 1316 $permsql .= " AND t.fid NOT IN ($unsearchforums)"; 1317 } 1318 $inactiveforums = get_inactive_forums(); 1319 if($inactiveforums) 1320 { 1321 $permsql .= " AND t.fid NOT IN ($inactiveforums)"; 1322 } 1323 1324 $visiblesql = $post_visiblesql = $plain_post_visiblesql = $unapproved_where_t = $unapproved_where_p = ""; 1325 if(isset($search['visible'])) 1326 { 1327 if($search['visible'] == 1) 1328 { 1329 $visiblesql = " AND t.visible = '1'"; 1330 1331 if($search['postthread'] == 1) 1332 { 1333 $post_visiblesql = " AND p.visible = '1'"; 1334 $plain_post_visiblesql = " AND visible = '1'"; 1335 } 1336 } 1337 elseif($search['visible'] == -1) 1338 { 1339 $visiblesql = " AND t.visible = '-1'"; 1340 1341 if($search['postthread'] == 1) 1342 { 1343 $post_visiblesql = " AND p.visible = '-1'"; 1344 $plain_post_visiblesql = " AND visible = '-1'"; 1345 } 1346 } 1347 else 1348 { 1349 $visiblesql = " AND t.visible == '0'"; 1350 1351 if($search['postthread'] == 1) 1352 { 1353 $post_visiblesql = " AND p.visible == '0'"; 1354 $plain_post_visiblesql = " AND visible == '0'"; 1355 } 1356 } 1357 } 1358 1359 // Moderators can view unapproved threads and deleted threads from forums they moderate 1360 $unapproved_where_t = get_visible_where('t'); 1361 $unapproved_where_p = get_visible_where('p'); 1362 1363 // Searching a specific thread? 1364 $tidsql = ''; 1365 if(!empty($search['tid'])) 1366 { 1367 $tidsql = " AND t.tid='".(int)$search['tid']."'"; 1368 } 1369 1370 $limitsql = ''; 1371 if((int)$mybb->settings['searchhardlimit'] > 0) 1372 { 1373 $limitsql = "LIMIT ".(int)$mybb->settings['searchhardlimit']; 1374 } 1375 1376 // Searching both posts and thread titles 1377 $threads = array(); 1378 $posts = array(); 1379 $firstposts = array(); 1380 if($search['postthread'] == 1) 1381 { 1382 // No need to search subjects when looking for results within a specific thread 1383 if(empty($search['tid'])) 1384 { 1385 $query = $db->query(" 1386 SELECT t.tid, t.firstpost 1387 FROM ".TABLE_PREFIX."threads t 1388 WHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} AND ({$unapproved_where_t}) AND t.closed NOT LIKE 'moved|%' {$subject_lookin} 1389 {$limitsql} 1390 "); 1391 while($thread = $db->fetch_array($query)) 1392 { 1393 $threads[$thread['tid']] = $thread['tid']; 1394 if($thread['firstpost']) 1395 { 1396 $posts[$thread['tid']] = $thread['firstpost']; 1397 } 1398 } 1399 } 1400 1401 $query = $db->query(" 1402 SELECT p.pid, p.tid 1403 FROM ".TABLE_PREFIX."posts p 1404 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) 1405 WHERE 1=1 {$post_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$post_usersql} {$permsql} {$tidsql} {$visiblesql} {$post_visiblesql} AND ({$unapproved_where_t}) AND ({$unapproved_where_p}) AND t.closed NOT LIKE 'moved|%' {$message_lookin} 1406 {$limitsql} 1407 "); 1408 while($post = $db->fetch_array($query)) 1409 { 1410 $posts[$post['pid']] = $post['pid']; 1411 $threads[$post['tid']] = $post['tid']; 1412 } 1413 1414 if(count($posts) < 1 && count($threads) < 1) 1415 { 1416 error($lang->error_nosearchresults); 1417 } 1418 $threads = implode(',', $threads); 1419 $posts = implode(',', $posts); 1420 1421 } 1422 // Searching only thread titles 1423 else 1424 { 1425 $query = $db->query(" 1426 SELECT t.tid, t.firstpost 1427 FROM ".TABLE_PREFIX."threads t 1428 WHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} {$subject_lookin} 1429 {$limitsql} 1430 "); 1431 while($thread = $db->fetch_array($query)) 1432 { 1433 $threads[$thread['tid']] = $thread['tid']; 1434 if($thread['firstpost']) 1435 { 1436 $firstposts[$thread['tid']] = $thread['firstpost']; 1437 } 1438 } 1439 if(count($threads) < 1) 1440 { 1441 error($lang->error_nosearchresults); 1442 } 1443 1444 $threads = implode(',', $threads); 1445 $firstposts = implode(',', $firstposts); 1446 if($firstposts) 1447 { 1448 $query = $db->simple_select("posts", "pid", "pid IN ($firstposts) {$plain_post_visiblesql} {$limitsql}"); 1449 while($post = $db->fetch_array($query)) 1450 { 1451 $posts[$post['pid']] = $post['pid']; 1452 } 1453 $posts = implode(',', $posts); 1454 } 1455 } 1456 return array( 1457 "threads" => $threads, 1458 "posts" => $posts, 1459 "querycache" => '' 1460 ); 1461 } 1462 1463 /** 1464 * Perform a thread and post search under MySQL or MySQLi using boolean fulltext capabilities 1465 * 1466 * @param array $search Array of search data 1467 * @return array Array of search data with results mixed in 1468 */ 1469 function perform_search_mysql_ft($search) 1470 { 1471 global $mybb, $db, $lang; 1472 1473 $keywords = clean_keywords_ft($search['keywords']); 1474 1475 if($mybb->settings['minsearchword'] < 1) 1476 { 1477 $mybb->settings['minsearchword'] = 4; 1478 } 1479 1480 $message_lookin = $subject_lookin = ''; 1481 if($keywords) 1482 { 1483 $keywords_exp = explode("\"", $keywords); 1484 $inquote = false; 1485 foreach($keywords_exp as $phrase) 1486 { 1487 if(!$inquote) 1488 { 1489 $split_words = preg_split("#\s{1,}#", $phrase, -1); 1490 foreach($split_words as $word) 1491 { 1492 $word = str_replace(array("+", "-", "*"), '', $word); 1493 if(!$word) 1494 { 1495 continue; 1496 } 1497 if(my_strlen($word) < $mybb->settings['minsearchword']) 1498 { 1499 $all_too_short = true; 1500 } 1501 else 1502 { 1503 $all_too_short = false; 1504 break; 1505 } 1506 } 1507 } 1508 else 1509 { 1510 $phrase = str_replace(array("+", "-", "*"), '', $phrase); 1511 if(my_strlen($phrase) < $mybb->settings['minsearchword']) 1512 { 1513 $all_too_short = true; 1514 } 1515 else 1516 { 1517 $all_too_short = false; 1518 break; 1519 } 1520 } 1521 $inquote = !$inquote; 1522 } 1523 // Show the minimum search term error only if all search terms are too short 1524 if($all_too_short == true) 1525 { 1526 $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); 1527 error($lang->error_minsearchlength); 1528 } 1529 $message_lookin = "AND MATCH(message) AGAINST('".$db->escape_string($keywords)."' IN BOOLEAN MODE)"; 1530 $subject_lookin = "AND MATCH(subject) AGAINST('".$db->escape_string($keywords)."' IN BOOLEAN MODE)"; 1531 } 1532 $post_usersql = ''; 1533 $thread_usersql = ''; 1534 if($search['author']) 1535 { 1536 $userids = array(); 1537 $search['author'] = my_strtolower($search['author']); 1538 if($search['matchusername']) 1539 { 1540 $user = get_user_by_username($search['author']); 1541 if($user) 1542 { 1543 $userids[] = $user['uid']; 1544 } 1545 } 1546 else 1547 { 1548 $query = $db->simple_select("users", "uid", "username LIKE '%".$db->escape_string_like($search['author'])."%'"); 1549 1550 while($user = $db->fetch_array($query)) 1551 { 1552 $userids[] = $user['uid']; 1553 } 1554 } 1555 1556 if(count($userids) < 1) 1557 { 1558 error($lang->error_nosearchresults); 1559 } 1560 else 1561 { 1562 $userids = implode(',', $userids); 1563 $post_usersql = " AND p.uid IN (".$userids.")"; 1564 $thread_usersql = " AND t.uid IN (".$userids.")"; 1565 } 1566 } 1567 $datecut = $thread_datecut = $post_datecut = ''; 1568 if($search['postdate']) 1569 { 1570 if($search['pddir'] == 0) 1571 { 1572 $datecut = "<="; 1573 } 1574 else 1575 { 1576 $datecut = ">="; 1577 } 1578 $now = TIME_NOW; 1579 $datelimit = $now-(86400 * $search['postdate']); 1580 $datecut .= "'$datelimit'"; 1581 $post_datecut = " AND p.dateline $datecut"; 1582 $thread_datecut = " AND t.dateline $datecut"; 1583 } 1584 1585 $thread_replycut = ''; 1586 if($search['numreplies'] != '' && $search['findthreadst']) 1587 { 1588 if((int)$search['findthreadst'] == 1) 1589 { 1590 $thread_replycut = " AND t.replies >= '".(int)$search['numreplies']."'"; 1591 } 1592 else 1593 { 1594 $thread_replycut = " AND t.replies <= '".(int)$search['numreplies']."'"; 1595 } 1596 } 1597 1598 $thread_prefixcut = ''; 1599 $prefixlist = array(); 1600 if($search['threadprefix'] && $search['threadprefix'][0] != 'any') 1601 { 1602 foreach($search['threadprefix'] as $threadprefix) 1603 { 1604 $threadprefix = (int)$threadprefix; 1605 $prefixlist[] = $threadprefix; 1606 } 1607 } 1608 if(count($prefixlist) == 1) 1609 { 1610 $thread_prefixcut .= " AND t.prefix='$threadprefix' "; 1611 } 1612 else 1613 { 1614 if(count($prefixlist) > 1) 1615 { 1616 $thread_prefixcut = " AND t.prefix IN (".implode(',', $prefixlist).")"; 1617 } 1618 } 1619 1620 $forumin = ''; 1621 $fidlist = array(); 1622 $searchin = array(); 1623 if(!empty($search['forums']) && (!is_array($search['forums']) || $search['forums'][0] != "all")) 1624 { 1625 if(!is_array($search['forums'])) 1626 { 1627 $search['forums'] = array((int)$search['forums']); 1628 } 1629 foreach($search['forums'] as $forum) 1630 { 1631 $forum = (int)$forum; 1632 if($forum > 0) 1633 { 1634 $fidlist[] = $forum; 1635 $child_list = get_child_list($forum); 1636 if(is_array($child_list)) 1637 { 1638 $fidlist = array_merge($fidlist, $child_list); 1639 } 1640 } 1641 } 1642 $fidlist = array_unique($fidlist); 1643 if(count($fidlist) >= 1) 1644 { 1645 $forumin = " AND t.fid IN (".implode(',', $fidlist).")"; 1646 } 1647 } 1648 $permsql = ""; 1649 $onlyusfids = array(); 1650 1651 // Check group permissions if we can't view threads not started by us 1652 $group_permissions = forum_permissions(); 1653 foreach($group_permissions as $fid => $forum_permissions) 1654 { 1655 if($forum_permissions['canonlyviewownthreads'] == 1) 1656 { 1657 $onlyusfids[] = $fid; 1658 } 1659 } 1660 if(!empty($onlyusfids)) 1661 { 1662 $permsql .= "AND ((t.fid IN(".implode(',', $onlyusfids).") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(".implode(',', $onlyusfids)."))"; 1663 } 1664 1665 $unsearchforums = get_unsearchable_forums(); 1666 if($unsearchforums) 1667 { 1668 $permsql .= " AND t.fid NOT IN ($unsearchforums)"; 1669 } 1670 $inactiveforums = get_inactive_forums(); 1671 if($inactiveforums) 1672 { 1673 $permsql .= " AND t.fid NOT IN ($inactiveforums)"; 1674 } 1675 1676 $visiblesql = $post_visiblesql = $plain_post_visiblesql = $unapproved_where_t = $unapproved_where_p = ""; 1677 if(isset($search['visible'])) 1678 { 1679 if($search['visible'] == 1) 1680 { 1681 $visiblesql = " AND t.visible = '1'"; 1682 1683 if($search['postthread'] == 1) 1684 { 1685 $post_visiblesql = " AND p.visible = '1'"; 1686 $plain_post_visiblesql = " AND visible = '1'"; 1687 } 1688 } 1689 elseif($search['visible'] == -1) 1690 { 1691 $visiblesql = " AND t.visible = '-1'"; 1692 1693 if($search['postthread'] == 1) 1694 { 1695 $post_visiblesql = " AND p.visible = '-1'"; 1696 $plain_post_visiblesql = " AND visible = '-1'"; 1697 } 1698 } 1699 else 1700 { 1701 $visiblesql = " AND t.visible != '1'"; 1702 1703 if($search['postthread'] == 1) 1704 { 1705 $post_visiblesql = " AND p.visible != '1'"; 1706 $plain_post_visiblesql = " AND visible != '1'"; 1707 } 1708 } 1709 } 1710 1711 // Moderators can view unapproved threads and deleted threads from forums they moderate 1712 $unapproved_where_t = get_visible_where('t'); 1713 $unapproved_where_p = get_visible_where('p'); 1714 1715 // Searching a specific thread? 1716 $tidsql = ''; 1717 if($search['tid']) 1718 { 1719 $tidsql = " AND t.tid='".(int)$search['tid']."'"; 1720 } 1721 1722 $limitsql = ''; 1723 if((int)$mybb->settings['searchhardlimit'] > 0) 1724 { 1725 $limitsql = "LIMIT ".(int)$mybb->settings['searchhardlimit']; 1726 } 1727 1728 // Searching both posts and thread titles 1729 $threads = array(); 1730 $posts = array(); 1731 $firstposts = array(); 1732 if($search['postthread'] == 1) 1733 { 1734 // No need to search subjects when looking for results within a specific thread 1735 if(!$search['tid']) 1736 { 1737 $query = $db->query(" 1738 SELECT t.tid, t.firstpost 1739 FROM ".TABLE_PREFIX."threads t 1740 WHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} AND ({$unapproved_where_t}) AND t.closed NOT LIKE 'moved|%' {$subject_lookin} 1741 {$limitsql} 1742 "); 1743 while($thread = $db->fetch_array($query)) 1744 { 1745 $threads[$thread['tid']] = $thread['tid']; 1746 if($thread['firstpost']) 1747 { 1748 $posts[$thread['tid']] = $thread['firstpost']; 1749 } 1750 } 1751 } 1752 1753 $query = $db->query(" 1754 SELECT p.pid, p.tid 1755 FROM ".TABLE_PREFIX."posts p 1756 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) 1757 WHERE 1=1 {$post_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$post_usersql} {$permsql} {$tidsql} {$post_visiblesql} {$visiblesql} AND ({$unapproved_where_t}) AND {$unapproved_where_p} AND t.closed NOT LIKE 'moved|%' {$message_lookin} 1758 {$limitsql} 1759 "); 1760 while($post = $db->fetch_array($query)) 1761 { 1762 $posts[$post['pid']] = $post['pid']; 1763 $threads[$post['tid']] = $post['tid']; 1764 } 1765 if(count($posts) < 1 && count($threads) < 1) 1766 { 1767 error($lang->error_nosearchresults); 1768 } 1769 $threads = implode(',', $threads); 1770 $posts = implode(',', $posts); 1771 1772 } 1773 // Searching only thread titles 1774 else 1775 { 1776 $query = $db->query(" 1777 SELECT t.tid, t.firstpost 1778 FROM ".TABLE_PREFIX."threads t 1779 WHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} {$subject_lookin} 1780 {$limitsql} 1781 "); 1782 while($thread = $db->fetch_array($query)) 1783 { 1784 $threads[$thread['tid']] = $thread['tid']; 1785 if($thread['firstpost']) 1786 { 1787 $firstposts[$thread['tid']] = $thread['firstpost']; 1788 } 1789 } 1790 if(count($threads) < 1) 1791 { 1792 error($lang->error_nosearchresults); 1793 } 1794 1795 $threads = implode(',', $threads); 1796 $firstposts = implode(',', $firstposts); 1797 if($firstposts) 1798 { 1799 $query = $db->simple_select("posts", "pid", "pid IN ($firstposts) {$plain_post_visiblesql} {$limitsql}"); 1800 while($post = $db->fetch_array($query)) 1801 { 1802 $posts[$post['pid']] = $post['pid']; 1803 } 1804 $posts = implode(',', $posts); 1805 } 1806 } 1807 return array( 1808 "threads" => $threads, 1809 "posts" => $posts, 1810 "querycache" => '' 1811 ); 1812 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup | Cross-referenced by PHPXref |