PageRenderTime 84ms CodeModel.GetById 19ms app.highlight 57ms RepoModel.GetById 1ms app.codeStats 0ms

/upload/search.php

http://torrentpier2.googlecode.com/
PHP | 959 lines | 763 code | 140 blank | 56 comment | 152 complexity | ace2655a86fa0b7f1b9e3bac6a06d445 MD5 | raw file
  1<?php
  2
  3define('BB_SCRIPT', 'search');
  4define('BB_ROOT', './');
  5require(BB_ROOT . 'common.php');
  6
  7require(INC_DIR . 'bbcode.php');
  8require(INC_DIR . 'class.utf8.php');
  9require(INC_DIR . 'class.correct.php');
 10require(INC_DIR . 'class.reflection.php');
 11
 12$page_cfg['load_tpl_vars'] = array(
 13	'post_buttons',
 14	'post_icons',
 15	'topic_icons',
 16);
 17
 18$user->session_start(array('req_login' => $bb_cfg['disable_search_for_guest']));
 19
 20set_die_append_msg();
 21
 22if (isset($_POST['del_my_post']))
 23{
 24	$template->assign_var('BB_DIE_APPEND_MSG', '
 25		<a href="#" onclick="window.close(); window.opener.focus();">'. $lang['GOTO_MY_MESSAGE'] .'</a>
 26		<br /><br />
 27		<a href="index.php">'. $lang['INDEX_RETURN'] .'</a>
 28	');
 29
 30	if (empty($_POST['topic_id_list']) OR !$topic_csv = get_id_csv($_POST['topic_id_list']))
 31	{
 32		bb_die($lang['NONE_SELECTED']);
 33	}
 34
 35	DB()->query("UPDATE ". BB_POSTS ." SET user_post = 0 WHERE poster_id = {$user->id} AND topic_id IN($topic_csv)");
 36
 37	if (DB()->affected_rows())
 38	{
 39		//bb_die('????????? ???? ['. count($_POST['topic_id_list']) .' ??.] ??????? ?? ?????? "??? ?????????"');
 40		bb_die($lang['DEL_MY_MESSAGE']);
 41	}
 42	else
 43	{
 44		bb_die($lang['NO_TOPICS_MY_MESSAGE']);
 45	}
 46}
 47else if(isset($_POST['add_my_post']))
 48{
 49	$template->assign_var('BB_DIE_APPEND_MSG', '
 50		<a href="#" onclick="window.close(); window.opener.focus();">'. $lang['GOTO_MY_MESSAGE'] .'</a>
 51		<br /><br />
 52		<a href="index.php">'. $lang['INDEX_RETURN'] .'</a>
 53	');
 54
 55	if (IS_GUEST)
 56	{
 57		redirect('index.php');
 58	}
 59
 60	DB()->query("UPDATE ". BB_POSTS ." SET user_post = 1 WHERE poster_id = {$user->id}");
 61
 62	redirect("search.php?u={$user->id}");
 63}
 64
 65$tracking_topics = get_tracks('topic');
 66$tracking_forums = get_tracks('forum');
 67
 68if ($mode =& $_REQUEST['mode'])
 69{
 70	// This handles the simple windowed user search functions called from various other scripts
 71	if ($mode == 'searchuser')
 72	{
 73		$username = isset($_POST['search_username']) ? $_POST['search_username'] : '';
 74		username_search($username);
 75		exit;
 76	}
 77}
 78
 79$excluded_forums_csv = $user->get_excluded_forums(AUTH_READ);
 80
 81$search_limit        = 500;
 82$forum_select_size   = 16;   // forum select box max rows
 83$max_forum_name_len  = 60;   // inside forum select box
 84$text_match_max_len  = 60;
 85$poster_name_max_len = 25;
 86
 87$start = isset($_REQUEST['start']) ? abs(intval($_REQUEST['start'])) : 0;
 88$url   = basename(__FILE__);
 89
 90$anon_id    = GUEST_UID;
 91$user_id    = $userdata['user_id'];
 92$lastvisit  = (IS_GUEST) ? TIMENOW : $userdata['user_lastvisit'];
 93$search_id  = (isset($_GET['id']) && verify_id($_GET['id'], SEARCH_ID_LENGTH)) ? $_GET['id'] : '';
 94$session_id = $userdata['session_id'];
 95
 96$items_found = $items_display = $previous_settings = null;
 97$text_match_sql = '';
 98
 99$cat_tbl        = BB_CATEGORIES      .' c';
100$dl_stat_tbl    = BB_BT_DLSTATUS     .' dl';
101$forums_tbl     = BB_FORUMS          .' f';
102$posts_tbl      = BB_POSTS           .' p';
103$posts_text_tbl = BB_POSTS_TEXT      .' pt';
104$posts_html_tbl = BB_POSTS_HTML      .' h';
105$tr_snap_tbl    = BB_BT_TRACKER_SNAP .' sn';
106$topics_tbl     = BB_TOPICS          .' t';
107$torrents_tbl   = BB_BT_TORRENTS     .' tor';
108$tracker_tbl    = BB_BT_TRACKER      .' tr';
109$users_tbl      = BB_USERS           .' u';
110
111// Cat/forum data
112if (!$forums = $datastore->get('cat_forums'))
113{
114	$datastore->update('cat_forums');
115	$forums = $datastore->get('cat_forums');
116}
117$forum_name_html = $forums['forum_name_html'];
118
119//
120// Search options
121//
122// Key values
123$search_all = 0;
124
125$sort_asc   = 1;
126$sort_desc  = 0;
127
128$as_topics = 0;
129$as_posts  = 1;
130
131$show_all     = 0;
132$show_briefly = 1;
133
134$ord_posted   = 1;
135$ord_name     = 2;
136$ord_repl     = 3;
137$ord_views    = 4;
138$ord_last_p   = 5;
139$ord_created  = 6;
140
141// Order options
142$order_opt = array(
143	$ord_posted    => array(
144		'lang' => $lang['SORT_TIME'],
145		'sql'  => 'item_id',
146	),
147	$ord_last_p    => array(
148		'lang' => $lang['BT_LAST_POST'],
149		'sql'  => 't.topic_last_post_id',
150	),
151	$ord_created   => array(
152		'lang' => $lang['BT_CREATED'],
153		'sql'  => 't.topic_time',
154	),
155	$ord_name      => array(
156		'lang' => $lang['SORT_TOPIC_TITLE'],
157		'sql'  => 't.topic_title',
158	),
159	$ord_repl      => array(
160		'lang' => $lang['REPLIES'],
161		'sql'  => 't.topic_replies',
162	),
163);
164$order_select = array();
165foreach ($order_opt as $val => $opt)
166{
167	$order_select[$opt['lang']] = $val;
168}
169
170// Sort direction
171$sort_opt = array(
172	$sort_asc  => array(
173		'lang' => $lang['ASC'],
174		'sql'  => ' ASC ',
175	),
176	$sort_desc => array(
177		'lang' => $lang['DESC'],
178		'sql'  => ' DESC ',
179	),
180);
181$sort_select = array();
182foreach ($sort_opt as $val => $opt)
183{
184	$sort_select[$opt['lang']] = $val;
185}
186
187// Previous days
188$time_opt = array(
189	$search_all => array(
190		'lang' => $lang['BT_ALL_DAYS_FOR'],
191		'sql'  => 0,
192	),
193	1  => array(
194		'lang' => $lang['BT_1_DAY_FOR'],
195		'sql'  => TIMENOW - 86400,
196	),
197	3  => array(
198		'lang' => $lang['BT_3_DAY_FOR'],
199		'sql'  => TIMENOW - 86400*3,
200	),
201	7  => array(
202		'lang' => $lang['BT_7_DAYS_FOR'],
203		'sql'  => TIMENOW - 86400*7,
204	),
205	14 => array(
206		'lang' => $lang['BT_2_WEEKS_FOR'],
207		'sql'  => TIMENOW - 86400*14,
208	),
209	30 => array(
210		'lang' => $lang['BT_1_MONTH_FOR'],
211		'sql'  => TIMENOW - 86400*30,
212	),
213);
214$time_select = array();
215foreach ($time_opt as $val => $opt)
216{
217	$time_select[$opt['lang']] = $val;
218}
219
220// Display as
221$display_as_opt = array(
222	$as_topics => array(
223		'lang' => $lang['TOPICS'],
224	),
225	$as_posts  => array(
226		'lang' => $lang['MESSAGE'],
227	),
228);
229$display_as_select = array();
230foreach ($display_as_opt as $val => $opt)
231{
232	$display_as_select[$opt['lang']] = $val;
233}
234
235// Chars
236$chars_opt = array(
237	$show_all => array(
238		'lang' => $lang['ALL_AVAILABLE'],
239	),
240	$show_briefly  => array(
241		'lang' => $lang['BRIEFLY'],
242	),
243);
244$chars_select = array();
245foreach ($chars_opt as $val => $opt)
246{
247	$chars_select[$opt['lang']] = $val;
248}
249
250$GPC = array(
251#	  var_name              key_name  def_value    GPC type
252	'all_words'     => array('allw',  1,            CHBOX),
253	'cat'           => array('c',     null,         REQUEST),
254	'chars'         => array('ch',    $show_all,    SELECT),
255	'display_as'    => array('dm',    $as_topics,   SELECT),
256	'dl_cancel'     => array('dla',   0,            CHBOX),
257	'dl_compl'      => array('dlc',   0,            CHBOX),
258	'dl_down'       => array('dld',   0,            CHBOX),
259	'dl_user_id'    => array('dlu',   $user_id,     CHBOX),
260	'dl_will'       => array('dlw',   0,            CHBOX),
261	'forum'         => array('f',     $search_all,  REQUEST),
262	'my_topics'     => array('myt',   0,            CHBOX),
263	'new'           => array('new',   0,            CHBOX),
264	'new_topics'    => array('nt',    0,            CHBOX),
265	'order'         => array('o',     $ord_posted,  SELECT),
266	'poster_id'     => array('uid',   null,         REQUEST),
267	'poster_name'   => array('pn',    null,         REQUEST),
268	'sort'          => array('s',     $sort_desc,   SELECT),
269	'text_match'    => array('nm',    null,         REQUEST),
270	'time'          => array('tm',    $search_all,  SELECT),
271	'title_only'    => array('to',    0,            CHBOX),
272	'topic'         => array('t',     null,         REQUEST),
273);
274
275// Define all GPC vars with default values
276foreach ($GPC as $var_name => $var_options)
277{
278	$GLOBALS["{$var_name}_key"] = $var_options[KEY_NAME];
279	$GLOBALS["{$var_name}_val"] = $var_options[DEF_VAL];
280}
281
282// Output basic page
283if (empty($_GET) && empty($_POST))
284{
285	// Make forum select box
286	$forum_select_mode = explode(',', $excluded_forums_csv);
287	$forum_select = get_forum_select($forum_select_mode, "{$forum_key}[]", $search_all, $max_forum_name_len, $forum_select_size, 'style="width: 95%;"', $search_all);
288
289	$template->assign_vars(array(
290		'TPL_SEARCH_MAIN'   => true,
291		'PAGE_TITLE'        => $lang['SEARCH'],
292
293		'POSTER_ID_KEY'     => $poster_id_key,
294		'TEXT_MATCH_KEY'    => $text_match_key,
295		'POSTER_NAME_KEY'   => $poster_name_key,
296
297		'THIS_USER_ID'      => $userdata['user_id'],
298		'THIS_USER_NAME'    => addslashes($userdata['username']),
299		'SEARCH_ACTION'     => "search.php",
300		'U_SEARCH_USER'     => "search.php?mode=searchuser&amp;input_name=$poster_name_key",
301		'ONLOAD_FOCUS_ID'   => 'text_match_input',
302
303		'MY_TOPICS_ID'      => 'my_topics',
304		'MY_TOPICS_CHBOX'   => build_checkbox ($my_topics_key,  $lang['SEARCH_MY_TOPICS'],   $my_topics_val,  true,     null, 'my_topics'),
305		'TITLE_ONLY_CHBOX'  => build_checkbox ($title_only_key, $lang['SEARCH_TITLES_ONLY'], true,            $bb_cfg['disable_ft_search_in_posts']),
306		'ALL_WORDS_CHBOX'   => build_checkbox ($all_words_key,  $lang['SEARCH_ALL_WORDS'],   true),
307		'DL_CANCEL_CHBOX'   => build_checkbox ($dl_cancel_key,  $lang['SEARCH_DL_CANCEL'],   $dl_cancel_val,  IS_GUEST, 'dlCancel'),
308		'DL_COMPL_CHBOX'    => build_checkbox ($dl_compl_key,   $lang['SEARCH_DL_COMPLETE'], $dl_compl_val,   IS_GUEST, 'dlComplete'),
309		'DL_DOWN_CHBOX'     => build_checkbox ($dl_down_key,    $lang['SEARCH_DL_DOWN'],     $dl_down_val,    IS_GUEST, 'dlDown'),
310		'DL_WILL_CHBOX'     => build_checkbox ($dl_will_key,    $lang['SEARCH_DL_WILL'],     $dl_will_val,    IS_GUEST, 'dlWill'),
311		'ONLY_NEW_CHBOX'    => build_checkbox ($new_key,        $lang['BT_ONLY_NEW'],        $new_val,        IS_GUEST),
312		'NEW_TOPICS_CHBOX'  => build_checkbox ($new_topics_key, $lang['NEW_TOPICS'],         $new_topics_val, IS_GUEST),
313
314		'FORUM_SELECT'      => $forum_select,
315		'TIME_SELECT'       => build_select ($time_key,  $time_select,  $time_val),
316		'ORDER_SELECT'      => build_select ($order_key, $order_select, $order_val),
317		'SORT_SELECT'       => build_select ($sort_key,  $sort_select,  $sort_val),
318		'CHARS_SELECT'      => '', # build_select ($chars_key, $chars_select, $chars_val),
319		'DISPLAY_AS_SELECT' => build_select ($display_as_key, $display_as_select, $display_as_val),
320	));
321
322	print_page('search.tpl');
323}
324
325unset($forums);
326$datastore->rm('cat_forums');
327
328// Restore previously found items list and search settings if we have valid $search_id
329if ($search_id)
330{
331	$row = DB()->fetch_row("
332		SELECT search_array, search_settings
333		FROM ". BB_SEARCH ."
334		WHERE session_id = '$session_id'
335			AND search_type = ". SEARCH_TYPE_POST ."
336			AND search_id = '$search_id'
337		LIMIT 1
338	");
339
340	if (empty($row['search_settings']))
341	{
342		bb_die($lang['SESSION_EXPIRED']);
343	}
344
345	$previous_settings = unserialize($row['search_settings']);
346	$items_found = explode(',', $row['search_array']);
347}
348
349// Get simple "CHBOX" and "SELECT" type vars
350foreach ($GPC as $name => $params)
351{
352	if ($params[GPC_TYPE] == CHBOX)
353	{
354		checkbox_get_val($params[KEY_NAME], ${"{$name}_val"}, $params[DEF_VAL]);
355	}
356	else if ($params[GPC_TYPE] == SELECT)
357	{
358		select_get_val($params[KEY_NAME], ${"{$name}_val"}, ${"{$name}_opt"}, $params[DEF_VAL]);
359	}
360}
361
362// Get other "REQUEST" vars
363$egosearch = false;
364
365if (!$items_found)
366{
367	// For compatibility with old-style params
368	if (isset($_REQUEST['search_id']))
369	{
370		switch ($_REQUEST['search_id'])
371		{
372		case 'egosearch':
373			$egosearch = true;
374			$display_as_val = $as_topics;
375			if (empty($_REQUEST[$poster_id_key]))
376			{
377				$_REQUEST[$poster_id_key] = $user_id;
378			}
379			break;
380		case 'newposts':
381			$new_val = true;
382			break;
383		}
384	}
385
386	// Forum
387	$forum_selected = '';
388	if ($var =& $_REQUEST[$forum_key])
389	{
390		$forum_selected = get_id_ary($var);
391
392		if (!in_array($search_all, $forum_selected))
393		{
394			$forum_val = join(',', $forum_selected);
395		}
396	}
397
398	// Topic
399	if ($var =& $_REQUEST[$topic_key])
400	{
401		$topic_val = join(',', get_id_ary($var));
402	}
403
404	// Poster id (from requested name or id)
405	if ($var = request_var($poster_id_key, 0))
406	{
407		$poster_id_val = (int) $var;
408
409		if ($poster_id_val != $user_id && !get_username($poster_id_val))
410		{
411			bb_die($lang['USER_NOT_EXIST']);
412		}
413	}
414	else if ($var =& $_POST[$poster_name_key])
415	{
416		$poster_name_sql = str_replace("\\'", "''", clean_username($var));
417
418		if (!$poster_id_val = get_user_id($poster_name_sql))
419		{
420			bb_die($lang['USER_NOT_EXIST']);
421		}
422	}
423
424	// Search words
425	if ($var =& $_REQUEST[$text_match_key])
426	{
427		if ($tmp = substr(trim($var), 0, $text_match_max_len))
428		{
429			// Autocorrect wrong keyboard layout
430			$tlc             = new Text_LangCorrect();
431			$title_match_val = $tlc->parse($tlc->parse($tmp, 1), 2);
432			$text_match_sql = clean_text_match($title_match_val, $all_words_val, false, true);
433		}
434	}
435}
436
437$dl_status = array();
438if ($dl_cancel_val) $dl_status[] = DL_STATUS_CANCEL;
439if ($dl_compl_val)  $dl_status[] = DL_STATUS_COMPLETE;
440if ($dl_down_val)   $dl_status[] = DL_STATUS_DOWN;
441if ($dl_will_val)   $dl_status[] = DL_STATUS_WILL;
442$dl_status_csv = join(',', $dl_status);
443
444// Switches
445$dl_search   = ($dl_status && !IS_GUEST);
446$new_posts   = ($new_val && !IS_GUEST);
447$prev_days   = ($time_val != $search_all);
448$new_topics  = (!IS_GUEST && ($new_topics_val || isset($_GET['newposts'])));
449$my_topics   = ($poster_id_val && $my_topics_val);
450$my_posts    = ($poster_id_val && !$my_topics_val);
451$title_match = ($text_match_sql && ($title_only_val || $bb_cfg['disable_ft_search_in_posts']));
452
453// "Display as" mode (posts or topics)
454$post_mode = (!$dl_search && ($display_as_val == $as_posts || isset($_GET['search_author'])));
455
456// Start building SQL
457$SQL = DB()->get_empty_sql_array();
458
459// Displaying "as posts" mode
460if ($post_mode)
461{
462	$order    = $order_opt[$order_val]['sql'];
463	$sort     = $sort_opt[$sort_val]['sql'];
464	$per_page = $bb_cfg['posts_per_page'];
465	$display_as_val = $as_posts;
466
467	// Run initial search for post_ids
468	if (!$items_found)
469	{
470		$join_t = ($title_match || $my_topics || $new_topics || in_array($order_val, array($ord_last_p, $ord_created, $ord_name, $ord_repl)));
471		$join_s = ($text_match_sql && !$title_match);
472		$join_p = ($my_posts || $join_s);
473
474		$tbl        = ($join_t && !$join_p) ? 't' : 'p';
475		$time_field = ($join_t && !$join_p) ? 'topic_last_post_time' : 'post_time';
476
477		// SELECT
478		$SQL['SELECT'][] = ($join_t && !$join_p) ? 't.topic_first_post_id AS item_id' : 'p.post_id AS item_id';
479
480		// FROM
481		if ($join_t) $SQL['FROM'][] = $topics_tbl;
482		if ($join_p) $SQL['FROM'][] = $posts_tbl;
483
484		if (!$SQL['FROM'])
485		{
486			$join_p = true;
487			$SQL['FROM'][] = $posts_tbl;
488		}
489
490		// WHERE
491		if ($join_p && $join_t) $SQL['WHERE'][] = "t.topic_id = p.topic_id";
492
493		if ($excluded_forums_csv) $SQL['WHERE'][] = "$tbl.forum_id NOT IN($excluded_forums_csv)";
494
495		if ($forum_val)  $SQL['WHERE'][] = "$tbl.forum_id IN($forum_val)";
496		if ($topic_val)  $SQL['WHERE'][] = "$tbl.topic_id IN($topic_val)";
497		if ($new_posts)  $SQL['WHERE'][] = "$tbl.$time_field > $lastvisit";
498		if ($new_topics) $SQL['WHERE'][] = "t.topic_time > $lastvisit";
499		if ($prev_days)  $SQL['WHERE'][] = "$tbl.$time_field > ". $time_opt[$time_val]['sql'];
500		if ($my_posts)   $SQL['WHERE'][] = "p.poster_id = $poster_id_val";
501		if ($my_topics)  $SQL['WHERE'][] = "t.topic_poster = $poster_id_val";
502
503		if ($text_match_sql)
504		{
505			$search_match_topics_csv = '';
506			$title_match_topics = get_title_match_topics($text_match_sql, $forum_selected);
507
508			if (!$search_match_topics_csv = join(',', $title_match_topics))
509			{
510				bb_die($lang['NO_SEARCH_MATCH']);
511			}
512
513			$where_id = ($title_match) ? 'topic_id' : 'post_id';
514
515			$SQL['WHERE'][] = "$tbl.$where_id IN($search_match_topics_csv)";
516			prevent_huge_searches($SQL);
517		}
518
519		if (!$SQL['WHERE']) redirect(basename(__FILE__));
520
521		$SQL['GROUP BY'][] = "item_id";
522		$SQL['ORDER BY'][] = ($new_posts && $join_p) ? "p.topic_id ASC, p.post_time ASC" : "$order $sort";
523		$SQL['LIMIT'][]    = "$search_limit";
524
525		$items_display = fetch_search_ids($SQL);
526	}
527	else if (!$items_display = array_slice($items_found, $start, $per_page))
528	{
529		bb_die($lang['NO_SEARCH_MATCH']);
530	}
531
532	// Build SQL for displaying posts
533	$excluded_forums_sql = ($excluded_forums_csv) ? " AND t.forum_id NOT IN($excluded_forums_csv) " : '';
534
535	$sql = "
536		SELECT
537		  p.post_id AS item_id,
538		  t.*,
539		  p.*,
540		  h.post_html, IF(h.post_html IS NULL, pt.post_text, NULL) AS post_text,
541		  IF(p.poster_id = $anon_id, p.post_username, u.username) AS username, u.user_id, u.user_rank
542		FROM       $posts_tbl
543		INNER JOIN $topics_tbl     ON(t.topic_id = p.topic_id)
544		INNER JOIN $posts_text_tbl ON(pt.post_id = p.post_id)
545		 LEFT JOIN $posts_html_tbl ON(h.post_id = pt.post_id)
546		INNER JOIN $users_tbl      ON(u.user_id = p.poster_id)
547		WHERE
548		      p.post_id IN(". join(',', $items_display) .")
549		    $excluded_forums_sql
550		LIMIT $per_page
551	";
552
553	// Fetch posts data
554	if (!$unsorted_rows = DB()->fetch_rowset($sql))
555	{
556		bb_die($lang['NO_SEARCH_MATCH']);
557	}
558	$tmp = $sorted_rows = array();
559
560	foreach ($unsorted_rows as $row)
561	{
562		$tmp[$row['post_id']] = $row;
563	}
564	foreach ($items_display as $post_id)
565	{
566		if (empty($tmp[$post_id]))
567		{
568			continue;  // if post was deleted but still remain in search results
569		}
570		$topic_id = $tmp[$post_id]['topic_id'];
571		$sorted_rows[$topic_id][] = $tmp[$post_id];
572	}
573
574	// Output page
575	$new_tracks = array();
576
577	foreach ($sorted_rows as $topic_id => $topic_posts)
578	{
579		// Topic title block
580		$first_post  = $topic_posts[0];
581		$topic_id    = (int) $topic_id;
582		$forum_id    = (int) $first_post['forum_id'];
583		$is_unread_t = is_unread($first_post['topic_last_post_time'], $topic_id, $forum_id);
584
585		$template->assign_block_vars('t', array(
586			'FORUM_ID'    => $forum_id,
587			'FORUM_NAME'  => $forum_name_html[$forum_id],
588			'TOPIC_ID'    => $topic_id,
589			'TOPIC_TITLE' => $first_post['topic_title'],
590			'TOPIC_ICON'  => get_topic_icon($first_post, $is_unread_t),
591		));
592
593		$quote_btn = true;
594		$edit_btn = $delpost_btn = $ip_btn = (IS_AM);
595
596		// Topic posts block
597		foreach ($topic_posts as $row_num => $post)
598		{
599			$template->assign_block_vars('t.p', array(
600				'ROW_NUM'      => $row_num,
601				'POSTER_ID'    => $post['poster_id'],
602				'POSTER'       => profile_url($post),
603				'POST_ID'      => $post['post_id'],
604				'POST_DATE'    => bb_date($post['post_time'], $bb_cfg['post_date_format']),
605				'IS_UNREAD'    => is_unread($post['post_time'], $topic_id, $forum_id),
606				'MESSAGE'      => ($chars_val == $show_all) ? get_parsed_post($post, 'full') : get_parsed_post($post, 'briefly'),
607				'POSTED_AFTER' => '',
608				'QUOTE'        => $quote_btn,
609				'EDIT'         => $edit_btn,
610				'DELETE'       => $delpost_btn,
611				'IP'           => $ip_btn,
612			));
613
614			$curr_new_track_val = !empty($new_tracks[$topic_id]) ? $new_tracks[$topic_id] : 0;
615			$new_tracks[$topic_id] = max($curr_new_track_val, $post['post_time']);
616		}
617	}
618	set_tracks(COOKIE_TOPIC, $tracking_topics, $new_tracks);
619}
620// Displaying "as topics" mode
621else
622{
623	$order    = $order_opt[$order_val]['sql'];
624	$sort     = $sort_opt[$sort_val]['sql'];
625	$per_page = $bb_cfg['topics_per_page'];
626	$display_as_val = $as_topics;
627
628	// Run initial search for topic_ids
629	if (!$items_found)
630	{
631		$join_t  = ($title_match || $my_topics || $new_topics || $dl_search || $new_posts || in_array($order_val, array($ord_last_p, $ord_created, $ord_name, $ord_repl)));
632		$join_s  = ($text_match_sql && !$title_match);
633		$join_p  = ($my_posts || $join_s);
634		$join_dl = ($dl_search);
635
636		$tbl        = ($join_p && !$join_t) ? 'p' : 't';
637		$time_field = ($join_p && !$join_t) ? 'post_time' : 'topic_last_post_time';
638
639		// SELECT
640		if ($egosearch)
641		{
642			$SQL['SELECT'][] = 'p.topic_id AS item_id, MAX(p.post_time) AS max_post_time';
643		}
644		else
645		{
646			$SQL['SELECT'][] = ($join_p && !$join_t) ? 'p.topic_id AS item_id' : 't.topic_id AS item_id';
647		}
648
649		// FROM
650		if ($join_t) $SQL['FROM'][] = $topics_tbl;
651		if ($join_p) $SQL['FROM'][] = $posts_tbl;
652
653		if (!$SQL['FROM'])
654		{
655			$join_t = true;
656			$SQL['FROM'][] = $topics_tbl;
657		}
658
659		// WHERE
660		if ($join_p && $join_t) $SQL['WHERE'][] = "t.topic_id = p.topic_id";
661
662		if ($excluded_forums_csv) $SQL['WHERE'][] = "$tbl.forum_id NOT IN($excluded_forums_csv)";
663
664		if ($join_t)     $SQL['WHERE'][] = "t.topic_status != ". TOPIC_MOVED;
665		if ($forum_val)  $SQL['WHERE'][] = "$tbl.forum_id IN($forum_val)";
666		if ($topic_val)  $SQL['WHERE'][] = "$tbl.topic_id IN($topic_val)";
667		if ($new_posts)  $SQL['WHERE'][] = "$tbl.$time_field > $lastvisit";
668		if ($new_topics) $SQL['WHERE'][] = "t.topic_time > $lastvisit";
669		if ($prev_days)  $SQL['WHERE'][] = "$tbl.$time_field > ". $time_opt[$time_val]['sql'];
670		if ($my_posts)   $SQL['WHERE'][] = "p.poster_id = $poster_id_val";
671		if ($my_posts && $user->id == $poster_id_val)
672		{
673			$SQL['WHERE'][] = "p.user_post = 1";
674
675			if($userdata['user_posts'])
676			{
677				$template->assign_var('BB_DIE_APPEND_MSG', '
678					<form id="mod-action" method="POST" action="search.php">
679					    <input type="submit" name="add_my_post" value="'. $lang['RESTORE_ALL_POSTS'] .'" class="bold" onclick="if (!window.confirm( this.value +\'?\' )){ return false };" />
680					</form>
681					<br /><br />
682					<a href="index.php">'. $lang['INDEX_RETURN'] .'</a>
683				');
684			}	
685		}
686		if ($my_topics)  $SQL['WHERE'][] = "t.topic_poster = $poster_id_val";
687
688		if ($text_match_sql)
689		{
690			$search_match_topics_csv = '';
691            $title_match_topics = get_title_match_topics($text_match_sql, $forum_selected);
692
693			if (!$search_match_topics_csv = join(',', $title_match_topics))
694			{
695				bb_die($lang['NO_SEARCH_MATCH']);
696			}
697
698            $where_id = ($title_match) ? 't.topic_id' : 'p.post_id';
699
700			$SQL['WHERE'][] = "$where_id IN($search_match_topics_csv)";
701			prevent_huge_searches($SQL);
702		}
703
704		if ($join_dl) $SQL['FROM'][] = $dl_stat_tbl;
705		if ($join_dl) $SQL['WHERE'][] = "dl.topic_id = t.topic_id AND dl.user_id = $dl_user_id_val AND dl.user_status IN($dl_status_csv)";
706
707		if (!$SQL['WHERE']) redirect(basename(__FILE__));
708
709		$SQL['GROUP BY'][] = "item_id";
710		$SQL['LIMIT'][]    = "$search_limit";
711
712		if ($egosearch)
713		{
714			$SQL['ORDER BY'][] = 'max_post_time DESC';
715		}
716		else
717		{
718			$SQL['ORDER BY'][] = ($order_val == $ord_posted) ? "$tbl.$time_field $sort" : "$order $sort";
719		}
720
721		$items_display = fetch_search_ids($SQL);
722	}
723	else if (!$items_display = array_slice($items_found, $start, $per_page))
724	{
725		bb_die($lang['NO_SEARCH_MATCH']);
726	}
727
728	// Build SQL for displaying topics
729	$SQL = DB()->get_empty_sql_array();
730	$join_dl = ($bb_cfg['show_dl_status_in_search'] && !IS_GUEST);
731
732	$SQL['SELECT'][] = "
733		t.*, t.topic_poster AS first_user_id, u1.user_rank AS first_user_rank,
734		IF(t.topic_poster = $anon_id, p1.post_username, u1.username) AS first_username,
735		p2.poster_id AS last_user_id, u2.user_rank AS last_user_rank,
736		IF(p2.poster_id = $anon_id, p2.post_username, u2.username) AS last_username
737	";
738	if ($join_dl) $SQL['SELECT'][] = "dl.user_status AS dl_status";
739
740	$SQL['FROM'][]      = BB_TOPICS ." t";
741	$SQL['LEFT JOIN'][] = BB_POSTS  ." p1 ON(t.topic_first_post_id = p1.post_id)";
742	$SQL['LEFT JOIN'][] = BB_USERS  ." u1 ON(t.topic_poster = u1.user_id)";
743	$SQL['LEFT JOIN'][] = BB_POSTS  ." p2 ON(t.topic_last_post_id = p2.post_id)";
744	$SQL['LEFT JOIN'][] = BB_USERS  ." u2 ON(p2.poster_id = u2.user_id)";
745	if ($join_dl)
746	{
747		$SQL['LEFT JOIN'][] = BB_BT_DLSTATUS ." dl ON(dl.user_id = $user_id AND dl.topic_id = t.topic_id)";
748	}
749
750	$SQL['WHERE'][]	= "t.topic_id IN(". join(',', $items_display) .")";
751	if ($excluded_forums_csv)
752	{
753		$SQL['WHERE'][]	= "t.forum_id NOT IN($excluded_forums_csv)";
754	}
755
756	$SQL['LIMIT'][] = "$per_page";
757
758	// Fetch topics data
759	$topic_rows = array();
760	foreach (DB()->fetch_rowset($SQL) as $row)
761	{
762		$topic_rows[$row['topic_id']] = $row;
763	}
764	if (!$topic_rows)
765	{
766		bb_die($lang['NO_SEARCH_MATCH']);
767	}
768
769	// Output page
770	foreach ($items_display as $row_num => $item_id)
771	{
772		if (empty($topic_rows[$item_id]))
773		{
774			continue;  // if topic was deleted but still remain in search results
775		}
776		$topic     = $topic_rows[$item_id];
777		$topic_id  = $topic['topic_id'];
778		$forum_id  = $topic['forum_id'];
779		$is_unread = is_unread($topic['topic_last_post_time'], $topic_id, $forum_id);
780		$moved     = ($topic['topic_status'] == TOPIC_MOVED);
781
782		$template->assign_block_vars('t', array(
783			'ROW_NUM'       => $row_num,
784			'FORUM_ID'      => $forum_id,
785			'FORUM_NAME'    => $forum_name_html[$forum_id],
786			'TOPIC_ID'      => $topic_id,
787			'HREF_TOPIC_ID' => ($moved) ? $topic['topic_moved_id'] : $topic['topic_id'],
788			'TOPIC_TITLE'   => wbr($topic['topic_title']),
789			'IS_UNREAD'     => $is_unread,
790			'TOPIC_ICON'    => get_topic_icon($topic, $is_unread),
791			'PAGINATION'    => ($moved) ? '' : build_topic_pagination(TOPIC_URL . $topic_id, $topic['topic_replies'], $bb_cfg['posts_per_page']),
792			'REPLIES'       => $topic['topic_replies'],
793			'ATTACH'        => $topic['topic_attachment'],
794			'STATUS'        => $topic['topic_status'],
795			'TYPE'          => $topic['topic_type'],
796			'DL'            => ($topic['topic_dl_type'] == TOPIC_DL_TYPE_DL),
797			'POLL'          => $topic['topic_vote'],
798			'DL_CLASS'      => isset($topic['dl_status']) ? $dl_link_css[$topic['dl_status']] : '',
799
800			'TOPIC_AUTHOR'  => profile_url(array('username' => $topic['first_username'], 'user_id' => $topic['first_user_id'], 'user_rank' => $topic['first_user_rank'])),
801			'LAST_POSTER'   => profile_url(array('username' => $topic['last_username'], 'user_id' => $topic['last_user_id'], 'user_rank' => $topic['last_user_rank'])),
802			'LAST_POST_TIME' => bb_date($topic['topic_last_post_time']),
803			'LAST_POST_ID'  => $topic['topic_last_post_id'],
804		));
805	}
806}
807
808if ($items_display)
809{
810	$items_count = count($items_found);
811	$pages = (!$items_count) ? 1 : ceil($items_count / $per_page);
812	$url = ($search_id) ? url_arg($url, 'id', $search_id) : $url;
813
814    generate_pagination($url, $items_count, $per_page, $start);
815
816	$template->assign_vars(array(
817		'PAGE_TITLE'       => $lang['SEARCH'],
818
819		'SEARCH_MATCHES'   => ($items_count) ? sprintf($lang['FOUND_SEARCH_MATCHES'], $items_count) : '',
820		'DISPLAY_AS_POSTS' => $post_mode,
821
822		'DL_CONTROLS'      => ($dl_search && $dl_user_id_val == $user_id),
823		'DL_ACTION'        => 'dl_list.php',
824		'MY_POSTS'         => (!$post_mode && $my_posts && $user->id == $poster_id_val),
825	));
826
827	print_page('search_results.tpl');
828}
829
830redirect(basename(__FILE__));
831
832// ----------------------------------------------------------- //
833// Functions
834//
835function fetch_search_ids ($sql, $search_type = SEARCH_TYPE_POST, $redirect_to_result = UA_IE)
836{
837	global $lang, $search_id, $session_id, $items_found, $per_page;
838
839	$items_found = array();
840	foreach (DB()->fetch_rowset($sql) as $row)
841	{
842		$items_found[] = $row['item_id'];
843	}
844	if (!$items_count = count($items_found))
845	{
846		bb_die($lang['NO_SEARCH_MATCH']);
847	}
848
849	// Save results in DB
850	$search_id = make_rand_str(SEARCH_ID_LENGTH);
851	$redirect  = ($redirect_to_result && isset($_POST['submit']));
852
853	if ($items_count > $per_page || $redirect)
854	{
855		$search_array = join(',', $items_found);
856
857		$save_in_db = array(
858			'order',
859			'sort',
860			'display_as',
861			'chars',
862		);
863		if ($GLOBALS['dl_cancel_val']) $save_in_db[] = 'dl_cancel';
864		if ($GLOBALS['dl_compl_val'])  $save_in_db[] = 'dl_compl';
865		if ($GLOBALS['dl_down_val'])   $save_in_db[] = 'dl_down';
866		if ($GLOBALS['dl_will_val'])   $save_in_db[] = 'dl_will';
867
868		$curr_set = array();
869		foreach ($save_in_db as $name)
870		{
871			$curr_set[$GLOBALS["{$name}_key"]] = $GLOBALS["{$name}_val"];
872		}
873		$search_settings = DB()->escape(serialize($curr_set));
874
875		$columns =  'session_id,   search_type,   search_id,   search_time,    search_settings,    search_array';
876		$values = "'$session_id', $search_type, '$search_id', ". TIMENOW .", '$search_settings', '$search_array'";
877
878		DB()->query("REPLACE INTO ". BB_SEARCH ." ($columns) VALUES ($values)");
879	}
880
881	if ($redirect)
882	{
883		redirect("search.php?id=$search_id");
884	}
885
886	return array_slice($items_found, 0, $per_page);
887}
888
889function prevent_huge_searches ($SQL)
890{
891	global $bb_cfg;
892
893	if ($bb_cfg['limit_max_search_results'])
894	{
895		$SQL['select_options'][] = 'SQL_CALC_FOUND_ROWS';
896		$SQL['ORDER BY'] = array();
897		$SQL['LIMIT']    = array('0');
898
899		if (DB()->query($SQL) AND $row = DB()->fetch_row("SELECT FOUND_ROWS() AS rows_count"))
900		{
901			if ($row['rows_count'] > $bb_cfg['limit_max_search_results'])
902			{
903#				bb_log(str_compact(DB()->build_sql($SQL)) ." [{$row['rows_count']} rows]". LOG_LF, 'sql_huge_search');
904				bb_die('Too_many_search_results');
905			}
906		}
907### TEMP ###
908#		preg_match("#MATCH \((\w).*?\) AGAINST \('(.*?)' IN BOOLEAN MODE\)#", stripslashes($SQL['WHERE'][count($SQL['WHERE'])-1]), $m);
909#		$msg = date('m-d | H:i:s | ') . sprintf('%-18s', $GLOBALS['userdata']['username']) .' | '. sprintf('%04d', $row['rows_count']) .' | '. $m[1] .' | '. sprintf('%-40s', $m[2]) .' | ';
910#		bb_log($msg . str_compact(DB()->build_sql($SQL)) . LOG_LF, 'sql_text_search');
911### / TEMP ###
912	}
913}
914
915function username_search ($search_match)
916{
917	global $template, $lang;
918	global $gen_simple_header;
919
920	$username_list = '';
921
922	if (!empty($search_match))
923	{
924		$username_search = preg_replace('/\*/', '%', clean_username($search_match));
925
926		$sql = "
927			SELECT username
928			FROM ". BB_USERS ."
929			WHERE username LIKE '". DB()->escape($username_search) . "'
930				AND user_id <> ". GUEST_UID ."
931			ORDER BY username
932			LIMIT 200
933		";
934
935		foreach (DB()->fetch_rowset($sql) as $row)
936		{
937			$username = htmlCHR(stripslashes(html_entity_decode($row['username'])));
938			$username_list .= '<option value="'. $username .'">'. $username .'</option>';
939		}
940		if (!$username_list)
941		{
942			$username_list = '<option>'. $lang['NO_MATCH'] .'</option>';
943		}
944	}
945
946	$input_name = isset($_REQUEST['input_name']) ? htmlCHR($_REQUEST['input_name']) : 'username';
947
948	$template->assign_vars(array(
949		'TPL_SEARCH_USERNAME' => true,
950
951		'PAGE_TITLE'        => $lang['SEARCH'],
952		'USERNAME'          => !empty($search_match) ? htmlCHR(stripslashes(html_entity_decode($search_match))) : '',
953		'INPUT_NAME'        => $input_name,
954		'USERNAME_OPTIONS'  => $username_list,
955		'SEARCH_ACTION'     => "search.php?mode=searchuser&amp;input_name=$input_name",
956	));
957
958	print_page('search.tpl', 'simple');
959}