Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

search.php

Zuletzt modifiziert: 09.10.2024, 12:50 - Dateigröße: 48.66 KiB


0001  <?php
0002  /**
0003  *
0004  * This file is part of the phpBB Forum Software package.
0005  *
0006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
0007  * @license GNU General Public License, version 2 (GPL-2.0)
0008  *
0009  * For full copyright and license information, please see
0010  * the docs/CREDITS.txt file.
0011  *
0012  */
0013   
0014  /**
0015  * @ignore
0016  */
0017  define('IN_PHPBB', true);
0018  $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';
0019  $phpEx = substr(strrchr(__FILE__, '.'), 1);
0020  include($phpbb_root_path . 'common.' . $phpEx);
0021   
0022  // Start session management
0023  $user->session_begin();
0024  $auth->acl($user->data);
0025  $user->setup('search');
0026   
0027  // Define initial vars
0028  $mode            = request_var('mode', '');
0029  $search_id        = request_var('search_id', '');
0030  $start            = max(request_var('start', 0), 0);
0031  $post_id        = request_var('p', 0);
0032  $topic_id        = request_var('t', 0);
0033  $view            = request_var('view', '');
0034   
0035  $submit            = request_var('submit', false);
0036  $keywords        = utf8_normalize_nfc(request_var('keywords', '', true));
0037  $add_keywords    = utf8_normalize_nfc(request_var('add_keywords', '', true));
0038  $author            = request_var('author', '', true);
0039  $author_id        = request_var('author_id', 0);
0040  $show_results    = ($topic_id) ? 'posts' : request_var('sr', 'posts');
0041  $show_results    = ($show_results == 'posts') ? 'posts' : 'topics';
0042  $search_terms    = request_var('terms', 'all');
0043  $search_fields    = request_var('sf', 'all');
0044  $search_child    = request_var('sc', true);
0045   
0046  $sort_days        = request_var('st', 0);
0047  $sort_key        = request_var('sk', 't');
0048  $sort_dir        = request_var('sd', 'd');
0049   
0050  $return_chars    = request_var('ch', ($topic_id) ? -1 : 300);
0051  $search_forum    = request_var('fid', array(0));
0052   
0053  // We put login boxes for the case if search_id is newposts, egosearch or unreadposts
0054  // because a guest should be able to log in even if guests search is not permitted
0055   
0056  switch ($search_id)
0057  {
0058      // Egosearch is an author search
0059      case 'egosearch':
0060          $author_id = $user->data['user_id'];
0061          if ($user->data['user_id'] == ANONYMOUS)
0062          {
0063              login_box('', $user->lang['LOGIN_EXPLAIN_EGOSEARCH']);
0064          }
0065      break;
0066   
0067      // Search for unread posts needs to be allowed and user to be logged in if topics tracking for guests is disabled
0068      case 'unreadposts':
0069          if (!$config['load_unreads_search'])
0070          {
0071              $template->assign_var('S_NO_SEARCH', true);
0072              trigger_error('NO_SEARCH_UNREADS');
0073          }
0074          else if (!$config['load_anon_lastread'] && !$user->data['is_registered'])
0075          {
0076              login_box('', $user->lang['LOGIN_EXPLAIN_UNREADSEARCH']);
0077          }
0078      break;
0079   
0080      // The "new posts" search uses user_lastvisit which is user based, so it should require user to log in.
0081      case 'newposts':
0082          if ($user->data['user_id'] == ANONYMOUS)
0083          {
0084              login_box('', $user->lang['LOGIN_EXPLAIN_NEWPOSTS']);
0085          }
0086      break;
0087   
0088      default:
0089          // There's nothing to do here for now ;)
0090      break;
0091  }
0092   
0093  // Is user able to search? Has search been disabled?
0094  if (!$auth->acl_get('u_search') || !$auth->acl_getf_global('f_search') || !$config['load_search'])
0095  {
0096      $template->assign_var('S_NO_SEARCH', true);
0097      trigger_error('NO_SEARCH');
0098  }
0099   
0100  // Check search load limit
0101  if ($user->load && $config['limit_search_load'] && ($user->load > doubleval($config['limit_search_load'])))
0102  {
0103      $template->assign_var('S_NO_SEARCH', true);
0104      trigger_error('NO_SEARCH_TIME');
0105  }
0106   
0107  // It is applicable if the configuration setting is non-zero, and the user cannot
0108  // ignore the flood setting, and the search is a keyword search.
0109  $interval = ($user->data['user_id'] == ANONYMOUS) ? $config['search_anonymous_interval'] : $config['search_interval'];
0110  if ($interval && !in_array($search_id, array('unreadposts', 'unanswered', 'active_topics', 'egosearch')) && !$auth->acl_get('u_ignoreflood'))
0111  {
0112      if ($user->data['user_last_search'] > time() - $interval)
0113      {
0114          $template->assign_var('S_NO_SEARCH', true);
0115          trigger_error($user->lang('NO_SEARCH_TIME', (int) ($user->data['user_last_search'] + $interval - time())));
0116      }
0117  }
0118   
0119  // Define some vars
0120  $limit_days        = array(0 => $user->lang['ALL_RESULTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
0121  $sort_by_text    = array('a' => $user->lang['SORT_AUTHOR'], 't' => $user->lang['SORT_TIME'], 'f' => $user->lang['SORT_FORUM'], 'i' => $user->lang['SORT_TOPIC_TITLE'], 's' => $user->lang['SORT_POST_SUBJECT']);
0122   
0123  $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
0124  gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
0125   
0126  $phpbb_content_visibility = $phpbb_container->get('content.visibility');
0127  $pagination = $phpbb_container->get('pagination');
0128   
0129  if ($keywords || $author || $author_id || $search_id || $submit)
0130  {
0131      // clear arrays
0132      $id_ary = array();
0133   
0134      // If we are looking for authors get their ids
0135      $author_id_ary = array();
0136      $sql_author_match = '';
0137      if ($author_id)
0138      {
0139          $author_id_ary[] = $author_id;
0140      }
0141      else if ($author)
0142      {
0143          if ((strpos($author, '*') !== false) && (utf8_strlen(str_replace(array('*', '%'), '', $author)) < $config['min_search_author_chars']))
0144          {
0145              trigger_error($user->lang('TOO_FEW_AUTHOR_CHARS', (int) $config['min_search_author_chars']));
0146          }
0147   
0148          $sql_where = (strpos($author, '*') !== false) ? ' username_clean ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), utf8_clean_string($author))) : " username_clean = '" . $db->sql_escape(utf8_clean_string($author)) . "'";
0149   
0150          $sql = 'SELECT user_id
0151              FROM ' . USERS_TABLE . "
0152              WHERE $sql_where
0153                  AND user_type <> " . USER_IGNORE;
0154          $result = $db->sql_query_limit($sql, 100);
0155   
0156          while ($row = $db->sql_fetchrow($result))
0157          {
0158              $author_id_ary[] = (int) $row['user_id'];
0159          }
0160          $db->sql_freeresult($result);
0161   
0162          $sql_where = (strpos($author, '*') !== false) ? ' post_username ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), utf8_clean_string($author))) : " post_username = '" . $db->sql_escape(utf8_clean_string($author)) . "'";
0163   
0164          $sql = 'SELECT 1 as guest_post
0165              FROM ' . POSTS_TABLE . "
0166              WHERE $sql_where
0167                  AND poster_id = " . ANONYMOUS;
0168          $result = $db->sql_query_limit($sql, 1);
0169          $found_guest_post = $db->sql_fetchfield('guest_post');
0170          $db->sql_freeresult($result);
0171   
0172          if ($found_guest_post)
0173          {
0174              $author_id_ary[] = ANONYMOUS;
0175              $sql_author_match = (strpos($author, '*') !== false) ? ' ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), utf8_clean_string($author))) : " = '" . $db->sql_escape(utf8_clean_string($author)) . "'";
0176          }
0177   
0178          if (!sizeof($author_id_ary))
0179          {
0180              trigger_error('NO_SEARCH_RESULTS');
0181          }
0182      }
0183   
0184      // if we search in an existing search result just add the additional keywords. But we need to use "all search terms"-mode
0185      // so we can keep the old keywords in their old mode, but add the new ones as required words
0186      if ($add_keywords)
0187      {
0188          if ($search_terms == 'all')
0189          {
0190              $keywords .= ' ' . $add_keywords;
0191          }
0192          else
0193          {
0194              $search_terms = 'all';
0195              $keywords = implode(' |', explode(' ', preg_replace('#\s+#u', ' ', $keywords))) . ' ' .$add_keywords;
0196          }
0197      }
0198   
0199      // Which forums should not be searched? Author searches are also carried out in unindexed forums
0200      if (empty($keywords) && sizeof($author_id_ary))
0201      {
0202          $ex_fid_ary = array_keys($auth->acl_getf('!f_read', true));
0203      }
0204      else
0205      {
0206          $ex_fid_ary = array_unique(array_merge(array_keys($auth->acl_getf('!f_read', true)), array_keys($auth->acl_getf('!f_search', true))));
0207      }
0208   
0209      $not_in_fid = (sizeof($ex_fid_ary)) ? 'WHERE ' . $db->sql_in_set('f.forum_id', $ex_fid_ary, true) . " OR (f.forum_password <> '' AND fa.user_id <> " . (int) $user->data['user_id'] . ')' : "";
0210   
0211      $sql = 'SELECT f.forum_id, f.forum_name, f.parent_id, f.forum_type, f.right_id, f.forum_password, f.forum_flags, fa.user_id
0212          FROM ' . FORUMS_TABLE . ' f
0213          LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa ON (fa.forum_id = f.forum_id
0214              AND fa.session_id = '" . $db->sql_escape($user->session_id) . "')
0215          $not_in_fid
0216          ORDER BY f.left_id";
0217      $result = $db->sql_query($sql);
0218   
0219      $right_id = 0;
0220      $reset_search_forum = true;
0221      while ($row = $db->sql_fetchrow($result))
0222      {
0223          if ($row['forum_password'] && $row['user_id'] != $user->data['user_id'])
0224          {
0225              $ex_fid_ary[] = (int) $row['forum_id'];
0226              continue;
0227          }
0228   
0229          // Exclude forums from active topics
0230          if (!($row['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS) && ($search_id == 'active_topics'))
0231          {
0232              $ex_fid_ary[] = (int) $row['forum_id'];
0233              continue;
0234          }
0235   
0236          if (sizeof($search_forum))
0237          {
0238              if ($search_child)
0239              {
0240                  if (in_array($row['forum_id'], $search_forum) && $row['right_id'] > $right_id)
0241                  {
0242                      $right_id = (int) $row['right_id'];
0243                  }
0244                  else if ($row['right_id'] < $right_id)
0245                  {
0246                      continue;
0247                  }
0248              }
0249   
0250              if (!in_array($row['forum_id'], $search_forum))
0251              {
0252                  $ex_fid_ary[] = (int) $row['forum_id'];
0253                  $reset_search_forum = false;
0254              }
0255          }
0256      }
0257      $db->sql_freeresult($result);
0258   
0259      // find out in which forums the user is allowed to view posts
0260      $m_approve_posts_fid_sql = $phpbb_content_visibility->get_global_visibility_sql('post', $ex_fid_ary, 'p.');
0261      $m_approve_topics_fid_sql = $phpbb_content_visibility->get_global_visibility_sql('topic', $ex_fid_ary, 't.');
0262   
0263      if ($reset_search_forum)
0264      {
0265          $search_forum = array();
0266      }
0267   
0268      // Select which method we'll use to obtain the post_id or topic_id information
0269      $search_type = $config['search_type'];
0270   
0271      if (!class_exists($search_type))
0272      {
0273          trigger_error('NO_SUCH_SEARCH_MODULE');
0274      }
0275      // We do some additional checks in the module to ensure it can actually be utilised
0276      $error = false;
0277      $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
0278   
0279      if ($error)
0280      {
0281          trigger_error($error);
0282      }
0283   
0284      // let the search module split up the keywords
0285      if ($keywords)
0286      {
0287          $correct_query = $search->split_keywords($keywords, $search_terms);
0288          $common_words = $search->get_common_words();
0289          if (!$correct_query || (!$search->get_search_query() && !sizeof($author_id_ary) && !$search_id))
0290          {
0291              $ignored = (sizeof($common_words)) ? sprintf($user->lang['IGNORED_TERMS_EXPLAIN'], implode(' ', $common_words)) . '<br />' : '';
0292              $word_length = $search->get_word_length();
0293              if ($word_length)
0294              {
0295                  trigger_error($ignored . $user->lang('NO_KEYWORDS', $user->lang('CHARACTERS', (int) $word_length['min']), $user->lang('CHARACTERS', (int) $word_length['max'])));
0296              }
0297              else
0298              {
0299                  trigger_error($ignored);
0300              }
0301          }
0302      }
0303   
0304      if (!$keywords && sizeof($author_id_ary))
0305      {
0306          // if it is an author search we want to show topics by default
0307          $show_results = ($topic_id) ? 'posts' : request_var('sr', ($search_id == 'egosearch') ? 'topics' : 'posts');
0308          $show_results = ($show_results == 'posts') ? 'posts' : 'topics';
0309      }
0310   
0311      // define some variables needed for retrieving post_id/topic_id information
0312      $sort_by_sql = array('a' => 'u.username_clean', 't' => (($show_results == 'posts') ? 'p.post_time' : 't.topic_last_post_time'), 'f' => 'f.forum_id', 'i' => 't.topic_title', 's' => (($show_results == 'posts') ? 'p.post_subject' : 't.topic_title'));
0313   
0314      // pre-made searches
0315      $sql = $field = $l_search_title = '';
0316      if ($search_id)
0317      {
0318          switch ($search_id)
0319          {
0320              // Oh holy Bob, bring us some activity...
0321              case 'active_topics':
0322                  $l_search_title = $user->lang['SEARCH_ACTIVE_TOPICS'];
0323                  $show_results = 'topics';
0324                  $sort_key = 't';
0325                  $sort_dir = 'd';
0326                  $sort_days = request_var('st', 7);
0327                  $sort_by_sql['t'] = 't.topic_last_post_time';
0328   
0329                  gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
0330                  $s_sort_key = $s_sort_dir = '';
0331   
0332                  $last_post_time_sql = ($sort_days) ? ' AND t.topic_last_post_time > ' . (time() - ($sort_days * 24 * 3600)) : '';
0333   
0334                  $sql = 'SELECT t.topic_last_post_time, t.topic_id
0335                      FROM ' . TOPICS_TABLE . " t
0336                      WHERE t.topic_moved_id = 0
0337                          $last_post_time_sql
0338                          AND " . $m_approve_topics_fid_sql . '
0339                          ' . ((sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . '
0340                      ORDER BY t.topic_last_post_time DESC';
0341                  $field = 'topic_id';
0342              break;
0343   
0344              case 'unanswered':
0345                  $l_search_title = $user->lang['SEARCH_UNANSWERED'];
0346                  $show_results = request_var('sr', 'topics');
0347                  $show_results = ($show_results == 'posts') ? 'posts' : 'topics';
0348                  $sort_by_sql['t'] = ($show_results == 'posts') ? 'p.post_time' : 't.topic_last_post_time';
0349                  $sort_by_sql['s'] = ($show_results == 'posts') ? 'p.post_subject' : 't.topic_title';
0350                  $sql_sort = 'ORDER BY ' . $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC');
0351   
0352                  $sort_join = ($sort_key == 'f') ? FORUMS_TABLE . ' f, ' : '';
0353                  $sql_sort = ($sort_key == 'f') ? ' AND f.forum_id = p.forum_id ' . $sql_sort : $sql_sort;
0354   
0355                  if ($sort_days)
0356                  {
0357                      $last_post_time = 'AND p.post_time > ' . (time() - ($sort_days * 24 * 3600));
0358                  }
0359                  else
0360                  {
0361                      $last_post_time = '';
0362                  }
0363   
0364                  if ($sort_key == 'a')
0365                  {
0366                      $sort_join = USERS_TABLE . ' u, ';
0367                      $sql_sort = ' AND u.user_id = p.poster_id ' . $sql_sort;
0368                  }
0369                  if ($show_results == 'posts')
0370                  {
0371                      $sql = "SELECT p.post_id
0372                          FROM $sort_join" . POSTS_TABLE . ' p, ' . TOPICS_TABLE . " t
0373                          WHERE t.topic_posts_approved = 1
0374                              AND p.topic_id = t.topic_id
0375                              $last_post_time
0376                              AND $m_approve_posts_fid_sql
0377                              " . ((sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . "
0378                              $sql_sort";
0379                      $field = 'post_id';
0380                  }
0381                  else
0382                  {
0383                      $sql = 'SELECT DISTINCT ' . $sort_by_sql[$sort_key] . ", p.topic_id
0384                          FROM $sort_join" . POSTS_TABLE . ' p, ' . TOPICS_TABLE . " t
0385                          WHERE t.topic_posts_approved = 1
0386                              AND t.topic_moved_id = 0
0387                              AND p.topic_id = t.topic_id
0388                              $last_post_time
0389                              AND $m_approve_topics_fid_sql
0390                              " . ((sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . "
0391                          $sql_sort";
0392                      $field = 'topic_id';
0393                  }
0394              break;
0395   
0396              case 'unreadposts':
0397                  $l_search_title = $user->lang['SEARCH_UNREAD'];
0398                  // force sorting
0399                  $show_results = 'topics';
0400                  $sort_key = 't';
0401                  $sort_by_sql['t'] = 't.topic_last_post_time';
0402                  $sql_sort = 'ORDER BY ' . $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC');
0403   
0404                  $sql_where = 'AND t.topic_moved_id = 0
0405                      AND ' . $m_approve_topics_fid_sql . '
0406                      ' . ((sizeof($ex_fid_ary)) ? 'AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '');
0407   
0408                  gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
0409                  $s_sort_key = $s_sort_dir = $u_sort_param = $s_limit_days = '';
0410              break;
0411   
0412              case 'newposts':
0413                  $l_search_title = $user->lang['SEARCH_NEW'];
0414                  // force sorting
0415                  $show_results = (request_var('sr', 'topics') == 'posts') ? 'posts' : 'topics';
0416                  $sort_key = 't';
0417                  $sort_dir = 'd';
0418                  $sort_by_sql['t'] = ($show_results == 'posts') ? 'p.post_time' : 't.topic_last_post_time';
0419                  $sql_sort = 'ORDER BY ' . $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC');
0420   
0421                  gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
0422                  $s_sort_key = $s_sort_dir = $u_sort_param = $s_limit_days = '';
0423   
0424                  if ($show_results == 'posts')
0425                  {
0426                      $sql = 'SELECT p.post_id
0427                          FROM ' . POSTS_TABLE . ' p
0428                          WHERE p.post_time > ' . $user->data['user_lastvisit'] . '
0429                              AND ' . $m_approve_posts_fid_sql . '
0430                              ' . ((sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . "
0431                          $sql_sort";
0432                      $field = 'post_id';
0433                  }
0434                  else
0435                  {
0436                      $sql = 'SELECT t.topic_id
0437                          FROM ' . TOPICS_TABLE . ' t
0438                          WHERE t.topic_last_post_time > ' . $user->data['user_lastvisit'] . '
0439                              AND t.topic_moved_id = 0
0440                              AND ' . $m_approve_topics_fid_sql . '
0441                              ' . ((sizeof($ex_fid_ary)) ? 'AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . "
0442                          $sql_sort";
0443  /*
0444          [Fix] queued replies missing from "view new posts" (Bug #42705 - Patch by Paul)
0445          - Creates temporary table, query is far from optimized
0446   
0447                      $sql = 'SELECT t.topic_id
0448                          FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
0449                          WHERE p.post_time > ' . $user->data['user_lastvisit'] . '
0450                              AND t.topic_id = p.topic_id
0451                              AND t.topic_moved_id = 0
0452                              AND ' . $m_approve_topics_fid_sql . "
0453                          GROUP BY t.topic_id
0454                          $sql_sort";
0455  */
0456                      $field = 'topic_id';
0457                  }
0458              break;
0459   
0460              case 'egosearch':
0461                  $l_search_title = $user->lang['SEARCH_SELF'];
0462              break;
0463          }
0464      }
0465   
0466      // show_results should not change after this
0467      $per_page = ($show_results == 'posts') ? $config['posts_per_page'] : $config['topics_per_page'];
0468      $total_match_count = 0;
0469   
0470      // Set limit for the $total_match_count to reduce server load
0471      $total_matches_limit = 1000;
0472      $found_more_search_matches = false;
0473   
0474      if ($search_id)
0475      {
0476          if ($sql)
0477          {
0478              // Only return up to $total_matches_limit+1 ids (the last one will be removed later)
0479              $result = $db->sql_query_limit($sql, $total_matches_limit + 1);
0480   
0481              while ($row = $db->sql_fetchrow($result))
0482              {
0483                  $id_ary[] = (int) $row[$field];
0484              }
0485              $db->sql_freeresult($result);
0486          }
0487          else if ($search_id == 'unreadposts')
0488          {
0489              // Only return up to $total_matches_limit+1 ids (the last one will be removed later)
0490              $id_ary = array_keys(get_unread_topics($user->data['user_id'], $sql_where, $sql_sort, $total_matches_limit + 1));
0491          }
0492          else
0493          {
0494              $search_id = '';
0495          }
0496   
0497          $total_match_count = sizeof($id_ary);
0498          if ($total_match_count)
0499          {
0500              // Limit the number to $total_matches_limit for pre-made searches
0501              if ($total_match_count > $total_matches_limit)
0502              {
0503                  $found_more_search_matches = true;
0504                  $total_match_count = $total_matches_limit;
0505              }
0506   
0507              // Make sure $start is set to the last page if it exceeds the amount
0508              $start = $pagination->validate_start($start, $per_page, $total_match_count);
0509   
0510              $id_ary = array_slice($id_ary, $start, $per_page);
0511          }
0512          else
0513          {
0514              // Set $start to 0 if no matches were found
0515              $start = 0;
0516          }
0517      }
0518   
0519      // make sure that some arrays are always in the same order
0520      sort($ex_fid_ary);
0521      sort($author_id_ary);
0522   
0523      if ($search->get_search_query())
0524      {
0525          $total_match_count = $search->keyword_search($show_results, $search_fields, $search_terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_posts_fid_sql, $topic_id, $author_id_ary, $sql_author_match, $id_ary, $start, $per_page);
0526      }
0527      else if (sizeof($author_id_ary))
0528      {
0529          $firstpost_only = ($search_fields === 'firstpost' || $search_fields == 'titleonly') ? true : false;
0530          $total_match_count = $search->author_search($show_results, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_posts_fid_sql, $topic_id, $author_id_ary, $sql_author_match, $id_ary, $start, $per_page);
0531      }
0532   
0533      $sql_where = '';
0534   
0535      if (sizeof($id_ary))
0536      {
0537          $sql_where .= $db->sql_in_set(($show_results == 'posts') ? 'p.post_id' : 't.topic_id', $id_ary);
0538          $sql_where .= (sizeof($ex_fid_ary)) ? ' AND (' . $db->sql_in_set('f.forum_id', $ex_fid_ary, true) . ' OR f.forum_id IS NULL)' : '';
0539          $sql_where .= ' AND ' . (($show_results == 'posts') ? $m_approve_posts_fid_sql : $m_approve_topics_fid_sql);
0540      }
0541   
0542      if ($show_results == 'posts')
0543      {
0544          include($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
0545      }
0546      else
0547      {
0548          include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
0549      }
0550   
0551      $user->add_lang('viewtopic');
0552   
0553      // Grab icons
0554      $icons = $cache->obtain_icons();
0555   
0556      // define some vars for urls
0557      // A single wildcard will make the search results look ugly
0558      $hilit = phpbb_clean_search_string(str_replace(array('+', '-', '|', '(', ')', '&quot;'), ' ', $keywords));
0559      $hilit = str_replace(' ', '|', $hilit);
0560   
0561      $u_hilit = urlencode(htmlspecialchars_decode(str_replace('|', ' ', $hilit)));
0562      $u_show_results = '&amp;sr=' . $show_results;
0563      $u_search_forum = implode('&amp;fid%5B%5D=', $search_forum);
0564   
0565      $u_search = append_sid("{$phpbb_root_path}search.$phpEx", $u_sort_param . $u_show_results);
0566      $u_search .= ($search_id) ? '&amp;search_id=' . $search_id : '';
0567      $u_search .= ($u_hilit) ? '&amp;keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
0568      $u_search .= ($search_terms != 'all') ? '&amp;terms=' . $search_terms : '';
0569      $u_search .= ($topic_id) ? '&amp;t=' . $topic_id : '';
0570      $u_search .= ($author) ? '&amp;author=' . urlencode(htmlspecialchars_decode($author)) : '';
0571      $u_search .= ($author_id) ? '&amp;author_id=' . $author_id : '';
0572      $u_search .= ($u_search_forum) ? '&amp;fid%5B%5D=' . $u_search_forum : '';
0573      $u_search .= (!$search_child) ? '&amp;sc=0' : '';
0574      $u_search .= ($search_fields != 'all') ? '&amp;sf=' . $search_fields : '';
0575      $u_search .= ($return_chars != 300) ? '&amp;ch=' . $return_chars : '';
0576   
0577      if ($sql_where)
0578      {
0579          if ($show_results == 'posts')
0580          {
0581              // @todo Joining this query to the one below?
0582              $sql = 'SELECT zebra_id, friend, foe
0583                  FROM ' . ZEBRA_TABLE . '
0584                  WHERE user_id = ' . $user->data['user_id'];
0585              $result = $db->sql_query($sql);
0586   
0587              $zebra = array();
0588              while ($row = $db->sql_fetchrow($result))
0589              {
0590                  $zebra[($row['friend']) ? 'friend' : 'foe'][] = $row['zebra_id'];
0591              }
0592              $db->sql_freeresult($result);
0593   
0594              $sql_array = array(
0595                  'SELECT'    => 'p.*, f.forum_id, f.forum_name, t.*, u.username, u.username_clean, u.user_sig, u.user_sig_bbcode_uid, u.user_colour',
0596                  'FROM'        => array(
0597                      POSTS_TABLE        => 'p',
0598                  ),
0599                  'LEFT_JOIN' => array(
0600                      array(
0601                          'FROM'    => array(TOPICS_TABLE => 't'),
0602                          'ON'    => 'p.topic_id = t.topic_id',
0603                      ),
0604                      array(
0605                          'FROM'    => array(FORUMS_TABLE => 'f'),
0606                          'ON'    => 'p.forum_id = f.forum_id',
0607                      ),
0608                      array(
0609                          'FROM'    => array(USERS_TABLE => 'u'),
0610                          'ON'    => 'p.poster_id = u.user_id',
0611                      ),
0612                  ),
0613                  'WHERE'    => $sql_where,
0614                  'ORDER_BY' => $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'),
0615              );
0616   
0617              /**
0618              * Event to modify the SQL query before the posts data is retrieved
0619              *
0620              * @event core.search_get_posts_data
0621              * @var    array    sql_array        The SQL array
0622              * @var    array    zebra            Array of zebra data for the current user
0623              * @var    int        total_match_count    The total number of search matches
0624              * @var    string    keywords        String of the specified keywords
0625              * @var    array    sort_by_sql        Array of SQL sorting instructions
0626              * @var    string    s_sort_dir        The sort direction
0627              * @var    string    s_sort_key        The sort key
0628              * @var    string    s_limit_days    Limit the age of results
0629              * @var    array    ex_fid_ary        Array of excluded forum ids
0630              * @var    array    author_id_ary    Array of exclusive author ids
0631              * @var    string    search_fields    The data fields to search in
0632              * @var    int        search_id        The id of the search request
0633              * @var    int        start            The starting id of the results
0634              * @since 3.1.0-b3
0635              */
0636              $vars = array(
0637                  'sql_array',
0638                  'zebra',
0639                  'total_match_count',
0640                  'keywords',
0641                  'sort_by_sql',
0642                  's_sort_dir',
0643                  's_sort_key',
0644                  's_limit_days',
0645                  'ex_fid_ary',
0646                  'author_id_ary',
0647                  'search_fields',
0648                  'search_id',
0649                  'start',
0650              );
0651              extract($phpbb_dispatcher->trigger_event('core.search_get_posts_data', compact($vars)));
0652   
0653              $sql = $db->sql_build_query('SELECT', $sql_array);
0654          }
0655          else
0656          {
0657              $sql_from = TOPICS_TABLE . ' t
0658                  LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = t.forum_id)
0659                  ' . (($sort_key == 'a') ? ' LEFT JOIN ' . USERS_TABLE . ' u ON (u.user_id = t.topic_poster) ' : '');
0660              $sql_select = 't.*, f.forum_id, f.forum_name';
0661   
0662              if ($user->data['is_registered'])
0663              {
0664                  if ($config['load_db_track'] && $author_id !== $user->data['user_id'])
0665                  {
0666                      $sql_from .= ' LEFT JOIN ' . TOPICS_POSTED_TABLE . ' tp ON (tp.user_id = ' . $user->data['user_id'] . '
0667                          AND t.topic_id = tp.topic_id)';
0668                      $sql_select .= ', tp.topic_posted';
0669                  }
0670   
0671                  if ($config['load_db_lastread'])
0672                  {
0673                      $sql_from .= ' LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt ON (tt.user_id = ' . $user->data['user_id'] . '
0674                              AND t.topic_id = tt.topic_id)
0675                          LEFT JOIN ' . FORUMS_TRACK_TABLE . ' ft ON (ft.user_id = ' . $user->data['user_id'] . '
0676                              AND ft.forum_id = f.forum_id)';
0677                      $sql_select .= ', tt.mark_time, ft.mark_time as f_mark_time';
0678                  }
0679              }
0680   
0681              if ($config['load_anon_lastread'] || ($user->data['is_registered'] && !$config['load_db_lastread']))
0682              {
0683                  $tracking_topics = $request->variable($config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE);
0684                  $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
0685              }
0686   
0687              /**
0688              * Event to modify the SQL query before the topic data is retrieved
0689              *
0690              * @event core.search_get_topic_data
0691              * @var    string    sql_select        The SQL SELECT string used by search to get topic data
0692              * @var    string    sql_from        The SQL FROM string used by search to get topic data
0693              * @var    string    sql_where        The SQL WHERE string used by search to get topic data
0694              * @var    int        total_match_count    The total number of search matches
0695              * @since 3.1.0-a1
0696              * @changed 3.1.0-RC5 Added total_match_count
0697              */
0698              $vars = array('sql_select', 'sql_from', 'sql_where', 'total_match_count');
0699              extract($phpbb_dispatcher->trigger_event('core.search_get_topic_data', compact($vars)));
0700   
0701              $sql = "SELECT $sql_select
0702                  FROM $sql_from
0703                  WHERE $sql_where";
0704              $sql .= ' ORDER BY ' . $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
0705          }
0706          $result = $db->sql_query($sql);
0707          $result_topic_id = 0;
0708   
0709          $rowset = array();
0710   
0711          if ($show_results == 'topics')
0712          {
0713              $forums = $rowset = $shadow_topic_list = array();
0714              while ($row = $db->sql_fetchrow($result))
0715              {
0716                  $row['forum_id'] = (int) $row['forum_id'];
0717                  $row['topic_id'] = (int) $row['topic_id'];
0718   
0719                  if ($row['topic_status'] == ITEM_MOVED)
0720                  {
0721                      $shadow_topic_list[$row['topic_moved_id']] = $row['topic_id'];
0722                  }
0723   
0724                  $rowset[$row['topic_id']] = $row;
0725   
0726                  if (!isset($forums[$row['forum_id']]) && $user->data['is_registered'] && $config['load_db_lastread'])
0727                  {
0728                      $forums[$row['forum_id']]['mark_time'] = $row['f_mark_time'];
0729                  }
0730                  $forums[$row['forum_id']]['topic_list'][] = $row['topic_id'];
0731                  $forums[$row['forum_id']]['rowset'][$row['topic_id']] = &$rowset[$row['topic_id']];
0732              }
0733              $db->sql_freeresult($result);
0734   
0735              // If we have some shadow topics, update the rowset to reflect their topic information
0736              if (sizeof($shadow_topic_list))
0737              {
0738                  $sql = 'SELECT *
0739                      FROM ' . TOPICS_TABLE . '
0740                      WHERE ' . $db->sql_in_set('topic_id', array_keys($shadow_topic_list));
0741                  $result = $db->sql_query($sql);
0742   
0743                  while ($row = $db->sql_fetchrow($result))
0744                  {
0745                      $orig_topic_id = $shadow_topic_list[$row['topic_id']];
0746   
0747                      // We want to retain some values
0748                      $row = array_merge($row, array(
0749                          'topic_moved_id'    => $rowset[$orig_topic_id]['topic_moved_id'],
0750                          'topic_status'        => $rowset[$orig_topic_id]['topic_status'],
0751                          'forum_name'        => $rowset[$orig_topic_id]['forum_name'])
0752                      );
0753   
0754                      $rowset[$orig_topic_id] = $row;
0755                  }
0756                  $db->sql_freeresult($result);
0757              }
0758              unset($shadow_topic_list);
0759   
0760              foreach ($forums as $forum_id => $forum)
0761              {
0762                  if ($user->data['is_registered'] && $config['load_db_lastread'])
0763                  {
0764                      $topic_tracking_info[$forum_id] = get_topic_tracking($forum_id, $forum['topic_list'], $forum['rowset'], array($forum_id => $forum['mark_time']));
0765                  }
0766                  else if ($config['load_anon_lastread'] || $user->data['is_registered'])
0767                  {
0768                      $topic_tracking_info[$forum_id] = get_complete_topic_tracking($forum_id, $forum['topic_list']);
0769   
0770                      if (!$user->data['is_registered'])
0771                      {
0772                          $user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate']) : 0;
0773                      }
0774                  }
0775              }
0776              unset($forums);
0777          }
0778          else
0779          {
0780              $bbcode_bitfield = $text_only_message = '';
0781              $attach_list = array();
0782   
0783              while ($row = $db->sql_fetchrow($result))
0784              {
0785                  // We pre-process some variables here for later usage
0786                  $row['post_text'] = censor_text($row['post_text']);
0787   
0788                  $text_only_message = $row['post_text'];
0789                  // make list items visible as such
0790                  if ($row['bbcode_uid'])
0791                  {
0792                      $text_only_message = str_replace('[*:' . $row['bbcode_uid'] . ']', '&sdot;&nbsp;', $text_only_message);
0793                      // no BBCode in text only message
0794                      strip_bbcode($text_only_message, $row['bbcode_uid']);
0795                  }
0796   
0797                  if ($return_chars == -1 || utf8_strlen($text_only_message) < ($return_chars + 3))
0798                  {
0799                      $row['display_text_only'] = false;
0800                      $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']);
0801   
0802                      // Does this post have an attachment? If so, add it to the list
0803                      if ($row['post_attachment'] && $config['allow_attachments'])
0804                      {
0805                          $attach_list[$row['forum_id']][] = $row['post_id'];
0806                      }
0807                  }
0808                  else
0809                  {
0810                      $row['post_text'] = $text_only_message;
0811                      $row['display_text_only'] = true;
0812                  }
0813   
0814                  $rowset[] = $row;
0815              }
0816              $db->sql_freeresult($result);
0817   
0818              unset($text_only_message);
0819   
0820              // Instantiate BBCode if needed
0821              if ($bbcode_bitfield !== '')
0822              {
0823                  include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx);
0824                  $bbcode = new bbcode(base64_encode($bbcode_bitfield));
0825              }
0826   
0827              // Pull attachment data
0828              if (sizeof($attach_list))
0829              {
0830                  $use_attach_list = $attach_list;
0831                  $attach_list = array();
0832   
0833                  foreach ($use_attach_list as $forum_id => $_list)
0834                  {
0835                      if ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id))
0836                      {
0837                          $attach_list = array_merge($attach_list, $_list);
0838                      }
0839                  }
0840              }
0841   
0842              if (sizeof($attach_list))
0843              {
0844                  $sql = 'SELECT *
0845                      FROM ' . ATTACHMENTS_TABLE . '
0846                      WHERE ' . $db->sql_in_set('post_msg_id', $attach_list) . '
0847                          AND in_message = 0
0848                      ORDER BY filetime DESC, post_msg_id ASC';
0849                  $result = $db->sql_query($sql);
0850   
0851                  while ($row = $db->sql_fetchrow($result))
0852                  {
0853                      $attachments[$row['post_msg_id']][] = $row;
0854                  }
0855                  $db->sql_freeresult($result);
0856              }
0857          }
0858   
0859          if ($hilit)
0860          {
0861              // Remove bad highlights
0862              $hilit_array = array_filter(explode('|', $hilit), 'strlen');
0863              foreach ($hilit_array as $key => $value)
0864              {
0865                  $hilit_array[$key] = phpbb_clean_search_string($value);
0866                  $hilit_array[$key] = str_replace('\*', '\w*?', preg_quote($hilit_array[$key], '#'));
0867                  $hilit_array[$key] = preg_replace('#(^|\s)\\\\w\*\?(\s|$)#', '$1\w+?$2', $hilit_array[$key]);
0868              }
0869              $hilit = implode('|', $hilit_array);
0870          }
0871   
0872          /**
0873          * Modify the rowset data
0874          *
0875          * @event core.search_modify_rowset
0876          * @var    array    attachments                Array with posts attachments data
0877          * @var    string    hilit                    String to highlight
0878          * @var    array    rowset                    Array with the search results data
0879          * @var    string    show_results            String indicating the show results mode
0880          * @var    array    topic_tracking_info        Array with the topics tracking data
0881          * @var    string    u_hilit                    Highlight string to be injected into URL
0882          * @var    string    view                    Search results view mode
0883          * @var    array    zebra                    Array with zebra data for the current user
0884          * @since 3.1.0-b4
0885          * @changed 3.1.0-b5 Added var show_results
0886          */
0887          $vars = array(
0888              'attachments',
0889              'hilit',
0890              'rowset',
0891              'show_results',
0892              'topic_tracking_info',
0893              'u_hilit',
0894              'view',
0895              'zebra',
0896          );
0897          extract($phpbb_dispatcher->trigger_event('core.search_modify_rowset', compact($vars)));
0898   
0899          foreach ($rowset as $row)
0900          {
0901              $forum_id = $row['forum_id'];
0902              $result_topic_id = $row['topic_id'];
0903              $topic_title = censor_text($row['topic_title']);
0904              $replies = $phpbb_content_visibility->get_count('topic_posts', $row, $forum_id) - 1;
0905   
0906              $view_topic_url_params = "f=$forum_id&amp;t=$result_topic_id" . (($u_hilit) ? "&amp;hilit=$u_hilit" : '');
0907              $view_topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params);
0908   
0909              if ($show_results == 'topics')
0910              {
0911                  if ($config['load_db_track'] && $author_id === $user->data['user_id'])
0912                  {
0913                      $row['topic_posted'] = 1;
0914                  }
0915   
0916                  $folder_img = $folder_alt = $topic_type = '';
0917                  topic_status($row, $replies, (isset($topic_tracking_info[$forum_id][$row['topic_id']]) && $row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']]) ? true : false, $folder_img, $folder_alt, $topic_type);
0918   
0919                  $unread_topic = (isset($topic_tracking_info[$forum_id][$row['topic_id']]) && $row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']]) ? true : false;
0920   
0921                  $topic_unapproved = (($row['topic_visibility'] == ITEM_UNAPPROVED || $row['topic_visibility'] == ITEM_REAPPROVE) && $auth->acl_get('m_approve', $forum_id)) ? true : false;
0922                  $posts_unapproved = ($row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $auth->acl_get('m_approve', $forum_id)) ? true : false;
0923                  $topic_deleted = $row['topic_visibility'] == ITEM_DELETED;
0924                  $u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . "&amp;t=$result_topic_id", true, $user->session_id) : '';
0925                  $u_mcp_queue = (!$u_mcp_queue && $topic_deleted) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&amp;mode=deleted_topics&amp;t=$result_topic_id", true, $user->session_id) : '';
0926   
0927                  $row['topic_title'] = preg_replace('#(?!<.*)(?<!\w)(' . $hilit . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#is', '<span class="posthilit">$1</span>', $row['topic_title']);
0928   
0929                  $tpl_ary = array(
0930                      'TOPIC_AUTHOR'                => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
0931                      'TOPIC_AUTHOR_COLOUR'        => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
0932                      'TOPIC_AUTHOR_FULL'            => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
0933                      'FIRST_POST_TIME'            => $user->format_date($row['topic_time']),
0934                      'LAST_POST_SUBJECT'            => $row['topic_last_post_subject'],
0935                      'LAST_POST_TIME'            => $user->format_date($row['topic_last_post_time']),
0936                      'LAST_VIEW_TIME'            => $user->format_date($row['topic_last_view_time']),
0937                      'LAST_POST_AUTHOR'            => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
0938                      'LAST_POST_AUTHOR_COLOUR'    => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
0939                      'LAST_POST_AUTHOR_FULL'        => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
0940   
0941                      'TOPIC_TYPE'        => $topic_type,
0942   
0943                      'TOPIC_IMG_STYLE'        => $folder_img,
0944                      'TOPIC_FOLDER_IMG'        => $user->img($folder_img, $folder_alt),
0945                      'TOPIC_FOLDER_IMG_ALT'    => $user->lang[$folder_alt],
0946   
0947                      'TOPIC_ICON_IMG'        => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '',
0948                      'TOPIC_ICON_IMG_WIDTH'    => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '',
0949                      'TOPIC_ICON_IMG_HEIGHT'    => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '',
0950                      'ATTACH_ICON_IMG'        => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '',
0951                      'UNAPPROVED_IMG'        => ($topic_unapproved || $posts_unapproved) ? $user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '',
0952   
0953                      'S_TOPIC_TYPE'            => $row['topic_type'],
0954                      'S_USER_POSTED'            => (!empty($row['topic_posted'])) ? true : false,
0955                      'S_UNREAD_TOPIC'        => $unread_topic,
0956   
0957                      'S_TOPIC_REPORTED'        => (!empty($row['topic_reported']) && $auth->acl_get('m_report', $forum_id)) ? true : false,
0958                      'S_TOPIC_UNAPPROVED'    => $topic_unapproved,
0959                      'S_POSTS_UNAPPROVED'    => $posts_unapproved,
0960                      'S_TOPIC_DELETED'        => $topic_deleted,
0961                      'S_HAS_POLL'            => ($row['poll_start']) ? true : false,
0962   
0963                      'U_LAST_POST'            => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&amp;p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'],
0964                      'U_LAST_POST_AUTHOR'    => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
0965                      'U_TOPIC_AUTHOR'        => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
0966                      'U_NEWEST_POST'            => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&amp;view=unread') . '#unread',
0967                      'U_MCP_REPORT'            => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&amp;mode=reports&amp;t=' . $result_topic_id, true, $user->session_id),
0968                      'U_MCP_QUEUE'            => $u_mcp_queue,
0969                  );
0970              }
0971              else
0972              {
0973                  if ((isset($zebra['foe']) && in_array($row['poster_id'], $zebra['foe'])) && (!$view || $view != 'show' || $post_id != $row['post_id']))
0974                  {
0975                      $template->assign_block_vars('searchresults', array(
0976                          'S_IGNORE_POST' => true,
0977   
0978                          'L_IGNORE_POST' => sprintf($user->lang['POST_BY_FOE'], $row['username'], "<a href=\"$u_search&amp;start=$start&amp;p=" . $row['post_id'] . '&amp;view=show#p' . $row['post_id'] . '">', '</a>'))
0979                      );
0980   
0981                      continue;
0982                  }
0983   
0984                  // Replace naughty words such as farty pants
0985                  $row['post_subject'] = censor_text($row['post_subject']);
0986   
0987                  if ($row['display_text_only'])
0988                  {
0989                      // now find context for the searched words
0990                      $row['post_text'] = get_context($row['post_text'], array_filter(explode('|', $hilit), 'strlen'), $return_chars);
0991                      $row['post_text'] = bbcode_nl2br($row['post_text']);
0992                  }
0993                  else
0994                  {
0995                      $parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES;
0996                      $row['post_text'] = generate_text_for_display($row['post_text'], $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, false);
0997   
0998                      if (!empty($attachments[$row['post_id']]))
0999                      {
1000                          parse_attachments($forum_id, $row['post_text'], $attachments[$row['post_id']], $update_count);
1001   
1002                          // we only display inline attachments
1003                          unset($attachments[$row['post_id']]);
1004                      }
1005                  }
1006   
1007                  if ($hilit)
1008                  {
1009                      // post highlighting
1010                      $row['post_text'] = preg_replace('#(?!<.*)(?<!\w)(' . $hilit . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#is', '<span class="posthilit">$1</span>', $row['post_text']);
1011                      $row['post_subject'] = preg_replace('#(?!<.*)(?<!\w)(' . $hilit . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#is', '<span class="posthilit">$1</span>', $row['post_subject']);
1012                  }
1013   
1014                  $tpl_ary = array(
1015                      'POST_AUTHOR_FULL'        => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']),
1016                      'POST_AUTHOR_COLOUR'    => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']),
1017                      'POST_AUTHOR'            => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']),
1018                      'U_POST_AUTHOR'            => get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']),
1019   
1020                      'POST_SUBJECT'        => $row['post_subject'],
1021                      'POST_DATE'            => (!empty($row['post_time'])) ? $user->format_date($row['post_time']) : '',
1022                      'MESSAGE'            => $row['post_text']
1023                  );
1024              }
1025   
1026              $tpl_ary = array_merge($tpl_ary, array(
1027                  'FORUM_ID'            => $forum_id,
1028                  'TOPIC_ID'            => $result_topic_id,
1029                  'POST_ID'            => ($show_results == 'posts') ? $row['post_id'] : false,
1030   
1031                  'FORUM_TITLE'        => $row['forum_name'],
1032                  'TOPIC_TITLE'        => $topic_title,
1033                  'TOPIC_REPLIES'        => $replies,
1034                  'TOPIC_VIEWS'        => $row['topic_views'],
1035   
1036                  'U_VIEW_TOPIC'        => $view_topic_url,
1037                  'U_VIEW_FORUM'        => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id),
1038                  'U_VIEW_POST'        => (!empty($row['post_id'])) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=" . $row['topic_id'] . '&amp;p=' . $row['post_id'] . (($u_hilit) ? '&amp;hilit=' . $u_hilit : '')) . '#p' . $row['post_id'] : '',
1039              ));
1040   
1041              /**
1042              * Modify the topic data before it is assigned to the template
1043              *
1044              * @event core.search_modify_tpl_ary
1045              * @var    array    row                Array with topic data
1046              * @var    array    tpl_ary            Template block array with topic data
1047              * @var    string    show_results    Display topics or posts
1048              * @var    string    topic_title        Cleaned topic title
1049              * @var    int        replies            The number of topic replies
1050              * @var    string    view_topic_url    The URL to the topic
1051              * @var    string    folder_img        The folder image of the topic
1052              * @var    string    folder_alt        The alt attribute of the topic folder img
1053              * @var    int        topic_type        The topic type
1054              * @var    bool    unread_topic    Whether the topic has unread posts
1055              * @var    bool    topic_unapproved    Whether the topic is unapproved
1056              * @var    int        posts_unapproved    The number of unapproved posts
1057              * @var    bool    topic_deleted    Whether the topic has been deleted
1058              * @var    string    u_mcp_queue        The URL to the corresponding MCP queue page
1059              * @var    array    zebra            The zebra data of the current user
1060              * @var    array    attachments        All the attachments of the search results
1061              * @since 3.1.0-a1
1062              * @changed 3.1.0-b3 Added vars show_results, topic_title, replies,
1063              *        view_topic_url, folder_img, folder_alt, topic_type, unread_topic,
1064              *        topic_unapproved, posts_unapproved, topic_deleted, u_mcp_queue,
1065              *        zebra, attachments
1066              */
1067              $vars = array(
1068                  'row',
1069                  'tpl_ary',
1070                  'show_results',
1071                  'topic_title',
1072                  'replies',
1073                  'view_topic_url',
1074                  'folder_img',
1075                  'folder_alt',
1076                  'topic_type',
1077                  'unread_topic',
1078                  'topic_unapproved',
1079                  'posts_unapproved',
1080                  'topic_deleted',
1081                  'u_mcp_queue',
1082                  'zebra',
1083                  'attachments',
1084              );
1085              extract($phpbb_dispatcher->trigger_event('core.search_modify_tpl_ary', compact($vars)));
1086   
1087              $template->assign_block_vars('searchresults', $tpl_ary);
1088   
1089              if ($show_results == 'topics')
1090              {
1091                  $pagination->generate_template_pagination($view_topic_url, 'searchresults.pagination', 'start', $replies + 1, $config['posts_per_page'], 1, true, true);
1092              }
1093          }
1094   
1095          if ($topic_id && ($topic_id == $result_topic_id))
1096          {
1097              $template->assign_vars(array(
1098                  'SEARCH_TOPIC'        => $topic_title,
1099                  'L_RETURN_TO_TOPIC'    => $user->lang('RETURN_TO', $topic_title),
1100                  'U_SEARCH_TOPIC'    => $view_topic_url
1101              ));
1102          }
1103      }
1104      unset($rowset);
1105   
1106      // Output header
1107      if ($found_more_search_matches)
1108      {
1109          $l_search_matches = $user->lang('FOUND_MORE_SEARCH_MATCHES', (int) $total_match_count);
1110      }
1111      else
1112      {
1113          $l_search_matches = $user->lang('FOUND_SEARCH_MATCHES', (int) $total_match_count);
1114      }
1115   
1116      // Check if search backend supports phrase search or not
1117      $phrase_search_disabled = '';
1118      if (strpos(html_entity_decode($keywords), '"') !== false && method_exists($search, 'supports_phrase_search'))
1119      {
1120          $phrase_search_disabled = $search->supports_phrase_search() ? false : true;
1121      }
1122   
1123      $pagination->generate_template_pagination($u_search, 'pagination', 'start', $total_match_count, $per_page, $start);
1124   
1125      $template->assign_vars(array(
1126          'SEARCH_TITLE'        => $l_search_title,
1127          'SEARCH_MATCHES'    => $l_search_matches,
1128          'SEARCH_WORDS'        => $keywords,
1129          'SEARCHED_QUERY'    => $search->get_search_query(),
1130          'IGNORED_WORDS'        => (!empty($common_words)) ? implode(' ', $common_words) : '',
1131   
1132          'PHRASE_SEARCH_DISABLED'        => $phrase_search_disabled,
1133   
1134          'TOTAL_MATCHES'        => $total_match_count,
1135          'SEARCH_IN_RESULTS'    => ($search_id) ? false : true,
1136   
1137          'S_SELECT_SORT_DIR'        => $s_sort_dir,
1138          'S_SELECT_SORT_KEY'        => $s_sort_key,
1139          'S_SELECT_SORT_DAYS'    => $s_limit_days,
1140          'S_SEARCH_ACTION'        => $u_search,
1141          'S_SHOW_TOPICS'            => ($show_results == 'posts') ? false : true,
1142   
1143          'GOTO_PAGE_IMG'        => $user->img('icon_post_target', 'GOTO_PAGE'),
1144          'NEWEST_POST_IMG'    => $user->img('icon_topic_newest', 'VIEW_NEWEST_POST'),
1145          'REPORTED_IMG'        => $user->img('icon_topic_reported', 'TOPIC_REPORTED'),
1146          'UNAPPROVED_IMG'    => $user->img('icon_topic_unapproved', 'TOPIC_UNAPPROVED'),
1147          'DELETED_IMG'        => $user->img('icon_topic_deleted', 'TOPIC_DELETED'),
1148          'POLL_IMG'            => $user->img('icon_topic_poll', 'TOPIC_POLL'),
1149          'LAST_POST_IMG'        => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'),
1150   
1151          'U_SEARCH_WORDS'    => $u_search,
1152      ));
1153   
1154      /**
1155      * Modify the title and/or load data for the search results page
1156      *
1157      * @event core.search_results_modify_search_title
1158      * @var    int        author_id        ID of the author to search by
1159      * @var    string    l_search_title    The title of the search page
1160      * @var    string    search_id        Predefined search type name
1161      * @var    string    show_results    Search results output mode - topics or posts
1162      * @var    int        start            The starting id of the results
1163      * @since 3.1.0-RC4
1164      */
1165      $vars = array('author_id', 'l_search_title', 'search_id', 'show_results', 'start');
1166      extract($phpbb_dispatcher->trigger_event('core.search_results_modify_search_title', compact($vars)));
1167   
1168      page_header(($l_search_title) ? $l_search_title : $user->lang['SEARCH']);
1169   
1170      $template->set_filenames(array(
1171          'body' => 'search_results.html')
1172      );
1173      make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx"));
1174   
1175      page_footer();
1176  }
1177   
1178  // Search forum
1179  $s_forums = '';
1180  $sql = 'SELECT f.forum_id, f.forum_name, f.parent_id, f.forum_type, f.left_id, f.right_id, f.forum_password, f.enable_indexing, fa.user_id
1181      FROM ' . FORUMS_TABLE . ' f
1182      LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa ON (fa.forum_id = f.forum_id
1183          AND fa.session_id = '" . $db->sql_escape($user->session_id) . "')
1184      ORDER BY f.left_id ASC";
1185  $result = $db->sql_query($sql);
1186   
1187  $right = $cat_right = $padding_inc = 0;
1188  $padding = $forum_list = $holding = '';
1189  $pad_store = array('0' => '');
1190   
1191  while ($row = $db->sql_fetchrow($result))
1192  {
1193      if ($row['forum_type'] == FORUM_CAT && ($row['left_id'] + 1 == $row['right_id']))
1194      {
1195          // Non-postable forum with no subforums, don't display
1196          continue;
1197      }
1198   
1199      if ($row['forum_type'] == FORUM_POST && ($row['left_id'] + 1 == $row['right_id']) && !$row['enable_indexing'])
1200      {
1201          // Postable forum with no subforums and indexing disabled, don't display
1202          continue;
1203      }
1204   
1205      if ($row['forum_type'] == FORUM_LINK || ($row['forum_password'] && !$row['user_id']))
1206      {
1207          // if this forum is a link or password protected (user has not entered the password yet) then skip to the next branch
1208          continue;
1209      }
1210   
1211      if ($row['left_id'] < $right)
1212      {
1213          $padding .= '&nbsp; &nbsp;';
1214          $pad_store[$row['parent_id']] = $padding;
1215      }
1216      else if ($row['left_id'] > $right + 1)
1217      {
1218          if (isset($pad_store[$row['parent_id']]))
1219          {
1220              $padding = $pad_store[$row['parent_id']];
1221          }
1222          else
1223          {
1224              continue;
1225          }
1226      }
1227   
1228      $right = $row['right_id'];
1229   
1230      if ($auth->acl_gets('!f_search', '!f_list', $row['forum_id']))
1231      {
1232          // if the user does not have permissions to search or see this forum skip only this forum/category
1233          continue;
1234      }
1235   
1236      $selected = (in_array($row['forum_id'], $search_forum)) ? ' selected="selected"' : '';
1237   
1238      if ($row['left_id'] > $cat_right)
1239      {
1240          // make sure we don't forget anything
1241          $s_forums .= $holding;
1242          $holding = '';
1243      }
1244   
1245      if ($row['right_id'] - $row['left_id'] > 1)
1246      {
1247          $cat_right = max($cat_right, $row['right_id']);
1248   
1249          $holding .= '<option value="' . $row['forum_id'] . '"' . $selected . '>' . $padding . $row['forum_name'] . '</option>';
1250      }
1251      else
1252      {
1253          $s_forums .= $holding . '<option value="' . $row['forum_id'] . '"' . $selected . '>' . $padding . $row['forum_name'] . '</option>';
1254          $holding = '';
1255      }
1256  }
1257   
1258  if ($holding)
1259  {
1260      $s_forums .= $holding;
1261  }
1262   
1263  $db->sql_freeresult($result);
1264  unset($pad_store);
1265   
1266  if (!$s_forums)
1267  {
1268      trigger_error('NO_SEARCH');
1269  }
1270   
1271  // Number of chars returned
1272  $s_characters = '<option value="-1">' . $user->lang['ALL_AVAILABLE'] . '</option>';
1273  $s_characters .= '<option value="0">0</option>';
1274  $s_characters .= '<option value="25">25</option>';
1275  $s_characters .= '<option value="50">50</option>';
1276   
1277  for ($i = 100; $i <= 1000; $i += 100)
1278  {
1279      $selected = ($i == 300) ? ' selected="selected"' : '';
1280      $s_characters .= '<option value="' . $i . '"' . $selected . '>' . $i . '</option>';
1281  }
1282   
1283  $s_hidden_fields = array('t' => $topic_id);
1284   
1285  if ($_SID)
1286  {
1287      $s_hidden_fields['sid'] = $_SID;
1288  }
1289   
1290  if (!empty($_EXTRA_URL))
1291  {
1292      foreach ($_EXTRA_URL as $url_param)
1293      {
1294          $url_param = explode('=', $url_param, 2);
1295          $s_hidden_fields[$url_param[0]] = $url_param[1];
1296      }
1297  }
1298   
1299  $template->assign_vars(array(
1300      'S_SEARCH_ACTION'        => append_sid("{$phpbb_root_path}search.$phpEx", false, true, 0), // We force no ?sid= appending by using 0
1301      'S_HIDDEN_FIELDS'        => build_hidden_fields($s_hidden_fields),
1302      'S_CHARACTER_OPTIONS'    => $s_characters,
1303      'S_FORUM_OPTIONS'        => $s_forums,
1304      'S_SELECT_SORT_DIR'        => $s_sort_dir,
1305      'S_SELECT_SORT_KEY'        => $s_sort_key,
1306      'S_SELECT_SORT_DAYS'    => $s_limit_days,
1307      'S_IN_SEARCH'            => true,
1308  ));
1309   
1310  // only show recent searches to search administrators
1311  if ($auth->acl_get('a_search'))
1312  {
1313      // Handle large objects differently for Oracle and MSSQL
1314      switch ($db->get_sql_layer())
1315      {
1316          case 'oracle':
1317              $sql = 'SELECT search_time, search_keywords
1318                  FROM ' . SEARCH_RESULTS_TABLE . '
1319                  WHERE dbms_lob.getlength(search_keywords) > 0
1320                  ORDER BY search_time DESC';
1321          break;
1322   
1323          case 'mssql':
1324          case 'mssql_odbc':
1325          case 'mssqlnative':
1326              $sql = 'SELECT search_time, search_keywords
1327                  FROM ' . SEARCH_RESULTS_TABLE . '
1328                  WHERE DATALENGTH(search_keywords) > 0
1329                  ORDER BY search_time DESC';
1330          break;
1331   
1332          default:
1333              $sql = 'SELECT search_time, search_keywords
1334                  FROM ' . SEARCH_RESULTS_TABLE . '
1335                  WHERE search_keywords <> \'\'
1336                  ORDER BY search_time DESC';
1337          break;
1338      }
1339      $result = $db->sql_query_limit($sql, 5);
1340   
1341      while ($row = $db->sql_fetchrow($result))
1342      {
1343          $keywords = $row['search_keywords'];
1344   
1345          $template->assign_block_vars('recentsearch', array(
1346              'KEYWORDS'    => $keywords,
1347              'TIME'        => $user->format_date($row['search_time']),
1348   
1349              'U_KEYWORDS'    => append_sid("{$phpbb_root_path}search.$phpEx", 'keywords=' . urlencode(htmlspecialchars_decode($keywords)))
1350          ));
1351      }
1352      $db->sql_freeresult($result);
1353  }
1354   
1355  // Output the basic page
1356  page_header($user->lang['SEARCH']);
1357   
1358  $template->set_filenames(array(
1359      'body' => 'search_body.html')
1360  );
1361  make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx"));
1362   
1363  page_footer();
1364