search_forum.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. <?php
  2. /**
  3. * [Discuz!] (C)2001-2099 Comsenz Inc.
  4. * This is NOT a freeware, use is subject to license terms
  5. *
  6. * $Id: search_forum.php 33198 2013-05-06 09:23:45Z jeffjzhang $
  7. */
  8. if(!defined('IN_DISCUZ')) {
  9. exit('Access Denied');
  10. }
  11. define('NOROBOT', TRUE);
  12. if(!$_G['setting']['search']['forum']['status']) {
  13. showmessage('search_forum_closed');
  14. }
  15. if(!$_G['adminid'] && !($_G['group']['allowsearch'] & 2)) {
  16. showmessage('group_nopermission', NULL, array('grouptitle' => $_G['group']['grouptitle']), array('login' => 1));
  17. }
  18. $_G['setting']['search']['forum']['searchctrl'] = intval($_G['setting']['search']['forum']['searchctrl']);
  19. require_once libfile('function/forumlist');
  20. require_once libfile('function/forum');
  21. require_once libfile('function/post');
  22. loadcache(array('forums', 'posttable_info'));
  23. $posttableselect = '';
  24. if(!empty($_G['cache']['posttable_info']) && is_array($_G['cache']['posttable_info'])) {
  25. $posttableselect = '<select name="seltableid" id="seltableid" class="ps" style="display:none">';
  26. foreach($_G['cache']['posttable_info'] as $posttableid => $data) {
  27. $posttableselect .= '<option value="'.$posttableid.'"'.($_GET['posttableid'] == $posttableid ? ' selected="selected"' : '').'>'.($data['memo'] ? $data['memo'] : 'post_'.$posttableid).'</option>';
  28. }
  29. $posttableselect .= '</select>';
  30. }
  31. $srchmod = 2;
  32. $cachelife_time = 300; // Life span for cache of searching in specified range of time
  33. $cachelife_text = 3600; // Life span for cache of text searching
  34. $srchtype = empty($_GET['srchtype']) ? '' : trim($_GET['srchtype']);
  35. $searchid = isset($_GET['searchid']) ? intval($_GET['searchid']) : 0;
  36. $seltableid = intval($_GET['seltableid']);
  37. if($srchtype != 'title' && $srchtype != 'fulltext') {
  38. $srchtype = '';
  39. }
  40. $srchtxt = trim($_GET['srchtxt']);
  41. $srchuid = intval($_GET['srchuid']);
  42. $srchuname = isset($_GET['srchuname']) ? trim(str_replace('|', '', $_GET['srchuname'])) : '';;
  43. $srchfrom = intval($_GET['srchfrom']);
  44. $before = intval($_GET['before']);
  45. $srchfid = $_GET['srchfid'];
  46. $srhfid = intval($_GET['srhfid']);
  47. $keyword = isset($srchtxt) ? dhtmlspecialchars(trim($srchtxt)) : '';
  48. $forumselect = forumselect();
  49. if(!empty($srchfid) && !is_numeric($srchfid)) {
  50. $forumselect = str_replace('<option value="'.$srchfid.'">', '<option value="'.$srchfid.'" selected="selected">', $forumselect);
  51. }
  52. $mySearchData = $_G['setting']['my_search_data'];
  53. if($mySearchData['status'] && !$srchfrom && !$searchid) {
  54. if (!$_G['setting']['my_siteid']) {
  55. dheader('Location: index.php');
  56. }
  57. $appService = Cloud::loadClass('Service_App');
  58. if($appService->getCloudAppStatus('search') && $searchparams) {
  59. $source = 'discuz';
  60. $cloudSource = array('collectionsearch', 'hotsearch');
  61. if(!empty($_GET['srhlocality'])) {
  62. $sourcetype = explode('::', $_GET['srhlocality']);
  63. if($sourcetype[0] == 'forum') {
  64. $source = $sourcetype[1] == 'index' ? 'forum' : ($sourcetype[1] == 'forumdisplay' ? 'forum_forum' : 'forum_thread');
  65. } elseif($sourcetype[0] == 'portal') {
  66. $source = $sourcetype[1] == 'view' ? 'article' : ($sourcetype[1] == 'list' ? 'portal_list': 'portal');
  67. } elseif($sourcetype[0] == 'group') {
  68. $source = $sourcetype[1] == 'viewthread' ? 'group_thread' : ($sourcetype[1] == 'group' ? 'group_forum' : 'group');
  69. } elseif($sourcetype[0] == 'home') {
  70. $source = 'home'.(empty($sourcetype[1]) ? '' : '_'.$sourcetype[1]);
  71. } elseif($sourcetype[0] == 'misc' && $sourcetype[1] == 'ranklist') {
  72. $source = 'toplist';
  73. }
  74. } elseif(in_array($_GET['source'], $cloudSource)) {
  75. $source = $_GET['source'];
  76. }
  77. $params = array();
  78. $params['source'] = $source;
  79. $params['q'] = $keyword;
  80. $params['module'] = 'forum';
  81. if($srhfid) {
  82. $params['fId'] = $srhfid;
  83. }
  84. if($_GET['adv']) {
  85. $params['isAdv'] = 1;
  86. }
  87. if(!empty($_GET['author'])) {
  88. $params['author']=$_GET['author'];
  89. }
  90. if(!empty($_GET['scope'])) {
  91. $params['scope']=$_GET['scope'];
  92. }
  93. if(!empty($_GET['orderField'])) {
  94. $params['orderField']=$_GET['orderField'];
  95. }
  96. $searchparams['params'] = array_merge($searchparams['params'], $params);
  97. $utilService = Cloud::loadClass('Service_Util');
  98. $url = $searchparams['url'] . '?' . $utilService->httpBuildQuery($searchparams['params'], '', '&');
  99. $utilService->redirect($url);
  100. die;
  101. }
  102. }
  103. if(!submitcheck('searchsubmit', 1)) {
  104. if($_GET['adv']) {
  105. include template('search/forum_adv');
  106. } else {
  107. include template('search/forum');
  108. }
  109. } else {
  110. $orderby = in_array($_GET['orderby'], array('dateline', 'replies', 'views')) ? $_GET['orderby'] : 'lastpost';
  111. $ascdesc = isset($_GET['ascdesc']) && $_GET['ascdesc'] == 'asc' ? 'asc' : 'desc';
  112. if(!empty($searchid)) {
  113. require_once libfile('function/misc');
  114. $page = max(1, intval($_GET['page']));
  115. $start_limit = ($page - 1) * $_G['tpp'];
  116. $index = C::t('common_searchindex')->fetch_by_searchid_srchmod($searchid, $srchmod);
  117. if(!$index) {
  118. showmessage('search_id_invalid');
  119. }
  120. $keyword = dhtmlspecialchars($index['keywords']);
  121. $keyword = $keyword != '' ? str_replace('+', ' ', $keyword) : '';
  122. $index['keywords'] = rawurlencode($index['keywords']);
  123. $searchstring = explode('|', $index['searchstring']);
  124. $index['searchtype'] = $searchstring[0];//preg_replace("/^([a-z]+)\|.*/", "\\1", $index['searchstring']);
  125. $searchstring[2] = base64_decode($searchstring[2]);
  126. $srchuname = $searchstring[3];
  127. $modfid = 0;
  128. if($keyword) {
  129. $modkeyword = str_replace(' ', ',', $keyword);
  130. $fids = explode(',', str_replace('\'', '', $searchstring[5]));
  131. if(count($fids) == 1 && in_array($_G['adminid'], array(1,2,3))) {
  132. $modfid = $fids[0];
  133. if($_G['adminid'] == 3 && !C::t('forum_moderator')->fetch_uid_by_fid_uid($modfid, $_G['uid'])) {
  134. $modfid = 0;
  135. }
  136. }
  137. }
  138. $threadlist = $posttables = array();
  139. foreach(C::t('forum_thread')->fetch_all_by_tid_fid_displayorder(explode(',',$index['ids']), null, 0, $orderby, $start_limit, $_G['tpp'], '>=', $ascdesc) as $thread) {
  140. $thread['subject'] = bat_highlight($thread['subject'], $keyword);
  141. $thread['realtid'] = $thread['isgroup'] == 1 ? $thread['closed'] : $thread['tid'];
  142. $threadlist[$thread['tid']] = procthread($thread, 'dt');
  143. $posttables[$thread['posttableid']][] = $thread['tid'];
  144. }
  145. if($threadlist) {
  146. foreach($posttables as $tableid => $tids) {
  147. foreach(C::t('forum_post')->fetch_all_by_tid($tableid, $tids, true, '', 0, 0, 1) as $post) {
  148. $threadlist[$post['tid']]['message'] = bat_highlight(messagecutstr($post['message'], 200), $keyword);
  149. }
  150. }
  151. }
  152. $multipage = multi($index['num'], $_G['tpp'], $page, "search.php?mod=forum&searchid=$searchid&orderby=$orderby&ascdesc=$ascdesc&searchsubmit=yes");
  153. $url_forward = 'search.php?mod=forum&'.$_SERVER['QUERY_STRING'];
  154. $fulltextchecked = $searchstring[1] == 'fulltext' ? 'checked="checked"' : '';
  155. include template('search/forum');
  156. } else {
  157. if($_G['group']['allowsearch'] & 32 && $srchtype == 'fulltext') {
  158. periodscheck('searchbanperiods');
  159. } elseif($srchtype != 'title') {
  160. $srchtype = 'title';
  161. }
  162. $forumsarray = array();
  163. if(!empty($srchfid)) {
  164. foreach((is_array($srchfid) ? $srchfid : explode('_', $srchfid)) as $forum) {
  165. if($forum = intval(trim($forum))) {
  166. $forumsarray[] = $forum;
  167. }
  168. }
  169. }
  170. $fids = $comma = '';
  171. foreach($_G['cache']['forums'] as $fid => $forum) {
  172. if($forum['type'] != 'group' && (!$forum['viewperm'] && $_G['group']['readaccess']) || ($forum['viewperm'] && forumperm($forum['viewperm']))) {
  173. if(!$forumsarray || in_array($fid, $forumsarray)) {
  174. $fids .= "$comma'$fid'";
  175. $comma = ',';
  176. }
  177. }
  178. }
  179. if($_G['setting']['threadplugins'] && $specialplugin) {
  180. $specialpluginstr = implode("','", $specialplugin);
  181. $special[] = 127;
  182. } else {
  183. $specialpluginstr = '';
  184. }
  185. $special = $_GET['special'];
  186. $specials = $special ? implode(',', $special) : '';
  187. $srchfilter = in_array($_GET['srchfilter'], array('all', 'digest', 'top')) ? $_GET['srchfilter'] : 'all';
  188. $searchstring = 'forum|'.$srchtype.'|'.base64_encode($srchtxt).'|'.intval($srchuid).'|'.$srchuname.'|'.addslashes($fids).'|'.intval($srchfrom).'|'.intval($before).'|'.$srchfilter.'|'.$specials.'|'.$specialpluginstr.'|'.$seltableid;
  189. $searchindex = array('id' => 0, 'dateline' => '0');
  190. foreach(C::t('common_searchindex')->fetch_all_search($_G['setting']['search']['forum']['searchctrl'], $_G['clientip'], $_G['uid'], $_G['timestamp'], $searchstring, $srchmod) as $index) {
  191. if($index['indexvalid'] && $index['dateline'] > $searchindex['dateline']) {
  192. $searchindex = array('id' => $index['searchid'], 'dateline' => $index['dateline']);
  193. break;
  194. } elseif($_G['adminid'] != '1' && $index['flood']) {
  195. showmessage('search_ctrl', 'search.php?mod=forum', array('searchctrl' => $_G['setting']['search']['forum']['searchctrl']));
  196. }
  197. }
  198. if($searchindex['id']) {
  199. $searchid = $searchindex['id'];
  200. } else {
  201. !($_G['group']['exempt'] & 2) && checklowerlimit('search');
  202. if(!$srchtxt && !$srchuid && !$srchuname && !$srchfrom && !in_array($srchfilter, array('digest', 'top')) && !is_array($special)) {
  203. dheader('Location: search.php?mod=forum');
  204. } elseif(isset($srchfid) && !empty($srchfid) && $srchfid != 'all' && !(is_array($srchfid) && in_array('all', $srchfid)) && empty($forumsarray)) {
  205. showmessage('search_forum_invalid', 'search.php?mod=forum');
  206. } elseif(!$fids) {
  207. showmessage('group_nopermission', NULL, array('grouptitle' => $_G['group']['grouptitle']), array('login' => 1));
  208. }
  209. if($_G['adminid'] != '1' && $_G['setting']['search']['forum']['maxspm']) {
  210. if(C::t('common_searchindex')->count_by_dateline($_G['timestamp'], $srchmod) >= $_G['setting']['search']['forum']['maxspm']) {
  211. showmessage('search_toomany', 'search.php?mod=forum', array('maxspm' => $_G['setting']['search']['forum']['maxspm']));
  212. }
  213. }
  214. if($srchtype == 'fulltext' && $_G['setting']['sphinxon']) {
  215. require_once libfile('class/sphinx');
  216. $s = new SphinxClient();
  217. $s->setServer($_G['setting']['sphinxhost'], intval($_G['setting']['sphinxport']));
  218. $s->setMaxQueryTime(intval($_G['setting']['sphinxmaxquerytime']));
  219. $s->SetRankingMode($_G['setting']['sphinxrank']);
  220. $s->setLimits(0, intval($_G['setting']['sphinxlimit']), intval($_G['setting']['sphinxlimit']));
  221. $s->setGroupBy('tid', SPH_GROUPBY_ATTR);
  222. if($srchfilter == 'digest') {
  223. $s->setFilterRange('digest', 1, 3, false);
  224. }
  225. if($srchfilter == 'top') {
  226. $s->setFilterRange('displayorder', 1, 2, false);
  227. } else {
  228. $s->setFilterRange('displayorder', 0, 2, false);
  229. }
  230. if(!empty($srchfrom) && empty($srchtxt) && empty($srchuid) && empty($srchuname)) {
  231. $expiration = TIMESTAMP + $cachelife_time;
  232. $keywords = '';
  233. if($before) {
  234. $spx_timemix = 0;
  235. $spx_timemax = TIMESTAMP - $srchfrom;
  236. } else {
  237. $spx_timemix = TIMESTAMP - $srchfrom;
  238. $spx_timemax = TIMESTAMP;
  239. }
  240. } else {
  241. $uids = array();
  242. if($srchuname) {
  243. $uids = array_keys(C::t('common_member')->fetch_all_by_like_username($srchuname, 0, 50));
  244. if(count($uids) == 0) {
  245. $uids = array(0);
  246. }
  247. } elseif($srchuid) {
  248. $uids = array($srchuid);
  249. }
  250. if(is_array($uids) && count($uids) > 0) {
  251. $s->setFilter('authorid', $uids, false);
  252. }
  253. if($srchtxt) {
  254. if(preg_match("/\".*\"/", $srchtxt)) {
  255. $spx_matchmode = "PHRASE";
  256. $s->setMatchMode(SPH_MATCH_PHRASE);
  257. } elseif(preg_match("(AND|\+|&|\s)", $srchtxt) && !preg_match("(OR|\|)", $srchtxt)) {
  258. $srchtxt = preg_replace("/( AND |&| )/is", "+", $srchtxt);
  259. $spx_matchmode = "ALL";
  260. $s->setMatchMode(SPH_MATCH_ALL);
  261. } else {
  262. $srchtxt = preg_replace("/( OR |\|)/is", "+", $srchtxt);
  263. $spx_matchmode = 'ANY';
  264. $s->setMatchMode(SPH_MATCH_ANY);
  265. }
  266. $srchtxt = str_replace('*', '%', addcslashes($srchtxt, '%_'));
  267. foreach(explode('+', $srchtxt) as $text) {
  268. $text = trim(daddslashes($text));
  269. if($text) {
  270. $sqltxtsrch .= $andor;
  271. $sqltxtsrch .= $srchtype == 'fulltext' ? "(p.message LIKE '%".str_replace('_', '\_', $text)."%' OR p.subject LIKE '%$text%')" : "t.subject LIKE '%$text%'";
  272. }
  273. }
  274. $sqlsrch .= " AND ($sqltxtsrch)";
  275. }
  276. if(!empty($srchfrom)) {
  277. if($before) {
  278. $spx_timemix = 0;
  279. $spx_timemax = TIMESTAMP - $srchfrom;
  280. } else {
  281. $spx_timemix = TIMESTAMP - $srchfrom;
  282. $spx_timemax = TIMESTAMP;
  283. }
  284. $s->setFilterRange('lastpost', $spx_timemix, $spx_timemax, false);
  285. }
  286. if(!empty($specials)) {
  287. $s->setFilter('special', explode(",", $special), false);
  288. }
  289. $keywords = str_replace('%', '+', $srchtxt).(trim($srchuname) ? '+'.str_replace('%', '+', $srchuname) : '');
  290. $expiration = TIMESTAMP + $cachelife_text;
  291. }
  292. if($srchtype == "fulltext") {
  293. $result = $s->query("'".$srchtxt."'", $_G['setting']['sphinxmsgindex']);
  294. } else {
  295. $result = $s->query($srchtxt, $_G['setting']['sphinxsubindex']);
  296. }
  297. $tids = array();
  298. if($result) {
  299. if(is_array($result['matches'])) {
  300. foreach($result['matches'] as $value) {
  301. if($value['attrs']['tid']) {
  302. $tids[$value['attrs']['tid']] = $value['attrs']['tid'];
  303. }
  304. }
  305. }
  306. }
  307. if(count($tids) == 0) {
  308. $ids = 0;
  309. $num = 0;
  310. } else {
  311. $ids = implode(",", $tids);
  312. $num = $result['total_found'];
  313. }
  314. } else {
  315. $digestltd = $srchfilter == 'digest' ? "t.digest>'0' AND" : '';
  316. $topltd = $srchfilter == 'top' ? "AND t.displayorder>'0'" : "AND t.displayorder>='0'";
  317. if(!empty($srchfrom) && empty($srchtxt) && empty($srchuid) && empty($srchuname)) {
  318. $searchfrom = $before ? '<=' : '>=';
  319. $searchfrom .= TIMESTAMP - $srchfrom;
  320. $sqlsrch = "FROM ".DB::table('forum_thread')." t WHERE $digestltd t.fid IN ($fids) $topltd AND t.lastpost$searchfrom";
  321. $expiration = TIMESTAMP + $cachelife_time;
  322. $keywords = '';
  323. } else {
  324. $sqlsrch = $srchtype == 'fulltext' ?
  325. "FROM ".DB::table(getposttable($seltableid))." p, ".DB::table('forum_thread')." t WHERE $digestltd t.fid IN ($fids) $topltd AND p.tid=t.tid AND p.invisible='0'" :
  326. "FROM ".DB::table('forum_thread')." t WHERE $digestltd t.fid IN ($fids) $topltd";
  327. if($srchuname) {
  328. $srchuid = array_keys(C::t('common_member')->fetch_all_by_like_username($srchuname, 0, 50));
  329. if(!$srchuid) {
  330. $sqlsrch .= ' AND 0';
  331. }
  332. }/* elseif($srchuid) {
  333. $srchuid = "'$srchuid'";
  334. }*/
  335. if($srchtxt) {
  336. $srcharr = $srchtype == 'fulltext' ? searchkey($keyword, "(p.message LIKE '%{text}%' OR p.subject LIKE '%{text}%')", true) : searchkey($keyword,"t.subject LIKE '%{text}%'", true);
  337. $srchtxt = $srcharr[0];
  338. $sqlsrch .= $srcharr[1];
  339. }
  340. if($srchuid) {
  341. $sqlsrch .= ' AND '.($srchtype == 'fulltext' ? 'p' : 't').'.authorid IN ('.dimplode((array)$srchuid).')';
  342. }
  343. if(!empty($srchfrom)) {
  344. $searchfrom = ($before ? '<=' : '>=').(TIMESTAMP - $srchfrom);
  345. $sqlsrch .= " AND t.lastpost$searchfrom";
  346. }
  347. if(!empty($specials)) {
  348. $sqlsrch .= " AND special IN (".dimplode($special).")";
  349. }
  350. $keywords = str_replace('%', '+', $srchtxt);
  351. $expiration = TIMESTAMP + $cachelife_text;
  352. }
  353. $num = $ids = 0;
  354. $_G['setting']['search']['forum']['maxsearchresults'] = $_G['setting']['search']['forum']['maxsearchresults'] ? intval($_G['setting']['search']['forum']['maxsearchresults']) : 500;
  355. $query = DB::query("SELECT ".($srchtype == 'fulltext' ? 'DISTINCT' : '')." t.tid, t.closed, t.author, t.authorid $sqlsrch ORDER BY tid DESC LIMIT ".$_G['setting']['search']['forum']['maxsearchresults']);
  356. while($thread = DB::fetch($query)) {
  357. $ids .= ','.$thread['tid'];
  358. $num++;
  359. }
  360. DB::free_result($query);
  361. }
  362. $searchid = C::t('common_searchindex')->insert(array(
  363. 'srchmod' => $srchmod,
  364. 'keywords' => $keywords,
  365. 'searchstring' => $searchstring,
  366. 'useip' => $_G['clientip'],
  367. 'uid' => $_G['uid'],
  368. 'dateline' => $_G['timestamp'],
  369. 'expiration' => $expiration,
  370. 'num' => $num,
  371. 'ids' => $ids
  372. ), true);
  373. !($_G['group']['exempt'] & 2) && updatecreditbyaction('search');
  374. }
  375. dheader("location: search.php?mod=forum&searchid=$searchid&orderby=$orderby&ascdesc=$ascdesc&searchsubmit=yes&kw=".urlencode($keyword));
  376. }
  377. }
  378. ?>