mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +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:
commit
4fdea244af
@ -861,7 +861,7 @@ public class EamDbSettingsDialog extends JDialog {
|
|||||||
*
|
*
|
||||||
* @return true
|
* @return true
|
||||||
*/
|
*/
|
||||||
@Messages({"EamDbSettingsDialog.validation.mustTest=Once you are statisfied with the database settings, click the Test button to test the database connection, settings, and schema.",
|
@Messages({"EamDbSettingsDialog.validation.mustTest=Once you are statisfied with the database settings, click the Test button to test the database connection, settings, and schema. SQLite should only be used by one examiner at a time.",
|
||||||
"EamDbSettingsDialog.validation.failedConnection=The connection to the database failed. Update the settings and try the Test again."})
|
"EamDbSettingsDialog.validation.failedConnection=The connection to the database failed. Update the settings and try the Test again."})
|
||||||
private boolean enableTestButton(boolean isValidInput) {
|
private boolean enableTestButton(boolean isValidInput) {
|
||||||
if (selectedPlatform != EamDbPlatformEnum.DISABLED && isValidInput) {
|
if (selectedPlatform != EamDbPlatformEnum.DISABLED && isValidInput) {
|
||||||
|
@ -220,6 +220,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resetComponent() {
|
public void resetComponent() {
|
||||||
|
setText("");
|
||||||
return;
|
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 final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
private String[][] rowData = null;
|
private String[][] rowData = null;
|
||||||
private final String artifactDisplayName;
|
private final String artifactDisplayName;
|
||||||
|
private final Content content;
|
||||||
|
|
||||||
ResultsTableArtifact(BlackboardArtifact artifact) {
|
ResultsTableArtifact(BlackboardArtifact artifact, Content content) {
|
||||||
artifactDisplayName = artifact.getDisplayName();
|
artifactDisplayName = artifact.getDisplayName();
|
||||||
|
this.content = content;
|
||||||
addRows(artifact);
|
addRows(artifact);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultsTableArtifact(String errorMsg) {
|
ResultsTableArtifact(String errorMsg) {
|
||||||
artifactDisplayName = errorMsg;
|
artifactDisplayName = errorMsg;
|
||||||
rowData = new String[1][3];
|
rowData = new String[1][3];
|
||||||
rowData[0] = new String[]{"", errorMsg, ""};
|
rowData[0] = new String[]{"", errorMsg, ""};
|
||||||
|
content = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String[][] getRows() {
|
private String[][] getRows() {
|
||||||
@ -514,7 +515,6 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
|||||||
private void addRows(BlackboardArtifact artifact) {
|
private void addRows(BlackboardArtifact artifact) {
|
||||||
List<String[]> rowsToAdd = new ArrayList<>();
|
List<String[]> rowsToAdd = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
Content content = artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
|
|
||||||
/*
|
/*
|
||||||
* Add rows for each attribute.
|
* Add rows for each attribute.
|
||||||
*/
|
*/
|
||||||
@ -701,12 +701,15 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
|||||||
if (contents.isEmpty()) {
|
if (contents.isEmpty()) {
|
||||||
return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
|
return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
|
||||||
}
|
}
|
||||||
|
Content underlyingContent = null;
|
||||||
for (Content content : contents) {
|
for (Content content : contents) {
|
||||||
if ( (content != null) && (!(content instanceof BlackboardArtifact)) ) {
|
if ( (content != null) && (!(content instanceof BlackboardArtifact)) ) {
|
||||||
// Get all of the blackboard artifacts associated with the content. These are what this
|
// Get all of the blackboard artifacts associated with the content. These are what this
|
||||||
// viewer displays.
|
// viewer displays.
|
||||||
try {
|
try {
|
||||||
artifacts = content.getAllArtifacts();
|
artifacts = content.getAllArtifacts();
|
||||||
|
underlyingContent = content;
|
||||||
|
break;
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
logger.log(Level.SEVERE, "Couldn't get artifacts", ex); //NON-NLS
|
logger.log(Level.SEVERE, "Couldn't get artifacts", ex); //NON-NLS
|
||||||
return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
|
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.
|
// Build the new artifact contents cache.
|
||||||
ArrayList<ResultsTableArtifact> artifactContents = new ArrayList<>();
|
ArrayList<ResultsTableArtifact> artifactContents = new ArrayList<>();
|
||||||
for (BlackboardArtifact artifact : artifacts) {
|
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,
|
// 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.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.CancellationException;
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@ -104,8 +105,8 @@ class ThumbnailViewChildren extends Children.Keys<Integer> {
|
|||||||
* children nodes (which might not be preloaded at this point).
|
* children nodes (which might not be preloaded at this point).
|
||||||
*/
|
*/
|
||||||
// get list of supported children sorted by persisted criteria
|
// get list of supported children sorted by persisted criteria
|
||||||
final List<Node> suppContent =
|
final List<Node> suppContent
|
||||||
Stream.of(parent.getChildren().getNodes())
|
= Stream.of(parent.getChildren().getNodes())
|
||||||
.filter(ThumbnailViewChildren::isSupported)
|
.filter(ThumbnailViewChildren::isSupported)
|
||||||
.sorted(getComparator())
|
.sorted(getComparator())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
@ -314,7 +315,12 @@ class ThumbnailViewChildren extends Children.Keys<Integer> {
|
|||||||
private boolean cancelled = false;
|
private boolean cancelled = false;
|
||||||
|
|
||||||
ThumbnailLoadTask() {
|
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());
|
progressText = Bundle.ThumbnailViewNode_progressHandle_text(content.getName());
|
||||||
|
|
||||||
progressHandle = ProgressHandleFactory.createSystemHandle(progressText);
|
progressHandle = ProgressHandleFactory.createSystemHandle(progressText);
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
@ -26,6 +28,8 @@ 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;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
@ -35,12 +39,12 @@ import org.openide.util.Lookup;
|
|||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.lookup.Lookups;
|
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.MessageNotifyUtil;
|
|
||||||
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
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 static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
|
||||||
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;
|
||||||
@ -59,10 +63,15 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
*/
|
*/
|
||||||
public class BlackboardArtifactNode extends DisplayableItemNode {
|
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 final BlackboardArtifact artifact;
|
||||||
private Content associated = null;
|
private Content associated = null;
|
||||||
private List<NodeProperty<? extends Object>> customProperties;
|
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
|
* Artifact types which should have the full unique path of the associated
|
||||||
* content as a property.
|
* content as a property.
|
||||||
@ -107,6 +116,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
if (evt.getNewValue() == null) {
|
if (evt.getNewValue() == null) {
|
||||||
// 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();
|
||||||
|
contentCache.invalidateAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -539,31 +549,25 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
|||||||
/**
|
/**
|
||||||
* Create a Lookup based on what is in the passed in artifact.
|
* 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) {
|
private static Lookup createLookup(BlackboardArtifact artifact) {
|
||||||
List<Object> forLookup = new ArrayList<>();
|
|
||||||
forLookup.add(artifact);
|
|
||||||
|
|
||||||
// Add the content the artifact is associated with
|
// Add the content the artifact is associated with
|
||||||
Content content = getAssociatedContent(artifact);
|
final long objectID = artifact.getObjectID();
|
||||||
if (content != null) {
|
|
||||||
forLookup.add(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Lookups.fixed(forLookup.toArray(new Object[forLookup.size()]));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Content getAssociatedContent(BlackboardArtifact artifact) {
|
|
||||||
try {
|
try {
|
||||||
return artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
|
Content content = contentCache.get(objectID, () -> artifact.getSleuthkitCase().getContentById(objectID));
|
||||||
} catch (TskCoreException ex) {
|
if (content == null) {
|
||||||
LOGGER.log(Level.WARNING, "Getting file failed", ex); //NON-NLS
|
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
|
@Override
|
||||||
|
@ -42,7 +42,6 @@ BlackboardArtifactNode.createSheet.filePath.name=File Path
|
|||||||
BlackboardArtifactNode.createSheet.filePath.displayName=File Path
|
BlackboardArtifactNode.createSheet.filePath.displayName=File Path
|
||||||
BlackboardArtifactNode.createSheet.dataSrc.name=Data Source
|
BlackboardArtifactNode.createSheet.dataSrc.name=Data Source
|
||||||
BlackboardArtifactNode.createSheet.dataSrc.displayName=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.srcFile.text=Source File
|
||||||
BlackboardArtifactTagNode.createSheet.unavail.text=Unavailable
|
BlackboardArtifactTagNode.createSheet.unavail.text=Unavailable
|
||||||
BlackboardArtifactTagNode.createSheet.srcFilePath.text=Source File Path
|
BlackboardArtifactTagNode.createSheet.srcFilePath.text=Source File Path
|
||||||
@ -87,8 +86,8 @@ DeletedContent.deletedContentsNode.name=Deleted Files
|
|||||||
DeletedContent.createSheet.name.name=Name
|
DeletedContent.createSheet.name.name=Name
|
||||||
DeletedContent.createSheet.name.displayName=Name
|
DeletedContent.createSheet.name.displayName=Name
|
||||||
DeletedContent.createSheet.name.desc=no description
|
DeletedContent.createSheet.name.desc=no description
|
||||||
DeletedContent.createSheet.filterType.name=Filter Type
|
DeletedContent.createSheet.filterType.name=Type
|
||||||
DeletedContent.createSheet.filterType.displayName=Filter Type
|
DeletedContent.createSheet.filterType.displayName=Type
|
||||||
DeletedContent.createSheet.filterType.desc=no description
|
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.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}
|
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.name=Name
|
||||||
FileSize.createSheet.name.displayName=Name
|
FileSize.createSheet.name.displayName=Name
|
||||||
FileSize.createSheet.name.desc=no description
|
FileSize.createSheet.name.desc=no description
|
||||||
FileSize.createSheet.filterType.name=Filter Type
|
FileSize.createSheet.filterType.name=Size Range
|
||||||
FileSize.createSheet.filterType.displayName=Filter Type
|
FileSize.createSheet.filterType.displayName=Size Range
|
||||||
FileSize.createSheet.filterType.desc=no description
|
FileSize.createSheet.filterType.desc=no description
|
||||||
FileSize.exception.notSupported.msg=Not supported for this type of Displayable Item\: {0}
|
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}
|
FileTypeChildren.exception.notSupported.msg=Not supported for this type of Displayable Item\: {0}
|
||||||
FileTypesByExtNode.createSheet.filterType.name=Filter Type
|
FileTypesByExtNode.createSheet.filterType.name=File Type
|
||||||
FileTypesByExtNode.createSheet.filterType.displayName=Filter Type
|
FileTypesByExtNode.createSheet.filterType.displayName=File Type
|
||||||
FileTypesByExtNode.createSheet.filterType.desc=no description
|
FileTypesByExtNode.createSheet.filterType.desc=no description
|
||||||
FileTypesByExtNode.createSheet.fileExt.name=File Extensions
|
FileTypesByExtNode.createSheet.fileExt.name=File Extensions
|
||||||
FileTypesByExtNode.createSheet.fileExt.displayName=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.filePath.displayName=\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9
|
||||||
BlackboardArtifactNode.createSheet.dataSrc.name=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9
|
BlackboardArtifactNode.createSheet.dataSrc.name=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9
|
||||||
BlackboardArtifactNode.createSheet.dataSrc.displayName=\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.srcFile.text=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb
|
||||||
BlackboardArtifactTagNode.createSheet.unavail.text=\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
|
BlackboardArtifactTagNode.createSheet.unavail.text=\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
|
||||||
BlackboardArtifactTagNode.createSheet.srcFilePath.text=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9
|
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.fsDelFilter.text=\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0
|
||||||
DeletedContent.allDelFilter.text=\u3059\u3079\u3066
|
DeletedContent.allDelFilter.text=\u3059\u3079\u3066
|
||||||
DeletedContent.deletedContentsNode.name=\u524a\u9664\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb
|
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.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.name=\u30d5\u30a3\u30eb\u30bf\u30fc\u30bf\u30a4\u30d7
|
||||||
DeletedContent.createSheet.filterType.displayName=\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.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
|
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.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.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.name=\u30d5\u30a3\u30eb\u30bf\u30fc\u30bf\u30a4\u30d7
|
||||||
FileSize.createSheet.filterType.displayName=\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.autoDocPdfFilter.text=PDF
|
||||||
FileTypeExtensionFilters.autDocTxtFilter.text=\u30d7\u30ec\u30fc\u30f3\u30c6\u30ad\u30b9\u30c8
|
FileTypeExtensionFilters.autDocTxtFilter.text=\u30d7\u30ec\u30fc\u30f3\u30c6\u30ad\u30b9\u30c8
|
||||||
FileTypeExtensionFilters.autDocRtfFilter.text=\u30ea\u30c3\u30c1\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.filterType.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
||||||
FileTypesByExtNode.createSheet.fileExt.name=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50
|
FileTypesByExtNode.createSheet.fileExt.name=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50
|
||||||
FileTypesByExtNode.createSheet.fileExt.displayName=\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.AddContentTagAction;
|
||||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||||
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
|
||||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.HashSearchAction;
|
import org.sleuthkit.autopsy.directorytree.HashSearchAction;
|
||||||
@ -62,8 +61,7 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
|||||||
} else {
|
} else {
|
||||||
ext = "." + ext;
|
ext = "." + ext;
|
||||||
}
|
}
|
||||||
if (ImageUtils.isImageThumbnailSupported(file)
|
if (FileTypeExtensions.getImageExtensions().contains(ext)) {
|
||||||
|| FileTypeExtensions.getImageExtensions().contains(ext)) {
|
|
||||||
return "org/sleuthkit/autopsy/images/image-file.png"; //NON-NLS
|
return "org/sleuthkit/autopsy/images/image-file.png"; //NON-NLS
|
||||||
}
|
}
|
||||||
if (FileTypeExtensions.getVideoExtensions().contains(ext)) {
|
if (FileTypeExtensions.getVideoExtensions().contains(ext)) {
|
||||||
|
@ -45,6 +45,7 @@ import org.sleuthkit.datamodel.File;
|
|||||||
import org.sleuthkit.datamodel.FsContent;
|
import org.sleuthkit.datamodel.FsContent;
|
||||||
import org.sleuthkit.datamodel.LayoutFile;
|
import org.sleuthkit.datamodel.LayoutFile;
|
||||||
import org.sleuthkit.datamodel.LocalFile;
|
import org.sleuthkit.datamodel.LocalFile;
|
||||||
|
import org.sleuthkit.datamodel.SlackFile;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
@ -483,6 +484,11 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
return new FileNode(f, false);
|
return new FileNode(f, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileNode visit(SlackFile f) {
|
||||||
|
return new FileNode(f, false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractNode defaultVisit(Content di) {
|
protected AbstractNode defaultVisit(Content di) {
|
||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2016 Basis Technology Corp.
|
* Copyright 2011-2017 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");
|
||||||
@ -18,9 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
@ -31,6 +34,8 @@ import org.openide.util.Lookup;
|
|||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
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.Content;
|
||||||
import org.sleuthkit.datamodel.ContentVisitor;
|
import org.sleuthkit.datamodel.ContentVisitor;
|
||||||
import org.sleuthkit.datamodel.DerivedFile;
|
import org.sleuthkit.datamodel.DerivedFile;
|
||||||
@ -40,6 +45,7 @@ import org.sleuthkit.datamodel.LayoutFile;
|
|||||||
import org.sleuthkit.datamodel.LocalFile;
|
import org.sleuthkit.datamodel.LocalFile;
|
||||||
import org.sleuthkit.datamodel.SlackFile;
|
import org.sleuthkit.datamodel.SlackFile;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitItemVisitor;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,10 +53,24 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
*/
|
*/
|
||||||
public final class FileTypes implements AutopsyVisitableItem {
|
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 final SleuthkitCase skCase;
|
||||||
private boolean showCounts = true;
|
|
||||||
|
|
||||||
FileTypes(SleuthkitCase skCase) {
|
FileTypes(SleuthkitCase skCase) {
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
@ -66,15 +86,16 @@ public final class FileTypes implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the nodes show counts?
|
* Check the db to determine if the nodes should show child counts.
|
||||||
*
|
*/
|
||||||
*
|
void updateShowCounts() {
|
||||||
* @return True, unless the DB has more than 200k rows.
|
/*
|
||||||
|
* once we have passed the threshold, we don't need to keep checking the
|
||||||
|
* number of rows in tsk_files
|
||||||
*/
|
*/
|
||||||
boolean shouldShowCounts() {
|
|
||||||
if (showCounts) {
|
if (showCounts) {
|
||||||
try {
|
try {
|
||||||
if (skCase.countFilesWhere("1=1") > 200000) { //NON-NLS
|
if (skCase.countFilesWhere("1=1") > NODE_COUNT_FILE_TABLE_THRESHOLD) { //NON-NLS
|
||||||
showCounts = false;
|
showCounts = false;
|
||||||
}
|
}
|
||||||
} catch (TskCoreException tskCoreException) {
|
} catch (TskCoreException tskCoreException) {
|
||||||
@ -82,10 +103,7 @@ public final class FileTypes implements AutopsyVisitableItem {
|
|||||||
logger.log(Level.SEVERE, "Error counting files.", tskCoreException); //NON-NLS
|
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.
|
* 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 FileTypesByExtension(FileTypes.this),
|
||||||
new FileTypesByMimeType(FileTypes.this))),
|
new FileTypesByMimeType(FileTypes.this))),
|
||||||
Lookups.singleton(NAME));
|
Lookups.singleton(NAME));
|
||||||
setName(NAME);
|
this.setName(NAME);
|
||||||
setDisplayName(NAME);
|
this.setDisplayName(NAME);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); //NON-NLS
|
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
|
* Updates the display name of the mediaSubTypeNode to include the count
|
||||||
* of files which it represents.
|
* of files which it represents.
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages("FileTypes.bgCounting.placeholder=(counting...)")
|
@NbBundle.Messages("FileTypes.bgCounting.placeholder= (counting...)")
|
||||||
void updateDisplayName() {
|
void updateDisplayName() {
|
||||||
if (typesRoot.shouldShowCounts()) {
|
if (typesRoot.showCounts) {
|
||||||
//only show "(counting...)" the first time, otherwise it is distracting.
|
//only show "(counting...)" the first time, otherwise it is distracting.
|
||||||
setDisplayName(getDisplayNameBase() + ((childCount < 0) ? Bundle.FileTypes_bgCounting_placeholder()
|
setDisplayName(getDisplayNameBase() + ((childCount < 0) ? Bundle.FileTypes_bgCounting_placeholder()
|
||||||
: ("(" + childCount + ")"))); //NON-NLS
|
: ("(" + childCount + ")"))); //NON-NLS
|
||||||
@ -239,8 +257,186 @@ public final class FileTypes implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
} else {
|
} 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
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-17 Basis Technology Corp.
|
* Copyright 2011-2017 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,7 +24,10 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.logging.Level;
|
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.ChildFactory;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
import org.openide.nodes.Node;
|
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.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesKey;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
@ -87,7 +92,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
Case.getCurrentCase();
|
Case.getCurrentCase();
|
||||||
typesRoot.shouldShowCounts();
|
typesRoot.updateShowCounts();
|
||||||
update();
|
update();
|
||||||
} catch (IllegalStateException notUsed) {
|
} catch (IllegalStateException notUsed) {
|
||||||
/**
|
/**
|
||||||
@ -147,8 +152,9 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
* provides updates on events
|
* provides updates on events
|
||||||
*/
|
*/
|
||||||
private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) {
|
private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) {
|
||||||
|
|
||||||
super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, o), true),
|
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;
|
this.filter = filter;
|
||||||
|
|
||||||
// root node of tree
|
// root node of tree
|
||||||
@ -157,7 +163,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
super.setDisplayName(FNAME);
|
super.setDisplayName(FNAME);
|
||||||
} // sub-node in file tree (i.e. documents, exec, etc.)
|
} // sub-node in file tree (i.e. documents, exec, etc.)
|
||||||
else {
|
else {
|
||||||
super.setName(filter.getName());
|
super.setName(filter.getDisplayName());
|
||||||
super.setDisplayName(filter.getDisplayName());
|
super.setDisplayName(filter.getDisplayName());
|
||||||
}
|
}
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); //NON-NLS
|
||||||
@ -181,7 +187,16 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
ss = Sheet.createPropertiesSet();
|
ss = Sheet.createPropertiesSet();
|
||||||
s.put(ss);
|
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;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +287,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
super(typesRoot, Children.create(new FileExtensionNodeChildren(filter, skCase, o), true),
|
super(typesRoot, Children.create(new FileExtensionNodeChildren(filter, skCase, o), true),
|
||||||
Lookups.singleton(filter.getDisplayName()));
|
Lookups.singleton(filter.getDisplayName()));
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
setName(filter.getName());
|
super.setName(filter.getDisplayName());
|
||||||
updateDisplayName();
|
updateDisplayName();
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
|
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) {
|
private String createQuery(FileTypesByExtension.SearchFilterInterface filter) {
|
||||||
StringBuilder query = new StringBuilder();
|
if (filter.getFilter().isEmpty()) {
|
||||||
query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS
|
// We should never be given a search filter without extensions
|
||||||
if (UserPreferences.hideKnownFilesInViewsTree()) {
|
// but if we are it is clearly a programming error so we throw
|
||||||
query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS
|
// an IllegalArgumentException.
|
||||||
|
throw new IllegalArgumentException("Empty filter list passed to createQuery()"); // NON-NLS
|
||||||
}
|
}
|
||||||
query.append(" AND (NULL"); //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()) {
|
for (String s : filter.getFilter()) {
|
||||||
query.append(" OR LOWER(name) LIKE LOWER('%").append(s).append("')"); //NON-NLS
|
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.
|
* 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 SleuthkitCase skCase;
|
||||||
private final FileTypesByExtension.SearchFilterInterface filter;
|
private final FileTypesByExtension.SearchFilterInterface filter;
|
||||||
@ -387,9 +421,10 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<Content> list) {
|
protected boolean createKeys(List<FileTypesKey> list) {
|
||||||
try {
|
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) {
|
} 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
|
||||||
}
|
}
|
||||||
@ -397,7 +432,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(Content key) {
|
protected Node createNodeForKey(FileTypesKey key) {
|
||||||
return key.accept(new FileTypes.FileNodeCreationVisitor());
|
return key.accept(new FileTypes.FileNodeCreationVisitor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -419,10 +454,10 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
FileTypeExtensions.getArchiveExtensions()),
|
FileTypeExtensions.getArchiveExtensions()),
|
||||||
TSK_DOCUMENT_FILTER(3, "TSK_DOCUMENT_FILTER", //NON-NLS
|
TSK_DOCUMENT_FILTER(3, "TSK_DOCUMENT_FILTER", //NON-NLS
|
||||||
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskDocumentFilter.text"),
|
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
|
TSK_EXECUTABLE_FILTER(3, "TSK_EXECUTABLE_FILTER", //NON-NLS
|
||||||
NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskExecFilter.text"),
|
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 int id;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
@ -30,16 +30,20 @@ import java.util.Map;
|
|||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
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.ChildFactory;
|
import org.openide.nodes.ChildFactory;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
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.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesKey;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
@ -55,6 +59,7 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
public final class FileTypesByMimeType extends Observable implements AutopsyVisitableItem {
|
public final class FileTypesByMimeType extends Observable implements AutopsyVisitableItem {
|
||||||
|
|
||||||
private final static Logger logger = Logger.getLogger(FileTypesByMimeType.class.getName());
|
private final static Logger logger = Logger.getLogger(FileTypesByMimeType.class.getName());
|
||||||
|
|
||||||
private final SleuthkitCase skCase;
|
private final SleuthkitCase skCase;
|
||||||
/**
|
/**
|
||||||
* The nodes of this tree will be determined dynamically by the mimetypes
|
* 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.
|
* 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 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 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
|
* The pcl is in the class because it has the easiest mechanisms to add and
|
||||||
* remove itself during its life cycles.
|
* remove itself during its life cycles.
|
||||||
*/
|
*/
|
||||||
private final PropertyChangeListener pcl;
|
private final PropertyChangeListener pcl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the query on the database to get all distinct MIME types of
|
* Create the base expression used as the where clause in the queries for
|
||||||
* files in it, and populate the hashmap with those results.
|
* 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() {
|
static private String createBaseWhereExpr() {
|
||||||
String query = "SELECT mime_type,count(*) as count from tsk_files "
|
return "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")"
|
||||||
+ " where mime_type IS NOT null "
|
|
||||||
+ " AND dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()
|
|
||||||
+ " AND (type IN ("
|
+ " AND (type IN ("
|
||||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal() + ","
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal() + ","
|
||||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal() + ","
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal() + ","
|
||||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal() + ","
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal() + ","
|
||||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()
|
||||||
+ ((UserPreferences.hideSlackFilesInViewsTree()) ? ""
|
+ (hideSlackFilesInViewsTree() ? "" : ("," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
|
||||||
: ("," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
|
+ "))"
|
||||||
+ "))" + " GROUP BY mime_type";
|
+ (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) {
|
synchronized (existingMimeTypeCounts) {
|
||||||
existingMimeTypeCounts.clear();
|
existingMimeTypeCounts.clear();
|
||||||
|
|
||||||
@ -114,7 +136,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (TskCoreException | SQLException ex) {
|
} 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 {
|
try {
|
||||||
Case.getCurrentCase();
|
Case.getCurrentCase();
|
||||||
typesRoot.shouldShowCounts();
|
typesRoot.updateShowCounts();
|
||||||
populateHashMap();
|
populateHashMap();
|
||||||
} catch (IllegalStateException notUsed) {
|
} catch (IllegalStateException notUsed) {
|
||||||
/**
|
/**
|
||||||
@ -187,11 +209,12 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
*/
|
*/
|
||||||
class ByMimeTypeNode extends DisplayableItemNode {
|
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();
|
final String NAME = Bundle.FileTypesByMimeType_name_text();
|
||||||
|
|
||||||
ByMimeTypeNode() {
|
ByMimeTypeNode() {
|
||||||
super(Children.create(new ByMimeTypeNodeChildren(), true));
|
super(Children.create(new ByMimeTypeNodeChildren(), true), Lookups.singleton(Bundle.FileTypesByMimeType_name_text()));
|
||||||
super.setName(NAME);
|
super.setName(NAME);
|
||||||
super.setDisplayName(NAME);
|
super.setDisplayName(NAME);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png");
|
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 {
|
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) {
|
MediaTypeNode(String name) {
|
||||||
super(Children.create(new MediaTypeNodeChildren(name), true));
|
super(Children.create(new MediaTypeNodeChildren(name), true), Lookups.singleton(name));
|
||||||
setName(name);
|
setName(name);
|
||||||
setDisplayName(name);
|
setDisplayName(name);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png");
|
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);
|
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
|
@Override
|
||||||
public String getItemType() {
|
public String getItemType() {
|
||||||
return getClass().getName();
|
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 {
|
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 mimeType;
|
||||||
private final String subType;
|
private final String subType;
|
||||||
|
|
||||||
private MediaSubTypeNode(String mimeType) {
|
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.mimeType = mimeType;
|
||||||
this.subType = StringUtils.substringAfter(mimeType, "/");
|
this.subType = StringUtils.substringAfter(mimeType, "/");
|
||||||
super.setName(mimeType);
|
super.setName(mimeType);
|
||||||
|
super.setDisplayName(subType);
|
||||||
updateDisplayName();
|
updateDisplayName();
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
|
||||||
|
|
||||||
addObserver(this);
|
addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,6 +392,17 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
public <T> T accept(DisplayableItemNodeVisitor< T> v) {
|
public <T> T accept(DisplayableItemNodeVisitor< T> v) {
|
||||||
return v.visit(this);
|
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
|
@Override
|
||||||
public String getItemType() {
|
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
|
* 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
|
* files that match MimeType which is represented by this position in the
|
||||||
* tree.
|
* tree.
|
||||||
*/
|
*/
|
||||||
private class MediaSubTypeNodeChildren extends ChildFactory.Detachable<Content> implements Observer {
|
private class MediaSubTypeNodeChildren extends ChildFactory.Detachable<FileTypesKey> implements Observer {
|
||||||
|
|
||||||
private final String mimeType;
|
private final String mimeType;
|
||||||
|
|
||||||
@ -411,23 +440,13 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
this.mimeType = mimeType;
|
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
|
@Override
|
||||||
protected boolean createKeys(List<Content> list) {
|
protected boolean createKeys(List<FileTypesKey> list) {
|
||||||
try {
|
try {
|
||||||
List<AbstractFile> files = skCase.findAllFilesWhere(createQuery(mimeType));
|
list.addAll(skCase.findAllFilesWhere(createBaseWhereExpr() + " AND mime_type = '" + mimeType + "'")
|
||||||
list.addAll(files);
|
.stream().map(f -> new FileTypesKey(f)).collect(Collectors.toList())); //NON-NLS
|
||||||
} catch (TskCoreException ex) {
|
} 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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -437,19 +456,9 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
refresh(true);
|
refresh(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the content to populate the Directory Listing Table view for
|
|
||||||
* each file
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(Content key) {
|
protected Node createNodeForKey(FileTypesKey key) {
|
||||||
return key.accept(new FileTypes.FileNodeCreationVisitor());
|
return key.accept(new FileTypes.FileNodeCreationVisitor());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ import java.sql.ResultSet;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -33,6 +32,7 @@ import java.util.Observable;
|
|||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
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.ChildFactory;
|
import org.openide.nodes.ChildFactory;
|
||||||
import org.openide.nodes.Children;
|
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
|
+ " OR attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()//NON-NLS
|
||||||
+ ")"; //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) {
|
public KeywordHits(SleuthkitCase skCase) {
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
keywordResults = new KeywordResults();
|
keywordResults = new KeywordResults();
|
||||||
@ -265,7 +269,6 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
addRegExpToList(listMap, reg, word, id);
|
addRegExpToList(listMap, reg, word, id);
|
||||||
}
|
}
|
||||||
} else {//single term
|
} else {//single term
|
||||||
|
|
||||||
if ("1".equals(kwType) || reg == null) { //literal, substring or exact
|
if ("1".equals(kwType) || reg == null) { //literal, substring or exact
|
||||||
/*
|
/*
|
||||||
* Substring, treated same as exact match. "1" is
|
* Substring, treated same as exact match. "1" is
|
||||||
@ -626,9 +629,8 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLeafTypeNode() {
|
public boolean isLeafTypeNode() {
|
||||||
List<String> instances = keywordResults.getKeywordInstances(setName, keyword);
|
|
||||||
// is this an exact/substring match (i.e. did we use the DEFAULT name)?
|
// 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
|
@Override
|
||||||
@ -661,7 +663,6 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -706,7 +707,6 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
private final String keyword;
|
private final String keyword;
|
||||||
private final String setName;
|
private final String setName;
|
||||||
private final Map<RegExpInstanceKey, DisplayableItemNode> nodesMap = new HashMap<>();
|
|
||||||
|
|
||||||
private RegExpInstancesFactory(String setName, String keyword) {
|
private RegExpInstancesFactory(String setName, String keyword) {
|
||||||
super();
|
super();
|
||||||
@ -720,29 +720,20 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
// The keys are different depending on what we are displaying.
|
// The keys are different depending on what we are displaying.
|
||||||
// regexp get another layer to show instances.
|
// regexp get another layer to show instances.
|
||||||
// Exact/substring matches don't.
|
// Exact/substring matches don't.
|
||||||
if ((instances.size() == 1) && (instances.get(0).equals(DEFAULT_INSTANCE_NAME))) {
|
if (isOnlyDefaultInstance(instances)) {
|
||||||
for (Long id : keywordResults.getArtifactIds(setName, keyword, DEFAULT_INSTANCE_NAME)) {
|
list.addAll(keywordResults.getArtifactIds(setName, keyword, DEFAULT_INSTANCE_NAME).stream()
|
||||||
RegExpInstanceKey key = new RegExpInstanceKey(id);
|
.map(RegExpInstanceKey::new)
|
||||||
nodesMap.computeIfAbsent(key, k -> createNode(k));
|
.collect(Collectors.toList()));
|
||||||
list.add(key);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for (String instance : instances) {
|
list.addAll(instances.stream()
|
||||||
RegExpInstanceKey key = new RegExpInstanceKey(instance);
|
.map(RegExpInstanceKey::new)
|
||||||
nodesMap.computeIfAbsent(key, k -> createNode(k));
|
.collect(Collectors.toList()));
|
||||||
list.add(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(RegExpInstanceKey key) {
|
protected Node createNodeForKey(RegExpInstanceKey key) {
|
||||||
return nodesMap.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DisplayableItemNode createNode(RegExpInstanceKey key) {
|
|
||||||
if (key.isRegExp()) {
|
if (key.isRegExp()) {
|
||||||
return new RegExpInstanceNode(setName, keyword, key.getRegExpKey());
|
return new RegExpInstanceNode(setName, keyword, key.getRegExpKey());
|
||||||
} else {
|
} else {
|
||||||
@ -750,6 +741,7 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
return createBlackboardArtifactNode(key.getIdKey());
|
return createBlackboardArtifactNode(key.getIdKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -884,7 +876,6 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
private final String keyword;
|
private final String keyword;
|
||||||
private final String setName;
|
private final String setName;
|
||||||
private final String instance;
|
private final String instance;
|
||||||
private final Map<Long, BlackboardArtifactNode> nodesMap = new HashMap<>();
|
|
||||||
|
|
||||||
private HitsFactory(String setName, String keyword, String instance) {
|
private HitsFactory(String setName, String keyword, String instance) {
|
||||||
super();
|
super();
|
||||||
@ -895,16 +886,13 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<Long> list) {
|
protected boolean createKeys(List<Long> list) {
|
||||||
for (Long id : keywordResults.getArtifactIds(setName, keyword, instance)) {
|
list.addAll(keywordResults.getArtifactIds(setName, keyword, instance));
|
||||||
nodesMap.computeIfAbsent(id, i -> createBlackboardArtifactNode(i));
|
|
||||||
list.add(id);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(Long artifactId) {
|
protected Node createNodeForKey(Long artifactId) {
|
||||||
return nodesMap.get(artifactId);
|
return createBlackboardArtifactNode(artifactId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -417,8 +417,10 @@ final class ExtractUnallocAction extends AbstractAction {
|
|||||||
try {
|
try {
|
||||||
List<LayoutFile> lflst = new ArrayList<>();
|
List<LayoutFile> lflst = new ArrayList<>();
|
||||||
for (Content layout : vd.getChildren()) {
|
for (Content layout : vd.getChildren()) {
|
||||||
|
if(layout instanceof LayoutFile){
|
||||||
lflst.add((LayoutFile) layout);
|
lflst.add((LayoutFile) layout);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return lflst;
|
return lflst;
|
||||||
} catch (TskCoreException tce) {
|
} catch (TskCoreException tce) {
|
||||||
logger.log(Level.WARNING, "Could not get list of Layout Files, failed at visiting Layout Directory", tce); //NON-NLS
|
logger.log(Level.WARNING, "Could not get list of Layout Files, failed at visiting Layout Directory", tce); //NON-NLS
|
||||||
|
@ -51,6 +51,7 @@ final class GetFilesCountVisitor extends ContentVisitor.Default<Long> {
|
|||||||
queryB.append(") )");
|
queryB.append(") )");
|
||||||
queryB.append(" AND ( (meta_type = ").append(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()); //NON-NLS
|
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_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(") 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(" AND (name != '.') AND (name != '..')"); //NON-NLS
|
||||||
queryB.append(") )");
|
queryB.append(") )");
|
||||||
|
@ -537,10 +537,12 @@ public final class FilesSet implements Serializable {
|
|||||||
case FILES:
|
case FILES:
|
||||||
return file.isFile();
|
return file.isFile();
|
||||||
case DIRECTORIES:
|
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:
|
case FILES_AND_DIRECTORIES:
|
||||||
return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG
|
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:
|
case ALL:
|
||||||
return true; //Effectively ignores the metatype condition when All is selected.
|
return true; //Effectively ignores the metatype condition when All is selected.
|
||||||
default:
|
default:
|
||||||
|
@ -23,17 +23,13 @@ import java.io.FilenameFilter;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
|
||||||
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
|
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
|
||||||
import org.sleuthkit.autopsy.casemodule.GeneralFilter;
|
|
||||||
|
|
||||||
final class PathUtils {
|
final class PathUtils {
|
||||||
|
|
||||||
private static final List<String> CASE_METADATA_FILE_EXTS = Arrays.asList(new String[]{CaseMetadata.getFileExtension()});
|
private final static String CASE_METADATA_EXT = CaseMetadata.getFileExtension();
|
||||||
private static final GeneralFilter caseMetadataFileFilter = new GeneralFilter(CASE_METADATA_FILE_EXTS, "Autopsy Case File");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches a given folder for the most recently modified case folder for a
|
* Searches a given folder for the most recently modified case folder for a
|
||||||
@ -83,34 +79,6 @@ final class PathUtils {
|
|||||||
return caseFolderPaths;
|
return caseFolderPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether or not there is a case metadata file in a given
|
|
||||||
* folder.
|
|
||||||
*
|
|
||||||
* @param folderPath Path to the folder to search.
|
|
||||||
*
|
|
||||||
* @return True or false.
|
|
||||||
*/
|
|
||||||
static boolean hasCaseMetadataFile(Path folderPath) {
|
|
||||||
/**
|
|
||||||
* TODO: If need be, this can be rewritten without the FilenameFilter so
|
|
||||||
* that it does not necessarily visit every file in the folder.
|
|
||||||
*/
|
|
||||||
File folder = folderPath.toFile();
|
|
||||||
if (!folder.isDirectory()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] caseDataFiles = folder.list((File folder1, String fileName) -> {
|
|
||||||
File file = new File(folder1, fileName);
|
|
||||||
if (file.isFile()) {
|
|
||||||
return caseMetadataFileFilter.accept(file);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
return caseDataFiles.length != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the case name from a case folder path.
|
* Extracts the case name from a case folder path.
|
||||||
*
|
*
|
||||||
@ -141,6 +109,12 @@ final class PathUtils {
|
|||||||
return Paths.get(caseFoldersPath.toString(), folderName);
|
return Paths.get(caseFoldersPath.toString(), folderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supress creation of instances of this class.
|
||||||
|
*/
|
||||||
|
private PathUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
private static class CaseFolderFilter implements FilenameFilter {
|
private static class CaseFolderFilter implements FilenameFilter {
|
||||||
|
|
||||||
private final String caseName;
|
private final String caseName;
|
||||||
@ -152,28 +126,37 @@ final class PathUtils {
|
|||||||
@Override
|
@Override
|
||||||
public boolean accept(File folder, String fileName) {
|
public boolean accept(File folder, String fileName) {
|
||||||
File file = new File(folder, fileName);
|
File file = new File(folder, fileName);
|
||||||
if (file.isDirectory() && fileName.length() > TimeStampUtils.getTimeStampLength()) {
|
if (fileName.length() > TimeStampUtils.getTimeStampLength() && file.isDirectory()) {
|
||||||
Path filePath = Paths.get(file.getPath());
|
|
||||||
if (TimeStampUtils.endsWithTimeStamp(fileName)) {
|
if (TimeStampUtils.endsWithTimeStamp(fileName)) {
|
||||||
if (null != caseName) {
|
if (null != caseName) {
|
||||||
String fileNamePrefix = fileName.substring(0, fileName.length() - TimeStampUtils.getTimeStampLength());
|
String fileNamePrefix = fileName.substring(0, fileName.length() - TimeStampUtils.getTimeStampLength());
|
||||||
if (fileNamePrefix.equals(caseName)) {
|
if (fileNamePrefix.equals(caseName)) {
|
||||||
return hasCaseMetadataFile(filePath);
|
return hasCaseMetadataFile(file);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return hasCaseMetadataFile(filePath);
|
return hasCaseMetadataFile(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supress creation of instances of this class.
|
* Determines whether or not there is a case metadata file in a given
|
||||||
|
* folder.
|
||||||
|
*
|
||||||
|
* @param folder The file object representing the folder to search.
|
||||||
|
*
|
||||||
|
* @return True or false.
|
||||||
*/
|
*/
|
||||||
private PathUtils() {
|
private static boolean hasCaseMetadataFile(File folder) {
|
||||||
|
for (File file : folder.listFiles()) {
|
||||||
|
if (file.getName().toLowerCase().endsWith(CASE_METADATA_EXT) && file.isFile()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2015 Basis Technology Corp.
|
* Copyright 2015-2017 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");
|
||||||
@ -174,6 +174,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
validateSettings();
|
validateSettings();
|
||||||
|
enableOptionsBasedOnMode(getModeFromRadioButtons());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -306,10 +307,13 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
|
|||||||
*/
|
*/
|
||||||
boolean valid() {
|
boolean valid() {
|
||||||
|
|
||||||
if (!cbJoinAutoIngestCluster.isSelected()) {
|
if (!cbJoinAutoIngestCluster.isSelected()) { //hide the invalid field warnings when in stand alone mode
|
||||||
|
jLabelInvalidImageFolder.setVisible(false);
|
||||||
|
jLabelInvalidResultsFolder.setVisible(false);
|
||||||
|
sharedSettingsErrorTextField.setVisible(false);
|
||||||
|
configButtonErrorTextField.setText("");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isValidNodePanel = true;
|
boolean isValidNodePanel = true;
|
||||||
|
|
||||||
switch (getModeFromRadioButtons()) {
|
switch (getModeFromRadioButtons()) {
|
||||||
@ -326,6 +330,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REVIEW:
|
case REVIEW:
|
||||||
|
jLabelInvalidImageFolder.setVisible(false);
|
||||||
if (!validateResultsPath()) {
|
if (!validateResultsPath()) {
|
||||||
isValidNodePanel = false;
|
isValidNodePanel = false;
|
||||||
}
|
}
|
||||||
@ -596,23 +601,24 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
private void enableOptionsBasedOnMode(OptionsUiMode mode) {
|
private void enableOptionsBasedOnMode(OptionsUiMode mode) {
|
||||||
if (mode != OptionsUiMode.DOWNLOADING_CONFIGURATION) {
|
if (mode != OptionsUiMode.DOWNLOADING_CONFIGURATION) {
|
||||||
jRadioButtonAutomated.setEnabled(cbJoinAutoIngestCluster.isSelected());
|
boolean nonMasterSharedConfig = !masterNodeCheckBox.isSelected() && sharedConfigCheckbox.isSelected();
|
||||||
jRadioButtonReview.setEnabled(cbJoinAutoIngestCluster.isSelected());
|
jRadioButtonAutomated.setEnabled(cbJoinAutoIngestCluster.isSelected() && !sharedConfigCheckbox.isSelected());
|
||||||
|
jRadioButtonReview.setEnabled(cbJoinAutoIngestCluster.isSelected() && !sharedConfigCheckbox.isSelected());
|
||||||
|
|
||||||
jLabelSelectInputFolder.setEnabled(mode == OptionsUiMode.AIM);
|
jLabelSelectInputFolder.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
|
||||||
inputPathTextField.setEnabled(mode == OptionsUiMode.AIM);
|
inputPathTextField.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
|
||||||
browseInputFolderButton.setEnabled(mode == OptionsUiMode.AIM);
|
browseInputFolderButton.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
|
||||||
|
|
||||||
jLabelSelectOutputFolder.setEnabled(mode == OptionsUiMode.AIM || mode == OptionsUiMode.REVIEW);
|
jLabelSelectOutputFolder.setEnabled((mode == OptionsUiMode.AIM && !nonMasterSharedConfig) || mode == OptionsUiMode.REVIEW);
|
||||||
outputPathTextField.setEnabled(mode == OptionsUiMode.AIM || mode == OptionsUiMode.REVIEW);
|
outputPathTextField.setEnabled((mode == OptionsUiMode.AIM && !nonMasterSharedConfig) || mode == OptionsUiMode.REVIEW);
|
||||||
browseOutputFolderButton.setEnabled(mode == OptionsUiMode.AIM || mode == OptionsUiMode.REVIEW);
|
browseOutputFolderButton.setEnabled((mode == OptionsUiMode.AIM && !nonMasterSharedConfig) || mode == OptionsUiMode.REVIEW);
|
||||||
|
|
||||||
jPanelSharedConfig.setEnabled(mode == OptionsUiMode.AIM);
|
jPanelSharedConfig.setEnabled(mode == OptionsUiMode.AIM);
|
||||||
|
|
||||||
jPanelIngestSettings.setEnabled(mode == OptionsUiMode.AIM);
|
jPanelIngestSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
|
||||||
bnEditIngestSettings.setEnabled(mode == OptionsUiMode.AIM);
|
bnEditIngestSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
|
||||||
bnAdvancedSettings.setEnabled(mode == OptionsUiMode.AIM);
|
bnAdvancedSettings.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
|
||||||
bnLogging.setEnabled(mode == OptionsUiMode.AIM);
|
bnLogging.setEnabled(mode == OptionsUiMode.AIM && !nonMasterSharedConfig);
|
||||||
jPanelSharedConfig.setEnabled(mode == OptionsUiMode.AIM);
|
jPanelSharedConfig.setEnabled(mode == OptionsUiMode.AIM);
|
||||||
sharedConfigCheckbox.setEnabled(mode == OptionsUiMode.AIM);
|
sharedConfigCheckbox.setEnabled(mode == OptionsUiMode.AIM);
|
||||||
masterNodeCheckBox.setEnabled(mode == OptionsUiMode.AIM && sharedConfigCheckbox.isSelected());
|
masterNodeCheckBox.setEnabled(mode == OptionsUiMode.AIM && sharedConfigCheckbox.isSelected());
|
||||||
@ -1389,12 +1395,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
void setEnabledStateForSharedConfiguration() {
|
void setEnabledStateForSharedConfiguration() {
|
||||||
if (jRadioButtonAutomated.isSelected() && cbJoinAutoIngestCluster.isSelected()) {
|
if (jRadioButtonAutomated.isSelected() && cbJoinAutoIngestCluster.isSelected()) {
|
||||||
if (sharedConfigCheckbox.isEnabled() && sharedConfigCheckbox.isSelected()) {
|
enableOptionsBasedOnMode(OptionsUiMode.AIM);
|
||||||
setEnabledState(masterNodeCheckBox.isSelected());
|
|
||||||
} else {
|
|
||||||
// If we are in AIM mode and shared config is not enabled, allow this
|
|
||||||
setEnabledState(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ AdvancedAutoIngestSettingsPanel.lbSecondsBetweenJobs.toolTipText=A wait time use
|
|||||||
AdvancedAutoIngestSettingsPanel.tbWarning.text=WARNING: Ensure you know what you are doing before modifying these values. Informed use can improve system performance. Misuse can cause system performance degradation and data loss. Please consult the user guide for details.
|
AdvancedAutoIngestSettingsPanel.tbWarning.text=WARNING: Ensure you know what you are doing before modifying these values. Informed use can improve system performance. Misuse can cause system performance degradation and data loss. Please consult the user guide for details.
|
||||||
AdvancedAutoIngestSettingsPanel.threadCountLabel.text=For this computer, a maximum of {0} file ingest threads should be used.
|
AdvancedAutoIngestSettingsPanel.threadCountLabel.text=For this computer, a maximum of {0} file ingest threads should be used.
|
||||||
AIMIngestSettingsPanel.browseGlobalSettingsButton.text=Browse
|
AIMIngestSettingsPanel.browseGlobalSettingsButton.text=Browse
|
||||||
AIMIngestSettingsPanel.globalSettingsCheckbox.text=Use shared configuration in folder:
|
|
||||||
AIMIngestSettingsPanel.globalSettingsErrorTextField.text=
|
AIMIngestSettingsPanel.globalSettingsErrorTextField.text=
|
||||||
AIMIngestSettingsPanel.globalSettingsTextField.text=
|
AIMIngestSettingsPanel.globalSettingsTextField.text=
|
||||||
AIMIngestSettingsPanel.jButton1.text=Download shared settings
|
AIMIngestSettingsPanel.jButton1.text=Download shared settings
|
||||||
@ -33,7 +32,6 @@ AutoIngestSettingsPanel.downloadButton.text=Download Config
|
|||||||
AutoIngestSettingsPanel.EmptySettingsDirectory=Enter path to settings directory
|
AutoIngestSettingsPanel.EmptySettingsDirectory=Enter path to settings directory
|
||||||
AutoIngestSettingsPanel.ErrorSettingDefaultFolder=Error creating default folder
|
AutoIngestSettingsPanel.ErrorSettingDefaultFolder=Error creating default folder
|
||||||
AutoIngestSettingsPanel.FileExportRules.text=File Export Rules
|
AutoIngestSettingsPanel.FileExportRules.text=File Export Rules
|
||||||
AutoIngestSettingsPanel.globalSettingsCheckbox.text=Use shared configuration in folder:
|
|
||||||
AutoIngestSettingsPanel.globalSettingsErrorTextField.text=
|
AutoIngestSettingsPanel.globalSettingsErrorTextField.text=
|
||||||
AutoIngestSettingsPanel.globalSettingsTextField.text=
|
AutoIngestSettingsPanel.globalSettingsTextField.text=
|
||||||
AutoIngestSettingsPanel.ImageDirectoryUnspecified=Shared images folder must be set
|
AutoIngestSettingsPanel.ImageDirectoryUnspecified=Shared images folder must be set
|
||||||
|
@ -127,8 +127,8 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
|
|
||||||
@NbBundle.Messages("GlobalEditListPanel.editKeyword.title=Edit Keyword")
|
@NbBundle.Messages("GlobalEditListPanel.editKeyword.title=Edit Keyword")
|
||||||
/**
|
/**
|
||||||
* Adds keywords to a keyword list, returns true if at least one keyword was successfully added and no
|
* Adds keywords to a keyword list, returns true if at least one keyword was
|
||||||
* duplicates were found.
|
* successfully added and no duplicates were found.
|
||||||
*
|
*
|
||||||
* @return - true or false
|
* @return - true or false
|
||||||
*/
|
*/
|
||||||
@ -140,7 +140,7 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
int dupeCount = 0;
|
int dupeCount = 0;
|
||||||
int badCount = 1; // Default to 1 so we enter the loop the first time
|
int badCount = 1; // Default to 1 so we enter the loop the first time
|
||||||
|
|
||||||
if (!existingKeywords.isEmpty()){ //if there is an existing keyword then this action was called by the edit button
|
if (!existingKeywords.isEmpty()) { //if there is an existing keyword then this action was called by the edit button
|
||||||
dialog.setTitle(NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.editKeyword.title"));
|
dialog.setTitle(NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.editKeyword.title"));
|
||||||
}
|
}
|
||||||
while (badCount > 0) {
|
while (badCount > 0) {
|
||||||
@ -232,7 +232,8 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
/**
|
/**
|
||||||
* Remove one or more keywords from a keyword list.
|
* Remove one or more keywords from a keyword list.
|
||||||
*
|
*
|
||||||
* @param selectedKeywords the indices of the keywords you would like to delete
|
* @param selectedKeywords the indices of the keywords you would like to
|
||||||
|
* delete
|
||||||
*/
|
*/
|
||||||
private void deleteKeywordAction(int[] selectedKeywords) {
|
private void deleteKeywordAction(int[] selectedKeywords) {
|
||||||
tableModel.deleteSelected(selectedKeywords);
|
tableModel.deleteSelected(selectedKeywords);
|
||||||
@ -411,21 +412,16 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
|||||||
public void valueChanged(ListSelectionEvent e) {
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
//respond to list selection changes in KeywordSearchListManagementPanel
|
//respond to list selection changes in KeywordSearchListManagementPanel
|
||||||
ListSelectionModel listSelectionModel = (ListSelectionModel) e.getSource();
|
ListSelectionModel listSelectionModel = (ListSelectionModel) e.getSource();
|
||||||
if (!listSelectionModel.isSelectionEmpty()) {
|
|
||||||
int index = listSelectionModel.getMinSelectionIndex();
|
|
||||||
|
|
||||||
listSelectionModel.setSelectionInterval(index, index);
|
|
||||||
XmlKeywordSearchList loader = XmlKeywordSearchList.getCurrent();
|
|
||||||
|
|
||||||
currentKeywordList = loader.getListsL(false).get(index);
|
|
||||||
tableModel.resync();
|
|
||||||
setButtonStates();
|
|
||||||
} else {
|
|
||||||
currentKeywordList = null;
|
currentKeywordList = null;
|
||||||
|
if (!listSelectionModel.isSelectionEmpty()) {
|
||||||
|
XmlKeywordSearchList loader = XmlKeywordSearchList.getCurrent();
|
||||||
|
if (listSelectionModel.getMinSelectionIndex() == listSelectionModel.getMaxSelectionIndex()) {
|
||||||
|
currentKeywordList = loader.getListsL(false).get(listSelectionModel.getMinSelectionIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
tableModel.resync();
|
tableModel.resync();
|
||||||
setButtonStates();
|
setButtonStates();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void store() {
|
public void store() {
|
||||||
|
@ -46,8 +46,7 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.title"), NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.body"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
|
if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.title"), NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.body"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
|
||||||
String toDelete = editListPanel.getCurrentKeywordList().getName();
|
deleteAction();
|
||||||
deleteAction(toDelete);
|
|
||||||
listsManagementPanel.resync();
|
listsManagementPanel.resync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,9 +55,8 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
|
|||||||
listsManagementPanel.addRenameButtonActionPerformed(new ActionListener() {
|
listsManagementPanel.addRenameButtonActionPerformed(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
String toDelete = editListPanel.getCurrentKeywordList().getName();
|
|
||||||
if (copyAction()) {
|
if (copyAction()) {
|
||||||
deleteAction(toDelete);
|
deleteAction();
|
||||||
listsManagementPanel.resync();
|
listsManagementPanel.resync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,9 +81,8 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
|
|||||||
*
|
*
|
||||||
* @param toDelete - the list to delete
|
* @param toDelete - the list to delete
|
||||||
*/
|
*/
|
||||||
private void deleteAction(String toDelete) {
|
private void deleteAction() {
|
||||||
XmlKeywordSearchList deleter = XmlKeywordSearchList.getCurrent();
|
listsManagementPanel.deleteSelected();
|
||||||
deleter.deleteList(toDelete);
|
|
||||||
editListPanel.setCurrentKeywordList(null);
|
editListPanel.setCurrentKeywordList(null);
|
||||||
editListPanel.setButtonStates();
|
editListPanel.setButtonStates();
|
||||||
listsManagementPanel.setButtonStates();
|
listsManagementPanel.setButtonStates();
|
||||||
|
@ -102,13 +102,13 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the dialogue for creating a new keyword list and adds it to the table.
|
* Opens the dialogue for creating a new keyword list and adds it to the
|
||||||
|
* table.
|
||||||
*/
|
*/
|
||||||
private void newKeywordListAction() {
|
private void newKeywordListAction() {
|
||||||
XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent();
|
XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent();
|
||||||
String listName = "";
|
String listName = "";
|
||||||
|
|
||||||
|
|
||||||
listName = (String) JOptionPane.showInputDialog(null, NbBundle.getMessage(this.getClass(), "KeywordSearch.newKwListTitle"),
|
listName = (String) JOptionPane.showInputDialog(null, NbBundle.getMessage(this.getClass(), "KeywordSearch.newKwListTitle"),
|
||||||
NbBundle.getMessage(this.getClass(), "KeywordSearch.newKeywordListMsg"), JOptionPane.PLAIN_MESSAGE, null, null, listName);
|
NbBundle.getMessage(this.getClass(), "KeywordSearch.newKeywordListMsg"), JOptionPane.PLAIN_MESSAGE, null, null, listName);
|
||||||
|
|
||||||
@ -158,15 +158,19 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
|
|||||||
boolean isIngestRunning = IngestManager.getInstance().isIngestRunning();
|
boolean isIngestRunning = IngestManager.getInstance().isIngestRunning();
|
||||||
boolean isListSelected = !listsTable.getSelectionModel().isSelectionEmpty();
|
boolean isListSelected = !listsTable.getSelectionModel().isSelectionEmpty();
|
||||||
boolean canEditList = isListSelected && !isIngestRunning;
|
boolean canEditList = isListSelected && !isIngestRunning;
|
||||||
|
boolean multiSelection = false; //can't rename or copy when multiple lists selected
|
||||||
|
if (isListSelected) {
|
||||||
|
multiSelection = (listsTable.getSelectionModel().getMaxSelectionIndex() != listsTable.getSelectionModel().getMinSelectionIndex());
|
||||||
|
}
|
||||||
// items that only need ingest to not be running
|
// items that only need ingest to not be running
|
||||||
importButton.setEnabled(!isIngestRunning);
|
importButton.setEnabled(!isIngestRunning);
|
||||||
|
|
||||||
// items that need an unlocked list w/out ingest running
|
// items that need an unlocked list w/out ingest running
|
||||||
deleteListButton.setEnabled(canEditList);
|
deleteListButton.setEnabled(canEditList);
|
||||||
renameListButton.setEnabled(canEditList);
|
renameListButton.setEnabled(canEditList);
|
||||||
|
renameListButton.setEnabled(canEditList && !multiSelection);
|
||||||
// items that only need a selected list
|
// items that only need a selected list
|
||||||
copyListButton.setEnabled(isListSelected);
|
copyListButton.setEnabled(isListSelected);
|
||||||
|
copyListButton.setEnabled(isListSelected && !multiSelection);
|
||||||
exportButton.setEnabled(isListSelected);
|
exportButton.setEnabled(isListSelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,13 +439,9 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
|
|||||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||||
}//GEN-LAST:event_importButtonActionPerformed
|
}//GEN-LAST:event_importButtonActionPerformed
|
||||||
private void listsTableKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_listsTableKeyPressed
|
private void listsTableKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_listsTableKeyPressed
|
||||||
if (evt.getKeyCode() == KeyEvent.VK_DELETE) {
|
if (evt.getKeyCode() == KeyEvent.VK_DELETE && !IngestManager.getInstance().isIngestRunning() && !listsTable.getSelectionModel().isSelectionEmpty()) {
|
||||||
int[] selected = listsTable.getSelectedRows();
|
if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.title"), NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.body"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
|
||||||
if (selected.length == 0) {
|
deleteSelected();
|
||||||
return;
|
|
||||||
} else if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.title"), NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.body"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
|
|
||||||
String listName = (String) listsTable.getModel().getValueAt(selected[0], 0);
|
|
||||||
XmlKeywordSearchList.getCurrent().deleteList(listName);
|
|
||||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
@ -492,7 +492,11 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
|
|||||||
XmlKeywordSearchList reader = XmlKeywordSearchList.getCurrent();
|
XmlKeywordSearchList reader = XmlKeywordSearchList.getCurrent();
|
||||||
|
|
||||||
List<KeywordList> toWrite = new ArrayList<>();
|
List<KeywordList> toWrite = new ArrayList<>();
|
||||||
toWrite.add(reader.getList(listName));
|
|
||||||
|
for (int index : listsTable.getSelectedRows()) {
|
||||||
|
toWrite.add(reader.getList(listsTable.getValueAt(index, 0).toString()));
|
||||||
|
}
|
||||||
|
|
||||||
final XmlKeywordSearchList exporter = new XmlKeywordSearchList(fileAbs);
|
final XmlKeywordSearchList exporter = new XmlKeywordSearchList(fileAbs);
|
||||||
boolean written = exporter.saveLists(toWrite);
|
boolean written = exporter.saveLists(toWrite);
|
||||||
if (written) {
|
if (written) {
|
||||||
@ -541,6 +545,14 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
|
|||||||
tableModel.resync();
|
tableModel.resync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void deleteSelected() {
|
||||||
|
int[] selected = listsTable.getSelectedRows();
|
||||||
|
if (selected.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tableModel.deleteSelected(selected);
|
||||||
|
}
|
||||||
|
|
||||||
private class KeywordListTableModel extends AbstractTableModel {
|
private class KeywordListTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -586,8 +598,8 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
|
|||||||
//delete selected from handle, events are fired from the handle
|
//delete selected from handle, events are fired from the handle
|
||||||
void deleteSelected(int[] selected) {
|
void deleteSelected(int[] selected) {
|
||||||
List<String> toDel = new ArrayList<>();
|
List<String> toDel = new ArrayList<>();
|
||||||
for (int i = 0; i < selected.length; i++) {
|
for (int i : selected) {
|
||||||
toDel.add((String) getValueAt(0, selected[i]));
|
toDel.add(getValueAt(i, 0).toString());
|
||||||
}
|
}
|
||||||
for (String del : toDel) {
|
for (String del : toDel) {
|
||||||
listsHandle.deleteList(del);
|
listsHandle.deleteList(del);
|
||||||
|
@ -216,6 +216,14 @@ class TestRunner(object):
|
|||||||
TestRunner._run_ant(test_data)
|
TestRunner._run_ant(test_data)
|
||||||
time.sleep(2) # Give everything a second to process
|
time.sleep(2) # Give everything a second to process
|
||||||
|
|
||||||
|
# exit if any build errors are found in antlog.txt
|
||||||
|
antlog = 'antlog.txt'
|
||||||
|
logs_path = test_data.logs_dir
|
||||||
|
for ant_line in codecs.open(os.path.join(logs_path, os.pardir, antlog)):
|
||||||
|
ant_ignoreCase = ant_line.lower()
|
||||||
|
if ant_line.startswith("BUILD FAILED") or "fatal error" in ant_ignoreCase or "crashed" in ant_ignoreCase:
|
||||||
|
Errors.print_error("Autopsy test failed. Please check the build log antlog.txt for details.")
|
||||||
|
sys.exit(1)
|
||||||
# exit if .db was not created
|
# exit if .db was not created
|
||||||
if not file_exists(test_data.get_db_path(DBType.OUTPUT)):
|
if not file_exists(test_data.get_db_path(DBType.OUTPUT)):
|
||||||
Errors.print_error("Autopsy did not run properly; No .db file was created")
|
Errors.print_error("Autopsy did not run properly; No .db file was created")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user