/** * Perform a thread and post search under MySQL or MySQLi * * @param array Array of search data * @return array Array of search data with results mixed in */ function perform_search_mysql($search) { global $mybb, $db, $lang; $keywords = clean_keywords($search['keywords']); if (!$keywords && !$search['author']) { error($lang->error_nosearchterms); } if ($mybb->settings['minsearchword'] < 1) { $mybb->settings['minsearchword'] = 3; } if ($keywords) { // Complex search $keywords = " {$keywords} "; if (preg_match("# and|or #", $keywords)) { $subject_lookin = " AND ("; $message_lookin = " AND ("; // Expand the string by double quotes $keywords_exp = explode("\"", $keywords); $inquote = false; foreach ($keywords_exp as $phrase) { // If we're not in a double quoted section if (!$inquote) { // Expand out based on search operators (and, or) $matches = preg_split("#\\s{1,}(and|or)\\s{1,}#", $phrase, -1, PREG_SPLIT_DELIM_CAPTURE); $count_matches = count($matches); for ($i = 0; $i < $count_matches; ++$i) { $word = trim($matches[$i]); if (empty($word)) { continue; } // If this word is a search operator set the boolean if ($i % 2 && ($word == "and" || $word == "or")) { $boolean = $word; } else { $word = trim($word); // Word is too short - show error message if (my_strlen($word) < $mybb->settings['minsearchword']) { $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); error($lang->error_minsearchlength); } // Add terms to search query $subject_lookin .= " {$boolean} LOWER(t.subject) LIKE '%{$word}%'"; if ($search['postthread'] == 1) { $message_lookin .= " {$boolean} LOWER(p.message) LIKE '%{$word}%'"; } } } } else { $phrase = str_replace(array("+", "-", "*"), '', trim($phrase)); if (my_strlen($phrase) < $mybb->settings['minsearchword']) { $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); error($lang->error_minsearchlength); } // Add phrase to search query $subject_lookin .= " {$boolean} LOWER(t.subject) LIKE '%{$phrase}%'"; if ($search['postthread'] == 1) { $message_lookin .= " {$boolean} LOWER(p.message) LIKE '%{$phrase}%'"; } } $inquote = !$inquote; } $subject_lookin .= ")"; $message_lookin .= ")"; } else { $keywords = str_replace("\"", '', trim($keywords)); if (my_strlen($keywords) < $mybb->settings['minsearchword']) { $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); error($lang->error_minsearchlength); } $subject_lookin = " AND LOWER(t.subject) LIKE '%{$keywords}%'"; if ($search['postthread'] == 1) { $message_lookin = " AND LOWER(p.message) LIKE '%{$keywords}%'"; } } } $post_usersql = ''; $thread_usersql = ''; if ($search['author']) { $userids = array(); if ($search['matchusername']) { $query = $db->simple_select("users", "uid", "username='******'author']) . "'"); } else { $search['author'] = my_strtolower($search['author']); $query = $db->simple_select("users", "uid", "LOWER(username) LIKE '%" . $db->escape_string_like($db->escape_string($search['author'])) . "%'"); } while ($user = $db->fetch_array($query)) { $userids[] = $user['uid']; } if (count($userids) < 1) { error($lang->error_nosearchresults); } else { $userids = implode(',', $userids); $post_usersql = " AND p.uid IN (" . $userids . ")"; $thread_usersql = " AND t.uid IN (" . $userids . ")"; } } $datecut = ''; if ($search['postdate']) { if ($search['pddir'] == 0) { $datecut = "<="; } else { $datecut = ">="; } $now = TIME_NOW; $datelimit = $now - 86400 * $search['postdate']; $datecut .= "'{$datelimit}'"; $post_datecut = " AND p.dateline {$datecut}"; $thread_datecut = " AND t.dateline {$datecut}"; } $thread_replycut = ''; if ($search['numreplies'] != '' && $search['findthreadst']) { if (intval($search['findthreadst']) == 1) { $thread_replycut = " AND t.replies >= '" . intval($search['numreplies']) . "'"; } else { $thread_replycut = " AND t.replies <= '" . intval($search['numreplies']) . "'"; } } $forumin = ''; $fidlist = array(); $searchin = array(); if ($search['forums'] != "all") { if (!is_array($search['forums'])) { $search['forums'] = array(intval($search['forums'])); } foreach ($search['forums'] as $forum) { if (!$searchin[$forum]) { $forum = intval($forum); switch ($db->type) { case "pgsql": $query = $db->query("\n\t\t\t\t\t\t\tSELECT DISTINCT f.fid \n\t\t\t\t\t\t\tFROM " . TABLE_PREFIX . "forums f \n\t\t\t\t\t\t\tLEFT JOIN " . TABLE_PREFIX . "forumpermissions p ON (f.fid=p.fid AND p.gid='" . $mybb->user['usergroup'] . "')\n\t\t\t\t\t\t\tWHERE (','||parentlist||',' LIKE ',%{$forum}%,') = true AND active!=0 AND (p.fid IS NULL OR p.cansearch=1)\n\t\t\t\t\t\t"); break; case "sqlite3": case "sqlite2": $query = $db->query("\n\t\t\t\t\t\t\tSELECT DISTINCT f.fid \n\t\t\t\t\t\t\tFROM " . TABLE_PREFIX . "forums f \n\t\t\t\t\t\t\tLEFT JOIN " . TABLE_PREFIX . "forumpermissions p ON (f.fid=p.fid AND p.gid='" . $mybb->user['usergroup'] . "')\n\t\t\t\t\t\t\tWHERE (','||parentlist||',' LIKE ',%{$forum}%,') > 0 AND active!=0 AND (p.fid = NULL OR p.cansearch=1)\n\t\t\t\t\t\t"); break; default: $query = $db->query("\n\t\t\t\t\t\t\tSELECT DISTINCT f.fid \n\t\t\t\t\t\t\tFROM " . TABLE_PREFIX . "forums f \n\t\t\t\t\t\t\tLEFT JOIN " . TABLE_PREFIX . "forumpermissions p ON (f.fid=p.fid AND p.gid='" . $mybb->user['usergroup'] . "')\n\t\t\t\t\t\t\tWHERE INSTR(CONCAT(',',parentlist,','),',{$forum},') > 0 AND active!=0 AND (ISNULL(p.fid) OR p.cansearch=1)\n\t\t\t\t\t\t"); } while ($sforum = $db->fetch_array($query)) { $fidlist[] = $sforum['fid']; } } } if (count($fidlist) == 1) { $forumin .= " AND t.fid='{$forum}' "; $searchin[$fid] = 1; } else { if (count($fidlist) > 1) { $forumin = " AND t.fid IN (" . implode(',', $fidlist) . ")"; } } } $unsearchforums = get_unsearchable_forums(); if ($unsearchforums) { $permsql = " AND t.fid NOT IN ({$unsearchforums})"; } $inactiveforums = get_inactive_forums(); if ($inactiveforums) { $permsql .= " AND t.fid NOT IN ({$inactiveforums})"; } // Searching a specific thread? if ($search['tid']) { $tidsql = " AND t.tid='" . intval($search['tid']) . "'"; } $limitsql = ''; if (intval($mybb->settings['searchhardlimit']) > 0) { $limitsql = "LIMIT " . intval($mybb->settings['searchhardlimit']); } // Searching both posts and thread titles $threads = array(); $posts = array(); $firstposts = array(); if ($search['postthread'] == 1) { // No need to search subjects when looking for results within a specific thread if (!$search['tid']) { $query = $db->query("\n\t\t\t\tSELECT t.tid, t.firstpost\n\t\t\t\tFROM " . TABLE_PREFIX . "threads t\n\t\t\t\tWHERE 1=1 {$thread_datecut} {$thread_replycut} {$forumin} {$thread_usersql} {$permsql} AND t.visible >= '0' AND t.closed NOT LIKE 'moved|%' {$subject_lookin}\n\t\t\t\t{$limitsql}\n\t\t\t"); while ($thread = $db->fetch_array($query)) { $threads[$thread['tid']] = $thread['tid']; if ($thread['firstpost']) { $posts[$thread['tid']] = $thread['firstpost']; } } } $query = $db->query("\n\t\t\tSELECT p.pid, p.tid\n\t\t\tFROM " . TABLE_PREFIX . "posts p\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "threads t ON (t.tid=p.tid)\n\t\t\tWHERE 1=1 {$post_datecut} {$thread_replycut} {$forumin} {$post_usersql} {$permsql} {$tidsql} AND p.visible >= '0' AND t.visible >= '0' AND t.closed NOT LIKE 'moved|%' {$message_lookin}\n\t\t\t{$limitsql}\n\t\t"); while ($post = $db->fetch_array($query)) { $posts[$post['pid']] = $post['pid']; $threads[$post['tid']] = $post['tid']; } if (count($posts) < 1 && count($threads) < 1) { error($lang->error_nosearchresults); } $threads = implode(',', $threads); $posts = implode(',', $posts); } else { $query = $db->query("\n\t\t\tSELECT t.tid, t.firstpost\n\t\t\tFROM " . TABLE_PREFIX . "threads t\n\t\t\tWHERE 1=1 {$thread_datecut} {$thread_replycut} {$forumin} {$thread_usersql} {$permsql} AND t.visible >= '0' {$subject_lookin}\n\t\t\t{$limitsql}\n\t\t"); while ($thread = $db->fetch_array($query)) { $threads[$thread['tid']] = $thread['tid']; if ($thread['firstpost']) { $firstposts[$thread['tid']] = $thread['firstpost']; } } if (count($threads) < 1) { error($lang->error_nosearchresults); } $threads = implode(',', $threads); $firstposts = implode(',', $firstposts); if ($firstposts) { $query = $db->simple_select("posts", "pid", "pid IN ({$firstposts}) AND visible >= '0' {$limitsql}"); while ($post = $db->fetch_array($query)) { $posts[$post['pid']] = $post['pid']; } $posts = implode(',', $posts); } } return array("threads" => $threads, "posts" => $posts, "querycache" => ''); }
/** * Perform a thread and post search under MySQL or MySQLi * * @param array Array of search data * @return array Array of search data with results mixed in */ function perform_search_mysql($search) { global $mybb, $db, $lang, $cache; $keywords = clean_keywords($search['keywords']); if (!$keywords && !$search['author']) { error($lang->error_nosearchterms); } if ($mybb->settings['minsearchword'] < 1) { $mybb->settings['minsearchword'] = 3; } if ($keywords) { // Complex search $keywords = " {$keywords} "; if (preg_match("#\\s(and|or)\\s#", $keywords)) { $subject_lookin = " AND ("; $message_lookin = " AND ("; // Expand the string by double quotes $keywords_exp = explode("\"", $keywords); $inquote = false; $boolean = ''; foreach ($keywords_exp as $phrase) { // If we're not in a double quoted section if (!$inquote) { // Expand out based on search operators (and, or) $matches = preg_split("#\\s{1,}(and|or)\\s{1,}#", $phrase, -1, PREG_SPLIT_DELIM_CAPTURE); $count_matches = count($matches); for ($i = 0; $i < $count_matches; ++$i) { $word = trim($matches[$i]); if (empty($word)) { continue; } // If this word is a search operator set the boolean if ($i % 2 && ($word == "and" || $word == "or")) { if ($i <= 1 && $subject_lookin == " AND (") { continue; } $boolean = $word; } else { $word = trim($word); // Word is too short - show error message if (my_strlen($word) < $mybb->settings['minsearchword']) { $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); error($lang->error_minsearchlength); } // Add terms to search query $subject_lookin .= " {$boolean} LOWER(t.subject) LIKE '%{$word}%'"; if ($search['postthread'] == 1) { $message_lookin .= " {$boolean} LOWER(p.message) LIKE '%{$word}%'"; } $boolean = 'AND'; } } } else { $phrase = str_replace(array("+", "-", "*"), '', trim($phrase)); if (my_strlen($phrase) < $mybb->settings['minsearchword']) { $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); error($lang->error_minsearchlength); } // Add phrase to search query $subject_lookin .= " {$boolean} LOWER(t.subject) LIKE '%{$phrase}%'"; if ($search['postthread'] == 1) { $message_lookin .= " {$boolean} LOWER(p.message) LIKE '%{$phrase}%'"; } $boolean = 'AND'; } if ($subject_lookin == " AND (") { // There are no search keywords to look for $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); error($lang->error_minsearchlength); } $inquote = !$inquote; } $subject_lookin .= ")"; $message_lookin .= ")"; } else { $keywords = str_replace("\"", '', trim($keywords)); if (my_strlen($keywords) < $mybb->settings['minsearchword']) { $lang->error_minsearchlength = $lang->sprintf($lang->error_minsearchlength, $mybb->settings['minsearchword']); error($lang->error_minsearchlength); } $subject_lookin = " AND LOWER(t.subject) LIKE '%{$keywords}%'"; if ($search['postthread'] == 1) { $message_lookin = " AND LOWER(p.message) LIKE '%{$keywords}%'"; } } } $post_usersql = ''; $thread_usersql = ''; if ($search['author']) { $userids = array(); if ($search['matchusername']) { $query = $db->simple_select("users", "uid", "username='******'author']) . "'"); } else { $search['author'] = my_strtolower($search['author']); $query = $db->simple_select("users", "uid", "LOWER(username) LIKE '%" . $db->escape_string_like($search['author']) . "%'"); } while ($user = $db->fetch_array($query)) { $userids[] = $user['uid']; } if (count($userids) < 1) { error($lang->error_nosearchresults); } else { $userids = implode(',', $userids); $post_usersql = " AND p.uid IN (" . $userids . ")"; $thread_usersql = " AND t.uid IN (" . $userids . ")"; } } $datecut = ''; if ($search['postdate']) { if ($search['pddir'] == 0) { $datecut = "<="; } else { $datecut = ">="; } $now = TIME_NOW; $datelimit = $now - 86400 * $search['postdate']; $datecut .= "'{$datelimit}'"; $post_datecut = " AND p.dateline {$datecut}"; $thread_datecut = " AND t.dateline {$datecut}"; } $thread_replycut = ''; if ($search['numreplies'] != '' && $search['findthreadst']) { if (intval($search['findthreadst']) == 1) { $thread_replycut = " AND t.replies >= '" . intval($search['numreplies']) . "'"; } else { $thread_replycut = " AND t.replies <= '" . intval($search['numreplies']) . "'"; } } $thread_prefixcut = ''; $prefixlist = array(); if ($search['threadprefix'] && $search['threadprefix'][0] != 'any') { foreach ($search['threadprefix'] as $threadprefix) { $threadprefix = intval($threadprefix); $prefixlist[] = $threadprefix; } } if (count($prefixlist) == 1) { $thread_prefixcut .= " AND t.prefix='{$threadprefix}' "; } else { if (count($prefixlist) > 1) { $thread_prefixcut = " AND t.prefix IN (" . implode(',', $prefixlist) . ")"; } } $forumin = ''; $fidlist = array(); $searchin = array(); if ($search['forums'][0] != "all") { if (!is_array($search['forums'])) { $search['forums'] = array(intval($search['forums'])); } // Generate a comma separated list of all groups the user belongs to $user_groups = $mybb->user['usergroup']; if ($mybb->user['additionalgroups']) { $user_groups .= "," . $mybb->user['additionalgroups']; // Setup some quick permissions for us $fcache = $cache->read("forumpermissions"); $add_groups = explode(",", $mybb->user['additionalgroups']); } foreach ($search['forums'] as $forum) { $forum = intval($forum); if (!$searchin[$forum]) { if (is_array($add_groups)) { $can_search = 0; foreach ($add_groups as $add_group) { // Check to make sure that we have sufficient permissions to search this forum if (!is_array($fcache[$forum][$add_group]) || $fcache[$forum][$add_group]['cansearch'] == 1 || $mybb->usergroup['cansearch'] == 1) { $can_search = 1; } } if ($can_search == 0) { // We can't search this forum... continue; } } switch ($db->type) { case "pgsql": $query = $db->simple_select("forums", "DISTINCT fid", "(','||parentlist||',' LIKE ',%{$forum}%,') = true AND active != 0"); break; case "sqlite": $query = $db->simple_select("forums", "DISTINCT fid", "(','||parentlist||',' LIKE ',%{$forum}%,') > 0 AND active != 0"); break; default: $query = $db->simple_select("forums", "DISTINCT fid", "INSTR(CONCAT(',',parentlist,','),',{$forum},') > 0 AND active != 0"); } while ($sforum = $db->fetch_array($query)) { $fidlist[] = $sforum['fid']; } } } if (count($fidlist) == 1) { $forumin .= " AND t.fid='{$forum}' "; $searchin[$fid] = 1; } else { if (count($fidlist) > 1) { $forumin = " AND t.fid IN (" . implode(',', $fidlist) . ")"; } } } $permsql = ""; $onlyusfids = array(); // Check group permissions if we can't view threads not started by us if ($group_permissions = forum_permissions()) { foreach ($group_permissions as $fid => $forum_permissions) { if ($forum_permissions['canonlyviewownthreads'] == 1) { $onlyusfids[] = $fid; } } } if (!empty($onlyusfids)) { $permsql .= "AND ((t.fid IN(" . implode(',', $onlyusfids) . ") AND t.uid='{$mybb->user['uid']}') OR t.fid NOT IN(" . implode(',', $onlyusfids) . "))"; } $unsearchforums = get_unsearchable_forums(); if ($unsearchforums) { $permsql .= " AND t.fid NOT IN ({$unsearchforums})"; } $inactiveforums = get_inactive_forums(); if ($inactiveforums) { $permsql .= " AND t.fid NOT IN ({$inactiveforums})"; } $visiblesql = $post_visiblesql = $plain_post_visiblesql = ""; if (isset($search['visible'])) { if ($search['visible'] == 1) { $visiblesql = " AND t.visible = '1'"; if ($search['postthread'] == 1) { $post_visiblesql = " AND p.visible = '1'"; $plain_post_visiblesql = " AND visible = '1'"; } } else { $visiblesql = " AND t.visible != '1'"; if ($search['postthread'] == 1) { $post_visiblesql = " AND p.visible != '1'"; $plain_post_visiblesql = " AND visible != '1'"; } } } // Searching a specific thread? if ($search['tid']) { $tidsql = " AND t.tid='" . intval($search['tid']) . "'"; } $limitsql = ''; if (intval($mybb->settings['searchhardlimit']) > 0) { $limitsql = "LIMIT " . intval($mybb->settings['searchhardlimit']); } // Searching both posts and thread titles $threads = array(); $posts = array(); $firstposts = array(); if ($search['postthread'] == 1) { // No need to search subjects when looking for results within a specific thread if (!$search['tid']) { $query = $db->query("\n\t\t\t\tSELECT t.tid, t.firstpost\n\t\t\t\tFROM " . TABLE_PREFIX . "threads t\n\t\t\t\tWHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} AND t.closed NOT LIKE 'moved|%' {$subject_lookin}\n\t\t\t\t{$limitsql}\n\t\t\t"); while ($thread = $db->fetch_array($query)) { $threads[$thread['tid']] = $thread['tid']; if ($thread['firstpost']) { $posts[$thread['tid']] = $thread['firstpost']; } } } $query = $db->query("\n\t\t\tSELECT p.pid, p.tid\n\t\t\tFROM " . TABLE_PREFIX . "posts p\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "threads t ON (t.tid=p.tid)\n\t\t\tWHERE 1=1 {$post_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$post_usersql} {$permsql} {$tidsql} {$visiblesql} {$post_visiblesql} AND t.closed NOT LIKE 'moved|%' {$message_lookin}\n\t\t\t{$limitsql}\n\t\t"); while ($post = $db->fetch_array($query)) { $posts[$post['pid']] = $post['pid']; $threads[$post['tid']] = $post['tid']; } if (count($posts) < 1 && count($threads) < 1) { error($lang->error_nosearchresults); } $threads = implode(',', $threads); $posts = implode(',', $posts); } else { $query = $db->query("\n\t\t\tSELECT t.tid, t.firstpost\n\t\t\tFROM " . TABLE_PREFIX . "threads t\n\t\t\tWHERE 1=1 {$thread_datecut} {$thread_replycut} {$thread_prefixcut} {$forumin} {$thread_usersql} {$permsql} {$visiblesql} {$subject_lookin}\n\t\t\t{$limitsql}\n\t\t"); while ($thread = $db->fetch_array($query)) { $threads[$thread['tid']] = $thread['tid']; if ($thread['firstpost']) { $firstposts[$thread['tid']] = $thread['firstpost']; } } if (count($threads) < 1) { error($lang->error_nosearchresults); } $threads = implode(',', $threads); $firstposts = implode(',', $firstposts); if ($firstposts) { $query = $db->simple_select("posts", "pid", "pid IN ({$firstposts}) {$plain_post_visiblesql} {$limitsql}"); while ($post = $db->fetch_array($query)) { $posts[$post['pid']] = $post['pid']; } $posts = implode(',', $posts); } } return array("threads" => $threads, "posts" => $posts, "querycache" => ''); }