From dfefa0b8e6dc88eea0a43d84a7e3eb0f28ab84b0 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 10 Sep 2013 11:29:28 -0400 Subject: [PATCH 01/11] removed decoded URL from artifacts because it takes up a lot of table space and doesn't provide much. --- .../org/sleuthkit/autopsy/recentactivity/Chrome.java | 10 +++++----- .../sleuthkit/autopsy/recentactivity/ExtractIE.java | 6 +++--- .../org/sleuthkit/autopsy/recentactivity/Firefox.java | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java index 1ca8ff9a0e..2d10921deb 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java @@ -138,7 +138,7 @@ public class Chrome extends Extract { Collection bbattributes = new ArrayList(); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? result.get("url").toString() : ""))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : ""))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : ""))); //TODO Revisit usage of deprecated constructor per TSK-583 //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", ((Long.valueOf(result.get("last_visit_time").toString())) / 10000000))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", ((Long.valueOf(result.get("last_visit_time").toString())) / 10000000))); @@ -232,7 +232,7 @@ public class Chrome extends Extract { //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", (date / 10000000))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", (date / 10000000))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", url)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", EscapeUtil.decodeURL(url))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", EscapeUtil.decodeURL(url))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "Recent Activity", name)); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "Recent Activity", "Chrome")); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", domain)); @@ -299,7 +299,7 @@ public class Chrome extends Extract { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "Recent Activity", ((result.get("value").toString() != null) ? result.get("value").toString() : ""))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "Recent Activity", "Chrome")); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("host_key").toString() != null) ? result.get("host_key").toString() : ""))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("host_key").toString() != null) ? EscapeUtil.decodeURL(result.get("host_key").toString()) : ""))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("host_key").toString() != null) ? EscapeUtil.decodeURL(result.get("host_key").toString()) : ""))); String domain = result.get("host_key").toString(); domain = domain.replaceFirst("^\\.+(?!$)", ""); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", domain)); @@ -358,7 +358,7 @@ public class Chrome extends Extract { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), "Recent Activity", (result.get("full_path").toString()))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID(), "Recent Activity", Util.findID(dataSource, (result.get("full_path").toString())))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? result.get("url").toString() : ""))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : ""))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : ""))); Long time = (Long.valueOf(result.get("start_time").toString())); String Tempdate = time.toString(); time = Long.valueOf(Tempdate) / 10000000; @@ -417,7 +417,7 @@ public class Chrome extends Extract { for (HashMap result : tempList) { Collection bbattributes = new ArrayList(); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("origin_url").toString() != null) ? result.get("origin_url").toString() : ""))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("origin_url").toString() != null) ? EscapeUtil.decodeURL(result.get("origin_url").toString()) : ""))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("origin_url").toString() != null) ? EscapeUtil.decodeURL(result.get("origin_url").toString()) : ""))); //TODO Revisit usage of deprecated constructor as per TSK-583 //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", ((Long.valueOf(result.get("last_visit_time").toString())) / 1000000))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", ((Long.valueOf(result.get("last_visit_time").toString())) / 1000000))); diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java index 0b00d47732..16d2d99e11 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java @@ -189,7 +189,7 @@ public class ExtractIE extends Extract { //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", datetime)); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "RecentActivity", datetime)); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", url)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(url))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(url))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", name)); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "RecentActivity", "Internet Explorer")); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "RecentActivity", domain)); @@ -238,7 +238,7 @@ public class ExtractIE extends Extract { Collection bbattributes = new ArrayList(); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", url)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(url))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(url))); //TODO Revisit usage of deprecated Constructor as of TSK-583 //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "RecentActivity", "Last Visited", datetime)); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "RecentActivity", datetime)); @@ -505,7 +505,7 @@ public class ExtractIE extends Extract { BlackboardArtifact bbart = tskCase.getContentById(artObjId).newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY); Collection bbattributes = new ArrayList(); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", realurl)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(realurl))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(realurl))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "RecentActivity", ftime)); diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java index 3b39b21ff8..4322a2b926 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java @@ -119,7 +119,7 @@ public class Firefox extends Extract { for (HashMap result : tempList) { Collection bbattributes = new ArrayList(); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? result.get("url").toString() : ""))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : ""))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : ""))); //TODO Revisit usage of deprecated constructor as per TSK-583 //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("visit_date").toString())))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "RecentActivity", (Long.valueOf(result.get("visit_date").toString())))); @@ -177,7 +177,7 @@ public class Firefox extends Extract { Collection bbattributes = new ArrayList(); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? result.get("url").toString() : ""))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : ""))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : ""))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", ((result.get("title").toString() != null) ? result.get("title").toString() : ""))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "RecentActivity", "FireFox")); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "RecentActivity", (Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); @@ -241,7 +241,7 @@ public class Firefox extends Extract { Collection bbattributes = new ArrayList(); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", ((result.get("host").toString() != null) ? result.get("host").toString() : ""))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("host").toString() != null) ? EscapeUtil.decodeURL(result.get("host").toString()) : ""))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("host").toString() != null) ? EscapeUtil.decodeURL(result.get("host").toString()) : ""))); //TODO Revisit usage of deprecated constructor as per TSK-583 //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", "Title", ((result.get("name").toString() != null) ? result.get("name").toString() : ""))); //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("lastAccessed").toString())))); @@ -312,7 +312,7 @@ public class Firefox extends Extract { Collection bbattributes = new ArrayList(); String urldecodedtarget = URLDecoder.decode(result.get("source").toString().replaceAll("file:///", ""), "UTF-8"); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? result.get("source").toString() : ""))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : ""))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : ""))); //TODO Revisit usage of deprecated constructor as per TSK-583 //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("startTime").toString())))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "RecentActivity", (Long.valueOf(result.get("startTime").toString())))); From c346fe607a4d70e14febe6bc013e39f63d2a1bc4 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 10 Sep 2013 15:57:08 -0400 Subject: [PATCH 02/11] added object id to metadata viewer --- Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java index cae2561fc8..6fa7960527 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java @@ -144,6 +144,8 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer } addRow(sb, "MD5", md5); + addRow(sb, "Internal ID", new Long(file.getId()).toString()); + endTable(sb); setText(sb.toString()); } From 282523a46f0bb174d3050a61293d1bf25ee3855f Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 10 Sep 2013 15:58:03 -0400 Subject: [PATCH 03/11] minor renaming and updates to IE parsing --- .../autopsy/recentactivity/ExtractIE.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java index 16d2d99e11..bbf876a7c6 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java @@ -136,7 +136,7 @@ public class ExtractIE extends Extract { } try { - this.parsePascoResults(pascoResults); + this.getHistory(pascoResults); } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing IE History", e); @@ -394,7 +394,7 @@ public class ExtractIE extends Extract { execPasco.execute(writer, JAVA_PATH, "-cp", PASCO_LIB_PATH, "isi.pasco2.Main", "-T", "history", indexFilePath ); - + // @@@ Investigate use of history versus cache as type. } catch (IOException ex) { success = false; logger.log(Level.SEVERE, "Unable to execute Pasco to process Internet Explorer web history.", ex); @@ -416,7 +416,7 @@ public class ExtractIE extends Extract { return success; } - private void parsePascoResults(List filenames) { + private void getHistory(List filenames) { if (pascoFound == false) { return; } @@ -451,6 +451,15 @@ public class ExtractIE extends Extract { String line = fileScanner.nextLine(); + // lines at end of file + if ((line.startsWith("LEAK entries")) || + (line.startsWith("REDR entries")) || + (line.startsWith("URL entries")) || + (line.startsWith("ent entries")) || + (line.startsWith("unknown entries"))) { + continue; + } + if (line.startsWith("URL")) { String[] lineBuff = line.split("\\t"); @@ -466,6 +475,10 @@ public class ExtractIE extends Extract { String realurl = ""; String domain = ""; + /* We've seen two types of lines: + * URL http://XYZ.com .... + * URL Visited: Joe@http://XYZ.com .... + */ if (lineBuff[1].contains("@")) { String url[] = lineBuff[1].split("@", 2); user = url[0]; From cb3679c0dfa60036333e473c5f632504475cf0db Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 11 Sep 2013 12:07:12 -0400 Subject: [PATCH 04/11] Workaround for undesirable interaction between viewers in keyword search results --- .../sleuthkit/autopsy/corecomponents/DataResultPanel.java | 7 ++++++- .../autopsy/corecomponents/DataResultViewerTable.java | 1 - .../autopsy/corecomponents/DataResultViewerThumbnail.java | 1 - 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java index 18a13ec560..755f2d01d9 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java @@ -189,7 +189,12 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C // to better handle the ExplorerManager sharing implemented to support actions that operate on // multiple selected nodes. addDataResultViewer(new DataResultViewerTable(this.explorerManager)); - addDataResultViewer(new DataResultViewerThumbnail(this.explorerManager)); + + // @@@ Temporary fix until unintended interaction between DataResultViewerTable and DataResultViewerThumbnail + // via the shared ExplorerManager in a Keyword Search Result window is resolved. + if (isMain) { + addDataResultViewer(new DataResultViewerThumbnail(this.explorerManager)); + } // Find all DataResultViewer service providers and add them to the tabbed pane. for (DataResultViewer factory : Lookup.getDefault().lookupAll(DataResultViewer.class)) { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 36ccb8715d..1da346f00c 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -78,7 +78,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer { ov.setAllowedDragActions(DnDConstants.ACTION_NONE); ov.setAllowedDropActions(DnDConstants.ACTION_NONE); - // only allow one item to be selected at a time ov.getOutline().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); // don't show the root node diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java index 9c4fd31609..a9a70152df 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java @@ -85,7 +85,6 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { private void initialize() { initComponents(); - // only allow one item to be selected at a time ((IconView) thumbnailScrollPanel).setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); curPage = -1; From 9c48c2ddd5412d76b6bdf5fdc7ddca652edd44e0 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 11 Sep 2013 15:34:04 -0400 Subject: [PATCH 05/11] move list of supported extentions to specific panels because 32-bit did not really support swf. --- .../DataContentViewerMedia.java | 27 +++++++++---------- .../autopsy/corecomponents/FXVideoPanel.java | 6 +++++ .../autopsy/corecomponents/GstVideoPanel.java | 7 +++++ .../corecomponents/MediaViewVideoPanel.java | 5 ++++ 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index 544bc6b85b..94c8523c45 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -25,9 +25,7 @@ import java.util.Arrays; import java.util.logging.Level; import javax.imageio.ImageIO; import org.sleuthkit.autopsy.coreutils.Logger; -import javax.swing.SwingUtilities; import org.openide.nodes.Node; -import org.openide.util.Exceptions; import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProviders; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; @@ -41,16 +39,15 @@ import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM; @ServiceProvider(service = DataContentViewer.class, position = 5) }) public class DataContentViewerMedia extends javax.swing.JPanel implements DataContentViewer { - - private String[] IMAGES; // use javafx supported - private static final String[] VIDEOS = new String[]{".swf", ".mov", ".m4v", ".flv", ".mp4", ".3gp", ".avi", ".mpg", ".mpeg", ".wmv"}; - private static final String[] AUDIOS = new String[]{".mp3", ".wav", ".wma"}; + private static final String[] AUDIO_EXTENSIONS = new String[]{".mp3", ".wav", ".wma"}; private static final Logger logger = Logger.getLogger(DataContentViewerMedia.class.getName()); private AbstractFile lastFile; //UI private final MediaViewVideoPanel videoPanel; + private final String[] videoExtensions; // get them from the panel + private String[] imageExtensions; // use javafx supported private final MediaViewImagePanel imagePanel; private boolean videoPanelInited; private boolean imagePanelInited; @@ -72,6 +69,8 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo videoPanelInited = videoPanel.isInited(); imagePanelInited = imagePanel.isInited(); + videoExtensions = videoPanel.getExtensions(); + customizeComponents(); logger.log(Level.INFO, "Created MediaView instance: " + this); } @@ -80,12 +79,12 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo //initialize supported image types //TODO use mime-types instead once we have support String[] fxSupportedImagesSuffixes = ImageIO.getReaderFileSuffixes(); - IMAGES = new String[fxSupportedImagesSuffixes.length]; + imageExtensions = new String[fxSupportedImagesSuffixes.length]; //logger.log(Level.INFO, "Supported image formats by javafx image viewer: "); for (int i = 0; i < fxSupportedImagesSuffixes.length; ++i) { String suffix = fxSupportedImagesSuffixes[i]; //logger.log(Level.INFO, "suffix: " + suffix); - IMAGES[i] = "." + suffix; + imageExtensions[i] = "." + suffix; } add(imagePanel, IMAGE_VIEWER_LAYER); @@ -132,11 +131,11 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo final Dimension dims = DataContentViewerMedia.this.getSize(); - if (imagePanelInited && containsExt(file.getName(), IMAGES)) { + if (imagePanelInited && containsExt(file.getName(), imageExtensions)) { imagePanel.showImageFx(file, dims); this.switchPanels(false); } else if (videoPanelInited - && (containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS))) { + && (containsExt(file.getName(), videoExtensions) || containsExt(file.getName(), AUDIO_EXTENSIONS))) { videoPanel.setupVideo(file, dims); switchPanels(true); } @@ -203,13 +202,13 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo } String name = file.getName().toLowerCase(); - if (imagePanelInited && containsExt(name, IMAGES)) { + if (imagePanelInited && containsExt(name, imageExtensions)) { return true; } //for gstreamer formats, check if initialized first, then //support audio formats, and video formats else if (videoPanelInited && videoPanel.isInited() - && (containsExt(name, AUDIOS) - || (containsExt(name, VIDEOS)))) { + && (containsExt(name, AUDIO_EXTENSIONS) + || (containsExt(name, videoExtensions)))) { return true; } @@ -227,7 +226,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo String name = file.getName().toLowerCase(); boolean deleted = file.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC); - if (containsExt(name, VIDEOS) && deleted) { + if (containsExt(name, videoExtensions) && deleted) { return 0; } else { return 7; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/FXVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/FXVideoPanel.java index 88e8cc3105..132e84a8cf 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/FXVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/FXVideoPanel.java @@ -76,6 +76,7 @@ import org.sleuthkit.datamodel.TskData; }) public class FXVideoPanel extends MediaViewVideoPanel { + private static final String[] EXTENSIONS = new String[]{".swf", ".mov", ".m4v", ".flv", ".mp4", ".3gp", ".avi", ".mpg", ".mpeg", ".wmv"}; private static final Logger logger = Logger.getLogger(MediaViewVideoPanel.class.getName()); private boolean fxInited = false; // FX Components @@ -639,4 +640,9 @@ public class FXVideoPanel extends MediaViewVideoPanel { // return frames; // } // } + + @Override + public String[] getExtensions() { + return EXTENSIONS; + } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java index 1eea6fb84d..e81fe519c7 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java @@ -67,6 +67,8 @@ import org.sleuthkit.datamodel.TskData; }) public class GstVideoPanel extends MediaViewVideoPanel { + private static final String[] EXTENSIONS = new String[]{".mov", ".m4v", ".flv", ".mp4", ".3gp", ".avi", ".mpg", ".mpeg", ".wmv"}; + private static final Logger logger = Logger.getLogger(GstVideoPanel.class.getName()); private boolean gstInited; private static final long MIN_FRAME_INTERVAL_MILLIS = 500; @@ -767,4 +769,9 @@ public class GstVideoPanel extends MediaViewVideoPanel { }); } } + + @Override + public String[] getExtensions() { + return EXTENSIONS; + } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java index b76724c08b..9275ef7c1d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java @@ -115,4 +115,9 @@ public abstract class MediaViewVideoPanel extends JPanel implements FrameCapture * @param dims dimension of the parent window */ abstract void setupVideo(final AbstractFile file, final Dimension dims); + + /** + * Return the extensions supported by this video panel. + */ + abstract public String[] getExtensions(); } From 8d26819abbe9c6331d4a7c979835ca60c951a9c1 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 11 Sep 2013 18:34:19 -0400 Subject: [PATCH 06/11] renamed and refactored file type views to make them easier to navigate --- .../datamodel/AbstractContentChildren.java | 4 +- .../autopsy/datamodel/AutopsyItemVisitor.java | 16 ++-- .../datamodel/DisplayableItemNodeVisitor.java | 8 +- ...terChildren.java => FileTypeChildren.java} | 14 ++-- ...ers.java => FileTypeExtensionFilters.java} | 11 ++- .../autopsy/datamodel/FileTypeExtensions.java | 18 +++++ ...earchFilterNode.java => FileTypeNode.java} | 12 +-- .../autopsy/datamodel/FileTypesChildren.java | 75 +++++++++++++++++++ ...rchFiltersNode.java => FileTypesNode.java} | 18 +++-- .../datamodel/SearchFiltersChildren.java | 68 ----------------- .../autopsy/datamodel/ViewsNode.java | 2 +- 11 files changed, 141 insertions(+), 105 deletions(-) rename Core/src/org/sleuthkit/autopsy/datamodel/{FileSearchFilterChildren.java => FileTypeChildren.java} (87%) rename Core/src/org/sleuthkit/autopsy/datamodel/{SearchFilters.java => FileTypeExtensionFilters.java} (93%) rename Core/src/org/sleuthkit/autopsy/datamodel/{FileSearchFilterNode.java => FileTypeNode.java} (84%) create mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/FileTypesChildren.java rename Core/src/org/sleuthkit/autopsy/datamodel/{SearchFiltersNode.java => FileTypesNode.java} (76%) delete mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersChildren.java diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java index 76ad367ace..97d9e99524 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java @@ -122,8 +122,8 @@ abstract class AbstractContentChildren extends Keys { } @Override - public AbstractNode visit(SearchFilters sf) { - return new SearchFiltersNode(sf.getSleuthkitCase(), null); + public AbstractNode visit(FileTypeExtensionFilters sf) { + return new FileTypesNode(sf.getSleuthkitCase(), null); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java index 431c9adf27..428db99c76 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java @@ -26,13 +26,13 @@ public interface AutopsyItemVisitor { T visit(ExtractedContent ec); - T visit(SearchFilters sf); + T visit(FileTypeExtensionFilters sf); - T visit(SearchFilters.FileSearchFilter fsf); + T visit(FileTypeExtensionFilters.RootFilter fsf); - T visit(SearchFilters.DocumentFilter df); + T visit(FileTypeExtensionFilters.DocumentFilter df); - T visit(SearchFilters.ExecutableFilter ef); + T visit(FileTypeExtensionFilters.ExecutableFilter ef); T visit(RecentFiles rf); @@ -70,22 +70,22 @@ public interface AutopsyItemVisitor { } @Override - public T visit(SearchFilters sf) { + public T visit(FileTypeExtensionFilters sf) { return defaultVisit(sf); } @Override - public T visit(SearchFilters.FileSearchFilter fsf) { + public T visit(FileTypeExtensionFilters.RootFilter fsf) { return defaultVisit(fsf); } @Override - public T visit(SearchFilters.DocumentFilter df) { + public T visit(FileTypeExtensionFilters.DocumentFilter df) { return defaultVisit(df); } @Override - public T visit(SearchFilters.ExecutableFilter ef) { + public T visit(FileTypeExtensionFilters.ExecutableFilter ef) { return defaultVisit(ef); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index 9072a35689..6e42c7d611 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -53,7 +53,7 @@ public interface DisplayableItemNodeVisitor { T visit(ExtractedContentNode ecn); - T visit(FileSearchFilterNode fsfn); + T visit(FileTypeNode fsfn); T visit(DeletedContentNode dcn); @@ -63,7 +63,7 @@ public interface DisplayableItemNodeVisitor { T visit(FileSizeNode fsn); - T visit(SearchFiltersNode sfn); + T visit(FileTypesNode sfn); T visit(RecentFilesNode rfn); @@ -155,7 +155,7 @@ public interface DisplayableItemNodeVisitor { } @Override - public T visit(FileSearchFilterNode fsfn) { + public T visit(FileTypeNode fsfn) { return defaultVisit(fsfn); } @@ -180,7 +180,7 @@ public interface DisplayableItemNodeVisitor { } @Override - public T visit(SearchFiltersNode sfn) { + public T visit(FileTypesNode sfn) { return defaultVisit(sfn); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeChildren.java similarity index 87% rename from Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterChildren.java rename to Core/src/org/sleuthkit/autopsy/datamodel/FileTypeChildren.java index cc4f6309f0..7196857b94 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeChildren.java @@ -38,16 +38,16 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; /** - * Children factory for the file by type view in dir tree + * Children factory for a specific file type - does the database query. */ -class FileSearchFilterChildren extends ChildFactory { +class FileTypeChildren extends ChildFactory { private SleuthkitCase skCase; - private SearchFilters.SearchFilterInterface filter; - private static final Logger logger = Logger.getLogger(FileSearchFilterChildren.class.getName()); + private FileTypeExtensionFilters.SearchFilterInterface filter; + private static final Logger logger = Logger.getLogger(FileTypeChildren.class.getName()); //private final static int MAX_OBJECTS = 2000; - public FileSearchFilterChildren(SearchFilters.SearchFilterInterface filter, SleuthkitCase skCase) { + public FileTypeChildren(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase) { this.filter = filter; this.skCase = skCase; } @@ -61,7 +61,7 @@ class FileSearchFilterChildren extends ChildFactory { private String createQuery(){ String query = "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")" - + " AND (known IS NULL OR known != 1) AND (0"; + + " AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN + ") AND (0"; for(String s : filter.getFilter()){ query += " OR name LIKE '%" + s + "'"; } @@ -72,7 +72,7 @@ class FileSearchFilterChildren extends ChildFactory { private List runQuery(){ - List list = new ArrayList(); + List list = new ArrayList<>(); try { List res = skCase.findAllFilesWhere(createQuery()); for(AbstractFile c : res){ diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SearchFilters.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeExtensionFilters.java similarity index 93% rename from Core/src/org/sleuthkit/autopsy/datamodel/SearchFilters.java rename to Core/src/org/sleuthkit/autopsy/datamodel/FileTypeExtensionFilters.java index 4bdbe641b7..3f08fd807e 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/SearchFilters.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeExtensionFilters.java @@ -25,11 +25,12 @@ import org.sleuthkit.datamodel.SleuthkitCase; /** * Filters database results by file extension. */ -public class SearchFilters implements AutopsyVisitableItem { +public class FileTypeExtensionFilters implements AutopsyVisitableItem { private SleuthkitCase skCase; - public enum FileSearchFilter implements AutopsyVisitableItem,SearchFilterInterface { + // root node filters + public enum RootFilter implements AutopsyVisitableItem,SearchFilterInterface { TSK_IMAGE_FILTER(0, "TSK_IMAGE_FILTER", "Images", FileTypeExtensions.getImageExtensions()), TSK_VIDEO_FILTER(1, "TSK_VIDEO_FILTER", "Videos", FileTypeExtensions.getVideoExtensions()), TSK_AUDIO_FILTER(2, "TSK_AUDIO_FILTER", "Audio", FileTypeExtensions.getAudioExtensions()), @@ -42,7 +43,7 @@ public class SearchFilters implements AutopsyVisitableItem { private String displayName; private List filter; - private FileSearchFilter(int id, String name, String displayName, List filter){ + private RootFilter(int id, String name, String displayName, List filter){ this.id = id; this.name = name; this.displayName = displayName; @@ -75,6 +76,7 @@ public class SearchFilters implements AutopsyVisitableItem { } } + // document sub-node filters public enum DocumentFilter implements AutopsyVisitableItem,SearchFilterInterface { AUT_DOC_HTML(0, "AUT_DOC_HTML", "HTML", Arrays.asList(".htm", ".html")), AUT_DOC_OFFICE(1, "AUT_DOC_OFFICE", "Office", Arrays.asList(".doc", ".docx", @@ -122,6 +124,7 @@ public class SearchFilters implements AutopsyVisitableItem { } + // executable sub-node filters public enum ExecutableFilter implements AutopsyVisitableItem,SearchFilterInterface { ExecutableFilter_EXE(0, "ExecutableFilter_EXE", ".exe", Arrays.asList(".exe")), ExecutableFilter_DLL(1, "ExecutableFilter_DLL", ".dll", Arrays.asList(".dll")), @@ -167,7 +170,7 @@ public class SearchFilters implements AutopsyVisitableItem { } } - public SearchFilters(SleuthkitCase skCase){ + public FileTypeExtensionFilters(SleuthkitCase skCase){ this.skCase = skCase; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeExtensions.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeExtensions.java index 74a54ef66e..0b067a4678 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeExtensions.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeExtensions.java @@ -1,3 +1,21 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-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.Arrays; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeNode.java similarity index 84% rename from Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterNode.java rename to Core/src/org/sleuthkit/autopsy/datamodel/FileTypeNode.java index 2313d08429..3af3340bac 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeNode.java @@ -24,15 +24,15 @@ import org.openide.util.lookup.Lookups; import org.sleuthkit.datamodel.SleuthkitCase; /** - * Node for the file search filter + * Node for a specific file type / extension */ -public class FileSearchFilterNode extends DisplayableItemNode { +public class FileTypeNode extends DisplayableItemNode { - SearchFilters.SearchFilterInterface filter; + FileTypeExtensionFilters.SearchFilterInterface filter; SleuthkitCase skCase; - FileSearchFilterNode(SearchFilters.SearchFilterInterface filter, SleuthkitCase skCase) { - super(Children.create(new FileSearchFilterChildren(filter, skCase), true), Lookups.singleton(filter.getDisplayName())); + FileTypeNode(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase) { + super(Children.create(new FileTypeChildren(filter, skCase), true), Lookups.singleton(filter.getDisplayName())); this.filter = filter; this.skCase = skCase; @@ -40,7 +40,7 @@ public class FileSearchFilterNode extends DisplayableItemNode { super.setName(filter.getName()); //get count of children without preloading all children nodes - final long count = new FileSearchFilterChildren(filter, skCase).calculateItems(); + final long count = new FileTypeChildren(filter, skCase).calculateItems(); //final long count = getChildren().getNodesCount(true); super.setDisplayName(filter.getDisplayName() + " (" + count + ")"); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesChildren.java new file mode 100644 index 0000000000..e55124bebc --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesChildren.java @@ -0,0 +1,75 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011 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.Arrays; +import java.util.List; +import org.openide.nodes.ChildFactory; +import org.openide.nodes.Node; +import org.sleuthkit.autopsy.datamodel.FileTypeExtensionFilters.RootFilter; +import org.sleuthkit.datamodel.SleuthkitCase; + +/** + * + */ +class FileTypesChildren extends ChildFactory { + + private SleuthkitCase skCase; + private FileTypeExtensionFilters.RootFilter filter; + + /** + * + * @param skCase + * @param filter Is null for root node + */ + public FileTypesChildren(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter) { + this.skCase = skCase; + this.filter = filter; + } + + @Override + protected boolean createKeys(List list) { + // root node + if (filter == null) { + list.addAll(Arrays.asList(RootFilter.values())); + } + // document and executable has another level of nodes + else if (filter.equals(RootFilter.TSK_DOCUMENT_FILTER) ){ + list.addAll(Arrays.asList(FileTypeExtensionFilters.DocumentFilter.values())); + } + else if (filter.equals(RootFilter.TSK_EXECUTABLE_FILTER) ){ + list.addAll(Arrays.asList(FileTypeExtensionFilters.ExecutableFilter.values())); + } + return true; + } + + @Override + protected Node createNodeForKey(FileTypeExtensionFilters.SearchFilterInterface key){ + // make new nodes for the sub-nodes + if(key.getName().equals(FileTypeExtensionFilters.RootFilter.TSK_DOCUMENT_FILTER.getName())){ + return new FileTypesNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_DOCUMENT_FILTER); + } + else if(key.getName().equals(FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER.getName())){ + return new FileTypesNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER); + } + else { + return new FileTypeNode(key, skCase); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java similarity index 76% rename from Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersNode.java rename to Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java index 6eabf8cc79..b8198c0d14 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java @@ -24,19 +24,27 @@ import org.openide.util.lookup.Lookups; import org.sleuthkit.datamodel.SleuthkitCase; /** - * Node for search filter + * Node for extension/file type filter view */ -public class SearchFiltersNode extends DisplayableItemNode { +public class FileTypesNode extends DisplayableItemNode { private static final String FNAME = "File Types"; private SleuthkitCase skCase; - SearchFiltersNode(SleuthkitCase skCase, SearchFilters.FileSearchFilter filter) { - super(Children.create(new SearchFiltersChildren(skCase, filter), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); + /** + * + * @param skCase + * @param filter null to display root node of file type tree, pass in something to provide a sub-node. + */ + FileTypesNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter) { + super(Children.create(new FileTypesChildren(skCase, filter), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); + // root node of tree if (filter == null) { super.setName(FNAME); super.setDisplayName(FNAME); - } else { + } + // sub-node in file tree (i.e. documents, exec, etc.) + else { super.setName(filter.getName()); super.setDisplayName(filter.getDisplayName()); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersChildren.java deleted file mode 100644 index cdc1109a47..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersChildren.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 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.Arrays; -import java.util.List; -import org.openide.nodes.ChildFactory; -import org.openide.nodes.Node; -import org.sleuthkit.autopsy.datamodel.SearchFilters.FileSearchFilter; -import org.sleuthkit.datamodel.SleuthkitCase; - -/** - * - */ -class SearchFiltersChildren extends ChildFactory { - - private SleuthkitCase skCase; - private SearchFilters.FileSearchFilter filter; - - public SearchFiltersChildren(SleuthkitCase skCase, SearchFilters.FileSearchFilter filter) { - this.skCase = skCase; - this.filter = filter; - } - - @Override - protected boolean createKeys(List list) { - if (filter == null) { - list.addAll(Arrays.asList(FileSearchFilter.values())); - } - else if (filter.equals(FileSearchFilter.TSK_DOCUMENT_FILTER) ){ - list.addAll(Arrays.asList(SearchFilters.DocumentFilter.values())); - } - else if (filter.equals(FileSearchFilter.TSK_EXECUTABLE_FILTER) ){ - list.addAll(Arrays.asList(SearchFilters.ExecutableFilter.values())); - } - return true; - } - - @Override - protected Node createNodeForKey(SearchFilters.SearchFilterInterface key){ - if(key.getName().equals(SearchFilters.FileSearchFilter.TSK_DOCUMENT_FILTER.getName())){ - return new SearchFiltersNode(skCase, SearchFilters.FileSearchFilter.TSK_DOCUMENT_FILTER); - } - else if(key.getName().equals(SearchFilters.FileSearchFilter.TSK_EXECUTABLE_FILTER.getName())){ - return new SearchFiltersNode(skCase, SearchFilters.FileSearchFilter.TSK_EXECUTABLE_FILTER); - } - else { - return new FileSearchFilterNode(key, skCase); - } - } - -} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java index eea33be974..652ae959a2 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java @@ -34,7 +34,7 @@ public class ViewsNode extends DisplayableItemNode { public ViewsNode(SleuthkitCase sleuthkitCase) { super(new RootContentChildren(Arrays.asList( - new SearchFilters(sleuthkitCase), + new FileTypeExtensionFilters(sleuthkitCase), new RecentFiles(sleuthkitCase), new DeletedContent(sleuthkitCase), new FileSize(sleuthkitCase) From 2e38eafa4c0e914777d35d1cea761684ad353711 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 11 Sep 2013 19:23:03 -0400 Subject: [PATCH 07/11] Fixed bug in paging in hex viewer and cleaned up code --- .../corecomponents/DataContentViewerHex.java | 88 ++++++++----------- 1 file changed, 38 insertions(+), 50 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java index 0ec89f14ca..a867c9d955 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,8 +32,6 @@ import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.autopsy.datamodel.DataConversion; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.FsContent; -import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.TskException; /** @@ -41,11 +39,10 @@ import org.sleuthkit.datamodel.TskException; */ @ServiceProvider(service = DataContentViewer.class, position = 1) public class DataContentViewerHex extends javax.swing.JPanel implements DataContentViewer { - - private static long currentOffset = 0; private static final long pageLength = 16384; private final byte[] data = new byte[(int) pageLength]; private static int currentPage = 1; + private int totalPages; private Content dataSource; private static final Logger logger = Logger.getLogger(DataContentViewerHex.class.getName()); @@ -243,39 +240,28 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont }// //GEN-END:initComponents private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevPageButtonActionPerformed - //@@@ this is part of the code dealing with the data viewer. could be copied/removed to implement the scrollbar - currentOffset -= pageLength; - currentPage = currentPage - 1; - currentPageLabel.setText(Integer.toString(currentPage)); - setDataView(dataSource, currentOffset); + setDataView(currentPage - 1); }//GEN-LAST:event_prevPageButtonActionPerformed private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed - //@@@ this is part of the code dealing with the data viewer. could be copied/removed to implement the scrollbar - currentOffset += pageLength; - currentPage = currentPage + 1; - currentPageLabel.setText(Integer.toString(currentPage)); - setDataView(dataSource, currentOffset); + setDataView(currentPage + 1); }//GEN-LAST:event_nextPageButtonActionPerformed private void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goToPageTextFieldActionPerformed String pageNumberStr = goToPageTextField.getText(); int pageNumber = 0; - int maxPage = Math.round((dataSource.getSize() - 1) / pageLength) + 1; + try { pageNumber = Integer.parseInt(pageNumberStr); } catch (NumberFormatException ex) { - pageNumber = maxPage + 1; + pageNumber = totalPages + 1; } - if (pageNumber > maxPage || pageNumber < 1) { - JOptionPane.showMessageDialog(this, "Please enter a valid page number between 1 and " + maxPage, + if (pageNumber > totalPages || pageNumber < 1) { + JOptionPane.showMessageDialog(this, "Please enter a valid page number between 1 and " + totalPages, "Invalid page number", JOptionPane.WARNING_MESSAGE); return; } - currentOffset = (pageNumber - 1) * pageLength; - currentPage = pageNumber; - currentPageLabel.setText(Integer.toString(currentPage)); - setDataView(dataSource, currentOffset); + setDataView(pageNumber); }//GEN-LAST:event_goToPageTextFieldActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JMenuItem copyMenuItem; @@ -296,30 +282,27 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont // End of variables declaration//GEN-END:variables - @Deprecated - public void setDataView(Content dataSource, long offset, boolean reset) { - if (reset) { - resetComponent(); - return; - } - setDataView(dataSource, offset); - } - /** * Sets the DataView (The tabbed panel) * - * @param dataSource the content that want to be shown - * @param offset the starting offset + * @param page Page to display (1-based counting) */ - private void setDataView(Content dataSource, long offset) { - if (dataSource == null) { + private void setDataView(int page) { + if (this.dataSource == null) { return; } + if (page == 0) { + return; + } + + currentPage = page; + long offset = (currentPage - 1) * pageLength; + + // change the cursor to "waiting cursor" for this operation this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - this.dataSource = dataSource; String errorText = null; int bytesRead = 0; @@ -327,7 +310,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont try { bytesRead = dataSource.read(data, offset, pageLength); // read the data } catch (TskException ex) { - errorText = "(offset " + currentOffset + "-" + (currentOffset + pageLength) + errorText = "(offset " + offset + "-" + (offset + pageLength) + " could not be read)"; logger.log(Level.WARNING, "Error while trying to show the hex content.", ex); } @@ -335,27 +318,26 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont // set the data on the bottom and show it if (bytesRead <= 0) { - errorText = "(offset " + currentOffset + "-" + (currentOffset + pageLength) + errorText = "(offset " + offset + "-" + (offset + pageLength) + " could not be read)"; } // disable or enable the next button - if ((errorText != null) && (offset + pageLength < dataSource.getSize())) { + if ((errorText == null) && (currentPage < totalPages)) { nextPageButton.setEnabled(true); - } else { + } + else { nextPageButton.setEnabled(false); } - if ((offset == 0) || (errorText == null)) { - prevPageButton.setEnabled(false); - currentPage = 1; // reset the page number - } else { + if ((errorText == null) && (currentPage > 1)) { prevPageButton.setEnabled(true); + } + else { + prevPageButton.setEnabled(false); } - - int totalPage = Math.round((dataSource.getSize() - 1) / pageLength) + 1; - totalPageLabel.setText(Integer.toString(totalPage)); + currentPageLabel.setText(Integer.toString(currentPage)); setComponentsVisibility(true); // shows the components that not needed @@ -384,8 +366,15 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont resetComponent(); return; } + + dataSource = content; + totalPages = 0; + if (dataSource.getSize() > 0) { + totalPages = Math.round((dataSource.getSize() - 1) / pageLength) + 1; + } + totalPageLabel.setText(Integer.toString(totalPages)); - this.setDataView(content, 0); + this.setDataView(1); } @Override @@ -408,7 +397,6 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont public void resetComponent() { // clear / reset the fields currentPage = 1; - currentOffset = 0; this.dataSource = null; currentPageLabel.setText(""); totalPageLabel.setText(""); From 69ea984602ecfce93f7cb1d1fa5e87f20206ef99 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 11 Sep 2013 20:40:15 -0400 Subject: [PATCH 08/11] cleaned up handling of history in directory tree --- .../directorytree/DataResultFilterNode.java | 1088 ++++++++--------- .../DirectoryTreeTopComponent.java | 124 +- 2 files changed, 610 insertions(+), 602 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index ed0ffc23df..8ccc8a7405 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -1,545 +1,545 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011-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.directorytree; - -import java.awt.event.ActionEvent; -import java.beans.PropertyVetoException; -import java.util.ArrayList; -import java.util.List; -import org.sleuthkit.autopsy.datamodel.VolumeNode; -import org.sleuthkit.autopsy.datamodel.DirectoryNode; -import java.util.logging.Level; -import org.sleuthkit.autopsy.coreutils.Logger; -import javax.swing.AbstractAction; -import javax.swing.Action; -import org.openide.explorer.ExplorerManager; -import org.openide.nodes.AbstractNode; -import org.openide.nodes.FilterNode; -import org.openide.nodes.Node; -import org.openide.nodes.Sheet; -import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType; -import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode; -import org.sleuthkit.autopsy.datamodel.ArtifactTypeNode; -import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; -import org.sleuthkit.autopsy.datamodel.LocalFileNode; -import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.DeletedContentNode; -import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; -import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; -import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; -import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedAccountNode; -import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedFolderNode; -import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedRootNode; -import org.sleuthkit.autopsy.datamodel.ExtractedContentNode; -import org.sleuthkit.autopsy.datamodel.FileNode; -import org.sleuthkit.autopsy.datamodel.FileSearchFilterNode; -import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; -import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode; -import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsRootNode; -import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsSetNode; -import org.sleuthkit.autopsy.datamodel.ImageNode; -import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsKeywordNode; -import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsListNode; -import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsRootNode; -import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; -import org.sleuthkit.autopsy.datamodel.LayoutFileNode; -import org.sleuthkit.autopsy.datamodel.RecentFilesFilterNode; -import org.sleuthkit.autopsy.datamodel.RecentFilesNode; -import org.sleuthkit.autopsy.datamodel.SearchFiltersNode; -import org.sleuthkit.autopsy.datamodel.Tags.TagNodeRoot; -import org.sleuthkit.autopsy.datamodel.Tags.TagsNodeRoot; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.DerivedFile; -import org.sleuthkit.datamodel.Directory; -import org.sleuthkit.datamodel.File; -import org.sleuthkit.datamodel.LayoutFile; -import org.sleuthkit.datamodel.LocalFile; -import org.sleuthkit.datamodel.TskException; -import org.sleuthkit.datamodel.VirtualDirectory; - -/** - * This class wraps nodes as they are passed to the DataResult viewers. It - * defines the actions that the node should have. - */ -public class DataResultFilterNode extends FilterNode { - - private ExplorerManager sourceEm; - private final DisplayableItemNodeVisitor> getActionsDIV; - private final DisplayableItemNodeVisitor getPreferredActionsDIV; - - /** - * - * @param node Root node to be passed to DataResult viewers - * @param em ExplorerManager for component that is creating the node - */ - public DataResultFilterNode(Node node, ExplorerManager em) { - super(node, new DataResultFilterChildren(node, em)); - this.sourceEm = em; - getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor(); - getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor(); - } - - /** - * Right click action for the nodes that we want to pass to the directory - * table and the output view. - * - * @param popup - * @return actions - */ - @Override - public Action[] getActions(boolean popup) { - - List actions = new ArrayList<>(); - - final DisplayableItemNode originalNode = (DisplayableItemNode) this.getOriginal(); - actions.addAll(originalNode.accept(getActionsDIV)); - - //actions.add(new IndexContentFilesAction(nodeContent, "Index")); - - return actions.toArray(new Action[actions.size()]); - } - - /** - * Double click action for the nodes that we want to pass to the directory - * table and the output view. - * - * @return action - */ - @Override - public Action getPreferredAction() { - // double click action(s) for volume node or directory node - - final DisplayableItemNode originalNode; - originalNode = (DisplayableItemNode) this.getOriginal(); - - return originalNode.accept(getPreferredActionsDIV); - } - - @Override - public Node.PropertySet[] getPropertySets() { - Node.PropertySet[] propertySets = super.getPropertySets(); - - for (int i = 0; i < propertySets.length; i++) { - Node.PropertySet ps = propertySets[i]; - - if (ps.getName().equals(Sheet.PROPERTIES)) { - Sheet.Set newPs = new Sheet.Set(); - newPs.setName(ps.getName()); - newPs.setDisplayName(ps.getDisplayName()); - newPs.setShortDescription(ps.getShortDescription()); - - newPs.put(ps.getProperties()); - if (newPs.remove(AbstractFsContentNode.HIDE_PARENT) != null) { - newPs.remove(AbstractFilePropertyType.LOCATION.toString()); - } - propertySets[i] = newPs; - } - } - - return propertySets; - } - - /** - * Uses the default nodes actions per node, adds some custom ones and - * returns them per visited node type - */ - private static class GetPopupActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default> { - - @Override - public List visit(BlackboardArtifactNode ban) { - //set up actions for artifact node based on its Content object - //TODO all actions need to be consolidated in single place! - //they should be set in individual Node subclass and using a utility to get Actions per Content sub-type - - List actions = new ArrayList<>(); - - //merge predefined specific node actions if bban subclasses have their own - for (Action a : ban.getActions(true)) { - actions.add(a); - } - BlackboardArtifact ba = ban.getLookup().lookup(BlackboardArtifact.class); - final int artifactTypeID = ba.getArtifactTypeID(); - - if (artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() - || artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { - actions.add(new ViewContextAction("View File in Directory", ban)); - } else { - Content c = findLinked(ban); - if (c != null) { - actions.add(new ViewContextAction("View File in Directory", c)); - } - actions.add(new ViewContextAction("View Source File in Directory", ban)); - } - File f = ban.getLookup().lookup(File.class); - LayoutFile lf = null; - AbstractFile locF = null; - Directory d = null; - VirtualDirectory vd = null; - if (f != null) { - final FileNode fn = new FileNode(f); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction("View in New Window", fn)); - actions.add(new ExternalViewerAction("Open in External Viewer", fn)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); - actions.add(new HashSearchAction("Search for files with the same MD5 hash", fn)); - - //add file/result tag if itself is not a tag - if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() - && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { - actions.add(null); // creates a menu separator - actions.add(TagAbstractFileAction.getInstance()); - actions.add(TagBlackboardArtifactAction.getInstance()); - } - } - if ((d = ban.getLookup().lookup(Directory.class)) != null) { - DirectoryNode dn = new DirectoryNode(d); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction("View in New Window", dn)); - actions.add(new ExternalViewerAction("Open in External Viewer", dn)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); - - //add file/result tag if itself is not a tag - if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() - && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { - actions.add(null); // creates a menu separator - actions.add(TagAbstractFileAction.getInstance()); - actions.add(TagBlackboardArtifactAction.getInstance()); - } - } - if ((vd = ban.getLookup().lookup(VirtualDirectory.class)) != null) { - VirtualDirectoryNode dn = new VirtualDirectoryNode(vd); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction("View in New Window", dn)); - actions.add(new ExternalViewerAction("Open in External Viewer", dn)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); - - //add file/result tag if itself is not a tag - if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() - && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { - actions.add(null); // creates a menu separator - actions.add(TagAbstractFileAction.getInstance()); - actions.add(TagBlackboardArtifactAction.getInstance()); - } - } else if ((lf = ban.getLookup().lookup(LayoutFile.class)) != null) { - LayoutFileNode lfn = new LayoutFileNode(lf); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction("View in New Window", lfn)); - actions.add(new ExternalViewerAction("Open in External Viewer", lfn)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); - - //add tag if itself is not a tag - if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() - && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { - actions.add(null); // creates a menu separator - actions.add(TagAbstractFileAction.getInstance()); - actions.add(TagBlackboardArtifactAction.getInstance()); - } - } else if ((locF = ban.getLookup().lookup(LocalFile.class)) != null - || (locF = ban.getLookup().lookup(DerivedFile.class)) != null) { - final LocalFileNode locfn = new LocalFileNode(locF); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction("View in New Window", locfn)); - actions.add(new ExternalViewerAction("Open in External Viewer", locfn)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); - - //add tag if itself is not a tag - if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() - && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { - actions.add(null); // creates a menu separator - actions.add(TagAbstractFileAction.getInstance()); - actions.add(TagBlackboardArtifactAction.getInstance()); - } - } - - return actions; - } - - @Override - protected List defaultVisit(DisplayableItemNode ditem) { - //preserve the default node's actions - List actions = new ArrayList<>(); - - for (Action action : ditem.getActions(true)) { - actions.add(action); - } - - return actions; - } - - private Content findLinked(BlackboardArtifactNode ba) { - BlackboardArtifact art = ba.getLookup().lookup(BlackboardArtifact.class); - Content c = null; - try { - for (BlackboardAttribute attr : art.getAttributes()) { - if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { - switch (attr.getValueType()) { - case INTEGER: - int i = attr.getValueInt(); - if (i != -1) { - c = art.getSleuthkitCase().getContentById(i); - } - break; - case LONG: - long l = attr.getValueLong(); - if (l != -1) { - c = art.getSleuthkitCase().getContentById(l); - } - break; - } - } - } - } catch (TskException ex) { - Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Error getting linked file", ex); - } - return c; - } - } - - /* - * Action for double-click / preferred action on nodes. - */ - private class GetPreferredActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default { - - @Override - public AbstractAction visit(ImageNode in) { - return openChild(in); - } - - @Override - public AbstractAction visit(VolumeNode vn) { - return openChild(vn); - } - - @Override - public AbstractAction visit(ExtractedContentNode ecn) { - return openChild(ecn); - } - - @Override - public AbstractAction visit(KeywordHitsRootNode khrn) { - return openChild(khrn); - } - - @Override - public AbstractAction visit(HashsetHitsRootNode hhrn) { - return openChild(hhrn); - } - - @Override - public AbstractAction visit(HashsetHitsSetNode hhsn) { - return openChild(hhsn); - } - - @Override - public AbstractAction visit(EmailExtractedRootNode eern) { - return openChild(eern); - } - - @Override - public AbstractAction visit(EmailExtractedAccountNode eean) { - return openChild(eean); - } - - @Override - public AbstractAction visit(EmailExtractedFolderNode eefn) { - return openChild(eefn); - } - - @Override - public AbstractAction visit(RecentFilesNode rfn) { - return openChild(rfn); - } - - @Override - public AbstractAction visit(DeletedContentsNode dcn) { - return openChild(dcn); - } - - @Override - public AbstractAction visit(DeletedContentNode dcn) { - return openChild(dcn); - } - - @Override - public AbstractAction visit(FileSizeRootNode fsrn) { - return openChild(fsrn); - } - - @Override - public AbstractAction visit(FileSizeNode fsn) { - return openChild(fsn); - } - - @Override - public AbstractAction visit(BlackboardArtifactNode ban) { - return new ViewContextAction("View in Directory", ban); - } - - @Override - public AbstractAction visit(ArtifactTypeNode atn) { - return openChild(atn); - } - - @Override - public AbstractAction visit(TagNodeRoot tnr) { - return openChild(tnr); - } - - @Override - public AbstractAction visit(TagsNodeRoot tnr) { - return openChild(tnr); - } - - @Override - public AbstractAction visit(DirectoryNode dn) { - if (dn.getDisplayName().equals(DirectoryNode.DOTDOTDIR)) { - return openParent(dn); - } - else if (dn.getDisplayName().equals(DirectoryNode.DOTDIR) == false) { - return openChild(dn); - } - else { - return null; - } - } - - @Override - public AbstractAction visit(VirtualDirectoryNode ldn) { - return openChild(ldn); - } - - @Override - public AbstractAction visit(FileNode fn) { - if (fn.hasContentChildren()) { - return openChild(fn); - } - else { - return null; - } - } - - @Override - public AbstractAction visit(LocalFileNode dfn) { - if (dfn.hasContentChildren()) { - return openChild(dfn); - } - else { - return null; - } - } - - @Override - public AbstractAction visit(FileSearchFilterNode fsfn) { - return openChild(fsfn); - } - - @Override - public AbstractAction visit(SearchFiltersNode sfn) { - return openChild(sfn); - } - - @Override - public AbstractAction visit(RecentFilesFilterNode rffn) { - return openChild(rffn); - } - - @Override - public AbstractAction visit(KeywordHitsListNode khsn) { - return openChild(khsn); - } - - @Override - public AbstractAction visit(KeywordHitsKeywordNode khmln) { - return openChild(khmln); - } - - @Override - protected AbstractAction defaultVisit(DisplayableItemNode c) { - return null; - } - - /** - * Tell the originating ExplorerManager to display the given node. - * @param node Original (non-filtered) node to open - * @return - */ - private AbstractAction openChild(AbstractNode node) { - // get the parent node from sourceEm because that will get us the filtered version of it. - // node.getParentNode() returns the low-level datamodel node. - final Node[] parentFilterNodes = sourceEm.getSelectedNodes(); - final Node parentFilterNode = parentFilterNodes[0]; - final Node originalNode = node; - - return new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - if (parentFilterNode != null) { - - // Find the filter version of the passed in node. - final int childrenNodesCount = parentFilterNode.getChildren().getNodesCount(); - for (int i = 0; i < childrenNodesCount; i++) { - Node childFilterNode = parentFilterNode.getChildren().getNodeAt(i); - if (childFilterNode != null && childFilterNode.getName().equals(originalNode.getName())) { - try { - sourceEm.setExploredContextAndSelection(childFilterNode, new Node[]{childFilterNode}); - break; - } catch (PropertyVetoException ex) { - // throw an error here - Logger logger = Logger.getLogger(DataResultFilterNode.class.getName()); - logger.log(Level.WARNING, "Error: can't open the selected directory.", ex); - } - } - } - } - } - }; - } - - /** - * Tell the originating ExplorerManager to display the parent of the given node. - * @param node Original (non-filtered) node to open - * @return - */ - private AbstractAction openParent(AbstractNode node) { - // @@@ Why do we ignore node? - Node[] selectedFilterNodes = sourceEm.getSelectedNodes(); - Node selectedFilterNode = selectedFilterNodes[0]; - final Node parentNode = selectedFilterNode.getParentNode(); - - return new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - try { - sourceEm.setSelectedNodes(new Node[]{parentNode}); - } catch (PropertyVetoException ex) { - Logger logger = Logger.getLogger(DataResultFilterNode.class.getName()); - logger.log(Level.WARNING, "Error: can't open the parent directory.", ex); - } - } - }; - } - } +/* + * Autopsy Forensic Browser + * + * Copyright 2011-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.directorytree; + +import java.awt.event.ActionEvent; +import java.beans.PropertyVetoException; +import java.util.ArrayList; +import java.util.List; +import org.sleuthkit.autopsy.datamodel.VolumeNode; +import org.sleuthkit.autopsy.datamodel.DirectoryNode; +import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; +import javax.swing.AbstractAction; +import javax.swing.Action; +import org.openide.explorer.ExplorerManager; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.FilterNode; +import org.openide.nodes.Node; +import org.openide.nodes.Sheet; +import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType; +import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode; +import org.sleuthkit.autopsy.datamodel.ArtifactTypeNode; +import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; +import org.sleuthkit.autopsy.datamodel.LocalFileNode; +import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.DeletedContentNode; +import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; +import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; +import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; +import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedAccountNode; +import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedFolderNode; +import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedRootNode; +import org.sleuthkit.autopsy.datamodel.ExtractedContentNode; +import org.sleuthkit.autopsy.datamodel.FileNode; +import org.sleuthkit.autopsy.datamodel.FileTypeNode; +import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; +import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode; +import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsRootNode; +import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsSetNode; +import org.sleuthkit.autopsy.datamodel.ImageNode; +import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsKeywordNode; +import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsListNode; +import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsRootNode; +import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; +import org.sleuthkit.autopsy.datamodel.LayoutFileNode; +import org.sleuthkit.autopsy.datamodel.RecentFilesFilterNode; +import org.sleuthkit.autopsy.datamodel.RecentFilesNode; +import org.sleuthkit.autopsy.datamodel.FileTypesNode; +import org.sleuthkit.autopsy.datamodel.Tags.TagNodeRoot; +import org.sleuthkit.autopsy.datamodel.Tags.TagsNodeRoot; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.DerivedFile; +import org.sleuthkit.datamodel.Directory; +import org.sleuthkit.datamodel.File; +import org.sleuthkit.datamodel.LayoutFile; +import org.sleuthkit.datamodel.LocalFile; +import org.sleuthkit.datamodel.TskException; +import org.sleuthkit.datamodel.VirtualDirectory; + +/** + * This class wraps nodes as they are passed to the DataResult viewers. It + * defines the actions that the node should have. + */ +public class DataResultFilterNode extends FilterNode { + + private ExplorerManager sourceEm; + private final DisplayableItemNodeVisitor> getActionsDIV; + private final DisplayableItemNodeVisitor getPreferredActionsDIV; + + /** + * + * @param node Root node to be passed to DataResult viewers + * @param em ExplorerManager for component that is creating the node + */ + public DataResultFilterNode(Node node, ExplorerManager em) { + super(node, new DataResultFilterChildren(node, em)); + this.sourceEm = em; + getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor(); + getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor(); + } + + /** + * Right click action for the nodes that we want to pass to the directory + * table and the output view. + * + * @param popup + * @return actions + */ + @Override + public Action[] getActions(boolean popup) { + + List actions = new ArrayList<>(); + + final DisplayableItemNode originalNode = (DisplayableItemNode) this.getOriginal(); + actions.addAll(originalNode.accept(getActionsDIV)); + + //actions.add(new IndexContentFilesAction(nodeContent, "Index")); + + return actions.toArray(new Action[actions.size()]); + } + + /** + * Double click action for the nodes that we want to pass to the directory + * table and the output view. + * + * @return action + */ + @Override + public Action getPreferredAction() { + // double click action(s) for volume node or directory node + + final DisplayableItemNode originalNode; + originalNode = (DisplayableItemNode) this.getOriginal(); + + return originalNode.accept(getPreferredActionsDIV); + } + + @Override + public Node.PropertySet[] getPropertySets() { + Node.PropertySet[] propertySets = super.getPropertySets(); + + for (int i = 0; i < propertySets.length; i++) { + Node.PropertySet ps = propertySets[i]; + + if (ps.getName().equals(Sheet.PROPERTIES)) { + Sheet.Set newPs = new Sheet.Set(); + newPs.setName(ps.getName()); + newPs.setDisplayName(ps.getDisplayName()); + newPs.setShortDescription(ps.getShortDescription()); + + newPs.put(ps.getProperties()); + if (newPs.remove(AbstractFsContentNode.HIDE_PARENT) != null) { + newPs.remove(AbstractFilePropertyType.LOCATION.toString()); + } + propertySets[i] = newPs; + } + } + + return propertySets; + } + + /** + * Uses the default nodes actions per node, adds some custom ones and + * returns them per visited node type + */ + private static class GetPopupActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default> { + + @Override + public List visit(BlackboardArtifactNode ban) { + //set up actions for artifact node based on its Content object + //TODO all actions need to be consolidated in single place! + //they should be set in individual Node subclass and using a utility to get Actions per Content sub-type + + List actions = new ArrayList<>(); + + //merge predefined specific node actions if bban subclasses have their own + for (Action a : ban.getActions(true)) { + actions.add(a); + } + BlackboardArtifact ba = ban.getLookup().lookup(BlackboardArtifact.class); + final int artifactTypeID = ba.getArtifactTypeID(); + + if (artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() + || artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { + actions.add(new ViewContextAction("View File in Directory", ban)); + } else { + Content c = findLinked(ban); + if (c != null) { + actions.add(new ViewContextAction("View File in Directory", c)); + } + actions.add(new ViewContextAction("View Source File in Directory", ban)); + } + File f = ban.getLookup().lookup(File.class); + LayoutFile lf = null; + AbstractFile locF = null; + Directory d = null; + VirtualDirectory vd = null; + if (f != null) { + final FileNode fn = new FileNode(f); + actions.add(null); // creates a menu separator + actions.add(new NewWindowViewAction("View in New Window", fn)); + actions.add(new ExternalViewerAction("Open in External Viewer", fn)); + actions.add(null); // creates a menu separator + actions.add(ExtractAction.getInstance()); + actions.add(new HashSearchAction("Search for files with the same MD5 hash", fn)); + + //add file/result tag if itself is not a tag + if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() + && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { + actions.add(null); // creates a menu separator + actions.add(TagAbstractFileAction.getInstance()); + actions.add(TagBlackboardArtifactAction.getInstance()); + } + } + if ((d = ban.getLookup().lookup(Directory.class)) != null) { + DirectoryNode dn = new DirectoryNode(d); + actions.add(null); // creates a menu separator + actions.add(new NewWindowViewAction("View in New Window", dn)); + actions.add(new ExternalViewerAction("Open in External Viewer", dn)); + actions.add(null); // creates a menu separator + actions.add(ExtractAction.getInstance()); + + //add file/result tag if itself is not a tag + if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() + && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { + actions.add(null); // creates a menu separator + actions.add(TagAbstractFileAction.getInstance()); + actions.add(TagBlackboardArtifactAction.getInstance()); + } + } + if ((vd = ban.getLookup().lookup(VirtualDirectory.class)) != null) { + VirtualDirectoryNode dn = new VirtualDirectoryNode(vd); + actions.add(null); // creates a menu separator + actions.add(new NewWindowViewAction("View in New Window", dn)); + actions.add(new ExternalViewerAction("Open in External Viewer", dn)); + actions.add(null); // creates a menu separator + actions.add(ExtractAction.getInstance()); + + //add file/result tag if itself is not a tag + if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() + && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { + actions.add(null); // creates a menu separator + actions.add(TagAbstractFileAction.getInstance()); + actions.add(TagBlackboardArtifactAction.getInstance()); + } + } else if ((lf = ban.getLookup().lookup(LayoutFile.class)) != null) { + LayoutFileNode lfn = new LayoutFileNode(lf); + actions.add(null); // creates a menu separator + actions.add(new NewWindowViewAction("View in New Window", lfn)); + actions.add(new ExternalViewerAction("Open in External Viewer", lfn)); + actions.add(null); // creates a menu separator + actions.add(ExtractAction.getInstance()); + + //add tag if itself is not a tag + if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() + && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { + actions.add(null); // creates a menu separator + actions.add(TagAbstractFileAction.getInstance()); + actions.add(TagBlackboardArtifactAction.getInstance()); + } + } else if ((locF = ban.getLookup().lookup(LocalFile.class)) != null + || (locF = ban.getLookup().lookup(DerivedFile.class)) != null) { + final LocalFileNode locfn = new LocalFileNode(locF); + actions.add(null); // creates a menu separator + actions.add(new NewWindowViewAction("View in New Window", locfn)); + actions.add(new ExternalViewerAction("Open in External Viewer", locfn)); + actions.add(null); // creates a menu separator + actions.add(ExtractAction.getInstance()); + + //add tag if itself is not a tag + if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() + && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { + actions.add(null); // creates a menu separator + actions.add(TagAbstractFileAction.getInstance()); + actions.add(TagBlackboardArtifactAction.getInstance()); + } + } + + return actions; + } + + @Override + protected List defaultVisit(DisplayableItemNode ditem) { + //preserve the default node's actions + List actions = new ArrayList<>(); + + for (Action action : ditem.getActions(true)) { + actions.add(action); + } + + return actions; + } + + private Content findLinked(BlackboardArtifactNode ba) { + BlackboardArtifact art = ba.getLookup().lookup(BlackboardArtifact.class); + Content c = null; + try { + for (BlackboardAttribute attr : art.getAttributes()) { + if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + switch (attr.getValueType()) { + case INTEGER: + int i = attr.getValueInt(); + if (i != -1) { + c = art.getSleuthkitCase().getContentById(i); + } + break; + case LONG: + long l = attr.getValueLong(); + if (l != -1) { + c = art.getSleuthkitCase().getContentById(l); + } + break; + } + } + } + } catch (TskException ex) { + Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Error getting linked file", ex); + } + return c; + } + } + + /* + * Action for double-click / preferred action on nodes. + */ + private class GetPreferredActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default { + + @Override + public AbstractAction visit(ImageNode in) { + return openChild(in); + } + + @Override + public AbstractAction visit(VolumeNode vn) { + return openChild(vn); + } + + @Override + public AbstractAction visit(ExtractedContentNode ecn) { + return openChild(ecn); + } + + @Override + public AbstractAction visit(KeywordHitsRootNode khrn) { + return openChild(khrn); + } + + @Override + public AbstractAction visit(HashsetHitsRootNode hhrn) { + return openChild(hhrn); + } + + @Override + public AbstractAction visit(HashsetHitsSetNode hhsn) { + return openChild(hhsn); + } + + @Override + public AbstractAction visit(EmailExtractedRootNode eern) { + return openChild(eern); + } + + @Override + public AbstractAction visit(EmailExtractedAccountNode eean) { + return openChild(eean); + } + + @Override + public AbstractAction visit(EmailExtractedFolderNode eefn) { + return openChild(eefn); + } + + @Override + public AbstractAction visit(RecentFilesNode rfn) { + return openChild(rfn); + } + + @Override + public AbstractAction visit(DeletedContentsNode dcn) { + return openChild(dcn); + } + + @Override + public AbstractAction visit(DeletedContentNode dcn) { + return openChild(dcn); + } + + @Override + public AbstractAction visit(FileSizeRootNode fsrn) { + return openChild(fsrn); + } + + @Override + public AbstractAction visit(FileSizeNode fsn) { + return openChild(fsn); + } + + @Override + public AbstractAction visit(BlackboardArtifactNode ban) { + return new ViewContextAction("View in Directory", ban); + } + + @Override + public AbstractAction visit(ArtifactTypeNode atn) { + return openChild(atn); + } + + @Override + public AbstractAction visit(TagNodeRoot tnr) { + return openChild(tnr); + } + + @Override + public AbstractAction visit(TagsNodeRoot tnr) { + return openChild(tnr); + } + + @Override + public AbstractAction visit(DirectoryNode dn) { + if (dn.getDisplayName().equals(DirectoryNode.DOTDOTDIR)) { + return openParent(dn); + } + else if (dn.getDisplayName().equals(DirectoryNode.DOTDIR) == false) { + return openChild(dn); + } + else { + return null; + } + } + + @Override + public AbstractAction visit(VirtualDirectoryNode ldn) { + return openChild(ldn); + } + + @Override + public AbstractAction visit(FileNode fn) { + if (fn.hasContentChildren()) { + return openChild(fn); + } + else { + return null; + } + } + + @Override + public AbstractAction visit(LocalFileNode dfn) { + if (dfn.hasContentChildren()) { + return openChild(dfn); + } + else { + return null; + } + } + + @Override + public AbstractAction visit(FileTypeNode fsfn) { + return openChild(fsfn); + } + + @Override + public AbstractAction visit(FileTypesNode sfn) { + return openChild(sfn); + } + + @Override + public AbstractAction visit(RecentFilesFilterNode rffn) { + return openChild(rffn); + } + + @Override + public AbstractAction visit(KeywordHitsListNode khsn) { + return openChild(khsn); + } + + @Override + public AbstractAction visit(KeywordHitsKeywordNode khmln) { + return openChild(khmln); + } + + @Override + protected AbstractAction defaultVisit(DisplayableItemNode c) { + return null; + } + + /** + * Tell the originating ExplorerManager to display the given node. + * @param node Original (non-filtered) node to open + * @return + */ + private AbstractAction openChild(AbstractNode node) { + // get the parent node from sourceEm because that will get us the filtered version of it. + // node.getParentNode() returns the low-level datamodel node. + final Node[] parentFilterNodes = sourceEm.getSelectedNodes(); + final Node parentFilterNode = parentFilterNodes[0]; + final Node originalNode = node; + + return new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + if (parentFilterNode != null) { + + // Find the filter version of the passed in node. + final int childrenNodesCount = parentFilterNode.getChildren().getNodesCount(); + for (int i = 0; i < childrenNodesCount; i++) { + Node childFilterNode = parentFilterNode.getChildren().getNodeAt(i); + if (childFilterNode != null && childFilterNode.getName().equals(originalNode.getName())) { + try { + sourceEm.setExploredContextAndSelection(childFilterNode, new Node[]{childFilterNode}); + break; + } catch (PropertyVetoException ex) { + // throw an error here + Logger logger = Logger.getLogger(DataResultFilterNode.class.getName()); + logger.log(Level.WARNING, "Error: can't open the selected directory.", ex); + } + } + } + } + } + }; + } + + /** + * Tell the originating ExplorerManager to display the parent of the given node. + * @param node Original (non-filtered) node to open + * @return + */ + private AbstractAction openParent(AbstractNode node) { + // @@@ Why do we ignore node? + Node[] selectedFilterNodes = sourceEm.getSelectedNodes(); + Node selectedFilterNode = selectedFilterNodes[0]; + final Node parentNode = selectedFilterNode.getParentNode(); + + return new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + try { + sourceEm.setSelectedNodes(new Node[]{parentNode}); + } catch (PropertyVetoException ex) { + Logger logger = Logger.getLogger(DataResultFilterNode.class.getName()); + logger.log(Level.WARNING, "Error: can't open the parent directory.", ex); + } + } + }; + } + } } \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 0c7c2ef543..05ae16d893 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -219,10 +219,16 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat private void backButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_backButtonActionPerformed // change the cursor to "waiting cursor" for this operation this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - // update the back and forward List + + // the end is the current place, String[] currentNodePath = backList.pollLast(); - String[] newCurrentNodePath = backList.peekLast(); forwardList.addLast(currentNodePath); + forwardButton.setEnabled(true); + + /* We peek instead of poll because we use its existence + * in the list later on so that we do not reset the forward list + * after the selection occurs. */ + String[] newCurrentNodePath = backList.peekLast(); // enable / disable the back and forward button if (backList.size() > 1) { @@ -230,39 +236,31 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat } else { backButton.setEnabled(false); } - this.forwardButton.setEnabled(true); - + // update the selection on directory tree setSelectedNode(newCurrentNodePath, null); - this.setCursor(null); - }//GEN-LAST:event_backButtonActionPerformed private void forwardButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_forwardButtonActionPerformed // change the cursor to "waiting cursor" for this operation this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); -// try { - // update the back and forward List - //int newCurrentIndex = forwardList.size() - 1; - String[] newCurrentNodePath = forwardList.pollLast(); - //forwardList.remove(newCurrentIndex); - backList.addLast(newCurrentNodePath); - // enable / disable the back and forward button + String[] newCurrentNodePath = forwardList.pollLast(); if (!forwardList.isEmpty()) { forwardButton.setEnabled(true); } else { forwardButton.setEnabled(false); } - this.backButton.setEnabled(true); - + + backList.addLast(newCurrentNodePath); + backButton.setEnabled(true); + // update the selection on directory tree setSelectedNode(newCurrentNodePath, null); this.setCursor(null); - }//GEN-LAST:event_forwardButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton backButton; @@ -337,7 +335,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat ((BeanTreeView) this.jScrollPane1).setRootVisible(false); // hide the root } else { // if there's at least one image, load the image and open the top component - List items = new ArrayList(); + List items = new ArrayList<>(); final SleuthkitCase tskCase = currentCase.getSleuthkitCase(); items.add(new DataSources(tskCase)); items.add(new Views(tskCase)); @@ -375,7 +373,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat ((BeanTreeView) this.jScrollPane1).setRootVisible(false); // hide the root // Reset the forward and back lists because we're resetting the root context - resetHistoryListAndButtons(); + resetHistory(); Children childNodes = em.getRootContext().getChildren(); TreeView tree = getTree(); @@ -533,7 +531,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat // case opened if (newValue != null) { - resetHistoryListAndButtons(); + resetHistory(); } } // if the image is added to the case else if (changed.equals(Case.CASE_ADD_DATA_SOURCE)) { @@ -671,31 +669,53 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat }); // update the back and forward list - Node[] selectedNode = em.getSelectedNodes(); - if (selectedNode.length > 0) { - Node selectedContext = selectedNode[0]; - - final String[] selectedPath = NodeOp.createPath(selectedContext, em.getRootContext()); - String[] currentLast = backList.peekLast(); - String lastNodeName = null; - if (currentLast != null) { - lastNodeName = currentLast[currentLast.length - 1]; - } - String selectedNodeName = selectedContext.getName(); - if (currentLast == null || !selectedNodeName.equals(lastNodeName)) { - //add to the list if the last if not the same as current - - backList.addLast(selectedPath); // add the node to the "backList" - if (backList.size() > 1) { - backButton.setEnabled(true); - } else { - backButton.setEnabled(false); - } - - forwardList.clear(); // clear the "forwardList" - forwardButton.setEnabled(false); // disable the forward Button - } + updateHistory(em.getSelectedNodes()); + } + + private void updateHistory(Node[] selectedNodes) { + if (selectedNodes.length == 0) { + return; } + + Node selectedNode = selectedNodes[0]; + String selectedNodeName = selectedNode.getName(); + + /* get the previous entry to make sure we don't duplicate it. + * Motivation for this is also that if we used the back button, + * then we already added the 'current' node to 'back' and we will + * detect that and not reset the forward list. + */ + String[] currentLast = backList.peekLast(); + String lastNodeName = null; + if (currentLast != null) { + lastNodeName = currentLast[currentLast.length - 1]; + } + + if (currentLast == null || !selectedNodeName.equals(lastNodeName)) { + //add to the list if the last if not the same as current + final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext()); + backList.addLast(selectedPath); // add the node to the "backList" + if (backList.size() > 1) { + backButton.setEnabled(true); + } else { + backButton.setEnabled(false); + } + + forwardList.clear(); // clear the "forwardList" + forwardButton.setEnabled(false); // disable the forward Button + } + } + + /** + * Resets the back and forward list, and also disable the back and forward + * buttons. + */ + private void resetHistory() { + // clear the back and forward list + backList.clear(); + forwardList.clear(); + backButton.setEnabled(false); + forwardButton.setEnabled(false); } @Override @@ -708,17 +728,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat pcs.removePropertyChangeListener(listener); } - /** - * Resets the back and forward list, and also disable the back and forward - * buttons. - */ - private void resetHistoryListAndButtons() { - // clear the back and forward list - backList.clear(); - forwardList.clear(); - backButton.setEnabled(false); - forwardButton.setEnabled(false); - } + /** * Gets the tree on this DirectoryTreeTopComponent. @@ -845,19 +855,17 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat if (path.length > 0 && (rootNodeName == null || path[0].equals(rootNodeName))) { try { - final TreeView tree = getTree(); Node newSelection = NodeOp.findPath(em.getRootContext(), path); - //resetHistoryListAndButtons(); + if (newSelection != null) { if (rootNodeName != null) { //called from tree auto refresh context //remove last from backlist, because auto select will result in duplication backList.pollLast(); } - //select - //tree.expandNode(newSelection); em.setExploredContextAndSelection(newSelection, new Node[]{newSelection}); } + // We need to set the selection, which will refresh dataresult and get rid of the oob exception } catch (NodeNotFoundException ex) { logger.log(Level.WARNING, "Node not found", ex); From 58dd29d382e0c59ecaaf59b3134c69bcfa51cb5e Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 12 Sep 2013 15:33:41 -0400 Subject: [PATCH 09/11] Flattened keyword search results listing node hierarchy for DataResultViewers --- .../corecomponents/DataResultPanel.java | 9 +-- .../AbstractKeywordSearchPerformer.java | 11 +-- .../KeywordSearchQueryManager.java | 22 +++--- .../KeywordSearchResultFactory.java | 73 ++++++++++--------- 4 files changed, 54 insertions(+), 61 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java index 755f2d01d9..3497b8f274 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java @@ -188,13 +188,8 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C // as DataResultViewer service providers when DataResultViewers are updated // to better handle the ExplorerManager sharing implemented to support actions that operate on // multiple selected nodes. - addDataResultViewer(new DataResultViewerTable(this.explorerManager)); - - // @@@ Temporary fix until unintended interaction between DataResultViewerTable and DataResultViewerThumbnail - // via the shared ExplorerManager in a Keyword Search Result window is resolved. - if (isMain) { - addDataResultViewer(new DataResultViewerThumbnail(this.explorerManager)); - } + addDataResultViewer(new DataResultViewerTable(this.explorerManager)); + addDataResultViewer(new DataResultViewerThumbnail(this.explorerManager)); // Find all DataResultViewer service providers and add them to the tabbed pane. for (DataResultViewer factory : Lookup.getDefault().lookupAll(DataResultViewer.class)) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractKeywordSearchPerformer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractKeywordSearchPerformer.java index 1cfdae3774..436c069698 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractKeywordSearchPerformer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/AbstractKeywordSearchPerformer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,9 +21,6 @@ package org.sleuthkit.autopsy.keywordsearch; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; -import java.util.logging.Level; -import org.apache.solr.client.solrj.SolrServerException; -import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.keywordsearch.KeywordSearch.QueryType; import org.sleuthkit.autopsy.keywordsearch.KeywordSearchQueryManager.Presentation; @@ -35,7 +32,6 @@ import org.sleuthkit.autopsy.keywordsearch.KeywordSearchQueryManager.Presentatio abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel implements KeywordSearchPerformerInterface { protected int filesIndexed; - private static final Logger logger = Logger.getLogger(AbstractKeywordSearchPerformer.class.getName()); AbstractKeywordSearchPerformer() { initListeners(); @@ -47,7 +43,6 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme @Override public void propertyChange(PropertyChangeEvent evt) { String changed = evt.getPropertyName(); - Object oldValue = evt.getOldValue(); Object newValue = evt.getNewValue(); if (changed.equals(KeywordSearch.NUM_FILES_CHANGE_EVT)) { @@ -114,7 +109,7 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme KeywordSearchUtil.displayDialog("Keyword Search Error", "Keyword list is empty, please add at least one keyword to the list", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); return; } - man = new KeywordSearchQueryManager(keywords, Presentation.COLLAPSE); + man = new KeywordSearchQueryManager(keywords, Presentation.FLAT); } else { QueryType queryType = null; @@ -128,7 +123,7 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme KeywordSearchUtil.displayDialog("Keyword Search Error", "Please enter a keyword to search for", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); return; } - man = new KeywordSearchQueryManager(getQueryText(), queryType, Presentation.COLLAPSE); + man = new KeywordSearchQueryManager(getQueryText(), queryType, Presentation.FLAT); } if (man.validate()) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java index f11838f90e..c95a270952 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,7 +28,6 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; -import org.openide.windows.TopComponent; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; import org.sleuthkit.autopsy.datamodel.KeyValue; import org.sleuthkit.autopsy.keywordsearch.KeywordSearch.QueryType; @@ -41,7 +40,7 @@ public class KeywordSearchQueryManager { // how to display the results public enum Presentation { - COLLAPSE, DETAIL + FLAT, COLLAPSE, DETAIL }; private List keywords; @@ -70,7 +69,7 @@ public class KeywordSearchQueryManager { * @param presentation Presentation Layout */ public KeywordSearchQueryManager(String query, QueryType qt, Presentation presentation) { - keywords = new ArrayList(); + keywords = new ArrayList<>(); keywords.add(new Keyword(query, qt == QueryType.REGEX ? false : true)); this.presentation = presentation; queryType = qt; @@ -84,7 +83,7 @@ public class KeywordSearchQueryManager { * @param presentation Presentation layout */ public KeywordSearchQueryManager(String query, boolean isLiteral, Presentation presentation) { - keywords = new ArrayList(); + keywords = new ArrayList<>(); keywords.add(new Keyword(query, isLiteral)); this.presentation = presentation; queryType = isLiteral ? QueryType.WORD : QueryType.REGEX; @@ -96,7 +95,7 @@ public class KeywordSearchQueryManager { * Create a list of queries to later run */ private void init() { - queryDelegates = new ArrayList(); + queryDelegates = new ArrayList<>(); for (Keyword keyword : keywords) { KeywordSearchQuery query = null; switch (queryType) { @@ -137,18 +136,17 @@ public class KeywordSearchQueryManager { // } else { //Collapsed view - Collection things = new ArrayList(); + Collection things = new ArrayList<>(); int queryID = 0; StringBuilder queryConcat = new StringBuilder(); // concatenation of all query strings for (KeywordSearchQuery q : queryDelegates) { - Map kvs = new LinkedHashMap(); + Map kvs = new LinkedHashMap<>(); final String queryStr = q.getQueryString(); queryConcat.append(queryStr).append(" "); things.add(new KeyValueQuery(queryStr, kvs, ++queryID, q)); } - Node rootNode = null; - + Node rootNode; String queryConcatStr = queryConcat.toString(); final int queryConcatStrLen = queryConcatStr.length(); final String queryStrShort = queryConcatStrLen > 15 ? queryConcatStr.substring(0, 14) + "..." : queryConcatStr; @@ -156,7 +154,7 @@ public class KeywordSearchQueryManager { DataResultTopComponent searchResultWin = DataResultTopComponent.createInstance(windowTitle); if (things.size() > 0) { Children childThingNodes = - Children.create(new KeywordSearchResultFactory(keywords, things, Presentation.COLLAPSE, searchResultWin), true); + Children.create(new KeywordSearchResultFactory(keywords, things, presentation, searchResultWin), true); rootNode = new AbstractNode(childThingNodes); } else { @@ -179,7 +177,7 @@ public class KeywordSearchQueryManager { boolean allValid = true; for (KeywordSearchQuery tcq : queryDelegates) { if (!tcq.validate()) { - logger.log(Level.WARNING, "Query has invalid syntax: " + tcq.getQueryString()); + logger.log(Level.WARNING, "Query has invalid syntax: {0}", tcq.getQueryString()); allValid = false; break; } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java index d616b0361e..e595307b65 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,7 +36,6 @@ import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.util.Cancellable; -import org.openide.util.Lookup; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; @@ -109,7 +108,7 @@ public class KeywordSearchResultFactory extends ChildFactory { } KeywordSearchResultFactory(Keyword query, Collection things, Presentation presentation, DataResultTopComponent viewer) { - queries = new ArrayList(); + queries = new ArrayList<>(); queries.add(query); this.presentation = presentation; this.things = things; @@ -134,7 +133,6 @@ public class KeywordSearchResultFactory extends ChildFactory { for (int i = 0; i < FS_PROPS_LEN; ++i) { toSet.put(fsTypes[i].toString(), ""); } - } public static void setCommonProperty(Map toSet, CommonPropertyTypes type, String value) { @@ -150,10 +148,21 @@ public class KeywordSearchResultFactory extends ChildFactory { @Override protected boolean createKeys(List toPopulate) { int id = 0; - if (presentation == Presentation.DETAIL) { + if (presentation == Presentation.FLAT) { + for (KeyValueQuery thing : things) { + Map map = thing.getMap(); + initCommonProperties(map); + final String query = thing.getName(); + setCommonProperty(map, CommonPropertyTypes.KEYWORD, query); + setCommonProperty(map, CommonPropertyTypes.REGEX, Boolean.valueOf(!thing.getQuery().isEscaped())); + ResultCollapsedChildFactory childFactory = new ResultCollapsedChildFactory(thing); + childFactory.createKeysForFlatNodes(toPopulate); + } + } + else if (presentation == Presentation.DETAIL) { Iterator it = things.iterator(); for (Keyword keyword : queries) { - Map map = new LinkedHashMap(); + Map map = new LinkedHashMap<>(); final String query = keyword.getQuery(); initCommonProperties(map); setCommonProperty(map, CommonPropertyTypes.KEYWORD, query); @@ -166,25 +175,26 @@ public class KeywordSearchResultFactory extends ChildFactory { } } else { for (KeyValueQuery thing : things) { - //Map map = new LinkedHashMap(); Map map = thing.getMap(); initCommonProperties(map); final String query = thing.getName(); setCommonProperty(map, CommonPropertyTypes.KEYWORD, query); setCommonProperty(map, CommonPropertyTypes.REGEX, Boolean.valueOf(!thing.getQuery().isEscaped())); - //toPopulate.add(new KeyValue(query, map, ++id)); toPopulate.add(thing); } } - + return true; } @Override protected Node createNodeForKey(KeyValueQuery thing) { - ChildFactory childFactory = null; - - if (presentation == Presentation.COLLAPSE) { + ChildFactory childFactory; + if (presentation == Presentation.FLAT) { + ResultCollapsedChildFactory factory = new ResultCollapsedChildFactory(thing); + return factory.createFlatNodeForKey(thing); + } + else if (presentation == Presentation.COLLAPSE) { childFactory = new ResultCollapsedChildFactory(thing); final Node ret = new KeyValueNode(thing, Children.create(childFactory, true)); SwingUtilities.invokeLater(new Runnable() { @@ -199,7 +209,6 @@ public class KeywordSearchResultFactory extends ChildFactory { }); return ret; } else { - childFactory = new ResulTermsMatchesChildFactory(things); return new KeyValueNode(thing, Children.create(childFactory, true)); } @@ -218,9 +227,13 @@ public class KeywordSearchResultFactory extends ChildFactory { this.queryThing = queryThing; } + // @@@ This method is a workaround until we decide whether we need all three presentation modes or FLAT is sufficient. + public boolean createKeysForFlatNodes(List toPopulate) { + return createKeys(toPopulate); + } + @Override protected boolean createKeys(List toPopulate) { - //final String origQuery = queryThing.getName(); final KeyValueQuery queryThingQuery = queryThing; final KeywordSearchQuery tcq = queryThingQuery.getQuery(); @@ -252,7 +265,7 @@ public class KeywordSearchResultFactory extends ChildFactory { for (final AbstractFile f : hitContents.keySet()) { final int previewChunk = hitContents.get(f); //get unique match result files - Map resMap = new LinkedHashMap(); + Map resMap = new LinkedHashMap<>(); setCommonProperty(resMap, CommonPropertyTypes.MATCH, f.getName()); try { @@ -306,12 +319,11 @@ public class KeywordSearchResultFactory extends ChildFactory { //whereas in bb we write every hit per file separately new ResultWriter(tcqRes, tcq, listName).execute(); - return true; } private String getHighlightQuery(KeywordSearchQuery tcq, boolean literal_query, Map> tcqRes, AbstractFile f) { - String highlightQueryEscaped = null; + String highlightQueryEscaped; if (literal_query) { //literal, treat as non-regex, non-term component query highlightQueryEscaped = tcq.getQueryString(); @@ -326,7 +338,7 @@ public class KeywordSearchResultFactory extends ChildFactory { highlightQuery.append(term); } else { //find terms for this file hit - List hitTerms = new ArrayList(); + List hitTerms = new ArrayList<>(); for (String term : tcqRes.keySet()) { List hitList = tcqRes.get(term); @@ -363,10 +375,13 @@ public class KeywordSearchResultFactory extends ChildFactory { return highlightQueryEscaped; } + // @@@ This method is a workaround until we decide whether we need all three presentation modes or FLAT is sufficient. + public Node createFlatNodeForKey(KeyValueQuery thing) { + return createNodeForKey(thing); + } + @Override protected Node createNodeForKey(KeyValueQuery thing) { - //return new KeyValueNode(thing, Children.LEAF); - //return new KeyValueNode(thing, Children.create(new ResultFilesChildFactory(thing), true)); final KeyValueQueryContent thingContent = (KeyValueQueryContent) thing; final Content content = thingContent.getContent(); final String queryStr = thingContent.getQueryStr(); @@ -377,7 +392,6 @@ public class KeywordSearchResultFactory extends ChildFactory { //wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization HighlightedMatchesSource highlights = new HighlightedMatchesSource(content, queryStr, !thingContent.getQuery().isEscaped(), false, hits); return new KeywordSearchFilterNode(highlights, kvNode, queryStr, previewChunk); - } } @@ -438,12 +452,11 @@ public class KeywordSearchResultFactory extends ChildFactory { for (final AbstractFile f : uniqueMatches.keySet()) { final int previewChunkId = uniqueMatches.get(f); - Map resMap = new LinkedHashMap(); + Map resMap = new LinkedHashMap<>(); if (f.getType() == TSK_DB_FILES_TYPE_ENUM.FS) { AbstractFsContentNode.fillPropertyMap(resMap, (FsContent) f); } toPopulate.add(new KeyValueQueryContent(f.getName(), resMap, ++resID, f, keywordQuery, thing.getQuery(), previewChunkId, matchesRes)); - } //write to bb new ResultWriter(matchesRes, origQuery, "").execute(); @@ -459,7 +472,6 @@ public class KeywordSearchResultFactory extends ChildFactory { final int previewChunk = thingContent.getPreviewChunk(); final Map> hits = thingContent.getHits(); - Node kvNode = new KeyValueNode(thingContent, Children.LEAF, Lookups.singleton(content)); //wrap in KeywordSearchFilterNode for the markup content HighlightedMatchesSource highlights = new HighlightedMatchesSource(content, query, !thingContent.getQuery().isEscaped(), hits); @@ -475,7 +487,6 @@ public class KeywordSearchResultFactory extends ChildFactory { private Content content; private String queryStr; - private KeywordSearchQuery query; private int previewChunk; private Map> hits; @@ -510,7 +521,7 @@ public class KeywordSearchResultFactory extends ChildFactory { */ static class ResultWriter extends SwingWorker { - private static List writers = new ArrayList(); + private static List writers = new ArrayList<>(); //lock utilized to enqueue writers and limit execution to 1 at a time private static final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true); //use fairness policy //private static final Lock writerLock = rwLock.writeLock(); @@ -518,14 +529,13 @@ public class KeywordSearchResultFactory extends ChildFactory { private KeywordSearchQuery query; private String listName; private Map> hits; - final Collection na = new ArrayList(); + final Collection na = new ArrayList<>(); private static final int QUERY_DISPLAY_LEN = 40; ResultWriter(Map> hits, KeywordSearchQuery query, String listName) { this.hits = hits; this.query = query; this.listName = listName; - } protected void finalizeWorker() { @@ -539,7 +549,6 @@ public class KeywordSearchResultFactory extends ChildFactory { } }); - if (!this.isCancelled() && !na.isEmpty()) { IngestServices.getDefault().fireModuleDataEvent(new ModuleDataEvent(KeywordSearchIngestModule.MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, na)); } @@ -573,7 +582,7 @@ public class KeywordSearchResultFactory extends ChildFactory { for (AbstractFile f : flattened.keySet()) { int chunkId = flattened.get(f); final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(hit); - String snippet = null; + String snippet; try { snippet = LuceneQuery.querySnippet(snippetQuery, f.getId(), chunkId, !query.isLiteral(), true); } catch (NoOpenCoreException e) { @@ -591,15 +600,11 @@ public class KeywordSearchResultFactory extends ChildFactory { } } } - } } finally { - //writerLock.unlock(); finalizeWorker(); } - - return null; } From e50da488f929aae79c5d685f101e50c2d2ef4577 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Thu, 12 Sep 2013 16:12:59 -0400 Subject: [PATCH 10/11] Added comment to new enum about display types --- .../autopsy/keywordsearch/KeywordSearchQueryManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java index c95a270952..eec153c0d8 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQueryManager.java @@ -40,7 +40,9 @@ public class KeywordSearchQueryManager { // how to display the results public enum Presentation { - FLAT, COLLAPSE, DETAIL + FLAT, // all results are in a single level (even if multiple keywords and reg-exps are used). We made this because we were having problems with multiple-levels of nodes and the thumbnail and table view sharing an ExplorerManager. IconView seemed to change EM so that it did not allow lower levels to be selected. + COLLAPSE, // two levels. Keywords on top, files on bottom. + DETAIL // not currently used, but seems like it has three levels of nodes }; private List keywords; From ebb7c2e28a911ce0049486b250e647515b6bb87d Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Thu, 12 Sep 2013 16:13:38 -0400 Subject: [PATCH 11/11] Added comment about needing package name to be same as NBM name --- Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java index 5c7a504af1..69701ac033 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java @@ -475,6 +475,9 @@ public final class IngestModuleLoader { for (final ModuleInfo moduleInfo : moduleInfos) { if (moduleInfo.isEnabled()) { + /* NOTE: We have an assumption here that the modules in an NBM will + * have the same package name as the NBM name. This means that + * an NBM can have only one package with modules in it. */ String basePackageName = moduleInfo.getCodeNameBase(); // skip the standard ones