mirror of
https://github.com/elisspace/autopsy.git
synced 2026-09-18 16:51:47 +00:00
Merge branch 'artifacts_are_content' of https://github.com/sleuthkit/autopsy into 2689_artifacts_are_content
# Conflicts: # Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java
This commit is contained in:
@@ -220,6 +220,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
|
||||
|
||||
@Override
|
||||
public void resetComponent() {
|
||||
setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -493,18 +493,19 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
private final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
private String[][] rowData = null;
|
||||
private final String artifactDisplayName;
|
||||
private final Content content;
|
||||
|
||||
ResultsTableArtifact(BlackboardArtifact artifact) {
|
||||
ResultsTableArtifact(BlackboardArtifact artifact, Content content) {
|
||||
artifactDisplayName = artifact.getDisplayName();
|
||||
this.content = content;
|
||||
addRows(artifact);
|
||||
|
||||
}
|
||||
|
||||
ResultsTableArtifact(String errorMsg) {
|
||||
artifactDisplayName = errorMsg;
|
||||
rowData = new String[1][3];
|
||||
rowData[0] = new String[]{"", errorMsg, ""};
|
||||
|
||||
content = null;
|
||||
}
|
||||
|
||||
private String[][] getRows() {
|
||||
@@ -514,7 +515,6 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
private void addRows(BlackboardArtifact artifact) {
|
||||
List<String[]> rowsToAdd = new ArrayList<>();
|
||||
try {
|
||||
Content content = artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
|
||||
/*
|
||||
* Add rows for each attribute.
|
||||
*/
|
||||
@@ -701,12 +701,15 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
if (contents.isEmpty()) {
|
||||
return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
|
||||
}
|
||||
Content underlyingContent = null;
|
||||
for (Content content : contents) {
|
||||
if ( (content != null) && (!(content instanceof BlackboardArtifact)) ) {
|
||||
// Get all of the blackboard artifacts associated with the content. These are what this
|
||||
// viewer displays.
|
||||
try {
|
||||
artifacts = content.getAllArtifacts();
|
||||
underlyingContent = content;
|
||||
break;
|
||||
} catch (TskException ex) {
|
||||
logger.log(Level.SEVERE, "Couldn't get artifacts", ex); //NON-NLS
|
||||
return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
|
||||
@@ -721,7 +724,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
// Build the new artifact contents cache.
|
||||
ArrayList<ResultsTableArtifact> artifactContents = new ArrayList<>();
|
||||
for (BlackboardArtifact artifact : artifacts) {
|
||||
artifactContents.add(new ResultsTableArtifact(artifact));
|
||||
artifactContents.add(new ResultsTableArtifact(artifact, underlyingContent));
|
||||
}
|
||||
|
||||
// If the node has an underlying blackboard artifact, show it. If not,
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -104,11 +105,11 @@ class ThumbnailViewChildren extends Children.Keys<Integer> {
|
||||
* children nodes (which might not be preloaded at this point).
|
||||
*/
|
||||
// get list of supported children sorted by persisted criteria
|
||||
final List<Node> suppContent =
|
||||
Stream.of(parent.getChildren().getNodes())
|
||||
.filter(ThumbnailViewChildren::isSupported)
|
||||
.sorted(getComparator())
|
||||
.collect(Collectors.toList());
|
||||
final List<Node> suppContent
|
||||
= Stream.of(parent.getChildren().getNodes())
|
||||
.filter(ThumbnailViewChildren::isSupported)
|
||||
.sorted(getComparator())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (suppContent.isEmpty()) {
|
||||
//if there are no images, there is nothing more to do
|
||||
@@ -314,7 +315,12 @@ class ThumbnailViewChildren extends Children.Keys<Integer> {
|
||||
private boolean cancelled = false;
|
||||
|
||||
ThumbnailLoadTask() {
|
||||
super(() -> ImageUtils.getThumbnail(content, thumbSize));
|
||||
super(new Callable<Image>() { //Does not work as lambda expression in dependent projects in IDE
|
||||
public Image call() {
|
||||
return ImageUtils.getThumbnail(content, thumbSize);
|
||||
}
|
||||
});
|
||||
//super(() -> ImageUtils.getThumbnail(content, thumbSize));
|
||||
progressText = Bundle.ThumbnailViewNode_progressHandle_text(content.getName());
|
||||
|
||||
progressHandle = ProgressHandleFactory.createSystemHandle(progressText);
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.text.MessageFormat;
|
||||
@@ -26,6 +28,8 @@ import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.Action;
|
||||
@@ -35,12 +39,12 @@ import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
|
||||
@@ -59,10 +63,15 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
*/
|
||||
public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(BlackboardArtifactNode.class.getName());
|
||||
|
||||
private static Cache<Long, Content> contentCache = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(1, TimeUnit.MINUTES).
|
||||
build();
|
||||
|
||||
private final BlackboardArtifact artifact;
|
||||
private Content associated = null;
|
||||
private List<NodeProperty<? extends Object>> customProperties;
|
||||
private static final Logger LOGGER = Logger.getLogger(BlackboardArtifactNode.class.getName());
|
||||
/*
|
||||
* Artifact types which should have the full unique path of the associated
|
||||
* content as a property.
|
||||
@@ -107,6 +116,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
if (evt.getNewValue() == null) {
|
||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||
removeListeners();
|
||||
contentCache.invalidateAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,7 +307,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
// Do nothing since the display name will be set to the file name.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
ss.put(new NodeProperty<>(entry.getKey(),
|
||||
entry.getKey(),
|
||||
@@ -491,46 +501,46 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
LOGGER.log(Level.SEVERE, "Getting attributes failed", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fill map with EmailMsg properties, not all attributes are filled
|
||||
*
|
||||
* @param map map with preserved ordering, where property names/values
|
||||
* are put
|
||||
* @param attribute attribute to check/fill as property
|
||||
*/
|
||||
* Fill map with EmailMsg properties, not all attributes are filled
|
||||
*
|
||||
* @param map map with preserved ordering, where property names/values
|
||||
* are put
|
||||
* @param attribute attribute to check/fill as property
|
||||
*/
|
||||
private void addEmailMsgProperty(Map<String, Object> map, BlackboardAttribute attribute ) {
|
||||
|
||||
final int attributeTypeID = attribute.getAttributeType().getTypeID();
|
||||
|
||||
// Skip certain Email msg attributes
|
||||
if (attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_RTF.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_BCC.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CC.getTypeID()
|
||||
|
||||
final int attributeTypeID = attribute.getAttributeType().getTypeID();
|
||||
|
||||
// Skip certain Email msg attributes
|
||||
if (attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_RTF.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_BCC.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CC.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_HEADERS.getTypeID()
|
||||
) {
|
||||
|
||||
// do nothing
|
||||
|
||||
// do nothing
|
||||
}
|
||||
else if (attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN.getTypeID()) {
|
||||
|
||||
String value = attribute.getDisplayString();
|
||||
if (value.length() > 160) {
|
||||
value = value.substring(0, 160) + "...";
|
||||
}
|
||||
map.put(attribute.getAttributeType().getDisplayName(), value);
|
||||
String value = attribute.getDisplayString();
|
||||
if (value.length() > 160) {
|
||||
value = value.substring(0, 160) + "...";
|
||||
}
|
||||
map.put(attribute.getAttributeType().getDisplayName(), value);
|
||||
}
|
||||
else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
|
||||
map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
|
||||
map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
|
||||
}
|
||||
else {
|
||||
map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
|
||||
map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
@@ -539,31 +549,25 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
/**
|
||||
* Create a Lookup based on what is in the passed in artifact.
|
||||
*
|
||||
* @param artifact
|
||||
* @param artifact The artifact to make a look up for.
|
||||
*
|
||||
* @return
|
||||
* @return A lookup with the artifact and possibly any associated content in
|
||||
* it.
|
||||
*/
|
||||
private static Lookup createLookup(BlackboardArtifact artifact) {
|
||||
List<Object> forLookup = new ArrayList<>();
|
||||
forLookup.add(artifact);
|
||||
|
||||
// Add the content the artifact is associated with
|
||||
Content content = getAssociatedContent(artifact);
|
||||
if (content != null) {
|
||||
forLookup.add(content);
|
||||
}
|
||||
|
||||
return Lookups.fixed(forLookup.toArray(new Object[forLookup.size()]));
|
||||
}
|
||||
|
||||
private static Content getAssociatedContent(BlackboardArtifact artifact) {
|
||||
final long objectID = artifact.getObjectID();
|
||||
try {
|
||||
return artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.WARNING, "Getting file failed", ex); //NON-NLS
|
||||
Content content = contentCache.get(objectID, () -> artifact.getSleuthkitCase().getContentById(objectID));
|
||||
if (content == null) {
|
||||
return Lookups.fixed(artifact);
|
||||
} else {
|
||||
return Lookups.fixed(artifact, content);
|
||||
}
|
||||
} catch (ExecutionException ex) {
|
||||
LOGGER.log(Level.WARNING, "Getting associated content for artifact failed", ex); //NON-NLS
|
||||
return Lookups.fixed(artifact);
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.getAssocCont.exception.msg"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -42,7 +42,6 @@ BlackboardArtifactNode.createSheet.filePath.name=File Path
|
||||
BlackboardArtifactNode.createSheet.filePath.displayName=File Path
|
||||
BlackboardArtifactNode.createSheet.dataSrc.name=Data Source
|
||||
BlackboardArtifactNode.createSheet.dataSrc.displayName=Data Source
|
||||
BlackboardArtifactNode.getAssocCont.exception.msg=Could not get file from database
|
||||
BlackboardArtifactTagNode.createSheet.srcFile.text=Source File
|
||||
BlackboardArtifactTagNode.createSheet.unavail.text=Unavailable
|
||||
BlackboardArtifactTagNode.createSheet.srcFilePath.text=Source File Path
|
||||
@@ -87,8 +86,8 @@ DeletedContent.deletedContentsNode.name=Deleted Files
|
||||
DeletedContent.createSheet.name.name=Name
|
||||
DeletedContent.createSheet.name.displayName=Name
|
||||
DeletedContent.createSheet.name.desc=no description
|
||||
DeletedContent.createSheet.filterType.name=Filter Type
|
||||
DeletedContent.createSheet.filterType.displayName=Filter Type
|
||||
DeletedContent.createSheet.filterType.name=Type
|
||||
DeletedContent.createSheet.filterType.displayName=Type
|
||||
DeletedContent.createSheet.filterType.desc=no description
|
||||
DeletedContent.createKeys.maxObjects.msg=There are more Deleted Files than can be displayed. Only the first {0} Deleted Files will be shown.
|
||||
DeletedContent.createNodeForKey.typeNotSupported.msg=Not supported for this type of Displayable Item\: {0}
|
||||
@@ -112,13 +111,13 @@ FileSize.fileSizeRootNode.name=File Size
|
||||
FileSize.createSheet.name.name=Name
|
||||
FileSize.createSheet.name.displayName=Name
|
||||
FileSize.createSheet.name.desc=no description
|
||||
FileSize.createSheet.filterType.name=Filter Type
|
||||
FileSize.createSheet.filterType.displayName=Filter Type
|
||||
FileSize.createSheet.filterType.name=Size Range
|
||||
FileSize.createSheet.filterType.displayName=Size Range
|
||||
FileSize.createSheet.filterType.desc=no description
|
||||
FileSize.exception.notSupported.msg=Not supported for this type of Displayable Item\: {0}
|
||||
FileTypeChildren.exception.notSupported.msg=Not supported for this type of Displayable Item\: {0}
|
||||
FileTypesByExtNode.createSheet.filterType.name=Filter Type
|
||||
FileTypesByExtNode.createSheet.filterType.displayName=Filter Type
|
||||
FileTypesByExtNode.createSheet.filterType.name=File Type
|
||||
FileTypesByExtNode.createSheet.filterType.displayName=File Type
|
||||
FileTypesByExtNode.createSheet.filterType.desc=no description
|
||||
FileTypesByExtNode.createSheet.fileExt.name=File Extensions
|
||||
FileTypesByExtNode.createSheet.fileExt.displayName=File Extensions
|
||||
|
||||
@@ -32,7 +32,6 @@ BlackboardArtifactNode.createSheet.filePath.name=\u30d5\u30a1\u30a4\u30eb\u30d1\
|
||||
BlackboardArtifactNode.createSheet.filePath.displayName=\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9
|
||||
BlackboardArtifactNode.createSheet.dataSrc.name=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9
|
||||
BlackboardArtifactNode.createSheet.dataSrc.displayName=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9
|
||||
BlackboardArtifactNode.getAssocCont.exception.msg=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f
|
||||
BlackboardArtifactTagNode.createSheet.srcFile.text=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb
|
||||
BlackboardArtifactTagNode.createSheet.unavail.text=\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
|
||||
BlackboardArtifactTagNode.createSheet.srcFilePath.text=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9
|
||||
@@ -64,8 +63,6 @@ DataSourcesNode.createSheet.name.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b
|
||||
DeletedContent.fsDelFilter.text=\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0
|
||||
DeletedContent.allDelFilter.text=\u3059\u3079\u3066
|
||||
DeletedContent.deletedContentsNode.name=\u524a\u9664\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb
|
||||
DeletedContent.createSheet.name.name=\u540d\u524d
|
||||
DeletedContent.createSheet.name.displayName=\u540d\u524d
|
||||
DeletedContent.createSheet.name.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
||||
DeletedContent.createSheet.filterType.name=\u30d5\u30a3\u30eb\u30bf\u30fc\u30bf\u30a4\u30d7
|
||||
DeletedContent.createSheet.filterType.displayName=\u30d5\u30a3\u30eb\u30bf\u30fc\u30bf\u30a4\u30d7
|
||||
@@ -92,8 +89,6 @@ FileNode.getActions.viewInNewWin.text=\u65b0\u898f\u30a6\u30a3\u30f3\u30c9\u30a6
|
||||
FileNode.getActions.openInExtViewer.text=\u5916\u90e8\u30d3\u30e5\u30fc\u30a2\u3067\u958b\u304f
|
||||
FileNode.getActions.searchFilesSameMD5.text=\u540c\u3058MD5\u30cf\u30c3\u30b7\u30e5\u3092\u6301\u3064\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22
|
||||
FileSize.fileSizeRootNode.name=\u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba
|
||||
FileSize.createSheet.name.name=\u540d\u524d
|
||||
FileSize.createSheet.name.displayName=\u540d\u524d
|
||||
FileSize.createSheet.name.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
||||
FileSize.createSheet.filterType.name=\u30d5\u30a3\u30eb\u30bf\u30fc\u30bf\u30a4\u30d7
|
||||
FileSize.createSheet.filterType.displayName=\u30d5\u30a3\u30eb\u30bf\u30fc\u30bf\u30a4\u30d7
|
||||
@@ -111,8 +106,6 @@ FileTypeExtensionFilters.autDocOfficeFilter.text=\u30aa\u30d5\u30a3\u30b9
|
||||
FileTypeExtensionFilters.autoDocPdfFilter.text=PDF
|
||||
FileTypeExtensionFilters.autDocTxtFilter.text=\u30d7\u30ec\u30fc\u30f3\u30c6\u30ad\u30b9\u30c8
|
||||
FileTypeExtensionFilters.autDocRtfFilter.text=\u30ea\u30c3\u30c1\u30c6\u30ad\u30b9\u30c8
|
||||
FileTypesByExtNode.createSheet.filterType.name=\u30d5\u30a3\u30eb\u30bf\u30fc\u30bf\u30a4\u30d7
|
||||
FileTypesByExtNode.createSheet.filterType.displayName=\u30d5\u30a3\u30eb\u30bf\u30fc\u30bf\u30a4\u30d7
|
||||
FileTypesByExtNode.createSheet.filterType.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
||||
FileTypesByExtNode.createSheet.fileExt.name=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50
|
||||
FileTypesByExtNode.createSheet.fileExt.displayName=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.HashSearchAction;
|
||||
@@ -62,8 +61,7 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
||||
} else {
|
||||
ext = "." + ext;
|
||||
}
|
||||
if (ImageUtils.isImageThumbnailSupported(file)
|
||||
|| FileTypeExtensions.getImageExtensions().contains(ext)) {
|
||||
if (FileTypeExtensions.getImageExtensions().contains(ext)) {
|
||||
return "org/sleuthkit/autopsy/images/image-file.png"; //NON-NLS
|
||||
}
|
||||
if (FileTypeExtensions.getVideoExtensions().contains(ext)) {
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.sleuthkit.datamodel.File;
|
||||
import org.sleuthkit.datamodel.FsContent;
|
||||
import org.sleuthkit.datamodel.LayoutFile;
|
||||
import org.sleuthkit.datamodel.LocalFile;
|
||||
import org.sleuthkit.datamodel.SlackFile;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
@@ -483,6 +484,11 @@ public class FileSize implements AutopsyVisitableItem {
|
||||
return new FileNode(f, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileNode visit(SlackFile f) {
|
||||
return new FileNode(f, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractNode defaultVisit(Content di) {
|
||||
throw new UnsupportedOperationException(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -18,9 +18,12 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.SwingWorker;
|
||||
@@ -31,6 +34,8 @@ import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentVisitor;
|
||||
import org.sleuthkit.datamodel.DerivedFile;
|
||||
@@ -40,6 +45,7 @@ import org.sleuthkit.datamodel.LayoutFile;
|
||||
import org.sleuthkit.datamodel.LocalFile;
|
||||
import org.sleuthkit.datamodel.SlackFile;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.SleuthkitItemVisitor;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
@@ -47,10 +53,24 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
*/
|
||||
public final class FileTypes implements AutopsyVisitableItem {
|
||||
|
||||
private final static Logger logger = Logger.getLogger(FileTypes.class.getName());
|
||||
private static final Logger logger = Logger.getLogger(FileTypes.class.getName());
|
||||
@NbBundle.Messages("FileTypes.name.text=File Types")
|
||||
private static final String NAME = Bundle.FileTypes_name_text();
|
||||
/**
|
||||
* Threshold used to limit db queries for child node counts. When the
|
||||
* tsk_files table has more than this number of rows, we don't query for the
|
||||
* child node counts, and since we don't have an accurate number we don't
|
||||
* show the counts.
|
||||
*/
|
||||
private static final int NODE_COUNT_FILE_TABLE_THRESHOLD = 1_000_000;
|
||||
/**
|
||||
* Used to keep track of whether we have hit
|
||||
* NODE_COUNT_FILE_TABLE_THRESHOLD. If we have, we stop querying for the
|
||||
* number of rows in tsk_files, since it is already too large.
|
||||
*/
|
||||
private boolean showCounts = true;
|
||||
|
||||
private final SleuthkitCase skCase;
|
||||
private boolean showCounts = true;
|
||||
|
||||
FileTypes(SleuthkitCase skCase) {
|
||||
this.skCase = skCase;
|
||||
@@ -66,15 +86,16 @@ public final class FileTypes implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the nodes show counts?
|
||||
*
|
||||
*
|
||||
* @return True, unless the DB has more than 200k rows.
|
||||
* Check the db to determine if the nodes should show child counts.
|
||||
*/
|
||||
boolean shouldShowCounts() {
|
||||
void updateShowCounts() {
|
||||
/*
|
||||
* once we have passed the threshold, we don't need to keep checking the
|
||||
* number of rows in tsk_files
|
||||
*/
|
||||
if (showCounts) {
|
||||
try {
|
||||
if (skCase.countFilesWhere("1=1") > 200000) { //NON-NLS
|
||||
if (skCase.countFilesWhere("1=1") > NODE_COUNT_FILE_TABLE_THRESHOLD) { //NON-NLS
|
||||
showCounts = false;
|
||||
}
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
@@ -82,10 +103,7 @@ public final class FileTypes implements AutopsyVisitableItem {
|
||||
logger.log(Level.SEVERE, "Error counting files.", tskCoreException); //NON-NLS
|
||||
}
|
||||
}
|
||||
return showCounts;
|
||||
}
|
||||
@NbBundle.Messages("FileTypes.name.text=File Types")
|
||||
static private final String NAME = Bundle.FileTypes_name_text();
|
||||
|
||||
/**
|
||||
* Node which will contain By Mime Type and By Extension nodes.
|
||||
@@ -97,8 +115,8 @@ public final class FileTypes implements AutopsyVisitableItem {
|
||||
new FileTypesByExtension(FileTypes.this),
|
||||
new FileTypesByMimeType(FileTypes.this))),
|
||||
Lookups.singleton(NAME));
|
||||
setName(NAME);
|
||||
setDisplayName(NAME);
|
||||
this.setName(NAME);
|
||||
this.setDisplayName(NAME);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); //NON-NLS
|
||||
}
|
||||
|
||||
@@ -215,9 +233,9 @@ public final class FileTypes implements AutopsyVisitableItem {
|
||||
* Updates the display name of the mediaSubTypeNode to include the count
|
||||
* of files which it represents.
|
||||
*/
|
||||
@NbBundle.Messages("FileTypes.bgCounting.placeholder=(counting...)")
|
||||
@NbBundle.Messages("FileTypes.bgCounting.placeholder= (counting...)")
|
||||
void updateDisplayName() {
|
||||
if (typesRoot.shouldShowCounts()) {
|
||||
if (typesRoot.showCounts) {
|
||||
//only show "(counting...)" the first time, otherwise it is distracting.
|
||||
setDisplayName(getDisplayNameBase() + ((childCount < 0) ? Bundle.FileTypes_bgCounting_placeholder()
|
||||
: ("(" + childCount + ")"))); //NON-NLS
|
||||
@@ -239,8 +257,186 @@ public final class FileTypes implements AutopsyVisitableItem {
|
||||
}
|
||||
}.execute();
|
||||
} else {
|
||||
setDisplayName(getDisplayNameBase() + ((childCount < 0) ? "" : ("(" + childCount + "+)"))); //NON-NLS
|
||||
setDisplayName(getDisplayNameBase() + ((childCount < 0) ? "" : (" (" + childCount + "+)"))); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that is used as a key by NetBeans for creating result nodes. This
|
||||
* is a wrapper around a Content object and is being put in place as an
|
||||
* optimization to avoid the Content.hashCode() implementation which issues
|
||||
* a database query to get the number of children when determining whether 2
|
||||
* Content objects represent the same thing. TODO: This is a temporary
|
||||
* solution that can hopefully be removed once we address the issue of
|
||||
* determining how many children a Content has (JIRA-2823).
|
||||
*/
|
||||
static class FileTypesKey implements Content {
|
||||
|
||||
private final Content content;
|
||||
|
||||
public FileTypesKey(Content content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final FileTypesKey other = (FileTypesKey) obj;
|
||||
|
||||
return this.content.getId() == other.content.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 101 * hash + (int)(this.content.getId() ^ (this.content.getId() >>> 32));
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(SleuthkitItemVisitor<T> v) {
|
||||
return content.accept(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buf, long offset, long len) throws TskCoreException {
|
||||
return content.read(buf, offset, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
content.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return content.getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ContentVisitor<T> v) {
|
||||
return content.accept(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return content.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniquePath() throws TskCoreException {
|
||||
return content.getUniquePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return content.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Content getDataSource() throws TskCoreException {
|
||||
return content.getDataSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Content> getChildren() throws TskCoreException {
|
||||
return content.getChildren();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasChildren() throws TskCoreException {
|
||||
return content.hasChildren();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChildrenCount() throws TskCoreException {
|
||||
return content.getChildrenCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Content getParent() throws TskCoreException {
|
||||
return content.getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> getChildrenIds() throws TskCoreException {
|
||||
return content.getChildrenIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlackboardArtifact newArtifact(int artifactTypeID) throws TskCoreException {
|
||||
return content.newArtifact(artifactTypeID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlackboardArtifact newArtifact(BlackboardArtifact.ARTIFACT_TYPE type) throws TskCoreException {
|
||||
return content.newArtifact(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<BlackboardArtifact> getArtifacts(String artifactTypeName) throws TskCoreException {
|
||||
return content.getArtifacts(artifactTypeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlackboardArtifact getGenInfoArtifact() throws TskCoreException {
|
||||
return content.getGenInfoArtifact();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlackboardArtifact getGenInfoArtifact(boolean create) throws TskCoreException {
|
||||
return content.getGenInfoArtifact(create);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<BlackboardAttribute> getGenInfoAttributes(BlackboardAttribute.ATTRIBUTE_TYPE attr_type) throws TskCoreException {
|
||||
return content.getGenInfoAttributes(attr_type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<BlackboardArtifact> getArtifacts(int artifactTypeID) throws TskCoreException {
|
||||
return content.getArtifacts(artifactTypeID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<BlackboardArtifact> getArtifacts(BlackboardArtifact.ARTIFACT_TYPE type) throws TskCoreException {
|
||||
return content.getArtifacts(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<BlackboardArtifact> getAllArtifacts() throws TskCoreException {
|
||||
return content.getAllArtifacts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getHashSetNames() throws TskCoreException {
|
||||
return content.getHashSetNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getArtifactsCount(String artifactTypeName) throws TskCoreException {
|
||||
return content.getArtifactsCount(artifactTypeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getArtifactsCount(int artifactTypeID) throws TskCoreException {
|
||||
return content.getArtifactsCount(artifactTypeID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getArtifactsCount(BlackboardArtifact.ARTIFACT_TYPE type) throws TskCoreException {
|
||||
return content.getArtifactsCount(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAllArtifactsCount() throws TskCoreException {
|
||||
return content.getAllArtifactsCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-17 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -24,7 +24,10 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
@@ -34,7 +37,9 @@ import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesKey;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
@@ -87,7 +92,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCase();
|
||||
typesRoot.shouldShowCounts();
|
||||
typesRoot.updateShowCounts();
|
||||
update();
|
||||
} catch (IllegalStateException notUsed) {
|
||||
/**
|
||||
@@ -147,8 +152,9 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
* provides updates on events
|
||||
*/
|
||||
private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) {
|
||||
|
||||
super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, o), true),
|
||||
Lookups.singleton(filter == null ? FNAME : filter.getName()));
|
||||
Lookups.singleton(filter == null ? FNAME : filter.getDisplayName()));
|
||||
this.filter = filter;
|
||||
|
||||
// root node of tree
|
||||
@@ -157,7 +163,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
super.setDisplayName(FNAME);
|
||||
} // sub-node in file tree (i.e. documents, exec, etc.)
|
||||
else {
|
||||
super.setName(filter.getName());
|
||||
super.setName(filter.getDisplayName());
|
||||
super.setDisplayName(filter.getDisplayName());
|
||||
}
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); //NON-NLS
|
||||
@@ -181,7 +187,16 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
ss = Sheet.createPropertiesSet();
|
||||
s.put(ss);
|
||||
}
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.desc"), getName()));
|
||||
if (filter != null && (filter.equals(FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER) || filter.equals(FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER))) {
|
||||
String extensions = "";
|
||||
for (String ext : filter.getFilter()) {
|
||||
extensions += "'" + ext + "', ";
|
||||
}
|
||||
extensions = extensions.substring(0, extensions.lastIndexOf(','));
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.desc"), extensions));
|
||||
} else {
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.desc"), getDisplayName()));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -272,7 +287,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
super(typesRoot, Children.create(new FileExtensionNodeChildren(filter, skCase, o), true),
|
||||
Lookups.singleton(filter.getDisplayName()));
|
||||
this.filter = filter;
|
||||
setName(filter.getName());
|
||||
super.setName(filter.getDisplayName());
|
||||
updateDisplayName();
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
|
||||
|
||||
@@ -330,24 +345,43 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
|
||||
private static String createQuery(FileTypesByExtension.SearchFilterInterface filter) {
|
||||
StringBuilder query = new StringBuilder();
|
||||
query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS
|
||||
if (UserPreferences.hideKnownFilesInViewsTree()) {
|
||||
query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS
|
||||
private String createQuery(FileTypesByExtension.SearchFilterInterface filter) {
|
||||
if (filter.getFilter().isEmpty()) {
|
||||
// We should never be given a search filter without extensions
|
||||
// but if we are it is clearly a programming error so we throw
|
||||
// an IllegalArgumentException.
|
||||
throw new IllegalArgumentException("Empty filter list passed to createQuery()"); // NON-NLS
|
||||
}
|
||||
query.append(" AND (NULL"); //NON-NLS
|
||||
for (String s : filter.getFilter()) {
|
||||
query.append(" OR LOWER(name) LIKE LOWER('%").append(s).append("')"); //NON-NLS
|
||||
|
||||
String query = "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")"
|
||||
+ (UserPreferences.hideKnownFilesInViewsTree() ? " AND (known IS NULL OR known != "
|
||||
+ TskData.FileKnown.KNOWN.getFileKnownValue() + ")" : " ")
|
||||
+ " AND (NULL "; //NON-NLS
|
||||
|
||||
if (skCase.getDatabaseType().equals(TskData.DbType.POSTGRESQL)) {
|
||||
// For PostgreSQL we get a more efficient query by using builtin
|
||||
// regular expression support and or'ing all extensions. We also
|
||||
// escape the dot at the beginning of the extension.
|
||||
// We will end up with a query that looks something like this:
|
||||
// OR LOWER(name) ~ '(\.zip|\.rar|\.7zip|\.cab|\.jar|\.cpio|\.ar|\.gz|\.tgz|\.bz2)$')
|
||||
query += "OR LOWER(name) ~ '(\\";
|
||||
query += StringUtils.join(filter.getFilter().stream()
|
||||
.map(String::toLowerCase).collect(Collectors.toList()), "|\\");
|
||||
query += ")$'";
|
||||
} else {
|
||||
for (String s : filter.getFilter()) {
|
||||
query += "OR LOWER(name) LIKE '%" + s.toLowerCase() + "'"; // NON-NLS
|
||||
}
|
||||
}
|
||||
query.append(')');
|
||||
return query.toString();
|
||||
|
||||
query += ')';
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Child node factory for a specific file type - does the database query.
|
||||
*/
|
||||
private static class FileExtensionNodeChildren extends ChildFactory.Detachable<Content> implements Observer {
|
||||
private class FileExtensionNodeChildren extends ChildFactory.Detachable<FileTypesKey> implements Observer {
|
||||
|
||||
private final SleuthkitCase skCase;
|
||||
private final FileTypesByExtension.SearchFilterInterface filter;
|
||||
@@ -387,9 +421,10 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<Content> list) {
|
||||
protected boolean createKeys(List<FileTypesKey> list) {
|
||||
try {
|
||||
list.addAll(skCase.findAllFilesWhere(createQuery(filter)));
|
||||
list.addAll(skCase.findAllFilesWhere(createQuery(filter))
|
||||
.stream().map(f -> new FileTypesKey(f)).collect(Collectors.toList()));
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Couldn't get search results", ex); //NON-NLS
|
||||
}
|
||||
@@ -397,7 +432,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(Content key) {
|
||||
protected Node createNodeForKey(FileTypesKey key) {
|
||||
return key.accept(new FileTypes.FileNodeCreationVisitor());
|
||||
}
|
||||
}
|
||||
@@ -419,10 +454,10 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
FileTypeExtensions.getArchiveExtensions()),
|
||||
TSK_DOCUMENT_FILTER(3, "TSK_DOCUMENT_FILTER", //NON-NLS
|
||||
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskDocumentFilter.text"),
|
||||
Arrays.asList(".doc", ".docx", ".pdf", ".xls", ".rtf", ".txt")), //NON-NLS
|
||||
Arrays.asList(".htm", ".html", ".doc", ".docx", ".odt", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".rtf")), //NON-NLS
|
||||
TSK_EXECUTABLE_FILTER(3, "TSK_EXECUTABLE_FILTER", //NON-NLS
|
||||
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskExecFilter.text"),
|
||||
Arrays.asList(".exe", ".dll", ".bat", ".cmd", ".com")); //NON-NLS
|
||||
FileTypeExtensions.getExecutableExtensions()); //NON-NLS
|
||||
|
||||
private final int id;
|
||||
private final String name;
|
||||
|
||||
@@ -30,16 +30,20 @@ import java.util.Map;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import static org.sleuthkit.autopsy.core.UserPreferences.hideKnownFilesInViewsTree;
|
||||
import static org.sleuthkit.autopsy.core.UserPreferences.hideSlackFilesInViewsTree;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesKey;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
@@ -55,6 +59,7 @@ import org.sleuthkit.datamodel.TskData;
|
||||
public final class FileTypesByMimeType extends Observable implements AutopsyVisitableItem {
|
||||
|
||||
private final static Logger logger = Logger.getLogger(FileTypesByMimeType.class.getName());
|
||||
|
||||
private final SleuthkitCase skCase;
|
||||
/**
|
||||
* The nodes of this tree will be determined dynamically by the mimetypes
|
||||
@@ -62,36 +67,53 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
* type as the key and a Map, from media subtype to count, as the value.
|
||||
*/
|
||||
private final HashMap<String, Map<String, Long>> existingMimeTypeCounts = new HashMap<>();
|
||||
private static final Logger LOGGER = Logger.getLogger(FileTypesByMimeType.class.getName());
|
||||
/**
|
||||
* Root of the File Types tree. Used to provide single answer to question:
|
||||
* Should the child counts be shown next to the nodes?
|
||||
*/
|
||||
private final FileTypes typesRoot;
|
||||
|
||||
private void removeListeners() {
|
||||
deleteObservers();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
Case.removePropertyChangeListener(pcl);
|
||||
}
|
||||
/*
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Performs the query on the database to get all distinct MIME types of
|
||||
* files in it, and populate the hashmap with those results.
|
||||
* Create the base expression used as the where clause in the queries for
|
||||
* files by mime type. Filters out certain kinds of files and directories,
|
||||
* and known/slack files based on user preferences.
|
||||
*
|
||||
* @return The base expression to be used in the where clause of queries for
|
||||
* files by mime type.
|
||||
*/
|
||||
private void populateHashMap() {
|
||||
String query = "SELECT mime_type,count(*) as count from tsk_files "
|
||||
+ " where mime_type IS NOT null "
|
||||
+ " AND dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()
|
||||
static private String createBaseWhereExpr() {
|
||||
return "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")"
|
||||
+ " AND (type IN ("
|
||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal() + ","
|
||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal() + ","
|
||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal() + ","
|
||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()
|
||||
+ ((UserPreferences.hideSlackFilesInViewsTree()) ? ""
|
||||
: ("," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
|
||||
+ "))" + " GROUP BY mime_type";
|
||||
+ (hideSlackFilesInViewsTree() ? "" : ("," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
|
||||
+ "))"
|
||||
+ (hideKnownFilesInViewsTree() ? (" AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")") : "");
|
||||
}
|
||||
|
||||
private void removeListeners() {
|
||||
deleteObservers();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
Case.removePropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
String query = "SELECT mime_type, count(*) AS count FROM tsk_files "
|
||||
+ " WHERE mime_type IS NOT null "
|
||||
+ " AND " + createBaseWhereExpr()
|
||||
+ " GROUP BY mime_type";
|
||||
synchronized (existingMimeTypeCounts) {
|
||||
existingMimeTypeCounts.clear();
|
||||
|
||||
@@ -114,7 +136,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException | SQLException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Unable to populate File Types by MIME Type tree view from DB: ", ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Unable to populate File Types by MIME Type tree view from DB: ", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +160,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCase();
|
||||
typesRoot.shouldShowCounts();
|
||||
typesRoot.updateShowCounts();
|
||||
populateHashMap();
|
||||
} catch (IllegalStateException notUsed) {
|
||||
/**
|
||||
@@ -187,11 +209,12 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
*/
|
||||
class ByMimeTypeNode extends DisplayableItemNode {
|
||||
|
||||
@NbBundle.Messages("FileTypesByMimeType.name.text=By MIME Type")
|
||||
@NbBundle.Messages({"FileTypesByMimeType.name.text=By MIME Type"})
|
||||
|
||||
final String NAME = Bundle.FileTypesByMimeType_name_text();
|
||||
|
||||
ByMimeTypeNode() {
|
||||
super(Children.create(new ByMimeTypeNodeChildren(), true));
|
||||
super(Children.create(new ByMimeTypeNodeChildren(), true), Lookups.singleton(Bundle.FileTypesByMimeType_name_text()));
|
||||
super.setName(NAME);
|
||||
super.setDisplayName(NAME);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png");
|
||||
@@ -259,8 +282,12 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
*/
|
||||
class MediaTypeNode extends DisplayableItemNode {
|
||||
|
||||
@NbBundle.Messages({"FileTypesByMimeTypeNode.createSheet.mediaType.name=Type",
|
||||
"FileTypesByMimeTypeNode.createSheet.mediaType.displayName=Type",
|
||||
"FileTypesByMimeTypeNode.createSheet.mediaType.desc=no description"})
|
||||
|
||||
MediaTypeNode(String name) {
|
||||
super(Children.create(new MediaTypeNodeChildren(name), true));
|
||||
super(Children.create(new MediaTypeNodeChildren(name), true), Lookups.singleton(name));
|
||||
setName(name);
|
||||
setDisplayName(name);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png");
|
||||
@@ -276,6 +303,18 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
return v.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
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<>(NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaType.name"), NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaType.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaType.desc"), getDisplayName()));
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
return getClass().getName();
|
||||
@@ -316,19 +355,25 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 FileTypes.BGCountUpdatingNode {
|
||||
|
||||
@NbBundle.Messages({"FileTypesByMimeTypeNode.createSheet.mediaSubtype.name=Subtype",
|
||||
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.displayName=Subtype",
|
||||
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.desc=no description"})
|
||||
private final String mimeType;
|
||||
private final String subType;
|
||||
|
||||
private MediaSubTypeNode(String mimeType) {
|
||||
super(typesRoot, Children.create(new MediaSubTypeNodeChildren(mimeType), true));
|
||||
super(typesRoot, Children.create(new MediaSubTypeNodeChildren(mimeType), true), Lookups.singleton(mimeType));
|
||||
this.mimeType = mimeType;
|
||||
this.subType = StringUtils.substringAfter(mimeType, "/");
|
||||
super.setName(mimeType);
|
||||
super.setDisplayName(subType);
|
||||
updateDisplayName();
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
|
||||
|
||||
addObserver(this);
|
||||
}
|
||||
|
||||
@@ -347,6 +392,17 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
public <T> T accept(DisplayableItemNodeVisitor< T> v) {
|
||||
return v.visit(this);
|
||||
}
|
||||
@Override
|
||||
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<>(NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaSubtype.name"), NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaSubtype.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByMimeTypeNode.createSheet.mediaSubtype.desc"), getDisplayName()));
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
@@ -369,39 +425,12 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
static private String createQuery(String mimeType) {
|
||||
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(",");
|
||||
if (!UserPreferences.hideSlackFilesInViewsTree()) {
|
||||
query.append(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.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(mimeType).append("'"); //NON-NLS
|
||||
return query.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class MediaSubTypeNodeChildren extends ChildFactory.Detachable<FileTypesKey> implements Observer {
|
||||
|
||||
private final String mimeType;
|
||||
|
||||
@@ -411,23 +440,13 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
this.mimeType = mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
protected boolean createKeys(List<FileTypesKey> list) {
|
||||
try {
|
||||
List<AbstractFile> files = skCase.findAllFilesWhere(createQuery(mimeType));
|
||||
list.addAll(files);
|
||||
list.addAll(skCase.findAllFilesWhere(createBaseWhereExpr() + " AND mime_type = '" + mimeType + "'")
|
||||
.stream().map(f -> new FileTypesKey(f)).collect(Collectors.toList())); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Couldn't get search results", ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Couldn't get search results", ex); //NON-NLS
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -437,19 +456,9 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
refresh(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the content to populate the Directory Listing Table view for
|
||||
* each file
|
||||
*
|
||||
* @param key
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected Node createNodeForKey(Content key) {
|
||||
protected Node createNodeForKey(FileTypesKey key) {
|
||||
return key.accept(new FileTypes.FileNodeCreationVisitor());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -33,6 +32,7 @@ import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
@@ -95,6 +95,10 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
+ " OR attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()//NON-NLS
|
||||
+ ")"; //NON-NLS
|
||||
|
||||
static private boolean isOnlyDefaultInstance(List<String> instances) {
|
||||
return (instances.size() == 1) && (instances.get(0).equals(DEFAULT_INSTANCE_NAME));
|
||||
}
|
||||
|
||||
public KeywordHits(SleuthkitCase skCase) {
|
||||
this.skCase = skCase;
|
||||
keywordResults = new KeywordResults();
|
||||
@@ -265,7 +269,6 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
addRegExpToList(listMap, reg, word, id);
|
||||
}
|
||||
} else {//single term
|
||||
|
||||
if ("1".equals(kwType) || reg == null) { //literal, substring or exact
|
||||
/*
|
||||
* Substring, treated same as exact match. "1" is
|
||||
@@ -626,9 +629,8 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
|
||||
@Override
|
||||
public boolean isLeafTypeNode() {
|
||||
List<String> instances = keywordResults.getKeywordInstances(setName, keyword);
|
||||
// is this an exact/substring match (i.e. did we use the DEFAULT name)?
|
||||
return instances.size() == 1 && instances.get(0).equals(DEFAULT_INSTANCE_NAME);
|
||||
return isOnlyDefaultInstance(keywordResults.getKeywordInstances(setName, keyword));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -661,7 +663,6 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -706,7 +707,6 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
|
||||
private final String keyword;
|
||||
private final String setName;
|
||||
private final Map<RegExpInstanceKey, DisplayableItemNode> nodesMap = new HashMap<>();
|
||||
|
||||
private RegExpInstancesFactory(String setName, String keyword) {
|
||||
super();
|
||||
@@ -720,29 +720,20 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
// The keys are different depending on what we are displaying.
|
||||
// regexp get another layer to show instances.
|
||||
// Exact/substring matches don't.
|
||||
if ((instances.size() == 1) && (instances.get(0).equals(DEFAULT_INSTANCE_NAME))) {
|
||||
for (Long id : keywordResults.getArtifactIds(setName, keyword, DEFAULT_INSTANCE_NAME)) {
|
||||
RegExpInstanceKey key = new RegExpInstanceKey(id);
|
||||
nodesMap.computeIfAbsent(key, k -> createNode(k));
|
||||
list.add(key);
|
||||
}
|
||||
if (isOnlyDefaultInstance(instances)) {
|
||||
list.addAll(keywordResults.getArtifactIds(setName, keyword, DEFAULT_INSTANCE_NAME).stream()
|
||||
.map(RegExpInstanceKey::new)
|
||||
.collect(Collectors.toList()));
|
||||
} else {
|
||||
for (String instance : instances) {
|
||||
RegExpInstanceKey key = new RegExpInstanceKey(instance);
|
||||
nodesMap.computeIfAbsent(key, k -> createNode(k));
|
||||
list.add(key);
|
||||
}
|
||||
|
||||
list.addAll(instances.stream()
|
||||
.map(RegExpInstanceKey::new)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(RegExpInstanceKey key) {
|
||||
return nodesMap.get(key);
|
||||
}
|
||||
|
||||
private DisplayableItemNode createNode(RegExpInstanceKey key) {
|
||||
if (key.isRegExp()) {
|
||||
return new RegExpInstanceNode(setName, keyword, key.getRegExpKey());
|
||||
} else {
|
||||
@@ -750,6 +741,7 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
return createBlackboardArtifactNode(key.getIdKey());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -884,7 +876,6 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
private final String keyword;
|
||||
private final String setName;
|
||||
private final String instance;
|
||||
private final Map<Long, BlackboardArtifactNode> nodesMap = new HashMap<>();
|
||||
|
||||
private HitsFactory(String setName, String keyword, String instance) {
|
||||
super();
|
||||
@@ -895,16 +886,13 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<Long> list) {
|
||||
for (Long id : keywordResults.getArtifactIds(setName, keyword, instance)) {
|
||||
nodesMap.computeIfAbsent(id, i -> createBlackboardArtifactNode(i));
|
||||
list.add(id);
|
||||
}
|
||||
list.addAll(keywordResults.getArtifactIds(setName, keyword, instance));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(Long artifactId) {
|
||||
return nodesMap.get(artifactId);
|
||||
return createBlackboardArtifactNode(artifactId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,7 +417,9 @@ final class ExtractUnallocAction extends AbstractAction {
|
||||
try {
|
||||
List<LayoutFile> lflst = new ArrayList<>();
|
||||
for (Content layout : vd.getChildren()) {
|
||||
lflst.add((LayoutFile) layout);
|
||||
if(layout instanceof LayoutFile){
|
||||
lflst.add((LayoutFile) layout);
|
||||
}
|
||||
}
|
||||
return lflst;
|
||||
} catch (TskCoreException tce) {
|
||||
|
||||
@@ -51,6 +51,7 @@ final class GetFilesCountVisitor extends ContentVisitor.Default<Long> {
|
||||
queryB.append(") )");
|
||||
queryB.append(" AND ( (meta_type = ").append(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()); //NON-NLS
|
||||
queryB.append(") OR (meta_type = ").append(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()); //NON-NLS
|
||||
queryB.append(") OR (meta_type = ").append(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue()); //NON-NLS
|
||||
queryB.append(") OR (meta_type = ").append(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT.getValue()); //NON-NLS
|
||||
queryB.append(" AND (name != '.') AND (name != '..')"); //NON-NLS
|
||||
queryB.append(") )");
|
||||
|
||||
@@ -537,10 +537,12 @@ public final class FilesSet implements Serializable {
|
||||
case FILES:
|
||||
return file.isFile();
|
||||
case DIRECTORIES:
|
||||
return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR;
|
||||
return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR
|
||||
|| file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR;
|
||||
case FILES_AND_DIRECTORIES:
|
||||
return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG
|
||||
|| file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR;
|
||||
|| file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR
|
||||
|| file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR;
|
||||
case ALL:
|
||||
return true; //Effectively ignores the metatype condition when All is selected.
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user