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