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