Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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