From 2f6852088012703b2f3a3a0d3e19e88bfe82ae3a Mon Sep 17 00:00:00 2001 From: Dawid Date: Wed, 12 Feb 2020 00:00:21 +0100 Subject: [PATCH] Fix not escaping special characters in search pattern fixes #5892 * add method to get search pattern for searched words with escaped javascript regexp special characters (for search without regular expressions) * in preview viewer use search pattern with escaped javascript regexp special characters --- .../org/jabref/gui/preview/PreviewViewer.java | 4 ++-- .../org/jabref/logic/search/SearchQuery.java | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/gui/preview/PreviewViewer.java b/src/main/java/org/jabref/gui/preview/PreviewViewer.java index 7f154c6e78d..190f973fa39 100644 --- a/src/main/java/org/jabref/gui/preview/PreviewViewer.java +++ b/src/main/java/org/jabref/gui/preview/PreviewViewer.java @@ -85,7 +85,7 @@ public class PreviewViewer extends ScrollPane implements InvalidationListener { private boolean registered; private ChangeListener> listener = (queryObservable, queryOldValue, queryNewValue) -> { - searchHighlightPattern = queryNewValue.flatMap(SearchQuery::getPatternForWords); + searchHighlightPattern = queryNewValue.flatMap(SearchQuery::getJsPatternForWords); highlightSearchPattern(); }; @@ -131,7 +131,7 @@ public void setTheme(String theme) { private void highlightSearchPattern() { if (searchHighlightPattern.isPresent()) { - String pattern = searchHighlightPattern.get().pattern().replace("\\Q", "").replace("\\E", ""); + String pattern = searchHighlightPattern.get().pattern(); previewView.getEngine().executeScript( "var markInstance = new Mark(document.getElementById(\"content\"));" + diff --git a/src/main/java/org/jabref/logic/search/SearchQuery.java b/src/main/java/org/jabref/logic/search/SearchQuery.java index e6e35486767..2070e1b70c8 100644 --- a/src/main/java/org/jabref/logic/search/SearchQuery.java +++ b/src/main/java/org/jabref/logic/search/SearchQuery.java @@ -18,6 +18,9 @@ public class SearchQuery implements SearchMatcher { + // regexp pattern for escaping special characters in javascript regex + public static final String JAVASCRIPT_ESCAPED_CHARS_PATTERN = "[\\.\\*\\+\\?\\^\\$\\{\\}\\(\\)\\|\\[\\]\\\\/]"; + private final String query; private final boolean caseSensitive; private final boolean regularExpression; @@ -124,6 +127,18 @@ public List getSearchWords() { // Returns a regular expression pattern in the form (w1)|(w2)| ... wi are escaped if no regular expression search is enabled public Optional getPatternForWords() { + return joinWordsToPattern(false); + } + + // Returns a regular expression pattern in the form (w1)|(w2)| ... wi are escaped for javascript if no regular expression search is enabled + public Optional getJsPatternForWords() { + return joinWordsToPattern(true); + } + + /* Returns a regular expression pattern in the form (w1)|(w2)| ... wi are escaped if no regular expression search is enabled + * @param escapeSpecialCharsForJS whether to escape characters in wi for javascript regexp (escaping all special characters) or for java (using \Q and \E) + */ + private Optional joinWordsToPattern(boolean escapeSpecialCharsForJS) { List words = getSearchWords(); if ((words == null) || words.isEmpty() || words.get(0).isEmpty()) { @@ -133,7 +148,7 @@ public Optional getPatternForWords() { // compile the words to a regular expression in the form (w1)|(w2)|(w3) StringJoiner joiner = new StringJoiner(")|(", "(", ")"); for (String word : words) { - joiner.add(regularExpression ? word : Pattern.quote(word)); + joiner.add(regularExpression ? word : (escapeSpecialCharsForJS ? word.replaceAll(JAVASCRIPT_ESCAPED_CHARS_PATTERN, "\\\\$0") : Pattern.quote(word))); } String searchPattern = joiner.toString();