From b43121d5652f21385553eef6a57aa7451b61b142 Mon Sep 17 00:00:00 2001 From: Jeff Wallace Date: Wed, 9 Oct 2013 17:47:48 -0400 Subject: [PATCH] Added filtering of known files. --- .../autopsy/corecomponents/Bundle.properties | 3 + .../autopsy/corecomponents/GeneralPanel.form | 64 ++++++- .../autopsy/corecomponents/GeneralPanel.java | 85 +++++++-- .../autopsy/datamodel/FileTypeChildren.java | 11 +- .../datamodel/KnownFileFilterNode.java | 178 ++++++++++++++++++ .../DirectoryTreeTopComponent.java | 6 +- 6 files changed, 316 insertions(+), 31 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/datamodel/KnownFileFilterNode.java diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index e89a04e083..952a8b0c87 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -109,3 +109,6 @@ MediaViewVideoPanel.infoLabel.text=info GeneralPanel.jLabel2.text=When displaying times: GeneralPanel.useLocalTimeRB.text=Use local timezone GeneralPanel.useGMTTimeRB.text=Use GMT +GeneralPanel.jLabel3.text=Hide known files in the Data Result Viewer when: +GeneralPanel.viewsHideKnownCB.text=Selecting under Views +GeneralPanel.dataSourcesHideKnownCB.text=Selecting under Data Sources diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/GeneralPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/GeneralPanel.form index a59ba4c28c..0488646444 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/GeneralPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/GeneralPanel.form @@ -22,22 +22,39 @@ - + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -50,12 +67,18 @@ + + + + + + - + @@ -126,5 +149,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/GeneralPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/GeneralPanel.java index 2c9d410e1d..833eb23b3c 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/GeneralPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/GeneralPanel.java @@ -1,16 +1,34 @@ /* - * To change this template, choose Tools | Templates - * and open the template in the editor. + * Autopsy Forensic Browser + * + * Copyright 2013 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.corecomponents; +import java.util.prefs.Preferences; import org.openide.util.NbPreferences; final class GeneralPanel extends javax.swing.JPanel { private final GeneralOptionsPanelController controller; - private final static String KEEP_PREFERRED_VIEWER = "keepPreferredViewer"; - private final static String USE_LOCAL_TIME = "useLocalTime"; + private static final String KEEP_PREFERRED_VIEWER = "keepPreferredViewer"; + private static final String USE_LOCAL_TIME = "useLocalTime"; + private static final String DS_HIDE_KNOWN = "dataSourcesHideKnown"; // Default false + private static final String VIEWS_HIDE_KNOWN = "viewsHideKnown"; // Default true + private final Preferences prefs = NbPreferences.forModule(this.getClass()); GeneralPanel(GeneralOptionsPanelController controller) { this.controller = controller; @@ -34,6 +52,9 @@ final class GeneralPanel extends javax.swing.JPanel { jLabel2 = new javax.swing.JLabel(); useLocalTimeRB = new javax.swing.JRadioButton(); useGMTTimeRB = new javax.swing.JRadioButton(); + jLabel3 = new javax.swing.JLabel(); + dataSourcesHideKnownCB = new javax.swing.JCheckBox(); + viewsHideKnownCB = new javax.swing.JCheckBox(); buttonGroup1.add(useBestViewerRB); useBestViewerRB.setSelected(true); @@ -60,6 +81,12 @@ final class GeneralPanel extends javax.swing.JPanel { buttonGroup3.add(useGMTTimeRB); org.openide.awt.Mnemonics.setLocalizedText(useGMTTimeRB, org.openide.util.NbBundle.getMessage(GeneralPanel.class, "GeneralPanel.useGMTTimeRB.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(GeneralPanel.class, "GeneralPanel.jLabel3.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(dataSourcesHideKnownCB, org.openide.util.NbBundle.getMessage(GeneralPanel.class, "GeneralPanel.dataSourcesHideKnownCB.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(viewsHideKnownCB, org.openide.util.NbBundle.getMessage(GeneralPanel.class, "GeneralPanel.viewsHideKnownCB.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -67,16 +94,27 @@ final class GeneralPanel extends javax.swing.JPanel { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel1) - .addComponent(jLabel2) .addGroup(layout.createSequentialGroup() - .addGap(10, 10, 10) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(useLocalTimeRB) - .addComponent(keepCurrentViewerRB) - .addComponent(useBestViewerRB) - .addComponent(useGMTTimeRB)))) - .addGap(0, 112, Short.MAX_VALUE)) + .addComponent(jLabel2) + .addGroup(layout.createSequentialGroup() + .addGap(10, 10, 10) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(useLocalTimeRB) + .addComponent(useGMTTimeRB)))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1) + .addComponent(jLabel3) + .addGroup(layout.createSequentialGroup() + .addGap(10, 10, 10) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(keepCurrentViewerRB) + .addComponent(useBestViewerRB) + .addComponent(dataSourcesHideKnownCB) + .addComponent(viewsHideKnownCB)))) + .addGap(0, 0, Short.MAX_VALUE)))) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -87,12 +125,18 @@ final class GeneralPanel extends javax.swing.JPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(keepCurrentViewerRB) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(dataSourcesHideKnownCB) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(viewsHideKnownCB) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(useLocalTimeRB) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(useGMTTimeRB) - .addContainerGap(26, Short.MAX_VALUE)) + .addContainerGap(30, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -101,17 +145,21 @@ final class GeneralPanel extends javax.swing.JPanel { }//GEN-LAST:event_useBestViewerRBActionPerformed void load() { - boolean keepPreferredViewer = NbPreferences.forModule(GeneralPanel.class).getBoolean(KEEP_PREFERRED_VIEWER, false); + boolean keepPreferredViewer = prefs.getBoolean(KEEP_PREFERRED_VIEWER, false); keepCurrentViewerRB.setSelected(keepPreferredViewer); useBestViewerRB.setSelected(!keepPreferredViewer); - boolean useLocalTime = NbPreferences.forModule(GeneralPanel.class).getBoolean(USE_LOCAL_TIME, true); + boolean useLocalTime = prefs.getBoolean(USE_LOCAL_TIME, true); useLocalTimeRB.setSelected(useLocalTime); useGMTTimeRB.setSelected(!useLocalTime); + dataSourcesHideKnownCB.setSelected(prefs.getBoolean(DS_HIDE_KNOWN, false)); + viewsHideKnownCB.setSelected(prefs.getBoolean(VIEWS_HIDE_KNOWN, true)); } void store() { - NbPreferences.forModule(GeneralPanel.class).putBoolean(KEEP_PREFERRED_VIEWER, keepCurrentViewerRB.isSelected()); - NbPreferences.forModule(GeneralPanel.class).putBoolean(USE_LOCAL_TIME, useLocalTimeRB.isSelected()); + prefs.putBoolean(KEEP_PREFERRED_VIEWER, keepCurrentViewerRB.isSelected()); + prefs.putBoolean(USE_LOCAL_TIME, useLocalTimeRB.isSelected()); + prefs.putBoolean(DS_HIDE_KNOWN, dataSourcesHideKnownCB.isSelected()); + prefs.putBoolean(VIEWS_HIDE_KNOWN, viewsHideKnownCB.isSelected()); } boolean valid() { @@ -121,11 +169,14 @@ final class GeneralPanel extends javax.swing.JPanel { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.ButtonGroup buttonGroup1; private javax.swing.ButtonGroup buttonGroup3; + private javax.swing.JCheckBox dataSourcesHideKnownCB; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; private javax.swing.JRadioButton keepCurrentViewerRB; private javax.swing.JRadioButton useBestViewerRB; private javax.swing.JRadioButton useGMTTimeRB; private javax.swing.JRadioButton useLocalTimeRB; + private javax.swing.JCheckBox viewsHideKnownCB; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeChildren.java index 3376e9f0d9..71d0e0e02c 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeChildren.java @@ -21,10 +21,12 @@ package org.sleuthkit.autopsy.datamodel; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; +import java.util.prefs.Preferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.openide.nodes.AbstractNode; import org.openide.nodes.ChildFactory; import org.openide.nodes.Node; +import org.openide.util.NbPreferences; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentVisitor; @@ -45,6 +47,8 @@ class FileTypeChildren extends ChildFactory { private SleuthkitCase skCase; private FileTypeExtensionFilters.SearchFilterInterface filter; private static final Logger logger = Logger.getLogger(FileTypeChildren.class.getName()); + private final Preferences prefs = NbPreferences.root().node("/org/sleuthkit/autopsy/core"); + private static final String HIDE_KNOWN = "viewsHideKnown"; //private final static int MAX_OBJECTS = 2000; public FileTypeChildren(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase) { @@ -59,8 +63,11 @@ class FileTypeChildren extends ChildFactory { } private String createQuery(){ - String query = "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")" - + " AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ") AND (0"; + String query = "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")"; + if (prefs.getBoolean(HIDE_KNOWN, true)) { + query += " AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")"; + } + query += " AND (0"; for(String s : filter.getFilter()){ query += " OR name LIKE '%" + s + "'"; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KnownFileFilterNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/KnownFileFilterNode.java new file mode 100755 index 0000000000..fdd754d64d --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KnownFileFilterNode.java @@ -0,0 +1,178 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 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.datamodel; + +import java.util.prefs.PreferenceChangeEvent; +import java.util.prefs.PreferenceChangeListener; +import java.util.prefs.Preferences; +import org.openide.nodes.FilterNode; +import org.openide.nodes.Node; +import org.openide.util.NbPreferences; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.TskData; + +/** + * A Filter Node responsible for filtering out Nodes that represent known files + * if the filter known files option is set. + * + * @author jwallace + */ +public class KnownFileFilterNode extends FilterNode { + + public enum SelectionContext { + DATA_SOURCES("Data Sources"), // Subnode of DataSources + VIEWS("Views"), // Subnode of Views + OTHER(""); // Subnode of another node. + + private final String displayName; + + SelectionContext(String displayName) { + this.displayName = displayName; + } + + public static SelectionContext getContextFromName(String name) { + if (name.equals(DATA_SOURCES.getName())) { + return DATA_SOURCES; + } else if (name.equals(VIEWS.getName())) { + return VIEWS; + } else { + return OTHER; + } + } + + private String getName() { + return displayName; + } + } + + public KnownFileFilterNode(Node arg, SelectionContext context) { + super(arg, new KnownFileFilterChildren(arg, context)); + } + + KnownFileFilterNode(Node arg, boolean filter) { + super(arg, new KnownFileFilterChildren(arg, filter)); + } + + public static SelectionContext getSelectionContext(Node n) { + if (n == null) { + // Parent of root node. Should never get here. + return SelectionContext.OTHER; + } else if (n.getParentNode().getParentNode() == null) { + // One level below root node. Should be one of DataSources, Views, or Results + return SelectionContext.getContextFromName(n.getDisplayName()); + } else { + return getSelectionContext(n.getParentNode()); + } + } +} + +/** + * Complementary class to KnownFileFilterNode. + * + * Listens for changes to the Filter Known Files option. Filters out children + * the Nodes which represent known files. Otherwise, returns the original node + * wrapped in another instance of the KnownFileFilterNode. + * + * @author jwallace + */ +class KnownFileFilterChildren extends FilterNode.Children { + + /** Preference key values. */ + private static final String DS_HIDE_KNOWN = "dataSourcesHideKnown"; // Default false + private static final String VIEWS_HIDE_KNOWN = "viewsHideKnown"; // Default true + + /** True if Nodes selected from the Views Node should filter Known Files. */ + private static boolean filterFromViews = true; + + /** True if Nodes selected from the DataSources Node should filter Known Files. */ + private static boolean filterFromDataSources = false; + + /** True if a listener has not been added to the preferences. */ + private static boolean addListener = true; + + /** True if this KnownFileFilterChildren should filter out known files. */ + private boolean filter; + + /** + * Constructor used when the context has already been determined. + * Should only be used internally by KnownFileFilerNode. + * @param arg + * @param filter + */ + KnownFileFilterChildren(Node arg, boolean filter) { + super(arg); + this.filter = filter; + } + + /** + * Constructor used when the context has not been determined. + * @param arg + * @param context + */ + KnownFileFilterChildren(Node arg, KnownFileFilterNode.SelectionContext context) { + super(arg); + + if (addListener) { + Preferences prefs = NbPreferences.root().node("/org/sleuthkit/autopsy/core"); + // Initialize with values stored in preferences + filterFromViews = prefs.getBoolean(VIEWS_HIDE_KNOWN, filterFromViews); + filterFromDataSources = prefs.getBoolean(DS_HIDE_KNOWN, filterFromDataSources); + + // Add listener + prefs.addPreferenceChangeListener(new PreferenceChangeListener() { + @Override + public void preferenceChange(PreferenceChangeEvent evt) { + switch (evt.getKey()) { + case VIEWS_HIDE_KNOWN: + filterFromViews = evt.getNode().getBoolean(VIEWS_HIDE_KNOWN, filterFromViews); + break; + case DS_HIDE_KNOWN: + filterFromDataSources = evt.getNode().getBoolean(DS_HIDE_KNOWN, filterFromDataSources); + break; + } + } + }); + addListener = false; + } + + switch (context) { + case DATA_SOURCES: + filter = filterFromDataSources; + break; + case VIEWS: + filter = filterFromViews; + break; + default: + filter = false; + break; + } + } + + @Override + protected Node[] createNodes(Node arg) { + if (filter) { + // Filter out child nodes that represent known files + AbstractFile file = arg.getLookup().lookup(AbstractFile.class); + if (file!= null && file.getKnown() == TskData.FileKnown.KNOWN) { + return new Node[]{}; + } + } + return new Node[] { new KnownFileFilterNode(arg, filter) }; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 05ae16d893..0d48589834 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -56,6 +56,7 @@ import org.sleuthkit.autopsy.datamodel.ExtractedContentNode; import org.sleuthkit.autopsy.datamodel.DataSources; import org.sleuthkit.autopsy.datamodel.DataSourcesNode; import org.sleuthkit.autopsy.datamodel.KeywordHits; +import org.sleuthkit.autopsy.datamodel.KnownFileFilterNode; import org.sleuthkit.autopsy.datamodel.Results; import org.sleuthkit.autopsy.datamodel.ResultsNode; import org.sleuthkit.autopsy.datamodel.RootContentChildren; @@ -634,7 +635,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat //set node, wrap in filter node first to filter out children Node drfn = new DataResultFilterNode(originNode, DirectoryTreeTopComponent.this.em); - dataResult.setNode(new TableFilterNode(drfn, true)); + Node kffn = new KnownFileFilterNode(drfn, KnownFileFilterNode.getSelectionContext(treeNode)); + dataResult.setNode(new TableFilterNode(kffn, true)); String displayName = ""; Content content = originNode.getLookup().lookup(Content.class); @@ -671,7 +673,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat // update the back and forward list updateHistory(em.getSelectedNodes()); } - + private void updateHistory(Node[] selectedNodes) { if (selectedNodes.length == 0) { return;