From 02378e94e779bbd407ef86166884c00e32d152fc Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Fri, 28 Mar 2014 21:58:18 +0100 Subject: [PATCH 1/5] [ticket/10423] Remove * from search or highlight string PHPBB3-10423 --- phpBB/search.php | 9 +++++---- phpBB/viewtopic.php | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/phpBB/search.php b/phpBB/search.php index 0f13dbbfa0..43eb42514e 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -574,9 +574,9 @@ if ($keywords || $author || $author_id || $search_id || $submit) } // define some vars for urls - $hilit = implode('|', explode(' ', preg_replace('#\s+#u', ' ', str_replace(array('+', '-', '|', '(', ')', '"'), ' ', $keywords)))); - // Do not allow *only* wildcard being used for hilight - $hilit = (strspn($hilit, '*') === strlen($hilit)) ? '' : $hilit; + // A single wildcard will destroy the search query + $hilit = trim(preg_replace('#(?<=^|\s)\*(?=\s|$)#', '', str_replace(array('+', '-', '|', '(', ')', '"'), ' ', $keywords))); + $hilit = implode('|', explode(' ', preg_replace('#\s+#u', ' ', $hilit))); $u_hilit = urlencode(htmlspecialchars_decode(str_replace('|', ' ', $hilit))); $u_show_results = '&sr=' . $show_results; @@ -840,7 +840,8 @@ if ($keywords || $author || $author_id || $search_id || $submit) $hilit_array = array_filter(explode('|', $hilit), 'strlen'); foreach ($hilit_array as $key => $value) { - $hilit_array[$key] = str_replace('\*', '\w*?', preg_quote($value, '#')); + $hilit_array[$key] = preg_replace('#\s+#u', ' ', trim(preg_replace('#(?<=^|\s)\*(?=\s|$)#', '', $value))); + $hilit_array[$key] = str_replace('\*', '\w*?', preg_quote($hilit_array[$key], '#')); $hilit_array[$key] = preg_replace('#(^|\s)\\\\w\*\?(\s|$)#', '$1\w+?$2', $hilit_array[$key]); } $hilit = implode('|', $hilit_array); diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index e08d6e1ef5..4c9302dbbe 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -475,9 +475,10 @@ if ($hilit_words) { if (trim($word)) { + $word = preg_replace('#\s+#u', ' ', trim(preg_replace('#(?<=^|\s)\*(?=\s|$)#', '', $word))); $word = str_replace('\*', '\w+?', preg_quote($word, '#')); $word = preg_replace('#(^|\s)\\\\w\*\?(\s|$)#', '$1\w+?$2', $word); - $highlight_match .= (($highlight_match != '') ? '|' : '') . $word; + $highlight_match .= (($highlight_match != '' && $word != '') ? '|' : '') . $word; } } From face175471b5064117ca57ece53a3403e51e20ba Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sun, 13 Apr 2014 21:15:14 +0200 Subject: [PATCH 2/5] [ticket/10423] Move code into a function and add tests for it PHPBB3-10423 --- phpBB/includes/functions_content.php | 18 +++++++++ phpBB/search.php | 8 ++-- phpBB/viewtopic.php | 2 +- .../phpbb_clean_search_string_test.php | 37 +++++++++++++++++++ 4 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 tests/functions_content/phpbb_clean_search_string_test.php diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index 6213d2fd24..69a29dc31b 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -21,6 +21,7 @@ if (!defined('IN_PHPBB')) * make_jumpbox() * bump_topic_allowed() * get_context() +* phpbb_clean_search_string() * decode_message() * strip_bbcode() * generate_text_for_display() @@ -360,6 +361,23 @@ function get_context($text, $words, $length = 400) } } +/** +* Cleans a search string by removing single wildcards from it and replacing multiple spaces with a single one. +* +* @param string $search_string The full search string which should be cleaned. +* +* @return string The cleaned search string without any wildcards and multiple spaces. +*/ +function phpbb_clean_search_string($search_string) +{ + // This regular expressions matches every single wildcard. + // That means one after a whitespace or the beginning of the string or one before a whitespace or the end of the string. + $search_string = preg_replace('#(?<=^|\s)\*(?=\s|$)#', '', $search_string); + $search_string = trim($search_string); + $search_string = preg_replace('#\s+#u', ' ', $search_string); + return $search_string; +} + /** * Decode text whereby text is coming from the db and expected to be pre-parsed content * We are placing this outside of the message parser because we are often in need of it... diff --git a/phpBB/search.php b/phpBB/search.php index 43eb42514e..d0d86fac17 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -574,9 +574,9 @@ if ($keywords || $author || $author_id || $search_id || $submit) } // define some vars for urls - // A single wildcard will destroy the search query - $hilit = trim(preg_replace('#(?<=^|\s)\*(?=\s|$)#', '', str_replace(array('+', '-', '|', '(', ')', '"'), ' ', $keywords))); - $hilit = implode('|', explode(' ', preg_replace('#\s+#u', ' ', $hilit))); + // A single wildcard will make the search results look ugly + $hilit = phpbb_clean_search_string(str_replace(array('+', '-', '|', '(', ')', '"'), ' ', $keywords)); + $hilit = str_replace(' ', '|', $hilit); $u_hilit = urlencode(htmlspecialchars_decode(str_replace('|', ' ', $hilit))); $u_show_results = '&sr=' . $show_results; @@ -840,7 +840,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) $hilit_array = array_filter(explode('|', $hilit), 'strlen'); foreach ($hilit_array as $key => $value) { - $hilit_array[$key] = preg_replace('#\s+#u', ' ', trim(preg_replace('#(?<=^|\s)\*(?=\s|$)#', '', $value))); + $hilit_array[$key] = phpbb_clean_search_string($value); $hilit_array[$key] = str_replace('\*', '\w*?', preg_quote($hilit_array[$key], '#')); $hilit_array[$key] = preg_replace('#(^|\s)\\\\w\*\?(\s|$)#', '$1\w+?$2', $hilit_array[$key]); } diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 4c9302dbbe..31bc1d2701 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -475,7 +475,7 @@ if ($hilit_words) { if (trim($word)) { - $word = preg_replace('#\s+#u', ' ', trim(preg_replace('#(?<=^|\s)\*(?=\s|$)#', '', $word))); + $word = phpbb_clean_search_string($word); $word = str_replace('\*', '\w+?', preg_quote($word, '#')); $word = preg_replace('#(^|\s)\\\\w\*\?(\s|$)#', '$1\w+?$2', $word); $highlight_match .= (($highlight_match != '' && $word != '') ? '|' : '') . $word; diff --git a/tests/functions_content/phpbb_clean_search_string_test.php b/tests/functions_content/phpbb_clean_search_string_test.php new file mode 100644 index 0000000000..3706ffedf9 --- /dev/null +++ b/tests/functions_content/phpbb_clean_search_string_test.php @@ -0,0 +1,37 @@ +assertEquals($expected, phpbb_clean_search_string($search_string)); + } +} From dde7ac3b2bcee9832a12255a8df496a67743e2e0 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sun, 13 Apr 2014 21:31:44 +0200 Subject: [PATCH 3/5] [ticket/10423] Match multiple wildcards Multiple wildcards are removed from the string if there is no word before or after them. If there is a word before or after them, they are just replaced with a single one. PHPBB3-10423 --- phpBB/includes/functions_content.php | 4 ++-- tests/functions_content/phpbb_clean_search_string_test.php | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index 69a29dc31b..19459239d5 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -372,9 +372,9 @@ function phpbb_clean_search_string($search_string) { // This regular expressions matches every single wildcard. // That means one after a whitespace or the beginning of the string or one before a whitespace or the end of the string. - $search_string = preg_replace('#(?<=^|\s)\*(?=\s|$)#', '', $search_string); + $search_string = preg_replace('#(?<=^|\s)\*+(?=\s|$)#', '', $search_string); $search_string = trim($search_string); - $search_string = preg_replace('#\s+#u', ' ', $search_string); + $search_string = preg_replace(array('#\s+#u', '#\*+#u'), array(' ', '*'), $search_string); return $search_string; } diff --git a/tests/functions_content/phpbb_clean_search_string_test.php b/tests/functions_content/phpbb_clean_search_string_test.php index 3706ffedf9..fef9b5e9ea 100644 --- a/tests/functions_content/phpbb_clean_search_string_test.php +++ b/tests/functions_content/phpbb_clean_search_string_test.php @@ -24,6 +24,8 @@ class phpbb_functions_content_phpbb_clean_search_string_test extends phpbb_test_ array('* *test*', '*test*'), array('test test * test', 'test test test'), array(' some wild*cards * between wo*rds ', 'some wild*cards between wo*rds'), + array(' we * now have*** multiple wild***cards * ', 'we now have* multiple wild*cards'), + array('pi is *** . * **** * *****', 'pi is .'), ); } From 601ecd3da132c376be2119ef7bc7126f219859f3 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Mon, 14 Apr 2014 18:31:30 +0200 Subject: [PATCH 4/5] [ticket/10423] Remove unnecessary include in test PHPBB3-10423 --- tests/functions_content/phpbb_clean_search_string_test.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/functions_content/phpbb_clean_search_string_test.php b/tests/functions_content/phpbb_clean_search_string_test.php index fef9b5e9ea..de642c9040 100644 --- a/tests/functions_content/phpbb_clean_search_string_test.php +++ b/tests/functions_content/phpbb_clean_search_string_test.php @@ -7,7 +7,6 @@ * */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; class phpbb_functions_content_phpbb_clean_search_string_test extends phpbb_test_case From f3cd7f73e1ed3acbf1a319331e2f99ea27d5fe2d Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Mon, 14 Apr 2014 19:22:14 +0200 Subject: [PATCH 5/5] [ticket/10423] Replace foreach with function in viewtopic.php PHPBB3-10423 --- phpBB/viewtopic.php | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 31bc1d2701..f52e04e1a8 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -471,18 +471,11 @@ else $highlight_match = $highlight = ''; if ($hilit_words) { - foreach (explode(' ', trim($hilit_words)) as $word) - { - if (trim($word)) - { - $word = phpbb_clean_search_string($word); - $word = str_replace('\*', '\w+?', preg_quote($word, '#')); - $word = preg_replace('#(^|\s)\\\\w\*\?(\s|$)#', '$1\w+?$2', $word); - $highlight_match .= (($highlight_match != '' && $word != '') ? '|' : '') . $word; - } - } - - $highlight = urlencode($hilit_words); + $highlight_match = phpbb_clean_search_string($hilit_words); + $highlight = urlencode($highlight_match); + $highlight_match = str_replace('\*', '\w+?', preg_quote($highlight_match, '#')); + $highlight_match = preg_replace('#(?<=^|\s)\\\\w\*\?(?=\s|$)#', '\w+?', $highlight_match); + $highlight_match = str_replace(' ', '|', $highlight_match); } // Make sure $start is set to the last page if it exceeds the amount