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