From a60dd923849505aba58bbd08265d63c0d9fcff62 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Thu, 6 Oct 2016 10:06:21 -0400 Subject: [PATCH 01/27] Rows initially colored, does not update upon tag addition or reordering --- .../corecomponents/DataResultViewerTable.java | 42 ++++++++++++++++++- .../datamodel/AbstractAbstractFileNode.java | 16 +++++++ .../datamodel/AbstractFsContentNode.java | 5 ++- .../datamodel/BlackboardArtifactNode.java | 18 ++++++++ .../autopsy/datamodel/Bundle.properties | 5 +++ .../autopsy/datamodel/LayoutFileNode.java | 5 ++- .../autopsy/datamodel/LocalFileNode.java | 4 +- 7 files changed, 90 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 8ea3846945..fb7f8acefb 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.corecomponents; +import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.FontMetrics; @@ -41,6 +42,7 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; +import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellRenderer; import org.netbeans.swing.outline.DefaultOutlineModel; import org.openide.explorer.ExplorerManager; @@ -55,6 +57,7 @@ import org.openide.nodes.NodeListener; import org.openide.nodes.NodeMemberEvent; import org.openide.nodes.NodeReorderEvent; import org.openide.nodes.Sheet; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; @@ -413,7 +416,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { for (int column = 0; column < ov.getOutline().getModel().getColumnCount(); column++) { int firstColumnPadding = (column == 0) ? 32 : 0; - int columnWidthLimit = (column == 0) ? 250 : 350; + int columnWidthLimit = (column == 0) ? 250 : 300; int valuesWidth = 0; // find the maximum width needed to fit the values for the first 30 rows, at most @@ -439,9 +442,44 @@ public class DataResultViewerTable extends AbstractDataResultViewer { ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); } } + // Node[] childrenNodes = currentRoot.getChildren().getNodes(); + final TableCellRenderer DEFAULT_RENDERER = ov.getOutline().getDefaultRenderer(Object.class); + final Color TAGGED_COLOR = new Color(230, 235, 240); + final Color SELECTED_COLOR = new Color(51, 153, 255); + + + class CustomRenderer extends DefaultTableCellRenderer { + private static final long serialVersionUID = 1L; + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, boolean isSelected, boolean hasFocus, int row, int col) { + Component component = DEFAULT_RENDERER.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col); + + if (col != 0) { + try { + int tag_col = ov.getOutline().getColumnModel().getColumnIndex("Tags"); + Property cellProp = (Property)(table.getModel().getValueAt(row, tag_col)); + if (cellProp != null) { + String valueString = cellProp.getValue().toString();//((Property) value).getValue().toString(); + if (!valueString.equals("")) { + component.setBackground(TAGGED_COLOR); + if (isSelected) { + component.setBackground(SELECTED_COLOR); + } + } + } + } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException ex) { + } + + } + return component; + } + } + ov.getOutline().setDefaultRenderer(Object.class, new CustomRenderer()); + } } - + /** * Store the current column order into a preference file. */ diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 0458ec9a59..f8865898da 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -20,10 +20,13 @@ package org.sleuthkit.autopsy.datamodel; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.List; import org.openide.nodes.Children; import java.util.Map; import java.util.logging.Level; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; +import org.openide.nodes.Sheet; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; @@ -31,6 +34,7 @@ import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TskCoreException; /** @@ -278,6 +282,18 @@ public abstract class AbstractAbstractFileNode extends A map.put(AbstractFilePropertyType.MIMETYPE.toString(), content.getMIMEType() == null ? "" : content.getMIMEType()); } + static void addTagProperty(Sheet.Set ss, Content content) { + final String NO_DESCR = NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.desc"); + try { + List tags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content); + ss.put(new NodeProperty<>(NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.name"), + NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), + NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex); + } + } + static String getContentDisplayName(AbstractFile file) { String name = file.getName(); switch (name) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractFsContentNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractFsContentNode.java index 5beca1dbc4..82de781b50 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractFsContentNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractFsContentNode.java @@ -84,7 +84,10 @@ public abstract class AbstractFsContentNode extends Abst ss.put(new NodeProperty<>(HIDE_PARENT, HIDE_PARENT, HIDE_PARENT, HIDE_PARENT)); } + // add tags property to the sheet + AbstractAbstractFileNode.addTagProperty(ss, content); + return s; } - + } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index bee4cba0a8..81c263980f 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -25,6 +25,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; +import java.util.stream.Collectors; import javax.swing.Action; import org.apache.commons.lang3.StringUtils; import org.openide.nodes.Children; @@ -40,9 +41,12 @@ import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; +import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.ContentTag; +import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; /** @@ -209,6 +213,20 @@ public class BlackboardArtifactNode extends DisplayableItemNode { ss.put(np); } } + + // add properties for tags + try { + List artifactTags = Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact); + List contentTags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(associated); + List tags = new ArrayList<>(artifactTags); + tags.addAll(contentTags); + ss.put(new NodeProperty<>(NbBundle.getMessage(AbstractAbstractFileNode.class, "BlackboardArtifactNode.createSheet.tags.name"), + NbBundle.getMessage(AbstractAbstractFileNode.class, "BlackboardArtifactNode.createSheet.tags.displayName"), + NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Failed to get tags for artifact " + artifact.getDisplayName(), ex); + } + final int artifactTypeId = artifact.getArtifactTypeID(); // If mismatch, add props for extension and file type diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties index ffe0797410..3134bd563d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties @@ -281,3 +281,8 @@ DeleteReportAction.actionDisplayName.multipleReports=Delete Reports DeleteReportAction.actionPerformed.showConfirmDialog.title=Confirm Deletion DeleteReportAction.actionPerformed.showConfirmDialog.single.msg=Do you want to delete 1 report from the case? DeleteReportAction.actionPerformed.showConfirmDialog.multiple.msg=Do you want to delete {0} reports from the case? +AbstractAbstractFileNode.addFileProperty.desc=no description +AbstractAbstractFileNode.addFileProperty.tags.name=Tags +AbstractAbstractFileNode.addFileProperty.tags.displayName=Tags +BlackboardArtifactNode.createSheet.tags.name=Tags +BlackboardArtifactNode.createSheet.tags.displayName=Tags \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java index 0e97757401..878f0809aa 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java @@ -39,7 +39,7 @@ import org.sleuthkit.datamodel.TskData; public class LayoutFileNode extends AbstractAbstractFileNode { public static enum LayoutContentPropertyType { - + PARTS { @Override public String toString() { @@ -86,6 +86,9 @@ public class LayoutFileNode extends AbstractAbstractFileNode { ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue())); } + // add tags property to the sheet + AbstractAbstractFileNode.addTagProperty(ss, content); + return s; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java index e2f701d044..9e3c40b595 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java @@ -74,7 +74,9 @@ public class LocalFileNode extends AbstractAbstractFileNode { for (Map.Entry entry : map.entrySet()) { ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue())); } - // @@@ add more properties here... + + // add tags property to the sheet + AbstractAbstractFileNode.addTagProperty(ss, content); return s; } From 83818aefb0ca9641833e93f5fe0418e3f15069f6 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Wed, 19 Oct 2016 17:00:58 -0400 Subject: [PATCH 02/27] Added listening to tag events for various nodes and node factories --- .../corecomponents/DataResultViewerTable.java | 2 +- .../datamodel/AbstractAbstractFileNode.java | 5 +- .../datamodel/BlackboardArtifactNode.java | 5 +- .../datamodel/BlackboardArtifactTagNode.java | 10 +++- .../autopsy/datamodel/ContentTagNode.java | 9 ++++ .../autopsy/datamodel/DataSourcesNode.java | 13 +++-- .../autopsy/datamodel/DeletedContent.java | 5 ++ .../autopsy/datamodel/EmailExtracted.java | 6 +++ .../autopsy/datamodel/ExtractedContent.java | 28 ++++++++++- .../sleuthkit/autopsy/datamodel/FileSize.java | 5 ++ .../autopsy/datamodel/FileTypesNode.java | 6 +++ .../autopsy/datamodel/HashsetHits.java | 6 +++ .../autopsy/datamodel/InterestingHits.java | 6 +++ .../autopsy/datamodel/KeywordHits.java | 47 ++++++++++++------- .../org/sleuthkit/autopsy/datamodel/Tags.java | 20 ++++---- .../autopsy/datamodel/accounts/Accounts.java | 37 ++++++++++++++- .../DirectoryTreeTopComponent.java | 1 + 17 files changed, 169 insertions(+), 42 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index fb7f8acefb..dfb84c642b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -458,7 +458,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { if (col != 0) { try { int tag_col = ov.getOutline().getColumnModel().getColumnIndex("Tags"); - Property cellProp = (Property)(table.getModel().getValueAt(row, tag_col)); + Property cellProp = (Property)(table.getModel().getValueAt(row, tag_col)); if (cellProp != null) { String valueString = cellProp.getValue().toString();//((Property) value).getValue().toString(); if (!valueString.equals("")) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index f8865898da..b8c61fcbcf 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -286,9 +286,8 @@ public abstract class AbstractAbstractFileNode extends A final String NO_DESCR = NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.desc"); try { List tags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content); - ss.put(new NodeProperty<>(NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.name"), - NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), - NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), + NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 7ceb7fbb40..1bbbc2149a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -219,9 +219,8 @@ public class BlackboardArtifactNode extends DisplayableItemNode { List contentTags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(associated); List tags = new ArrayList<>(artifactTags); tags.addAll(contentTags); - ss.put(new NodeProperty<>(NbBundle.getMessage(AbstractAbstractFileNode.class, "BlackboardArtifactNode.createSheet.tags.name"), - NbBundle.getMessage(AbstractAbstractFileNode.class, "BlackboardArtifactNode.createSheet.tags.displayName"), - NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "BlackboardArtifactNode.createSheet.tags.displayName"), + NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Failed to get tags for artifact " + artifact.getDisplayName(), ex); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactTagNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactTagNode.java index 3ff339e98d..d2620e85cd 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactTagNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactTagNode.java @@ -22,12 +22,14 @@ import java.text.MessageFormat; import java.util.Arrays; import java.util.List; import java.util.logging.Level; +import java.util.stream.Collectors; import javax.swing.Action; import org.openide.nodes.Children; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.actions.DeleteBlackboardArtifactTagAction; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction; @@ -93,7 +95,13 @@ public class BlackboardArtifactTagNode extends DisplayableItemNode { NbBundle.getMessage(this.getClass(), "BlackboardArtifactTagNode.createSheet.comment.text"), "", tag.getComment())); - + try { + List tags = Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(tag.getArtifact()); + properties.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), + "", tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + } catch (TskCoreException ex) { + //LOGGER.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex); + } return propertySheet; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java index a1d78644dd..37599dc5c8 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java @@ -21,12 +21,14 @@ package org.sleuthkit.autopsy.datamodel; import java.util.Arrays; import java.util.List; import java.util.logging.Level; +import java.util.stream.Collectors; import javax.swing.Action; import org.openide.nodes.Children; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.actions.DeleteContentTagAction; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.datamodel.AbstractFile; @@ -103,6 +105,13 @@ class ContentTagNode extends DisplayableItemNode { NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.displayName"), "", content.getSize())); + try { + List tags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content); + properties.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), + "", tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + } catch (TskCoreException ex) { + //LOGGER.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex); + } return propertySheet; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java index 73f4d95cd0..6343a79d7d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2014 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. @@ -81,6 +81,11 @@ public class DataSourcesNode extends DisplayableItemNode { String eventType = evt.getPropertyName(); if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { reloadKeys(); + } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + reloadKeys(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java index 3096a3e552..52c1b4be47 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java @@ -230,6 +230,11 @@ public class DeletedContent implements AutopsyVisitableItem { removeListeners(); } maxFilesDialogShown = false; + } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + update(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java index 9f8d3d9bd1..1e61078765 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java @@ -269,6 +269,12 @@ public class EmailExtracted implements AutopsyVisitableItem { removeNotify(); skCase = null; } + } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + refresh(true); + emailResults.update(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java index 896cec5322..ff4d9e259d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java @@ -244,9 +244,21 @@ public class ExtractedContent implements AutopsyVisitableItem { removeNotify(); skCase = null; } + } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + try { + Case.getCurrentCase(); + refresh(true); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } }; - + @Override protected void addNotify() { IngestManager.getInstance().addIngestJobEventListener(pcl); @@ -431,6 +443,18 @@ public class ExtractedContent implements AutopsyVisitableItem { * Case is closed, do nothing. */ } + } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + try { + Case.getCurrentCase(); + refresh(true); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } } } }; @@ -439,12 +463,14 @@ public class ExtractedContent implements AutopsyVisitableItem { protected void addNotify() { IngestManager.getInstance().addIngestJobEventListener(pcl); IngestManager.getInstance().addIngestModuleEventListener(pcl); + Case.addPropertyChangeListener(pcl); } @Override protected void removeNotify() { IngestManager.getInstance().removeIngestJobEventListener(pcl); IngestManager.getInstance().removeIngestModuleEventListener(pcl); + Case.removePropertyChangeListener(pcl); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java index c250166c3b..769f15973a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java @@ -226,6 +226,11 @@ public class FileSize implements AutopsyVisitableItem { if (evt.getNewValue() == null) { removeListeners(); } + } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + update(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java index daf1a31780..2c40f3e45d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java @@ -192,6 +192,12 @@ public class FileTypesNode extends DisplayableItemNode { if (evt.getNewValue() == null) { removeListeners(); } + } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + refresh(true); + update(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java index 5305df440b..068d9a44e5 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java @@ -243,6 +243,12 @@ public class HashsetHits implements AutopsyVisitableItem { removeNotify(); skCase = null; } + } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + refresh(true); + hashsetResults.update(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java index 872b5bcb25..e898ed448c 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java @@ -236,6 +236,12 @@ public class InterestingHits implements AutopsyVisitableItem { removeNotify(); skCase = null; } + } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + refresh(true); + interestingResults.update(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java index f81fd46e08..d7e95412bf 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java @@ -202,6 +202,9 @@ public class KeywordHits implements AutopsyVisitableItem { logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS } + setChanged(); + notifyObservers(); + populateMaps(artifactIds); } } @@ -306,6 +309,12 @@ public class KeywordHits implements AutopsyVisitableItem { removeNotify(); skCase = null; } + } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) + || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + refresh(true); + keywordResults.update(); } } }; @@ -409,24 +418,25 @@ public class KeywordHits implements AutopsyVisitableItem { } } - private class TermFactory extends ChildFactory.Detachable implements Observer { + private class TermFactory extends ChildFactory implements Observer { private String setName; private TermFactory(String setName) { super(); this.setName = setName; - } - - @Override - protected void addNotify() { keywordResults.addObserver(this); } - @Override - protected void removeNotify() { - keywordResults.deleteObserver(this); - } +// @Override +// protected void addNotify() { +// keywordResults.addObserver(this); +// } +// +// @Override +// protected void removeNotify() { +// keywordResults.deleteObserver(this); +// } @Override protected boolean createKeys(List list) { @@ -507,7 +517,7 @@ public class KeywordHits implements AutopsyVisitableItem { } } - public class HitsFactory extends ChildFactory.Detachable implements Observer { + public class HitsFactory extends ChildFactory implements Observer { private String keyword; private String setName; @@ -516,17 +526,18 @@ public class KeywordHits implements AutopsyVisitableItem { super(); this.setName = setName; this.keyword = keyword; - } - - @Override - protected void addNotify() { keywordResults.addObserver(this); } - @Override - protected void removeNotify() { - keywordResults.deleteObserver(this); - } +// @Override +// protected void addNotify() { +// keywordResults.addObserver(this); +// } +// +// @Override +// protected void removeNotify() { +// keywordResults.deleteObserver(this); +// } @Override protected boolean createKeys(List list) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 2d89ef3cca..1e5c71c813 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2015 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. @@ -46,8 +46,8 @@ import org.sleuthkit.datamodel.TskCoreException; * factory built on top of the NetBeans Children.Keys class. */ public class Tags implements AutopsyVisitableItem { - // Creation of a RootNode object corresponding to a Tags object is done - // by a CreateAutopsyNodeVisitor dispatched from the AbstractContentChildren + // Creation of a RootNode object corresponding to a Tags object is done + // by a CreateAutopsyNodeVisitor dispatched from the AbstractContentChildren // override of Children.Keys.createNodes(). private final TagResults tagResults = new TagResults(); @@ -134,7 +134,7 @@ public class Tags implements AutopsyVisitableItem { */ try { Case.getCurrentCase(); - refresh(true); + //refresh(true); tagResults.update(); } catch (IllegalStateException notUsed) { /** @@ -203,7 +203,7 @@ public class Tags implements AutopsyVisitableItem { @Override public void update(Observable o, Object arg) { - refresh(true); + //refresh(true); } } @@ -409,7 +409,7 @@ public class Tags implements AutopsyVisitableItem { @Override public void update(Observable o, Object arg) { - refresh(true); + refresh(true); //this caused table to update } } @@ -505,7 +505,7 @@ public class Tags implements AutopsyVisitableItem { // The blackboard artifact tags to be wrapped are used as the keys. return new BlackboardArtifactTagNode(key); } - + @Override public void update(Observable o, Object arg) { refresh(true); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java index 71b0b6492e..84b954eb70 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java @@ -320,11 +320,16 @@ final public class Accounts implements AutopsyVisitableItem { public boolean isLeafTypeNode() { return false; } - + @Override public T accept(DisplayableItemNodeVisitor v) { return v.visit(this); } + + @Override + public String getItemType() { + return getClass().getName(); + } } /** @@ -395,6 +400,11 @@ final public class Accounts implements AutopsyVisitableItem { public T accept(DisplayableItemNodeVisitor v) { return v.visit(this); } + + @Override + public String getItemType() { + return getClass().getName(); + } } /** @@ -460,6 +470,11 @@ final public class Accounts implements AutopsyVisitableItem { public T accept(DisplayableItemNodeVisitor v) { return v.visit(this); } + + @Override + public String getItemType() { + return getClass().getName(); + } } /** @@ -578,6 +593,11 @@ final public class Accounts implements AutopsyVisitableItem { return v.visit(this); } + @Override + public String getItemType() { + return getClass().getName(); + } + @Subscribe public void handleReviewStatusChange(ReviewStatusChangeEvent event) { updateDisplayName(); @@ -692,6 +712,11 @@ final public class Accounts implements AutopsyVisitableItem { return v.visit(this); } + @Override + public String getItemType() { + return getClass().getName(); + } + @Subscribe public void handleReviewStatusChange(ReviewStatusChangeEvent event) { updateDisplayName(); @@ -871,6 +896,11 @@ final public class Accounts implements AutopsyVisitableItem { return v.visit(this); } + @Override + public String getItemType() { + return getClass().getName(); + } + @Override @NbBundle.Messages({ "Accounts.FileWithCCNNode.nameProperty.displayName=File", @@ -1036,6 +1066,11 @@ final public class Accounts implements AutopsyVisitableItem { return v.visit(this); } + @Override + public String getItemType() { + return getClass().getName(); + } + private Sheet.Set getPropertySet(Sheet s) { Sheet.Set ss = s.get(Sheet.PROPERTIES); if (ss == null) { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 0a7308b065..8f63752a27 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -60,6 +60,7 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.autopsy.datamodel.DataSources; import org.sleuthkit.autopsy.datamodel.DataSourcesNode; +import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.ExtractedContent; import org.sleuthkit.autopsy.datamodel.KeywordHits; import org.sleuthkit.autopsy.datamodel.KnownFileFilterNode; From d961e4baa6d0410777abff4694be7e73a2ab50bb Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Fri, 21 Oct 2016 16:50:56 -0400 Subject: [PATCH 03/27] Modified table coloring method, reordering and filtering now work --- .../corecomponents/DataResultViewerTable.java | 71 ++++++++++++------- .../datamodel/AbstractAbstractFileNode.java | 10 +-- .../datamodel/BlackboardArtifactNode.java | 13 ++-- .../datamodel/BlackboardArtifactTagNode.java | 13 ++-- .../autopsy/datamodel/ContentTagNode.java | 17 +++-- .../autopsy/datamodel/DataSourcesNode.java | 5 -- .../autopsy/datamodel/KeywordHits.java | 8 +-- .../org/sleuthkit/autopsy/datamodel/Tags.java | 4 +- 8 files changed, 84 insertions(+), 57 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index dfb84c642b..d850b99282 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -42,8 +42,8 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; -import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellRenderer; +import org.netbeans.swing.outline.DefaultOutlineCellRenderer; import org.netbeans.swing.outline.DefaultOutlineModel; import org.openide.explorer.ExplorerManager; import org.openide.explorer.view.OutlineView; @@ -60,8 +60,12 @@ import org.openide.nodes.Sheet; import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.TskCoreException; /** * DataResult sortable table viewer @@ -77,6 +81,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { private final Set> propertiesAcc = new LinkedHashSet<>(); private final DummyNodeListener dummyNodeListener = new DummyNodeListener(); private static final String DUMMY_NODE_DISPLAY_NAME = NbBundle.getMessage(DataResultViewerTable.class, "DataResultViewerTable.dummyNodeDisplayName"); + private static final Color TAGGED_COLOR = new Color(230, 235, 240); private Node currentRoot; // The following two variables keep track of whether the user is trying // to move the first column, which is not allowed. @@ -114,6 +119,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { ov.getOutline().setRootVisible(false); ov.getOutline().setDragEnabled(false); + // add a listener so that when columns are moved, the new order is stored ov.getOutline().getColumnModel().addColumnModelListener(new TableColumnModelListener() { @Override public void columnAdded(TableColumnModelEvent e) { @@ -134,7 +140,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { if (fromIndex == toIndex) { return; } - // To keep track of attempts to move the first column + // to keep track of attempts to move the first column if (oldColumnIndex == -1) { oldColumnIndex = fromIndex; } @@ -151,6 +157,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { } }); + // add a listener to move columns back if user tries to move the first column out of place ov.getOutline().getTableHeader().addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { @@ -442,41 +449,55 @@ public class DataResultViewerTable extends AbstractDataResultViewer { ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); } } - // Node[] childrenNodes = currentRoot.getChildren().getNodes(); - final TableCellRenderer DEFAULT_RENDERER = ov.getOutline().getDefaultRenderer(Object.class); - final Color TAGGED_COLOR = new Color(230, 235, 240); - final Color SELECTED_COLOR = new Color(51, 153, 255); - - - class CustomRenderer extends DefaultTableCellRenderer { + + /** + * This custom renderer extends the renderer that was already being + * used by the outline table. This renderer colors a row if the file + * or artifact associated with the row's node is tagged. + */ + class ColorTagCustomRenderer extends DefaultOutlineCellRenderer { private static final long serialVersionUID = 1L; @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) { - Component component = DEFAULT_RENDERER.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col); - - if (col != 0) { - try { - int tag_col = ov.getOutline().getColumnModel().getColumnIndex("Tags"); - Property cellProp = (Property)(table.getModel().getValueAt(row, tag_col)); - if (cellProp != null) { - String valueString = cellProp.getValue().toString();//((Property) value).getValue().toString(); - if (!valueString.equals("")) { - component.setBackground(TAGGED_COLOR); - if (isSelected) { - component.setBackground(SELECTED_COLOR); + + Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col); + if (!isSelected) { + Node node = currentRoot.getChildren().getNodeAt(table.convertRowIndexToModel(row)); + boolean tagFound = false; + if (node != null) { + //see if there is a blackboard artifact at the node and whether the artifact is tagged + BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class); + if (artifact != null) { + try { + tagFound = !Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact).isEmpty(); + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); + } + } + + //if no tags have been found yet, see if the abstract file at the node is tagged + if (!tagFound) { + AbstractFile abstractFile = node.getLookup().lookup(AbstractFile.class); + if (abstractFile != null) { + try { + tagFound = !Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(abstractFile).isEmpty(); + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); } } } - } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException ex) { + + //if the node does have associated tags, set its background color + if (tagFound) { + component.setBackground(TAGGED_COLOR); + } } - } return component; } } - ov.getOutline().setDefaultRenderer(Object.class, new CustomRenderer()); - + ov.getOutline().setDefaultRenderer(Object.class, new ColorTagCustomRenderer()); } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index b8c61fcbcf..4cd37bed03 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.datamodel; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.ArrayList; import java.util.List; import org.openide.nodes.Children; import java.util.Map; @@ -34,7 +35,7 @@ import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.ContentTag; +import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; /** @@ -284,13 +285,14 @@ public abstract class AbstractAbstractFileNode extends A static void addTagProperty(Sheet.Set ss, Content content) { final String NO_DESCR = NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.desc"); + List tags = new ArrayList<>(); try { - List tags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content); - ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), - NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content)); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex); } + ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), + NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); } static String getContentDisplayName(AbstractFile file) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 1bbbc2149a..b10c867c9b 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -41,11 +41,9 @@ import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; -import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; @@ -214,16 +212,15 @@ public class BlackboardArtifactNode extends DisplayableItemNode { } // add properties for tags + List tags = new ArrayList<>(); try { - List artifactTags = Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact); - List contentTags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(associated); - List tags = new ArrayList<>(artifactTags); - tags.addAll(contentTags); - ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "BlackboardArtifactNode.createSheet.tags.displayName"), - NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact)); + tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(associated)); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Failed to get tags for artifact " + artifact.getDisplayName(), ex); } + ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "BlackboardArtifactNode.createSheet.tags.displayName"), + NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); final int artifactTypeId = artifact.getArtifactTypeID(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactTagNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactTagNode.java index d2620e85cd..86fce1ab78 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactTagNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactTagNode.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.datamodel; import java.text.MessageFormat; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; @@ -37,6 +38,7 @@ import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; +import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; /** @@ -95,13 +97,16 @@ public class BlackboardArtifactTagNode extends DisplayableItemNode { NbBundle.getMessage(this.getClass(), "BlackboardArtifactTagNode.createSheet.comment.text"), "", tag.getComment())); + + List tags = new ArrayList<>(); try { - List tags = Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(tag.getArtifact()); - properties.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), - "", tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(tag.getArtifact())); } catch (TskCoreException ex) { - //LOGGER.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex); + Logger.getLogger(ContentTagNode.class.getName()).log(Level.SEVERE, "Failed to get tags for artifact " + tag.getArtifact().getDisplayName(), ex); } + properties.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), + "", tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + return propertySheet; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java index 37599dc5c8..7569bc25d4 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.datamodel; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; @@ -34,6 +35,7 @@ import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; +import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; /** @@ -44,6 +46,8 @@ import org.sleuthkit.datamodel.TskCoreException; */ class ContentTagNode extends DisplayableItemNode { + private static final Logger LOGGER = Logger.getLogger(ContentTagNode.class.getName()); + private static final String ICON_PATH = "org/sleuthkit/autopsy/images/blue-tag-icon-16.png"; //NON-NLS private final ContentTag tag; @@ -62,7 +66,7 @@ class ContentTagNode extends DisplayableItemNode { try { contentPath = content.getUniquePath(); } catch (TskCoreException ex) { - Logger.getLogger(ContentTagNode.class.getName()).log(Level.SEVERE, "Failed to get path for content (id = " + content.getId() + ")", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Failed to get path for content (id = " + content.getId() + ")", ex); //NON-NLS contentPath = NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.unavail.path"); } AbstractFile file = content instanceof AbstractFile ? (AbstractFile) content : null; @@ -105,13 +109,16 @@ class ContentTagNode extends DisplayableItemNode { NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.displayName"), "", content.getSize())); + + List tags = new ArrayList<>(); try { - List tags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content); - properties.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), - "", tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content)); } catch (TskCoreException ex) { - //LOGGER.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex); + LOGGER.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex); } + properties.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), + "", tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + return propertySheet; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java index 6343a79d7d..6b4d425fbb 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java @@ -81,11 +81,6 @@ public class DataSourcesNode extends DisplayableItemNode { String eventType = evt.getPropertyName(); if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { reloadKeys(); - } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { - reloadKeys(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java index d7e95412bf..fec18d7c45 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java @@ -202,10 +202,10 @@ public class KeywordHits implements AutopsyVisitableItem { logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS } + populateMaps(artifactIds); + setChanged(); notifyObservers(); - - populateMaps(artifactIds); } } @@ -519,8 +519,8 @@ public class KeywordHits implements AutopsyVisitableItem { public class HitsFactory extends ChildFactory implements Observer { - private String keyword; - private String setName; + private final String keyword; + private final String setName; public HitsFactory(String setName, String keyword) { super(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 1e5c71c813..d3f9d6688f 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -134,7 +134,7 @@ public class Tags implements AutopsyVisitableItem { */ try { Case.getCurrentCase(); - //refresh(true); + refresh(true); tagResults.update(); } catch (IllegalStateException notUsed) { /** @@ -203,7 +203,7 @@ public class Tags implements AutopsyVisitableItem { @Override public void update(Observable o, Object arg) { - //refresh(true); + refresh(true); } } From e35faceb08834d22ae368e73aeee372e6650e8d3 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 25 Oct 2016 14:12:14 -0400 Subject: [PATCH 04/27] Now working, using property getValue to color, adding listeners at node to update --- .../casemodule/events/TagAddedEvent.java | 2 +- .../corecomponents/DataResultViewerTable.java | 67 ++++++++----------- .../datamodel/AbstractAbstractFileNode.java | 20 +++++- .../datamodel/AbstractFsContentNode.java | 2 +- .../datamodel/BlackboardArtifactNode.java | 49 ++++++++++++++ .../autopsy/datamodel/ExtractedContent.java | 4 +- .../autopsy/datamodel/KeywordHits.java | 13 +--- .../autopsy/datamodel/LayoutFileNode.java | 2 +- .../autopsy/datamodel/LocalFileNode.java | 2 +- 9 files changed, 103 insertions(+), 58 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/TagAddedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagAddedEvent.java index 365a3c0ff8..1f679c47a3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/TagAddedEvent.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagAddedEvent.java @@ -39,7 +39,7 @@ abstract class TagAddedEvent extends AutopsyEvent implements Seri private transient T tag; /** - * The id of the tag that was added. This will bu used to re-load the + * The id of the tag that was added. This will be used to re-load the * transient tag from the database. */ private final Long tagID; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index d850b99282..57ff03168f 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -60,18 +60,14 @@ import org.openide.nodes.Sheet; import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; -import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.TskCoreException; /** * DataResult sortable table viewer */ -// @@@ Restore implementation of DataResultViewerTable as a DataResultViewer -// service provider when DataResultViewers can be made compatible with node +// @@@ Restore implementation of DataResultViewerTable as a DataResultViewer +// service provider when DataResultViewers can be made compatible with node // multiple selection actions. //@ServiceProvider(service = DataResultViewer.class) public class DataResultViewerTable extends AbstractDataResultViewer { @@ -166,7 +162,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { } oldColumnIndex = -1; } - }); + }); } /** @@ -423,11 +419,12 @@ public class DataResultViewerTable extends AbstractDataResultViewer { for (int column = 0; column < ov.getOutline().getModel().getColumnCount(); column++) { int firstColumnPadding = (column == 0) ? 32 : 0; - int columnWidthLimit = (column == 0) ? 250 : 300; + int columnWidthLimit = (column == 0) ? 350 : 300; int valuesWidth = 0; - // find the maximum width needed to fit the values for the first 30 rows, at most - for (int row = 0; row < Math.min(30, ov.getOutline().getRowCount()); row++) { + // find the maximum width needed to fit the values for the first 15 rows, at most + // *15 is an arbitrary number + for (int row = 0; row < Math.min(15, ov.getOutline().getRowCount()); row++) { TableCellRenderer renderer = ov.getOutline().getCellRenderer(row, column); Component comp = ov.getOutline().prepareRenderer(renderer, row, column); valuesWidth = Math.max(comp.getPreferredSize().width, valuesWidth); @@ -466,32 +463,26 @@ public class DataResultViewerTable extends AbstractDataResultViewer { Node node = currentRoot.getChildren().getNodeAt(table.convertRowIndexToModel(row)); boolean tagFound = false; if (node != null) { - //see if there is a blackboard artifact at the node and whether the artifact is tagged - BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class); - if (artifact != null) { - try { - tagFound = !Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact).isEmpty(); - } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); - } - } + Node.PropertySet[] propSets = node.getPropertySets(); - //if no tags have been found yet, see if the abstract file at the node is tagged - if (!tagFound) { - AbstractFile abstractFile = node.getLookup().lookup(AbstractFile.class); - if (abstractFile != null) { - try { - tagFound = !Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(abstractFile).isEmpty(); - } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); + if (propSets.length != 0) { + Node.Property[] props = propSets[0].getProperties(); + for (Property prop : props) { + if (prop.getName().equals("Tags")) { + try { + tagFound = !prop.getValue().equals(""); + } catch (IllegalAccessException | InvocationTargetException ex) { + Exceptions.printStackTrace(ex); + } + break; } } } + } - //if the node does have associated tags, set its background color - if (tagFound) { - component.setBackground(TAGGED_COLOR); - } + //if the node does have associated tags, set its background color + if (tagFound) { + component.setBackground(TAGGED_COLOR); } } return component; @@ -500,7 +491,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { ov.getOutline().setDefaultRenderer(Object.class, new ColorTagCustomRenderer()); } } - + /** * Store the current column order into a preference file. */ @@ -580,8 +571,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer { + prop.getName().replaceAll("[^a-zA-Z0-9_]", "") + ".column"; } - // Populate a two-dimensional array with rows of property values for up - // to maxRows children of the node passed in. + // Populate a two-dimensional array with rows of property values for up + // to maxRows children of the node passed in. private static Object[][] getRowValues(Node node, int maxRows) { int numRows = Math.min(maxRows, node.getChildren().getNodesCount()); Object[][] rowValues = new Object[numRows][]; @@ -591,10 +582,10 @@ public class DataResultViewerTable extends AbstractDataResultViewer { break; } // BC: I got this once, I think it was because the table - // refreshed while we were in this method - // could be better synchronized. Or it was from - // the lazy nodes updating... Didn't have time - // to fully debug it. + // refreshed while we were in this method + // could be better synchronized. Or it was from + // the lazy nodes updating... Didn't have time + // to fully debug it. if (rowCount > numRows) { break; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 4cd37bed03..4b23a47898 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -30,6 +30,8 @@ import org.apache.commons.lang3.StringUtils; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; +import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; @@ -101,16 +103,30 @@ public abstract class AbstractAbstractFileNode extends A } catch (NullPointerException ex) { // Skip } - + } } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { if (evt.getNewValue() == null) { // case was closed. Remove listeners so that we don't get called with a stale case handle removeListeners(); } + } else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) { + ContentTagAddedEvent event = (ContentTagAddedEvent) evt; + if (event.getAddedTag().getContent().equals(content)) { + updateSheet(); + } + } else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + ContentTagDeletedEvent event = (ContentTagDeletedEvent) evt; + if (event.getDeletedTagInfo().getContentID() == content.getId()) { + updateSheet(); + } } }; + private void updateSheet() { + this.setSheet(createSheet()); + } + // Note: this order matters for the search result, changed it if the order of property headers on the "KeywordSearchNode"changed public static enum AbstractFilePropertyType { @@ -283,7 +299,7 @@ public abstract class AbstractAbstractFileNode extends A map.put(AbstractFilePropertyType.MIMETYPE.toString(), content.getMIMEType() == null ? "" : content.getMIMEType()); } - static void addTagProperty(Sheet.Set ss, Content content) { + protected void addTagProperty(Sheet.Set ss) { final String NO_DESCR = NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.desc"); List tags = new ArrayList<>(); try { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractFsContentNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractFsContentNode.java index 82de781b50..675e666373 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractFsContentNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractFsContentNode.java @@ -85,7 +85,7 @@ public abstract class AbstractFsContentNode extends Abst } // add tags property to the sheet - AbstractAbstractFileNode.addTagProperty(ss, content); + addTagProperty(ss); return s; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index b10c867c9b..8400c665e0 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.datamodel; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -36,6 +38,10 @@ import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent; +import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent; +import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; +import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction; import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.datamodel.AbstractFile; @@ -72,6 +78,39 @@ public class BlackboardArtifactNode extends DisplayableItemNode { private static final Integer[] SHOW_FILE_METADATA = new Integer[]{ BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),}; + private final PropertyChangeListener pcl = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + String eventType = evt.getPropertyName(); + if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString())) { + BlackBoardArtifactTagAddedEvent event = (BlackBoardArtifactTagAddedEvent) evt; + if (event.getAddedTag().getArtifact().equals(artifact)) { + updateSheet(); + } + } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString())) { + BlackBoardArtifactTagDeletedEvent event = (BlackBoardArtifactTagDeletedEvent) evt; + if (event.getDeletedTagInfo().getArtifactID() == artifact.getArtifactID()) { + updateSheet(); + } + } else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) { + ContentTagAddedEvent event = (ContentTagAddedEvent) evt; + if (event.getAddedTag().getContent().equals(associated)) { + updateSheet(); + } + } else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + ContentTagDeletedEvent event = (ContentTagDeletedEvent) evt; + if (event.getDeletedTagInfo().getContentID()== associated.getId()) { + updateSheet(); + } + } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + if (evt.getNewValue() == null) { + // case was closed. Remove listeners so that we don't get called with a stale case handle + removeListeners(); + } + } + } + }; + /** * Construct blackboard artifact node from an artifact and using provided * icon @@ -88,6 +127,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode { this.setName(Long.toString(artifact.getArtifactID())); this.setDisplayName(); this.setIconBaseWithExtension(iconPath); + Case.addPropertyChangeListener(pcl); } /** @@ -105,6 +145,11 @@ public class BlackboardArtifactNode extends DisplayableItemNode { this.setName(Long.toString(artifact.getArtifactID())); this.setDisplayName(); this.setIconBaseWithExtension(ExtractedContent.getIconFilePath(artifact.getArtifactTypeID())); //NON-NLS + Case.addPropertyChangeListener(pcl); + } + + private void removeListeners() { + Case.removePropertyChangeListener(pcl); } @Override @@ -311,6 +356,10 @@ public class BlackboardArtifactNode extends DisplayableItemNode { return s; } + private void updateSheet() { + this.setSheet(createSheet()); + } + private String getRootParentName() { String parentName = associated.getName(); Content parent = associated; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java index ff4d9e259d..603d056a08 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java @@ -444,9 +444,7 @@ public class ExtractedContent implements AutopsyVisitableItem { */ } } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) { try { Case.getCurrentCase(); refresh(true); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java index fec18d7c45..5a996d494a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java @@ -203,9 +203,6 @@ public class KeywordHits implements AutopsyVisitableItem { } populateMaps(artifactIds); - - setChanged(); - notifyObservers(); } } @@ -309,12 +306,6 @@ public class KeywordHits implements AutopsyVisitableItem { removeNotify(); skCase = null; } - } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { - refresh(true); - keywordResults.update(); } } }; @@ -457,8 +448,8 @@ public class KeywordHits implements AutopsyVisitableItem { public class TermNode extends DisplayableItemNode implements Observer { - private String setName; - private String keyword; + private final String setName; + private final String keyword; public TermNode(String setName, String keyword) { super(Children.create(new HitsFactory(setName, keyword), true), Lookups.singleton(keyword)); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java index 878f0809aa..158b682ac5 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java @@ -87,7 +87,7 @@ public class LayoutFileNode extends AbstractAbstractFileNode { } // add tags property to the sheet - AbstractAbstractFileNode.addTagProperty(ss, content); + addTagProperty(ss); return s; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java index 9e3c40b595..b7019cfeb7 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java @@ -76,7 +76,7 @@ public class LocalFileNode extends AbstractAbstractFileNode { } // add tags property to the sheet - AbstractAbstractFileNode.addTagProperty(ss, content); + addTagProperty(ss); return s; } From f126b5a23a6359fdd2ffd4bb560b1a33e3ba72db Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 25 Oct 2016 14:33:56 -0400 Subject: [PATCH 05/27] Recognized that exception thrown by getValue is ignored --- .../autopsy/corecomponents/DataResultViewerTable.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 57ff03168f..7a1bd8acf4 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -471,8 +471,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { if (prop.getName().equals("Tags")) { try { tagFound = !prop.getValue().equals(""); - } catch (IllegalAccessException | InvocationTargetException ex) { - Exceptions.printStackTrace(ex); + } catch (IllegalAccessException | InvocationTargetException ignore) { } break; } From c89af585ef5659783fe1a34ac51703f57c639fe4 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 25 Oct 2016 16:34:30 -0400 Subject: [PATCH 06/27] Cleaned up code --- .../corecomponents/DataResultViewerTable.java | 7 ++-- .../datamodel/AbstractAbstractFileNode.java | 5 +++ .../datamodel/AbstractFsContentNode.java | 2 +- .../autopsy/datamodel/DeletedContent.java | 5 --- .../autopsy/datamodel/EmailExtracted.java | 6 --- .../autopsy/datamodel/ExtractedContent.java | 26 +------------ .../sleuthkit/autopsy/datamodel/FileSize.java | 5 --- .../autopsy/datamodel/FileTypesNode.java | 6 --- .../autopsy/datamodel/HashsetHits.java | 6 --- .../autopsy/datamodel/InterestingHits.java | 6 --- .../autopsy/datamodel/KeywordHits.java | 38 +++++++++---------- .../autopsy/datamodel/LayoutFileNode.java | 2 +- .../org/sleuthkit/autopsy/datamodel/Tags.java | 2 +- .../autopsy/datamodel/accounts/Accounts.java | 2 +- 14 files changed, 32 insertions(+), 86 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 7a1bd8acf4..2011d01911 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -449,8 +449,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer { /** * This custom renderer extends the renderer that was already being - * used by the outline table. This renderer colors a row if the file - * or artifact associated with the row's node is tagged. + * used by the outline table. This renderer colors a row if the + * tags property of the node is not empty. */ class ColorTagCustomRenderer extends DefaultOutlineCellRenderer { private static final long serialVersionUID = 1L; @@ -459,13 +459,14 @@ public class DataResultViewerTable extends AbstractDataResultViewer { Object value, boolean isSelected, boolean hasFocus, int row, int col) { Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col); + // only override the color if a node is not selected if (!isSelected) { Node node = currentRoot.getChildren().getNodeAt(table.convertRowIndexToModel(row)); boolean tagFound = false; if (node != null) { Node.PropertySet[] propSets = node.getPropertySets(); - if (propSets.length != 0) { + // currently, a node has only one property set, named Sheet.PROPERTIES ("properties") Node.Property[] props = propSets[0].getProperties(); for (Property prop : props) { if (prop.getName().equals("Tags")) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 4b23a47898..6d005d2aaf 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -299,6 +299,11 @@ public abstract class AbstractAbstractFileNode extends A map.put(AbstractFilePropertyType.MIMETYPE.toString(), content.getMIMEType() == null ? "" : content.getMIMEType()); } + /** + * Used by subclasses of AbstractAbstractFileNode to add the tags property + * to their sheets. + * @param ss + */ protected void addTagProperty(Sheet.Set ss) { final String NO_DESCR = NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.desc"); List tags = new ArrayList<>(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractFsContentNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractFsContentNode.java index 675e666373..a6db3c1df1 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractFsContentNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractFsContentNode.java @@ -89,5 +89,5 @@ public abstract class AbstractFsContentNode extends Abst return s; } - + } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java index 52c1b4be47..3096a3e552 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java @@ -230,11 +230,6 @@ public class DeletedContent implements AutopsyVisitableItem { removeListeners(); } maxFilesDialogShown = false; - } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { - update(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java index 1e61078765..9f8d3d9bd1 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java @@ -269,12 +269,6 @@ public class EmailExtracted implements AutopsyVisitableItem { removeNotify(); skCase = null; } - } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { - refresh(true); - emailResults.update(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java index 603d056a08..896cec5322 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java @@ -244,21 +244,9 @@ public class ExtractedContent implements AutopsyVisitableItem { removeNotify(); skCase = null; } - } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { - try { - Case.getCurrentCase(); - refresh(true); - } catch (IllegalStateException notUsed) { - /** - * Case is closed, do nothing. - */ - } } }; - + @Override protected void addNotify() { IngestManager.getInstance().addIngestJobEventListener(pcl); @@ -443,16 +431,6 @@ public class ExtractedContent implements AutopsyVisitableItem { * Case is closed, do nothing. */ } - } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) { - try { - Case.getCurrentCase(); - refresh(true); - } catch (IllegalStateException notUsed) { - /** - * Case is closed, do nothing. - */ - } } } }; @@ -461,14 +439,12 @@ public class ExtractedContent implements AutopsyVisitableItem { protected void addNotify() { IngestManager.getInstance().addIngestJobEventListener(pcl); IngestManager.getInstance().addIngestModuleEventListener(pcl); - Case.addPropertyChangeListener(pcl); } @Override protected void removeNotify() { IngestManager.getInstance().removeIngestJobEventListener(pcl); IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removePropertyChangeListener(pcl); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java index 769f15973a..c250166c3b 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java @@ -226,11 +226,6 @@ public class FileSize implements AutopsyVisitableItem { if (evt.getNewValue() == null) { removeListeners(); } - } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { - update(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java index 2c40f3e45d..daf1a31780 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java @@ -192,12 +192,6 @@ public class FileTypesNode extends DisplayableItemNode { if (evt.getNewValue() == null) { removeListeners(); } - } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { - refresh(true); - update(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java index 068d9a44e5..5305df440b 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java @@ -243,12 +243,6 @@ public class HashsetHits implements AutopsyVisitableItem { removeNotify(); skCase = null; } - } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { - refresh(true); - hashsetResults.update(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java index e898ed448c..872b5bcb25 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java @@ -236,12 +236,6 @@ public class InterestingHits implements AutopsyVisitableItem { removeNotify(); skCase = null; } - } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { - refresh(true); - interestingResults.update(); } } }; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java index 5a996d494a..240f4e0ec0 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java @@ -409,25 +409,24 @@ public class KeywordHits implements AutopsyVisitableItem { } } - private class TermFactory extends ChildFactory implements Observer { + private class TermFactory extends ChildFactory.Detachable implements Observer { private String setName; private TermFactory(String setName) { super(); this.setName = setName; + } + + @Override + protected void addNotify() { keywordResults.addObserver(this); } -// @Override -// protected void addNotify() { -// keywordResults.addObserver(this); -// } -// -// @Override -// protected void removeNotify() { -// keywordResults.deleteObserver(this); -// } + @Override + protected void removeNotify() { + keywordResults.deleteObserver(this); + } @Override protected boolean createKeys(List list) { @@ -508,7 +507,7 @@ public class KeywordHits implements AutopsyVisitableItem { } } - public class HitsFactory extends ChildFactory implements Observer { + public class HitsFactory extends ChildFactory.Detachable implements Observer { private final String keyword; private final String setName; @@ -517,18 +516,17 @@ public class KeywordHits implements AutopsyVisitableItem { super(); this.setName = setName; this.keyword = keyword; + } + + @Override + protected void addNotify() { keywordResults.addObserver(this); } -// @Override -// protected void addNotify() { -// keywordResults.addObserver(this); -// } -// -// @Override -// protected void removeNotify() { -// keywordResults.deleteObserver(this); -// } + @Override + protected void removeNotify() { + keywordResults.deleteObserver(this); + } @Override protected boolean createKeys(List list) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java index 158b682ac5..495737488b 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java @@ -39,7 +39,7 @@ import org.sleuthkit.datamodel.TskData; public class LayoutFileNode extends AbstractAbstractFileNode { public static enum LayoutContentPropertyType { - + PARTS { @Override public String toString() { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index d3f9d6688f..ff51e7c92e 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -409,7 +409,7 @@ public class Tags implements AutopsyVisitableItem { @Override public void update(Observable o, Object arg) { - refresh(true); //this caused table to update + refresh(true); } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java index 84b954eb70..f1205211a4 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java @@ -320,7 +320,7 @@ final public class Accounts implements AutopsyVisitableItem { public boolean isLeafTypeNode() { return false; } - + @Override public T accept(DisplayableItemNodeVisitor v) { return v.visit(this); From f803b01f182eb252f5e2b1303d64c8ced943c036 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Wed, 26 Oct 2016 13:38:26 -0400 Subject: [PATCH 07/27] Cleaned up DataResultViewerTable --- .../corecomponents/DataResultViewerTable.java | 61 +++---------------- 1 file changed, 8 insertions(+), 53 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 2011d01911..d312af106a 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -57,7 +57,6 @@ import org.openide.nodes.NodeListener; import org.openide.nodes.NodeMemberEvent; import org.openide.nodes.NodeReorderEvent; import org.openide.nodes.Sheet; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; @@ -72,6 +71,8 @@ import org.sleuthkit.autopsy.coreutils.Logger; //@ServiceProvider(service = DataResultViewer.class) public class DataResultViewerTable extends AbstractDataResultViewer { + private static final long serialVersionUID = 1L; + private final String firstColumnLabel = NbBundle.getMessage(DataResultViewerTable.class, "DataResultViewerTable.firstColLbl"); // This is a set because we add properties of up to 100 child nodes, and we want unique properties private final Set> propertiesAcc = new LinkedHashSet<>(); @@ -405,10 +406,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { ov.getOutline().setAutoResizeMode((props.size() > 0) ? JTable.AUTO_RESIZE_OFF : JTable.AUTO_RESIZE_ALL_COLUMNS); // get first row's values for the table - Object[][] content; - content = getRowValues(root, 1); - - if (content != null) { + if (root.getChildren().getNodesCount() != 0) { final Graphics graphics = ov.getGraphics(); if (graphics != null) { @@ -438,13 +436,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { columnWidth = Math.min(columnWidth, columnWidthLimit); ov.getOutline().getColumnModel().getColumn(column).setPreferredWidth(columnWidth); - } - - // if there's no content just auto resize all columns - if (content.length <= 0) { - // turn on the auto resize - ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); - } + } } /** @@ -479,7 +471,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer { } } } - //if the node does have associated tags, set its background color if (tagFound) { component.setBackground(TAGGED_COLOR); @@ -489,6 +480,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer { } } ov.getOutline().setDefaultRenderer(Object.class, new ColorTagCustomRenderer()); + } else { + ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); } } @@ -571,41 +564,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer { + prop.getName().replaceAll("[^a-zA-Z0-9_]", "") + ".column"; } - // Populate a two-dimensional array with rows of property values for up - // to maxRows children of the node passed in. - private static Object[][] getRowValues(Node node, int maxRows) { - int numRows = Math.min(maxRows, node.getChildren().getNodesCount()); - Object[][] rowValues = new Object[numRows][]; - int rowCount = 0; - for (Node child : node.getChildren().getNodes()) { - if (rowCount >= maxRows) { - break; - } - // BC: I got this once, I think it was because the table - // refreshed while we were in this method - // could be better synchronized. Or it was from - // the lazy nodes updating... Didn't have time - // to fully debug it. - if (rowCount > numRows) { - break; - } - PropertySet[] propertySets = child.getPropertySets(); - if (propertySets.length > 0) { - Property[] properties = propertySets[0].getProperties(); - rowValues[rowCount] = new Object[properties.length]; - for (int j = 0; j < properties.length; ++j) { - try { - rowValues[rowCount][j] = properties[j].getValue(); - } catch (IllegalAccessException | InvocationTargetException ignore) { - rowValues[rowCount][j] = "n/a"; //NON-NLS - } - } - } - ++rowCount; - } - return rowValues; - } - @Override public String getTitle() { return NbBundle.getMessage(this.getClass(), "DataResultViewerTable.title"); @@ -640,11 +598,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer { if (SwingUtilities.isEventDispatchThread()) { setupTable(nme.getNode()); } else { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - setupTable(nme.getNode()); - } + SwingUtilities.invokeLater(() -> { + setupTable(nme.getNode()); }); } } From 5242566ea09907245ec9f32b3b5950f88b01874a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 8 Nov 2016 17:30:48 -0500 Subject: [PATCH 08/27] 1917 Added Node Level between Views and (Files by Ext AND Files by MIME) --- .../datamodel/AbstractContentChildren.java | 5 ++ .../autopsy/datamodel/AutopsyItemVisitor.java | 8 +++ .../datamodel/DisplayableItemNodeVisitor.java | 8 ++- .../autopsy/datamodel/FileTypes.java | 42 ++++++++++++ .../autopsy/datamodel/FileTypesNew.java | 66 +++++++++++++++++++ .../autopsy/datamodel/ResultsNode.java | 2 + .../autopsy/datamodel/ViewsNode.java | 3 +- .../directorytree/DataResultFilterNode.java | 15 ++++- .../DirectoryTreeFilterChildren.java | 11 ++++ 9 files changed, 156 insertions(+), 4 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java create mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java index f2babbc88e..db85e382f3 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java @@ -189,6 +189,11 @@ abstract class AbstractContentChildren extends Keys { return new ResultsNode(r.getSleuthkitCase()); } + @Override + public AbstractNode visit(FileTypes ft) { + return new FileTypesNew(ft.getSleuthkitCase()); + } + @Override public AbstractNode visit(Reports reportsItem) { return new Reports.ReportsListNode(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java index d673acb71e..e06e7c9d08 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java @@ -71,6 +71,8 @@ public interface AutopsyItemVisitor { T visit(Accounts accountsItem); + T visit(FileTypes aThis); + static abstract public class Default implements AutopsyItemVisitor { protected abstract T defaultVisit(AutopsyVisitableItem ec); @@ -170,6 +172,12 @@ public interface AutopsyItemVisitor { return defaultVisit(r); } + + @Override + public T visit(FileTypes ft) { + return defaultVisit(ft); + } + @Override public T visit(Reports reportsItem) { return defaultVisit(reportsItem); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index e300ace134..3af8d3c0f8 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -140,6 +140,8 @@ public interface DisplayableItemNodeVisitor { T visit(Accounts.DefaultAccountTypeNode node); + T visit(FileTypesNew fileTypes); + /** * Visitor with an implementable default behavior for all types. Override * specific visit types to not use the default behavior. @@ -256,7 +258,11 @@ public interface DisplayableItemNodeVisitor { public T visit(ResultsNode rn) { return defaultVisit(rn); } - + + @Override + public T visit(FileTypesNew ft) { + return defaultVisit(ft); + } @Override public T visit(DataSourcesNode in) { return defaultVisit(in); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java new file mode 100644 index 0000000000..f977a1e797 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java @@ -0,0 +1,42 @@ +/* + * 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 org.sleuthkit.datamodel.SleuthkitCase; + +/** + * Results node support + */ +public class FileTypes implements AutopsyVisitableItem { + + private SleuthkitCase skCase; + + public FileTypes(SleuthkitCase skCase) { + this.skCase = skCase; + } + + @Override + public T accept(AutopsyItemVisitor v) { + return v.visit(this); + } + + public SleuthkitCase getSleuthkitCase() { + return skCase; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java new file mode 100644 index 0000000000..b0273b4ae4 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java @@ -0,0 +1,66 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.datamodel; + +import java.util.Arrays; +import org.openide.nodes.Sheet; +import org.openide.util.NbBundle; +import org.openide.util.lookup.Lookups; +import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters; +import org.sleuthkit.datamodel.SleuthkitCase; + +/** + * + * @author wschaefer + */ +public class FileTypesNew extends DisplayableItemNode { + + @NbBundle.Messages("FileTypesNew.name.text=File Types_New") + public static final String NAME = Bundle.FileTypesNew_name_text(); + + public FileTypesNew(SleuthkitCase sleuthkitCase) { + super(new RootContentChildren(Arrays.asList( + + new FileTypeExtensionFilters(sleuthkitCase) + )), Lookups.singleton(NAME)); + setName(NAME); + setDisplayName(NAME); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); + } + + + @Override + public boolean isLeafTypeNode() { + return false; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + @NbBundle.Messages({ + "FileTypesNew.createSheet.name.name=Name", + "FileTypesNew.createSheet.name.displayName=Name", + "FileTypesNew.createSheet.name.desc=no description"}) + protected Sheet createSheet() { + Sheet s = super.createSheet(); + Sheet.Set ss = s.get(Sheet.PROPERTIES); + if (ss == null) { + ss = Sheet.createPropertiesSet(); + s.put(ss); + } + + ss.put(new NodeProperty<>(Bundle.FileTypesNew_createSheet_name_name(), + Bundle.FileTypesNew_createSheet_name_displayName(), + Bundle.FileTypesNew_createSheet_name_desc(), + NAME + )); + return s; + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ResultsNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ResultsNode.java index ebf71a872d..d3b2cf8371 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ResultsNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ResultsNode.java @@ -33,6 +33,8 @@ public class ResultsNode extends DisplayableItemNode { @NbBundle.Messages("ResultsNode.name.text=Results") public static final String NAME = Bundle.ResultsNode_name_text(); + + public ResultsNode(SleuthkitCase sleuthkitCase) { super(new RootContentChildren(Arrays.asList( new ExtractedContent(sleuthkitCase), diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java index 89a6ac170f..06551eab67 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java @@ -36,7 +36,8 @@ public class ViewsNode extends DisplayableItemNode { public ViewsNode(SleuthkitCase sleuthkitCase) { super(new RootContentChildren(Arrays.asList( - new FileTypeExtensionFilters(sleuthkitCase), + // new FileTypeExtensionFilters(sleuthkitCase), + new FileTypes(sleuthkitCase), // June '15: Recent Files was removed because it was not useful w/out filtering // add it back in if we can filter the results to a more managable size. // new RecentFiles(sleuthkitCase), diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index ec66a5d4c7..26a14f34d3 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -42,6 +42,7 @@ import org.sleuthkit.autopsy.datamodel.DirectoryNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.FileNode; +import org.sleuthkit.autopsy.datamodel.FileTypesNew; import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.Reports; @@ -231,7 +232,12 @@ public class DataResultFilterNode extends FilterNode { // The base class Action is "Collapse All", inappropriate. return null; } - + + @Override + public List visit(FileTypesNew fileTypes) { + return defaultVisit(fileTypes); + } + @Override protected List defaultVisit(DisplayableItemNode ditem) { //preserve the default node's actions @@ -271,6 +277,7 @@ public class DataResultFilterNode extends FilterNode { } return c; } + } /* @@ -322,7 +329,11 @@ public class DataResultFilterNode extends FilterNode { protected AbstractAction defaultVisit(DisplayableItemNode c) { return openChild(c); } - + + @Override + public AbstractAction visit(FileTypesNew fileTypes) { + return openChild(fileTypes); + } /** * Tell the originating ExplorerManager to display the given * dataModelNode. diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java index e6ce27bc0e..728e42c426 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java @@ -29,6 +29,7 @@ import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.FileNode; +import org.sleuthkit.autopsy.datamodel.FileTypesNew; import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; @@ -236,6 +237,11 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { return visitDeep(vdn); //return ! vdn.hasContentChildren(); } + + @Override + public Boolean visit(FileTypesNew ft) { + return defaultVisit(ft); + } } private static class ShowItemVisitor extends DisplayableItemNodeVisitor.Default { @@ -273,5 +279,10 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { return true; //return vdn.hasContentChildren(); } + + @Override + public Boolean visit(FileTypesNew fileTypes) { + return defaultVisit(fileTypes); + } } } From 5052d62133dfc16afeaf878adcc0fa93b6669fcf Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Wed, 9 Nov 2016 10:32:58 -0500 Subject: [PATCH 09/27] Clean up code --- .../corecomponents/DataResultViewerTable.java | 12 ++++++------ .../datamodel/AbstractAbstractFileNode.java | 4 ++-- .../autopsy/datamodel/ContentTagNode.java | 10 +++++----- .../autopsy/datamodel/DataSourcesNode.java | 13 +++++++------ .../sleuthkit/autopsy/datamodel/KeywordHits.java | 6 +++--- .../sleuthkit/autopsy/datamodel/LocalFileNode.java | 7 +++---- Core/src/org/sleuthkit/autopsy/datamodel/Tags.java | 14 +++++++------- 7 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 0d6f057f9b..21135f68c8 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * - * Copyright 2013-2014 Basis Technology Corp. + * + * Copyright 2013-2016 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. @@ -391,7 +391,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { columnWidth = Math.min(columnWidth, columnWidthLimit); ov.getOutline().getColumnModel().getColumn(column).setPreferredWidth(columnWidth); - } + } } } else { // if there's no content just auto resize all columns diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 6d005d2aaf..131c069aa0 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -103,7 +103,7 @@ public abstract class AbstractAbstractFileNode extends A } catch (NullPointerException ex) { // Skip } - + } } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { if (evt.getNewValue() == null) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java index 7569bc25d4..8099bbc300 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * - * Copyright 2013 Basis Technology Corp. + * + * Copyright 2013-2016 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. diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java index 6b4d425fbb..7ac9e37398 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * - * Copyright 2011-2014 Basis Technology Corp. + * + * Copyright 2011-2016 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. @@ -23,6 +23,7 @@ import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.logging.Level; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; @@ -103,7 +104,7 @@ public class DataSourcesNode extends DisplayableItemNode { currentKeys = Case.getCurrentCase().getDataSources(); setKeys(currentKeys); } catch (TskCoreException | IllegalStateException ex) { - logger.severe("Error getting data sources: " + ex.getMessage()); // NON-NLS + logger.log(Level.SEVERE, "Error getting data sources: {0}", ex.getMessage()); // NON-NLS setKeys(Collections.emptySet()); } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java index 240f4e0ec0..c7b8983be0 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2015 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -346,7 +346,7 @@ public class KeywordHits implements AutopsyVisitableItem { public class ListNode extends DisplayableItemNode implements Observer { - private String listName; + private final String listName; public ListNode(String listName) { super(Children.create(new TermFactory(listName), true), Lookups.singleton(listName)); @@ -411,7 +411,7 @@ public class KeywordHits implements AutopsyVisitableItem { private class TermFactory extends ChildFactory.Detachable implements Observer { - private String setName; + private final String setName; private TermFactory(String setName) { super(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java index b7019cfeb7..ecccb26272 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2014 Basis Technology Corp. + * Copyright 2013-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.datamodel; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -84,9 +85,7 @@ public class LocalFileNode extends AbstractAbstractFileNode { @Override public Action[] getActions(boolean context) { List actionsList = new ArrayList<>(); - for (Action a : super.getActions(true)) { - actionsList.add(a); - } + actionsList.addAll(Arrays.asList(super.getActions(true))); actionsList.add(new ViewContextAction(NbBundle.getMessage(this.getClass(), "LocalFileNode.viewFileInDir.text"), this.content)); actionsList.add(null); // creates a menu separator actionsList.add(new NewWindowViewAction( diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index ff51e7c92e..b8127fe5a7 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * - * Copyright 2011-2015 Basis Technology Corp. + * + * Copyright 2011-2016 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. @@ -325,7 +325,7 @@ public class Tags implements AutopsyVisitableItem { public class ContentTagTypeNode extends DisplayableItemNode implements Observer { private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS - private TagName tagName; + private final TagName tagName; public ContentTagTypeNode(TagName tagName) { super(Children.create(new ContentTagNodeFactory(tagName), true), Lookups.singleton(tagName.getDisplayName() + " " + CONTENT_DISPLAY_NAME)); @@ -423,7 +423,7 @@ public class Tags implements AutopsyVisitableItem { */ public class BlackboardArtifactTagTypeNode extends DisplayableItemNode implements Observer { - private TagName tagName; + private final TagName tagName; private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS public BlackboardArtifactTagTypeNode(TagName tagName) { From cfeae3485099cb12a3d09e1970463a037524ef4d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 11 Nov 2016 13:55:47 -0500 Subject: [PATCH 10/27] 1917 - Mime Type tree added - still needs clean up and null case --- .../datamodel/AbstractContentChildren.java | 10 +- .../autopsy/datamodel/AutopsyItemVisitor.java | 12 +- .../autopsy/datamodel/Bundle.properties | 2 +- .../datamodel/DisplayableItemNodeVisitor.java | 33 +- ...leTypeNode.java => FileTypeByExtNode.java} | 6 +- .../autopsy/datamodel/FileTypes.java | 68 ++- ...TypesNode.java => FileTypesByExtNode.java} | 14 +- .../datamodel/FileTypesByMimeType.java | 407 ++++++++++++++++++ .../autopsy/datamodel/FileTypesNew.java | 66 --- .../directorytree/DataResultFilterNode.java | 10 +- .../DirectoryTreeFilterChildren.java | 8 +- 11 files changed, 539 insertions(+), 97 deletions(-) rename Core/src/org/sleuthkit/autopsy/datamodel/{FileTypeNode.java => FileTypeByExtNode.java} (97%) rename Core/src/org/sleuthkit/autopsy/datamodel/{FileTypesNode.java => FileTypesByExtNode.java} (93%) create mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java delete mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java index db85e382f3..67cfda93df 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java @@ -22,6 +22,7 @@ import org.openide.nodes.AbstractNode; import org.openide.nodes.Children.Keys; import org.openide.nodes.Node; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode; import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters; import org.sleuthkit.autopsy.datamodel.accounts.RecentFiles; import org.sleuthkit.autopsy.datamodel.accounts.Accounts; @@ -131,7 +132,7 @@ abstract class AbstractContentChildren extends Keys { @Override public AbstractNode visit(FileTypeExtensionFilters sf) { - return new FileTypesNode(sf.getSleuthkitCase(), null); + return new FileTypesByExtNode(sf.getSleuthkitCase(), null); } @Override @@ -191,7 +192,7 @@ abstract class AbstractContentChildren extends Keys { @Override public AbstractNode visit(FileTypes ft) { - return new FileTypesNew(ft.getSleuthkitCase()); + return new FileTypesNode(ft.getSleuthkitCase()); } @Override @@ -210,5 +211,10 @@ abstract class AbstractContentChildren extends Keys { NbBundle.getMessage(this.getClass(), "AbstractContentChildren.createAutopsyNodeVisitor.exception.noNodeMsg")); } + + @Override + public AbstractNode visit(FileTypesByMimeType ftByMimeTypeItem) { + return ftByMimeTypeItem.new FileTypesByMimeTypeNode(ftByMimeTypeItem.getSleuthkitCase()); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java index e06e7c9d08..f0d2bcc253 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java @@ -71,7 +71,10 @@ public interface AutopsyItemVisitor { T visit(Accounts accountsItem); - T visit(FileTypes aThis); + T visit(FileTypes fileTypesItem); + + T visit(FileTypesByMimeType aThis); + static abstract public class Default implements AutopsyItemVisitor { @@ -101,7 +104,12 @@ public interface AutopsyItemVisitor { public T visit(FileTypeExtensionFilters.ExecutableFilter ef) { return defaultVisit(ef); } - + + @Override + public T visit(FileTypesByMimeType ftByMimeType) { + return defaultVisit(ftByMimeType); + } + @Override public T visit(DeletedContent dc) { return defaultVisit(dc); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties index 3c24e02283..590f0fa993 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties @@ -124,7 +124,7 @@ FileTypeNode.createSheet.filterType.desc=no description FileTypeNode.createSheet.fileExt.name=File Extensions FileTypeNode.createSheet.fileExt.displayName=File Extensions FileTypeNode.createSheet.fileExt.desc=no description -FileTypesNode.fname.text=File Types +FileTypesNode.fname.text=By Extension FileTypesNode.createSheet.name.name=Name FileTypesNode.createSheet.name.displayName=Name FileTypesNode.createSheet.name.desc=no description diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index 3af8d3c0f8..51b6b5ce11 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -22,6 +22,7 @@ import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.De import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode; +import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode; import org.sleuthkit.autopsy.datamodel.accounts.Accounts; /** @@ -54,7 +55,7 @@ public interface DisplayableItemNodeVisitor { */ T visit(ViewsNode vn); - T visit(FileTypeNode fsfn); + T visit(FileTypeByExtNode fsfn); T visit(DeletedContentNode dcn); @@ -64,7 +65,7 @@ public interface DisplayableItemNodeVisitor { T visit(FileSizeNode fsn); - T visit(FileTypesNode sfn); + T visit(FileTypesByExtNode sfn); T visit(RecentFilesNode rfn); @@ -140,7 +141,14 @@ public interface DisplayableItemNodeVisitor { T visit(Accounts.DefaultAccountTypeNode node); - T visit(FileTypesNew fileTypes); + T visit(FileTypes.FileTypesNode fileTypes); + + T visit(FileTypesByMimeType.FileTypesByMimeTypeNode aThis); + + T visit(FileTypesByMimeType.MediaTypeNode aThis); + + T visit(FileTypesByMimeType.MediaSubTypeNode aThis); + /** * Visitor with an implementable default behavior for all types. Override @@ -195,10 +203,21 @@ public interface DisplayableItemNodeVisitor { } @Override - public T visit(FileTypeNode fsfn) { + public T visit(FileTypeByExtNode fsfn) { return defaultVisit(fsfn); } - + @Override + public T visit(FileTypesByMimeType.FileTypesByMimeTypeNode ftByMimeTypeNode) { + return defaultVisit(ftByMimeTypeNode); + } + @Override + public T visit(FileTypesByMimeType.MediaTypeNode ftByMimeTypeMediaTypeNode) { + return defaultVisit(ftByMimeTypeMediaTypeNode); + } + @Override + public T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaTypeNode) { + return defaultVisit(ftByMimeTypeMediaTypeNode); + } @Override public T visit(DeletedContentNode dcn) { return defaultVisit(dcn); @@ -220,7 +239,7 @@ public interface DisplayableItemNodeVisitor { } @Override - public T visit(FileTypesNode sfn) { + public T visit(FileTypesByExtNode sfn) { return defaultVisit(sfn); } @@ -260,7 +279,7 @@ public interface DisplayableItemNodeVisitor { } @Override - public T visit(FileTypesNew ft) { + public T visit(FileTypesNode ft) { return defaultVisit(ft); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/datamodel/FileTypeNode.java rename to Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java index ce65c82194..9561c3f2ef 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java @@ -48,14 +48,14 @@ import org.sleuthkit.datamodel.TskData; * Node for a specific file type / extension. Children of it will be the files * of that type. */ -public class FileTypeNode extends DisplayableItemNode { +public class FileTypeByExtNode extends DisplayableItemNode { FileTypeExtensionFilters.SearchFilterInterface filter; SleuthkitCase skCase; // deprecated in favor of the version that takes an observable to provide refresh updates @Deprecated - FileTypeNode(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase) { + FileTypeByExtNode(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase) { super(Children.create(new FileTypeChildFactory(filter, skCase), true), Lookups.singleton(filter.getDisplayName())); this.filter = filter; this.skCase = skCase; @@ -69,7 +69,7 @@ public class FileTypeNode extends DisplayableItemNode { * @param o Observable that sends updates when the child factories * should refresh */ - FileTypeNode(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) { + FileTypeByExtNode(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) { super(Children.create(new FileTypeChildFactory(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName())); this.filter = filter; this.skCase = skCase; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java index f977a1e797..44b357f12f 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,11 @@ */ package org.sleuthkit.autopsy.datamodel; +import java.util.Arrays; +import org.openide.nodes.Sheet; +import org.openide.util.NbBundle; +import org.openide.util.lookup.Lookups; +import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters; import org.sleuthkit.datamodel.SleuthkitCase; /** @@ -27,7 +32,7 @@ public class FileTypes implements AutopsyVisitableItem { private SleuthkitCase skCase; - public FileTypes(SleuthkitCase skCase) { + FileTypes(SleuthkitCase skCase) { this.skCase = skCase; } @@ -36,7 +41,64 @@ public class FileTypes implements AutopsyVisitableItem { return v.visit(this); } - public SleuthkitCase getSleuthkitCase() { + SleuthkitCase getSleuthkitCase() { return skCase; } + + /** + * + * @author wschaefer + */ + public static class FileTypesNode extends DisplayableItemNode { + + @NbBundle.Messages("FileTypesNew.name.text=File Types") + private static final String NAME = Bundle.FileTypesNew_name_text(); + + public FileTypesNode(SleuthkitCase sleuthkitCase) { + super(new RootContentChildren(Arrays.asList( + new FileTypeExtensionFilters(sleuthkitCase), + new FileTypesByMimeType(sleuthkitCase) + )), Lookups.singleton(NAME)); + setName(NAME); + setDisplayName(NAME); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); + } + + @Override + public boolean isLeafTypeNode() { + return false; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + @NbBundle.Messages({ + "FileTypesNew.createSheet.name.name=Name", + "FileTypesNew.createSheet.name.displayName=Name", + "FileTypesNew.createSheet.name.desc=no description"}) + protected Sheet createSheet() { + Sheet s = super.createSheet(); + Sheet.Set ss = s.get(Sheet.PROPERTIES); + if (ss == null) { + ss = Sheet.createPropertiesSet(); + s.put(ss); + } + + ss.put(new NodeProperty<>(Bundle.FileTypesNew_createSheet_name_name(), + Bundle.FileTypesNew_createSheet_name_displayName(), + Bundle.FileTypesNew_createSheet_name_desc(), + NAME + )); + return s; + } + + @Override + public String getItemType() { + return getClass().getName(); + } + + } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java similarity index 93% rename from Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java rename to Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java index daf1a31780..d9ce314ae7 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java @@ -37,9 +37,9 @@ import org.sleuthkit.datamodel.SleuthkitCase; /** * Node for root of file types view. Children are nodes for specific types. */ -public class FileTypesNode extends DisplayableItemNode { +public class FileTypesByExtNode extends DisplayableItemNode { - private static final String FNAME = NbBundle.getMessage(FileTypesNode.class, "FileTypesNode.fname.text"); + private static final String FNAME = NbBundle.getMessage(FileTypesByExtNode.class, "FileTypesNode.fname.text"); private final FileTypeExtensionFilters.RootFilter filter; /** * @@ -47,7 +47,7 @@ public class FileTypesNode extends DisplayableItemNode { * @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) { + FileTypesByExtNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter) { super(Children.create(new FileTypesChildren(skCase, filter, null), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); this.filter = filter; init(); @@ -60,7 +60,7 @@ public class FileTypesNode extends DisplayableItemNode { * @param o Observable that was created by a higher-level node that * provides updates on events */ - private FileTypesNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter, Observable o) { + private FileTypesByExtNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter, Observable o) { super(Children.create(new FileTypesChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); this.filter = filter; init(); @@ -220,11 +220,11 @@ public class FileTypesNode extends DisplayableItemNode { 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, notifier); + return new FileTypesByExtNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_DOCUMENT_FILTER, notifier); } else if (key.getName().equals(FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER.getName())) { - return new FileTypesNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER, notifier); + return new FileTypesByExtNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER, notifier); } else { - return new FileTypeNode(key, skCase, notifier); + return new FileTypeByExtNode(key, skCase, notifier); } } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java new file mode 100644 index 0000000000..59711cf1a0 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -0,0 +1,407 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2016 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.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Observable; +import java.util.Observer; +import java.util.logging.Level; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.ChildFactory; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.ContentVisitor; +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.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; + +/** + * Node for Root of the 'By Mime Type' view located in the File Types view, + * shows all files with a mime type. Will intially be empty until file type + * identification has been performed. + */ +class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { + + static SleuthkitCase skCase; + static final String EMPTY_MIME_TREE_STRING = "Data not available. Run file type identification module."; + /** + * The nodes of this tree will be determined dynamically by the mimetypes + * which exist in the database. This hashmap will store them with the media + * type as the key and a list of media subtypes as the value. + */ + private final HashMap> existingMimeTypes = new HashMap<>(); + private static final Logger LOGGER = Logger.getLogger(FileTypesByMimeType.class.getName()); + + /* + * The pcl is in the class because it has the easiest mechanisms to add + * and remove itself during its life cycles. + */ + private final PropertyChangeListener pcl = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + String eventType = evt.getPropertyName(); + if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) + // || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString()) + || eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { + /** + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked out. + * Currently, remote events may be received for a case that is + * already closed. + */ + try { + Case.getCurrentCase(); + populateHashMap(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } + } + }; + + private List getMediaTypeList() { + synchronized (existingMimeTypes) { + List mediaTypes = new ArrayList<>(existingMimeTypes.keySet()); + Collections.sort(mediaTypes); + return mediaTypes; + } + } + + private void populateHashMap() { + StringBuilder allDistinctMimeTypesQuery = new StringBuilder(); + allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type NOT null"); + allDistinctMimeTypesQuery.append(" AND dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(";"); //NON-NLS + synchronized (existingMimeTypes) { + existingMimeTypes.clear(); + } + + if (skCase == null) { + + return; + } + try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(allDistinctMimeTypesQuery.toString())) { + ResultSet resultSet = dbQuery.getResultSet(); + synchronized (existingMimeTypes) { + while (resultSet.next()) { + final String mime_type = resultSet.getString("mime_type"); //NON-NLS + if (!mime_type.isEmpty()) { + String mimeType[] = mime_type.split("/"); + if (!mimeType[0].isEmpty() && !mimeType[1].isEmpty()) { + if (!existingMimeTypes.containsKey(mimeType[0])) { + existingMimeTypes.put(mimeType[0], new ArrayList<>()); + } + existingMimeTypes.get(mimeType[0]).add(mimeType[1]); + } + } + } + } + } catch (TskCoreException | SQLException ex) { + LOGGER.log(Level.WARNING, "Unable to populate File Types by MIME Type tree view from DB: ", ex); //NON-NLS + } + setChanged(); + notifyObservers(); + } + + FileTypesByMimeType(SleuthkitCase skCase) { + IngestManager.getInstance().addIngestJobEventListener(pcl); + IngestManager.getInstance().addIngestModuleEventListener(pcl); +// Case.addPropertyChangeListener(pcl); + + FileTypesByMimeType.skCase = skCase; + } + + SleuthkitCase getSleuthkitCase() { + return skCase; + } + + @Override + public T accept(AutopsyItemVisitor v) { + return v.visit(this); + } + + class FileTypesByMimeTypeNode extends DisplayableItemNode { + + @NbBundle.Messages("FileTypesByMimeType.name.text=By MIME Type") + final String NAME = Bundle.FileTypesByMimeType_name_text(); + + FileTypesByMimeTypeNode(SleuthkitCase sleuthkitCase) { + super(Children.create(new FileTypesByMimeTypeNodeChildren(skCase), true)); + setName(NAME); + setDisplayName(NAME); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); + } + + @Override + public boolean isLeafTypeNode() { +// if (!existingMimeTypes.isEmpty()) { + return false; +// } +// else { +// return true; +// } + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + public String getItemType() { + return getClass().getName(); + } + + } + + class FileTypesByMimeTypeNodeChildren extends ChildFactory implements Observer { + + private SleuthkitCase skCase; + + /** + * + * @param skCase (or null if one needs to be created) + */ + public FileTypesByMimeTypeNodeChildren(SleuthkitCase skCase) { + super(); + addObserver(this); + this.skCase = skCase; + } + + @Override + protected boolean createKeys(List mediaTypeNodes) { +// if (!existingMimeTypes.isEmpty()) { + mediaTypeNodes.addAll(getMediaTypeList()); +// } else { +// mediaTypeNodes.add(EMPTY_MIME_TREE_STRING); +// } + return true; + } + + @Override + protected Node createNodeForKey(String key) { + return new MediaTypeNode(key); + + } + + @Override + public void update(Observable o, Object arg) { + refresh(true); + } + + } + + class MediaTypeNode extends DisplayableItemNode { + + String mediaType; + + MediaTypeNode(String name) { + super(Children.create(new MediaTypeChildren(name), true)); + setName(name); + setDisplayName(name); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); + } + + @Override + public boolean isLeafTypeNode() { + return false; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + public String getItemType() { + return getClass().getName(); + } + + } + + class MediaTypeChildren extends ChildFactory implements Observer { + + String mediaType; + + MediaTypeChildren(String name) { + addObserver(this); + this.mediaType = name; + } + + @Override + protected boolean createKeys(List mediaTypeNodes) { +// if (!existingMimeTypes.isEmpty() && !mediaType.equals(EMPTY_MIME_TREE_STRING)) { +// System.out.println(mediaType); +// System.out.println(existingMimeTypes.size()); + mediaTypeNodes.addAll(existingMimeTypes.get(mediaType)); + return true; +// } else { +// return false; +// } + } + + @Override + protected Node createNodeForKey(String subtype) { + String mimeType = mediaType + "/" + subtype; + return new MediaSubTypeNode(mimeType); + } + + @Override + public void update(Observable o, Object arg) { + refresh(true); + } + + } + + class MediaSubTypeNode extends DisplayableItemNode { + + private MediaSubTypeNode(String mimeType) { + super(Children.create(new MediaSubTypeNodeChildren(mimeType), true)); + init(mimeType); + } + + private void init(String mimeType) { + super.setName(mimeType); + updateDisplayName(mimeType); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS + } + + private void updateDisplayName(String mimeType) { + final long count = MediaSubTypeNodeChildren.calculateItems(skCase, mimeType); + super.setDisplayName(mimeType.split("/")[1] + " (" + count + ")"); + } + + @Override + public boolean isLeafTypeNode() { + return true; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + public String getItemType() { + return getClass().getName(); + } + + } + + private static class MediaSubTypeNodeChildren extends ChildFactory.Detachable { + + private final String mimeType; + + MediaSubTypeNodeChildren(String mimeType) { + super(); + this.mimeType = mimeType; + } + + /** + * Get children count without actually loading all nodes + * + * @return + */ + private static long calculateItems(SleuthkitCase sleuthkitCase, String mimeType) { + try { + return sleuthkitCase.countFilesWhere(createQuery(mimeType)); + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Error getting file search view count", ex); //NON-NLS + return 0; + } + } + + @Override + protected boolean createKeys(List list) { + try { + List files = skCase.findAllFilesWhere(createQuery(mimeType)); + list.addAll(files); + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Couldn't get search results", ex); //NON-NLS + } + return true; + } + + private static String createQuery(String mimeType) { + StringBuilder query = new StringBuilder(); + query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS + if (UserPreferences.hideKnownFilesInViewsTree()) { + query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS + } + query.append(" AND mime_type = '").append(mimeType).append("'"); + return query.toString(); + } + + @Override + protected Node createNodeForKey(Content key) { + return key.accept(new ContentVisitor.Default() { + @Override + public FileNode visit(File f) { + return new FileNode(f, false); + } + + @Override + public DirectoryNode visit(Directory d) { + return new DirectoryNode(d); + } + + @Override + public LayoutFileNode visit(LayoutFile lf) { + return new LayoutFileNode(lf); + } + + @Override + public LocalFileNode visit(DerivedFile df) { + return new LocalFileNode(df); + } + + @Override + public LocalFileNode visit(LocalFile lf) { + return new LocalFileNode(lf); + } + + @Override + protected AbstractNode defaultVisit(Content di) { + throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(), "FileTypeChildren.exception.notSupported.msg", di.toString())); + } + }); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java deleted file mode 100644 index b0273b4ae4..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.sleuthkit.autopsy.datamodel; - -import java.util.Arrays; -import org.openide.nodes.Sheet; -import org.openide.util.NbBundle; -import org.openide.util.lookup.Lookups; -import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters; -import org.sleuthkit.datamodel.SleuthkitCase; - -/** - * - * @author wschaefer - */ -public class FileTypesNew extends DisplayableItemNode { - - @NbBundle.Messages("FileTypesNew.name.text=File Types_New") - public static final String NAME = Bundle.FileTypesNew_name_text(); - - public FileTypesNew(SleuthkitCase sleuthkitCase) { - super(new RootContentChildren(Arrays.asList( - - new FileTypeExtensionFilters(sleuthkitCase) - )), Lookups.singleton(NAME)); - setName(NAME); - setDisplayName(NAME); - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); - } - - - @Override - public boolean isLeafTypeNode() { - return false; - } - - @Override - public T accept(DisplayableItemNodeVisitor v) { - return v.visit(this); - } - - @Override - @NbBundle.Messages({ - "FileTypesNew.createSheet.name.name=Name", - "FileTypesNew.createSheet.name.displayName=Name", - "FileTypesNew.createSheet.name.desc=no description"}) - protected Sheet createSheet() { - Sheet s = super.createSheet(); - Sheet.Set ss = s.get(Sheet.PROPERTIES); - if (ss == null) { - ss = Sheet.createPropertiesSet(); - s.put(ss); - } - - ss.put(new NodeProperty<>(Bundle.FileTypesNew_createSheet_name_name(), - Bundle.FileTypesNew_createSheet_name_displayName(), - Bundle.FileTypesNew_createSheet_name_desc(), - NAME - )); - return s; - } - -} diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index 26a14f34d3..2d3d26d5b3 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -42,7 +42,7 @@ import org.sleuthkit.autopsy.datamodel.DirectoryNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.FileNode; -import org.sleuthkit.autopsy.datamodel.FileTypesNew; +import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.Reports; @@ -234,10 +234,11 @@ public class DataResultFilterNode extends FilterNode { } @Override - public List visit(FileTypesNew fileTypes) { + public List visit(FileTypesNode fileTypes) { return defaultVisit(fileTypes); } + @Override protected List defaultVisit(DisplayableItemNode ditem) { //preserve the default node's actions @@ -331,9 +332,12 @@ public class DataResultFilterNode extends FilterNode { } @Override - public AbstractAction visit(FileTypesNew fileTypes) { + public AbstractAction visit(FileTypesNode fileTypes) { return openChild(fileTypes); } + + + /** * Tell the originating ExplorerManager to display the given * dataModelNode. diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java index 728e42c426..09759c79a8 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java @@ -29,7 +29,7 @@ import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.FileNode; -import org.sleuthkit.autopsy.datamodel.FileTypesNew; +import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; @@ -239,9 +239,10 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { } @Override - public Boolean visit(FileTypesNew ft) { + public Boolean visit(FileTypesNode ft) { return defaultVisit(ft); } + } private static class ShowItemVisitor extends DisplayableItemNodeVisitor.Default { @@ -281,8 +282,9 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { } @Override - public Boolean visit(FileTypesNew fileTypes) { + public Boolean visit(FileTypesNode fileTypes) { return defaultVisit(fileTypes); } + } } From f3f800e13864acf78284eabaea635d3231afd806 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Fri, 11 Nov 2016 14:51:21 -0500 Subject: [PATCH 11/27] 2050: KeyworkSearchException is handled at the caller level of performQuery --- .../keywordsearch/HighlightedText.java | 6 +++-- .../keywordsearch/KeywordSearchQuery.java | 3 ++- .../KeywordSearchResultFactory.java | 6 +++-- .../autopsy/keywordsearch/LuceneQuery.java | 24 +++++++------------ .../autopsy/keywordsearch/SearchRunner.java | 9 ++++--- .../keywordsearch/TermsComponentQuery.java | 13 +++------- 6 files changed, 25 insertions(+), 36 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java index 4e4b55d5f7..48c4997b37 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java @@ -31,6 +31,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrRequest.METHOD; import org.apache.solr.client.solrj.response.QueryResponse; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.autopsy.datamodel.TextMarkupLookup; import org.sleuthkit.autopsy.keywordsearch.KeywordQueryFilter.FilterType; @@ -143,8 +144,9 @@ class HighlightedText implements IndexedText, TextMarkupLookup { chunksQuery.addFilter(new KeywordQueryFilter(FilterType.CHUNK, this.objectId)); try { hits = chunksQuery.performQuery(); - } catch (NoOpenCoreException ex) { - logger.log(Level.INFO, "Could not get chunk info and get highlights", ex); //NON-NLS + } catch (KeywordSearchModuleException | NoOpenCoreException ex) { + logger.log(Level.SEVERE, "Could not perform the query to get chunk info and get highlights" + keywordQuery.getSearchTerm(), ex); //NON-NLS + MessageNotifyUtil.Notify.error(NbBundle.getMessage(HighlightedText.class, "Server.query.exception.msg", queryStr), ex.getCause().getMessage()); return; } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQuery.java index f373c2d162..34e530956a 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQuery.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQuery.java @@ -36,11 +36,12 @@ interface KeywordSearchQuery { * execute query and return results without publishing them return results * for all matching terms * + * @throws KeywordSearchModuleException error while executing Solr term query * @throws NoOpenCoreException if query failed due to server error, this * could be a notification to stop processing * @return */ - QueryResults performQuery() throws NoOpenCoreException; + QueryResults performQuery() throws KeywordSearchModuleException, NoOpenCoreException; /** * Set an optional filter to narrow down the search Adding multiple filters diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java index 97beb9e9c6..4217942415 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java @@ -38,6 +38,7 @@ import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode; import org.sleuthkit.autopsy.datamodel.KeyValue; @@ -158,10 +159,11 @@ class KeywordSearchResultFactory extends ChildFactory { QueryResults queryResults; try { queryResults = keywordSearchQuery.performQuery(); - } catch (NoOpenCoreException ex) { + } catch (KeywordSearchModuleException | NoOpenCoreException ex) { logger.log(Level.SEVERE, "Could not perform the query " + keywordSearchQuery.getQueryString(), ex); //NON-NLS + MessageNotifyUtil.Notify.error(NbBundle.getMessage(KeywordSearchResultFactory.class, "Server.query.exception.msg"), ex.getCause().getMessage()); return false; - } + } int id = 0; List tempList = new ArrayList<>(); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java index 5702a952f4..0b7941747e 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java @@ -32,11 +32,9 @@ import org.apache.solr.client.solrj.SolrRequest.METHOD; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; -import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; @@ -128,7 +126,7 @@ class LuceneQuery implements KeywordSearchQuery { } @Override - public QueryResults performQuery() throws NoOpenCoreException { + public QueryResults performQuery() throws KeywordSearchModuleException, NoOpenCoreException { QueryResults results = new QueryResults(this, keywordList); //in case of single term literal query there is only 1 term boolean showSnippets = KeywordSearchSettings.getShowSnippets(); @@ -199,7 +197,7 @@ class LuceneQuery implements KeywordSearchQuery { * * @throws NoOpenCoreException */ - private List performLuceneQuery(boolean snippets) throws NoOpenCoreException { + private List performLuceneQuery(boolean snippets) throws KeywordSearchModuleException, NoOpenCoreException { List matches = new ArrayList<>(); boolean allMatchesFetched = false; final Server solrServer = KeywordSearch.getServer(); @@ -210,21 +208,15 @@ class LuceneQuery implements KeywordSearchQuery { Map>> highlightResponse; Set uniqueSolrDocumentsWithHits; - try { - response = solrServer.query(q, METHOD.POST); + response = solrServer.query(q, METHOD.POST); - resultList = response.getResults(); + resultList = response.getResults(); - // objectId_chunk -> "text" -> List of previews - highlightResponse = response.getHighlighting(); + // objectId_chunk -> "text" -> List of previews + highlightResponse = response.getHighlighting(); - // get the unique set of files with hits - uniqueSolrDocumentsWithHits = filterOneHitPerDocument(resultList); - } catch (KeywordSearchModuleException ex) { - logger.log(Level.SEVERE, "Error executing Lucene Solr Query: " + keywordString, ex); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(Server.class, "Server.query.exception.msg", keywordString), ex.getCause().getMessage()); - return matches; - } + // get the unique set of files with hits + uniqueSolrDocumentsWithHits = filterOneHitPerDocument(resultList); // cycle through results in sets of MAX_RESULTS for (int start = 0; !allMatchesFetched; start = start + MAX_RESULTS) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java index 00fd1db2a7..894b1e32b0 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java @@ -38,6 +38,7 @@ import org.netbeans.api.progress.aggregate.ProgressContributor; import org.openide.util.Cancellable; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.StopWatch; import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestServices; @@ -453,8 +454,9 @@ public final class SearchRunner { // Do the actual search try { queryResults = keywordSearchQuery.performQuery(); - } catch (NoOpenCoreException ex) { - logger.log(Level.WARNING, "Error performing query: " + keywordQuery.getSearchTerm(), ex); //NON-NLS + } catch (KeywordSearchModuleException | NoOpenCoreException ex) { + logger.log(Level.SEVERE, "Error performing query: " + keywordQuery.getSearchTerm(), ex); //NON-NLS + MessageNotifyUtil.Notify.error(NbBundle.getMessage(SearchRunner.class, "Server.query.exception.msg", queryStr), ex.getCause().getMessage()); //no reason to continue with next query if recovery failed //or wait for recovery to kick in and run again later //likely case has closed and threads are being interrupted @@ -462,9 +464,6 @@ public final class SearchRunner { } catch (CancellationException e) { logger.log(Level.INFO, "Cancel detected, bailing during keyword query: {0}", keywordQuery.getSearchTerm()); //NON-NLS return null; - } catch (Exception e) { - logger.log(Level.WARNING, "Error performing query: " + keywordQuery.getSearchTerm(), e); //NON-NLS - continue; } // calculate new results by substracting results already obtained in this ingest diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java index 49343798b7..70fb9486f4 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java @@ -261,10 +261,8 @@ final class TermsComponentQuery implements KeywordSearchQuery { * * @throws NoOpenCoreException */ - // TODO: Make it so this cannot cause NPEs; this method should throw - // exceptions instead of logging them and returning null. @Override - public QueryResults performQuery() throws NoOpenCoreException { + public QueryResults performQuery() throws KeywordSearchModuleException, NoOpenCoreException { /* * Do a query using the Solr terms component to find any terms in the * index that match the regex. @@ -278,14 +276,9 @@ final class TermsComponentQuery implements KeywordSearchQuery { termsQuery.setTimeAllowed(TERMS_SEARCH_TIMEOUT); termsQuery.setShowDebugInfo(DEBUG_FLAG); termsQuery.setTermsLimit(MAX_TERMS_QUERY_RESULTS); - List terms = null; - try { - terms = KeywordSearch.getServer().queryTerms(termsQuery).getTerms(SEARCH_FIELD); - } catch (KeywordSearchModuleException ex) { - LOGGER.log(Level.SEVERE, "Error executing the regex terms query: " + keyword.getSearchTerm(), ex); //NON-NLS + List terms = KeywordSearch.getServer().queryTerms(termsQuery).getTerms(SEARCH_FIELD); + //LOGGER.log(Level.SEVERE, "Error executing the regex terms query: " + keyword.getSearchTerm(), ex); //NON-NLS //TODO: this is almost certainly wrong and guaranteed to throw a NPE at some point!!!! - } - /* * Do a term query for each term that matched the regex. */ From e0473bce63c0fdaecb1ff62835af2abf53a84559 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Fri, 11 Nov 2016 15:08:39 -0500 Subject: [PATCH 12/27] 2050: add more info for the error msg --- .../sleuthkit/autopsy/keywordsearch/HighlightedText.java | 6 ++++-- .../org/sleuthkit/autopsy/keywordsearch/SearchRunner.java | 4 +++- .../autopsy/keywordsearch/TermsComponentQuery.java | 2 -- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java index 48c4997b37..fe87ac26cc 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java @@ -31,6 +31,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrRequest.METHOD; import org.apache.solr.client.solrj.response.QueryResponse; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.autopsy.datamodel.TextMarkupLookup; @@ -101,6 +102,7 @@ class HighlightedText implements IndexedText, TextMarkupLookup { * The main goal of this method is to figure out which pages / chunks have * hits. */ + @Messages({"HighlightedText.query.exception.msg=Could not perform the query to get chunk info and get highlights:"}) private void loadPageInfo() { if (isPageInfoLoaded) { return; @@ -145,8 +147,8 @@ class HighlightedText implements IndexedText, TextMarkupLookup { try { hits = chunksQuery.performQuery(); } catch (KeywordSearchModuleException | NoOpenCoreException ex) { - logger.log(Level.SEVERE, "Could not perform the query to get chunk info and get highlights" + keywordQuery.getSearchTerm(), ex); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(HighlightedText.class, "Server.query.exception.msg", queryStr), ex.getCause().getMessage()); + logger.log(Level.SEVERE, "Could not perform the query to get chunk info and get highlights:" + keywordQuery.getSearchTerm(), ex); //NON-NLS + MessageNotifyUtil.Notify.error(Bundle.HighlightedText_query_exception_msg() + keywordQuery.getSearchTerm(), ex.getCause().getMessage()); return; } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java index 894b1e32b0..e41a03554a 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java @@ -37,6 +37,7 @@ import org.netbeans.api.progress.aggregate.AggregateProgressHandle; import org.netbeans.api.progress.aggregate.ProgressContributor; import org.openide.util.Cancellable; import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.StopWatch; @@ -384,6 +385,7 @@ public final class SearchRunner { } @Override + @Messages("SearchRunner.query.exception.msg=Error performing query:") protected Object doInBackground() throws Exception { final String displayName = NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.displayName") + (finalRun ? (" - " + NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.finalizeMsg")) : ""); @@ -456,7 +458,7 @@ public final class SearchRunner { queryResults = keywordSearchQuery.performQuery(); } catch (KeywordSearchModuleException | NoOpenCoreException ex) { logger.log(Level.SEVERE, "Error performing query: " + keywordQuery.getSearchTerm(), ex); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(SearchRunner.class, "Server.query.exception.msg", queryStr), ex.getCause().getMessage()); + MessageNotifyUtil.Notify.error(Bundle.SearchRunner_query_exception_msg() + keywordQuery.getSearchTerm(), ex.getCause().getMessage()); //no reason to continue with next query if recovery failed //or wait for recovery to kick in and run again later //likely case has closed and threads are being interrupted diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java index 70fb9486f4..e356c0b8c6 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermsComponentQuery.java @@ -277,8 +277,6 @@ final class TermsComponentQuery implements KeywordSearchQuery { termsQuery.setShowDebugInfo(DEBUG_FLAG); termsQuery.setTermsLimit(MAX_TERMS_QUERY_RESULTS); List terms = KeywordSearch.getServer().queryTerms(termsQuery).getTerms(SEARCH_FIELD); - //LOGGER.log(Level.SEVERE, "Error executing the regex terms query: " + keyword.getSearchTerm(), ex); //NON-NLS - //TODO: this is almost certainly wrong and guaranteed to throw a NPE at some point!!!! /* * Do a term query for each term that matched the regex. */ From 0e123d55ef934c901622c6b746fa770bf3967965 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Fri, 11 Nov 2016 15:12:12 -0500 Subject: [PATCH 13/27] 2050: add more info for the error msg for KeywordSearchResultFactory --- .../autopsy/keywordsearch/KeywordSearchResultFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java index 4217942415..8d940468ae 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java @@ -143,6 +143,7 @@ class KeywordSearchResultFactory extends ChildFactory { * * @return */ + @NbBundle.Messages({"KeywordSearchResultFactory.query.exception.msg=Could not perform the query "}) private boolean createFlatKeys(QueryRequest queryRequest, List toPopulate) { /** * Check the validity of the requested query. @@ -161,7 +162,7 @@ class KeywordSearchResultFactory extends ChildFactory { queryResults = keywordSearchQuery.performQuery(); } catch (KeywordSearchModuleException | NoOpenCoreException ex) { logger.log(Level.SEVERE, "Could not perform the query " + keywordSearchQuery.getQueryString(), ex); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(KeywordSearchResultFactory.class, "Server.query.exception.msg"), ex.getCause().getMessage()); + MessageNotifyUtil.Notify.error(Bundle.KeywordSearchResultFactory_query_exception_msg() + keywordSearchQuery.getQueryString(), ex.getCause().getMessage()); return false; } From f45b0b642b6d1b37a38e591f3a3f9e3cc207b6d1 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 11 Nov 2016 16:13:46 -0500 Subject: [PATCH 14/27] 1917 Mime Tree fixed when updating from empty to contents --- .../datamodel/DisplayableItemNodeVisitor.java | 7 +++ .../datamodel/FileTypesByMimeType.java | 61 +++++++++++++------ 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index 51b6b5ce11..457d4a8353 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -149,6 +149,8 @@ public interface DisplayableItemNodeVisitor { T visit(FileTypesByMimeType.MediaSubTypeNode aThis); + T visit(FileTypesByMimeType.EmptyNode aThis); + /** * Visitor with an implementable default behavior for all types. Override @@ -218,6 +220,11 @@ public interface DisplayableItemNodeVisitor { public T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaTypeNode) { return defaultVisit(ftByMimeTypeMediaTypeNode); } + @Override + public T visit(FileTypesByMimeType.EmptyNode ftByMimeTypeEmptyNode) { + return defaultVisit(ftByMimeTypeEmptyNode); + } + @Override public T visit(DeletedContentNode dcn) { return defaultVisit(dcn); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 59711cf1a0..24974d2df7 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -58,7 +58,6 @@ import org.sleuthkit.datamodel.TskData; class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { static SleuthkitCase skCase; - static final String EMPTY_MIME_TREE_STRING = "Data not available. Run file type identification module."; /** * The nodes of this tree will be determined dynamically by the mimetypes * which exist in the database. This hashmap will store them with the media @@ -77,7 +76,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) - // || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString()) + // || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString()) || eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { /** * Checking for a current case is a stop gap measure until a @@ -144,7 +143,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { IngestManager.getInstance().addIngestJobEventListener(pcl); IngestManager.getInstance().addIngestModuleEventListener(pcl); // Case.addPropertyChangeListener(pcl); - + // populateHashMap(); FileTypesByMimeType.skCase = skCase; } @@ -172,7 +171,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { @Override public boolean isLeafTypeNode() { // if (!existingMimeTypes.isEmpty()) { - return false; + return false; // } // else { // return true; @@ -194,6 +193,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { class FileTypesByMimeTypeNodeChildren extends ChildFactory implements Observer { private SleuthkitCase skCase; + static final String EMPTY_MIME_TREE_STRING = "Data not available. Run file type identification module."; /** * @@ -207,17 +207,21 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { @Override protected boolean createKeys(List mediaTypeNodes) { -// if (!existingMimeTypes.isEmpty()) { - mediaTypeNodes.addAll(getMediaTypeList()); -// } else { -// mediaTypeNodes.add(EMPTY_MIME_TREE_STRING); -// } + if (!existingMimeTypes.isEmpty()) { + mediaTypeNodes.addAll(getMediaTypeList()); + } else { + mediaTypeNodes.add(EMPTY_MIME_TREE_STRING); + } return true; } @Override protected Node createNodeForKey(String key) { + if (!existingMimeTypes.isEmpty()) { return new MediaTypeNode(key); + } else { + return new EmptyNode(EMPTY_MIME_TREE_STRING); + } } @@ -228,6 +232,31 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } + class EmptyNode extends DisplayableItemNode { + + EmptyNode(String name) { + super(Children.LEAF); + super.setName(name); + setName(name); + setDisplayName(name); + } + + @Override + public boolean isLeafTypeNode() { + return true; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + public String getItemType() { + return getClass().getName(); + } + } + class MediaTypeNode extends DisplayableItemNode { String mediaType; @@ -267,20 +296,14 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { @Override protected boolean createKeys(List mediaTypeNodes) { -// if (!existingMimeTypes.isEmpty() && !mediaType.equals(EMPTY_MIME_TREE_STRING)) { -// System.out.println(mediaType); -// System.out.println(existingMimeTypes.size()); - mediaTypeNodes.addAll(existingMimeTypes.get(mediaType)); - return true; -// } else { -// return false; -// } + mediaTypeNodes.addAll(existingMimeTypes.get(mediaType)); + return true; } @Override protected Node createNodeForKey(String subtype) { - String mimeType = mediaType + "/" + subtype; - return new MediaSubTypeNode(mimeType); + String mimeType = mediaType + "/" + subtype; + return new MediaSubTypeNode(mimeType); } @Override From e8f7029a0f3c4bcd84d705f6cd88d6a4237142f7 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 14 Nov 2016 13:05:23 -0500 Subject: [PATCH 15/27] 1917-Comments added and other minor clean up, emptyNode removed --- .../datamodel/DisplayableItemNodeVisitor.java | 15 +- .../autopsy/datamodel/FileTypeByExtNode.java | 2 +- .../autopsy/datamodel/FileTypes.java | 5 +- .../datamodel/FileTypesByMimeType.java | 157 +++++++++++------- 4 files changed, 108 insertions(+), 71 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index 457d4a8353..a203b6054a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -143,13 +143,11 @@ public interface DisplayableItemNodeVisitor { T visit(FileTypes.FileTypesNode fileTypes); - T visit(FileTypesByMimeType.FileTypesByMimeTypeNode aThis); + T visit(FileTypesByMimeType.FileTypesByMimeTypeNode ftByMimeTypeNode); - T visit(FileTypesByMimeType.MediaTypeNode aThis); + T visit(FileTypesByMimeType.MediaTypeNode ftByMimeTypeMediaType); - T visit(FileTypesByMimeType.MediaSubTypeNode aThis); - - T visit(FileTypesByMimeType.EmptyNode aThis); + T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaSubType); /** @@ -208,22 +206,21 @@ public interface DisplayableItemNodeVisitor { public T visit(FileTypeByExtNode fsfn) { return defaultVisit(fsfn); } + @Override public T visit(FileTypesByMimeType.FileTypesByMimeTypeNode ftByMimeTypeNode) { return defaultVisit(ftByMimeTypeNode); } + @Override public T visit(FileTypesByMimeType.MediaTypeNode ftByMimeTypeMediaTypeNode) { return defaultVisit(ftByMimeTypeMediaTypeNode); } + @Override public T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaTypeNode) { return defaultVisit(ftByMimeTypeMediaTypeNode); } - @Override - public T visit(FileTypesByMimeType.EmptyNode ftByMimeTypeEmptyNode) { - return defaultVisit(ftByMimeTypeEmptyNode); - } @Override public T visit(DeletedContentNode dcn) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java index 9561c3f2ef..f708a8d056 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java index 44b357f12f..54a4c792c8 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java @@ -26,7 +26,7 @@ import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters; import org.sleuthkit.datamodel.SleuthkitCase; /** - * Results node support + * File Types node support */ public class FileTypes implements AutopsyVisitableItem { @@ -46,8 +46,7 @@ public class FileTypes implements AutopsyVisitableItem { } /** - * - * @author wschaefer + * Node which will contain By Mime Type and By Extension nodes. */ public static class FileTypesNode extends DisplayableItemNode { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 24974d2df7..3ec3a41054 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -51,9 +51,11 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; /** - * Node for Root of the 'By Mime Type' view located in the File Types view, - * shows all files with a mime type. Will intially be empty until file type - * identification has been performed. + * Class which contains the Nodes for the 'By Mime Type' view located in the + * File Types view, shows all files with a mime type. Will initially be empty + * until file type identification has been performed. Contains a Property Change + * Listener which is checking for changes in IngestJobEvent Completed or + * Cancelled and IngestModuleEvent Content Changed. */ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { @@ -96,6 +98,12 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } }; + /** + * Retrieve the media types by retrieving the keyset from the hashmap. + * + * @return mediaTypes - a list of strings representing all distinct media + * types of files for this case + */ private List getMediaTypeList() { synchronized (existingMimeTypes) { List mediaTypes = new ArrayList<>(existingMimeTypes.keySet()); @@ -104,6 +112,10 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } } + /** + * Performs the query on the database to get all distinct MIME types of + * files in it, and populate the hashmap with those results. + */ private void populateHashMap() { StringBuilder allDistinctMimeTypesQuery = new StringBuilder(); allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type NOT null"); @@ -112,11 +124,11 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { existingMimeTypes.clear(); } - if (skCase == null) { + if (getSleuthkitCase() == null) { return; } - try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(allDistinctMimeTypesQuery.toString())) { + try (SleuthkitCase.CaseDbQuery dbQuery = getSleuthkitCase().executeQuery(allDistinctMimeTypesQuery.toString())) { ResultSet resultSet = dbQuery.getResultSet(); synchronized (existingMimeTypes) { while (resultSet.next()) { @@ -142,11 +154,12 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { FileTypesByMimeType(SleuthkitCase skCase) { IngestManager.getInstance().addIngestJobEventListener(pcl); IngestManager.getInstance().addIngestModuleEventListener(pcl); -// Case.addPropertyChangeListener(pcl); - // populateHashMap(); FileTypesByMimeType.skCase = skCase; } + /** + * @return skCase - the sluethkit case + */ SleuthkitCase getSleuthkitCase() { return skCase; } @@ -156,13 +169,19 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { return v.visit(this); } + /** + * Class which represents the root node of the "By MIME Type" tree, will + * have children of each media type present in the database or no children + * when the file detection module has not been run and MIME type is + * currently unknown. + */ class FileTypesByMimeTypeNode extends DisplayableItemNode { @NbBundle.Messages("FileTypesByMimeType.name.text=By MIME Type") final String NAME = Bundle.FileTypesByMimeType_name_text(); FileTypesByMimeTypeNode(SleuthkitCase sleuthkitCase) { - super(Children.create(new FileTypesByMimeTypeNodeChildren(skCase), true)); + super(Children.create(new FileTypesByMimeTypeNodeChildren(), true)); setName(NAME); setDisplayName(NAME); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); @@ -170,12 +189,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { @Override public boolean isLeafTypeNode() { -// if (!existingMimeTypes.isEmpty()) { return false; -// } -// else { -// return true; -// } } @Override @@ -190,27 +204,21 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } + /** + * Creates the children for the "By MIME Type" node these children will each + * represent a distinct media type present in the DB + */ class FileTypesByMimeTypeNodeChildren extends ChildFactory implements Observer { - private SleuthkitCase skCase; - static final String EMPTY_MIME_TREE_STRING = "Data not available. Run file type identification module."; - - /** - * - * @param skCase (or null if one needs to be created) - */ - public FileTypesByMimeTypeNodeChildren(SleuthkitCase skCase) { + public FileTypesByMimeTypeNodeChildren() { super(); addObserver(this); - this.skCase = skCase; } @Override protected boolean createKeys(List mediaTypeNodes) { if (!existingMimeTypes.isEmpty()) { mediaTypeNodes.addAll(getMediaTypeList()); - } else { - mediaTypeNodes.add(EMPTY_MIME_TREE_STRING); } return true; } @@ -220,7 +228,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { if (!existingMimeTypes.isEmpty()) { return new MediaTypeNode(key); } else { - return new EmptyNode(EMPTY_MIME_TREE_STRING); + return null; } } @@ -232,35 +240,13 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } - class EmptyNode extends DisplayableItemNode { - - EmptyNode(String name) { - super(Children.LEAF); - super.setName(name); - setName(name); - setDisplayName(name); - } - - @Override - public boolean isLeafTypeNode() { - return true; - } - - @Override - public T accept(DisplayableItemNodeVisitor v) { - return v.visit(this); - } - - @Override - public String getItemType() { - return getClass().getName(); - } - } - + /** + * The Media type node created by the FileTypesByMimeTypeNodeChildren and + * contains one of the unique media types present in the database for this + * case. + */ class MediaTypeNode extends DisplayableItemNode { - String mediaType; - MediaTypeNode(String name) { super(Children.create(new MediaTypeChildren(name), true)); setName(name); @@ -285,6 +271,11 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } + /** + * Creates children fro media type nodes, children will be MediaSubTypeNodes + * and represent one of the subtypes which are present in the database of + * their media type. + */ class MediaTypeChildren extends ChildFactory implements Observer { String mediaType; @@ -313,6 +304,10 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } + /** + * Node which represents the media sub type in the By MIME type tree, the + * media subtype is the portion of the MIME type following the /. + */ class MediaSubTypeNode extends DisplayableItemNode { private MediaSubTypeNode(String mimeType) { @@ -326,11 +321,24 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS } + /** + * Updates the display name of the mediaSubTypeNode to include the count + * of files which it represents. + * + * @param mimeType - the complete MimeType, needed for accurate query + * results + */ private void updateDisplayName(String mimeType) { - final long count = MediaSubTypeNodeChildren.calculateItems(skCase, mimeType); + final long count = MediaSubTypeNodeChildren.calculateItems(getSleuthkitCase(), mimeType); super.setDisplayName(mimeType.split("/")[1] + " (" + count + ")"); } + /** + * This returns true because any MediaSubTypeNode that exists is going + * to be a bottom level node in the Tree view on the left of Autopsy. + * + * @return true + */ @Override public boolean isLeafTypeNode() { return true; @@ -348,6 +356,11 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } + /** + * Factory for populating the contents of the Media Sub Type Node with the + * files that match MimeType which is represented by this position in the + * tree. + */ private static class MediaSubTypeNodeChildren extends ChildFactory.Detachable { private final String mimeType; @@ -360,17 +373,27 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { /** * Get children count without actually loading all nodes * - * @return + * @return count(*) - the number of items that will be shown in this + * items Directory Listing */ - private static long calculateItems(SleuthkitCase sleuthkitCase, String mimeType) { + private static long calculateItems(SleuthkitCase sleuthkitCase, String mime_type) { try { - return sleuthkitCase.countFilesWhere(createQuery(mimeType)); + return sleuthkitCase.countFilesWhere(createQuery(mime_type)); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Error getting file search view count", ex); //NON-NLS return 0; } } + /** + * Uses the createQuery method to complete the query, Select * from + * tsk_files WHERE. The results from the database will contain the files + * which match this mime type and their information. + * + * @param list - will contain all files and their attributes from the + * tsk_files table where mime_type matches the one specified + * @return true + */ @Override protected boolean createKeys(List list) { try { @@ -382,16 +405,33 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { return true; } - private static String createQuery(String mimeType) { + /** + * Create the portion of the query following WHERE for a query of the + * database for each file which matches the complete MIME type + * represented by this node. Matches against the mime_type column in + * tsk_files. + * + * @param mimeType - the complete mimetype of the file mediatype/subtype + * @return query.toString - portion of SQL query which will follow a + * WHERE clause. + */ + private static String createQuery(String mime_type) { StringBuilder query = new StringBuilder(); query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS if (UserPreferences.hideKnownFilesInViewsTree()) { query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS } - query.append(" AND mime_type = '").append(mimeType).append("'"); + query.append(" AND mime_type = '").append(mime_type).append("'"); return query.toString(); } + /** + * Creates the content to populate the Directory Listing Table view for + * each file + * + * @param key + * @return + */ @Override protected Node createNodeForKey(Content key) { return key.accept(new ContentVisitor.Default() { @@ -426,5 +466,6 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } }); } + } } From 0a15b431c0c4dd355ef72b9f95dd690cab029977 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 14 Nov 2016 13:43:22 -0500 Subject: [PATCH 16/27] 1917 minor comment fixes to denote some NON-NLS text --- .../org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 3ec3a41054..05a55f9bfb 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -118,7 +118,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { */ private void populateHashMap() { StringBuilder allDistinctMimeTypesQuery = new StringBuilder(); - allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type NOT null"); + allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type NOT null"); //NON-NLS allDistinctMimeTypesQuery.append(" AND dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(";"); //NON-NLS synchronized (existingMimeTypes) { existingMimeTypes.clear(); @@ -421,7 +421,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { if (UserPreferences.hideKnownFilesInViewsTree()) { query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS } - query.append(" AND mime_type = '").append(mime_type).append("'"); + query.append(" AND mime_type = '").append(mime_type).append("'"); //NON-NLS return query.toString(); } From 2bab13a1f2aa55554a3c9998bfc189d4a3ddeeee Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 15 Nov 2016 16:48:58 -0500 Subject: [PATCH 17/27] 1917 Null Case Implemented for MIME tree, and clean up --- .../autopsy/datamodel/FileTypesByExtNode.java | 14 ++-- .../datamodel/FileTypesByMimeType.java | 64 +++++++++++++++---- .../autopsy/datamodel/ViewsNode.java | 1 - .../DirectoryTreeTopComponent.java | 18 ++++-- 4 files changed, 74 insertions(+), 23 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java index d9ce314ae7..5afb64fef8 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java @@ -48,7 +48,7 @@ public class FileTypesByExtNode extends DisplayableItemNode { * something to provide a sub-node. */ FileTypesByExtNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter) { - super(Children.create(new FileTypesChildren(skCase, filter, null), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); + super(Children.create(new FileTypesByExtChildren(skCase, filter, null), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); this.filter = filter; init(); } @@ -61,7 +61,7 @@ public class FileTypesByExtNode extends DisplayableItemNode { * provides updates on events */ private FileTypesByExtNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter, Observable o) { - super(Children.create(new FileTypesChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); + super(Children.create(new FileTypesByExtChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); this.filter = filter; init(); } @@ -122,7 +122,7 @@ public class FileTypesByExtNode extends DisplayableItemNode { /** * */ - static class FileTypesChildren extends ChildFactory { + static class FileTypesByExtChildren extends ChildFactory { private SleuthkitCase skCase; private FileTypeExtensionFilters.RootFilter filter; @@ -135,12 +135,12 @@ public class FileTypesByExtNode extends DisplayableItemNode { * @param o Observable that provides updates based on events being * fired (or null if one needs to be created) */ - public FileTypesChildren(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter, Observable o) { + public FileTypesByExtChildren(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter, Observable o) { super(); this.skCase = skCase; this.filter = filter; if (o == null) { - this.notifier = new FileTypesChildrenObservable(); + this.notifier = new FileTypesByExtChildrenObservable(); } else { this.notifier = o; } @@ -150,9 +150,9 @@ public class FileTypesByExtNode extends DisplayableItemNode { * Listens for case and ingest invest. Updates observers when events are * fired. FileType and FileTypes nodes are all listening to this. */ - private final class FileTypesChildrenObservable extends Observable { + private final class FileTypesByExtChildrenObservable extends Observable { - FileTypesChildrenObservable() { + FileTypesByExtChildrenObservable() { IngestManager.getInstance().addIngestJobEventListener(pcl); IngestManager.getInstance().addIngestModuleEventListener(pcl); Case.addPropertyChangeListener(pcl); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 05a55f9bfb..892a34b653 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -57,9 +57,9 @@ import org.sleuthkit.datamodel.TskData; * Listener which is checking for changes in IngestJobEvent Completed or * Cancelled and IngestModuleEvent Content Changed. */ -class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { +public class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { - static SleuthkitCase skCase; + private static SleuthkitCase skCase; /** * The nodes of this tree will be determined dynamically by the mimetypes * which exist in the database. This hashmap will store them with the media @@ -175,15 +175,15 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { * when the file detection module has not been run and MIME type is * currently unknown. */ - class FileTypesByMimeTypeNode extends DisplayableItemNode { + public class FileTypesByMimeTypeNode extends DisplayableItemNode { @NbBundle.Messages("FileTypesByMimeType.name.text=By MIME Type") final String NAME = Bundle.FileTypesByMimeType_name_text(); FileTypesByMimeTypeNode(SleuthkitCase sleuthkitCase) { super(Children.create(new FileTypesByMimeTypeNodeChildren(), true)); - setName(NAME); - setDisplayName(NAME); + super.setName(NAME); + super.setDisplayName(NAME); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); } @@ -202,6 +202,10 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { return getClass().getName(); } + public boolean isEmpty() { + return existingMimeTypes.isEmpty(); + } + } /** @@ -225,12 +229,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { @Override protected Node createNodeForKey(String key) { - if (!existingMimeTypes.isEmpty()) { - return new MediaTypeNode(key); - } else { - return null; - } - + return new MediaTypeNode(key); } @Override @@ -468,4 +467,47 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } } + + /** + * EmptyNode Class made for edge case where no mime exist in the database + * yet. Creates a node to display information on why the tree is empty. + * + * Swapped for the FileTypesByMimeType node in + * DirectoryTreeTopComponent.respondSelection + */ + static public class EmptyNode extends AbstractNode { + + public EmptyNode() { + super(Children.create(new EmptyChildFactory(), true)); + + } + + static class EmptyChildFactory extends ChildFactory { + + String FILE_ID_MSG = "Data not available. Run file type identification module."; //NON-NLS + + @Override + protected boolean createKeys(List list) { + list.add(FILE_ID_MSG); + return true; + } + + @Override + protected Node createNodeForKey(String key) { + return new MessageNode(key); + } + + } + + static class MessageNode extends AbstractNode { + + MessageNode(String name) { + super(Children.LEAF); + super.setName(name); + setName(name); + setDisplayName(name); + } + } + } + } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java index 7e73f37bec..a2c09299d1 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java @@ -36,7 +36,6 @@ public class ViewsNode extends DisplayableItemNode { public ViewsNode(SleuthkitCase sleuthkitCase) { super(new RootContentChildren(Arrays.asList( - // new FileTypeExtensionFilters(sleuthkitCase), new FileTypes(sleuthkitCase), // June '15: Recent Files was removed because it was not useful w/out filtering // add it back in if we can filter the results to a more managable size. diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 8f63752a27..c0c5ac3cd4 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -61,7 +61,9 @@ import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.autopsy.datamodel.DataSources; import org.sleuthkit.autopsy.datamodel.DataSourcesNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; +import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType.EmptyNode; import org.sleuthkit.autopsy.datamodel.ExtractedContent; +import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType; import org.sleuthkit.autopsy.datamodel.KeywordHits; import org.sleuthkit.autopsy.datamodel.KnownFileFilterNode; import org.sleuthkit.autopsy.datamodel.Reports; @@ -361,7 +363,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat items.add(new Tags()); items.add(new Reports()); contentChildren = new RootContentChildren(items); - + Node root = new AbstractNode(contentChildren) { /** * to override the right click action in the white blank @@ -632,6 +634,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat if (origin == null) { return; } + Node originNode = origin.getNode(); //set node, wrap in filter node first to filter out children @@ -639,7 +642,15 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat Node kffn = new KnownFileFilterNode(drfn, KnownFileFilterNode.getSelectionContext(originNode)); // Create a TableFilterNode with knowledge of the node's type to allow for column order settings - if (originNode instanceof DisplayableItemNode) { + //Special case for when File Type Identification has not yet been run and + //there are no mime types to populate Files by Mime Type Tree + if (originNode instanceof FileTypesByMimeType.FileTypesByMimeTypeNode + && ((FileTypesByMimeType.FileTypesByMimeTypeNode) originNode).isEmpty()) { + EmptyNode emptyNode = new EmptyNode(); + Node emptyDrfn = new DataResultFilterNode(emptyNode, DirectoryTreeTopComponent.this.em); + Node emptyKffn = new KnownFileFilterNode(emptyDrfn, KnownFileFilterNode.getSelectionContext(emptyNode)); + dataResult.setNode(new TableFilterNode(emptyKffn, true, "This Node Is Empty")); + } else if (originNode instanceof DisplayableItemNode) { dataResult.setNode(new TableFilterNode(kffn, true, ((DisplayableItemNode) originNode).getItemType())); } else { dataResult.setNode(new TableFilterNode(kffn, true)); @@ -783,8 +794,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat * Set the selected node using a path to a previously selected node. * * @param previouslySelectedNodePath Path to a previously selected node. - * @param rootNodeName Name of the root node to match, may be - * null. + * @param rootNodeName Name of the root node to match, may be null. */ private void setSelectedNode(final String[] previouslySelectedNodePath, final String rootNodeName) { if (previouslySelectedNodePath == null) { From e4f351bf8cc42d5631ed8a88a48b724f924d39d7 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Mon, 21 Nov 2016 17:06:31 -0500 Subject: [PATCH 18/27] Remove optional parameters from MIME types --- .../autopsy/filesearch/MimeTypePanel.java | 33 +++++++------ .../modules/filetypeid/FileTypeDetector.java | 47 +++++++++++++----- .../filetypeid/TikaFileTypeDetector.java | 3 -- .../interestingitems/FilesSetRulePanel.java | 13 ++--- .../InterestingItemDefsPanel.java | 48 +++++++++---------- 5 files changed, 83 insertions(+), 61 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java index dfebc0c718..0949e5f8fe 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java @@ -1,11 +1,23 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Autopsy Forensic Browser + * + * Copyright 2011-2016 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.filesearch; -import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -14,18 +26,11 @@ import java.util.SortedSet; import java.util.logging.Level; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import org.apache.tika.mime.MediaType; -import org.apache.tika.mime.MimeTypes; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; -/** - * - * @author oliver - */ public class MimeTypePanel extends javax.swing.JPanel { - private static final SortedSet mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes(); private static final Logger logger = Logger.getLogger(MimeTypePanel.class.getName()); private static final long serialVersionUID = 1L; @@ -45,8 +50,8 @@ public class MimeTypePanel extends javax.swing.JPanel { private String[] getMimeTypeArray() { Set fileTypesCollated = new HashSet<>(); - for (MediaType mediaType : mediaTypes) { - fileTypesCollated.add(mediaType.toString()); + for (String mediaType : FileTypeDetector.getDetectedTypes()) { + fileTypesCollated.add(mediaType); } FileTypeDetector fileTypeDetector; @@ -78,7 +83,7 @@ public class MimeTypePanel extends javax.swing.JPanel { boolean isSelected() { return this.mimeTypeCheckBox.isSelected(); } - + void setComponentsEnabled() { boolean enabled = this.isSelected(); this.mimeTypeList.setEnabled(enabled); diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index b0f95c93fa..42bdfbe619 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -19,11 +19,13 @@ package org.sleuthkit.autopsy.modules.filetypeid; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.SortedSet; +import java.util.TreeSet; import java.util.logging.Level; +import java.util.stream.Collectors; import org.apache.tika.Tika; -import org.apache.tika.mime.MediaType; import org.apache.tika.mime.MimeTypes; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; @@ -49,6 +51,7 @@ public class FileTypeDetector { private final byte buffer[] = new byte[BUFFER_SIZE]; private final List userDefinedFileTypes; private final List autopsyDefinedFileTypes; + private static SortedSet detectedTypes; //no optional parameters /** * Constructs an object that detects the MIME type of a file by an @@ -100,6 +103,21 @@ public class FileTypeDetector { || isDetectableByTika(mimeType); } + /** + * Returns an unmodifiable list of MIME types that does not contain types + * with optional parameters. The list has no duplicate types and is in + * alphabetical order. + * + * @return an unmodifiable view of a set of MIME types + */ + public static synchronized SortedSet getDetectedTypes() { + if (detectedTypes == null) { + detectedTypes = org.apache.tika.mime.MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes() + .stream().filter(t -> !t.hasParameters()).map(s -> s.toString()).collect(Collectors.toCollection(TreeSet::new)); + } + return Collections.unmodifiableSortedSet(detectedTypes); + } + /** * Determines whether or not a given MIME type is detectable as a * user-defined MIME type by this detector. @@ -126,15 +144,7 @@ public class FileTypeDetector { * @return True or false. */ private boolean isDetectableByTika(String mimeType) { - String[] split = mimeType.split("/"); - if (split.length == 2) { - String type = split[0]; - String subtype = split[1]; - MediaType mediaType = new MediaType(type, subtype); - SortedSet m = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes(); - return m.contains(mediaType); - } - return false; + return this.getDetectedTypes().contains(removeOptionalParameter(mimeType)); } /** @@ -196,7 +206,7 @@ public class FileTypeDetector { */ String mimeType = file.getMIMEType(); if (null != mimeType) { - return mimeType; + return removeOptionalParameter(mimeType); } /* @@ -248,6 +258,7 @@ public class FileTypeDetector { * Remove the Tika suffix from the MIME type name. */ mimeType = tikaType.replace("tika-", ""); //NON-NLS + mimeType = removeOptionalParameter(mimeType); } catch (Exception ignored) { /* @@ -288,6 +299,20 @@ public class FileTypeDetector { return mimeType; } + /** + * Removes the optional parameter from a MIME type string + * @param mimeType + * @return MIME type without the optional parameter + */ + private String removeOptionalParameter(String mimeType) { + int indexOfSemicolon = mimeType.indexOf(";"); + if (indexOfSemicolon != -1 ) { + return mimeType.substring(0, indexOfSemicolon).trim(); + } else { + return mimeType; + } + } + /** * Determines whether or not the a file matches a user-defined custom file * type. diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/TikaFileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/TikaFileTypeDetector.java index e8bd4ab29b..c237fe6222 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/TikaFileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/TikaFileTypeDetector.java @@ -24,9 +24,6 @@ import org.apache.tika.mime.MediaType; import org.apache.tika.mime.MimeTypes; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.TskCoreException; /** * @deprecated Use org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java index 9ee7f1a172..4d249f35ce 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java @@ -31,8 +31,6 @@ import java.util.regex.PatternSyntaxException; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JOptionPane; -import org.apache.tika.mime.MediaType; -import org.apache.tika.mime.MimeTypes; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.util.NbBundle; @@ -58,7 +56,6 @@ final class FilesSetRulePanel extends javax.swing.JPanel { "FilesSetRulePanel.ZeroFileSizeError=File size condition value must not be 0 (Unless = is selected)." }) - private static final SortedSet mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes(); private static final Logger logger = Logger.getLogger(FilesSetRulePanel.class.getName()); private static final String SLEUTHKIT_PATH_SEPARATOR = "/"; // NON-NLS private static final List ILLEGAL_FILE_NAME_CHARS = InterestingItemDefsManager.getIllegalFileNameChars(); @@ -106,8 +103,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel { private void populateMimeTypesComboBox() { Set fileTypesCollated = new HashSet<>(); - for (MediaType mediaType : mediaTypes) { - fileTypesCollated.add(mediaType.toString()); + for (String mediaType : FileTypeDetector.getDetectedTypes()) { + fileTypesCollated.add(mediaType); } FileTypeDetector fileTypeDetector; @@ -321,7 +318,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } } - // The path condition, if specified, must either be a regular expression + // The path condition, if specified, must either be a regular expression // that compiles or a string without illegal file path chars. if (this.pathCheck.isSelected()) { if (this.pathTextField.getText().isEmpty()) { @@ -412,7 +409,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } } else { logger.log(Level.SEVERE, "Attempt to get name condition with illegal chars"); // NON-NLS - throw new IllegalStateException("The files set rule panel name condition is not in a valid state"); // NON-NLS + throw new IllegalStateException("The files set rule panel name condition is not in a valid state"); // NON-NLS } } return condition; @@ -498,7 +495,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { condition = new FilesSet.Rule.ParentPathCondition(path); } else { logger.log(Level.SEVERE, "Attempt to get path condition with illegal chars"); // NON-NLS - throw new IllegalStateException("The files set rule panel path condition is not in a valid state"); // NON-NLS + throw new IllegalStateException("The files set rule panel path condition is not in a valid state"); // NON-NLS } } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java index ea1b2f2fdb..c3f4b949d1 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java @@ -34,7 +34,6 @@ import javax.swing.JOptionPane; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.apache.tika.mime.MediaType; -import org.apache.tika.mime.MimeTypes; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; @@ -57,16 +56,15 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp "InterestingItemsDefsPanel.saveError=Error saving interesting files sets to file." }) - private static final SortedSet mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes(); private final DefaultListModel setsListModel = new DefaultListModel<>(); private final DefaultListModel rulesListModel = new DefaultListModel<>(); private final Logger logger = Logger.getLogger(InterestingItemDefsPanel.class.getName()); - private JButton okButton = new JButton("OK"); - private JButton cancelButton = new JButton("Cancel"); + private final JButton okButton = new JButton("OK"); + private final JButton cancelButton = new JButton("Cancel"); - // The following is a map of interesting files set names to interesting - // files set definitions. It is a snapshot of the files set definitions - // obtained from the interesting item definitions manager at the time the + // The following is a map of interesting files set names to interesting + // files set definitions. It is a snapshot of the files set definitions + // obtained from the interesting item definitions manager at the time the // the panel is loaded. When the panel saves or stores its settings, these // definitions, possibly changed, are submitted back to the interesting item // definitions manager. Note that it is a tree map to aid in displaying @@ -88,10 +86,10 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp @NbBundle.Messages({"InterestingItemDefsPanel.Title=Global Interesting Items Settings"}) private void customInit() { setName(Bundle.InterestingItemDefsPanel_Title()); - + Set fileTypesCollated = new HashSet<>(); - for (MediaType mediaType : mediaTypes) { - fileTypesCollated.add(mediaType.toString()); + for (String mediaType : FileTypeDetector.getDetectedTypes()) { + fileTypesCollated.add(mediaType); } FileTypeDetector fileTypeDetector; @@ -119,7 +117,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp this.fileSizeUnitComboBox.setSelectedIndex(1); this.equalitySignComboBox.setSelectedIndex(2); } - + /** * @inheritDoc */ @@ -156,14 +154,14 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp this.filesSets = new TreeMap<>(); } - // Populate the list model for the interesting files sets list + // Populate the list model for the interesting files sets list // component. for (FilesSet set : this.filesSets.values()) { this.setsListModel.addElement(set); } if (!this.filesSets.isEmpty()) { - // Select the first files set by default. The list selections + // Select the first files set by default. The list selections // listeners will then populate the other components. EventQueue.invokeLater(() -> { InterestingItemDefsPanel.this.setsList.setSelectedIndex(0); @@ -222,7 +220,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp // components. FilesSet selectedSet = InterestingItemDefsPanel.this.setsList.getSelectedValue(); if (selectedSet != null) { - // Populate the components that display the properties of the + // Populate the components that display the properties of the // selected files set. InterestingItemDefsPanel.this.setDescriptionTextArea.setText(selectedSet.getDescription()); InterestingItemDefsPanel.this.ignoreKnownFilesCheckbox.setSelected(selectedSet.ignoresKnownFiles()); @@ -269,7 +267,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp FilesSet.Rule.MimeTypeCondition mimeTypeCondition = rule.getMimeTypeCondition(); FilesSet.Rule.FileSizeCondition fileSizeCondition = rule.getFileSizeCondition(); - // Populate the components that display the properties of the + // Populate the components that display the properties of the // selected rule. if (nameCondition != null) { InterestingItemDefsPanel.this.fileNameTextField.setText(nameCondition.getTextToMatch()); @@ -345,7 +343,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp panel = new FilesSetPanel(); } - // Do a dialog box with the files set panel until the user either enters + // Do a dialog box with the files set panel until the user either enters // a valid definition or cancels. Note that the panel gives the user // feedback when isValidDefinition() is called. int option = JOptionPane.OK_OPTION; @@ -366,7 +364,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp Map rules = new HashMap<>(); if (selectedSet != null) { // Interesting file sets are immutable for thread safety, - // so editing a files set definition is a replacement operation. + // so editing a files set definition is a replacement operation. // Preserve the existing rules from the set being edited. rules.putAll(selectedSet.getRules()); } @@ -391,7 +389,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp // Creating a new rule definition. panel = new FilesSetRulePanel(okButton, cancelButton); } - // Do a dialog box with the files set panel until the user either enters + // Do a dialog box with the files set panel until the user either enters // a valid definition or cancels. Note that the panel gives the user // feedback when isValidDefinition() is called. int option = JOptionPane.OK_OPTION; @@ -401,12 +399,12 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp if (option == JOptionPane.OK_OPTION) { // Interesting file sets are immutable for thread safety, - // so editing a files set rule definition is a replacement + // so editing a files set rule definition is a replacement // operation. Preserve the existing rules from the set being edited. FilesSet selectedSet = this.setsList.getSelectedValue(); Map rules = new HashMap<>(selectedSet.getRules()); - // Remove the "old" rule definition and add the new/edited + // Remove the "old" rule definition and add the new/edited // definition. if (selectedRule != null) { rules.remove(selectedRule.getUuid()); @@ -414,12 +412,12 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp FilesSet.Rule newRule = new FilesSet.Rule(panel.getRuleName(), panel.getFileNameCondition(), panel.getMetaTypeCondition(), panel.getPathCondition(), panel.getMimeTypeCondition(), panel.getFileSizeCondition()); rules.put(newRule.getUuid(), newRule); - // Add the new/edited files set definition, replacing any previous + // Add the new/edited files set definition, replacing any previous // definition with the same name and refreshing the display. this.replaceFilesSet(selectedSet, selectedSet.getName(), selectedSet.getDescription(), selectedSet.ignoresKnownFiles(), rules); - // Select the new/edited rule. Queue it up so it happens after the - // selection listeners react to the selection of the "new" files + // Select the new/edited rule. Queue it up so it happens after the + // selection listeners react to the selection of the "new" files // set. EventQueue.invokeLater(() -> { this.rulesList.setSelectedValue(newRule, true); @@ -459,8 +457,8 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp this.setsListModel.addElement(set); } - // Select the new/edited files set definition in the set definitions - // list. This will cause the selection listeners to repopulate the + // Select the new/edited files set definition in the set definitions + // list. This will cause the selection listeners to repopulate the // subordinate components. this.setsList.setSelectedValue(newSet, true); } From 4daea3f48d24cb4a7ff450e36f2e150e3528842d Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Mon, 21 Nov 2016 17:11:43 -0500 Subject: [PATCH 19/27] Clean up code --- Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java | 1 - .../autopsy/modules/interestingitems/FilesSetRulePanel.java | 3 +-- .../modules/interestingitems/InterestingItemDefsPanel.java | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java index 0949e5f8fe..e89e8d8cc2 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java @@ -22,7 +22,6 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.SortedSet; import java.util.logging.Level; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java index 4d249f35ce..10ef3fd804 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2014-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,6 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.SortedSet; import java.util.logging.Level; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java index c3f4b949d1..b0bac78f6d 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java @@ -25,7 +25,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.SortedSet; import java.util.TreeMap; import java.util.logging.Level; import javax.swing.DefaultListModel; @@ -33,7 +32,6 @@ import javax.swing.JButton; import javax.swing.JOptionPane; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import org.apache.tika.mime.MediaType; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; From 961c29a28d27bc157d927bd40cb0b39be8ee1a43 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 22 Nov 2016 10:04:56 -0500 Subject: [PATCH 20/27] Rename method that gets the standard MIME types --- .../autopsy/filesearch/MimeTypePanel.java | 2 +- .../modules/filetypeid/FileTypeDetector.java | 14 ++++++++++---- .../interestingitems/FilesSetRulePanel.java | 2 +- .../interestingitems/InterestingItemDefsPanel.java | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java index e89e8d8cc2..3982cb2779 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java @@ -49,7 +49,7 @@ public class MimeTypePanel extends javax.swing.JPanel { private String[] getMimeTypeArray() { Set fileTypesCollated = new HashSet<>(); - for (String mediaType : FileTypeDetector.getDetectedTypes()) { + for (String mediaType : FileTypeDetector.getStandardDetectedTypes()) { fileTypesCollated.add(mediaType); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index 42bdfbe619..b1b2748ff1 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -104,13 +104,13 @@ public class FileTypeDetector { } /** - * Returns an unmodifiable list of MIME types that does not contain types - * with optional parameters. The list has no duplicate types and is in + * Returns an unmodifiable list of standard MIME types that does not contain + * types with optional parameters. The list has no duplicate types and is in * alphabetical order. * * @return an unmodifiable view of a set of MIME types */ - public static synchronized SortedSet getDetectedTypes() { + public static synchronized SortedSet getStandardDetectedTypes() { if (detectedTypes == null) { detectedTypes = org.apache.tika.mime.MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes() .stream().filter(t -> !t.hasParameters()).map(s -> s.toString()).collect(Collectors.toCollection(TreeSet::new)); @@ -144,7 +144,7 @@ public class FileTypeDetector { * @return True or false. */ private boolean isDetectableByTika(String mimeType) { - return this.getDetectedTypes().contains(removeOptionalParameter(mimeType)); + return this.getStandardDetectedTypes().contains(removeOptionalParameter(mimeType)); } /** @@ -206,6 +206,9 @@ public class FileTypeDetector { */ String mimeType = file.getMIMEType(); if (null != mimeType) { + // We remove the optional parameter to allow this method to work + // with legacy databases that may contain MIME types with the + // optional parameter attached. return removeOptionalParameter(mimeType); } @@ -258,6 +261,9 @@ public class FileTypeDetector { * Remove the Tika suffix from the MIME type name. */ mimeType = tikaType.replace("tika-", ""); //NON-NLS + /* + * Remove the optional parameter from the MIME type. + */ mimeType = removeOptionalParameter(mimeType); } catch (Exception ignored) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java index 10ef3fd804..29d56e6f8a 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java @@ -102,7 +102,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { private void populateMimeTypesComboBox() { Set fileTypesCollated = new HashSet<>(); - for (String mediaType : FileTypeDetector.getDetectedTypes()) { + for (String mediaType : FileTypeDetector.getStandardDetectedTypes()) { fileTypesCollated.add(mediaType); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java index b0bac78f6d..94af650828 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java @@ -86,7 +86,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp setName(Bundle.InterestingItemDefsPanel_Title()); Set fileTypesCollated = new HashSet<>(); - for (String mediaType : FileTypeDetector.getDetectedTypes()) { + for (String mediaType : FileTypeDetector.getStandardDetectedTypes()) { fileTypesCollated.add(mediaType); } From 6e8a6262f5889a4018f1fa11ec251d126814004f Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 22 Nov 2016 10:07:34 -0500 Subject: [PATCH 21/27] Change static method reference to use class name --- .../sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index b1b2748ff1..af796f0f6b 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -144,7 +144,7 @@ public class FileTypeDetector { * @return True or false. */ private boolean isDetectableByTika(String mimeType) { - return this.getStandardDetectedTypes().contains(removeOptionalParameter(mimeType)); + return FileTypeDetector.getStandardDetectedTypes().contains(removeOptionalParameter(mimeType)); } /** From e0112d2030189e6d8c83da8af8a532f52fd6f4b8 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Wed, 23 Nov 2016 10:27:43 -0500 Subject: [PATCH 22/27] Remove tag columns for tag nodes, add column for VD --- .../datamodel/AbstractAbstractFileNode.java | 17 +++++++------- .../datamodel/BlackboardArtifactNode.java | 2 +- .../datamodel/BlackboardArtifactTagNode.java | 15 +----------- .../autopsy/datamodel/ContentTagNode.java | 23 ++++--------------- .../datamodel/VirtualDirectoryNode.java | 1 + 5 files changed, 17 insertions(+), 41 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 131c069aa0..e3c750826d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2016 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. @@ -37,7 +37,7 @@ import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.Tag; +import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TskCoreException; /** @@ -302,14 +302,15 @@ public abstract class AbstractAbstractFileNode extends A /** * Used by subclasses of AbstractAbstractFileNode to add the tags property * to their sheets. - * @param ss + * @param ss the modifiable Sheet.Set returned by Sheet.get(Sheet.PROPERTIES) */ protected void addTagProperty(Sheet.Set ss) { final String NO_DESCR = NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.desc"); - List tags = new ArrayList<>(); + List tags; try { - tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content)); + tags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content); } catch (TskCoreException ex) { + tags = new ArrayList<>(); LOGGER.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex); } ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 8400c665e0..df2b6520a9 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -204,7 +204,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode { displayName = associated.getName(); } - // If this is a node for a keyword hit on an artifact, we set the + // If this is a node for a keyword hit on an artifact, we set the // display name to be the artifact type name followed by " Artifact" // e.g. "Messages Artifact". if (artifact != null && artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactTagNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactTagNode.java index 86fce1ab78..4647298931 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactTagNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactTagNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2014 Basis Technology Corp. + * Copyright 2013-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,18 +19,15 @@ package org.sleuthkit.autopsy.datamodel; import java.text.MessageFormat; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; -import java.util.stream.Collectors; import javax.swing.Action; import org.openide.nodes.Children; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.actions.DeleteBlackboardArtifactTagAction; -import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction; @@ -38,7 +35,6 @@ import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; -import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; /** @@ -98,15 +94,6 @@ public class BlackboardArtifactTagNode extends DisplayableItemNode { "", tag.getComment())); - List tags = new ArrayList<>(); - try { - tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(tag.getArtifact())); - } catch (TskCoreException ex) { - Logger.getLogger(ContentTagNode.class.getName()).log(Level.SEVERE, "Failed to get tags for artifact " + tag.getArtifact().getDisplayName(), ex); - } - properties.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), - "", tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); - return propertySheet; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java index 8099bbc300..74ab98d517 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2013-2016 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. @@ -18,24 +18,20 @@ */ package org.sleuthkit.autopsy.datamodel; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; -import java.util.stream.Collectors; import javax.swing.Action; import org.openide.nodes.Children; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.actions.DeleteContentTagAction; -import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; -import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; /** @@ -110,15 +106,6 @@ class ContentTagNode extends DisplayableItemNode { "", content.getSize())); - List tags = new ArrayList<>(); - try { - tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content)); - } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex); - } - properties.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), - "", tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); - return propertySheet; } @@ -131,7 +118,7 @@ class ContentTagNode extends DisplayableItemNode { if (file != null) { actions.add(ViewFileInTimelineAction.createViewFileAction(file)); } - actions.add(null); // Adds a menu item separator. + actions.add(null); // Adds a menu item separator. actions.add(DeleteContentTagAction.getInstance()); return actions.toArray(new Action[actions.size()]); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java index 9cf67f4649..246c6d6e1d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java @@ -148,6 +148,7 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode entry : map.entrySet()) { ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue())); } + addTagProperty(ss); } else { ss.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_type_name(), Bundle.VirtualDirectoryNode_createSheet_type_displayName(), From 8f0b9c057c970adcda350ffde1df89fb289cd9bf Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 23 Nov 2016 11:04:41 -0500 Subject: [PATCH 23/27] 1917-fixed re-opening project, and queries only returning files --- .../datamodel/DisplayableItemNodeVisitor.java | 9 ++++- .../datamodel/FileTypesByMimeType.java | 33 +++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index 2ec8b205bb..f7fdb96243 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -152,6 +152,8 @@ public interface DisplayableItemNodeVisitor { T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaSubType); + T visit(FileTypesByMimeType.EmptyNode.MessageNode aThis); + /** * Visitor with an implementable default behavior for all types. Override @@ -229,7 +231,12 @@ public interface DisplayableItemNodeVisitor { public T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaTypeNode) { return defaultVisit(ftByMimeTypeMediaTypeNode); } - + + @Override + public T visit(FileTypesByMimeType.EmptyNode.MessageNode ftByMimeTypeEmptyNode) { + return defaultVisit(ftByMimeTypeEmptyNode); + } + @Override public T visit(DeletedContentNode dcn) { return defaultVisit(dcn); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 892a34b653..444444b64a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -119,7 +119,11 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI private void populateHashMap() { StringBuilder allDistinctMimeTypesQuery = new StringBuilder(); allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type NOT null"); //NON-NLS - allDistinctMimeTypesQuery.append(" AND dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(";"); //NON-NLS + allDistinctMimeTypesQuery.append(" AND dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()); //NON-NLS + allDistinctMimeTypesQuery.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS + allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal()).append(","); + allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal()).append(","); + allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()).append("))"); synchronized (existingMimeTypes) { existingMimeTypes.clear(); } @@ -155,6 +159,7 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI IngestManager.getInstance().addIngestJobEventListener(pcl); IngestManager.getInstance().addIngestModuleEventListener(pcl); FileTypesByMimeType.skCase = skCase; + populateHashMap(); } /** @@ -417,6 +422,10 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI private static String createQuery(String mime_type) { StringBuilder query = new StringBuilder(); query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS + query.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS + query.append(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal()).append(","); + query.append(TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal()).append(","); + query.append(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()).append("))"); if (UserPreferences.hideKnownFilesInViewsTree()) { query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS } @@ -499,7 +508,12 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI } - static class MessageNode extends AbstractNode { + /** + * MessageNode is is the info message that displays in the table view, + * by also extending a DisplayableItemNode type, rather than an + * AbstractNode type it doesn't throw an error when right clicked. + */ + static class MessageNode extends DisplayableItemNode { MessageNode(String name) { super(Children.LEAF); @@ -507,6 +521,21 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI setName(name); setDisplayName(name); } + + @Override + public boolean isLeafTypeNode() { + return true; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + public String getItemType() { + return getClass().getName(); + } } } From 0917c3f53f4f238c646fc5abd78bf21b5afc9b8b Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Wed, 23 Nov 2016 13:00:01 -0500 Subject: [PATCH 24/27] Make tagged items darker and move tags column to end by default --- .../corecomponents/DataResultViewerTable.java | 2 +- .../datamodel/BlackboardArtifactNode.java | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 8b26ac8ca4..a3e87e3008 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -81,7 +81,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { private final Map> propertiesMap = new TreeMap<>(); private final DummyNodeListener dummyNodeListener = new DummyNodeListener(); private static final String DUMMY_NODE_DISPLAY_NAME = NbBundle.getMessage(DataResultViewerTable.class, "DataResultViewerTable.dummyNodeDisplayName"); - private static final Color TAGGED_COLOR = new Color(230, 235, 240); + private static final Color TAGGED_COLOR = new Color(200, 210, 220); private Node currentRoot; // When a column in the table is moved, these two variables keep track of where // the column started and where it ended up. diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index df2b6520a9..7d15bb2101 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -256,17 +256,6 @@ public class BlackboardArtifactNode extends DisplayableItemNode { } } - // add properties for tags - List tags = new ArrayList<>(); - try { - tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact)); - tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(associated)); - } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Failed to get tags for artifact " + artifact.getDisplayName(), ex); - } - ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "BlackboardArtifactNode.createSheet.tags.displayName"), - NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); - final int artifactTypeId = artifact.getArtifactTypeID(); // If mismatch, add props for extension and file type @@ -353,6 +342,17 @@ public class BlackboardArtifactNode extends DisplayableItemNode { } } + // add properties for tags + List tags = new ArrayList<>(); + try { + tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact)); + tags.addAll(Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(associated)); + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Failed to get tags for artifact " + artifact.getDisplayName(), ex); + } + ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "BlackboardArtifactNode.createSheet.tags.displayName"), + NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + return s; } From ef94fd80a8584478c60fc361df4efd756bcccfd8 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 30 Nov 2016 10:29:40 -0500 Subject: [PATCH 25/27] 1917-fixed issue where mime nodes were not updating --- .../datamodel/FileTypesByMimeType.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 444444b64a..2d6393b000 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -312,10 +312,11 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI * Node which represents the media sub type in the By MIME type tree, the * media subtype is the portion of the MIME type following the /. */ - class MediaSubTypeNode extends DisplayableItemNode { + class MediaSubTypeNode extends DisplayableItemNode implements Observer { private MediaSubTypeNode(String mimeType) { super(Children.create(new MediaSubTypeNodeChildren(mimeType), true)); + addObserver(this); init(mimeType); } @@ -333,7 +334,9 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI * results */ private void updateDisplayName(String mimeType) { - final long count = MediaSubTypeNodeChildren.calculateItems(getSleuthkitCase(), mimeType); + + final long count = new MediaSubTypeNodeChildren(mimeType).calculateItems(getSleuthkitCase(), mimeType); + super.setDisplayName(mimeType.split("/")[1] + " (" + count + ")"); } @@ -358,6 +361,10 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI return getClass().getName(); } + @Override + public void update(Observable o, Object arg) { + updateDisplayName(getName()); + } } /** @@ -365,12 +372,13 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI * files that match MimeType which is represented by this position in the * tree. */ - private static class MediaSubTypeNodeChildren extends ChildFactory.Detachable { + private class MediaSubTypeNodeChildren extends ChildFactory.Detachable implements Observer { private final String mimeType; MediaSubTypeNodeChildren(String mimeType) { super(); + addObserver(this); this.mimeType = mimeType; } @@ -380,7 +388,7 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI * @return count(*) - the number of items that will be shown in this * items Directory Listing */ - private static long calculateItems(SleuthkitCase sleuthkitCase, String mime_type) { + private long calculateItems(SleuthkitCase sleuthkitCase, String mime_type) { try { return sleuthkitCase.countFilesWhere(createQuery(mime_type)); } catch (TskCoreException ex) { @@ -419,7 +427,7 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI * @return query.toString - portion of SQL query which will follow a * WHERE clause. */ - private static String createQuery(String mime_type) { + private String createQuery(String mime_type) { StringBuilder query = new StringBuilder(); query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS query.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS @@ -432,7 +440,13 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI query.append(" AND mime_type = '").append(mime_type).append("'"); //NON-NLS return query.toString(); } + + @Override + public void update(Observable o, Object arg) { + refresh(true); + } + /** * Creates the content to populate the Directory Listing Table view for * each file @@ -474,7 +488,6 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI } }); } - } /** From dc06e7727b1abfb9d85ad93d7d822a85cb526f6f Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 1 Dec 2016 12:21:57 -0500 Subject: [PATCH 26/27] 1917 Fixing broken multi-user query, by adding IS --- .../org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 2d6393b000..f0fcb90901 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -118,7 +118,7 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI */ private void populateHashMap() { StringBuilder allDistinctMimeTypesQuery = new StringBuilder(); - allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type NOT null"); //NON-NLS + allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type IS NOT null"); //NON-NLS allDistinctMimeTypesQuery.append(" AND dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()); //NON-NLS allDistinctMimeTypesQuery.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal()).append(","); From 57e506b8ae76c6d57b2999b4cc4a2a09c640ac27 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 2 Dec 2016 12:30:06 -0500 Subject: [PATCH 27/27] Delete KWS issue report file, move into JIRA --- .../src/org/sleuthkit/autopsy/keywordsearch/notes.txt | 5 ----- 1 file changed, 5 deletions(-) delete mode 100755 KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/notes.txt diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/notes.txt b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/notes.txt deleted file mode 100755 index 1c771a55cd..0000000000 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -- Tika has a bug in the true type font parser included in fontbox. It should - be fixed in the next release of Tika (1.5, or a 1.4 point release). Until then - we bypass Tika when it detects a type of "application/x-font-ttf". See - AbstractFileTikaTextExtract::isSupported. This should be removed when we - update Tika. \ No newline at end of file