[ Index ]

PHP Cross Reference of MyBB 1.8.40

title

Body

[close]

/inc/ -> functions_search.php (source)

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


2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup Cross-referenced by PHPXref