home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 April / PCWorld_2005-04_cd.bin / akce / web / phpnuke / PHP-Nuke-7.5.exe / html / includes / functions_search.php < prev    next >
PHP Script  |  2004-07-22  |  24KB  |  538 lines

  1. <?php
  2. /***************************************************************************
  3. *                              functions_search.php
  4. *                              -------------------
  5. *     begin                : Wed Sep 05 2001
  6. *     copyright            : (C) 2002 The phpBB Group
  7. *     email                : support@phpbb.com
  8. *
  9. *     $Id: functions_search.php,v 1.8.2.17 2003/08/23 01:16:13 psotfx Exp $
  10. *
  11. ****************************************************************************/
  12. /***************************************************************************
  13. * phpbb2 forums port version 2.0.5 (c) 2003 - Nuke Cops (http://nukecops.com)
  14. *
  15. * Ported by Nuke Cops to phpbb2 standalone 2.0.5 Test
  16. * and debugging completed by the Elite Nukers and site members.
  17. *
  18. * You run this package at your sole risk. Nuke Cops and affiliates cannot
  19. * be held liable if anything goes wrong. You are advised to test this
  20. * package on a development system. Backup everything before implementing
  21. * in a production environment. If something goes wrong, you can always
  22. * backout and restore your backups.
  23. *
  24. * Installing and running this also means you agree to the terms of the AUP
  25. * found at Nuke Cops.
  26. *
  27. * This is version 2.0.5 of the phpbb2 forum port for PHP-Nuke. Work is based
  28. * on Tom Nitzschner's forum port version 2.0.6. Tom's 2.0.6 port was based
  29. * on the phpbb2 standalone version 2.0.3. Our version 2.0.5 from Nuke Cops is
  30. * now reflecting phpbb2 standalone 2.0.5 that fixes some bugs and the
  31. * invalid_session error message.
  32. ***************************************************************************/
  33. /***************************************************************************
  34.  *   This file is part of the phpBB2 port to Nuke 6.0 (c) copyright 2002
  35.  *   by Tom Nitzschner (tom@toms-home.com)
  36.  *   http://bbtonuke.sourceforge.net (or http://www.toms-home.com)
  37.  *
  38.  *   As always, make a backup before messing with anything. All code
  39.  *   release by me is considered sample code only. It may be fully
  40.  *   functual, but you use it at your own risk, if you break it,
  41.  *   you get to fix it too. No waranty is given or implied.
  42.  *
  43.  *   Please post all questions/request about this port on http://bbtonuke.sourceforge.net first,
  44.  *   then on my site. All original header code and copyright messages will be maintained
  45.  *   to give credit where credit is due. If you modify this, the only requirement is
  46.  *   that you also maintain all original copyright messages. All my work is released
  47.  *   under the GNU GENERAL PUBLIC LICENSE. Please see the README for more information.
  48.  *
  49.  ***************************************************************************/
  50.  
  51. /***************************************************************************
  52.  *
  53.  *   This program is free software; you can redistribute it and/or modify
  54.  *   it under the terms of the GNU General Public License as published by
  55.  *   the Free Software Foundation; either version 2 of the License, or
  56.  *   (at your option) any later version.
  57.  *
  58.  ***************************************************************************/
  59.  
  60. if (!defined('IN_PHPBB')) {
  61.     die();
  62. }
  63.  
  64. function clean_words($mode, &$entry, &$stopword_list, &$synonym_list)
  65. {
  66.         static $drop_char_match =   array('^', '$', '&', '(', ')', '<', '>', '`', '\'', '"', '|', ',', '@', '_', '?', '%', '-', '~', '+', '.', '[', ']', '{', '}', ':', '\\', '/', '=', '#', '\'', ';', '!');
  67.         static $drop_char_replace = array(' ', ' ', ' ', ' ', ' ', ' ', ' ', '',  '',   ' ', ' ', ' ', ' ', '',  ' ', ' ', '',  ' ',  ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' , ' ', ' ', ' ', ' ',  ' ', ' ');
  68.  
  69.         $entry = ' ' . strip_tags(strtolower($entry)) . ' ';
  70.  
  71.         if ( $mode == 'post' )
  72.         {
  73.                 // Replace line endings by a space
  74.                 $entry = preg_replace('/[\n\r]/is', ' ', $entry);
  75.                 // HTML entities like  
  76.                 $entry = preg_replace('/\b&[a-z]+;\b/', ' ', $entry);
  77.                 // Remove URL's
  78.                 $entry = preg_replace('/\b[a-z0-9]+:\/\/[a-z0-9\.\-]+(\/[a-z0-9\?\.%_\-\+=&\/]+)?/', ' ', $entry);
  79.                 // Quickly remove BBcode.
  80.                 $entry = preg_replace('/\[img:[a-z0-9]{10,}\].*?\[\/img:[a-z0-9]{10,}\]/', ' ', $entry);
  81.                 $entry = preg_replace('/\[\/?url(=.*?)?\]/', ' ', $entry);
  82.                 $entry = preg_replace('/\[\/?[a-z\*=\+\-]+(\:?[0-9a-z]+)?:[a-z0-9]{10,}(\:[a-z0-9]+)?=?.*?\]/', ' ', $entry);
  83.         }
  84.         else if ( $mode == 'search' )
  85.         {
  86.                 $entry = str_replace(' +', ' and ', $entry);
  87.                 $entry = str_replace(' -', ' not ', $entry);
  88.         }
  89.  
  90.         //
  91.         // Filter out strange characters like ^, $, &, change "it's" to "its"
  92.         //
  93.         for($i = 0; $i < count($drop_char_match); $i++)
  94.         {
  95.                 $entry =  str_replace($drop_char_match[$i], $drop_char_replace[$i], $entry);
  96.         }
  97.  
  98.         if ( $mode == 'post' )
  99.         {
  100.                 $entry = str_replace('*', ' ', $entry);
  101.  
  102.                 // 'words' that consist of <3 or >20 characters are removed.
  103.         $entry = preg_replace('/[ ]([\S]{1,2}|[\S]{21,})[ ]/',' ', $entry);
  104.         }
  105.  
  106.         if ( !empty($stopword_list) )
  107.         {
  108.                 for ($j = 0; $j < count($stopword_list); $j++)
  109.                 {
  110.                         $stopword = trim($stopword_list[$j]);
  111.  
  112.                         if ( $mode == 'post' || ( $stopword != 'not' && $stopword != 'and' && $stopword != 'or' ) )
  113.                         {
  114.                                 $entry = str_replace(' ' . trim($stopword) . ' ', ' ', $entry);
  115.                         }
  116.                 }
  117.         }
  118.  
  119.         if ( !empty($synonym_list) )
  120.         {
  121.                 for ($j = 0; $j < count($synonym_list); $j++)
  122.                 {
  123.                         list($replace_synonym, $match_synonym) = split(' ', trim(strtolower($synonym_list[$j])));
  124.                         if ( $mode == 'post' || ( $match_synonym != 'not' && $match_synonym != 'and' && $match_synonym != 'or' ) )
  125.                         {
  126.                                 $entry =  str_replace(' ' . trim($match_synonym) . ' ', ' ' . trim($replace_synonym) . ' ', $entry);
  127.                         }
  128.                 }
  129.         }
  130.  
  131.         return $entry;
  132. }
  133.  
  134. function split_words(&$entry, $mode = 'post')
  135. {
  136.         // If you experience problems with the new method, uncomment this block.
  137. /*
  138.         $rex = ( $mode == 'post' ) ? "/\b([\w▒╡- ][\w▒╡- ']*[\w▒╡- ]+|[\w▒╡- ]+?)\b/" : '/(\*?[a-z0-9▒╡- ]+\*?)|\b([a-z0-9▒╡- ]+)\b/';
  139.         preg_match_all($rex, $entry, $split_entries);
  140.  
  141.         return $split_entries[1];
  142. */
  143.     // Trim 1+ spaces to one space and split this trimmed string into words.
  144.     return explode(' ', trim(preg_replace('#\s+#', ' ', $entry)));
  145. }
  146.  
  147. function add_search_words($mode, $post_id, $post_text, $post_title = '')
  148. {
  149.         global $db, $phpbb_root_path, $board_config, $lang;
  150.  
  151.         $stopword_array = @file($phpbb_root_path . 'language/lang_' . $board_config['default_lang'] . "/search_stopwords.txt");
  152.         $synonym_array = @file($phpbb_root_path . 'language/lang_' . $board_config['default_lang'] . "/search_synonyms.txt");
  153.  
  154.         $search_raw_words = array();
  155.         $search_raw_words['text'] = split_words(clean_words('post', $post_text, $stopword_array, $synonym_array));
  156.         $search_raw_words['title'] = split_words(clean_words('post', $post_title, $stopword_array, $synonym_array));
  157.     @set_time_limit(0);
  158.         $word = array();
  159.         $word_insert_sql = array();
  160.         while ( list($word_in, $search_matches) = @each($search_raw_words) )
  161.         {
  162.                 $word_insert_sql[$word_in] = '';
  163.                 if ( !empty($search_matches) )
  164.                 {
  165.                         for ($i = 0; $i < count($search_matches); $i++)
  166.                         {
  167.                                 $search_matches[$i] = trim($search_matches[$i]);
  168.  
  169.                                 if( $search_matches[$i] != '' )
  170.                                 {
  171.                                         $word[] = $search_matches[$i];
  172.                                         if ( !strstr($word_insert_sql[$word_in], "'" . $search_matches[$i] . "'") )
  173.                                         {
  174.                                                 $word_insert_sql[$word_in] .= ( $word_insert_sql[$word_in] != "" ) ? ", '" . $search_matches[$i] . "'" : "'" . $search_matches[$i] . "'";
  175.                                         }
  176.                                 }
  177.                         }
  178.                 }
  179.         }
  180.  
  181.         if ( count($word) )
  182.         {
  183.                 sort($word);
  184.  
  185.                 $prev_word = '';
  186.                 $word_text_sql = '';
  187.                 $temp_word = array();
  188.                 for($i = 0; $i < count($word); $i++)
  189.                 {
  190.                         if ( $word[$i] != $prev_word )
  191.                         {
  192.                                 $temp_word[] = $word[$i];
  193.                                 $word_text_sql .= ( ( $word_text_sql != '' ) ? ', ' : '' ) . "'" . $word[$i] . "'";
  194.                         }
  195.                         $prev_word = $word[$i];
  196.                 }
  197.                 $word = $temp_word;
  198.  
  199.                 $check_words = array();
  200.                 switch( SQL_LAYER )
  201.                 {
  202.                         case 'postgresql':
  203.                         case 'msaccess':
  204.                         case 'mssql-odbc':
  205.                         case 'oracle':
  206.                         case 'db2':
  207.                                 $sql = "SELECT word_id, word_text
  208.                                         FROM " . SEARCH_WORD_TABLE . "
  209.                                         WHERE word_text IN ($word_text_sql)";
  210.                                 if ( !($result = $db->sql_query($sql)) )
  211.                                 {
  212.                                         message_die(GENERAL_ERROR, 'Could not select words', '', __LINE__, __FILE__, $sql);
  213.                                 }
  214.  
  215.                                 while ( $row = $db->sql_fetchrow($result) )
  216.                                 {
  217.                                         $check_words[$row['word_text']] = $row['word_id'];
  218.                                 }
  219.                                 break;
  220.                 }
  221.  
  222.                 $value_sql = '';
  223.                 $match_word = array();
  224.                 for ($i = 0; $i < count($word); $i++)
  225.                 {
  226.                         $new_match = true;
  227.                         if ( isset($check_words[$word[$i]]) )
  228.                         {
  229.                                 $new_match = false;
  230.                         }
  231.  
  232.                         if ( $new_match )
  233.                         {
  234.                                 switch( SQL_LAYER )
  235.                                 {
  236.                                         case 'mysql':
  237.                                         case 'mysql4':
  238.                                                 $value_sql .= ( ( $value_sql != '' ) ? ', ' : '' ) . '(\'' . $word[$i] . '\', 0)';
  239.                                                 break;
  240.                                         case 'mssql':
  241.                                         case 'mssql-odbc':
  242.                                                 $value_sql .= ( ( $value_sql != '' ) ? ' UNION ALL ' : '' ) . "SELECT '" . $word[$i] . "', 0";
  243.                                                 break;
  244.                                         default:
  245.                                                 $sql = "INSERT INTO " . SEARCH_WORD_TABLE . " (word_text, word_common)
  246.                                                         VALUES ('" . $word[$i] . "', '0')";
  247.                                                 if( !$db->sql_query($sql) )
  248.                                                 {
  249.                                                         message_die(GENERAL_ERROR, 'Could not insert new word', '', __LINE__, __FILE__, $sql);
  250.                                                 }
  251.                                                 break;
  252.                                 }
  253.                         }
  254.                 }
  255.  
  256.                 if ( $value_sql != '' )
  257.                 {
  258.                         switch ( SQL_LAYER )
  259.                         {
  260.                                 case 'mysql':
  261.                                 case 'mysql4':
  262.                                         $sql = "INSERT IGNORE INTO " . SEARCH_WORD_TABLE . " (word_text, word_common)
  263.                                                 VALUES $value_sql";
  264.                                         break;
  265.                                 case 'mssql':
  266.                                 case 'mssql-odbc':
  267.                                         $sql = "INSERT INTO " . SEARCH_WORD_TABLE . " (word_text, word_common)
  268.                                                 $value_sql";
  269.                                         break;
  270.                         }
  271.  
  272.                         if ( !$db->sql_query($sql) )
  273.                         {
  274.                                 message_die(GENERAL_ERROR, 'Could not insert new word', '', __LINE__, __FILE__, $sql);
  275.                         }
  276.                 }
  277.         }
  278.  
  279.         while( list($word_in, $match_sql) = @each($word_insert_sql) )
  280.         {
  281.                 $title_match = ( $word_in == 'title' ) ? 1 : 0;
  282.  
  283.                 if ( $match_sql != '' )
  284.                 {
  285.                         $sql = "INSERT INTO " . SEARCH_MATCH_TABLE . " (post_id, word_id, title_match)
  286.                                 SELECT $post_id, word_id, $title_match
  287.                                         FROM " . SEARCH_WORD_TABLE . "
  288.                                         WHERE word_text IN ($match_sql)";
  289.                         if ( !$db->sql_query($sql) )
  290.                         {
  291.                                 message_die(GENERAL_ERROR, 'Could not insert new word matches', '', __LINE__, __FILE__, $sql);
  292.                         }
  293.                 }
  294.         }
  295.  
  296.         if ($mode == 'single')
  297.         {
  298.                 remove_common('single', 4/10, $word);
  299.         }
  300.  
  301.         return;
  302. }
  303.  
  304. //
  305. // Check if specified words are too common now
  306. //
  307. function remove_common($mode, $fraction, $word_id_list = array())
  308. {
  309.         global $db;
  310.  
  311.         $sql = "SELECT COUNT(post_id) AS total_posts
  312.                 FROM " . POSTS_TABLE;
  313.         if ( !($result = $db->sql_query($sql)) )
  314.         {
  315.                 message_die(GENERAL_ERROR, 'Could not obtain post count', '', __LINE__, __FILE__, $sql);
  316.         }
  317.  
  318.         $row = $db->sql_fetchrow($result);
  319.  
  320.         if ( $row['total_posts'] >= 100 )
  321.         {
  322.                 $common_threshold = floor($row['total_posts'] * $fraction);
  323.  
  324.                 if ( $mode == 'single' && count($word_id_list) )
  325.                 {
  326.                         $word_id_sql = '';
  327.                         for($i = 0; $i < count($word_id_list); $i++)
  328.                         {
  329.                                 $word_id_sql .= ( ( $word_id_sql != '' ) ? ', ' : '' ) . "'" . $word_id_list[$i] . "'";
  330.                         }
  331.  
  332.                         $sql = "SELECT m.word_id
  333.                                 FROM " . SEARCH_MATCH_TABLE . " m, " . SEARCH_WORD_TABLE . " w
  334.                                 WHERE w.word_text IN ($word_id_sql)
  335.                                         AND m.word_id = w.word_id
  336.                                 GROUP BY m.word_id
  337.                                 HAVING COUNT(m.word_id) > $common_threshold";
  338.                 }
  339.                 else
  340.                 {
  341.                         $sql = "SELECT word_id
  342.                                 FROM " . SEARCH_MATCH_TABLE . "
  343.                                 GROUP BY word_id
  344.                                 HAVING COUNT(word_id) > $common_threshold";
  345.                 }
  346.  
  347.                 if ( !($result = $db->sql_query($sql)) )
  348.                 {
  349.                         message_die(GENERAL_ERROR, 'Could not obtain common word list', '', __LINE__, __FILE__, $sql);
  350.                 }
  351.  
  352.                 $common_word_id = '';
  353.                 while ( $row = $db->sql_fetchrow($result) )
  354.                 {
  355.                         $common_word_id .= ( ( $common_word_id != '' ) ? ', ' : '' ) . $row['word_id'];
  356.                 }
  357.                 $db->sql_freeresult($result);
  358.  
  359.                 if ( $common_word_id != '' )
  360.                 {
  361.                         $sql = "UPDATE " . SEARCH_WORD_TABLE . "
  362.                                 SET word_common = " . TRUE . "
  363.                                 WHERE word_id IN ($common_word_id)";
  364.                         if ( !$db->sql_query($sql) )
  365.                         {
  366.                                 message_die(GENERAL_ERROR, 'Could not delete word list entry', '', __LINE__, __FILE__, $sql);
  367.                         }
  368.  
  369.                         $sql = "DELETE FROM " . SEARCH_MATCH_TABLE . "
  370.                                 WHERE word_id IN ($common_word_id)";
  371.                         if ( !$db->sql_query($sql) )
  372.                         {
  373.                                 message_die(GENERAL_ERROR, 'Could not delete word match entry', '', __LINE__, __FILE__, $sql);
  374.                         }
  375.                 }
  376.         }
  377.  
  378.         return;
  379. }
  380.  
  381. function remove_search_post($post_id_sql)
  382. {
  383.         global $db;
  384.  
  385.         $words_removed = false;
  386.  
  387.         switch ( SQL_LAYER )
  388.         {
  389.                 case 'mysql':
  390.                 case 'mysql4':
  391.                         $sql = "SELECT word_id
  392.                                 FROM " . SEARCH_MATCH_TABLE . "
  393.                                 WHERE post_id IN ($post_id_sql)
  394.                                 GROUP BY word_id";
  395.                         if ( $result = $db->sql_query($sql) )
  396.                         {
  397.                                 $word_id_sql = '';
  398.                                 while ( $row = $db->sql_fetchrow($result) )
  399.                                 {
  400.                                         $word_id_sql .= ( $word_id_sql != '' ) ? ', ' . $row['word_id'] : $row['word_id'];
  401.                                 }
  402.  
  403.                                 $sql = "SELECT word_id
  404.                                         FROM " . SEARCH_MATCH_TABLE . "
  405.                                         WHERE word_id IN ($word_id_sql)
  406.                                         GROUP BY word_id
  407.                                         HAVING COUNT(word_id) = 1";
  408.                                 if ( $result = $db->sql_query($sql) )
  409.                                 {
  410.                                         $word_id_sql = '';
  411.                                         while ( $row = $db->sql_fetchrow($result) )
  412.                                         {
  413.                                                 $word_id_sql .= ( $word_id_sql != '' ) ? ', ' . $row['word_id'] : $row['word_id'];
  414.                                         }
  415.  
  416.                                         if ( $word_id_sql != '' )
  417.                                         {
  418.                                                 $sql = "DELETE FROM " . SEARCH_WORD_TABLE . "
  419.                                                         WHERE word_id IN ($word_id_sql)";
  420.                                                 if ( !$db->sql_query($sql) )
  421.                                                 {
  422.                                                         message_die(GENERAL_ERROR, 'Could not delete word list entry', '', __LINE__, __FILE__, $sql);
  423.                                                 }
  424.  
  425.                                                 $words_removed = $db->sql_affectedrows();
  426.                                         }
  427.                                 }
  428.                         }
  429.                         break;
  430.  
  431.                 default:
  432.                         $sql = "DELETE FROM " . SEARCH_WORD_TABLE . "
  433.                                 WHERE word_id IN (
  434.                                         SELECT word_id
  435.                                         FROM " . SEARCH_MATCH_TABLE . "
  436.                                         WHERE word_id IN (
  437.                                                 SELECT word_id
  438.                                                 FROM " . SEARCH_MATCH_TABLE . "
  439.                                                 WHERE post_id IN ($post_id_sql)
  440.                                                 GROUP BY word_id
  441.                                         )
  442.                                         GROUP BY word_id
  443.                                         HAVING COUNT(word_id) = 1
  444.                                 )";
  445.                         if ( !$db->sql_query($sql) )
  446.                         {
  447.                                 message_die(GENERAL_ERROR, 'Could not delete old words from word table', '', __LINE__, __FILE__, $sql);
  448.                         }
  449.  
  450.                         $words_removed = $db->sql_affectedrows();
  451.  
  452.                         break;
  453.         }
  454.  
  455.         $sql = "DELETE FROM " . SEARCH_MATCH_TABLE . "
  456.                 WHERE post_id IN ($post_id_sql)";
  457.         if ( !$db->sql_query($sql) )
  458.         {
  459.                 message_die(GENERAL_ERROR, 'Error in deleting post', '', __LINE__, __FILE__, $sql);
  460.         }
  461.  
  462.         return $words_removed;
  463. }
  464.  
  465. //
  466. // Username search
  467. //
  468. function username_search($search_match)
  469. {
  470.         global $db, $board_config, $template, $lang, $images, $theme, $phpEx, $phpbb_root_path;
  471.         global $starttime, $gen_simple_header;
  472.  
  473.         $gen_simple_header = TRUE;
  474.  
  475.         $username_list = '';
  476.         if ( !empty($search_match) )
  477.         {
  478.                 $username_search = preg_replace('/\*/', '%', trim(strip_tags($search_match)));
  479.  
  480.                 $sql = "SELECT username
  481.                         FROM " . USERS_TABLE . "
  482.                         WHERE username LIKE '" . str_replace("\'", "''", $username_search) . "' AND user_id <> " . ANONYMOUS . "
  483.                         ORDER BY username";
  484.                 if ( !($result = $db->sql_query($sql)) )
  485.                 {
  486.                         message_die(GENERAL_ERROR, 'Could not obtain search results', '', __LINE__, __FILE__, $sql);
  487.                 }
  488.  
  489.                 if ( $row = $db->sql_fetchrow($result) )
  490.                 {
  491.                         do
  492.                         {
  493.                                 $username_list .= '<option value="' . $row['username'] . '">' . $row['username'] . '</option>';
  494.                         }
  495.                         while ( $row = $db->sql_fetchrow($result) );
  496.                 }
  497.                 else
  498.                 {
  499.                         $username_list .= '<option>' . $lang['No_match']. '</option>';
  500.                 }
  501.                 $db->sql_freeresult($result);
  502.         }
  503.  
  504.         $page_title = $lang['Search'];
  505.         include("includes/page_header_review.php");
  506.  
  507.         $template->set_filenames(array(
  508.                 'search_user_body' => 'search_username.tpl')
  509.         );
  510.  
  511.         $template->assign_vars(array(
  512.                 'USERNAME' => ( !empty($search_match) ) ? strip_tags($search_match) : '',
  513.  
  514.                 'L_CLOSE_WINDOW' => $lang['Close_window'],
  515.                 'L_SEARCH_USERNAME' => $lang['Find_username'],
  516.                 'L_UPDATE_USERNAME' => $lang['Select_username'],
  517.                 'L_SELECT' => $lang['Select'],
  518.                 'L_SEARCH' => $lang['Search'],
  519.                 'L_SEARCH_EXPLAIN' => $lang['Search_author_explain'],
  520.                 'L_CLOSE_WINDOW' => $lang['Close_window'],
  521.  
  522.                 'S_USERNAME_OPTIONS' => $username_list,
  523.                 'S_SEARCH_ACTION' => append_sid("search.$phpEx?mode=searchuser&popup=1"))
  524.         );
  525.  
  526.         if ( $username_list != '' )
  527.         {
  528.                 $template->assign_block_vars('switch_select_name', array());
  529.         }
  530.  
  531.         $template->pparse('search_user_body');
  532.  
  533.         include("includes/page_tail_review.php");
  534.  
  535.         return;
  536. }
  537.  
  538. ?>