diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java index d4f2ce0e8e..aee8368831 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java @@ -19,6 +19,8 @@ package org.sleuthkit.autopsy.datamodel; import java.awt.event.ActionEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; @@ -27,6 +29,7 @@ import java.util.List; import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.Action; +import org.openide.nodes.Children; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; @@ -35,11 +38,14 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.directorytree.ExplorerNodeActionVisitor; import org.sleuthkit.autopsy.directorytree.FileSearchAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; +import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.RunIngestModulesDialog; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.VirtualDirectory; /** * This class is used to represent the "Node" for the image. The children of @@ -71,6 +77,16 @@ public class ImageNode extends AbstractContentNode { String imgName = nameForImage(img); this.setDisplayName(imgName); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/hard-drive-icon.jpg"); //NON-NLS + + // Listen for ingest events so that we can detect new added files (e.g. carved) + IngestManager.getInstance().addIngestModuleEventListener(pcl); + // Listen for case events so that we can detect when case is closed + Case.addPropertyChangeListener(pcl); + } + + private void removeListeners() { + IngestManager.getInstance().removeIngestModuleEventListener(pcl); + Case.removePropertyChangeListener(pcl); } /** @@ -199,4 +215,46 @@ public class ImageNode extends AbstractContentNode { public String getItemType() { return getClass().getName(); } + + private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { + String eventType = evt.getPropertyName(); + + // See if the new file is a child of ours + if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { + if ((evt.getOldValue() instanceof ModuleContentEvent) == false) { + return; + } + ModuleContentEvent moduleContentEvent = (ModuleContentEvent) evt.getOldValue(); + if ((moduleContentEvent.getSource() instanceof Content) == false) { + return; + } + Content newContent = (Content) moduleContentEvent.getSource(); + + try { + Content parent = newContent.getParent(); + if (parent != null) { + // Is this a new carved file? + if (parent.getName().equals(VirtualDirectory.NAME_CARVED)) { + // Was this new carved file produced from this image? + if (parent.getParent().getId() == getContent().getId()) { + Children children = getChildren(); + if (children != null) { + ((ContentChildren) children).refreshChildren(); + children.getNodesCount(); + } + } + } + } + } catch (TskCoreException ex) { + // Do nothing. + } + } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + if (evt.getNewValue() == null) { + // case was closed. Remove listeners so that we don't get called with a stale case handle + removeListeners(); + } + } + }; + + } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties index c119e136dd..d5fa88092b 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties @@ -82,7 +82,13 @@ ConfirmationDialog.Exit=Exit ConfirmationDialog.DoNotExit=Do Not Exit ConfirmationDialog.ConfirmExit=All incomplete copy jobs will be cancelled. Are you sure? ConfirmationDialog.ConfirmExitHeader=Confirm Exit +OpenIDE-Module-Long-Description=\ + This module contains features that are being developed by Basis Technology and are not part of the default Autopsy distribution. \ + You can enable this module to use the new features. \ + The features should be stable, but their exact behavior and API are subject to change. \n\n\ + We make no guarantee that the API of this module will not change, so developers should be careful when relying on it. OpenIDE-Module-Name=Experimental +OpenIDE-Module-Short-Description=This module contains features that are being developed by Basis Technology and are not part of the default Autopsy distribution. ReviewModeCasePanel.bnRefresh.text=&Refresh ReviewModeCasePanel.bnOpen.text=&Open ReviewModeCasePanel.rbGroupLabel.text=Show Last 10: diff --git a/KeywordSearch/release/solr/solr/configsets/AutopsyConfig/conf/schema.xml b/KeywordSearch/release/solr/solr/configsets/AutopsyConfig/conf/schema.xml index 7bfafe964e..6c4466d61e 100644 --- a/KeywordSearch/release/solr/solr/configsets/AutopsyConfig/conf/schema.xml +++ b/KeywordSearch/release/solr/solr/configsets/AutopsyConfig/conf/schema.xml @@ -524,6 +524,7 @@ +