mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 18:17:43 +00:00
1903-Resolved conflicts from merge
This commit is contained in:
commit
dfacb3b41b
@ -39,7 +39,7 @@ abstract class TagAddedEvent<T extends Tag> extends AutopsyEvent implements Seri
|
|||||||
private transient T tag;
|
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.
|
* transient tag from the database.
|
||||||
*/
|
*/
|
||||||
private final Long tagID;
|
private final Long tagID;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.corecomponents;
|
package org.sleuthkit.autopsy.corecomponents;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Cursor;
|
import java.awt.Cursor;
|
||||||
import java.awt.FontMetrics;
|
import java.awt.FontMetrics;
|
||||||
@ -26,6 +27,7 @@ import java.awt.dnd.DnDConstants;
|
|||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
@ -41,6 +43,7 @@ import javax.swing.event.ListSelectionEvent;
|
|||||||
import javax.swing.event.TableColumnModelEvent;
|
import javax.swing.event.TableColumnModelEvent;
|
||||||
import javax.swing.event.TableColumnModelListener;
|
import javax.swing.event.TableColumnModelListener;
|
||||||
import javax.swing.table.TableCellRenderer;
|
import javax.swing.table.TableCellRenderer;
|
||||||
|
import org.netbeans.swing.outline.DefaultOutlineCellRenderer;
|
||||||
import org.netbeans.swing.outline.DefaultOutlineModel;
|
import org.netbeans.swing.outline.DefaultOutlineModel;
|
||||||
import org.openide.explorer.ExplorerManager;
|
import org.openide.explorer.ExplorerManager;
|
||||||
import org.openide.explorer.view.OutlineView;
|
import org.openide.explorer.view.OutlineView;
|
||||||
@ -66,6 +69,8 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
|||||||
//@ServiceProvider(service = DataResultViewer.class)
|
//@ServiceProvider(service = DataResultViewer.class)
|
||||||
public class DataResultViewerTable extends AbstractDataResultViewer {
|
public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final String firstColumnLabel = NbBundle.getMessage(DataResultViewerTable.class, "DataResultViewerTable.firstColLbl");
|
private final String firstColumnLabel = NbBundle.getMessage(DataResultViewerTable.class, "DataResultViewerTable.firstColLbl");
|
||||||
/* The properties map maps
|
/* The properties map maps
|
||||||
* key: stored value of column index -> value: property at that index
|
* key: stored value of column index -> value: property at that index
|
||||||
@ -76,6 +81,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
|||||||
private final Map<Integer, Property<?>> propertiesMap = new TreeMap<>();
|
private final Map<Integer, Property<?>> propertiesMap = new TreeMap<>();
|
||||||
private final DummyNodeListener dummyNodeListener = new DummyNodeListener();
|
private final DummyNodeListener dummyNodeListener = new DummyNodeListener();
|
||||||
private static final String DUMMY_NODE_DISPLAY_NAME = NbBundle.getMessage(DataResultViewerTable.class, "DataResultViewerTable.dummyNodeDisplayName");
|
private static final String DUMMY_NODE_DISPLAY_NAME = NbBundle.getMessage(DataResultViewerTable.class, "DataResultViewerTable.dummyNodeDisplayName");
|
||||||
|
private static final Color TAGGED_COLOR = new Color(200, 210, 220);
|
||||||
private Node currentRoot;
|
private Node currentRoot;
|
||||||
// When a column in the table is moved, these two variables keep track of where
|
// When a column in the table is moved, these two variables keep track of where
|
||||||
// the column started and where it ended up.
|
// the column started and where it ended up.
|
||||||
@ -113,6 +119,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
|||||||
ov.getOutline().setRootVisible(false);
|
ov.getOutline().setRootVisible(false);
|
||||||
ov.getOutline().setDragEnabled(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() {
|
ov.getOutline().getColumnModel().addColumnModelListener(new TableColumnModelListener() {
|
||||||
@Override
|
@Override
|
||||||
public void columnAdded(TableColumnModelEvent e) {
|
public void columnAdded(TableColumnModelEvent e) {
|
||||||
@ -183,6 +190,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() {
|
ov.getOutline().getTableHeader().addMouseListener(new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased(MouseEvent e) {
|
public void mouseReleased(MouseEvent e) {
|
||||||
@ -387,7 +395,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
|||||||
ov.getOutline().setAutoResizeMode((props.size() > 0) ? JTable.AUTO_RESIZE_OFF : JTable.AUTO_RESIZE_ALL_COLUMNS);
|
ov.getOutline().setAutoResizeMode((props.size() > 0) ? JTable.AUTO_RESIZE_OFF : JTable.AUTO_RESIZE_ALL_COLUMNS);
|
||||||
|
|
||||||
if (root.getChildren().getNodesCount() != 0) {
|
if (root.getChildren().getNodesCount() != 0) {
|
||||||
|
|
||||||
final Graphics graphics = ov.getGraphics();
|
final Graphics graphics = ov.getGraphics();
|
||||||
if (graphics != null) {
|
if (graphics != null) {
|
||||||
final FontMetrics metrics = graphics.getFontMetrics();
|
final FontMetrics metrics = graphics.getFontMetrics();
|
||||||
@ -397,7 +404,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
|||||||
|
|
||||||
for (int column = 0; column < ov.getOutline().getModel().getColumnCount(); column++) {
|
for (int column = 0; column < ov.getOutline().getModel().getColumnCount(); column++) {
|
||||||
int firstColumnPadding = (column == 0) ? 32 : 0;
|
int firstColumnPadding = (column == 0) ? 32 : 0;
|
||||||
int columnWidthLimit = (column == 0) ? 250 : 350;
|
int columnWidthLimit = (column == 0) ? 350 : 300;
|
||||||
int valuesWidth = 0;
|
int valuesWidth = 0;
|
||||||
|
|
||||||
// find the maximum width needed to fit the values for the first 100 rows, at most
|
// find the maximum width needed to fit the values for the first 100 rows, at most
|
||||||
@ -421,6 +428,48 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
|||||||
// if there's no content just auto resize all columns
|
// if there's no content just auto resize all columns
|
||||||
ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
|
ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This custom renderer extends the renderer that was already being
|
||||||
|
* 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;
|
||||||
|
@Override
|
||||||
|
public Component getTableCellRendererComponent(JTable table,
|
||||||
|
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")) {
|
||||||
|
try {
|
||||||
|
tagFound = !prop.getValue().equals("");
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException ignore) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//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 ColorTagCustomRenderer());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -547,11 +596,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
|||||||
if (SwingUtilities.isEventDispatchThread()) {
|
if (SwingUtilities.isEventDispatchThread()) {
|
||||||
setupTable(nme.getNode());
|
setupTable(nme.getNode());
|
||||||
} else {
|
} else {
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(() -> {
|
||||||
@Override
|
setupTable(nme.getNode());
|
||||||
public void run() {
|
|
||||||
setupTable(nme.getNode());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2014 Basis Technology Corp.
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -20,17 +20,24 @@ package org.sleuthkit.autopsy.datamodel;
|
|||||||
|
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
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.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
|
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
import org.sleuthkit.datamodel.ContentTag;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,9 +110,23 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
|||||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||||
removeListeners();
|
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
|
// Note: this order matters for the search result, changed it if the order of property headers on the "KeywordSearchNode"changed
|
||||||
public static enum AbstractFilePropertyType {
|
public static enum AbstractFilePropertyType {
|
||||||
|
|
||||||
@ -278,6 +299,24 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
|||||||
map.put(AbstractFilePropertyType.MIMETYPE.toString(), content.getMIMEType() == null ? "" : content.getMIMEType());
|
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 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<ContentTag> tags;
|
||||||
|
try {
|
||||||
|
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"),
|
||||||
|
NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", "))));
|
||||||
|
}
|
||||||
|
|
||||||
static String getContentDisplayName(AbstractFile file) {
|
static String getContentDisplayName(AbstractFile file) {
|
||||||
String name = file.getName();
|
String name = file.getName();
|
||||||
switch (name) {
|
switch (name) {
|
||||||
|
@ -22,6 +22,7 @@ import org.openide.nodes.AbstractNode;
|
|||||||
import org.openide.nodes.Children.Keys;
|
import org.openide.nodes.Children.Keys;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.NbBundle;
|
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.FileTypeExtensionFilters;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.RecentFiles;
|
import org.sleuthkit.autopsy.datamodel.accounts.RecentFiles;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
||||||
@ -137,7 +138,7 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(FileTypeExtensionFilters sf) {
|
public AbstractNode visit(FileTypeExtensionFilters sf) {
|
||||||
return new FileTypesNode(sf.getSleuthkitCase(), null);
|
return new FileTypesByExtNode(sf.getSleuthkitCase(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -195,6 +196,11 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
return new ResultsNode(r.getSleuthkitCase());
|
return new ResultsNode(r.getSleuthkitCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractNode visit(FileTypes ft) {
|
||||||
|
return new FileTypesNode(ft.getSleuthkitCase());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(Reports reportsItem) {
|
public AbstractNode visit(Reports reportsItem) {
|
||||||
return new Reports.ReportsListNode();
|
return new Reports.ReportsListNode();
|
||||||
@ -211,5 +217,10 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
NbBundle.getMessage(this.getClass(),
|
NbBundle.getMessage(this.getClass(),
|
||||||
"AbstractContentChildren.createAutopsyNodeVisitor.exception.noNodeMsg"));
|
"AbstractContentChildren.createAutopsyNodeVisitor.exception.noNodeMsg"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractNode visit(FileTypesByMimeType ftByMimeTypeItem) {
|
||||||
|
return ftByMimeTypeItem.new FileTypesByMimeTypeNode(ftByMimeTypeItem.getSleuthkitCase());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,9 @@ public abstract class AbstractFsContentNode<T extends AbstractFile> extends Abst
|
|||||||
ss.put(new NodeProperty<>(HIDE_PARENT, HIDE_PARENT, HIDE_PARENT, HIDE_PARENT));
|
ss.put(new NodeProperty<>(HIDE_PARENT, HIDE_PARENT, HIDE_PARENT, HIDE_PARENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add tags property to the sheet
|
||||||
|
addTagProperty(ss);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +71,11 @@ public interface AutopsyItemVisitor<T> {
|
|||||||
|
|
||||||
T visit(Accounts accountsItem);
|
T visit(Accounts accountsItem);
|
||||||
|
|
||||||
|
T visit(FileTypes fileTypesItem);
|
||||||
|
|
||||||
|
T visit(FileTypesByMimeType aThis);
|
||||||
|
|
||||||
|
|
||||||
static abstract public class Default<T> implements AutopsyItemVisitor<T> {
|
static abstract public class Default<T> implements AutopsyItemVisitor<T> {
|
||||||
|
|
||||||
protected abstract T defaultVisit(AutopsyVisitableItem ec);
|
protected abstract T defaultVisit(AutopsyVisitableItem ec);
|
||||||
@ -99,7 +104,12 @@ public interface AutopsyItemVisitor<T> {
|
|||||||
public T visit(FileTypeExtensionFilters.ExecutableFilter ef) {
|
public T visit(FileTypeExtensionFilters.ExecutableFilter ef) {
|
||||||
return defaultVisit(ef);
|
return defaultVisit(ef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T visit(FileTypesByMimeType ftByMimeType) {
|
||||||
|
return defaultVisit(ftByMimeType);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(DeletedContent dc) {
|
public T visit(DeletedContent dc) {
|
||||||
return defaultVisit(dc);
|
return defaultVisit(dc);
|
||||||
@ -170,6 +180,12 @@ public interface AutopsyItemVisitor<T> {
|
|||||||
return defaultVisit(r);
|
return defaultVisit(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T visit(FileTypes ft) {
|
||||||
|
return defaultVisit(ft);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(Reports reportsItem) {
|
public T visit(Reports reportsItem) {
|
||||||
return defaultVisit(reportsItem);
|
return defaultVisit(reportsItem);
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -25,6 +27,7 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
@ -35,6 +38,10 @@ import org.openide.util.lookup.Lookups;
|
|||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
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.ViewArtifactInTimelineAction;
|
||||||
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
|
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
@ -43,6 +50,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
|||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
import org.sleuthkit.datamodel.Tag;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,6 +78,39 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
private static final Integer[] SHOW_FILE_METADATA = new Integer[]{
|
private static final Integer[] SHOW_FILE_METADATA = new Integer[]{
|
||||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),};
|
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
|
* Construct blackboard artifact node from an artifact and using provided
|
||||||
* icon
|
* icon
|
||||||
@ -86,6 +127,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
this.setName(Long.toString(artifact.getArtifactID()));
|
this.setName(Long.toString(artifact.getArtifactID()));
|
||||||
this.setDisplayName();
|
this.setDisplayName();
|
||||||
this.setIconBaseWithExtension(iconPath);
|
this.setIconBaseWithExtension(iconPath);
|
||||||
|
Case.addPropertyChangeListener(pcl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,6 +145,11 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
this.setName(Long.toString(artifact.getArtifactID()));
|
this.setName(Long.toString(artifact.getArtifactID()));
|
||||||
this.setDisplayName();
|
this.setDisplayName();
|
||||||
this.setIconBaseWithExtension(ExtractedContent.getIconFilePath(artifact.getArtifactTypeID())); //NON-NLS
|
this.setIconBaseWithExtension(ExtractedContent.getIconFilePath(artifact.getArtifactTypeID())); //NON-NLS
|
||||||
|
Case.addPropertyChangeListener(pcl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeListeners() {
|
||||||
|
Case.removePropertyChangeListener(pcl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -157,7 +204,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
displayName = associated.getName();
|
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"
|
// display name to be the artifact type name followed by " Artifact"
|
||||||
// e.g. "Messages Artifact".
|
// e.g. "Messages Artifact".
|
||||||
if (artifact != null && artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
|
if (artifact != null && artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
|
||||||
@ -208,6 +255,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
ss.put(np);
|
ss.put(np);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final int artifactTypeId = artifact.getArtifactTypeID();
|
final int artifactTypeId = artifact.getArtifactTypeID();
|
||||||
|
|
||||||
// If mismatch, add props for extension and file type
|
// If mismatch, add props for extension and file type
|
||||||
@ -294,9 +342,24 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add properties for tags
|
||||||
|
List<Tag> 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;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateSheet() {
|
||||||
|
this.setSheet(createSheet());
|
||||||
|
}
|
||||||
|
|
||||||
private String getRootParentName() {
|
private String getRootParentName() {
|
||||||
String parentName = associated.getName();
|
String parentName = associated.getName();
|
||||||
Content parent = associated;
|
Content parent = associated;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013-2014 Basis Technology Corp.
|
* Copyright 2013-2016 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -124,7 +124,7 @@ FileTypeNode.createSheet.filterType.desc=no description
|
|||||||
FileTypeNode.createSheet.fileExt.name=File Extensions
|
FileTypeNode.createSheet.fileExt.name=File Extensions
|
||||||
FileTypeNode.createSheet.fileExt.displayName=File Extensions
|
FileTypeNode.createSheet.fileExt.displayName=File Extensions
|
||||||
FileTypeNode.createSheet.fileExt.desc=no description
|
FileTypeNode.createSheet.fileExt.desc=no description
|
||||||
FileTypesNode.fname.text=File Types
|
FileTypesNode.fname.text=By Extension
|
||||||
FileTypesNode.createSheet.name.name=Name
|
FileTypesNode.createSheet.name.name=Name
|
||||||
FileTypesNode.createSheet.name.displayName=Name
|
FileTypesNode.createSheet.name.displayName=Name
|
||||||
FileTypesNode.createSheet.name.desc=no description
|
FileTypesNode.createSheet.name.desc=no description
|
||||||
@ -270,3 +270,8 @@ DeleteReportAction.actionDisplayName.multipleReports=Delete Reports
|
|||||||
DeleteReportAction.actionPerformed.showConfirmDialog.title=Confirm Deletion
|
DeleteReportAction.actionPerformed.showConfirmDialog.title=Confirm Deletion
|
||||||
DeleteReportAction.actionPerformed.showConfirmDialog.single.msg=Do you want to delete 1 report from the case?
|
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?
|
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
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013 Basis Technology Corp.
|
* Copyright 2013-2016 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -42,6 +42,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
*/
|
*/
|
||||||
class ContentTagNode extends DisplayableItemNode {
|
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 static final String ICON_PATH = "org/sleuthkit/autopsy/images/blue-tag-icon-16.png"; //NON-NLS
|
||||||
private final ContentTag tag;
|
private final ContentTag tag;
|
||||||
|
|
||||||
@ -60,7 +62,7 @@ class ContentTagNode extends DisplayableItemNode {
|
|||||||
try {
|
try {
|
||||||
contentPath = content.getUniquePath();
|
contentPath = content.getUniquePath();
|
||||||
} catch (TskCoreException ex) {
|
} 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");
|
contentPath = NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.unavail.path");
|
||||||
}
|
}
|
||||||
AbstractFile file = content instanceof AbstractFile ? (AbstractFile) content : null;
|
AbstractFile file = content instanceof AbstractFile ? (AbstractFile) content : null;
|
||||||
@ -103,6 +105,7 @@ class ContentTagNode extends DisplayableItemNode {
|
|||||||
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.displayName"),
|
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.displayName"),
|
||||||
"",
|
"",
|
||||||
content.getSize()));
|
content.getSize()));
|
||||||
|
|
||||||
return propertySheet;
|
return propertySheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +118,7 @@ class ContentTagNode extends DisplayableItemNode {
|
|||||||
if (file != null) {
|
if (file != null) {
|
||||||
actions.add(ViewFileInTimelineAction.createViewFileAction(file));
|
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());
|
actions.add(DeleteContentTagAction.getInstance());
|
||||||
return actions.toArray(new Action[actions.size()]);
|
return actions.toArray(new Action[actions.size()]);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2014 Basis Technology Corp.
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -23,6 +23,7 @@ import java.beans.PropertyChangeListener;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
@ -81,9 +82,9 @@ public class DataSourcesNode extends DisplayableItemNode {
|
|||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())
|
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
|| eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|
||||||
|| eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
|| eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||||
reloadKeys();
|
reloadKeys();
|
||||||
refreshContentKeys();
|
refreshContentKeys();
|
||||||
}
|
}
|
||||||
@ -112,7 +113,7 @@ public class DataSourcesNode extends DisplayableItemNode {
|
|||||||
currentKeys = Case.getCurrentCase().getDataSources();
|
currentKeys = Case.getCurrentCase().getDataSources();
|
||||||
setKeys(currentKeys);
|
setKeys(currentKeys);
|
||||||
} catch (TskCoreException | IllegalStateException ex) {
|
} 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.<Content>emptySet());
|
setKeys(Collections.<Content>emptySet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.De
|
|||||||
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode;
|
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode;
|
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode;
|
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,7 +58,7 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
*/
|
*/
|
||||||
T visit(ViewsNode vn);
|
T visit(ViewsNode vn);
|
||||||
|
|
||||||
T visit(FileTypeNode fsfn);
|
T visit(FileTypeByExtNode fsfn);
|
||||||
|
|
||||||
T visit(DeletedContentNode dcn);
|
T visit(DeletedContentNode dcn);
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
|
|
||||||
T visit(FileSizeNode fsn);
|
T visit(FileSizeNode fsn);
|
||||||
|
|
||||||
T visit(FileTypesNode sfn);
|
T visit(FileTypesByExtNode sfn);
|
||||||
|
|
||||||
T visit(RecentFilesNode rfn);
|
T visit(RecentFilesNode rfn);
|
||||||
|
|
||||||
@ -143,6 +144,17 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
|
|
||||||
T visit(Accounts.DefaultAccountTypeNode node);
|
T visit(Accounts.DefaultAccountTypeNode node);
|
||||||
|
|
||||||
|
T visit(FileTypes.FileTypesNode fileTypes);
|
||||||
|
|
||||||
|
T visit(FileTypesByMimeType.FileTypesByMimeTypeNode ftByMimeTypeNode);
|
||||||
|
|
||||||
|
T visit(FileTypesByMimeType.MediaTypeNode ftByMimeTypeMediaType);
|
||||||
|
|
||||||
|
T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaSubType);
|
||||||
|
|
||||||
|
T visit(FileTypesByMimeType.EmptyNode.MessageNode aThis);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visitor with an implementable default behavior for all types. Override
|
* Visitor with an implementable default behavior for all types. Override
|
||||||
* specific visit types to not use the default behavior.
|
* specific visit types to not use the default behavior.
|
||||||
@ -201,10 +213,30 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypeNode fsfn) {
|
public T visit(FileTypeByExtNode fsfn) {
|
||||||
return defaultVisit(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.MessageNode ftByMimeTypeEmptyNode) {
|
||||||
|
return defaultVisit(ftByMimeTypeEmptyNode);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(DeletedContentNode dcn) {
|
public T visit(DeletedContentNode dcn) {
|
||||||
return defaultVisit(dcn);
|
return defaultVisit(dcn);
|
||||||
@ -226,7 +258,7 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(FileTypesNode sfn) {
|
public T visit(FileTypesByExtNode sfn) {
|
||||||
return defaultVisit(sfn);
|
return defaultVisit(sfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +296,11 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
public T visit(ResultsNode rn) {
|
public T visit(ResultsNode rn) {
|
||||||
return defaultVisit(rn);
|
return defaultVisit(rn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T visit(FileTypesNode ft) {
|
||||||
|
return defaultVisit(ft);
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public T visit(DataSourcesNode in) {
|
public T visit(DataSourcesNode in) {
|
||||||
return defaultVisit(in);
|
return defaultVisit(in);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2014 Basis Technology Corp.
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -48,14 +48,14 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
* Node for a specific file type / extension. Children of it will be the files
|
* Node for a specific file type / extension. Children of it will be the files
|
||||||
* of that type.
|
* of that type.
|
||||||
*/
|
*/
|
||||||
public class FileTypeNode extends DisplayableItemNode {
|
public class FileTypeByExtNode extends DisplayableItemNode {
|
||||||
|
|
||||||
FileTypeExtensionFilters.SearchFilterInterface filter;
|
FileTypeExtensionFilters.SearchFilterInterface filter;
|
||||||
SleuthkitCase skCase;
|
SleuthkitCase skCase;
|
||||||
|
|
||||||
// deprecated in favor of the version that takes an observable to provide refresh updates
|
// deprecated in favor of the version that takes an observable to provide refresh updates
|
||||||
@Deprecated
|
@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()));
|
super(Children.create(new FileTypeChildFactory(filter, skCase), true), Lookups.singleton(filter.getDisplayName()));
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
@ -69,7 +69,7 @@ public class FileTypeNode extends DisplayableItemNode {
|
|||||||
* @param o Observable that sends updates when the child factories
|
* @param o Observable that sends updates when the child factories
|
||||||
* should refresh
|
* 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()));
|
super(Children.create(new FileTypeChildFactory(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName()));
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
103
Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java
Normal file
103
Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File Types node support
|
||||||
|
*/
|
||||||
|
public class FileTypes implements AutopsyVisitableItem {
|
||||||
|
|
||||||
|
private SleuthkitCase skCase;
|
||||||
|
|
||||||
|
FileTypes(SleuthkitCase skCase) {
|
||||||
|
this.skCase = skCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
SleuthkitCase getSleuthkitCase() {
|
||||||
|
return skCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Node which will contain By Mime Type and By Extension nodes.
|
||||||
|
*/
|
||||||
|
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> T accept(DisplayableItemNodeVisitor<T> 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -37,9 +37,9 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
|||||||
/**
|
/**
|
||||||
* Node for root of file types view. Children are nodes for specific types.
|
* 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;
|
private final FileTypeExtensionFilters.RootFilter filter;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -47,8 +47,8 @@ public class FileTypesNode extends DisplayableItemNode {
|
|||||||
* @param filter null to display root node of file type tree, pass in
|
* @param filter null to display root node of file type tree, pass in
|
||||||
* something to provide a sub-node.
|
* 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()));
|
super(Children.create(new FileTypesByExtChildren(skCase, filter, null), true), Lookups.singleton(filter == null ? FNAME : filter.getName()));
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@ -60,8 +60,8 @@ public class FileTypesNode extends DisplayableItemNode {
|
|||||||
* @param o Observable that was created by a higher-level node that
|
* @param o Observable that was created by a higher-level node that
|
||||||
* provides updates on events
|
* 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()));
|
super(Children.create(new FileTypesByExtChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getName()));
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@ -122,7 +122,7 @@ public class FileTypesNode extends DisplayableItemNode {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static class FileTypesChildren extends ChildFactory<FileTypeExtensionFilters.SearchFilterInterface> {
|
static class FileTypesByExtChildren extends ChildFactory<FileTypeExtensionFilters.SearchFilterInterface> {
|
||||||
|
|
||||||
private SleuthkitCase skCase;
|
private SleuthkitCase skCase;
|
||||||
private FileTypeExtensionFilters.RootFilter filter;
|
private FileTypeExtensionFilters.RootFilter filter;
|
||||||
@ -135,12 +135,12 @@ public class FileTypesNode extends DisplayableItemNode {
|
|||||||
* @param o Observable that provides updates based on events being
|
* @param o Observable that provides updates based on events being
|
||||||
* fired (or null if one needs to be created)
|
* 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();
|
super();
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
if (o == null) {
|
if (o == null) {
|
||||||
this.notifier = new FileTypesChildrenObservable();
|
this.notifier = new FileTypesByExtChildrenObservable();
|
||||||
} else {
|
} else {
|
||||||
this.notifier = o;
|
this.notifier = o;
|
||||||
}
|
}
|
||||||
@ -150,9 +150,9 @@ public class FileTypesNode extends DisplayableItemNode {
|
|||||||
* Listens for case and ingest invest. Updates observers when events are
|
* Listens for case and ingest invest. Updates observers when events are
|
||||||
* fired. FileType and FileTypes nodes are all listening to this.
|
* 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().addIngestJobEventListener(pcl);
|
||||||
IngestManager.getInstance().addIngestModuleEventListener(pcl);
|
IngestManager.getInstance().addIngestModuleEventListener(pcl);
|
||||||
Case.addPropertyChangeListener(pcl);
|
Case.addPropertyChangeListener(pcl);
|
||||||
@ -220,11 +220,11 @@ public class FileTypesNode extends DisplayableItemNode {
|
|||||||
protected Node createNodeForKey(FileTypeExtensionFilters.SearchFilterInterface key) {
|
protected Node createNodeForKey(FileTypeExtensionFilters.SearchFilterInterface key) {
|
||||||
// make new nodes for the sub-nodes
|
// make new nodes for the sub-nodes
|
||||||
if (key.getName().equals(FileTypeExtensionFilters.RootFilter.TSK_DOCUMENT_FILTER.getName())) {
|
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())) {
|
} 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 {
|
} else {
|
||||||
return new FileTypeNode(key, skCase, notifier);
|
return new FileTypeByExtNode(key, skCase, notifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,555 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
public class FileTypesByMimeType extends Observable implements AutopsyVisitableItem {
|
||||||
|
|
||||||
|
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
|
||||||
|
* type as the key and a list of media subtypes as the value.
|
||||||
|
*/
|
||||||
|
private final HashMap<String, List<String>> 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.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<String> getMediaTypeList() {
|
||||||
|
synchronized (existingMimeTypes) {
|
||||||
|
List<String> mediaTypes = new ArrayList<>(existingMimeTypes.keySet());
|
||||||
|
Collections.sort(mediaTypes);
|
||||||
|
return mediaTypes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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(",");
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getSleuthkitCase() == null) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try (SleuthkitCase.CaseDbQuery dbQuery = getSleuthkitCase().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);
|
||||||
|
FileTypesByMimeType.skCase = skCase;
|
||||||
|
populateHashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return skCase - the sluethkit case
|
||||||
|
*/
|
||||||
|
SleuthkitCase getSleuthkitCase() {
|
||||||
|
return skCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
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));
|
||||||
|
super.setName(NAME);
|
||||||
|
super.setDisplayName(NAME);
|
||||||
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLeafTypeNode() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getItemType() {
|
||||||
|
return getClass().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return existingMimeTypes.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<String> implements Observer {
|
||||||
|
|
||||||
|
public FileTypesByMimeTypeNodeChildren() {
|
||||||
|
super();
|
||||||
|
addObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean createKeys(List<String> mediaTypeNodes) {
|
||||||
|
if (!existingMimeTypes.isEmpty()) {
|
||||||
|
mediaTypeNodes.addAll(getMediaTypeList());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(String key) {
|
||||||
|
return new MediaTypeNode(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
refresh(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
|
||||||
|
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> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getItemType() {
|
||||||
|
return getClass().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<String> implements Observer {
|
||||||
|
|
||||||
|
String mediaType;
|
||||||
|
|
||||||
|
MediaTypeChildren(String name) {
|
||||||
|
addObserver(this);
|
||||||
|
this.mediaType = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean createKeys(List<String> mediaTypeNodes) {
|
||||||
|
mediaTypeNodes.addAll(existingMimeTypes.get(mediaType));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(String subtype) {
|
||||||
|
String mimeType = mediaType + "/" + subtype;
|
||||||
|
return new MediaSubTypeNode(mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
refresh(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 implements Observer {
|
||||||
|
|
||||||
|
private MediaSubTypeNode(String mimeType) {
|
||||||
|
super(Children.create(new MediaSubTypeNodeChildren(mimeType), true));
|
||||||
|
addObserver(this);
|
||||||
|
init(mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(String mimeType) {
|
||||||
|
super.setName(mimeType);
|
||||||
|
updateDisplayName(mimeType);
|
||||||
|
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 = new MediaSubTypeNodeChildren(mimeType).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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getItemType() {
|
||||||
|
return getClass().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
updateDisplayName(getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 class MediaSubTypeNodeChildren extends ChildFactory.Detachable<Content> implements Observer {
|
||||||
|
|
||||||
|
private final String mimeType;
|
||||||
|
|
||||||
|
MediaSubTypeNodeChildren(String mimeType) {
|
||||||
|
super();
|
||||||
|
addObserver(this);
|
||||||
|
this.mimeType = mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get children count without actually loading all nodes
|
||||||
|
*
|
||||||
|
* @return count(*) - the number of items that will be shown in this
|
||||||
|
* items Directory Listing
|
||||||
|
*/
|
||||||
|
private long calculateItems(SleuthkitCase sleuthkitCase, String mime_type) {
|
||||||
|
try {
|
||||||
|
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<Content> list) {
|
||||||
|
try {
|
||||||
|
List<AbstractFile> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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
|
||||||
|
}
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(Content key) {
|
||||||
|
return key.accept(new ContentVisitor.Default<AbstractNode>() {
|
||||||
|
@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()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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> {
|
||||||
|
|
||||||
|
String FILE_ID_MSG = "Data not available. Run file type identification module."; //NON-NLS
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean createKeys(List<String> list) {
|
||||||
|
list.add(FILE_ID_MSG);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(String key) {
|
||||||
|
return new MessageNode(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
super.setName(name);
|
||||||
|
setName(name);
|
||||||
|
setDisplayName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLeafTypeNode() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getItemType() {
|
||||||
|
return getClass().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2015 Basis Technology Corp.
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* 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 {
|
public class ListNode extends DisplayableItemNode implements Observer {
|
||||||
|
|
||||||
private String listName;
|
private final String listName;
|
||||||
|
|
||||||
public ListNode(String listName) {
|
public ListNode(String listName) {
|
||||||
super(Children.create(new TermFactory(listName), true), Lookups.singleton(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<String> implements Observer {
|
private class TermFactory extends ChildFactory.Detachable<String> implements Observer {
|
||||||
|
|
||||||
private String setName;
|
private final String setName;
|
||||||
|
|
||||||
private TermFactory(String setName) {
|
private TermFactory(String setName) {
|
||||||
super();
|
super();
|
||||||
@ -447,8 +447,8 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
public class TermNode extends DisplayableItemNode implements Observer {
|
public class TermNode extends DisplayableItemNode implements Observer {
|
||||||
|
|
||||||
private String setName;
|
private final String setName;
|
||||||
private String keyword;
|
private final String keyword;
|
||||||
|
|
||||||
public TermNode(String setName, String keyword) {
|
public TermNode(String setName, String keyword) {
|
||||||
super(Children.create(new HitsFactory(setName, keyword), true), Lookups.singleton(keyword));
|
super(Children.create(new HitsFactory(setName, keyword), true), Lookups.singleton(keyword));
|
||||||
@ -509,8 +509,8 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
public class HitsFactory extends ChildFactory.Detachable<Long> implements Observer {
|
public class HitsFactory extends ChildFactory.Detachable<Long> implements Observer {
|
||||||
|
|
||||||
private String keyword;
|
private final String keyword;
|
||||||
private String setName;
|
private final String setName;
|
||||||
|
|
||||||
public HitsFactory(String setName, String keyword) {
|
public HitsFactory(String setName, String keyword) {
|
||||||
super();
|
super();
|
||||||
|
@ -86,6 +86,9 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
|
|||||||
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
|
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add tags property to the sheet
|
||||||
|
addTagProperty(ss);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013-2014 Basis Technology Corp.
|
* Copyright 2013-2016 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -74,7 +75,9 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
|
|||||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||||
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
|
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
|
||||||
}
|
}
|
||||||
// @@@ add more properties here...
|
|
||||||
|
// add tags property to the sheet
|
||||||
|
addTagProperty(ss);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -82,9 +85,7 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
|
|||||||
@Override
|
@Override
|
||||||
public Action[] getActions(boolean context) {
|
public Action[] getActions(boolean context) {
|
||||||
List<Action> actionsList = new ArrayList<>();
|
List<Action> actionsList = new ArrayList<>();
|
||||||
for (Action a : super.getActions(true)) {
|
actionsList.addAll(Arrays.asList(super.getActions(true)));
|
||||||
actionsList.add(a);
|
|
||||||
}
|
|
||||||
actionsList.add(new ViewContextAction(NbBundle.getMessage(this.getClass(), "LocalFileNode.viewFileInDir.text"), this.content));
|
actionsList.add(new ViewContextAction(NbBundle.getMessage(this.getClass(), "LocalFileNode.viewFileInDir.text"), this.content));
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new NewWindowViewAction(
|
actionsList.add(new NewWindowViewAction(
|
||||||
|
@ -33,6 +33,8 @@ public class ResultsNode extends DisplayableItemNode {
|
|||||||
@NbBundle.Messages("ResultsNode.name.text=Results")
|
@NbBundle.Messages("ResultsNode.name.text=Results")
|
||||||
public static final String NAME = Bundle.ResultsNode_name_text();
|
public static final String NAME = Bundle.ResultsNode_name_text();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public ResultsNode(SleuthkitCase sleuthkitCase) {
|
public ResultsNode(SleuthkitCase sleuthkitCase) {
|
||||||
super(new RootContentChildren(Arrays.asList(
|
super(new RootContentChildren(Arrays.asList(
|
||||||
new ExtractedContent(sleuthkitCase),
|
new ExtractedContent(sleuthkitCase),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2015 Basis Technology Corp.
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -46,8 +46,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
* factory built on top of the NetBeans Children.Keys class.
|
* factory built on top of the NetBeans Children.Keys class.
|
||||||
*/
|
*/
|
||||||
public class Tags implements AutopsyVisitableItem {
|
public class Tags implements AutopsyVisitableItem {
|
||||||
// Creation of a RootNode object corresponding to a Tags object is done
|
// Creation of a RootNode object corresponding to a Tags object is done
|
||||||
// by a CreateAutopsyNodeVisitor dispatched from the AbstractContentChildren
|
// by a CreateAutopsyNodeVisitor dispatched from the AbstractContentChildren
|
||||||
// override of Children.Keys<T>.createNodes().
|
// override of Children.Keys<T>.createNodes().
|
||||||
|
|
||||||
private final TagResults tagResults = new TagResults();
|
private final TagResults tagResults = new TagResults();
|
||||||
@ -325,7 +325,7 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
public class ContentTagTypeNode extends DisplayableItemNode implements Observer {
|
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 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) {
|
public ContentTagTypeNode(TagName tagName) {
|
||||||
super(Children.create(new ContentTagNodeFactory(tagName), true), Lookups.singleton(tagName.getDisplayName() + " " + CONTENT_DISPLAY_NAME));
|
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 {
|
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
|
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
||||||
|
|
||||||
public BlackboardArtifactTagTypeNode(TagName tagName) {
|
public BlackboardArtifactTagTypeNode(TagName tagName) {
|
||||||
@ -505,7 +505,7 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
// The blackboard artifact tags to be wrapped are used as the keys.
|
// The blackboard artifact tags to be wrapped are used as the keys.
|
||||||
return new BlackboardArtifactTagNode(key);
|
return new BlackboardArtifactTagNode(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
refresh(true);
|
refresh(true);
|
||||||
|
@ -36,7 +36,7 @@ public class ViewsNode extends DisplayableItemNode {
|
|||||||
|
|
||||||
public ViewsNode(SleuthkitCase sleuthkitCase) {
|
public ViewsNode(SleuthkitCase sleuthkitCase) {
|
||||||
super(new RootContentChildren(Arrays.asList(
|
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
|
// 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.
|
// add it back in if we can filter the results to a more managable size.
|
||||||
// new RecentFiles(sleuthkitCase),
|
// new RecentFiles(sleuthkitCase),
|
||||||
|
@ -148,6 +148,7 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirect
|
|||||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||||
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
|
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
|
||||||
}
|
}
|
||||||
|
addTagProperty(ss);
|
||||||
} else {
|
} else {
|
||||||
ss.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_type_name(),
|
ss.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_type_name(),
|
||||||
Bundle.VirtualDirectoryNode_createSheet_type_displayName(),
|
Bundle.VirtualDirectoryNode_createSheet_type_displayName(),
|
||||||
|
@ -42,6 +42,7 @@ import org.sleuthkit.autopsy.datamodel.DirectoryNode;
|
|||||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileNode;
|
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
|
import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
|
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.Reports;
|
import org.sleuthkit.autopsy.datamodel.Reports;
|
||||||
@ -235,7 +236,13 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
// The base class Action is "Collapse All", inappropriate.
|
// The base class Action is "Collapse All", inappropriate.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Action> visit(FileTypesNode fileTypes) {
|
||||||
|
return defaultVisit(fileTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Action> defaultVisit(DisplayableItemNode ditem) {
|
protected List<Action> defaultVisit(DisplayableItemNode ditem) {
|
||||||
//preserve the default node's actions
|
//preserve the default node's actions
|
||||||
@ -275,6 +282,7 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -326,7 +334,14 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
protected AbstractAction defaultVisit(DisplayableItemNode c) {
|
protected AbstractAction defaultVisit(DisplayableItemNode c) {
|
||||||
return openChild(c);
|
return openChild(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractAction visit(FileTypesNode fileTypes) {
|
||||||
|
return openChild(fileTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the originating ExplorerManager to display the given
|
* Tell the originating ExplorerManager to display the given
|
||||||
* dataModelNode.
|
* dataModelNode.
|
||||||
|
@ -29,6 +29,7 @@ import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
|
|||||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileNode;
|
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
|
import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
|
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.SlackFileNode;
|
import org.sleuthkit.autopsy.datamodel.SlackFileNode;
|
||||||
@ -242,6 +243,12 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
|
|||||||
return visitDeep(vdn);
|
return visitDeep(vdn);
|
||||||
//return ! vdn.hasContentChildren();
|
//return ! vdn.hasContentChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean visit(FileTypesNode ft) {
|
||||||
|
return defaultVisit(ft);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ShowItemVisitor extends DisplayableItemNodeVisitor.Default<Boolean> {
|
private static class ShowItemVisitor extends DisplayableItemNodeVisitor.Default<Boolean> {
|
||||||
@ -284,5 +291,11 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
|
|||||||
return true;
|
return true;
|
||||||
//return vdn.hasContentChildren();
|
//return vdn.hasContentChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean visit(FileTypesNode fileTypes) {
|
||||||
|
return defaultVisit(fileTypes);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,9 @@ import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
|||||||
import org.sleuthkit.autopsy.datamodel.DataSources;
|
import org.sleuthkit.autopsy.datamodel.DataSources;
|
||||||
import org.sleuthkit.autopsy.datamodel.DataSourcesNode;
|
import org.sleuthkit.autopsy.datamodel.DataSourcesNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType.EmptyNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
|
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType;
|
||||||
import org.sleuthkit.autopsy.datamodel.KeywordHits;
|
import org.sleuthkit.autopsy.datamodel.KeywordHits;
|
||||||
import org.sleuthkit.autopsy.datamodel.KnownFileFilterNode;
|
import org.sleuthkit.autopsy.datamodel.KnownFileFilterNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.Reports;
|
import org.sleuthkit.autopsy.datamodel.Reports;
|
||||||
@ -364,7 +366,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
items.add(new Tags());
|
items.add(new Tags());
|
||||||
items.add(new Reports());
|
items.add(new Reports());
|
||||||
contentChildren = new RootContentChildren(items);
|
contentChildren = new RootContentChildren(items);
|
||||||
|
|
||||||
Node root = new AbstractNode(contentChildren) {
|
Node root = new AbstractNode(contentChildren) {
|
||||||
/**
|
/**
|
||||||
* to override the right click action in the white blank
|
* to override the right click action in the white blank
|
||||||
@ -635,6 +637,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
if (origin == null) {
|
if (origin == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node originNode = origin.getNode();
|
Node originNode = origin.getNode();
|
||||||
|
|
||||||
//set node, wrap in filter node first to filter out children
|
//set node, wrap in filter node first to filter out children
|
||||||
@ -644,7 +647,17 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
|
|
||||||
|
|
||||||
// Create a TableFilterNode with knowledge of the node's type to allow for column order settings
|
// 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));
|
||||||
|
Node emptySffn = new SlackFileFilterNode(emptyKffn, SlackFileFilterNode.getSelectionContext(originNode));
|
||||||
|
dataResult.setNode(new TableFilterNode(emptySffn, true, "This Node Is Empty"));
|
||||||
|
} else if (originNode instanceof DisplayableItemNode) {
|
||||||
dataResult.setNode(new TableFilterNode(sffn, true, ((DisplayableItemNode) originNode).getItemType()));
|
dataResult.setNode(new TableFilterNode(sffn, true, ((DisplayableItemNode) originNode).getItemType()));
|
||||||
} else {
|
} else {
|
||||||
dataResult.setNode(new TableFilterNode(sffn, true));
|
dataResult.setNode(new TableFilterNode(sffn, true));
|
||||||
@ -788,8 +801,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
* Set the selected node using a path to a previously selected node.
|
* Set the selected node using a path to a previously selected node.
|
||||||
*
|
*
|
||||||
* @param previouslySelectedNodePath 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
|
* @param rootNodeName Name of the root node to match, may be null.
|
||||||
* null.
|
|
||||||
*/
|
*/
|
||||||
private void setSelectedNode(final String[] previouslySelectedNodePath, final String rootNodeName) {
|
private void setSelectedNode(final String[] previouslySelectedNodePath, final String rootNodeName) {
|
||||||
if (previouslySelectedNodePath == null) {
|
if (previouslySelectedNodePath == null) {
|
||||||
|
@ -1,31 +1,35 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* Autopsy Forensic Browser
|
||||||
* To change this template file, choose Tools | Templates
|
*
|
||||||
* and open the template in the editor.
|
* Copyright 2011-2016 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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;
|
package org.sleuthkit.autopsy.filesearch;
|
||||||
|
|
||||||
import java.beans.PropertyChangeListener;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
import javax.swing.event.ListSelectionListener;
|
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.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author oliver
|
|
||||||
*/
|
|
||||||
public class MimeTypePanel extends javax.swing.JPanel {
|
public class MimeTypePanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final SortedSet<MediaType> mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes();
|
|
||||||
private static final Logger logger = Logger.getLogger(MimeTypePanel.class.getName());
|
private static final Logger logger = Logger.getLogger(MimeTypePanel.class.getName());
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ -45,8 +49,8 @@ public class MimeTypePanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
private String[] getMimeTypeArray() {
|
private String[] getMimeTypeArray() {
|
||||||
Set<String> fileTypesCollated = new HashSet<>();
|
Set<String> fileTypesCollated = new HashSet<>();
|
||||||
for (MediaType mediaType : mediaTypes) {
|
for (String mediaType : FileTypeDetector.getStandardDetectedTypes()) {
|
||||||
fileTypesCollated.add(mediaType.toString());
|
fileTypesCollated.add(mediaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileTypeDetector fileTypeDetector;
|
FileTypeDetector fileTypeDetector;
|
||||||
@ -78,7 +82,7 @@ public class MimeTypePanel extends javax.swing.JPanel {
|
|||||||
boolean isSelected() {
|
boolean isSelected() {
|
||||||
return this.mimeTypeCheckBox.isSelected();
|
return this.mimeTypeCheckBox.isSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setComponentsEnabled() {
|
void setComponentsEnabled() {
|
||||||
boolean enabled = this.isSelected();
|
boolean enabled = this.isSelected();
|
||||||
this.mimeTypeList.setEnabled(enabled);
|
this.mimeTypeList.setEnabled(enabled);
|
||||||
|
@ -159,7 +159,7 @@ final class DataSourceIngestJob {
|
|||||||
private ProgressHandle fileIngestProgress;
|
private ProgressHandle fileIngestProgress;
|
||||||
private String currentFileIngestModule = "";
|
private String currentFileIngestModule = "";
|
||||||
private String currentFileIngestTask = "";
|
private String currentFileIngestTask = "";
|
||||||
private List<IngestModuleInfo> ingestModules = new ArrayList<>();
|
private final List<IngestModuleInfo> ingestModules = new ArrayList<>();
|
||||||
private IngestJobInfo ingestJob;
|
private IngestJobInfo ingestJob;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -171,12 +171,12 @@ final class DataSourceIngestJob {
|
|||||||
* Constructs an object that encapsulates a data source and the ingest
|
* Constructs an object that encapsulates a data source and the ingest
|
||||||
* module pipelines used to process it.
|
* module pipelines used to process it.
|
||||||
*
|
*
|
||||||
* @param parentJob The ingest job of which this data source ingest
|
* @param parentJob The ingest job of which this data source ingest job is a
|
||||||
* job is a part.
|
* part.
|
||||||
* @param dataSource The data source to be ingested.
|
* @param dataSource The data source to be ingested.
|
||||||
* @param settings The settings for the ingest job.
|
* @param settings The settings for the ingest job.
|
||||||
* @param runInteractively Whether or not this job should use NetBeans
|
* @param runInteractively Whether or not this job should use NetBeans
|
||||||
* progress handles.
|
* progress handles.
|
||||||
*/
|
*/
|
||||||
DataSourceIngestJob(IngestJob parentJob, Content dataSource, IngestJobSettings settings, boolean runInteractively) {
|
DataSourceIngestJob(IngestJob parentJob, Content dataSource, IngestJobSettings settings, boolean runInteractively) {
|
||||||
this.parentJob = parentJob;
|
this.parentJob = parentJob;
|
||||||
@ -277,12 +277,12 @@ final class DataSourceIngestJob {
|
|||||||
* collection as they are added to the output collection.
|
* collection as they are added to the output collection.
|
||||||
*
|
*
|
||||||
* @param ingestModuleTemplates A mapping of ingest module factory class
|
* @param ingestModuleTemplates A mapping of ingest module factory class
|
||||||
* names to ingest module templates.
|
* names to ingest module templates.
|
||||||
* @param pipelineConfig An ordered list of ingest module factory
|
* @param pipelineConfig An ordered list of ingest module factory class
|
||||||
* class names representing an ingest pipeline.
|
* names representing an ingest pipeline.
|
||||||
*
|
*
|
||||||
* @return An ordered list of ingest module templates, i.e., an
|
* @return An ordered list of ingest module templates, i.e., an
|
||||||
* uninstantiated pipeline.
|
* uninstantiated pipeline.
|
||||||
*/
|
*/
|
||||||
private static List<IngestModuleTemplate> getConfiguredIngestModuleTemplates(Map<String, IngestModuleTemplate> ingestModuleTemplates, List<String> pipelineConfig) {
|
private static List<IngestModuleTemplate> getConfiguredIngestModuleTemplates(Map<String, IngestModuleTemplate> ingestModuleTemplates, List<String> pipelineConfig) {
|
||||||
List<IngestModuleTemplate> templates = new ArrayList<>();
|
List<IngestModuleTemplate> templates = new ArrayList<>();
|
||||||
@ -331,16 +331,6 @@ final class DataSourceIngestJob {
|
|||||||
return this.settings.getProcessUnallocatedSpace();
|
return this.settings.getProcessUnallocatedSpace();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Queries whether or not unallocated space should be processed as part of
|
|
||||||
* this job.
|
|
||||||
*
|
|
||||||
* @return True or false.
|
|
||||||
*/
|
|
||||||
String runIngestModulesOnFilter() {
|
|
||||||
return this.settings.getRunIngestModulesOnFilter();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to see if this job has at least one ingest pipeline.
|
* Checks to see if this job has at least one ingest pipeline.
|
||||||
*
|
*
|
||||||
@ -746,9 +736,8 @@ final class DataSourceIngestJob {
|
|||||||
* @param task A file ingest task.
|
* @param task A file ingest task.
|
||||||
*
|
*
|
||||||
* @throws InterruptedException if the thread executing this code is
|
* @throws InterruptedException if the thread executing this code is
|
||||||
* interrupted while blocked on taking from or
|
* interrupted while blocked on taking from or putting to the file ingest
|
||||||
* putting to the file ingest pipelines
|
* pipelines collection.
|
||||||
* collection.
|
|
||||||
*/
|
*/
|
||||||
void process(FileIngestTask task) throws InterruptedException {
|
void process(FileIngestTask task) throws InterruptedException {
|
||||||
try {
|
try {
|
||||||
@ -849,7 +838,7 @@ final class DataSourceIngestJob {
|
|||||||
* process the data source is known.
|
* process the data source is known.
|
||||||
*
|
*
|
||||||
* @param workUnits Total number of work units for the processing of the
|
* @param workUnits Total number of work units for the processing of the
|
||||||
* data source.
|
* data source.
|
||||||
*/
|
*/
|
||||||
void switchDataSourceIngestProgressBarToDeterminate(int workUnits) {
|
void switchDataSourceIngestProgressBarToDeterminate(int workUnits) {
|
||||||
if (this.doUI && !this.cancelled) {
|
if (this.doUI && !this.cancelled) {
|
||||||
@ -914,7 +903,7 @@ final class DataSourceIngestJob {
|
|||||||
* mode. The task name is the "subtitle" under the display name.
|
* mode. The task name is the "subtitle" under the display name.
|
||||||
*
|
*
|
||||||
* @param currentTask The task name.
|
* @param currentTask The task name.
|
||||||
* @param workUnits Number of work units performed.
|
* @param workUnits Number of work units performed.
|
||||||
*/
|
*/
|
||||||
void advanceDataSourceIngestProgressBar(String currentTask, int workUnits) {
|
void advanceDataSourceIngestProgressBar(String currentTask, int workUnits) {
|
||||||
if (this.doUI && !this.cancelled) {
|
if (this.doUI && !this.cancelled) {
|
||||||
@ -1056,7 +1045,7 @@ final class DataSourceIngestJob {
|
|||||||
* To be used for more detailed cancelling.
|
* To be used for more detailed cancelling.
|
||||||
*
|
*
|
||||||
* @param moduleName Name of module currently running.
|
* @param moduleName Name of module currently running.
|
||||||
* @param taskName Name of file the module is running on.
|
* @param taskName Name of file the module is running on.
|
||||||
*/
|
*/
|
||||||
void setCurrentFileIngestModule(String moduleName, String taskName) {
|
void setCurrentFileIngestModule(String moduleName, String taskName) {
|
||||||
this.currentFileIngestModule = moduleName;
|
this.currentFileIngestModule = moduleName;
|
||||||
@ -1170,7 +1159,7 @@ final class DataSourceIngestJob {
|
|||||||
* Gets time these statistics were collected.
|
* Gets time these statistics were collected.
|
||||||
*
|
*
|
||||||
* @return The statistics collection time as number of milliseconds
|
* @return The statistics collection time as number of milliseconds
|
||||||
* since January 1, 1970, 00:00:00 GMT.
|
* since January 1, 1970, 00:00:00 GMT.
|
||||||
*/
|
*/
|
||||||
long getSnapshotTime() {
|
long getSnapshotTime() {
|
||||||
return snapShotTime;
|
return snapShotTime;
|
||||||
@ -1200,7 +1189,7 @@ final class DataSourceIngestJob {
|
|||||||
* Gets the time the ingest job was started.
|
* Gets the time the ingest job was started.
|
||||||
*
|
*
|
||||||
* @return The start time as number of milliseconds since January 1,
|
* @return The start time as number of milliseconds since January 1,
|
||||||
* 1970, 00:00:00 GMT.
|
* 1970, 00:00:00 GMT.
|
||||||
*/
|
*/
|
||||||
long getJobStartTime() {
|
long getJobStartTime() {
|
||||||
return jobStartTime;
|
return jobStartTime;
|
||||||
@ -1300,7 +1289,7 @@ final class DataSourceIngestJob {
|
|||||||
* ingest modules
|
* ingest modules
|
||||||
*
|
*
|
||||||
* @return A list of canceled data source level ingest module display
|
* @return A list of canceled data source level ingest module display
|
||||||
* names, possibly empty.
|
* names, possibly empty.
|
||||||
*/
|
*/
|
||||||
List<String> getCancelledDataSourceIngestModules() {
|
List<String> getCancelledDataSourceIngestModules() {
|
||||||
return Collections.unmodifiableList(this.cancelledDataSourceModules);
|
return Collections.unmodifiableList(this.cancelledDataSourceModules);
|
||||||
|
@ -19,11 +19,13 @@
|
|||||||
package org.sleuthkit.autopsy.modules.filetypeid;
|
package org.sleuthkit.autopsy.modules.filetypeid;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import org.apache.tika.Tika;
|
import org.apache.tika.Tika;
|
||||||
import org.apache.tika.mime.MediaType;
|
|
||||||
import org.apache.tika.mime.MimeTypes;
|
import org.apache.tika.mime.MimeTypes;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
@ -49,6 +51,7 @@ public class FileTypeDetector {
|
|||||||
private final byte buffer[] = new byte[BUFFER_SIZE];
|
private final byte buffer[] = new byte[BUFFER_SIZE];
|
||||||
private final List<FileType> userDefinedFileTypes;
|
private final List<FileType> userDefinedFileTypes;
|
||||||
private final List<FileType> autopsyDefinedFileTypes;
|
private final List<FileType> autopsyDefinedFileTypes;
|
||||||
|
private static SortedSet<String> detectedTypes; //no optional parameters
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an object that detects the MIME type of a file by an
|
* Constructs an object that detects the MIME type of a file by an
|
||||||
@ -100,6 +103,21 @@ public class FileTypeDetector {
|
|||||||
|| isDetectableByTika(mimeType);
|
|| isDetectableByTika(mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<String> 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));
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableSortedSet(detectedTypes);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether or not a given MIME type is detectable as a
|
* Determines whether or not a given MIME type is detectable as a
|
||||||
* user-defined MIME type by this detector.
|
* user-defined MIME type by this detector.
|
||||||
@ -126,15 +144,7 @@ public class FileTypeDetector {
|
|||||||
* @return True or false.
|
* @return True or false.
|
||||||
*/
|
*/
|
||||||
private boolean isDetectableByTika(String mimeType) {
|
private boolean isDetectableByTika(String mimeType) {
|
||||||
String[] split = mimeType.split("/");
|
return FileTypeDetector.getStandardDetectedTypes().contains(removeOptionalParameter(mimeType));
|
||||||
if (split.length == 2) {
|
|
||||||
String type = split[0];
|
|
||||||
String subtype = split[1];
|
|
||||||
MediaType mediaType = new MediaType(type, subtype);
|
|
||||||
SortedSet<MediaType> m = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes();
|
|
||||||
return m.contains(mediaType);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -196,7 +206,10 @@ public class FileTypeDetector {
|
|||||||
*/
|
*/
|
||||||
String mimeType = file.getMIMEType();
|
String mimeType = file.getMIMEType();
|
||||||
if (null != mimeType) {
|
if (null != mimeType) {
|
||||||
return 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -248,6 +261,10 @@ public class FileTypeDetector {
|
|||||||
* Remove the Tika suffix from the MIME type name.
|
* Remove the Tika suffix from the MIME type name.
|
||||||
*/
|
*/
|
||||||
mimeType = tikaType.replace("tika-", ""); //NON-NLS
|
mimeType = tikaType.replace("tika-", ""); //NON-NLS
|
||||||
|
/*
|
||||||
|
* Remove the optional parameter from the MIME type.
|
||||||
|
*/
|
||||||
|
mimeType = removeOptionalParameter(mimeType);
|
||||||
|
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
/*
|
/*
|
||||||
@ -288,6 +305,20 @@ public class FileTypeDetector {
|
|||||||
return mimeType;
|
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
|
* Determines whether or not the a file matches a user-defined custom file
|
||||||
* type.
|
* type.
|
||||||
|
@ -24,9 +24,6 @@ import org.apache.tika.mime.MediaType;
|
|||||||
import org.apache.tika.mime.MimeTypes;
|
import org.apache.tika.mime.MimeTypes;
|
||||||
|
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
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
|
* @deprecated Use org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2014 Basis Technology Corp.
|
* Copyright 2014-2016 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -24,15 +24,12 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.regex.PatternSyntaxException;
|
import java.util.regex.PatternSyntaxException;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import org.apache.tika.mime.MediaType;
|
|
||||||
import org.apache.tika.mime.MimeTypes;
|
|
||||||
import org.openide.DialogDisplayer;
|
import org.openide.DialogDisplayer;
|
||||||
import org.openide.NotifyDescriptor;
|
import org.openide.NotifyDescriptor;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
@ -58,7 +55,6 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
"FilesSetRulePanel.ZeroFileSizeError=File size condition value must not be 0 (Unless = is selected)."
|
"FilesSetRulePanel.ZeroFileSizeError=File size condition value must not be 0 (Unless = is selected)."
|
||||||
})
|
})
|
||||||
|
|
||||||
private static final SortedSet<MediaType> mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes();
|
|
||||||
private static final Logger logger = Logger.getLogger(FilesSetRulePanel.class.getName());
|
private static final Logger logger = Logger.getLogger(FilesSetRulePanel.class.getName());
|
||||||
private static final String SLEUTHKIT_PATH_SEPARATOR = "/"; // NON-NLS
|
private static final String SLEUTHKIT_PATH_SEPARATOR = "/"; // NON-NLS
|
||||||
private static final List<String> ILLEGAL_FILE_NAME_CHARS = InterestingItemDefsManager.getIllegalFileNameChars();
|
private static final List<String> ILLEGAL_FILE_NAME_CHARS = InterestingItemDefsManager.getIllegalFileNameChars();
|
||||||
@ -112,8 +108,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
private void populateMimeTypesComboBox() {
|
private void populateMimeTypesComboBox() {
|
||||||
Set<String> fileTypesCollated = new HashSet<>();
|
Set<String> fileTypesCollated = new HashSet<>();
|
||||||
for (MediaType mediaType : mediaTypes) {
|
for (String mediaType : FileTypeDetector.getStandardDetectedTypes()) {
|
||||||
fileTypesCollated.add(mediaType.toString());
|
fileTypesCollated.add(mediaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileTypeDetector fileTypeDetector;
|
FileTypeDetector fileTypeDetector;
|
||||||
@ -327,7 +323,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.
|
// that compiles or a string without illegal file path chars.
|
||||||
if (this.pathCheck.isSelected()) {
|
if (this.pathCheck.isSelected()) {
|
||||||
if (this.pathTextField.getText().isEmpty()) {
|
if (this.pathTextField.getText().isEmpty()) {
|
||||||
@ -418,7 +414,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.log(Level.SEVERE, "Attempt to get name condition with illegal chars"); // NON-NLS
|
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;
|
return condition;
|
||||||
@ -504,7 +500,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
condition = new FilesSet.Rule.ParentPathCondition(path);
|
condition = new FilesSet.Rule.ParentPathCondition(path);
|
||||||
} else {
|
} else {
|
||||||
logger.log(Level.SEVERE, "Attempt to get path condition with illegal chars"); // NON-NLS
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.DefaultListModel;
|
import javax.swing.DefaultListModel;
|
||||||
@ -33,8 +32,6 @@ import javax.swing.JButton;
|
|||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
import javax.swing.event.ListSelectionListener;
|
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.netbeans.spi.options.OptionsPanelController;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
|
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
|
||||||
@ -58,7 +55,6 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
"IngestFileFilter.title=Ingest File Set"
|
"IngestFileFilter.title=Ingest File Set"
|
||||||
})
|
})
|
||||||
|
|
||||||
private static final SortedSet<MediaType> MEDIA_TYPES = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes();
|
|
||||||
private final DefaultListModel<FilesSet> setsListModel = new DefaultListModel<>();
|
private final DefaultListModel<FilesSet> setsListModel = new DefaultListModel<>();
|
||||||
private final DefaultListModel<FilesSet.Rule> rulesListModel = new DefaultListModel<>();
|
private final DefaultListModel<FilesSet.Rule> rulesListModel = new DefaultListModel<>();
|
||||||
private final Logger logger = Logger.getLogger(InterestingItemDefsPanel.class.getName());
|
private final Logger logger = Logger.getLogger(InterestingItemDefsPanel.class.getName());
|
||||||
@ -68,9 +64,9 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
private final String settingsLegacyFileName;
|
private final String settingsLegacyFileName;
|
||||||
private final String ruleDialogTitle;
|
private final String ruleDialogTitle;
|
||||||
|
|
||||||
// The following is a map of interesting files set names to interesting
|
// The following is a map of interesting files set names to interesting
|
||||||
// files set definitions. It is a snapshot of the files set definitions
|
// files set definitions. It is a snapshot of the files set definitions
|
||||||
// obtained from the interesting item definitions manager at the time the
|
// obtained from the interesting item definitions manager at the time the
|
||||||
// the panel is loaded. When the panel saves or stores its settings, these
|
// the panel is loaded. When the panel saves or stores its settings, these
|
||||||
// definitions, possibly changed, are submitted back to the interesting item
|
// definitions, possibly changed, are submitted back to the interesting item
|
||||||
// definitions manager. Note that it is a tree map to aid in displaying
|
// definitions manager. Note that it is a tree map to aid in displaying
|
||||||
@ -113,9 +109,11 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
} else {
|
} else {
|
||||||
setName(Bundle.InterestingItemDefsPanel_Title());
|
setName(Bundle.InterestingItemDefsPanel_Title());
|
||||||
}
|
}
|
||||||
|
setName(Bundle.InterestingItemDefsPanel_Title());
|
||||||
|
|
||||||
Set<String> fileTypesCollated = new HashSet<>();
|
Set<String> fileTypesCollated = new HashSet<>();
|
||||||
for (MediaType mediaType : MEDIA_TYPES) {
|
for (String mediaType : FileTypeDetector.getStandardDetectedTypes()) {
|
||||||
fileTypesCollated.add(mediaType.toString());
|
fileTypesCollated.add(mediaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileTypeDetector fileTypeDetector;
|
FileTypeDetector fileTypeDetector;
|
||||||
@ -180,14 +178,14 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
this.filesSets = new TreeMap<>();
|
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.
|
// component.
|
||||||
for (FilesSet set : this.filesSets.values()) {
|
for (FilesSet set : this.filesSets.values()) {
|
||||||
this.setsListModel.addElement(set);
|
this.setsListModel.addElement(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.filesSets.isEmpty()) {
|
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.
|
// listeners will then populate the other components.
|
||||||
EventQueue.invokeLater(() -> {
|
EventQueue.invokeLater(() -> {
|
||||||
InterestingItemDefsPanel.this.setsList.setSelectedIndex(0);
|
InterestingItemDefsPanel.this.setsList.setSelectedIndex(0);
|
||||||
@ -247,7 +245,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
// components.
|
// components.
|
||||||
FilesSet selectedSet = InterestingItemDefsPanel.this.setsList.getSelectedValue();
|
FilesSet selectedSet = InterestingItemDefsPanel.this.setsList.getSelectedValue();
|
||||||
if (selectedSet != null) {
|
if (selectedSet != null) {
|
||||||
// Populate the components that display the properties of the
|
// Populate the components that display the properties of the
|
||||||
// selected files set.
|
// selected files set.
|
||||||
InterestingItemDefsPanel.this.setDescriptionTextArea.setText(selectedSet.getDescription());
|
InterestingItemDefsPanel.this.setDescriptionTextArea.setText(selectedSet.getDescription());
|
||||||
InterestingItemDefsPanel.this.ignoreKnownFilesCheckbox.setSelected(selectedSet.ignoresKnownFiles());
|
InterestingItemDefsPanel.this.ignoreKnownFilesCheckbox.setSelected(selectedSet.ignoresKnownFiles());
|
||||||
@ -294,7 +292,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
FilesSet.Rule.MimeTypeCondition mimeTypeCondition = rule.getMimeTypeCondition();
|
FilesSet.Rule.MimeTypeCondition mimeTypeCondition = rule.getMimeTypeCondition();
|
||||||
FilesSet.Rule.FileSizeCondition fileSizeCondition = rule.getFileSizeCondition();
|
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.
|
// selected rule.
|
||||||
if (nameCondition != null) {
|
if (nameCondition != null) {
|
||||||
InterestingItemDefsPanel.this.fileNameTextField.setText(nameCondition.getTextToMatch());
|
InterestingItemDefsPanel.this.fileNameTextField.setText(nameCondition.getTextToMatch());
|
||||||
@ -369,7 +367,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
panel = new FilesSetPanel();
|
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
|
// a valid definition or cancels. Note that the panel gives the user
|
||||||
// feedback when isValidDefinition() is called.
|
// feedback when isValidDefinition() is called.
|
||||||
int option = JOptionPane.OK_OPTION;
|
int option = JOptionPane.OK_OPTION;
|
||||||
@ -390,7 +388,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
Map<String, FilesSet.Rule> rules = new HashMap<>();
|
Map<String, FilesSet.Rule> rules = new HashMap<>();
|
||||||
if (selectedSet != null) {
|
if (selectedSet != null) {
|
||||||
// Interesting file sets are immutable for thread safety,
|
// 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.
|
// Preserve the existing rules from the set being edited.
|
||||||
rules.putAll(selectedSet.getRules());
|
rules.putAll(selectedSet.getRules());
|
||||||
}
|
}
|
||||||
@ -415,7 +413,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
// Creating a new rule definition.
|
// Creating a new rule definition.
|
||||||
panel = new FilesSetRulePanel(okButton, cancelButton, (settingsLegacyFileName.equals("")));
|
panel = new FilesSetRulePanel(okButton, cancelButton, (settingsLegacyFileName.equals("")));
|
||||||
}
|
}
|
||||||
// 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
|
// a valid definition or cancels. Note that the panel gives the user
|
||||||
// feedback when isValidDefinition() is called.
|
// feedback when isValidDefinition() is called.
|
||||||
int option = JOptionPane.OK_OPTION;
|
int option = JOptionPane.OK_OPTION;
|
||||||
@ -425,12 +423,12 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
|
|
||||||
if (option == JOptionPane.OK_OPTION) {
|
if (option == JOptionPane.OK_OPTION) {
|
||||||
// Interesting file sets are immutable for thread safety,
|
// 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.
|
// operation. Preserve the existing rules from the set being edited.
|
||||||
FilesSet selectedSet = this.setsList.getSelectedValue();
|
FilesSet selectedSet = this.setsList.getSelectedValue();
|
||||||
Map<String, FilesSet.Rule> rules = new HashMap<>(selectedSet.getRules());
|
Map<String, FilesSet.Rule> 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.
|
// definition.
|
||||||
if (selectedRule != null) {
|
if (selectedRule != null) {
|
||||||
rules.remove(selectedRule.getUuid());
|
rules.remove(selectedRule.getUuid());
|
||||||
@ -438,19 +436,18 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
FilesSet.Rule newRule = new FilesSet.Rule(panel.getRuleName(), panel.getFileNameCondition(), panel.getMetaTypeCondition(), panel.getPathCondition(), panel.getMimeTypeCondition(), panel.getFileSizeCondition());
|
FilesSet.Rule newRule = new FilesSet.Rule(panel.getRuleName(), panel.getFileNameCondition(), panel.getMetaTypeCondition(), panel.getPathCondition(), panel.getMimeTypeCondition(), panel.getFileSizeCondition());
|
||||||
rules.put(newRule.getUuid(), newRule);
|
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.
|
// definition with the same name and refreshing the display.
|
||||||
this.replaceFilesSet(selectedSet, selectedSet.getName(), selectedSet.getDescription(), selectedSet.ignoresKnownFiles(), rules, selectedSet.processesUnallocatedSpace());
|
this.replaceFilesSet(selectedSet, selectedSet.getName(), selectedSet.getDescription(), selectedSet.ignoresKnownFiles(), rules, selectedSet.processesUnallocatedSpace());
|
||||||
|
|
||||||
// Select the new/edited rule. Queue it up so it happens after the
|
// Select the new/edited rule. Queue it up so it happens after the
|
||||||
// selection listeners react to the selection of the "new" files
|
// selection listeners react to the selection of the "new" files
|
||||||
// set.
|
// set.
|
||||||
EventQueue.invokeLater(() -> {
|
EventQueue.invokeLater(() -> {
|
||||||
this.rulesList.setSelectedValue(newRule, true);
|
this.rulesList.setSelectedValue(newRule, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an interesting files set definition to the collection of definitions
|
* Adds an interesting files set definition to the collection of definitions
|
||||||
@ -463,8 +460,8 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
* @param ignoresKnownFiles Whether or not the files set ignores known
|
* @param ignoresKnownFiles Whether or not the files set ignores known
|
||||||
* files.
|
* files.
|
||||||
* @param rules The set membership rules for the set.
|
* @param rules The set membership rules for the set.
|
||||||
* @param processesUnallocatedSpace Whether or not this set of rules processes
|
* @param processesUnallocatedSpace Whether or not this set of rules
|
||||||
* unallocated space
|
* processes unallocated space
|
||||||
*/
|
*/
|
||||||
void replaceFilesSet(FilesSet oldSet, String name, String description, boolean ignoresKnownFiles, Map<String, FilesSet.Rule> rules, boolean processesUnallocatedSpace) {
|
void replaceFilesSet(FilesSet oldSet, String name, String description, boolean ignoresKnownFiles, Map<String, FilesSet.Rule> rules, boolean processesUnallocatedSpace) {
|
||||||
if (oldSet != null) {
|
if (oldSet != null) {
|
||||||
@ -485,8 +482,8 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
this.setsListModel.addElement(set);
|
this.setsListModel.addElement(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select the new/edited files set definition in the set definitions
|
// Select the new/edited files set definition in the set definitions
|
||||||
// list. This will cause the selection listeners to repopulate the
|
// list. This will cause the selection listeners to repopulate the
|
||||||
// subordinate components.
|
// subordinate components.
|
||||||
this.setsList.setSelectedValue(newSet, true);
|
this.setsList.setSelectedValue(newSet, true);
|
||||||
}
|
}
|
||||||
@ -496,7 +493,6 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
* WARNING: Do NOT modify this code. The content of this method is always
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
* regenerated by the Form Editor.
|
* regenerated by the Form Editor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
|
@ -31,6 +31,8 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
import org.apache.solr.client.solrj.SolrQuery;
|
import org.apache.solr.client.solrj.SolrQuery;
|
||||||
import org.apache.solr.client.solrj.SolrRequest.METHOD;
|
import org.apache.solr.client.solrj.SolrRequest.METHOD;
|
||||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
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.coreutils.Version;
|
||||||
import org.sleuthkit.autopsy.datamodel.TextMarkupLookup;
|
import org.sleuthkit.autopsy.datamodel.TextMarkupLookup;
|
||||||
import org.sleuthkit.autopsy.keywordsearch.KeywordQueryFilter.FilterType;
|
import org.sleuthkit.autopsy.keywordsearch.KeywordQueryFilter.FilterType;
|
||||||
@ -100,6 +102,7 @@ class HighlightedText implements IndexedText, TextMarkupLookup {
|
|||||||
* The main goal of this method is to figure out which pages / chunks have
|
* The main goal of this method is to figure out which pages / chunks have
|
||||||
* hits.
|
* hits.
|
||||||
*/
|
*/
|
||||||
|
@Messages({"HighlightedText.query.exception.msg=Could not perform the query to get chunk info and get highlights:"})
|
||||||
private void loadPageInfo() {
|
private void loadPageInfo() {
|
||||||
if (isPageInfoLoaded) {
|
if (isPageInfoLoaded) {
|
||||||
return;
|
return;
|
||||||
@ -143,8 +146,9 @@ class HighlightedText implements IndexedText, TextMarkupLookup {
|
|||||||
chunksQuery.addFilter(new KeywordQueryFilter(FilterType.CHUNK, this.objectId));
|
chunksQuery.addFilter(new KeywordQueryFilter(FilterType.CHUNK, this.objectId));
|
||||||
try {
|
try {
|
||||||
hits = chunksQuery.performQuery();
|
hits = chunksQuery.performQuery();
|
||||||
} catch (NoOpenCoreException ex) {
|
} catch (KeywordSearchModuleException | NoOpenCoreException ex) {
|
||||||
logger.log(Level.INFO, "Could not get chunk info and get highlights", ex); //NON-NLS
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,12 @@ interface KeywordSearchQuery {
|
|||||||
* execute query and return results without publishing them return results
|
* execute query and return results without publishing them return results
|
||||||
* for all matching terms
|
* for all matching terms
|
||||||
*
|
*
|
||||||
|
* @throws KeywordSearchModuleException error while executing Solr term query
|
||||||
* @throws NoOpenCoreException if query failed due to server error, this
|
* @throws NoOpenCoreException if query failed due to server error, this
|
||||||
* could be a notification to stop processing
|
* could be a notification to stop processing
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
QueryResults performQuery() throws NoOpenCoreException;
|
QueryResults performQuery() throws KeywordSearchModuleException, NoOpenCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an optional filter to narrow down the search Adding multiple filters
|
* Set an optional filter to narrow down the search Adding multiple filters
|
||||||
|
@ -38,6 +38,7 @@ import org.openide.util.NbBundle;
|
|||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
|
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
|
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.KeyValue;
|
import org.sleuthkit.autopsy.datamodel.KeyValue;
|
||||||
@ -142,6 +143,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@NbBundle.Messages({"KeywordSearchResultFactory.query.exception.msg=Could not perform the query "})
|
||||||
private boolean createFlatKeys(QueryRequest queryRequest, List<KeyValueQueryContent> toPopulate) {
|
private boolean createFlatKeys(QueryRequest queryRequest, List<KeyValueQueryContent> toPopulate) {
|
||||||
/**
|
/**
|
||||||
* Check the validity of the requested query.
|
* Check the validity of the requested query.
|
||||||
@ -158,10 +160,11 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
|
|||||||
QueryResults queryResults;
|
QueryResults queryResults;
|
||||||
try {
|
try {
|
||||||
queryResults = keywordSearchQuery.performQuery();
|
queryResults = keywordSearchQuery.performQuery();
|
||||||
} catch (NoOpenCoreException ex) {
|
} catch (KeywordSearchModuleException | NoOpenCoreException ex) {
|
||||||
logger.log(Level.SEVERE, "Could not perform the query " + keywordSearchQuery.getQueryString(), ex); //NON-NLS
|
logger.log(Level.SEVERE, "Could not perform the query " + keywordSearchQuery.getQueryString(), ex); //NON-NLS
|
||||||
|
MessageNotifyUtil.Notify.error(Bundle.KeywordSearchResultFactory_query_exception_msg() + keywordSearchQuery.getQueryString(), ex.getCause().getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int id = 0;
|
int id = 0;
|
||||||
List<KeyValueQueryContent> tempList = new ArrayList<>();
|
List<KeyValueQueryContent> tempList = new ArrayList<>();
|
||||||
|
@ -32,11 +32,9 @@ import org.apache.solr.client.solrj.SolrRequest.METHOD;
|
|||||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||||
import org.apache.solr.common.SolrDocument;
|
import org.apache.solr.common.SolrDocument;
|
||||||
import org.apache.solr.common.SolrDocumentList;
|
import org.apache.solr.common.SolrDocumentList;
|
||||||
import org.openide.util.NbBundle;
|
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
|
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.Version;
|
import org.sleuthkit.autopsy.coreutils.Version;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||||
@ -128,7 +126,7 @@ class LuceneQuery implements KeywordSearchQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QueryResults performQuery() throws NoOpenCoreException {
|
public QueryResults performQuery() throws KeywordSearchModuleException, NoOpenCoreException {
|
||||||
QueryResults results = new QueryResults(this, keywordList);
|
QueryResults results = new QueryResults(this, keywordList);
|
||||||
//in case of single term literal query there is only 1 term
|
//in case of single term literal query there is only 1 term
|
||||||
boolean showSnippets = KeywordSearchSettings.getShowSnippets();
|
boolean showSnippets = KeywordSearchSettings.getShowSnippets();
|
||||||
@ -199,7 +197,7 @@ class LuceneQuery implements KeywordSearchQuery {
|
|||||||
*
|
*
|
||||||
* @throws NoOpenCoreException
|
* @throws NoOpenCoreException
|
||||||
*/
|
*/
|
||||||
private List<KeywordHit> performLuceneQuery(boolean snippets) throws NoOpenCoreException {
|
private List<KeywordHit> performLuceneQuery(boolean snippets) throws KeywordSearchModuleException, NoOpenCoreException {
|
||||||
List<KeywordHit> matches = new ArrayList<>();
|
List<KeywordHit> matches = new ArrayList<>();
|
||||||
boolean allMatchesFetched = false;
|
boolean allMatchesFetched = false;
|
||||||
final Server solrServer = KeywordSearch.getServer();
|
final Server solrServer = KeywordSearch.getServer();
|
||||||
@ -210,21 +208,15 @@ class LuceneQuery implements KeywordSearchQuery {
|
|||||||
Map<String, Map<String, List<String>>> highlightResponse;
|
Map<String, Map<String, List<String>>> highlightResponse;
|
||||||
Set<SolrDocument> uniqueSolrDocumentsWithHits;
|
Set<SolrDocument> 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
|
// objectId_chunk -> "text" -> List of previews
|
||||||
highlightResponse = response.getHighlighting();
|
highlightResponse = response.getHighlighting();
|
||||||
|
|
||||||
// get the unique set of files with hits
|
// get the unique set of files with hits
|
||||||
uniqueSolrDocumentsWithHits = filterOneHitPerDocument(resultList);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cycle through results in sets of MAX_RESULTS
|
// cycle through results in sets of MAX_RESULTS
|
||||||
for (int start = 0; !allMatchesFetched; start = start + MAX_RESULTS) {
|
for (int start = 0; !allMatchesFetched; start = start + MAX_RESULTS) {
|
||||||
|
@ -37,7 +37,9 @@ import org.netbeans.api.progress.aggregate.AggregateProgressHandle;
|
|||||||
import org.netbeans.api.progress.aggregate.ProgressContributor;
|
import org.netbeans.api.progress.aggregate.ProgressContributor;
|
||||||
import org.openide.util.Cancellable;
|
import org.openide.util.Cancellable;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
import org.sleuthkit.autopsy.coreutils.StopWatch;
|
import org.sleuthkit.autopsy.coreutils.StopWatch;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
@ -383,6 +385,7 @@ public final class SearchRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Messages("SearchRunner.query.exception.msg=Error performing query:")
|
||||||
protected Object doInBackground() throws Exception {
|
protected Object doInBackground() throws Exception {
|
||||||
final String displayName = NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.displayName")
|
final String displayName = NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.displayName")
|
||||||
+ (finalRun ? (" - " + NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.finalizeMsg")) : "");
|
+ (finalRun ? (" - " + NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.finalizeMsg")) : "");
|
||||||
@ -453,8 +456,9 @@ public final class SearchRunner {
|
|||||||
// Do the actual search
|
// Do the actual search
|
||||||
try {
|
try {
|
||||||
queryResults = keywordSearchQuery.performQuery();
|
queryResults = keywordSearchQuery.performQuery();
|
||||||
} catch (NoOpenCoreException ex) {
|
} catch (KeywordSearchModuleException | NoOpenCoreException ex) {
|
||||||
logger.log(Level.WARNING, "Error performing query: " + keywordQuery.getSearchTerm(), ex); //NON-NLS
|
logger.log(Level.SEVERE, "Error performing query: " + keywordQuery.getSearchTerm(), ex); //NON-NLS
|
||||||
|
MessageNotifyUtil.Notify.error(Bundle.SearchRunner_query_exception_msg() + keywordQuery.getSearchTerm(), ex.getCause().getMessage());
|
||||||
//no reason to continue with next query if recovery failed
|
//no reason to continue with next query if recovery failed
|
||||||
//or wait for recovery to kick in and run again later
|
//or wait for recovery to kick in and run again later
|
||||||
//likely case has closed and threads are being interrupted
|
//likely case has closed and threads are being interrupted
|
||||||
@ -462,9 +466,6 @@ public final class SearchRunner {
|
|||||||
} catch (CancellationException e) {
|
} catch (CancellationException e) {
|
||||||
logger.log(Level.INFO, "Cancel detected, bailing during keyword query: {0}", keywordQuery.getSearchTerm()); //NON-NLS
|
logger.log(Level.INFO, "Cancel detected, bailing during keyword query: {0}", keywordQuery.getSearchTerm()); //NON-NLS
|
||||||
return null;
|
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
|
// calculate new results by substracting results already obtained in this ingest
|
||||||
|
@ -261,10 +261,8 @@ final class TermsComponentQuery implements KeywordSearchQuery {
|
|||||||
*
|
*
|
||||||
* @throws NoOpenCoreException
|
* @throws NoOpenCoreException
|
||||||
*/
|
*/
|
||||||
// TODO: Make it so this cannot cause NPEs; this method should throw
|
|
||||||
// exceptions instead of logging them and returning null.
|
|
||||||
@Override
|
@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
|
* Do a query using the Solr terms component to find any terms in the
|
||||||
* index that match the regex.
|
* index that match the regex.
|
||||||
@ -278,14 +276,7 @@ final class TermsComponentQuery implements KeywordSearchQuery {
|
|||||||
termsQuery.setTimeAllowed(TERMS_SEARCH_TIMEOUT);
|
termsQuery.setTimeAllowed(TERMS_SEARCH_TIMEOUT);
|
||||||
termsQuery.setShowDebugInfo(DEBUG_FLAG);
|
termsQuery.setShowDebugInfo(DEBUG_FLAG);
|
||||||
termsQuery.setTermsLimit(MAX_TERMS_QUERY_RESULTS);
|
termsQuery.setTermsLimit(MAX_TERMS_QUERY_RESULTS);
|
||||||
List<Term> terms = null;
|
List<Term> terms = KeywordSearch.getServer().queryTerms(termsQuery).getTerms(SEARCH_FIELD);
|
||||||
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
|
|
||||||
//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.
|
* Do a term query for each term that matched the regex.
|
||||||
*/
|
*/
|
||||||
|
@ -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.
|
|
Loading…
x
Reference in New Issue
Block a user