From e9255eb6ce2a938ac22d7b8c93f6f9e477ec8516 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Tue, 1 Dec 2020 10:44:52 -0500 Subject: [PATCH 1/4] Implemented previously notable grouping and filtering for domains --- .../discovery/search/Bundle.properties-MERGED | 4 + .../discovery/search/DiscoveryAttributes.java | 166 +++++++++++++++--- .../discovery/search/DiscoveryKeyUtils.java | 44 +++++ .../autopsy/discovery/search/Result.java | 11 +- .../autopsy/discovery/search/SearchData.java | 26 +++ .../discovery/search/SearchFiltering.java | 40 +++++ .../autopsy/discovery/ui/Bundle.properties | 1 + .../discovery/ui/Bundle.properties-MERGED | 1 + .../discovery/ui/DomainFilterPanel.java | 1 + .../ui/PreviouslyNotableFilterPanel.form | 58 ++++++ .../ui/PreviouslyNotableFilterPanel.java | 120 +++++++++++++ 11 files changed, 450 insertions(+), 22 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/discovery/ui/PreviouslyNotableFilterPanel.form create mode 100755 Core/src/org/sleuthkit/autopsy/discovery/ui/PreviouslyNotableFilterPanel.java diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/search/Bundle.properties-MERGED index 037868e838..f968ab0fe0 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/Bundle.properties-MERGED @@ -10,6 +10,7 @@ DiscoveryAttributes.GroupingAttributeType.none.displayName=None DiscoveryAttributes.GroupingAttributeType.numberOfVisits.displayName=Number of Visits DiscoveryAttributes.GroupingAttributeType.object.displayName=Object Detected DiscoveryAttributes.GroupingAttributeType.parent.displayName=Parent Folder +DiscoveryAttributes.GroupingAttributeType.previouslyNotable.displayName=Previous Notability DiscoveryAttributes.GroupingAttributeType.size.displayName=File Size DiscoveryAttributes.GroupingAttributeType.tag.displayName=Tag # {0} - Data source name @@ -84,6 +85,8 @@ SearchData.Frequency.rare.displayName=Rare (2-10) SearchData.Frequency.unique.displayName=Unique (1) SearchData.Frequency.unknown.displayName=Unknown SearchData.Frequency.verycommon.displayName=Very Common (100+) +SearchData.notPrevNotable.displayName=Previously Not Notable +SearchData.prevNotable.displayName=Previously Notable SearchData.Score.interesting.displayName=Interesting SearchData.Score.notable.displayName=Notable SearchData.Score.unknown.displayName=Unknown @@ -125,6 +128,7 @@ SearchFiltering.ParentSearchTerm.excludeString=\ (exclude) SearchFiltering.ParentSearchTerm.fullString=\ (exact) SearchFiltering.ParentSearchTerm.includeString=\ (include) SearchFiltering.ParentSearchTerm.subString=\ (substring) +SearchFiltering.PreviouslyNotableFilter.desc=Previously marked as notable in central repository # {0} - filters SearchFiltering.ScoreFilter.desc=Score(s) of : {0} # {0} - filters diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryAttributes.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryAttributes.java index 0153fe8e65..0a47894d30 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryAttributes.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryAttributes.java @@ -215,6 +215,141 @@ public class DiscoveryAttributes { } } } + + /** + * Organizes the domain instances by normalized domain value. + * This helps reduce the complexity of updating ResultDomain instances + * after the query has been executed. + * + * Example: query for notable status of google.com. Result: notable + * With this map, all domain instances that represent google.com can + * be updated after one simple lookup. + */ + private static Map> organizeByValue(List domainsBatch, CorrelationAttributeInstance.Type attributeType) { + final Map> resultDomainTable = new HashMap<>(); + for (ResultDomain domainInstance : domainsBatch) { + try { + final String domainValue = domainInstance.getDomain(); + final String normalizedDomain = CorrelationAttributeNormalizer.normalize(attributeType, domainValue); + final List bucket = resultDomainTable.getOrDefault(normalizedDomain, new ArrayList<>()); + bucket.add(domainInstance); + resultDomainTable.put(normalizedDomain, bucket); + } catch (CorrelationAttributeNormalizationException ex) { + logger.log(Level.INFO, String.format("Domain [%s] failed normalization, skipping...", domainInstance.getDomain())); + } + } + return resultDomainTable; + } + + /** + * Helper function to create a string of comma separated values. + * Each value is wrapped in `'`. This method is used to bundle up + * a collection of values for use in a SQL WHERE IN (...) clause. + */ + private static String createCSV(Set values) { + StringJoiner joiner = new StringJoiner(", "); + for (String value : values) { + joiner.add("'" + value + "'"); + } + return joiner.toString(); + } + + /** + * Attribute for grouping/sorting by notability in the CR. + */ + static class PreviouslyNotableAttribute extends AttributeType { + + static final int DOMAIN_BATCH_SIZE = 500; // Number of domains to look up at one time + + @Override + public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) { + return new DiscoveryKeyUtils.PreviouslyNotableGroupKey(result); + } + + @Override + public void addAttributeToResults(List results, SleuthkitCase caseDb, + CentralRepository centralRepoDb) throws DiscoveryException { + + if (centralRepoDb != null) { + processFilesWithCr(results, centralRepoDb); + } + } + + private void processFilesWithCr(List results, CentralRepository centralRepo) throws DiscoveryException { + + List domainsBatch = new ArrayList<>(); + for (Result result : results) { + if (result.getType() == SearchData.Type.DOMAIN) { + domainsBatch.add((ResultDomain) result); + if (domainsBatch.size() == DOMAIN_BATCH_SIZE) { + queryPreviouslyNotable(domainsBatch, centralRepo); + domainsBatch.clear(); + } + } + } + + queryPreviouslyNotable(domainsBatch, centralRepo); + } + + private void queryPreviouslyNotable(List domainsBatch, CentralRepository centralRepo) throws DiscoveryException { + if (domainsBatch.isEmpty()) { + return; + } + + try { + final CorrelationAttributeInstance.Type attributeType = centralRepo.getCorrelationTypeById(CorrelationAttributeInstance.DOMAIN_TYPE_ID); + final Map> resultDomainTable = organizeByValue(domainsBatch, attributeType); + final String values = createCSV(resultDomainTable.keySet()); + + final String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(attributeType); + final String domainFrequencyQuery = " value AS domain_name " + + "FROM " + tableName + " " + + "WHERE value IN (" + values + ") " + + "AND known_status = " + TskData.FileKnown.BAD.getFileKnownValue(); + + final DomainPreviouslyNotableCallback previouslyNotableCallback = new DomainPreviouslyNotableCallback(resultDomainTable); + centralRepo.processSelectClause(domainFrequencyQuery, previouslyNotableCallback); + + if (previouslyNotableCallback.getCause() != null) { + throw previouslyNotableCallback.getCause(); + } + } catch (CentralRepoException | SQLException ex) { + throw new DiscoveryException("Fatal exception encountered querying the CR.", ex); + } + } + + private static class DomainPreviouslyNotableCallback implements InstanceTableCallback { + + private final Map> domainLookup; + private SQLException sqlCause; + + private DomainPreviouslyNotableCallback(Map> domainLookup) { + this.domainLookup = domainLookup; + } + + @Override + public void process(ResultSet resultSet) { + try { + while (resultSet.next()) { + String domain = resultSet.getString("domain_name"); + List domainInstances = domainLookup.get(domain); + for (ResultDomain domainInstance : domainInstances) { + domainInstance.markAsPreviouslyNotable(); + } + } + } catch (SQLException ex) { + this.sqlCause = ex; + } + } + + /** + * Get the SQL exception if one occurred during this callback. + */ + SQLException getCause() { + return this.sqlCause; + } + } + } /** * Attribute for grouping/sorting by frequency in the central repository. @@ -307,27 +442,14 @@ public class DiscoveryAttributes { return; } try { - final Map> resultDomainTable = new HashMap<>(); - final StringJoiner joiner = new StringJoiner(", "); - final CorrelationAttributeInstance.Type attributeType = centralRepository.getCorrelationTypeById(CorrelationAttributeInstance.DOMAIN_TYPE_ID); - for (ResultDomain domainInstance : domainsToQuery) { - try { - final String domainValue = domainInstance.getDomain(); - final String normalizedDomain = CorrelationAttributeNormalizer.normalize(attributeType, domainValue); - final List bucket = resultDomainTable.getOrDefault(normalizedDomain, new ArrayList<>()); - bucket.add(domainInstance); - resultDomainTable.put(normalizedDomain, bucket); - joiner.add("'" + normalizedDomain + "'"); - } catch (CorrelationAttributeNormalizationException ex) { - logger.log(Level.INFO, String.format("Domain [%s] failed normalization, skipping...", domainInstance.getDomain())); - } - } + final Map> resultDomainTable = organizeByValue(domainsToQuery, attributeType); + final String values = createCSV(resultDomainTable.keySet()); final String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(attributeType); final String domainFrequencyQuery = " value AS domain_name, COUNT(*) AS frequency " + "FROM " + tableName + " " - + "WHERE value IN (" + joiner + ") " + + "WHERE value IN (" + values + ") " + "GROUP BY value"; final DomainFrequencyCallback frequencyCallback = new DomainFrequencyCallback(resultDomainTable); @@ -743,7 +865,8 @@ public class DiscoveryAttributes { "DiscoveryAttributes.GroupingAttributeType.mostRecentDate.displayName=Most Recent Activity Date", "DiscoveryAttributes.GroupingAttributeType.firstDate.displayName=First Activity Date", "DiscoveryAttributes.GroupingAttributeType.numberOfVisits.displayName=Number of Visits", - "DiscoveryAttributes.GroupingAttributeType.none.displayName=None"}) + "DiscoveryAttributes.GroupingAttributeType.none.displayName=None", + "DiscoveryAttributes.GroupingAttributeType.previouslyNotable.displayName=Previous Notability"}) public enum GroupingAttributeType { FILE_SIZE(new FileSizeAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_size_displayName()), FREQUENCY(new FrequencyAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_frequency_displayName()), @@ -757,7 +880,8 @@ public class DiscoveryAttributes { MOST_RECENT_DATE(new MostRecentActivityDateAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_mostRecentDate_displayName()), FIRST_DATE(new FirstActivityDateAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_firstDate_displayName()), NUMBER_OF_VISITS(new NumberOfVisitsAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_numberOfVisits_displayName()), - NO_GROUPING(new NoGroupingAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_none_displayName()); + NO_GROUPING(new NoGroupingAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_none_displayName()), + PREVIOUSLY_NOTABLE(new PreviouslyNotableAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_previouslyNotable_displayName()); private final AttributeType attributeType; private final String displayName; @@ -799,12 +923,12 @@ public class DiscoveryAttributes { } /** - * Get the list of enums that are valid for grouping files. + * Get the list of enums that are valid for grouping domains. * * @return Enums that can be used to group files. */ public static List getOptionsForGroupingForDomains() { - return Arrays.asList(FREQUENCY, MOST_RECENT_DATE, FIRST_DATE, NUMBER_OF_VISITS); + return Arrays.asList(FREQUENCY, MOST_RECENT_DATE, FIRST_DATE, NUMBER_OF_VISITS, PREVIOUSLY_NOTABLE); } } @@ -889,4 +1013,4 @@ public class DiscoveryAttributes { private DiscoveryAttributes() { // Class should not be instantiated } -} + } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryKeyUtils.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryKeyUtils.java index 9fe4fbf946..82d0f48ce9 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryKeyUtils.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryKeyUtils.java @@ -792,6 +792,50 @@ public class DiscoveryKeyUtils { return 0; } } + + /** + * Key representing a central repository notable status. + */ + static class PreviouslyNotableGroupKey extends GroupKey { + + private final SearchData.PreviouslyNotable notableStatus; + + PreviouslyNotableGroupKey(Result result) { + this.notableStatus = result.getPreviouslyNotable(); + } + + @Override + String getDisplayName() { + return this.notableStatus.toString(); + } + + @Override + public boolean equals(Object otherKey) { + if (otherKey instanceof GroupKey) { + return compareTo((GroupKey) otherKey) == 0; + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(getStatus().getRanking()); + } + + @Override + public int compareTo(GroupKey otherGroupKey) { + if (otherGroupKey instanceof PreviouslyNotableGroupKey) { + PreviouslyNotableGroupKey otherFrequencyGroupKey = (PreviouslyNotableGroupKey) otherGroupKey; + return Integer.compare(getStatus().getRanking(), otherFrequencyGroupKey.getStatus().getRanking()); + } else { + return compareClassNames(otherGroupKey); + } + } + + SearchData.PreviouslyNotable getStatus() { + return notableStatus; + } + } /** * Key representing a central repository frequency group. diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/Result.java b/Core/src/org/sleuthkit/autopsy/discovery/search/Result.java index cc4c97427b..9d7f693f62 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/Result.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/Result.java @@ -31,6 +31,7 @@ import org.sleuthkit.datamodel.TskData; public abstract class Result { private SearchData.Frequency frequency = SearchData.Frequency.UNKNOWN; + private SearchData.PreviouslyNotable isPreviouslyNotable = SearchData.PreviouslyNotable.NOT_PREVIOUSLY_NOTABLE; private final List tagNames = new ArrayList<>(); /** @@ -50,11 +51,19 @@ public abstract class Result { } /** - * Get the known status of the result. + * Get the known status of the result (known status being NSRL). * * @return The Known status of the result. */ public abstract TskData.FileKnown getKnown(); + + final public void markAsPreviouslyNotable() { + this.isPreviouslyNotable = SearchData.PreviouslyNotable.PREVIOUSLY_NOTABLE; + } + + final public SearchData.PreviouslyNotable getPreviouslyNotable() { + return this.isPreviouslyNotable; + } /** * Set the frequency of this result in the central repository. diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/SearchData.java b/Core/src/org/sleuthkit/autopsy/discovery/search/SearchData.java index 909cfb1acd..3de4ea7db7 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/SearchData.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/SearchData.java @@ -38,6 +38,32 @@ public final class SearchData { private final static long BYTES_PER_MB = 1000000; private static final Set DOMAIN_ARTIFACT_TYPES = EnumSet.of(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY); + + @NbBundle.Messages({ + "SearchData.prevNotable.displayName=Previously Notable", + "SearchData.notPrevNotable.displayName=Previously Not Notable" + }) + public enum PreviouslyNotable { + PREVIOUSLY_NOTABLE(0, Bundle.SearchData_prevNotable_displayName()), + NOT_PREVIOUSLY_NOTABLE(1, Bundle.SearchData_notPrevNotable_displayName()); + + private final int ranking; + private final String displayName; + + PreviouslyNotable(int ranking, String displayName) { + this.ranking = ranking; + this.displayName = displayName; + } + + public int getRanking() { + return ranking; + } + + @Override + public String toString() { + return displayName; + } + } /** * Enum representing how often the result occurs in the Central Repository. */ diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java b/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java index f39bb56634..ade423488c 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java @@ -689,6 +689,46 @@ public class SearchFiltering { return Bundle.SearchFiltering_FrequencyFilter_desc(desc); } } + + /** + * A filter for previously notable content in the central repository. + */ + public static class PreviouslyNotableFilter extends AbstractFilter { + + @Override + public String getWhereClause() { + throw new UnsupportedOperationException("Not supported, this is an alternative filter."); + } + + @Override + public boolean useAlternateFilter() { + return true; + } + + @Override + public List applyAlternateFilter(List currentResults, SleuthkitCase caseDb, + CentralRepository centralRepoDb) throws DiscoveryException { + DiscoveryAttributes.PreviouslyNotableAttribute previouslyNotableAttr = new DiscoveryAttributes.PreviouslyNotableAttribute(); + previouslyNotableAttr.addAttributeToResults(currentResults, caseDb, centralRepoDb); + + List filteredResults = new ArrayList<>(); + for (Result file : currentResults) { + if (file.getPreviouslyNotable() == SearchData.PreviouslyNotable.PREVIOUSLY_NOTABLE) { + filteredResults.add(file); + } + } + return filteredResults; + } + + @NbBundle.Messages({ + "SearchFiltering.PreviouslyNotableFilter.desc=Previously marked as notable in central repository" + }) + @Override + public String getDesc() { + return Bundle.SearchFiltering_PreviouslyNotableFilter_desc(); + } + + } /** * A filter for specifying hash set names. A file must match one of the diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties index 851045c71a..194c8d3398 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties @@ -60,3 +60,4 @@ DomainSummaryPanel.totalVisitsLabel.text= FileDetailsPanel.instancesList.border.title=Instances CookieDetailsPanel.jLabel1.text=Artifact: CookieDetailsPanel.jLabel2.text= +PreviouslyNotableFilterPanel.text_1=Include only previously notable domains diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED index 6c9f511ba6..c46263184f 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED @@ -140,6 +140,7 @@ DomainSummaryPanel.totalVisitsLabel.text= FileDetailsPanel.instancesList.border.title=Instances CookieDetailsPanel.jLabel1.text=Artifact: CookieDetailsPanel.jLabel2.text= +PreviouslyNotableFilterPanel.text_1=Include only previously notable domains VideoThumbnailPanel.bytes.text=bytes VideoThumbnailPanel.deleted.text=All instances of file are deleted. VideoThumbnailPanel.gigaBytes.text=GB diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainFilterPanel.java index 3216110694..88424d1076 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainFilterPanel.java @@ -40,6 +40,7 @@ public class DomainFilterPanel extends AbstractFiltersPanel { super(); initComponents(); addFilter(new DataSourceFilterPanel(), false, null, 0); + addFilter(new PreviouslyNotableFilterPanel(), false, null, 1); addFilter(new ArtifactTypeFilterPanel(), false, null, 1); addFilter(new DateFilterPanel(), false, null, 1); int[] pastOccurrencesIndices = null; diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/PreviouslyNotableFilterPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/PreviouslyNotableFilterPanel.form new file mode 100755 index 0000000000..745ff3f4ab --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/PreviouslyNotableFilterPanel.form @@ -0,0 +1,58 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/PreviouslyNotableFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/PreviouslyNotableFilterPanel.java new file mode 100755 index 0000000000..de239c5a8d --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/PreviouslyNotableFilterPanel.java @@ -0,0 +1,120 @@ +/* + * Autopsy + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.discovery.ui; + +import org.sleuthkit.autopsy.discovery.search.AbstractFilter; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JList; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; +import org.sleuthkit.autopsy.discovery.search.SearchFiltering; + +/** + * Panel to allow configuration of the previously notable (in CR) filter. + */ +final class PreviouslyNotableFilterPanel extends AbstractDiscoveryFilterPanel { + + private static final long serialVersionUID = 1L; + + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + PreviouslyNotableFilterPanel() { + initComponents(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + previouslyNotableCheckbox = new javax.swing.JCheckBox(); + + org.openide.awt.Mnemonics.setLocalizedText(previouslyNotableCheckbox, org.openide.util.NbBundle.getMessage(PreviouslyNotableFilterPanel.class, "PreviouslyNotableFilterPanel.text_1")); // NOI18N + previouslyNotableCheckbox.setMaximumSize(new java.awt.Dimension(255, 25)); + previouslyNotableCheckbox.setMinimumSize(new java.awt.Dimension(0, 25)); + previouslyNotableCheckbox.setName(""); // NOI18N + previouslyNotableCheckbox.setOpaque(false); + previouslyNotableCheckbox.setPreferredSize(new java.awt.Dimension(255, 25)); + previouslyNotableCheckbox.setRequestFocusEnabled(false); + + setMinimumSize(new java.awt.Dimension(0, 30)); + setPreferredSize(new java.awt.Dimension(255, 30)); + setVerifyInputWhenFocusTarget(false); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 300, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 42, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + @Override + void configurePanel(boolean selected, int[] indicesSelected) { + previouslyNotableCheckbox.setSelected(selected); + } + + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + @Override + JCheckBox getCheckbox() { + return previouslyNotableCheckbox; + } + + @Override + JLabel getAdditionalLabel() { + return null; + } + + @Override + String checkForError() { + //this filter currently has no errors it generates + return ""; + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox previouslyNotableCheckbox; + // End of variables declaration//GEN-END:variables + + @Override + JList getList() { + return null; + } + + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + @Override + AbstractFilter getFilter() { + if (previouslyNotableCheckbox.isSelected()) { + return new SearchFiltering.PreviouslyNotableFilter(); + } + return null; + } + + @Override + boolean hasPanel() { + return false; + } +} From de0fe431d53c19f2eaa194bdd434cd9f12d310e4 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Wed, 2 Dec 2020 10:27:55 -0500 Subject: [PATCH 2/4] Added comments and renamed a function name --- .../discovery/search/DiscoveryAttributes.java | 2 +- .../autopsy/discovery/search/DiscoveryKeyUtils.java | 2 +- .../sleuthkit/autopsy/discovery/search/Result.java | 12 ++++++++++-- .../autopsy/discovery/search/SearchData.java | 3 +++ .../autopsy/discovery/search/SearchFiltering.java | 2 +- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryAttributes.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryAttributes.java index 0a47894d30..58e906367e 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryAttributes.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryAttributes.java @@ -334,7 +334,7 @@ public class DiscoveryAttributes { String domain = resultSet.getString("domain_name"); List domainInstances = domainLookup.get(domain); for (ResultDomain domainInstance : domainInstances) { - domainInstance.markAsPreviouslyNotable(); + domainInstance.markAsPreviouslyNotableInCR(); } } } catch (SQLException ex) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryKeyUtils.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryKeyUtils.java index 82d0f48ce9..b271e91364 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryKeyUtils.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryKeyUtils.java @@ -801,7 +801,7 @@ public class DiscoveryKeyUtils { private final SearchData.PreviouslyNotable notableStatus; PreviouslyNotableGroupKey(Result result) { - this.notableStatus = result.getPreviouslyNotable(); + this.notableStatus = result.getPreviouslyNotableInCR(); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/Result.java b/Core/src/org/sleuthkit/autopsy/discovery/search/Result.java index 9d7f693f62..70bd345ad1 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/Result.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/Result.java @@ -57,11 +57,19 @@ public abstract class Result { */ public abstract TskData.FileKnown getKnown(); - final public void markAsPreviouslyNotable() { + /** + * Mark the result as being previously notable in the CR. + */ + final public void markAsPreviouslyNotableInCR() { this.isPreviouslyNotable = SearchData.PreviouslyNotable.PREVIOUSLY_NOTABLE; } - final public SearchData.PreviouslyNotable getPreviouslyNotable() { + /** + * Get the previously notable value of this result. + * + * @return The previously notable status enum. + */ + final public SearchData.PreviouslyNotable getPreviouslyNotableInCR() { return this.isPreviouslyNotable; } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/SearchData.java b/Core/src/org/sleuthkit/autopsy/discovery/search/SearchData.java index 3de4ea7db7..05e89f1220 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/SearchData.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/SearchData.java @@ -39,6 +39,9 @@ public final class SearchData { private static final Set DOMAIN_ARTIFACT_TYPES = EnumSet.of(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY); + /** + * Enum representing the notability of the result in the Central Repository. + */ @NbBundle.Messages({ "SearchData.prevNotable.displayName=Previously Notable", "SearchData.notPrevNotable.displayName=Previously Not Notable" diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java b/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java index ade423488c..c9c00998c4 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/SearchFiltering.java @@ -713,7 +713,7 @@ public class SearchFiltering { List filteredResults = new ArrayList<>(); for (Result file : currentResults) { - if (file.getPreviouslyNotable() == SearchData.PreviouslyNotable.PREVIOUSLY_NOTABLE) { + if (file.getPreviouslyNotableInCR() == SearchData.PreviouslyNotable.PREVIOUSLY_NOTABLE) { filteredResults.add(file); } } From 129e1f07f0db3938cf01e453a4e42ecf8fdf3f35 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Wed, 2 Dec 2020 10:29:20 -0500 Subject: [PATCH 3/4] Notable status variable name change --- Core/src/org/sleuthkit/autopsy/discovery/search/Result.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/Result.java b/Core/src/org/sleuthkit/autopsy/discovery/search/Result.java index 70bd345ad1..607417481a 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/Result.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/Result.java @@ -31,7 +31,7 @@ import org.sleuthkit.datamodel.TskData; public abstract class Result { private SearchData.Frequency frequency = SearchData.Frequency.UNKNOWN; - private SearchData.PreviouslyNotable isPreviouslyNotable = SearchData.PreviouslyNotable.NOT_PREVIOUSLY_NOTABLE; + private SearchData.PreviouslyNotable notabilityStatus = SearchData.PreviouslyNotable.NOT_PREVIOUSLY_NOTABLE; private final List tagNames = new ArrayList<>(); /** @@ -61,7 +61,7 @@ public abstract class Result { * Mark the result as being previously notable in the CR. */ final public void markAsPreviouslyNotableInCR() { - this.isPreviouslyNotable = SearchData.PreviouslyNotable.PREVIOUSLY_NOTABLE; + this.notabilityStatus = SearchData.PreviouslyNotable.PREVIOUSLY_NOTABLE; } /** @@ -70,7 +70,7 @@ public abstract class Result { * @return The previously notable status enum. */ final public SearchData.PreviouslyNotable getPreviouslyNotableInCR() { - return this.isPreviouslyNotable; + return this.notabilityStatus; } /** From 38344d37eef0ff8f479949711ec5b3e95aa1ad23 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Thu, 3 Dec 2020 19:49:19 -0500 Subject: [PATCH 4/4] Added in Will's fix for checkbox labels spanning multiple columns --- .../autopsy/discovery/ui/AbstractFiltersPanel.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractFiltersPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractFiltersPanel.java index c8f71a5d99..44e6446d49 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractFiltersPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/AbstractFiltersPanel.java @@ -114,8 +114,8 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li constraints.weightx = LABEL_WEIGHT; constraints.weighty = LABEL_WEIGHT; constraints.gridwidth = LABEL_WIDTH; - addToGridBagLayout(filterPanel.getCheckbox(), filterPanel.getAdditionalLabel(), column); if (filterPanel.hasPanel()) { + addToGridBagLayout(filterPanel.getCheckbox(), filterPanel.getAdditionalLabel(), column); constraints.gridx += constraints.gridwidth; constraints.fill = GridBagConstraints.BOTH; constraints.gridheight = PANEL_HEIGHT; @@ -123,6 +123,11 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li constraints.weighty = PANEL_WEIGHT; constraints.gridwidth = PANEL_WIDTH; addToGridBagLayout(filterPanel, null, column); + } else { + constraints.weightx = PANEL_WEIGHT; + constraints.fill = GridBagConstraints.BOTH; + constraints.gridwidth = PANEL_WIDTH + LABEL_WIDTH; + addToGridBagLayout(filterPanel.getCheckbox(), filterPanel.getAdditionalLabel(), column); } if (column == 0) { firstColumnY += constraints.gridheight;