$scripturl . '?action=search', 'name' => $txt[182] ); $context['compact'] = true; // Create an array for the permissions. $boards_can = array( 'post_reply_own' => boardsAllowedTo('post_reply_own'), 'post_reply_any' => boardsAllowedTo('post_reply_any'), 'mark_any_notify' => boardsAllowedTo('mark_any_notify') ); require_once($sourcedir . '/Display.php'); include('/var/www/rock/forum/sphinx/sphinxapi.php'); if (isset ($_GET['start'])) { $start = intval ($_GET['start']); if ($start < 0) $start=0; } else { $start = 0; } $cl = new SphinxClient(); $cl->SetServer( "localhost", 9312 ); $cl->SetMatchMode( SPH_MATCH_EXTENDED2 ); $cl->SetLimits($start, intval ($modSettings['search_results_per_page'])); $cl->SetArrayResult( true ); $q = $cl->EscapeString ($_GET['search']); $result = $cl->Query( "@(subject) $q", 'topics ' ); $msgs = array(); $subjects = array(); $bodies = array(); $context['messages'] = array(); $context['topics'] = array(); if (! empty ($result['matches'])) { foreach ($result['matches'] as $doc) { $context['messages'][] = $doc['id']; //$doc['attrs']['id_msg']; $context['topics'][$doc['id']]['id'] = $doc['attrs']['id_topic']; } $messages_request = db_query("SELECT m.*, b.name as bName FROM smf_messages m, smf_boards b WHERE m.ID_BOARD=b.ID_BOARD AND ID_MSG IN(".implode(',', $context['messages']).")", __FILE__, __LINE__); } $context['key_words'] = array_keys($result['words']); // Now that we know how many results to expect we can start calculating the page numbers. $context['page_index'] = constructPageIndex($scripturl . '?action=qsearch;search=' . urlencode($_GET['search']), $_REQUEST['start'], (int) $result['total_found'], $modSettings['search_results_per_page'], false); // Set the basic stuff for the template. $context['allow_hide_email'] = !empty($modSettings['allow_hideEmail']); $context['sub_template'] = 'results'; $context['page_title'] = $txt[166]; $context['get_topics'] = 'prepareSearchContext'; $context['can_send_pm'] = allowedTo('pm_send'); loadJumpTo(); } // Ask the user what they want to search for. function PlushSearch1() { global $txt, $scripturl, $db_prefix, $modSettings, $user_info, $context; loadTemplate('Newsearch'); // Check the user's permissions. isAllowedTo('search_posts'); // Link tree.... $context['linktree'][] = array( 'url' => $scripturl . '?action=search', 'name' => $txt[182] ); // If you got back from search2 by using the linktree, you get your original search parameters back. if (isset($_REQUEST['params'])) { $temp_params = explode('|"|', base64_decode($_REQUEST['params'])); $context['search_params'] = array(); foreach ($temp_params as $i => $data) { list ($k, $v) = explode('|\'|', $data); $context['search_params'][$k] = stripslashes($v); } if (isset($context['search_params']['brd'])) $context['search_params']['brd'] = $context['search_params']['brd'] == '' ? array() : explode(',', $context['search_params']['brd']); } if (isset($context['search_params']['search'])) $context['search_params']['search'] = htmlspecialchars($context['search_params']['search']); if (isset($context['search_params']['userspec'])) $context['search_params']['userspec'] = htmlspecialchars(stripslashes($context['search_params']['userspec'])); // Find all the boards this user is allowed to see. $request = db_query(" SELECT b.ID_CAT, c.name AS catName, b.ID_BOARD, b.name, b.childLevel FROM {$db_prefix}boards AS b LEFT JOIN {$db_prefix}categories AS c ON (c.ID_CAT = b.ID_CAT) WHERE $user_info[query_see_board] ORDER BY c.catOrder, b.boardOrder", __FILE__, __LINE__); $context['num_boards'] = mysql_num_rows($request); $context['categories'] = array(); while ($row = mysql_fetch_assoc($request)) { // This category hasn't been set up yet.. if (!isset($context['categories'][$row['ID_CAT']])) $context['categories'][$row['ID_CAT']] = array( 'id' => $row['ID_CAT'], 'name' => $row['catName'], 'boards' => array() ); // Set this board up, and let the template know when it's a child. (indent them..) $context['categories'][$row['ID_CAT']]['boards'][$row['ID_BOARD']] = array( 'id' => $row['ID_BOARD'], 'name' => $row['name'], 'child_level' => $row['childLevel'] ); } mysql_free_result($request); // Simple or not? $context['simple_search'] = !empty($modSettings['simpleSearch']) && !isset($_GET['advanced']); $context['page_title'] = $txt[183]; } // Gather the results and show them. function PlushSearch2() { global $modSettings, $sourcedir; global $scripturl, $txt, $db_prefix, $user_info, $context, $messages_request, $attachments, $boards_can; loadTemplate('Newsearch'); // Are you allowed? isAllowedTo('search_posts'); // So, we're allowed here, let's clean up the start variable - just incase. $_REQUEST['start'] = (int) $_REQUEST['start']; require_once($sourcedir . '/Display.php'); // $search_params will carry all settings that differ from the default search parameters. // That way, the URLs involved in a search page will be kept as short as possible. $search_params = array(); if (isset($_REQUEST['params'])) { $temp_params = explode('|"|', base64_decode($_REQUEST['params'])); foreach ($temp_params as $i => $data) { list ($k, $v) = explode('|\'|', $data); $search_params[$k] = stripslashes($v); } if (isset($search_params['brd'])) $search_params['brd'] = $search_params['brd'] == '' ? array() : explode(',', $search_params['brd']); } else { $search_params['subject_only'] = true; } // 1 => 'allwords' (default, don't set as param) / 2 => 'anywords'. if (!empty($search_params['searchtype']) || (!empty($_REQUEST['searchtype']) && $_REQUEST['searchtype'] == 2)) $search_params['searchtype'] = 2; // Minimum age of messages. Default to zero (don't set param in that case). if (!empty($search_params['minage']) || (!empty($_REQUEST['minage']) && $_REQUEST['minage'] > 0)) $search_params['minage'] = !empty($search_params['minage']) ? (int) $search_params['minage'] : (int) $_REQUEST['minage']; // Maximum age of messages. Default to infinite (9999 days: param not set). if (!empty($search_params['maxage']) || (!empty($_REQUEST['maxage']) && $_REQUEST['maxage'] != 9999)) $search_params['maxage'] = !empty($search_params['maxage']) ? (int) $search_params['maxage'] : (int) $_REQUEST['maxage']; $timeAddition = ''; $timeAddition .= !empty($search_params['minage']) ? ' AND m.posterTime <= ' . (time() - $search_params['minage'] * 86400) : ''; $timeAddition .= !empty($search_params['maxage']) ? ' AND m.posterTime >= ' . (time() - $search_params['maxage'] * 86400) : ''; // Default the user name to a wildcard matching every user (*). if (!empty($search_params['user_spec']) || (!empty($_REQUEST['userspec']) && $_REQUEST['userspec'] != '*')) $search_params['userspec'] = isset($search_params['userspec']) ? $search_params['userspec'] : $_REQUEST['userspec']; // If there's no specific user, then don't mention it in the main query. if (empty($search_params['userspec'])) $userQuery = ''; else { $userString = strtolower(addslashes(strtr($search_params['userspec'], array('%' => '\%', '_' => '\_', '*' => '%', '?' => '_')))); // Retrieve a list of possible members. $request = db_query(" SELECT ID_MEMBER FROM {$db_prefix}members WHERE realName LIKE '$userString'", __FILE__, __LINE__); // Simply do nothing if there're too many members matching the criteria. if (mysql_num_rows($request) > $maxMembersToSearch) $userQuery = ''; elseif (mysql_num_rows($request) == 0) $userQuery = "m.ID_MEMBER = 0 AND m.posterName LIKE '$userString'"; else { $memberlist = array(); while ($row = mysql_fetch_assoc($request)) $memberlist[] = $row['ID_MEMBER']; $userQuery = "(m.ID_MEMBER IN (" . implode(', ', $memberlist) . ") OR (m.ID_MEMBER = 0 AND m.posterName LIKE '$userString'))"; } } // If the boards were passed by URL (params=), temporarily put them back in $_REQUEST. if (!empty($search_params['brd']) && is_array($search_params['brd'])) $_REQUEST['brd'] = $search_params['brd']; // Make sure all boards are integers. if (!empty($_REQUEST['brd'])) foreach ($_REQUEST['brd'] as $id => $brd) $_REQUEST['brd'][$id] = (int) $brd; // Select all boards you've selected AND are allowed to see. if ($user_info['is_admin']) $search_params['brd'] = empty($_REQUEST['brd']) ? array() : $_REQUEST['brd']; else { $request = db_query(" SELECT b.ID_BOARD FROM {$db_prefix}boards AS b WHERE $user_info[query_see_board]" . (empty($_REQUEST['brd']) ? '' : " AND b.ID_BOARD IN (" . implode(', ', $_REQUEST['brd']) . ")"), __FILE__, __LINE__); $search_params['brd'] = array(); while ($row = mysql_fetch_assoc($request)) $search_params['brd'][] = $row['ID_BOARD']; mysql_free_result($request); // This error should pro'bly only happen for hackers. if (empty($search_params['brd'])) fatal_lang_error('search_no_boards'); } $search_params['show_complete'] = !empty($search_params['show_complete']) || !empty($_REQUEST['show_complete']); $search_params['subject_only'] = !empty($search_params['subject_only']) || !empty($_REQUEST['subject_only']); $context['compact'] = !$search_params['show_complete']; // What are we searching for? $search_params['search'] = !empty($search_params['search']) ? $search_params['search'] : (isset($_REQUEST['search']) ? stripslashes($_REQUEST['search']) : ''); // Nothing?? if (!isset($search_params['search']) || $search_params['search'] == '') fatal_lang_error('no_valid_search_string', false); ////////////////////////////////////////////////////////////////////////////////////////// // That's all, I guess. Following is some weird stuff used by previous search ////////////////////////////////////////////////////////////////////////////////////////// //if (0) { // игнорируем это пока // Extract phrase parts first (e.g. some words "this is a phrase" some more words.) preg_match_all('/(?:^|\s)"([^"]+)"(?:$|\s)/', $search_params['search'], $matches, PREG_PATTERN_ORDER); $searchArray = $matches[1]; // Remove the phrase parts and extract the words. $searchArray = array_merge($searchArray, explode(' ', preg_replace('/(?:^|\s)"([^"]+)"(?:$|\s)/', ' ', $search_params['search']))); // Trim everything and make sure there are no words that are the same. foreach ($searchArray as $index => $value) { $searchArray[$index] = addslashes(strtolower(trim($value))); if (!isset($searchArray[$index]) || $searchArray[$index] == '') unset($searchArray[$index]); } $searchArray = array_slice(array_unique($searchArray), 0, 10); if (empty($searchArray)) fatal_lang_error('no_valid_search_string', false); // Each word is matched against the body and the subject. $searchParts = array(); foreach ($searchArray as $word) { if (empty($modSettings['search_match_complete_words'])) $searchParts[] = " LIKE '%" . strtr($word, array('_' => '\\_', '%' => '\\%')) . "%'"; else $searchParts[] = " RLIKE '[[:<:]]" . addcslashes(preg_replace(array('/([\[\]$.+?|{}])/', '/\*/'), array('[$1]', '.+'), $word), '') . "[[:>:]]'"; } $searchQuery = 0; // Either all words must match (searchtype == 1) or any of the words (searchtype == 2). if (empty($search_params['searchtype'])) { // искать по содержимому сообщений if (!$search_params['subject_only']) $searchQuery = 'm.body' . implode(' AND m.body', $searchParts) . $timeAddition; // только по темам $topicQuery = 'm.subject' . implode(' AND m.subject', $searchParts) . $timeAddition; } else { if (!$search_params['subject_only']) $searchQuery = (count($searchParts) > 1 ? '(' : '') . 'm.body' . implode(' OR m.body', $searchParts) . (count($searchParts) > 1 ? ')' : '') . $timeAddition; $topicQuery = (count($searchParts) > 1 ? '(' : '') . 'm.subject' . implode(' OR m.subject', $searchParts) . (count($searchParts) > 1 ? ')' : '') . $timeAddition; } // Get the sorting parameters right. Default to sort by relevance descending. $sort_columns = array( 'relevance', 'numReplies', 'ID_MSG', ); if (empty($search_params['sort']) && !empty($_REQUEST['sort'])) list ($search_params['sort'], $search_params['sort_dir']) = array_pad(explode('|', $_REQUEST['sort']), 2, ''); $search_params['sort'] = !empty($search_params['sort']) && in_array($search_params['sort'], $sort_columns) ? $search_params['sort'] : 'relevance'; $search_params['sort_dir'] = !empty($search_params['sort_dir']) && $search_params['sort_dir'] == 'asc' ? 'asc' : 'desc'; $context['mark'] = array(); # foreach ($searchArray as $word) # $context['mark'][$word] = '' . $word . ''; // All search params have been checked, let's compile them to a single string... made less simple by PHP 4.3.9 and below. $temp_params = $search_params; if (isset($temp_params['brd'])) $temp_params['brd'] = implode(',', $temp_params['brd']); $context['params'] = array(); foreach ($temp_params as $k => $v) $context['params'][] = $k . '|\'|' . addslashes($v); $context['params'] = base64_encode(implode('|"|', $context['params'])); // ... and add the links to the link tree. $context['linktree'][] = array( 'url' => $scripturl . '?action=search;params=' . $context['params'], 'name' => $txt[182] ); $context['linktree'][] = array( 'url' => $scripturl . '?action=search2;params=' . $context['params'], 'name' => $txt['search_results'] ); // Create an array for the permissions. $boards_can = array( 'post_reply_own' => boardsAllowedTo('post_reply_own'), 'post_reply_any' => boardsAllowedTo('post_reply_any'), 'mark_any_notify' => boardsAllowedTo('mark_any_notify') ); include('/var/www/rock/forum/sphinx/sphinxapi.php'); $cl = new SphinxClient(); $cl->SetServer( "localhost", 9312 ); $cl->SetMatchMode( SPH_MATCH_EXTENDED ); $cl->SetSortMode( SPH_SORT_RELEVANCE ); //$cl->SetGroupBy ( "ID_TOPIC", SPH_GROUPBY_ATTR, '@weight DESC'); # $cl->SetFieldWeights(array('subject'=>10, 'body'=>1)); # $cl->SetSelect( 'ID_MSG as id_msg'); $cl->SetLimits($_REQUEST[start], intval($modSettings['search_results_per_page'])); $cl->SetFilter( 'id_board', $search_params['brd'] ); $cl->SetArrayResult( true ); $q = $cl->EscapeString ($search_params['search']); $result = $cl->Query( "@(subject) $q @(body) $q", 'posts_main posts_delta ' ); $context['messages'] = array(); $context['topics'] = array(); foreach ($result['matches'] as $doc) { $context['messages'][] = $doc['id']; //$doc['attrs']['id_msg']; $context['topics'][$doc['id']]['id'] = $doc['attrs']['id_topic']; } $messages_request = db_query("SELECT m.*, b.name as bName FROM smf_messages m, smf_boards b WHERE m.ID_BOARD=b.ID_BOARD AND ID_MSG IN(".implode(',', $context['messages']).")", __FILE__, __LINE__); $context['key_words'] = &$searchArray; // Set the basic stuff for the template. $context['allow_hide_email'] = !empty($modSettings['allow_hideEmail']); $context['sub_template'] = 'results'; $context['page_title'] = $txt[166]; $context['get_topics'] = 'prepareSearchContext'; $context['can_send_pm'] = allowedTo('pm_send'); loadJumpTo(); } // Callback to return messages - saves memory. function prepareSearchContext($reset = false) { global $txt, $modSettings, $scripturl, $ID_MEMBER; global $themeUser, $context, $messages_request, $db_prefix, $attachments, $boards_can; // Remember which message this is. (ie. reply #83) static $counter = null; if ($counter == null || $reset) $counter = $_REQUEST['start'] + 1; // If the query returned false, bail. if ($messages_request == false) return false; // Start from the beginning... if ($reset) return @mysql_data_seek($messages_request, 0); // Attempt to get the next message. $message = mysql_fetch_assoc($messages_request); if (!$message) return false; // Can't have an empty subject can we? $message['subject'] = $message['subject'] != '' ? $message['subject'] : $txt[24]; $message['first_subject'] = $message['first_subject'] != '' ? $message['first_subject'] : $txt[24]; // If it couldn't load, or the user was a guest.... someday may be done with a guest table. if (!loadMemberContext($message['ID_MEMBER'])) { // Notice this information isn't used anywhere else.... *cough guest table cough* $themeUser[$message['ID_MEMBER']]['name'] = $message['posterName']; $themeUser[$message['ID_MEMBER']]['id'] = 0; $themeUser[$message['ID_MEMBER']]['group'] = $txt[28]; $themeUser[$message['ID_MEMBER']]['link'] = $message['posterName']; $themeUser[$message['ID_MEMBER']]['email'] = $message['posterEmail']; } $themeUser[$message['ID_MEMBER']]['ip'] = $message['posterIP']; // Do the censor thang... censorText($message['body']); censorText($message['subject']); censorText($message['first_subject']); // Shorten this message if necessary. if ($context['compact']) { // Set the number of characters before and after the searched keyword. $charLimit = 40; $message['body'] = strtr($message['body'], array("\n" => ' ', '
' => "\n")); $message['body'] = doUBBC($message['body'], $message['smileysEnabled']); $message['body'] = strip_tags($message['body']); if (strlen($message['body']) > $charLimit) { if (empty($context['key_words'])) $message['body'] = htmlspecialchars(mb_substr(un_htmlspecialchars($message['body']), 0, $charLimit) . (mb_strlen($message['body']) > $charLimit ? '...' : ''), ENT_QUOTES); else { $matchString = ''; foreach ($context['key_words'] as $keyword) $matchString .= strtr(preg_quote($keyword, '/'), array('\*' => '.+?')) . '|'; $matchString = mb_substr($matchString, 0, -1); $message['body'] = un_htmlspecialchars(str_replace(' ', ' ', $message['body'])); if (empty($modSettings['search_match_complete_words'])) preg_match_all('/([^\s\W]{' . $charLimit . '}[\s\W]|[\s\W].{0,' . $charLimit . '}?|^)(' . $matchString . ')(.{0,' . $charLimit . '}[\s\W]|[^\s\W]{' . $charLimit . '})/isu', $message['body'], $matches); else preg_match_all('/([^\s\W]{' . $charLimit . '}[\s\W]|[\s\W].{0,' . $charLimit . '}?[\s\W]|^)(' . $matchString . ')([\s\W].{0,' . $charLimit . '}[\s\W]|[\s\W][^\s\W]{' . $charLimit . '})/isu', $message['body'], $matches); $message['body'] = ''; foreach ($matches[0] as $index => $match) { if ($index > 2) break; $message['body'] .= '... ' . htmlspecialchars($match, ENT_QUOTES) . ' ...
'; } } } } else { // Run UBBC interpreter on the message. $message['body'] = doUBBC($message['body'], $message['smileysEnabled']); } /// костыль! $message['last_posterTime'] = $message['posterTime']; $message['first_posterTime'] = $message['posterTime']; $output = array_merge($context['topics'][$message['ID_MSG']], array( 'is_sticky' => !empty($modSettings['enableStickyTopics']) && !empty($message['isSticky']), 'is_locked' => !empty($message['locked']), 'is_poll' => $modSettings['pollMode'] == '1' && $message['ID_POLL'] > 0, 'is_hot' => $message['numReplies'] >= $modSettings['hotTopicPosts'], 'is_very_hot' => $message['numReplies'] >= $modSettings['hotTopicVeryPosts'], 'views' => $message['numViews'], 'replies' => $message['numReplies'], 'can_reply' => in_array($message['ID_BOARD'], $boards_can['post_reply_any']) || in_array(0, $boards_can['post_reply_any']), 'can_mark_notify' => in_array($message['ID_BOARD'], $boards_can['mark_any_notify']) || in_array(0, $boards_can['mark_any_notify']), 'first_post' => array( 'id' => $message['first_msg'], 'time' => timeformat($message['first_posterTime']), 'subject' => $message['subject'], 'href' => $scripturl . '?topic=' . $message['ID_TOPIC'] . '.0', 'link' => '' . $message['subject'] . '', 'icon' => $message['icon'], 'member' => array( 'id' => $message['first_member_id'], 'name' => $message['first_member_name'], 'href' => !empty($message['first_member_id']) ? $scripturl . '?action=profile;u=' . $message['first_member_id'] : '', 'link' => !empty($message['first_member_id']) ? '' . $message['first_member_name'] . '' : $message['first_member_name'] ) ), 'last_post' => array( 'id' => $message['last_msg'], 'time' => timeformat($message['last_posterTime']), 'timestamp' => $message['last_posterTime'], 'member' => array( 'id' => $message['last_member_id'], 'name' => $message['last_member_name'], 'href' => !empty($message['last_member_id']) ? $scripturl . '?action=profile;u=' . $message['last_member_id'] : '', 'link' => !empty($message['last_member_id']) ? '' . $message['last_member_name'] . '' : $message['last_member_name'] ) ), 'board' => array( 'id' => $message['ID_BOARD'], 'name' => $message['bName'], 'href' => $scripturl . '?board=' . $message['ID_BOARD'] . '.0', 'link' => '' . $message['bName'] . '' ), 'category' => array( 'id' => $message['ID_CAT'], 'name' => $message['cName'], 'href' => $scripturl . '#' . $message['ID_CAT'], 'link' => '' . $message['cName'] . '' ) )); determineTopicClass($output); $body_highlighted = $message['body']; $subject_highlighted = $message['subject']; foreach ($context['key_words'] as $query) { // Fix the international characters in the keyword too. # $query = preg_replace('~&#(\d{4,5}|[3-9]\d{2,4}|2[6-9]\d);~', '&#$1;', strtr(preg_quote($query, '/'), array('&' => '&'))); $body_highlighted = preg_replace('/((<[^>]*)|' . $query . ')/ieu', "'\$2' == '\$1' ? stripslashes('\$1') : '\$1'", $body_highlighted); $subject_highlighted = preg_replace('/((<[^>]*)|' . $query . ')/ie', "'$2' == '$1' ? stripslashes('$1') : '$1'", $subject_highlighted); } $output['matches'][] = array( 'id' => $message['ID_MSG'], 'attachment' => loadAttachmentContext($message['ID_MSG']), 'alternate' => $counter % 2, 'member' => &$themeUser[$message['ID_MEMBER']], 'icon' => $message['icon'], 'subject' => $message['subject'], 'subject_highlighted' => $subject_highlighted, 'time' => timeformat($message['posterTime']), 'timestamp' => $message['posterTime'], 'counter' => $counter, 'modified' => array( 'time' => timeformat($message['modifiedTime']), 'timestamp' => $message['modifiedTime'], 'name' => $message['modifiedName'] ), 'body' => $message['body'], 'body_highlighted' => $body_highlighted, 'start' => 'msg' . $message['ID_MSG'] ); $counter++; return $output; } ?>