diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/EnCaseKeywordSearchList.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/EnCaseKeywordSearchList.java index ff5792e60f..a567812057 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/EnCaseKeywordSearchList.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/EnCaseKeywordSearchList.java @@ -74,7 +74,7 @@ class EnCaseKeywordSearchList extends KeywordSearchList { if (child.flags.contains(EncaseFlag.pg)) { // Skip GREP keywords break; } - children.add(new Keyword(child.value, true)); + children.add(new Keyword(child.value, true, true)); break; } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java index 9aa8b74a4f..ffe3a66456 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java @@ -179,7 +179,7 @@ class HighlightedText implements IndexedText { // Run a query to figure out which chunks for the current object have // hits for this keyword. - Keyword keywordQuery = new Keyword(keyword, isLiteral); + Keyword keywordQuery = new Keyword(keyword, isLiteral, true); KeywordSearchQuery chunksQuery = new LuceneQuery(new KeywordList(Arrays.asList(keywordQuery)), keywordQuery); chunksQuery.escape(); chunksQuery.addFilter(new KeywordQueryFilter(FilterType.CHUNK, this.objectId)); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Keyword.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Keyword.java index ae0743d560..22a2e1ca59 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Keyword.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Keyword.java @@ -39,38 +39,6 @@ class Keyword { private final String listName; private final String originalTerm; - /** - * Constructs a representation of a keyword for which to search. The search - * term for the keyword may be either a literal term that will be treated as - * a whole word, or a regex. - * - * @param searchTerm The search term for the keyword. - * @param isLiteral Whether or not the search term is a literal term that - * will be treated as a whole word, instead of a regex. - */ - Keyword(String searchTerm, boolean isLiteral) { - this.searchTerm = searchTerm; - this.isLiteral = isLiteral; - this.isWholeWord = true; - this.listName = ""; - this.originalTerm = searchTerm; - } - - Keyword(String searchTerm, boolean isLiteral, String listName, String originalTerm) { - this.searchTerm = searchTerm; - this.isLiteral = isLiteral; - this.isWholeWord = true; - this.listName = listName; - this.originalTerm = originalTerm; - } - - Keyword(String searchTerm, boolean isLiteral, boolean isWholeWord, String listName, String originalTerm) { - this.searchTerm = searchTerm; - this.isLiteral = isLiteral; - this.isWholeWord = isWholeWord; - this.listName = listName; - this.originalTerm = originalTerm; - } /** * Constructs a representation of a keyword for which to search. The search * term may be either a literal term, to be treated as either a whole word @@ -88,7 +56,37 @@ class Keyword { this.isLiteral = isLiteral; this.isWholeWord = isWholeWord; this.listName = ""; - this.originalTerm = searchTerm; + this.originalTerm = searchTerm; + } + + /** + * Constructs a representation of a keyword for which to search. The search + * term may be either a literal term, to be treated as either a whole word + * or as a substring, or a regex. + * + * NOTE: The addition of keyword list name and original search term was + * added to facilitate proper de-duping of results of periodic keyword + * searches that does not lose any keyword hits. Without this addition when + * using substring search feature during ingest, if there are multiple searches + * on differnt keyword lists that produce the same keyword hit, that hit is + * only going to be displayed in results of one of the list. For example, + * two substring searches, such as "pass" and "enger", will be missing one + * copy of any shared entries (i.e., "passenger" will only show up on one + * list). See JIRA story 2495. + * + * @param searchTerm The search term. + * @param isLiteral Whether or not the search term is a literal term, + * instead of a regex. + * @param isWholeWord Whether or not the search term, if it is a literal + * search term, should be treated as a whole word rather + * than a substring. + */ + Keyword(String searchTerm, boolean isLiteral, boolean isWholeWord, String listName, String originalTerm) { + this.searchTerm = searchTerm; + this.isLiteral = isLiteral; + this.isWholeWord = isWholeWord; + this.listName = listName; + this.originalTerm = originalTerm; } /** @@ -106,7 +104,7 @@ class Keyword { * @param keywordType The artifact attribute type. */ Keyword(String searchTerm, boolean isLiteral, BlackboardAttribute.ATTRIBUTE_TYPE artifactAtrributeType) { - this(searchTerm, isLiteral); + this(searchTerm, isLiteral, true); this.artifactAtrributeType = artifactAtrributeType; } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java index ce113b2e75..9f8686898f 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java @@ -181,7 +181,7 @@ class LuceneQuery implements KeywordSearchQuery { QueryResults results = new QueryResults(this); //in case of single term literal query there is only 1 term - results.addResult(new Keyword(originalKeyword.getSearchTerm(), true, originalKeyword.getListName(), originalKeyword.getOriginalTerm()), matches); + results.addResult(new Keyword(originalKeyword.getSearchTerm(), true, true, originalKeyword.getListName(), originalKeyword.getOriginalTerm()), matches); return results; } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java index bb96ae81d5..9834332567 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java @@ -204,7 +204,7 @@ final class RegexQuery implements KeywordSearchQuery { try { List keywordHits = createKeywordHits(resultDoc); for (KeywordHit hit : keywordHits) { - hitsMultiMap.put(new Keyword(hit.getHit(), true, originalKeyword.getListName(), originalKeyword.getOriginalTerm()), hit); + hitsMultiMap.put(new Keyword(hit.getHit(), true, true, originalKeyword.getListName(), originalKeyword.getOriginalTerm()), hit); } } catch (TskException ex) { // diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java index 43388a3687..f4413e3f2a 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java @@ -306,14 +306,14 @@ final class TermsComponentQuery implements KeywordSearchQuery { * query. */ String escapedTerm = KeywordSearchUtil.escapeLuceneQuery(term.getTerm()); - LuceneQuery termQuery = new LuceneQuery(keywordList, new Keyword(escapedTerm, true)); + LuceneQuery termQuery = new LuceneQuery(keywordList, new Keyword(escapedTerm, true, true)); filters.forEach(termQuery::addFilter); // This appears to be unused QueryResults termQueryResult = termQuery.performQuery(); Set termHits = new HashSet<>(); for (Keyword word : termQueryResult.getKeywords()) { termHits.addAll(termQueryResult.getResults(word)); } - results.addResult(new Keyword(term.getTerm(), false, originalKeyword.getListName(), originalKeyword.getOriginalTerm()), new ArrayList<>(termHits)); + results.addResult(new Keyword(term.getTerm(), false, true, originalKeyword.getListName(), originalKeyword.getOriginalTerm()), new ArrayList<>(termHits)); } return results; } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/XmlKeywordSearchList.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/XmlKeywordSearchList.java index a5c25d1dc7..79843e4d64 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/XmlKeywordSearchList.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/XmlKeywordSearchList.java @@ -201,7 +201,7 @@ final class XmlKeywordSearchList extends KeywordSearchList { Keyword keyword; String whole = wordEl.getAttribute(KEYWORD_WHOLE_ATTR); if (whole.equals("")) { - keyword = new Keyword(wordEl.getTextContent(), isLiteral); + keyword = new Keyword(wordEl.getTextContent(), isLiteral, true); } else { boolean isWhole = whole.equals("true"); keyword = new Keyword(wordEl.getTextContent(), isLiteral, isWhole);