From c49e33e5b68723c12866db256be2b7b817e40089 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 24 Jan 2018 17:20:01 -0500 Subject: [PATCH 01/15] Updated logic to properly handle artifact and content nodes. --- .../keywordsearch/ExtractedContentViewer.java | 104 +++++++++++------- .../keywordsearch/HighlightedText.java | 31 +++--- .../KeywordSearchFilterNode.java | 15 ++- .../KeywordSearchResultFactory.java | 57 +++++++++- 4 files changed, 143 insertions(+), 64 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java index dbed68e660..222ca18ebd 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,6 +33,8 @@ import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.QueryContent; +import org.sleuthkit.datamodel.AbstractContent; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -50,7 +52,7 @@ import org.sleuthkit.datamodel.TskCoreException; @ServiceProvider(service = DataContentViewer.class, position = 4) public class ExtractedContentViewer implements DataContentViewer { - private static final Logger logger = Logger.getLogger(ExtractedContentViewer.class.getName()); + private static final Logger LOGGER = Logger.getLogger(ExtractedContentViewer.class.getName()); private static final long INVALID_DOCUMENT_ID = 0L; private static final BlackboardAttribute.Type TSK_ASSOCIATED_ARTIFACT_TYPE = new BlackboardAttribute.Type(TSK_ASSOCIATED_ARTIFACT); @@ -93,7 +95,7 @@ public class ExtractedContentViewer implements DataContentViewer { } Lookup nodeLookup = node.getLookup(); - AbstractFile content = nodeLookup.lookup(AbstractFile.class); + AbstractContent content = nodeLookup.lookup(AbstractFile.class); /* * Assemble a collection of all of the indexed text "sources" for the @@ -104,41 +106,56 @@ public class ExtractedContentViewer implements DataContentViewer { IndexedText rawContentText = null; if (null != content && solrHasContent(content.getId())) { - QueryResults hits = nodeLookup.lookup(QueryResults.class); - BlackboardArtifact artifact = nodeLookup.lookup(BlackboardArtifact.class); - if (hits != null) { - /* - * if there is a QueryReslt object, in the lookup use that. This - * happens when a user selects a row in an ad-hoc search result - */ - highlightedHitText = new HighlightedText(content.getId(), hits); - } else if (artifact != null - && artifact.getArtifactTypeID() == TSK_ACCOUNT.getTypeID()) { - try { - // if the artifact is an account artifact, get an account text . - highlightedHitText = getAccountsText(content, nodeLookup); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Failed to create AccountsText for " + content, ex); //NON-NLS - - } - } else if (artifact != null - && artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) { - try { - //if there is kwh artifact use that to construct the HighlightedText - highlightedHitText = new HighlightedText(artifact); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Failed to create HighlightedText for " + artifact, ex); //NON-NLS - } - } - - if (highlightedHitText != null) { - sources.add(highlightedHitText); - } - /* - * Next, add the "raw" (not highlighted) text, if any, for any - * content associated with the node. + * Results for Keyword Hits. */ + BlackboardArtifact artifact = nodeLookup.lookup(BlackboardArtifact.class); + if (artifact != null) { + if (artifact.getArtifactTypeID() == TSK_ACCOUNT.getTypeID()) { + try { + // if the artifact is an account artifact, get an account text. + highlightedHitText = getAccountsText(content, nodeLookup); + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Failed to create AccountsText for " + content, ex); //NON-NLS + } + } else if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) { + try { + //if there is kwh artifact use that to construct the HighlightedText + highlightedHitText = new HighlightedText(artifact); + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Failed to create HighlightedText for " + artifact, ex); //NON-NLS + } + } + } + } else { + /* + * Results for ad-hoc search. + */ + QueryContent queryContent = nodeLookup.lookup(QueryContent.class); + content = (AbstractFile) queryContent.getContent(); + + if (null != content && solrHasContent(content.getId())) { + QueryResults queryResults = queryContent.getResults(); + if (queryResults != null) { + /* + * If there's a QueryContent object in the lookup, use that. + * This happens when a user selects a row in an ad-hoc + * search result. + */ + highlightedHitText = new HighlightedText(queryContent.getSolrObjectId(), queryResults); + } + } + } + + if (highlightedHitText != null) { + sources.add(highlightedHitText); + } + + /* + * Next, add the "raw" (not highlighted) text, if any, for any + * content associated with the node. + */ + if (content != null) { rawContentText = new RawText(content, content.getId()); sources.add(rawContentText); } @@ -151,7 +168,7 @@ public class ExtractedContentViewer implements DataContentViewer { try { rawArtifactText = getRawArtifactText(nodeLookup); } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error creating RawText for " + content, ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Error creating RawText for " + content, ex); //NON-NLS } if (rawArtifactText != null) { @@ -288,7 +305,7 @@ public class ExtractedContentViewer implements DataContentViewer { return true; } } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting TSK_ACCOUNT_TYPE attribute from artifact " + art.getArtifactID(), ex); + LOGGER.log(Level.SEVERE, "Error getting TSK_ACCOUNT_TYPE attribute from artifact " + art.getArtifactID(), ex); } } else if (artifactTypeID == TSK_KEYWORD_HIT.getTypeID()) { return true; @@ -352,7 +369,7 @@ public class ExtractedContentViewer implements DataContentViewer { try { return solrServer.queryIsIndexed(objectId); } catch (NoOpenCoreException | KeywordSearchModuleException ex) { - logger.log(Level.SEVERE, "Error querying Solr server", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Error querying Solr server", ex); //NON-NLS return false; } } @@ -386,7 +403,7 @@ public class ExtractedContentViewer implements DataContentViewer { return blackboardAttribute.getValueLong(); } } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting associated artifact attributes", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Error getting associated artifact attributes", ex); //NON-NLS } } } @@ -398,6 +415,13 @@ public class ExtractedContentViewer implements DataContentViewer { * handled above. */ Content content = node.getLookup().lookup(Content.class); + if (content == null) { + QueryContent queryContent = node.getLookup().lookup(QueryContent.class); + if (queryContent != null) { + content = queryContent.getContent(); + } + } + if (content != null) { return content.getId(); } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java index 70d2e69194..9bcbdd7b2a 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.keywordsearch; import com.google.common.collect.Iterators; import com.google.common.collect.Range; -import com.google.common.collect.RangeSet; import com.google.common.collect.TreeRangeSet; import java.util.Arrays; import java.util.Collection; @@ -55,7 +54,7 @@ import org.sleuthkit.datamodel.TskCoreException; */ class HighlightedText implements IndexedText { - private static final Logger logger = Logger.getLogger(HighlightedText.class.getName()); + private static final Logger LOGGER = Logger.getLogger(HighlightedText.class.getName()); private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT); @@ -70,7 +69,7 @@ class HighlightedText implements IndexedText { final private Server solrServer = KeywordSearch.getServer(); - private final long objectId; + private final long solrObjectId; /* * The keywords to highlight */ @@ -106,14 +105,14 @@ class HighlightedText implements IndexedText { * search results. In that case we have the entire QueryResults object and need to arrange the paging. * - * @param objectId The objectID of the content whose text will be + * @param solrObjectId The solrObjectId of the content whose text will be * highlighted. * @param QueryResults The QueryResults for the ad-hoc search from whose results a selection was made leading to this HighlightedText. */ - HighlightedText(long objectId, QueryResults hits) { - this.objectId = objectId; + HighlightedText(long solrObjectId, QueryResults hits) { + this.solrObjectId = solrObjectId; this.hits = hits; } @@ -129,9 +128,9 @@ class HighlightedText implements IndexedText { this.artifact = artifact; BlackboardAttribute attribute = artifact.getAttribute(TSK_ASSOCIATED_ARTIFACT); if (attribute != null) { - this.objectId = attribute.getValueLong(); + this.solrObjectId = attribute.getValueLong(); } else { - this.objectId = artifact.getObjectID(); + this.solrObjectId = artifact.getObjectID(); } } @@ -146,7 +145,7 @@ class HighlightedText implements IndexedText { return; } - this.numberPages = solrServer.queryNumFileChunks(this.objectId); + this.numberPages = solrServer.queryNumFileChunks(this.solrObjectId); if (artifact != null) { loadPageInfoFromArtifact(); @@ -194,7 +193,7 @@ class HighlightedText implements IndexedText { // Run a query to figure out which chunks for the current object have // hits for this keyword. - chunksQuery.addFilter(new KeywordQueryFilter(FilterType.CHUNK, this.objectId)); + chunksQuery.addFilter(new KeywordQueryFilter(FilterType.CHUNK, this.solrObjectId)); hits = chunksQuery.performQuery(); loadPageInfoFromHits(); @@ -216,7 +215,7 @@ class HighlightedText implements IndexedText { for (KeywordHit hit : hits.getResults(k)) { int chunkID = hit.getChunkId(); if (artifact != null) { - if (chunkID != 0 && this.objectId == hit.getSolrObjectId()) { + if (chunkID != 0 && this.solrObjectId == hit.getSolrObjectId()) { String hit1 = hit.getHit(); if (keywords.stream().anyMatch(hit1::contains)) { numberOfHitsPerPage.put(chunkID, 0); //unknown number of matches in the page @@ -225,7 +224,7 @@ class HighlightedText implements IndexedText { } } } else { - if (chunkID != 0 && this.objectId == hit.getSolrObjectId()) { + if (chunkID != 0 && this.solrObjectId == hit.getSolrObjectId()) { numberOfHitsPerPage.put(chunkID, 0); //unknown number of matches in the page currentHitPerPage.put(chunkID, 0); //set current hit to 0th @@ -354,7 +353,7 @@ class HighlightedText implements IndexedText { SolrQuery q = new SolrQuery(); q.setShowDebugInfo(DEBUG); //debug - String contentIdStr = Long.toString(this.objectId); + String contentIdStr = Long.toString(this.solrObjectId); if (numberPages != 0) { chunkID = Integer.toString(this.currentPage); contentIdStr += "0".equals(chunkID) ? "" : "_" + chunkID; @@ -401,7 +400,7 @@ class HighlightedText implements IndexedText { // either be a single chunk containing hits or we narrow our // query down to the current page/chunk. if (response.getResults().size() > 1) { - logger.log(Level.WARNING, "Unexpected number of results for Solr highlighting query: {0}", q); //NON-NLS + LOGGER.log(Level.WARNING, "Unexpected number of results for Solr highlighting query: {0}", q); //NON-NLS } String highlightedContent; Map>> responseHighlight = response.getHighlighting(); @@ -427,7 +426,7 @@ class HighlightedText implements IndexedText { return "
" + highlightedContent + "
"; //NON-NLS } catch (TskCoreException | KeywordSearchModuleException | NoOpenCoreException ex) { - logger.log(Level.SEVERE, "Error getting highlighted text for Solr doc id " + objectId + ", chunkID " + chunkID + ", highlight query: " + highlightField, ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Error getting highlighted text for Solr doc id " + solrObjectId + ", chunkID " + chunkID + ", highlight query: " + highlightField, ex); //NON-NLS return NbBundle.getMessage(this.getClass(), "HighlightedMatchesSource.getMarkup.queryFailedMsg"); } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java index 7674ee5e34..b848892691 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2017 Basis Technology Corp. + * Copyright 2013-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,6 +39,7 @@ import org.sleuthkit.autopsy.actions.AddContentTagAction; import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.directorytree.HashSearchAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; +import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.QueryContent; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentVisitor; @@ -52,12 +53,18 @@ import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.VirtualDirectory; /** - * + * FilterNode containing data pertaining to keyword search. */ class KeywordSearchFilterNode extends FilterNode { - KeywordSearchFilterNode(QueryResults highlights, Node original) { - super(original, null, new ProxyLookup(Lookups.singleton(highlights), original.getLookup())); + /** + * Instantiate a KeywordSearchFilterNode. + * + * @param queryContent The query content. + * @param original The original source node. + */ + KeywordSearchFilterNode(QueryContent queryContent, Node original) { + super(original, null, new ProxyLookup(Lookups.singleton(queryContent), original.getLookup())); } @Override diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java index a8bc995eae..c8c1c07b15 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java @@ -250,13 +250,12 @@ class KeywordSearchResultFactory extends ChildFactory { Node resultNode; if (key instanceof KeyValueQueryContent) { - final Content content = ((KeyValueQueryContent) key).getContent(); - QueryResults hits = ((KeyValueQueryContent) key).getHits(); + QueryContent queryContent = new QueryContent((KeyValueQueryContent) key); - Node kvNode = new KeyValueNode(key, Children.LEAF, Lookups.singleton(content)); + Node kvNode = new KeyValueNode(key, Children.LEAF, Lookups.singleton(queryContent)); //wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization - resultNode = new KeywordSearchFilterNode(hits, kvNode); + resultNode = new KeywordSearchFilterNode(queryContent, kvNode); } else { resultNode = new EmptyNode("This Node Is Empty"); resultNode.setDisplayName(NbBundle.getMessage(this.getClass(), "KeywordSearchResultFactory.createNodeForKey.noResultsFound.text")); @@ -265,6 +264,56 @@ class KeywordSearchResultFactory extends ChildFactory { return resultNode; } + + /** + * This class encapsulates content, query results, and an associated Solr + * object ID for storing in the Lookup to be read later. + */ + class QueryContent { + private final long solrObjectId; + private final Content content; + private final QueryResults results; + + /** + * Instantiate a QueryContent object. + * + * @param solrObjectId The Solr object ID associated with the content. + * @param content The content for the query result. + * @param results The query results. + */ + QueryContent(KeyValueQueryContent key) { + this.solrObjectId = key.getSolrObjectId(); + this.content = key.getContent(); + this.results = key.getHits(); + } + + /** + * Get the Solr object ID associated with the content. + * + * @return The Solr object ID. + */ + long getSolrObjectId() { + return solrObjectId; + } + + /** + * Get the content for the query result. + * + * @return The content. + */ + Content getContent() { + return content; + } + + /** + * Get the query results. + * + * @return The query results. + */ + QueryResults getResults() { + return results; + } + } /** * Used to display keyword search results in table. Eventually turned into a From eeb83e270ce10a21f3d6e1a1529a1db808eab435 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 24 Jan 2018 17:31:32 -0500 Subject: [PATCH 02/15] Revised some code comments. --- .../keywordsearch/ExtractedContentViewer.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java index 222ca18ebd..bf4b2eb317 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java @@ -113,14 +113,18 @@ public class ExtractedContentViewer implements DataContentViewer { if (artifact != null) { if (artifact.getArtifactTypeID() == TSK_ACCOUNT.getTypeID()) { try { - // if the artifact is an account artifact, get an account text. + /* + * Generate AccountsText for the account artifact. + */ highlightedHitText = getAccountsText(content, nodeLookup); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Failed to create AccountsText for " + content, ex); //NON-NLS } } else if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) { try { - //if there is kwh artifact use that to construct the HighlightedText + /* + * Generate HighlightedText for the keyword hit artifact. + */ highlightedHitText = new HighlightedText(artifact); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Failed to create HighlightedText for " + artifact, ex); //NON-NLS @@ -137,11 +141,6 @@ public class ExtractedContentViewer implements DataContentViewer { if (null != content && solrHasContent(content.getId())) { QueryResults queryResults = queryContent.getResults(); if (queryResults != null) { - /* - * If there's a QueryContent object in the lookup, use that. - * This happens when a user selects a row in an ad-hoc - * search result. - */ highlightedHitText = new HighlightedText(queryContent.getSolrObjectId(), queryResults); } } From a33e4c9b3bb478863ba87561346bf8f04e90aeea Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 24 Jan 2018 17:35:50 -0500 Subject: [PATCH 03/15] Corrected typo. --- .../autopsy/keywordsearch/ExtractedContentViewer.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java index bf4b2eb317..43f0d7baf8 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java @@ -34,7 +34,6 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.QueryContent; -import org.sleuthkit.datamodel.AbstractContent; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -95,7 +94,7 @@ public class ExtractedContentViewer implements DataContentViewer { } Lookup nodeLookup = node.getLookup(); - AbstractContent content = nodeLookup.lookup(AbstractFile.class); + AbstractFile content = nodeLookup.lookup(AbstractFile.class); /* * Assemble a collection of all of the indexed text "sources" for the From ce995690626f71b6ab1cc90158953cf033d784ff Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 31 Jan 2018 13:33:40 -0500 Subject: [PATCH 04/15] 3445 Date Filter option added for files created or modified in last N days --- .../interestingitems/Bundle.properties | 9 +- .../modules/interestingitems/FilesSet.java | 64 ++++- .../interestingitems/FilesSetDefsPanel.form | 213 ++++++++------- .../interestingitems/FilesSetDefsPanel.java | 178 ++++++------ .../interestingitems/FilesSetRulePanel.form | 176 +++++++----- .../interestingitems/FilesSetRulePanel.java | 257 ++++++++++++------ .../interestingitems/FilesSetsManager.java | 6 +- .../InterestingItemsFilesSetSettings.java | 56 +++- 8 files changed, 605 insertions(+), 354 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties index f38bcbc815..0a415c8ca8 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties @@ -38,8 +38,6 @@ FilesSetRulePanel.interesting.jLabel5.text=Enter information about files that yo FilesSetRulePanel.ingest.jLabel5.text=Enter information about files that you want to run ingest on. FilesSetRulePanel.nameCheck.text=Name Pattern: FilesSetRulePanel.pathCheck.text=Path Pattern: -FilesSetRulePanel.mimeCheck.text=MIME Type: -FilesSetRulePanel.fileSizeCheck.text=File Size: FilesSetRulePanel.filesRadioButton.text=Files FilesSetRulePanel.dirsRadioButton.text=Directories FilesSetDefsPanel.interesting.setsListLabel.text=Rule Sets: @@ -79,3 +77,10 @@ FilesSetDefsPanel.ingoreUnallocCheckbox.text=Ignore Unallocated Space FilesSetDefsPanel.ingoreUnallocCheckbox.toolTipText=Ignores unallocated space, such as deleted files. May run faster but produce less complete results. FilesSetDefsPanel.ingestWarningLabel.text=Ingest is ongoing, some settings will be unavailable until it finishes. FilesSetDefsPanel.allRadioButton.text=All +FilesSetRulePanel.dateCheck.text=Modified Within: +FilesSetRulePanel.daysAgoLabel.text=day(s) +FilesSetRulePanel.fileSizeCheck.text=File Size: +FilesSetRulePanel.mimeCheck.text=MIME Type: +FilesSetDefsPanel.daysAgoTextField.text= +FilesSetDefsPanel.modifiedDateLabel.text=Modified Within: +FilesSetDefsPanel.daysAgoLabel.text=day(s) diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java index 38d7285fc1..913db37528 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; import java.util.regex.Pattern; +import org.openide.util.NbBundle; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.TskData; @@ -169,6 +170,7 @@ public final class FilesSet implements Serializable { private final ParentPathCondition pathCondition; private final MimeTypeCondition mimeTypeCondition; private final FileSizeCondition fileSizeCondition; + private final DateCondition dateCondition; private final List conditions = new ArrayList<>(); /** @@ -180,8 +182,10 @@ public final class FilesSet implements Serializable { * @param pathCondition A file path condition, may be null. * @param mimeTypeCondition A file mime type condition, may be null. * @param fileSizeCondition A file size condition, may be null. + * @param dateCondition A file date created or modified condition, + * may be null */ - Rule(String ruleName, FileNameCondition fileNameCondition, MetaTypeCondition metaTypeCondition, ParentPathCondition pathCondition, MimeTypeCondition mimeTypeCondition, FileSizeCondition fileSizeCondition) { + Rule(String ruleName, FileNameCondition fileNameCondition, MetaTypeCondition metaTypeCondition, ParentPathCondition pathCondition, MimeTypeCondition mimeTypeCondition, FileSizeCondition fileSizeCondition, DateCondition dateCondition) { // since ruleName is optional, ruleUUID can be used to uniquely identify a rule. this.uuid = UUID.randomUUID().toString(); if (metaTypeCondition == null) { @@ -216,6 +220,10 @@ public final class FilesSet implements Serializable { if (this.pathCondition != null) { this.conditions.add(this.pathCondition); } + this.dateCondition = dateCondition; + if (this.dateCondition != null) { + this.conditions.add(this.dateCondition); + } } /** @@ -254,6 +262,10 @@ public final class FilesSet implements Serializable { return this.pathCondition; } + DateCondition getDateCondition() { + return this.dateCondition; + } + /** * Determines whether or not a file satisfies the rule. * @@ -270,6 +282,10 @@ public final class FilesSet implements Serializable { return true; } + @NbBundle.Messages({ + "# {0} - daysAgo", + "FilesSet.rule.dateRule.toString=(modified within {0} day(s))" + }) @Override public String toString() { // This override is designed to provide a display name for use with @@ -283,6 +299,8 @@ public final class FilesSet implements Serializable { } else if (this.fileSizeCondition != null) { return this.ruleName + " (" + fileSizeCondition.getComparator().getSymbol() + " " + fileSizeCondition.getSizeValue() + " " + fileSizeCondition.getUnit().getName() + ")"; + } else if (this.dateCondition != null) { + return this.ruleName + Bundle.FilesSet_rule_dateRule_toString(dateCondition.getDaysAgo()); } else { return this.ruleName + " ()"; } @@ -537,7 +555,7 @@ public final class FilesSet implements Serializable { case FILES: return file.isFile(); case DIRECTORIES: - return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR + return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR || file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR; case FILES_AND_DIRECTORIES: return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG @@ -737,6 +755,46 @@ public final class FilesSet implements Serializable { } + /** + * A class for checking whether a file's creation or modification + * occured in a specific range of time + */ + static final class DateCondition implements FileAttributeCondition { + + private final static long DAY_IN_S = 60 * 60 * 24; + + private int daysAgo; + + /** + * Construct a new DateCondition + * + * @param days - files created or modified more recently than this + * number of days will pass + */ + DateCondition(int days) { + daysAgo = days; + } + + /** + * Get the number of days which this condition allows to pass + * + * @return integer value of the number days which will pass + */ + int getDaysAgo() { + return daysAgo; + } + + @Override + public boolean passes(AbstractFile file) { + long dateThreshold = System.currentTimeMillis() / 1000 - daysAgo * DAY_IN_S; + if (file.getCrtime() > dateThreshold || file.getMtime() > dateThreshold) { + return true; + } + return false; + } + + } + /** * A file name extension condition for an interesting files set * membership rule. The immutability of a file name extension condition diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form index bffb00f33b..02d4cec624 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form @@ -90,11 +90,69 @@ + - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -102,97 +160,22 @@ - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -213,8 +196,8 @@ - - + + @@ -223,7 +206,7 @@ - + @@ -232,14 +215,14 @@ - + - + @@ -250,26 +233,32 @@ - + - + - + - + - + + + + + + + @@ -996,6 +985,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java index c67051be97..4afdf6d91e 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -251,6 +251,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp this.fileNameRegexCheckbox.setSelected(false); this.filesRadioButton.setSelected(true); this.rulePathConditionTextField.setText(""); + this.daysAgoTextField.setText(""); this.rulePathConditionRegexCheckBox.setSelected(false); this.mimeTypeComboBox.setSelectedIndex(0); this.equalitySignComboBox.setSelectedIndex(2); @@ -326,7 +327,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp FilesSet.Rule.ParentPathCondition pathCondition = rule.getPathCondition(); FilesSet.Rule.MimeTypeCondition mimeTypeCondition = rule.getMimeTypeCondition(); FilesSet.Rule.FileSizeCondition fileSizeCondition = rule.getFileSizeCondition(); - + FilesSet.Rule.DateCondition dateCondition = rule.getDateCondition(); // Populate the components that display the properties of the // selected rule. if (nameCondition != null) { @@ -372,7 +373,12 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp FilesSetDefsPanel.this.equalitySignComboBox.setSelectedIndex(2); FilesSetDefsPanel.this.fileSizeSpinner.setValue(0); } - + if (dateCondition != null){ + FilesSetDefsPanel.this.daysAgoTextField.setText(Integer.toString(dateCondition.getDaysAgo())); + } + else { + FilesSetDefsPanel.this.daysAgoTextField.setText(""); + } // Enable the new, edit and delete rule buttons. FilesSetDefsPanel.this.newRuleButton.setEnabled(true && canBeEnabled); FilesSetDefsPanel.this.editRuleButton.setEnabled(true && canBeEnabled); @@ -477,7 +483,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp if (selectedRule != null) { rules.remove(selectedRule.getUuid()); } - FilesSet.Rule newRule = new FilesSet.Rule(panel.getRuleName(), panel.getFileNameCondition(), panel.getMetaTypeCondition(), panel.getPathCondition(), panel.getMimeTypeCondition(), panel.getFileSizeCondition()); + FilesSet.Rule newRule = new FilesSet.Rule(panel.getRuleName(), panel.getFileNameCondition(), panel.getMetaTypeCondition(), panel.getPathCondition(), panel.getMimeTypeCondition(), panel.getFileSizeCondition(), panel.getDateCondition()); rules.put(newRule.getUuid(), newRule); // Add the new/edited files set definition, replacing any previous @@ -590,6 +596,9 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp copySetButton = new javax.swing.JButton(); importSetButton = new javax.swing.JButton(); exportSetButton = new javax.swing.JButton(); + modifiedDateLabel = new javax.swing.JLabel(); + daysAgoTextField = new javax.swing.JTextField(); + daysAgoLabel = new javax.swing.JLabel(); setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11)); @@ -841,6 +850,17 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp } }); + org.openide.awt.Mnemonics.setLocalizedText(modifiedDateLabel, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.modifiedDateLabel.text")); // NOI18N + + daysAgoTextField.setEditable(false); + daysAgoTextField.setHorizontalAlignment(javax.swing.JTextField.TRAILING); + daysAgoTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.daysAgoTextField.text")); // NOI18N + daysAgoTextField.setMinimumSize(new java.awt.Dimension(60, 20)); + daysAgoTextField.setPreferredSize(new java.awt.Dimension(60, 20)); + + org.openide.awt.Mnemonics.setLocalizedText(daysAgoLabel, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.daysAgoLabel.text")); // NOI18N + daysAgoLabel.setEnabled(false); + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( @@ -867,83 +887,75 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp .addComponent(setsListLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(separator, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(rulesListScrollPane, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(setDescScrollPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(101, 101, 101) + .addGap(16, 16, 16) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(jLabel7) + .addComponent(jLabel8) + .addComponent(jLabel2) + .addComponent(jLabel4) + .addComponent(modifiedDateLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(rulePathConditionTextField) + .addComponent(fileNameTextField, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(mimeTypeComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(fileSizeSpinner, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(fileNameRadioButton) + .addComponent(rulePathConditionRegexCheckBox) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(daysAgoTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(daysAgoLabel))) + .addGap(0, 0, Short.MAX_VALUE))))) + .addGap(8, 8, 8)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(rulesListLabel) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(ignoreKnownFilesCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ingoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 158, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel5) + .addComponent(jLabel6)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ingestWarningLabel)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(95, 95, 95) .addComponent(filesRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(dirsRadioButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(allRadioButton)) .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(105, 105, 105) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(fileNameRadioButton) - .addGap(4, 4, 4) - .addComponent(fileNameExtensionRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(fileNameRegexCheckbox)) - .addComponent(rulePathConditionRegexCheckBox))) + .addGap(174, 174, 174) + .addComponent(fileNameExtensionRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(fileNameRegexCheckbox)) + .addComponent(jLabel1) .addGroup(jPanel1Layout.createSequentialGroup() - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(rulesListLabel) - .addComponent(jLabel1) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(newRuleButton) - .addGap(18, 18, 18) - .addComponent(editRuleButton) - .addGap(18, 18, 18) - .addComponent(deleteRuleButton)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(ignoreKnownFilesCheckbox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(ingoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 158, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel5) - .addComponent(jLabel6)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(ingestWarningLabel))))) - .addGap(24, 28, Short.MAX_VALUE)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(22, 22, 22) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel7) - .addComponent(jLabel8)) - .addGap(18, 18, 18)) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel3) - .addComponent(jLabel2)) - .addGap(6, 6, 6)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() - .addComponent(jLabel4) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)))) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 44, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(fileSizeSpinner, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(rulePathConditionTextField) - .addComponent(fileNameTextField, javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(mimeTypeComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(rulesListScrollPane, javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(setDescScrollPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) - .addGap(8, 8, 8)))) + .addComponent(newRuleButton) + .addGap(18, 18, 18) + .addComponent(editRuleButton) + .addGap(18, 18, 18) + .addComponent(deleteRuleButton))) + .addGap(24, 28, Short.MAX_VALUE)))) ); jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {copySetButton, deleteSetButton, editSetButton, exportSetButton, importSetButton, newSetButton}); @@ -963,7 +975,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp .addGap(1, 1, 1)) .addComponent(ingestWarningLabel, javax.swing.GroupLayout.Alignment.TRAILING)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(setDescScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(setDescScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 45, Short.MAX_VALUE) .addGap(6, 6, 6) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(ignoreKnownFilesCheckbox) @@ -971,7 +983,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(rulesListLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(rulesListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 82, Short.MAX_VALUE) + .addComponent(rulesListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(newRuleButton) @@ -979,13 +991,13 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp .addComponent(deleteRuleButton)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel1) - .addGap(8, 8, 8) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel2) .addComponent(filesRadioButton) .addComponent(dirsRadioButton) .addComponent(allRadioButton)) - .addGap(8, 8, 8) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel3) .addComponent(fileNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) @@ -994,23 +1006,28 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp .addComponent(fileNameRadioButton) .addComponent(fileNameExtensionRadioButton) .addComponent(fileNameRegexCheckbox)) - .addGap(8, 8, 8) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel4) .addComponent(rulePathConditionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(6, 6, 6) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(rulePathConditionRegexCheckBox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel7) .addComponent(mimeTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel8) .addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(fileSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(5, 5, 5)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(modifiedDateLabel) + .addComponent(daysAgoTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(daysAgoLabel)) + .addContainerGap()) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -1262,6 +1279,8 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JRadioButton allRadioButton; private javax.swing.JButton copySetButton; + private javax.swing.JLabel daysAgoLabel; + private javax.swing.JTextField daysAgoTextField; private javax.swing.JButton deleteRuleButton; private javax.swing.JButton deleteSetButton; private javax.swing.JRadioButton dirsRadioButton; @@ -1294,6 +1313,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp private javax.swing.JScrollPane jScrollPane2; private javax.swing.JTextArea jTextArea1; private javax.swing.JComboBox mimeTypeComboBox; + private javax.swing.JLabel modifiedDateLabel; private javax.swing.JButton newRuleButton; private javax.swing.JButton newSetButton; private javax.swing.JCheckBox rulePathConditionRegexCheckBox; diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form index 4777c108b4..3d7513f6bc 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form @@ -23,82 +23,80 @@ - - + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - + - + @@ -106,17 +104,22 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + + @@ -134,7 +137,7 @@ - + @@ -146,7 +149,13 @@ - + + + + + + + @@ -170,9 +179,6 @@ - - - @@ -380,5 +386,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java index d70a5474ee..cbca5fd600 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014-2017 Basis Technology Corp. + * Copyright 2014-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.modules.interestingitems; import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.util.List; import java.util.SortedSet; import java.util.logging.Level; @@ -50,6 +49,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel { "FilesSetRulePanel.NoMimeTypeError=Please select a valid MIME type.", "FilesSetRulePanel.NoNameError=Name cannot be empty", "FilesSetRulePanel.NoPathError=Path cannot be empty", + "FilesSetRulePanel.DaysAgoEmptyError=Number of days ago cannot be empty.", + "FilesSetRulePanel.DaysAgoInvalidError=Number of days ago must be a positive integer.", "FilesSetRulePanel.ZeroFileSizeError=File size condition value must not be 0 (Unless = is selected)." }) @@ -82,6 +83,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } else { populateMimeTypesComboBox(); } + this.dateCheckActionPerformed(null); populateComponentsWithDefaultValues(); this.setButtons(okButton, cancelButton); } @@ -108,12 +110,14 @@ final class FilesSetRulePanel extends javax.swing.JPanel { populateMimeTypesComboBox(); populateMimeConditionComponents(rule); populateSizeConditionComponents(rule); + } populateMimeTypesComboBox(); populateRuleNameComponent(rule); populateTypeConditionComponents(rule); populateNameConditionComponents(rule); populatePathConditionComponents(rule); + populateDateConditionComponents(rule); this.setButtons(okButton, cancelButton); } @@ -176,7 +180,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { private void setOkButton() { if (this.okButton != null) { this.okButton.setEnabled(this.fileSizeCheck.isSelected() || this.mimeCheck.isSelected() - || this.nameCheck.isSelected() || this.pathCheck.isSelected()); + || this.nameCheck.isSelected() || this.pathCheck.isSelected() || this.dateCheck.isSelected()); } } @@ -274,6 +278,21 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } } + /** + * Populates the UI components that display the optional date condition for + * a rule. + * + * @param rule The files set rule to be edited. + */ + private void populateDateConditionComponents(FilesSet.Rule rule) { + FilesSet.Rule.DateCondition dateCondition = rule.getDateCondition(); + if (dateCondition != null) { + this.dateCheck.setSelected(true); + this.dateCheckActionPerformed(null); + this.daysAgoTextField.setText(Integer.toString(dateCondition.getDaysAgo())); + } + } + /** * Returns whether or not the data entered in the panel constitutes a valid * files set membership rule definition, displaying a dialog explaining the @@ -283,7 +302,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { */ boolean isValidRuleDefinition() { - if (!(this.mimeCheck.isSelected() || this.fileSizeCheck.isSelected() || this.pathCheck.isSelected() || this.nameCheck.isSelected())) { + if (!(this.mimeCheck.isSelected() || this.fileSizeCheck.isSelected() || this.pathCheck.isSelected() || this.nameCheck.isSelected() || this.dateCheck.isSelected())) { NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( Bundle.FilesSetRulePanel_NoConditionError(), NotifyDescriptor.WARNING_MESSAGE); @@ -367,6 +386,25 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } } + if (this.dateCheck.isSelected()) { + if (this.daysAgoTextField.getText().isEmpty()) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + Bundle.FilesSetRulePanel_DaysAgoEmptyError(), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } + try { + Integer.parseInt(daysAgoTextField.getText()); + } catch (NumberFormatException e) { + //field did not contain an integer + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + Bundle.FilesSetRulePanel_DaysAgoInvalidError(), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } + } return true; } @@ -504,6 +542,23 @@ final class FilesSetRulePanel extends javax.swing.JPanel { return condition; } + /** + * Gets the optional date condition for the rule that was created or edited. + * Should only be called if isValidDefintion() returns true. + * + * @return A date condition or null if no date condition was specified. + * + * @throws IllegalStateException if the specified date condition is not + * valid. + */ + FilesSet.Rule.DateCondition getDateCondition() { + FilesSet.Rule.DateCondition dateCondition = null; + if (!daysAgoTextField.getText().isEmpty()) { + dateCondition = new FilesSet.Rule.DateCondition(Integer.parseInt(daysAgoTextField.getText())); + } + return dateCondition; + } + /** * Checks an input string for the use of illegal characters. * @@ -582,15 +637,13 @@ final class FilesSetRulePanel extends javax.swing.JPanel { filesRadioButton = new javax.swing.JRadioButton(); dirsRadioButton = new javax.swing.JRadioButton(); allRadioButton = new javax.swing.JRadioButton(); + daysAgoTextField = new javax.swing.JTextField(); + daysAgoLabel = new javax.swing.JLabel(); + dateCheck = new javax.swing.JCheckBox(); org.openide.awt.Mnemonics.setLocalizedText(ruleNameLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.ruleNameLabel.text")); // NOI18N ruleNameTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.ruleNameTextField.text")); // NOI18N - ruleNameTextField.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - ruleNameTextFieldActionPerformed(evt); - } - }); org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.jLabel1.text")); // NOI18N @@ -685,85 +738,99 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } }); + daysAgoTextField.setEnabled(false); + daysAgoTextField.setMinimumSize(new java.awt.Dimension(60, 20)); + daysAgoTextField.setPreferredSize(new java.awt.Dimension(60, 20)); + + org.openide.awt.Mnemonics.setLocalizedText(daysAgoLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.daysAgoLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(dateCheck, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.dateCheck.text")); // NOI18N + dateCheck.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + dateCheckActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(8, 8, 8) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(ruleNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(ruleNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 234, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(ruleNameLabel) + .addGap(5, 5, 5) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(mimeTypeComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pathTextField) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(equalitySymbolComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(fileSizeSpinner) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(fileSizeComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(pathRegexCheckBox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pathSeparatorInfoLabel)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(daysAgoTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(daysAgoLabel)) + .addComponent(ruleNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 249, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(fullNameRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(extensionRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 98, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(nameRegexCheckbox))) + .addGap(1, 1, 1)))) + .addComponent(jLabel5) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel5) + .addComponent(nameCheck, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 95, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel1)) + .addGap(16, 16, 16) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(jLabel1) - .addGap(65, 65, 65) .addComponent(filesRadioButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(dirsRadioButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(allRadioButton))) - .addGap(0, 0, Short.MAX_VALUE)))) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(nameCheck) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 249, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addContainerGap() - .addComponent(pathCheck) - .addGap(4, 4, 4) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(pathRegexCheckBox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(pathSeparatorInfoLabel)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 250, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(layout.createSequentialGroup() - .addComponent(fullNameRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(extensionRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(nameRegexCheckbox) - .addGap(0, 0, Short.MAX_VALUE)))) + .addComponent(allRadioButton)) + .addComponent(nameTextField))))) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(pathCheck) .addComponent(mimeCheck) - .addComponent(fileSizeCheck)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(layout.createSequentialGroup() - .addComponent(equalitySymbolComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(18, 18, 18) - .addComponent(fileSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 94, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(18, 18, 18) - .addComponent(fileSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(mimeTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 250, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addComponent(fileSizeCheck) + .addComponent(dateCheck)) + .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jLabel5) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel1) - .addComponent(filesRadioButton) - .addComponent(dirsRadioButton) - .addComponent(allRadioButton)) - .addGap(5, 5, 5) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(nameCheck)) + .addGap(3, 3, 3) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addGap(10, 10, 10) + .addComponent(nameCheck)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(filesRadioButton) + .addComponent(dirsRadioButton) + .addComponent(allRadioButton)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(fullNameRadioButton) @@ -777,7 +844,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(pathRegexCheckBox) .addComponent(pathSeparatorInfoLabel)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 8, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(mimeTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(mimeCheck)) @@ -787,7 +854,12 @@ final class FilesSetRulePanel extends javax.swing.JPanel { .addComponent(fileSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(fileSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(fileSizeCheck)) - .addGap(15, 15, 15) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(daysAgoTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(daysAgoLabel) + .addComponent(dateCheck)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(ruleNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(ruleNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) @@ -795,10 +867,6 @@ final class FilesSetRulePanel extends javax.swing.JPanel { ); }// //GEN-END:initComponents - private void ruleNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ruleNameTextFieldActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_ruleNameTextFieldActionPerformed - private void nameCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nameCheckActionPerformed if (!this.nameCheck.isSelected()) { this.nameTextField.setEnabled(false); @@ -831,15 +899,30 @@ final class FilesSetRulePanel extends javax.swing.JPanel { this.setOkButton(); }//GEN-LAST:event_pathCheckActionPerformed - private void mimeCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mimeCheckActionPerformed - if (!this.mimeCheck.isSelected()) { - this.mimeTypeComboBox.setEnabled(false); - this.mimeTypeComboBox.setSelectedIndex(0); + private void filesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_filesRadioButtonActionPerformed + + this.setComponentsForSearchType(); + }//GEN-LAST:event_filesRadioButtonActionPerformed + + private void dirsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dirsRadioButtonActionPerformed + this.setComponentsForSearchType(); + }//GEN-LAST:event_dirsRadioButtonActionPerformed + + private void allRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allRadioButtonActionPerformed + this.setComponentsForSearchType(); + }//GEN-LAST:event_allRadioButtonActionPerformed + + private void dateCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dateCheckActionPerformed + if (!this.dateCheck.isSelected()) { + this.daysAgoTextField.setEnabled(false); + this.daysAgoLabel.setEnabled(false); + this.daysAgoTextField.setText(""); } else { - this.mimeTypeComboBox.setEnabled(true); + this.daysAgoTextField.setEnabled(true); + this.daysAgoLabel.setEnabled(true); } this.setOkButton(); - }//GEN-LAST:event_mimeCheckActionPerformed + }//GEN-LAST:event_dateCheckActionPerformed private void fileSizeCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileSizeCheckActionPerformed if (!this.fileSizeCheck.isSelected()) { @@ -855,21 +938,21 @@ final class FilesSetRulePanel extends javax.swing.JPanel { this.setOkButton(); }//GEN-LAST:event_fileSizeCheckActionPerformed - private void filesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_filesRadioButtonActionPerformed - - this.setComponentsForSearchType(); - }//GEN-LAST:event_filesRadioButtonActionPerformed - - private void dirsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dirsRadioButtonActionPerformed - this.setComponentsForSearchType(); - }//GEN-LAST:event_dirsRadioButtonActionPerformed - - private void allRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allRadioButtonActionPerformed - this.setComponentsForSearchType(); - }//GEN-LAST:event_allRadioButtonActionPerformed + private void mimeCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mimeCheckActionPerformed + if (!this.mimeCheck.isSelected()) { + this.mimeTypeComboBox.setEnabled(false); + this.mimeTypeComboBox.setSelectedIndex(0); + } else { + this.mimeTypeComboBox.setEnabled(true); + } + this.setOkButton(); + }//GEN-LAST:event_mimeCheckActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JRadioButton allRadioButton; + private javax.swing.JCheckBox dateCheck; + private javax.swing.JLabel daysAgoLabel; + private javax.swing.JTextField daysAgoTextField; private javax.swing.JRadioButton dirsRadioButton; private javax.swing.JComboBox equalitySymbolComboBox; private javax.swing.JRadioButton extensionRadioButton; diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetsManager.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetsManager.java index 6350805ee6..8397d77c72 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetsManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetsManager.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2014-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -52,7 +52,7 @@ public final class FilesSetsManager extends Observable { { put(Bundle.FilesSetsManager_allFilesAndDirectories(), new Rule(Bundle.FilesSetsManager_allFilesAndDirectories(), null, - new MetaTypeCondition(MetaTypeCondition.Type.ALL), null, null, null)); + new MetaTypeCondition(MetaTypeCondition.Type.ALL), null, null, null, null)); } }); private static final FilesSet FILES_DIRS_UNALLOC_INGEST_FILTER = new FilesSet( @@ -61,7 +61,7 @@ public final class FilesSetsManager extends Observable { { put(Bundle.FilesSetsManager_allFilesDirectoriesAndUnallocated(), new Rule(Bundle.FilesSetsManager_allFilesDirectoriesAndUnallocated(), null, - new MetaTypeCondition(MetaTypeCondition.Type.ALL), null, null, null)); + new MetaTypeCondition(MetaTypeCondition.Type.ALL), null, null, null, null)); } }); diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java index de88aee68e..d9a7393a95 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,6 +44,7 @@ import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.FileSizeCond import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.MetaTypeCondition; import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.MimeTypeCondition; import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.ParentPathCondition; +import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.DateCondition; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -67,6 +68,7 @@ class InterestingItemsFilesSetSettings implements Serializable { private static final String FILE_SET_TAG = "INTERESTING_FILE_SET"; //NON-NLS private static final String NAME_RULE_TAG = "NAME"; //NON-NLS private static final String NAME_ATTR = "name"; //NON-NLS + private static final String DAYS_AGO_ATTR = "daysAgo"; private static final String MIME_ATTR = "mimeType"; private static final String FS_COMPARATOR_ATTR = "comparatorSymbol"; private static final String FS_SIZE_ATTR = "sizeValue"; @@ -166,6 +168,35 @@ class InterestingItemsFilesSetSettings implements Serializable { return pathCondition; } + /** + * Construct a date condition for a FilesSet membership rule from data in an + * XML element. + * + * @param ruleElement The XML element. + * + * @return The date condition, or null if there is an error (logged). + * + * @throws + * org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException + */ + private static DateCondition readDateCondition(Element ruleElement) throws FilesSetsManager.FilesSetsManagerException { + // Read in the optional path condition. Null is o.k., but if the attribute + // is there, be sure it is not malformed. + DateCondition dateCondition = null; + if (!ruleElement.getAttribute(DAYS_AGO_ATTR).isEmpty()) { + String daysAgo = ruleElement.getAttribute(DAYS_AGO_ATTR); + if (!daysAgo.isEmpty()) { + try { + dateCondition = new DateCondition(Integer.parseInt(daysAgo)); + } catch (NumberFormatException ex) { + logger.log(Level.SEVERE, "Error creating condition for " + daysAgo + ", ignoring malformed date condition definition", ex); // NON-NLS + throw new FilesSetsManager.FilesSetsManagerException(String.format("error compiling %s regex", DAYS_AGO_ATTR), ex); + } + } + } + return dateCondition; + } + /** * Attempts to compile a regular expression. * @@ -183,12 +214,13 @@ class InterestingItemsFilesSetSettings implements Serializable { } /** - * Construct a fileset membership rule from the data in an xml element for + * Construct a fileset membership rule from the data in an xml element for * use in a FilesSet. * * @param elem The XML element. * - * @return A file set constructed from the conditions available in the XML element + * @return A file set constructed from the conditions available in the XML + * element * * @throws * org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSetsManagerException @@ -200,17 +232,17 @@ class InterestingItemsFilesSetSettings implements Serializable { ParentPathCondition pathCondition = readPathCondition(elem); MimeTypeCondition mimeCondition = readMimeCondition(elem); FileSizeCondition sizeCondition = readSizeCondition(elem); - //if meta type condition or all four types of conditions the user can create are all null then don't make the rule - if (metaCondition == null || (nameCondition == null && pathCondition == null && mimeCondition == null && sizeCondition == null)) { + DateCondition dateCondition = readDateCondition(elem); //if meta type condition or all four types of conditions the user can create are all null then don't make the rule + if (metaCondition == null || (nameCondition == null && pathCondition == null && mimeCondition == null && sizeCondition == null && dateCondition == null)) { logger.log(Level.WARNING, "Error Reading Rule, " + ruleName + " was either missing a meta condition or contained only a meta condition. No rule was imported."); // NON-NLS throw new FilesSetsManager.FilesSetsManagerException(String.format("Invalid Rule in FilesSet xml, missing necessary conditions for %s", ruleName)); } - return new FilesSet.Rule(ruleName, nameCondition, metaCondition, pathCondition, mimeCondition, sizeCondition); + return new FilesSet.Rule(ruleName, nameCondition, metaCondition, pathCondition, mimeCondition, sizeCondition, dateCondition); } /** - * Construct a file name condition for a FilesSet membership rule from data in an - * XML element. + * Construct a file name condition for a FilesSet membership rule from data + * in an XML element. * * @param ruleElement The XML element. * @@ -256,8 +288,8 @@ class InterestingItemsFilesSetSettings implements Serializable { } /** - * Construct a MIME type condition for a FilesSet membership rule from data in an - * XML element. + * Construct a MIME type condition for a FilesSet membership rule from data + * in an XML element. * * @param ruleElement The XML element. * @@ -275,8 +307,8 @@ class InterestingItemsFilesSetSettings implements Serializable { } /** - * Construct a file size condition for a FilesSet membership rule from data in an - * XML element. + * Construct a file size condition for a FilesSet membership rule from data + * in an XML element. * * @param ruleElement The XML element. * From 1bee51ee593e0e45eddf7bd9e6fccbe767ed1e10 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 31 Jan 2018 14:00:11 -0500 Subject: [PATCH 05/15] 3445 adjust date filter gui changes --- .../interestingitems/FilesSetDefsPanel.form | 17 ++++++++--------- .../interestingitems/FilesSetDefsPanel.java | 17 ++++++++--------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form index 02d4cec624..e4d5d64d47 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form @@ -127,6 +127,13 @@ + + + + + + + @@ -151,14 +158,6 @@ - - - - - - - - @@ -426,7 +425,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java index 4afdf6d91e..0834698a65 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java @@ -652,7 +652,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp setDescriptionTextArea.setColumns(20); setDescriptionTextArea.setFont(setDescriptionTextArea.getFont().deriveFont(setDescriptionTextArea.getFont().getStyle() & ~java.awt.Font.BOLD, 13)); setDescriptionTextArea.setLineWrap(true); - setDescriptionTextArea.setRows(10); + setDescriptionTextArea.setRows(8); setDescriptionTextArea.setMinimumSize(new java.awt.Dimension(10, 22)); setDescScrollPanel.setViewportView(setDescriptionTextArea); @@ -920,7 +920,13 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(daysAgoTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(daysAgoLabel))) + .addComponent(daysAgoLabel)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(filesRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(dirsRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(allRadioButton))) .addGap(0, 0, Short.MAX_VALUE))))) .addGap(8, 8, 8)) .addGroup(jPanel1Layout.createSequentialGroup() @@ -936,13 +942,6 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp .addComponent(jLabel6)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(ingestWarningLabel)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(95, 95, 95) - .addComponent(filesRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(dirsRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(allRadioButton)) .addGroup(jPanel1Layout.createSequentialGroup() .addGap(174, 174, 174) .addComponent(fileNameExtensionRadioButton) From 8e0354d9005f4c95b16efda0916b6267bfd1bab0 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 31 Jan 2018 14:24:11 -0500 Subject: [PATCH 06/15] 3445 adjust sizing of FilesSetDefsPanel elements after Date filter changes --- .../modules/interestingitems/FilesSetDefsPanel.form | 8 ++++---- .../modules/interestingitems/FilesSetDefsPanel.java | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form index e4d5d64d47..2658d8c167 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form @@ -196,8 +196,8 @@ - - + + @@ -205,7 +205,7 @@ - + @@ -425,7 +425,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java index 0834698a65..ec610d6ff1 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java @@ -652,7 +652,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp setDescriptionTextArea.setColumns(20); setDescriptionTextArea.setFont(setDescriptionTextArea.getFont().deriveFont(setDescriptionTextArea.getFont().getStyle() & ~java.awt.Font.BOLD, 13)); setDescriptionTextArea.setLineWrap(true); - setDescriptionTextArea.setRows(8); + setDescriptionTextArea.setRows(6); setDescriptionTextArea.setMinimumSize(new java.awt.Dimension(10, 22)); setDescScrollPanel.setViewportView(setDescriptionTextArea); @@ -974,15 +974,15 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp .addGap(1, 1, 1)) .addComponent(ingestWarningLabel, javax.swing.GroupLayout.Alignment.TRAILING)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(setDescScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 45, Short.MAX_VALUE) - .addGap(6, 6, 6) + .addComponent(setDescScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 69, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(ignoreKnownFilesCheckbox) .addComponent(ingoreUnallocCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(rulesListLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(rulesListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(rulesListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(newRuleButton) From e1cc0e7859a1e2dc2a17b73d6ad918fa800963a1 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 31 Jan 2018 14:47:18 -0500 Subject: [PATCH 07/15] 3445 refactor variable and method names for Date Filter option --- .../interestingitems/Bundle.properties | 6 +-- .../modules/interestingitems/FilesSet.java | 14 ++--- .../interestingitems/FilesSetDefsPanel.form | 16 +++--- .../interestingitems/FilesSetDefsPanel.java | 36 ++++++------- .../interestingitems/FilesSetRulePanel.form | 14 ++--- .../interestingitems/FilesSetRulePanel.java | 52 +++++++++---------- .../InterestingItemsFilesSetSettings.java | 14 ++--- 7 files changed, 76 insertions(+), 76 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties index 0a415c8ca8..830901a6d9 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties @@ -78,9 +78,9 @@ FilesSetDefsPanel.ingoreUnallocCheckbox.toolTipText=Ignores unallocated space, s FilesSetDefsPanel.ingestWarningLabel.text=Ingest is ongoing, some settings will be unavailable until it finishes. FilesSetDefsPanel.allRadioButton.text=All FilesSetRulePanel.dateCheck.text=Modified Within: -FilesSetRulePanel.daysAgoLabel.text=day(s) FilesSetRulePanel.fileSizeCheck.text=File Size: FilesSetRulePanel.mimeCheck.text=MIME Type: -FilesSetDefsPanel.daysAgoTextField.text= FilesSetDefsPanel.modifiedDateLabel.text=Modified Within: -FilesSetDefsPanel.daysAgoLabel.text=day(s) +FilesSetDefsPanel.daysIncludedTextField.text= +FilesSetDefsPanel.daysIncludedLabel.text=day(s) +FilesSetRulePanel.daysIncludedLabel.text=day(s) diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java index 913db37528..94697d4fc6 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java @@ -283,7 +283,7 @@ public final class FilesSet implements Serializable { } @NbBundle.Messages({ - "# {0} - daysAgo", + "# {0} - daysIncluded", "FilesSet.rule.dateRule.toString=(modified within {0} day(s))" }) @Override @@ -300,7 +300,7 @@ public final class FilesSet implements Serializable { return this.ruleName + " (" + fileSizeCondition.getComparator().getSymbol() + " " + fileSizeCondition.getSizeValue() + " " + fileSizeCondition.getUnit().getName() + ")"; } else if (this.dateCondition != null) { - return this.ruleName + Bundle.FilesSet_rule_dateRule_toString(dateCondition.getDaysAgo()); + return this.ruleName + Bundle.FilesSet_rule_dateRule_toString(dateCondition.getDaysIncluded()); } else { return this.ruleName + " ()"; } @@ -763,7 +763,7 @@ public final class FilesSet implements Serializable { private final static long DAY_IN_S = 60 * 60 * 24; - private int daysAgo; + private int daysIncluded; /** * Construct a new DateCondition @@ -772,7 +772,7 @@ public final class FilesSet implements Serializable { * number of days will pass */ DateCondition(int days) { - daysAgo = days; + daysIncluded = days; } /** @@ -780,13 +780,13 @@ public final class FilesSet implements Serializable { * * @return integer value of the number days which will pass */ - int getDaysAgo() { - return daysAgo; + int getDaysIncluded() { + return daysIncluded; } @Override public boolean passes(AbstractFile file) { - long dateThreshold = System.currentTimeMillis() / 1000 - daysAgo * DAY_IN_S; + long dateThreshold = System.currentTimeMillis() / 1000 - daysIncluded * DAY_IN_S; if (file.getCrtime() > dateThreshold || file.getMtime() > dateThreshold) { return true; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form index 2658d8c167..4d8f94589f 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.form @@ -123,9 +123,9 @@ - + - + @@ -254,8 +254,8 @@ - - + + @@ -991,12 +991,12 @@ - + - + @@ -1006,10 +1006,10 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java index ec610d6ff1..4fd933b167 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetDefsPanel.java @@ -251,7 +251,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp this.fileNameRegexCheckbox.setSelected(false); this.filesRadioButton.setSelected(true); this.rulePathConditionTextField.setText(""); - this.daysAgoTextField.setText(""); + this.daysIncludedTextField.setText(""); this.rulePathConditionRegexCheckBox.setSelected(false); this.mimeTypeComboBox.setSelectedIndex(0); this.equalitySignComboBox.setSelectedIndex(2); @@ -374,10 +374,10 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp FilesSetDefsPanel.this.fileSizeSpinner.setValue(0); } if (dateCondition != null){ - FilesSetDefsPanel.this.daysAgoTextField.setText(Integer.toString(dateCondition.getDaysAgo())); + FilesSetDefsPanel.this.daysIncludedTextField.setText(Integer.toString(dateCondition.getDaysIncluded())); } else { - FilesSetDefsPanel.this.daysAgoTextField.setText(""); + FilesSetDefsPanel.this.daysIncludedTextField.setText(""); } // Enable the new, edit and delete rule buttons. FilesSetDefsPanel.this.newRuleButton.setEnabled(true && canBeEnabled); @@ -597,8 +597,8 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp importSetButton = new javax.swing.JButton(); exportSetButton = new javax.swing.JButton(); modifiedDateLabel = new javax.swing.JLabel(); - daysAgoTextField = new javax.swing.JTextField(); - daysAgoLabel = new javax.swing.JLabel(); + daysIncludedTextField = new javax.swing.JTextField(); + daysIncludedLabel = new javax.swing.JLabel(); setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11)); @@ -852,14 +852,14 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp org.openide.awt.Mnemonics.setLocalizedText(modifiedDateLabel, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.modifiedDateLabel.text")); // NOI18N - daysAgoTextField.setEditable(false); - daysAgoTextField.setHorizontalAlignment(javax.swing.JTextField.TRAILING); - daysAgoTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.daysAgoTextField.text")); // NOI18N - daysAgoTextField.setMinimumSize(new java.awt.Dimension(60, 20)); - daysAgoTextField.setPreferredSize(new java.awt.Dimension(60, 20)); + daysIncludedTextField.setEditable(false); + daysIncludedTextField.setHorizontalAlignment(javax.swing.JTextField.TRAILING); + daysIncludedTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.daysIncludedTextField.text")); // NOI18N + daysIncludedTextField.setMinimumSize(new java.awt.Dimension(60, 20)); + daysIncludedTextField.setPreferredSize(new java.awt.Dimension(60, 20)); - org.openide.awt.Mnemonics.setLocalizedText(daysAgoLabel, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.daysAgoLabel.text")); // NOI18N - daysAgoLabel.setEnabled(false); + org.openide.awt.Mnemonics.setLocalizedText(daysIncludedLabel, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.daysIncludedLabel.text")); // NOI18N + daysIncludedLabel.setEnabled(false); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); @@ -918,9 +918,9 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp .addComponent(fileNameRadioButton) .addComponent(rulePathConditionRegexCheckBox) .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(daysAgoTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(daysAgoLabel)) + .addComponent(daysIncludedLabel)) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(filesRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) @@ -1024,8 +1024,8 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(modifiedDateLabel) - .addComponent(daysAgoTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(daysAgoLabel)) + .addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(daysIncludedLabel)) .addContainerGap()) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) @@ -1278,8 +1278,8 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JRadioButton allRadioButton; private javax.swing.JButton copySetButton; - private javax.swing.JLabel daysAgoLabel; - private javax.swing.JTextField daysAgoTextField; + private javax.swing.JLabel daysIncludedLabel; + private javax.swing.JTextField daysIncludedTextField; private javax.swing.JButton deleteRuleButton; private javax.swing.JButton deleteSetButton; private javax.swing.JRadioButton dirsRadioButton; diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form index 3d7513f6bc..b91bb34d36 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form @@ -48,9 +48,9 @@ - + - + @@ -151,8 +151,8 @@ - - + + @@ -386,7 +386,7 @@ - + @@ -397,10 +397,10 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java index cbca5fd600..bead96c5ed 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java @@ -49,8 +49,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel { "FilesSetRulePanel.NoMimeTypeError=Please select a valid MIME type.", "FilesSetRulePanel.NoNameError=Name cannot be empty", "FilesSetRulePanel.NoPathError=Path cannot be empty", - "FilesSetRulePanel.DaysAgoEmptyError=Number of days ago cannot be empty.", - "FilesSetRulePanel.DaysAgoInvalidError=Number of days ago must be a positive integer.", + "FilesSetRulePanel.DaysIncludedEmptyError=Number of days included cannot be empty.", + "FilesSetRulePanel.DaysIncludedInvalidError=Number of days included must be a positive integer.", "FilesSetRulePanel.ZeroFileSizeError=File size condition value must not be 0 (Unless = is selected)." }) @@ -289,7 +289,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { if (dateCondition != null) { this.dateCheck.setSelected(true); this.dateCheckActionPerformed(null); - this.daysAgoTextField.setText(Integer.toString(dateCondition.getDaysAgo())); + this.daysIncludedTextField.setText(Integer.toString(dateCondition.getDaysIncluded())); } } @@ -387,19 +387,19 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } if (this.dateCheck.isSelected()) { - if (this.daysAgoTextField.getText().isEmpty()) { + if (this.daysIncludedTextField.getText().isEmpty()) { NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( - Bundle.FilesSetRulePanel_DaysAgoEmptyError(), + Bundle.FilesSetRulePanel_DaysIncludedEmptyError(), NotifyDescriptor.WARNING_MESSAGE); DialogDisplayer.getDefault().notify(notifyDesc); return false; } try { - Integer.parseInt(daysAgoTextField.getText()); + Integer.parseInt(daysIncludedTextField.getText()); } catch (NumberFormatException e) { //field did not contain an integer NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( - Bundle.FilesSetRulePanel_DaysAgoInvalidError(), + Bundle.FilesSetRulePanel_DaysIncludedInvalidError(), NotifyDescriptor.WARNING_MESSAGE); DialogDisplayer.getDefault().notify(notifyDesc); return false; @@ -553,8 +553,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel { */ FilesSet.Rule.DateCondition getDateCondition() { FilesSet.Rule.DateCondition dateCondition = null; - if (!daysAgoTextField.getText().isEmpty()) { - dateCondition = new FilesSet.Rule.DateCondition(Integer.parseInt(daysAgoTextField.getText())); + if (!daysIncludedTextField.getText().isEmpty()) { + dateCondition = new FilesSet.Rule.DateCondition(Integer.parseInt(daysIncludedTextField.getText())); } return dateCondition; } @@ -637,8 +637,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel { filesRadioButton = new javax.swing.JRadioButton(); dirsRadioButton = new javax.swing.JRadioButton(); allRadioButton = new javax.swing.JRadioButton(); - daysAgoTextField = new javax.swing.JTextField(); - daysAgoLabel = new javax.swing.JLabel(); + daysIncludedTextField = new javax.swing.JTextField(); + daysIncludedLabel = new javax.swing.JLabel(); dateCheck = new javax.swing.JCheckBox(); org.openide.awt.Mnemonics.setLocalizedText(ruleNameLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.ruleNameLabel.text")); // NOI18N @@ -738,11 +738,11 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } }); - daysAgoTextField.setEnabled(false); - daysAgoTextField.setMinimumSize(new java.awt.Dimension(60, 20)); - daysAgoTextField.setPreferredSize(new java.awt.Dimension(60, 20)); + daysIncludedTextField.setEnabled(false); + daysIncludedTextField.setMinimumSize(new java.awt.Dimension(60, 20)); + daysIncludedTextField.setPreferredSize(new java.awt.Dimension(60, 20)); - org.openide.awt.Mnemonics.setLocalizedText(daysAgoLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.daysAgoLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(daysIncludedLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.daysIncludedLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(dateCheck, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.dateCheck.text")); // NOI18N dateCheck.addActionListener(new java.awt.event.ActionListener() { @@ -779,9 +779,9 @@ final class FilesSetRulePanel extends javax.swing.JPanel { .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(daysAgoTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(daysAgoLabel)) + .addComponent(daysIncludedLabel)) .addComponent(ruleNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 249, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(fullNameRadioButton) @@ -856,8 +856,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel { .addComponent(fileSizeCheck)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(daysAgoTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(daysAgoLabel) + .addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(daysIncludedLabel) .addComponent(dateCheck)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) @@ -914,12 +914,12 @@ final class FilesSetRulePanel extends javax.swing.JPanel { private void dateCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dateCheckActionPerformed if (!this.dateCheck.isSelected()) { - this.daysAgoTextField.setEnabled(false); - this.daysAgoLabel.setEnabled(false); - this.daysAgoTextField.setText(""); + this.daysIncludedTextField.setEnabled(false); + this.daysIncludedLabel.setEnabled(false); + this.daysIncludedTextField.setText(""); } else { - this.daysAgoTextField.setEnabled(true); - this.daysAgoLabel.setEnabled(true); + this.daysIncludedTextField.setEnabled(true); + this.daysIncludedLabel.setEnabled(true); } this.setOkButton(); }//GEN-LAST:event_dateCheckActionPerformed @@ -951,8 +951,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JRadioButton allRadioButton; private javax.swing.JCheckBox dateCheck; - private javax.swing.JLabel daysAgoLabel; - private javax.swing.JTextField daysAgoTextField; + private javax.swing.JLabel daysIncludedLabel; + private javax.swing.JTextField daysIncludedTextField; private javax.swing.JRadioButton dirsRadioButton; private javax.swing.JComboBox equalitySymbolComboBox; private javax.swing.JRadioButton extensionRadioButton; diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java index d9a7393a95..0e1bfff033 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java @@ -68,7 +68,7 @@ class InterestingItemsFilesSetSettings implements Serializable { private static final String FILE_SET_TAG = "INTERESTING_FILE_SET"; //NON-NLS private static final String NAME_RULE_TAG = "NAME"; //NON-NLS private static final String NAME_ATTR = "name"; //NON-NLS - private static final String DAYS_AGO_ATTR = "daysAgo"; + private static final String DAYS_INCLUDED_ATTR = "daysIncluded"; private static final String MIME_ATTR = "mimeType"; private static final String FS_COMPARATOR_ATTR = "comparatorSymbol"; private static final String FS_SIZE_ATTR = "sizeValue"; @@ -183,14 +183,14 @@ class InterestingItemsFilesSetSettings implements Serializable { // Read in the optional path condition. Null is o.k., but if the attribute // is there, be sure it is not malformed. DateCondition dateCondition = null; - if (!ruleElement.getAttribute(DAYS_AGO_ATTR).isEmpty()) { - String daysAgo = ruleElement.getAttribute(DAYS_AGO_ATTR); - if (!daysAgo.isEmpty()) { + if (!ruleElement.getAttribute(DAYS_INCLUDED_ATTR).isEmpty()) { + String daysIncluded = ruleElement.getAttribute(DAYS_INCLUDED_ATTR); + if (!daysIncluded.isEmpty()) { try { - dateCondition = new DateCondition(Integer.parseInt(daysAgo)); + dateCondition = new DateCondition(Integer.parseInt(daysIncluded)); } catch (NumberFormatException ex) { - logger.log(Level.SEVERE, "Error creating condition for " + daysAgo + ", ignoring malformed date condition definition", ex); // NON-NLS - throw new FilesSetsManager.FilesSetsManagerException(String.format("error compiling %s regex", DAYS_AGO_ATTR), ex); + logger.log(Level.SEVERE, "Error creating condition for " + daysIncluded + ", ignoring malformed date condition definition", ex); // NON-NLS + throw new FilesSetsManager.FilesSetsManagerException(String.format("error compiling %s regex", DAYS_INCLUDED_ATTR), ex); } } } From e03173c46bf247b9c95b6a038f39b3ac5a0e677b Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 9 Feb 2018 12:26:48 -0500 Subject: [PATCH 08/15] 3445 make Date Filter condition reject negative day value --- .../autopsy/modules/interestingitems/FilesSetRulePanel.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java index bead96c5ed..4965652c5f 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java @@ -395,7 +395,10 @@ final class FilesSetRulePanel extends javax.swing.JPanel { return false; } try { - Integer.parseInt(daysIncludedTextField.getText()); + int value = Integer.parseInt(daysIncludedTextField.getText()); + if (value < 0) { + throw new NumberFormatException("Negative numbers are not allowed for the within N days condition"); + } } catch (NumberFormatException e) { //field did not contain an integer NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( From a7ef9f7e54d5bc7c255d34915389dc8f368ef606 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 9 Feb 2018 12:30:42 -0500 Subject: [PATCH 09/15] 3445 rename varialbe DAY_IN_S to SECS_PER_DAY for clarity --- .../sleuthkit/autopsy/modules/interestingitems/FilesSet.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java index 94697d4fc6..3a3e9b2360 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java @@ -761,7 +761,7 @@ public final class FilesSet implements Serializable { */ static final class DateCondition implements FileAttributeCondition { - private final static long DAY_IN_S = 60 * 60 * 24; + private final static long SECS_PER_DAY = 60 * 60 * 24; private int daysIncluded; @@ -786,7 +786,7 @@ public final class FilesSet implements Serializable { @Override public boolean passes(AbstractFile file) { - long dateThreshold = System.currentTimeMillis() / 1000 - daysIncluded * DAY_IN_S; + long dateThreshold = System.currentTimeMillis() / 1000 - daysIncluded * SECS_PER_DAY; if (file.getCrtime() > dateThreshold || file.getMtime() > dateThreshold) { return true; } From 1621cd5d43fccad3669eaf50ed770c8cf0fb8ddf Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 9 Feb 2018 14:23:39 -0500 Subject: [PATCH 10/15] Partial changes. --- .../keywordsearch/ExtractedContentViewer.java | 194 ++++++++---------- .../keywordsearch/HighlightedText.java | 6 +- .../KeywordSearchFilterNode.java | 10 +- .../KeywordSearchResultFactory.java | 28 +-- 4 files changed, 106 insertions(+), 132 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java index 43f0d7baf8..b8fef30f01 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java @@ -27,13 +27,14 @@ import java.util.Collection; import java.util.List; import java.util.logging.Level; import org.openide.nodes.Node; +import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.QueryContent; +import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.AdHocQueryResult; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -51,7 +52,7 @@ import org.sleuthkit.datamodel.TskCoreException; @ServiceProvider(service = DataContentViewer.class, position = 4) public class ExtractedContentViewer implements DataContentViewer { - private static final Logger LOGGER = Logger.getLogger(ExtractedContentViewer.class.getName()); + private static final Logger logger = Logger.getLogger(ExtractedContentViewer.class.getName()); private static final long INVALID_DOCUMENT_ID = 0L; private static final BlackboardAttribute.Type TSK_ASSOCIATED_ARTIFACT_TYPE = new BlackboardAttribute.Type(TSK_ASSOCIATED_ARTIFACT); @@ -93,9 +94,6 @@ public class ExtractedContentViewer implements DataContentViewer { currentNode = node; } - Lookup nodeLookup = node.getLookup(); - AbstractFile content = nodeLookup.lookup(AbstractFile.class); - /* * Assemble a collection of all of the indexed text "sources" for the * node. @@ -104,44 +102,37 @@ public class ExtractedContentViewer implements DataContentViewer { IndexedText highlightedHitText = null; IndexedText rawContentText = null; - if (null != content && solrHasContent(content.getId())) { - /* - * Results for Keyword Hits. - */ - BlackboardArtifact artifact = nodeLookup.lookup(BlackboardArtifact.class); - if (artifact != null) { - if (artifact.getArtifactTypeID() == TSK_ACCOUNT.getTypeID()) { - try { - /* - * Generate AccountsText for the account artifact. - */ - highlightedHitText = getAccountsText(content, nodeLookup); - } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Failed to create AccountsText for " + content, ex); //NON-NLS - } - } else if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) { - try { - /* - * Generate HighlightedText for the keyword hit artifact. - */ - highlightedHitText = new HighlightedText(artifact); - } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Failed to create HighlightedText for " + artifact, ex); //NON-NLS - } + Lookup nodeLookup = node.getLookup(); + + AdHocQueryResult adHocQueryResult = nodeLookup.lookup(AdHocQueryResult.class); + BlackboardArtifact artifact = nodeLookup.lookup(BlackboardArtifact.class); + AbstractFile content = nodeLookup.lookup(AbstractFile.class); + + if (adHocQueryResult != null) { + highlightedHitText = new HighlightedText(adHocQueryResult.getSolrObjectId(), adHocQueryResult.getResults()); + } else if (artifact != null) { + if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) { + try { + highlightedHitText = new HighlightedText(artifact); + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); + } + } else if (artifact.getArtifactTypeID() == TSK_ACCOUNT.getTypeID() && content != null) { + try { + highlightedHitText = getAccountsText(content, nodeLookup); + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); } } - } else { - /* - * Results for ad-hoc search. - */ - QueryContent queryContent = nodeLookup.lookup(QueryContent.class); - content = (AbstractFile) queryContent.getContent(); - - if (null != content && solrHasContent(content.getId())) { - QueryResults queryResults = queryContent.getResults(); - if (queryResults != null) { - highlightedHitText = new HighlightedText(queryContent.getSolrObjectId(), queryResults); - } + } + + if (content != null) { + rawContentText = new RawText(content, content.getId()); + } else if (artifact != null) { + try { + rawContentText = getRawArtifactText(nodeLookup); + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); } } @@ -150,11 +141,10 @@ public class ExtractedContentViewer implements DataContentViewer { } /* - * Next, add the "raw" (not highlighted) text, if any, for any - * content associated with the node. + * Next, add the "raw" (not highlighted) text, if any, for any content + * associated with the node. */ - if (content != null) { - rawContentText = new RawText(content, content.getId()); + if (rawContentText != null) { sources.add(rawContentText); } @@ -166,7 +156,7 @@ public class ExtractedContentViewer implements DataContentViewer { try { rawArtifactText = getRawArtifactText(nodeLookup); } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Error creating RawText for " + content, ex); //NON-NLS + logger.log(Level.SEVERE, "Error creating RawText for " + content, ex); //NON-NLS } if (rawArtifactText != null) { @@ -289,6 +279,11 @@ public class ExtractedContentViewer implements DataContentViewer { return false; } + AdHocQueryResult adHocQueryResult = node.getLookup().lookup(AdHocQueryResult.class); + if (adHocQueryResult != null) { + return true; + } + /* * Is there a credit card or keyword hit artifact in the lookup */ @@ -296,26 +291,63 @@ public class ExtractedContentViewer implements DataContentViewer { if (artifacts != null) { for (BlackboardArtifact art : artifacts) { final int artifactTypeID = art.getArtifactTypeID(); - if (artifactTypeID == TSK_ACCOUNT.getTypeID()) { + if (artifactTypeID == TSK_KEYWORD_HIT.getTypeID()) { + return true; + } else if (artifactTypeID == TSK_ACCOUNT.getTypeID()) { try { BlackboardAttribute attribute = art.getAttribute(TSK_ACCOUNT_TYPE); if (attribute != null && Account.Type.CREDIT_CARD.getTypeName().equals(attribute.getValueString())) { return true; } } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Error getting TSK_ACCOUNT_TYPE attribute from artifact " + art.getArtifactID(), ex); + logger.log(Level.SEVERE, "Error getting TSK_ACCOUNT_TYPE attribute from artifact " + art.getArtifactID(), ex); + return true; } - } else if (artifactTypeID == TSK_KEYWORD_HIT.getTypeID()) { - return true; } } } + /** + * If the node is a Blackboard artifact node for anything other than a + * keyword hit, the document ID for the text extracted from the artifact + * (the concatenation of its attributes) is the artifact ID, a large, + * negative integer. If it is a keyword hit, see if there is an + * associated artifact. If there is, get the associated artifact's ID + * and return it. + */ + long documentID = INVALID_DOCUMENT_ID; + + BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class); + if (null != artifact) { + if (artifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { + documentID = artifact.getArtifactID(); + } else { + try { + // Get the associated artifact attribute and return its value as the ID + BlackboardAttribute blackboardAttribute = artifact.getAttribute(TSK_ASSOCIATED_ARTIFACT_TYPE); + if (blackboardAttribute != null) { + documentID = blackboardAttribute.getValueLong(); + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting associated artifact attributes", ex); //NON-NLS + } + } + } + + /* + * For keyword search hit artifact nodes and all other nodes, the + * document ID for the extracted text is the ID of the associated + * content, if any, unless there is an associated artifact, which is + * handled above. + */ + Content content = node.getLookup().lookup(Content.class); + if (content != null) { + documentID = content.getId(); + } /* * No highlighted text for a keyword hit, so is there any indexed text * at all for this node? */ - long documentID = getDocumentId(node); if (INVALID_DOCUMENT_ID == documentID) { return false; } @@ -367,69 +399,11 @@ public class ExtractedContentViewer implements DataContentViewer { try { return solrServer.queryIsIndexed(objectId); } catch (NoOpenCoreException | KeywordSearchModuleException ex) { - LOGGER.log(Level.SEVERE, "Error querying Solr server", ex); //NON-NLS + logger.log(Level.SEVERE, "Error querying Solr server", ex); //NON-NLS return false; } } - /** - * Gets the object ID to use as the document ID for accessing any indexed - * text for the given node. - * - * @param node The node. - * - * @return The document ID or zero, which is an invalid document ID. - */ - private Long getDocumentId(Node node) { - /** - * If the node is a Blackboard artifact node for anything other than a - * keyword hit, the document ID for the text extracted from the artifact - * (the concatenation of its attributes) is the artifact ID, a large, - * negative integer. If it is a keyword hit, see if there is an - * associated artifact. If there is, get the associated artifact's ID - * and return it. - */ - BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class); - if (null != artifact) { - if (artifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { - return artifact.getArtifactID(); - } else { - try { - // Get the associated artifact attribute and return its value as the ID - BlackboardAttribute blackboardAttribute = artifact.getAttribute(TSK_ASSOCIATED_ARTIFACT_TYPE); - if (blackboardAttribute != null) { - return blackboardAttribute.getValueLong(); - } - } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Error getting associated artifact attributes", ex); //NON-NLS - } - } - } - - /* - * For keyword search hit artifact nodes and all other nodes, the - * document ID for the extracted text is the ID of the associated - * content, if any, unless there is an associated artifact, which is - * handled above. - */ - Content content = node.getLookup().lookup(Content.class); - if (content == null) { - QueryContent queryContent = node.getLookup().lookup(QueryContent.class); - if (queryContent != null) { - content = queryContent.getContent(); - } - } - - if (content != null) { - return content.getId(); - } - - /* - * No extracted text, return an invalid docuemnt ID. - */ - return 0L; - } - private class NextFindActionListener implements ActionListener { @Override diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java index 9bcbdd7b2a..2fa4bbf999 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java @@ -54,7 +54,7 @@ import org.sleuthkit.datamodel.TskCoreException; */ class HighlightedText implements IndexedText { - private static final Logger LOGGER = Logger.getLogger(HighlightedText.class.getName()); + private static final Logger logger = Logger.getLogger(HighlightedText.class.getName()); private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT); @@ -400,7 +400,7 @@ class HighlightedText implements IndexedText { // either be a single chunk containing hits or we narrow our // query down to the current page/chunk. if (response.getResults().size() > 1) { - LOGGER.log(Level.WARNING, "Unexpected number of results for Solr highlighting query: {0}", q); //NON-NLS + logger.log(Level.WARNING, "Unexpected number of results for Solr highlighting query: {0}", q); //NON-NLS } String highlightedContent; Map>> responseHighlight = response.getHighlighting(); @@ -426,7 +426,7 @@ class HighlightedText implements IndexedText { return "
" + highlightedContent + "
"; //NON-NLS } catch (TskCoreException | KeywordSearchModuleException | NoOpenCoreException ex) { - LOGGER.log(Level.SEVERE, "Error getting highlighted text for Solr doc id " + solrObjectId + ", chunkID " + chunkID + ", highlight query: " + highlightField, ex); //NON-NLS + logger.log(Level.SEVERE, "Error getting highlighted text for Solr doc id " + solrObjectId + ", chunkID " + chunkID + ", highlight query: " + highlightField, ex); //NON-NLS return NbBundle.getMessage(this.getClass(), "HighlightedMatchesSource.getMarkup.queryFailedMsg"); } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java index b848892691..58876870e5 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java @@ -39,7 +39,7 @@ import org.sleuthkit.autopsy.actions.AddContentTagAction; import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.directorytree.HashSearchAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; -import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.QueryContent; +import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.AdHocQueryResult; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentVisitor; @@ -60,11 +60,11 @@ class KeywordSearchFilterNode extends FilterNode { /** * Instantiate a KeywordSearchFilterNode. * - * @param queryContent The query content. - * @param original The original source node. + * @param adHocQueryResult The query content. + * @param original The original source node. */ - KeywordSearchFilterNode(QueryContent queryContent, Node original) { - super(original, null, new ProxyLookup(Lookups.singleton(queryContent), original.getLookup())); + KeywordSearchFilterNode(AdHocQueryResult adHocQueryResult, Node original) { + super(original, null, new ProxyLookup(Lookups.singleton(adHocQueryResult), original.getLookup())); } @Override diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java index c8c1c07b15..fb37a84e59 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java @@ -66,7 +66,7 @@ import org.sleuthkit.datamodel.TskCoreException; */ class KeywordSearchResultFactory extends ChildFactory { - private static final Logger LOGGER = Logger.getLogger(KeywordSearchResultFactory.class.getName()); + private static final Logger logger = Logger.getLogger(KeywordSearchResultFactory.class.getName()); //common properties (superset of all Node properties) to be displayed as columns static final List COMMON_PROPERTIES @@ -140,7 +140,7 @@ class KeywordSearchResultFactory extends ChildFactory { try { queryResults = queryRequest.performQuery(); } catch (KeywordSearchModuleException | NoOpenCoreException ex) { - LOGGER.log(Level.SEVERE, "Could not perform the query " + queryRequest.getQueryString(), ex); //NON-NLS + logger.log(Level.SEVERE, "Could not perform the query " + queryRequest.getQueryString(), ex); //NON-NLS MessageNotifyUtil.Notify.error(Bundle.KeywordSearchResultFactory_query_exception_msg() + queryRequest.getQueryString(), ex.getCause().getMessage()); return false; } @@ -148,7 +148,7 @@ class KeywordSearchResultFactory extends ChildFactory { try { tskCase = Case.getCurrentCase().getSleuthkitCase(); } catch (IllegalStateException ex) { - LOGGER.log(Level.SEVERE, "There was no case open.", ex); //NON-NLS + logger.log(Level.SEVERE, "There was no case open.", ex); //NON-NLS return false; } @@ -165,11 +165,11 @@ class KeywordSearchResultFactory extends ChildFactory { try { content = tskCase.getContentById(hit.getContentID()); if (content == null) { - LOGGER.log(Level.SEVERE, "There was a error getting content by id."); //NON-NLS + logger.log(Level.SEVERE, "There was a error getting content by id."); //NON-NLS return false; } } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "There was a error getting content by id.", ex); //NON-NLS + logger.log(Level.SEVERE, "There was a error getting content by id.", ex); //NON-NLS return false; } @@ -192,7 +192,7 @@ class KeywordSearchResultFactory extends ChildFactory { try { hitName = tskCase.getBlackboardArtifact(hit.getArtifactID().get()).getDisplayName() + " Artifact"; //NON-NLS } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Error getting blckboard artifact by id", ex); + logger.log(Level.SEVERE, "Error getting blckboard artifact by id", ex); return false; } } else { @@ -250,12 +250,12 @@ class KeywordSearchResultFactory extends ChildFactory { Node resultNode; if (key instanceof KeyValueQueryContent) { - QueryContent queryContent = new QueryContent((KeyValueQueryContent) key); + AdHocQueryResult adHocQueryResult = new AdHocQueryResult((KeyValueQueryContent) key); - Node kvNode = new KeyValueNode(key, Children.LEAF, Lookups.singleton(queryContent)); + Node kvNode = new KeyValueNode(key, Children.LEAF); //wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization - resultNode = new KeywordSearchFilterNode(queryContent, kvNode); + resultNode = new KeywordSearchFilterNode(adHocQueryResult, kvNode); } else { resultNode = new EmptyNode("This Node Is Empty"); resultNode.setDisplayName(NbBundle.getMessage(this.getClass(), "KeywordSearchResultFactory.createNodeForKey.noResultsFound.text")); @@ -269,19 +269,19 @@ class KeywordSearchResultFactory extends ChildFactory { * This class encapsulates content, query results, and an associated Solr * object ID for storing in the Lookup to be read later. */ - class QueryContent { + final class AdHocQueryResult { private final long solrObjectId; private final Content content; private final QueryResults results; /** - * Instantiate a QueryContent object. + * Instantiate a AdHocQueryResult object. * * @param solrObjectId The Solr object ID associated with the content. * @param content The content for the query result. * @param results The query results. */ - QueryContent(KeyValueQueryContent key) { + AdHocQueryResult(KeyValueQueryContent key) { this.solrObjectId = key.getSolrObjectId(); this.content = key.getContent(); this.results = key.getHits(); @@ -407,9 +407,9 @@ class KeywordSearchResultFactory extends ChildFactory { try { get(); } catch (InterruptedException | CancellationException ex) { - LOGGER.log(Level.WARNING, "User cancelled writing of ad hoc search query results for '{0}' to the blackboard", query.getQueryString()); //NON-NLS + logger.log(Level.WARNING, "User cancelled writing of ad hoc search query results for '{0}' to the blackboard", query.getQueryString()); //NON-NLS } catch (ExecutionException ex) { - LOGGER.log(Level.SEVERE, "Error writing of ad hoc search query results for " + query.getQueryString() + " to the blackboard", ex); //NON-NLS + logger.log(Level.SEVERE, "Error writing of ad hoc search query results for " + query.getQueryString() + " to the blackboard", ex); //NON-NLS } } From ebc8d5b73c29af3504cb4355b4c448ac0bac76bc Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 9 Feb 2018 15:15:20 -0500 Subject: [PATCH 11/15] Minor changes to 'setNode()'. --- .../keywordsearch/ExtractedContentViewer.java | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java index b8fef30f01..4647892cdc 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java @@ -27,7 +27,6 @@ import java.util.Collection; import java.util.List; import java.util.logging.Level; import org.openide.nodes.Node; -import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; @@ -108,6 +107,10 @@ public class ExtractedContentViewer implements DataContentViewer { BlackboardArtifact artifact = nodeLookup.lookup(BlackboardArtifact.class); AbstractFile content = nodeLookup.lookup(AbstractFile.class); + /* + * Add the highlighted text, if any, for any artifact associated with the + * node. + */ if (adHocQueryResult != null) { highlightedHitText = new HighlightedText(adHocQueryResult.getSolrObjectId(), adHocQueryResult.getResults()); } else if (artifact != null) { @@ -115,27 +118,16 @@ public class ExtractedContentViewer implements DataContentViewer { try { highlightedHitText = new HighlightedText(artifact); } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); + logger.log(Level.SEVERE, "Failed to create HighlightedText for " + artifact, ex); //NON-NLS } } else if (artifact.getArtifactTypeID() == TSK_ACCOUNT.getTypeID() && content != null) { try { highlightedHitText = getAccountsText(content, nodeLookup); } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); + logger.log(Level.SEVERE, "Failed to create AccountsText for " + content, ex); //NON-NLS } } } - - if (content != null) { - rawContentText = new RawText(content, content.getId()); - } else if (artifact != null) { - try { - rawContentText = getRawArtifactText(nodeLookup); - } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); - } - } - if (highlightedHitText != null) { sources.add(highlightedHitText); } @@ -144,7 +136,9 @@ public class ExtractedContentViewer implements DataContentViewer { * Next, add the "raw" (not highlighted) text, if any, for any content * associated with the node. */ - if (rawContentText != null) { + + if (content != null) { + rawContentText = new RawText(content, content.getId()); sources.add(rawContentText); } @@ -155,13 +149,14 @@ public class ExtractedContentViewer implements DataContentViewer { IndexedText rawArtifactText = null; try { rawArtifactText = getRawArtifactText(nodeLookup); + + if (rawArtifactText != null) { + sources.add(rawArtifactText); + } } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Error creating RawText for " + content, ex); //NON-NLS } - if (rawArtifactText != null) { - sources.add(rawArtifactText); - } // Now set the default source to be displayed. if (null != highlightedHitText) { From b28694743d56fa8089fba96f81a76ecd3804babb Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 9 Feb 2018 23:23:52 -0500 Subject: [PATCH 12/15] Fixes. --- .../keywordsearch/ExtractedContentViewer.java | 148 +++++++++--------- 1 file changed, 72 insertions(+), 76 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java index 4647892cdc..d66617edd2 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java @@ -53,7 +53,6 @@ public class ExtractedContentViewer implements DataContentViewer { private static final Logger logger = Logger.getLogger(ExtractedContentViewer.class.getName()); - private static final long INVALID_DOCUMENT_ID = 0L; private static final BlackboardAttribute.Type TSK_ASSOCIATED_ARTIFACT_TYPE = new BlackboardAttribute.Type(TSK_ASSOCIATED_ARTIFACT); public static final BlackboardAttribute.Type TSK_ACCOUNT_TYPE = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE); @@ -98,33 +97,42 @@ public class ExtractedContentViewer implements DataContentViewer { * node. */ List sources = new ArrayList<>(); - IndexedText highlightedHitText = null; - IndexedText rawContentText = null; - Lookup nodeLookup = node.getLookup(); - AdHocQueryResult adHocQueryResult = nodeLookup.lookup(AdHocQueryResult.class); BlackboardArtifact artifact = nodeLookup.lookup(BlackboardArtifact.class); - AbstractFile content = nodeLookup.lookup(AbstractFile.class); + AbstractFile file = nodeLookup.lookup(AbstractFile.class); /* - * Add the highlighted text, if any, for any artifact associated with the - * node. + * First, get text with highlighted hits if this node is for a search + * result. */ + IndexedText highlightedHitText = null; if (adHocQueryResult != null) { + /* + * The node is an ad hoc search result node. + */ highlightedHitText = new HighlightedText(adHocQueryResult.getSolrObjectId(), adHocQueryResult.getResults()); } else if (artifact != null) { if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) { + /* + * The node is a keyword hit artifact node. + */ try { highlightedHitText = new HighlightedText(artifact); } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Failed to create HighlightedText for " + artifact, ex); //NON-NLS } - } else if (artifact.getArtifactTypeID() == TSK_ACCOUNT.getTypeID() && content != null) { + } else if (artifact.getArtifactTypeID() == TSK_ACCOUNT.getTypeID() && file != null) { try { - highlightedHitText = getAccountsText(content, nodeLookup); + BlackboardAttribute attribute = artifact.getAttribute(TSK_ACCOUNT_TYPE); + if (attribute != null && Account.Type.CREDIT_CARD.getTypeName().equals(attribute.getValueString())) { + /* + * The node is an credit card account node. + */ + highlightedHitText = getAccountsText(file, nodeLookup); + } } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Failed to create AccountsText for " + content, ex); //NON-NLS + logger.log(Level.SEVERE, "Failed to create AccountsText for " + file, ex); //NON-NLS } } } @@ -133,12 +141,12 @@ public class ExtractedContentViewer implements DataContentViewer { } /* - * Next, add the "raw" (not highlighted) text, if any, for any content + * Next, add the "raw" (not highlighted) text, if any, for any file * associated with the node. */ - - if (content != null) { - rawContentText = new RawText(content, content.getId()); + IndexedText rawContentText = null; + if (file != null) { + rawContentText = new RawText(file, file.getId()); sources.add(rawContentText); } @@ -149,22 +157,20 @@ public class ExtractedContentViewer implements DataContentViewer { IndexedText rawArtifactText = null; try { rawArtifactText = getRawArtifactText(nodeLookup); - if (rawArtifactText != null) { sources.add(rawArtifactText); } } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error creating RawText for " + content, ex); //NON-NLS - + logger.log(Level.SEVERE, "Error creating RawText for " + file, ex); //NON-NLS } // Now set the default source to be displayed. - if (null != highlightedHitText) { + if (highlightedHitText != null) { currentSource = highlightedHitText; - } else if (null != rawContentText) { - currentSource = rawContentText; - } else { + } else if (rawArtifactText != null) { currentSource = rawArtifactText; + } else { + currentSource = rawContentText; } // Push the text sources into the panel. @@ -177,8 +183,8 @@ public class ExtractedContentViewer implements DataContentViewer { panel.updateControls(currentSource); String contentName = ""; - if (content != null) { - contentName = content.getName(); + if (file != null) { + contentName = file.getName(); } setPanel(contentName, sources); @@ -274,80 +280,70 @@ public class ExtractedContentViewer implements DataContentViewer { return false; } + /* + * If the lookup of the node contains an ad hoc search result object, + * then there must be indexed text that produced the hit. + */ AdHocQueryResult adHocQueryResult = node.getLookup().lookup(AdHocQueryResult.class); if (adHocQueryResult != null) { return true; } /* - * Is there a credit card or keyword hit artifact in the lookup + * If the lookup of the node contains either a keyword hit artifact or + * one to many credit card account artifacts from a credit card account + * numbers search, then there must be indexed text that produced the + * hit(s). */ - Collection artifacts = node.getLookup().lookupAll(BlackboardArtifact.class); - if (artifacts != null) { - for (BlackboardArtifact art : artifacts) { - final int artifactTypeID = art.getArtifactTypeID(); - if (artifactTypeID == TSK_KEYWORD_HIT.getTypeID()) { - return true; - } else if (artifactTypeID == TSK_ACCOUNT.getTypeID()) { - try { - BlackboardAttribute attribute = art.getAttribute(TSK_ACCOUNT_TYPE); - if (attribute != null && Account.Type.CREDIT_CARD.getTypeName().equals(attribute.getValueString())) { - return true; - } - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting TSK_ACCOUNT_TYPE attribute from artifact " + art.getArtifactID(), ex); + BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class); + if (artifact != null) { + final int artifactTypeID = artifact.getArtifactTypeID(); + if (artifactTypeID == TSK_KEYWORD_HIT.getTypeID()) { + return true; + } else if (artifactTypeID == TSK_ACCOUNT.getTypeID()) { + try { + BlackboardAttribute attribute = artifact.getAttribute(TSK_ACCOUNT_TYPE); + if (attribute != null && Account.Type.CREDIT_CARD.getTypeName().equals(attribute.getValueString())) { return true; } - } - } - } - /** - * If the node is a Blackboard artifact node for anything other than a - * keyword hit, the document ID for the text extracted from the artifact - * (the concatenation of its attributes) is the artifact ID, a large, - * negative integer. If it is a keyword hit, see if there is an - * associated artifact. If there is, get the associated artifact's ID - * and return it. - */ - long documentID = INVALID_DOCUMENT_ID; - - BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class); - if (null != artifact) { - if (artifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { - documentID = artifact.getArtifactID(); - } else { - try { - // Get the associated artifact attribute and return its value as the ID - BlackboardAttribute blackboardAttribute = artifact.getAttribute(TSK_ASSOCIATED_ARTIFACT_TYPE); - if (blackboardAttribute != null) { - documentID = blackboardAttribute.getValueLong(); - } } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting associated artifact attributes", ex); //NON-NLS + /* + * If there is an error, log it and return true. The reason + * for returning true is so that the user will have an + * opportunity to see an error message in the panel when + * this query fails again when setNode is called, instead of + * having an unexpectedly disabled content viewer with no + * other feedback. + */ + logger.log(Level.SEVERE, "Error getting TSK_ACCOUNT_TYPE attribute from artifact " + artifact.getArtifactID(), ex); + return true; } } } /* - * For keyword search hit artifact nodes and all other nodes, the - * document ID for the extracted text is the ID of the associated - * content, if any, unless there is an associated artifact, which is - * handled above. + * If the lookup of the node contains an artifact that is neither a + * keyword hit artifact nor a credit card account artifact, check to see + * if there is indexed text for the artifact. */ - Content content = node.getLookup().lookup(Content.class); - if (content != null) { - documentID = content.getId(); + if (artifact != null) { + return solrHasContent(artifact.getArtifactID()); } /* - * No highlighted text for a keyword hit, so is there any indexed text - * at all for this node? + * If the lookup of the node contains no artifacts but does contain a + * file, check to see if there is indexed text for the file. */ - if (INVALID_DOCUMENT_ID == documentID) { - return false; + AbstractFile file = node.getLookup().lookup(AbstractFile.class); + if (file != null) { + return solrHasContent(file.getId()); } - return solrHasContent(documentID); + /* + * If the lookup of the node contains neither ad hoc search results, nor + * artifacts, nor a file, there is no indexed text. + */ + return false; } @Override From eb3987f8006f9d012d18f96e22397e98109de141 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Mon, 12 Feb 2018 13:19:18 -0500 Subject: [PATCH 13/15] Fixed bugs; cleanup. --- .../keywordsearch/ExtractedContentViewer.java | 22 +++-- .../KeywordSearchFilterNode.java | 2 +- .../KeywordSearchResultFactory.java | 86 ++++++++++++------- 3 files changed, 73 insertions(+), 37 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java index d66617edd2..97066a61c8 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java @@ -98,9 +98,22 @@ public class ExtractedContentViewer implements DataContentViewer { */ List sources = new ArrayList<>(); Lookup nodeLookup = node.getLookup(); + AdHocQueryResult adHocQueryResult = nodeLookup.lookup(AdHocQueryResult.class); - BlackboardArtifact artifact = nodeLookup.lookup(BlackboardArtifact.class); - AbstractFile file = nodeLookup.lookup(AbstractFile.class); + AbstractFile file; + BlackboardArtifact artifact; + + /* + * If we have an ad hoc query result, pull the file and artifact objects + * from that. Otherwise, pull them from the lookup. + */ + if (adHocQueryResult != null) { + artifact = adHocQueryResult.getArtifact(); + file = adHocQueryResult.getFile(); + } else { + artifact = nodeLookup.lookup(BlackboardArtifact.class); + file = nodeLookup.lookup(AbstractFile.class); + } /* * First, get text with highlighted hits if this node is for a search @@ -156,7 +169,7 @@ public class ExtractedContentViewer implements DataContentViewer { */ IndexedText rawArtifactText = null; try { - rawArtifactText = getRawArtifactText(nodeLookup); + rawArtifactText = getRawArtifactText(artifact); if (rawArtifactText != null) { sources.add(rawArtifactText); } @@ -190,9 +203,8 @@ public class ExtractedContentViewer implements DataContentViewer { } - static private IndexedText getRawArtifactText(Lookup nodeLookup) throws TskCoreException { + static private IndexedText getRawArtifactText(BlackboardArtifact artifact) throws TskCoreException { IndexedText rawArtifactText = null; - BlackboardArtifact artifact = nodeLookup.lookup(BlackboardArtifact.class); if (null != artifact) { /* * For keyword hit artifacts, add the text of the artifact that hit, diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java index 58876870e5..98c7ca0969 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java @@ -53,7 +53,7 @@ import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.VirtualDirectory; /** - * FilterNode containing data pertaining to keyword search. + * FilterNode containing properties and actions for keyword search. */ class KeywordSearchFilterNode extends FilterNode { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java index fb37a84e59..6725c647cc 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java @@ -37,7 +37,6 @@ import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.util.NbBundle; -import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; @@ -49,6 +48,7 @@ import org.sleuthkit.autopsy.datamodel.KeyValue; import org.sleuthkit.autopsy.datamodel.KeyValueNode; import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.KeyValueQueryContent; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW; @@ -75,10 +75,10 @@ class KeywordSearchResultFactory extends ChildFactory { TSK_KEYWORD, TSK_KEYWORD_REGEXP, TSK_KEYWORD_PREVIEW) - .map(BlackboardAttribute.ATTRIBUTE_TYPE::getDisplayName), + .map(BlackboardAttribute.ATTRIBUTE_TYPE::getDisplayName), Arrays.stream(AbstractAbstractFileNode.AbstractFilePropertyType.values()) - .map(Object::toString)) - .collect(Collectors.toList()); + .map(Object::toString)) + .collect(Collectors.toList()); private final Collection queryRequests; @@ -188,9 +188,11 @@ class KeywordSearchResultFactory extends ChildFactory { } String hitName; + BlackboardArtifact artifact = null; if (hit.isArtifactHit()) { try { - hitName = tskCase.getBlackboardArtifact(hit.getArtifactID().get()).getDisplayName() + " Artifact"; //NON-NLS + artifact = tskCase.getBlackboardArtifact(hit.getArtifactID().get()); + hitName = artifact.getDisplayName() + " Artifact"; //NON-NLS } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Error getting blckboard artifact by id", ex); return false; @@ -199,7 +201,7 @@ class KeywordSearchResultFactory extends ChildFactory { hitName = contentName; } hitNumber++; - tempList.add(new KeyValueQueryContent(hitName, properties, hitNumber, hit.getSolrObjectId(), content, queryRequest, queryResults)); + tempList.add(new KeyValueQueryContent(hitName, properties, hitNumber, hit.getSolrObjectId(), (AbstractFile) content, artifact, queryRequest, queryResults)); } @@ -264,50 +266,65 @@ class KeywordSearchResultFactory extends ChildFactory { return resultNode; } - + /** * This class encapsulates content, query results, and an associated Solr * object ID for storing in the Lookup to be read later. */ final class AdHocQueryResult { + private final long solrObjectId; - private final Content content; + private final AbstractFile file; + private final BlackboardArtifact artifact; private final QueryResults results; - + /** * Instantiate a AdHocQueryResult object. - * - * @param solrObjectId The Solr object ID associated with the content. - * @param content The content for the query result. - * @param results The query results. + * + * @param solrObjectId The Solr object ID associated with the object in + * which the hit was found. + * @param file The file for the query result. + * @param artifact The artifact associated with the query result. + * @param results The query results. */ AdHocQueryResult(KeyValueQueryContent key) { this.solrObjectId = key.getSolrObjectId(); - this.content = key.getContent(); + this.file = key.getFile(); + this.artifact = key.getArtifact(); this.results = key.getHits(); } - + /** - * Get the Solr object ID associated with the content. - * + * Get the Solr object ID associated with the object in which the hit + * was found. This could be a file or an artifact. + * * @return The Solr object ID. */ long getSolrObjectId() { return solrObjectId; } - + /** - * Get the content for the query result. - * + * Get the file for the query result. + * * @return The content. */ - Content getContent() { - return content; + AbstractFile getFile() { + return file; } - + + /** + * Get the artifact for the query result. + * + * @return The artifact. + */ + BlackboardArtifact getArtifact() { + return artifact; + } + /** * Get the query results. - * + * * @return The query results. */ QueryResults getResults() { @@ -323,7 +340,8 @@ class KeywordSearchResultFactory extends ChildFactory { private final long solrObjectId; - private final Content content; + private final AbstractFile file; + private final BlackboardArtifact artifact; private final QueryResults hits; private final KeywordSearchQuery query; @@ -335,22 +353,28 @@ class KeywordSearchResultFactory extends ChildFactory { * @param map Contains content metadata, snippets, etc. * (property map) * @param id User incremented ID - * @param solrObjectId - * @param content File that had the hit. + * @param solrObjectId The ID of the object. + * @param file File that had the hit. + * @param artifact The blackboard artifact. * @param query Query used in search * @param hits Full set of search results (for all files! @@@) */ - KeyValueQueryContent(String name, Map map, int id, long solrObjectId, Content content, KeywordSearchQuery query, QueryResults hits) { + KeyValueQueryContent(String name, Map map, int id, long solrObjectId, AbstractFile file, BlackboardArtifact artifact, KeywordSearchQuery query, QueryResults hits) { super(name, map, id); this.solrObjectId = solrObjectId; - this.content = content; + this.file = file; + this.artifact = artifact; this.hits = hits; this.query = query; } - Content getContent() { - return content; + AbstractFile getFile() { + return file; + } + + BlackboardArtifact getArtifact() { + return artifact; } long getSolrObjectId() { From d8be685908b28e29143e389efa3762a2c01eb3f1 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Mon, 12 Feb 2018 15:31:38 -0500 Subject: [PATCH 14/15] Changed AbstractFile to Content to account for data sources. --- .../keywordsearch/ExtractedContentViewer.java | 7 ++-- .../KeywordSearchResultFactory.java | 32 +++++++++++-------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java index 97066a61c8..0f05f3df99 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java @@ -100,7 +100,7 @@ public class ExtractedContentViewer implements DataContentViewer { Lookup nodeLookup = node.getLookup(); AdHocQueryResult adHocQueryResult = nodeLookup.lookup(AdHocQueryResult.class); - AbstractFile file; + AbstractFile file = null; BlackboardArtifact artifact; /* @@ -109,7 +109,10 @@ public class ExtractedContentViewer implements DataContentViewer { */ if (adHocQueryResult != null) { artifact = adHocQueryResult.getArtifact(); - file = adHocQueryResult.getFile(); + Content content = adHocQueryResult.getContent(); + if (content instanceof AbstractFile) { + file = (AbstractFile) content; + } } else { artifact = nodeLookup.lookup(BlackboardArtifact.class); file = nodeLookup.lookup(AbstractFile.class); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java index 6725c647cc..fbeb4268b7 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java @@ -201,7 +201,7 @@ class KeywordSearchResultFactory extends ChildFactory { hitName = contentName; } hitNumber++; - tempList.add(new KeyValueQueryContent(hitName, properties, hitNumber, hit.getSolrObjectId(), (AbstractFile) content, artifact, queryRequest, queryResults)); + tempList.add(new KeyValueQueryContent(hitName, properties, hitNumber, hit.getSolrObjectId(), content, artifact, queryRequest, queryResults)); } @@ -274,7 +274,7 @@ class KeywordSearchResultFactory extends ChildFactory { final class AdHocQueryResult { private final long solrObjectId; - private final AbstractFile file; + private final Content content; private final BlackboardArtifact artifact; private final QueryResults results; @@ -283,13 +283,13 @@ class KeywordSearchResultFactory extends ChildFactory { * * @param solrObjectId The Solr object ID associated with the object in * which the hit was found. - * @param file The file for the query result. + * @param content The content for the query result. * @param artifact The artifact associated with the query result. * @param results The query results. */ AdHocQueryResult(KeyValueQueryContent key) { this.solrObjectId = key.getSolrObjectId(); - this.file = key.getFile(); + this.content = key.getContent(); this.artifact = key.getArtifact(); this.results = key.getHits(); } @@ -305,12 +305,16 @@ class KeywordSearchResultFactory extends ChildFactory { } /** - * Get the file for the query result. + * Get the content for the query result. This can be either a file or a + * data source, and it may or may not be the content in which the hit + * occurred. If the hit is in a file, the Content object represents that + * file. But if the hit is in an artifact, the Content object represents + * the source file or data source of the artifact. * - * @return The content. + * @return The content object. */ - AbstractFile getFile() { - return file; + Content getContent() { + return content; } /** @@ -340,7 +344,7 @@ class KeywordSearchResultFactory extends ChildFactory { private final long solrObjectId; - private final AbstractFile file; + private final Content content; private final BlackboardArtifact artifact; private final QueryResults hits; private final KeywordSearchQuery query; @@ -354,23 +358,23 @@ class KeywordSearchResultFactory extends ChildFactory { * (property map) * @param id User incremented ID * @param solrObjectId The ID of the object. - * @param file File that had the hit. + * @param content The content object. * @param artifact The blackboard artifact. * @param query Query used in search * @param hits Full set of search results (for all files! @@@) */ - KeyValueQueryContent(String name, Map map, int id, long solrObjectId, AbstractFile file, BlackboardArtifact artifact, KeywordSearchQuery query, QueryResults hits) { + KeyValueQueryContent(String name, Map map, int id, long solrObjectId, Content content, BlackboardArtifact artifact, KeywordSearchQuery query, QueryResults hits) { super(name, map, id); this.solrObjectId = solrObjectId; - this.file = file; + this.content = content; this.artifact = artifact; this.hits = hits; this.query = query; } - AbstractFile getFile() { - return file; + Content getContent() { + return content; } BlackboardArtifact getArtifact() { From be21b664a422d28a242e28a2b6d70dc828cb5f34 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 12 Feb 2018 16:07:45 -0500 Subject: [PATCH 15/15] 3445 add Date condition xml writing for exporting rules to xml --- .../interestingitems/InterestingItemsFilesSetSettings.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java index 0e1bfff033..3f4cca4465 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java @@ -576,6 +576,13 @@ class InterestingItemsFilesSetSettings implements Serializable { ruleElement.setAttribute(FS_SIZE_ATTR, Integer.toString(sizeCondition.getSizeValue())); ruleElement.setAttribute(FS_UNITS_ATTR, sizeCondition.getUnit().getName()); } + + //Add the optional date condition + DateCondition dateCondition = rule.getDateCondition(); + if (dateCondition != null) { + ruleElement.setAttribute(DAYS_INCLUDED_ATTR, Integer.toString(dateCondition.getDaysIncluded())); + } + setElement.appendChild(ruleElement); } rootElement.appendChild(setElement);