Merge remote-tracking branch 'upstream/develop' into improved-case-deletion-part2
@ -365,6 +365,7 @@ public class EamArtifactUtil {
|
|||||||
case CARVED:
|
case CARVED:
|
||||||
case DERIVED:
|
case DERIVED:
|
||||||
case LOCAL:
|
case LOCAL:
|
||||||
|
case LAYOUT_FILE:
|
||||||
return true;
|
return true;
|
||||||
case FS:
|
case FS:
|
||||||
return file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC);
|
return file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC);
|
||||||
|
@ -39,7 +39,7 @@ MediaFileViewer.title=Media
|
|||||||
MediaFileViewer.toolTip=Displays supported multimedia files (images, videos, audio)
|
MediaFileViewer.toolTip=Displays supported multimedia files (images, videos, audio)
|
||||||
MediaViewImagePanel.errorLabel.OOMText=Could not load file into Media View: insufficent memory.
|
MediaViewImagePanel.errorLabel.OOMText=Could not load file into Media View: insufficent memory.
|
||||||
MediaViewImagePanel.errorLabel.text=Could not load file into Media View.
|
MediaViewImagePanel.errorLabel.text=Could not load file into Media View.
|
||||||
MediaViewImagePanel.externalViewerButton.text=Open in External Viewer
|
MediaViewImagePanel.externalViewerButton.text=Open in External Viewer Ctrl+E
|
||||||
MediaViewVideoPanel.pauseButton.text=\u25ba
|
MediaViewVideoPanel.pauseButton.text=\u25ba
|
||||||
MediaViewVideoPanel.progressLabel.text=00:00
|
MediaViewVideoPanel.progressLabel.text=00:00
|
||||||
MediaViewVideoPanel.infoLabel.text=info
|
MediaViewVideoPanel.infoLabel.text=info
|
||||||
|
@ -60,7 +60,7 @@ import org.sleuthkit.datamodel.AbstractFile;
|
|||||||
* Image viewer part of the Media View layered pane. Uses JavaFX to display the
|
* Image viewer part of the Media View layered pane. Uses JavaFX to display the
|
||||||
* image.
|
* image.
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages({"MediaViewImagePanel.externalViewerButton.text=Open in External Viewer",
|
@NbBundle.Messages({"MediaViewImagePanel.externalViewerButton.text=Open in External Viewer Ctrl+E",
|
||||||
"MediaViewImagePanel.errorLabel.text=Could not load file into Media View.",
|
"MediaViewImagePanel.errorLabel.text=Could not load file into Media View.",
|
||||||
"MediaViewImagePanel.errorLabel.OOMText=Could not load file into Media View: insufficent memory."})
|
"MediaViewImagePanel.errorLabel.OOMText=Could not load file into Media View: insufficent memory."})
|
||||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2018 Basis Technology Corp.
|
* Copyright 2011-2019 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");
|
||||||
@ -38,6 +38,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
|||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResult;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResult;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A DataResultTopComponent object is a NetBeans top component that provides
|
* A DataResultTopComponent object is a NetBeans top component that provides
|
||||||
@ -248,6 +249,8 @@ public final class DataResultTopComponent extends TopComponent implements DataRe
|
|||||||
setName(title);
|
setName(title);
|
||||||
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(AddBookmarkTagAction.BOOKMARK_SHORTCUT, "addBookmarkTag"); //NON-NLS
|
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(AddBookmarkTagAction.BOOKMARK_SHORTCUT, "addBookmarkTag"); //NON-NLS
|
||||||
getActionMap().put("addBookmarkTag", new AddBookmarkTagAction()); //NON-NLS
|
getActionMap().put("addBookmarkTag", new AddBookmarkTagAction()); //NON-NLS
|
||||||
|
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ExternalViewerShortcutAction.EXTERNAL_VIEWER_SHORTCUT, "useExternalViewer"); //NON-NLS
|
||||||
|
getActionMap().put("useExternalViewer", ExternalViewerShortcutAction.getInstance()); //NON-NLS
|
||||||
putClientProperty(TopComponent.PROP_CLOSING_DISABLED, isMain);
|
putClientProperty(TopComponent.PROP_CLOSING_DISABLED, isMain);
|
||||||
putClientProperty(TopComponent.PROP_MAXIMIZATION_DISABLED, true);
|
putClientProperty(TopComponent.PROP_MAXIMIZATION_DISABLED, true);
|
||||||
putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, true);
|
putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, true);
|
||||||
|
@ -22,6 +22,8 @@ import java.beans.PropertyChangeEvent;
|
|||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -31,7 +33,6 @@ import org.openide.nodes.Node;
|
|||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.datamodel.DataSource;
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
@ -87,6 +88,16 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Objec
|
|||||||
|
|
||||||
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
|
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
|
||||||
List<DataSource> dataSources = tskCase.getDataSources();
|
List<DataSource> dataSources = tskCase.getDataSources();
|
||||||
|
|
||||||
|
Collections.sort(dataSources, new Comparator<DataSource>() {
|
||||||
|
@Override
|
||||||
|
public int compare(DataSource dataS1, DataSource dataS2) {
|
||||||
|
String dataS1Name = dataS1.getName().toLowerCase();
|
||||||
|
String dataS2Name = dataS2.getName().toLowerCase();
|
||||||
|
return dataS1Name.compareTo(dataS2Name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
List<DataSourceGrouping> keys = new ArrayList<>();
|
List<DataSourceGrouping> keys = new ArrayList<>();
|
||||||
dataSources.forEach((datasource) -> {
|
dataSources.forEach((datasource) -> {
|
||||||
keys.add(new DataSourceGrouping(datasource));
|
keys.add(new DataSourceGrouping(datasource));
|
||||||
|
@ -53,7 +53,7 @@ ContentUtils.exception.msg=Cannot extract a {0}
|
|||||||
DataModelActionsFactory.srcFileInDir.text=View Source File in Directory
|
DataModelActionsFactory.srcFileInDir.text=View Source File in Directory
|
||||||
DataModelActionsFactory.fileInDir.text=View File in Directory
|
DataModelActionsFactory.fileInDir.text=View File in Directory
|
||||||
DataModelActionsFactory.viewNewWin.text=View in New Window
|
DataModelActionsFactory.viewNewWin.text=View in New Window
|
||||||
DataModelActionsFactory.openExtViewer.text=Open in External Viewer
|
DataModelActionsFactory.openExtViewer.text=Open in External Viewer Ctrl+E
|
||||||
DataSourcesNode.name=Data Sources
|
DataSourcesNode.name=Data Sources
|
||||||
DataSourcesNode.group_by_datasource.name=Data Source Files
|
DataSourcesNode.group_by_datasource.name=Data Source Files
|
||||||
DataSourcesNode.createSheet.name.name=Name
|
DataSourcesNode.createSheet.name.name=Name
|
||||||
@ -120,13 +120,13 @@ LayoutFileNode.createSheet.name.displayName=Name
|
|||||||
LayoutFileNode.createSheet.name.desc=no description
|
LayoutFileNode.createSheet.name.desc=no description
|
||||||
LayoutFileNode.createSheet.noDescr.text=no description
|
LayoutFileNode.createSheet.noDescr.text=no description
|
||||||
LayoutFileNode.getActions.viewInNewWin.text=View in New Window
|
LayoutFileNode.getActions.viewInNewWin.text=View in New Window
|
||||||
LayoutFileNode.getActions.openInExtViewer.text=Open in External Viewer
|
LayoutFileNode.getActions.openInExtViewer.text=Open in External Viewer Ctrl+E
|
||||||
LocalFileNode.createSheet.name.name=Name
|
LocalFileNode.createSheet.name.name=Name
|
||||||
LocalFileNode.createSheet.name.displayName=Name
|
LocalFileNode.createSheet.name.displayName=Name
|
||||||
LocalFileNode.createSheet.name.desc=no description
|
LocalFileNode.createSheet.name.desc=no description
|
||||||
LocalFileNode.createSheet.noDescr.text=no description
|
LocalFileNode.createSheet.noDescr.text=no description
|
||||||
LocalFileNode.getActions.viewInNewWin.text=View in New Window
|
LocalFileNode.getActions.viewInNewWin.text=View in New Window
|
||||||
LocalFileNode.getActions.openInExtViewer.text=Open in External Viewer
|
LocalFileNode.getActions.openInExtViewer.text=Open in External Viewer Ctrl+E
|
||||||
LocalFileNode.getActions.searchFilesSameMd5.text=Search for files with the same MD5 hash
|
LocalFileNode.getActions.searchFilesSameMd5.text=Search for files with the same MD5 hash
|
||||||
OpenReportAction.actionDisplayName=Open Report
|
OpenReportAction.actionDisplayName=Open Report
|
||||||
OpenReportAction.actionPerformed.MessageBoxTitle=Open Report Failure
|
OpenReportAction.actionPerformed.MessageBoxTitle=Open Report Failure
|
||||||
|
@ -95,7 +95,7 @@ DeletedContent.fsDelFilter.text=File System
|
|||||||
DeleteReportAction.showConfirmDialog.errorMsg=An error occurred while deleting the reports.
|
DeleteReportAction.showConfirmDialog.errorMsg=An error occurred while deleting the reports.
|
||||||
DeleteReportAction.showConfirmDialog.multiple.explanation=The reports will remain on disk.
|
DeleteReportAction.showConfirmDialog.multiple.explanation=The reports will remain on disk.
|
||||||
DeleteReportAction.showConfirmDialog.single.explanation=The report will remain on disk.
|
DeleteReportAction.showConfirmDialog.single.explanation=The report will remain on disk.
|
||||||
FileNode.getActions.openInExtViewer.text=Open in External Viewer
|
FileNode.getActions.openInExtViewer.text=Open in External Viewer Ctrl+E
|
||||||
FileNode.getActions.searchFilesSameMD5.text=Search for files with the same MD5 hash
|
FileNode.getActions.searchFilesSameMD5.text=Search for files with the same MD5 hash
|
||||||
FileNode.getActions.viewFileInDir.text=View File in Directory
|
FileNode.getActions.viewFileInDir.text=View File in Directory
|
||||||
FileNode.getActions.viewInNewWin.text=View in New Window
|
FileNode.getActions.viewInNewWin.text=View in New Window
|
||||||
@ -210,7 +210,7 @@ ContentUtils.exception.msg=Cannot extract a {0}
|
|||||||
DataModelActionsFactory.srcFileInDir.text=View Source File in Directory
|
DataModelActionsFactory.srcFileInDir.text=View Source File in Directory
|
||||||
DataModelActionsFactory.fileInDir.text=View File in Directory
|
DataModelActionsFactory.fileInDir.text=View File in Directory
|
||||||
DataModelActionsFactory.viewNewWin.text=View in New Window
|
DataModelActionsFactory.viewNewWin.text=View in New Window
|
||||||
DataModelActionsFactory.openExtViewer.text=Open in External Viewer
|
DataModelActionsFactory.openExtViewer.text=Open in External Viewer Ctrl+E
|
||||||
DataSourcesNode.name=Data Sources
|
DataSourcesNode.name=Data Sources
|
||||||
DataSourcesNode.group_by_datasource.name=Data Source Files
|
DataSourcesNode.group_by_datasource.name=Data Source Files
|
||||||
DataSourcesNode.createSheet.name.name=Name
|
DataSourcesNode.createSheet.name.name=Name
|
||||||
@ -277,13 +277,13 @@ LayoutFileNode.createSheet.name.displayName=Name
|
|||||||
LayoutFileNode.createSheet.name.desc=no description
|
LayoutFileNode.createSheet.name.desc=no description
|
||||||
LayoutFileNode.createSheet.noDescr.text=no description
|
LayoutFileNode.createSheet.noDescr.text=no description
|
||||||
LayoutFileNode.getActions.viewInNewWin.text=View in New Window
|
LayoutFileNode.getActions.viewInNewWin.text=View in New Window
|
||||||
LayoutFileNode.getActions.openInExtViewer.text=Open in External Viewer
|
LayoutFileNode.getActions.openInExtViewer.text=Open in External Viewer Ctrl+E
|
||||||
LocalFileNode.createSheet.name.name=Name
|
LocalFileNode.createSheet.name.name=Name
|
||||||
LocalFileNode.createSheet.name.displayName=Name
|
LocalFileNode.createSheet.name.displayName=Name
|
||||||
LocalFileNode.createSheet.name.desc=no description
|
LocalFileNode.createSheet.name.desc=no description
|
||||||
LocalFileNode.createSheet.noDescr.text=no description
|
LocalFileNode.createSheet.noDescr.text=no description
|
||||||
LocalFileNode.getActions.viewInNewWin.text=View in New Window
|
LocalFileNode.getActions.viewInNewWin.text=View in New Window
|
||||||
LocalFileNode.getActions.openInExtViewer.text=Open in External Viewer
|
LocalFileNode.getActions.openInExtViewer.text=Open in External Viewer Ctrl+E
|
||||||
LocalFileNode.getActions.searchFilesSameMd5.text=Search for files with the same MD5 hash
|
LocalFileNode.getActions.searchFilesSameMd5.text=Search for files with the same MD5 hash
|
||||||
OpenReportAction.actionDisplayName=Open Report
|
OpenReportAction.actionDisplayName=Open Report
|
||||||
OpenReportAction.actionPerformed.MessageBoxTitle=Open Report Failure
|
OpenReportAction.actionPerformed.MessageBoxTitle=Open Report Failure
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013-2018 Basis Technology Corp.
|
* Copyright 2013-2019 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");
|
||||||
@ -37,6 +37,7 @@ import org.sleuthkit.autopsy.actions.ReplaceContentTagAction;
|
|||||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||||
import org.sleuthkit.autopsy.datamodel.Reports.ReportNode;
|
import org.sleuthkit.autopsy.datamodel.Reports.ReportNode;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||||
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||||
@ -82,7 +83,13 @@ public class DataModelActionsFactory {
|
|||||||
final FileNode fileNode = new FileNode(file);
|
final FileNode fileNode = new FileNode(file);
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, fileNode));
|
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, fileNode));
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, fileNode));
|
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, fileNode));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(ExtractAction.getInstance());
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
@ -90,20 +97,16 @@ public class DataModelActionsFactory {
|
|||||||
if (isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
final Collection<AbstractFile> selectedFilesList =
|
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if(selectedFilesList.size() == 1) {
|
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
if(isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
final Collection<BlackboardArtifact> selectedArtifactsList
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||||
if(selectedArtifactsList.size() == 1) {
|
if (selectedArtifactsList.size() == 1) {
|
||||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||||
return actionsList;
|
return actionsList;
|
||||||
}
|
}
|
||||||
@ -121,20 +124,18 @@ public class DataModelActionsFactory {
|
|||||||
if (isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
final Collection<AbstractFile> selectedFilesList =
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
if (selectedFilesList.size() == 1) {
|
||||||
if(selectedFilesList.size() == 1) {
|
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
if(isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
final Collection<BlackboardArtifact> selectedArtifactsList
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||||
if(selectedArtifactsList.size() == 1) {
|
if (selectedArtifactsList.size() == 1) {
|
||||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||||
return actionsList;
|
return actionsList;
|
||||||
}
|
}
|
||||||
@ -145,7 +146,13 @@ public class DataModelActionsFactory {
|
|||||||
LayoutFileNode layoutFileNode = new LayoutFileNode(file);
|
LayoutFileNode layoutFileNode = new LayoutFileNode(file);
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, layoutFileNode));
|
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, layoutFileNode));
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, layoutFileNode));
|
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, layoutFileNode));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(ExtractAction.getInstance());//
|
actionsList.add(ExtractAction.getInstance());//
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
@ -153,20 +160,16 @@ public class DataModelActionsFactory {
|
|||||||
if (isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
final Collection<AbstractFile> selectedFilesList =
|
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if(selectedFilesList.size() == 1) {
|
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
if(isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
final Collection<BlackboardArtifact> selectedArtifactsList
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||||
if(selectedArtifactsList.size() == 1) {
|
if (selectedArtifactsList.size() == 1) {
|
||||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||||
return actionsList;
|
return actionsList;
|
||||||
}
|
}
|
||||||
@ -177,7 +180,13 @@ public class DataModelActionsFactory {
|
|||||||
DirectoryNode directoryNode = new DirectoryNode(directory);
|
DirectoryNode directoryNode = new DirectoryNode(directory);
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, directoryNode));
|
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, directoryNode));
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, directoryNode));
|
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, directoryNode));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(ExtractAction.getInstance());
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
@ -185,20 +194,16 @@ public class DataModelActionsFactory {
|
|||||||
if (isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
final Collection<AbstractFile> selectedFilesList =
|
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if(selectedFilesList.size() == 1) {
|
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
if(isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
final Collection<BlackboardArtifact> selectedArtifactsList
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||||
if(selectedArtifactsList.size() == 1) {
|
if (selectedArtifactsList.size() == 1) {
|
||||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||||
return actionsList;
|
return actionsList;
|
||||||
}
|
}
|
||||||
@ -209,7 +214,13 @@ public class DataModelActionsFactory {
|
|||||||
VirtualDirectoryNode directoryNode = new VirtualDirectoryNode(directory);
|
VirtualDirectoryNode directoryNode = new VirtualDirectoryNode(directory);
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, directoryNode));
|
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, directoryNode));
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, directoryNode));
|
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, directoryNode));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(ExtractAction.getInstance());
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
@ -217,20 +228,16 @@ public class DataModelActionsFactory {
|
|||||||
if (isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
final Collection<AbstractFile> selectedFilesList =
|
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if(selectedFilesList.size() == 1) {
|
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
if(isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
final Collection<BlackboardArtifact> selectedArtifactsList
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||||
if(selectedArtifactsList.size() == 1) {
|
if (selectedArtifactsList.size() == 1) {
|
||||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||||
return actionsList;
|
return actionsList;
|
||||||
}
|
}
|
||||||
@ -241,7 +248,13 @@ public class DataModelActionsFactory {
|
|||||||
LocalDirectoryNode directoryNode = new LocalDirectoryNode(directory);
|
LocalDirectoryNode directoryNode = new LocalDirectoryNode(directory);
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, directoryNode));
|
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, directoryNode));
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, directoryNode));
|
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, directoryNode));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(ExtractAction.getInstance());
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
@ -249,20 +262,16 @@ public class DataModelActionsFactory {
|
|||||||
if (isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
final Collection<AbstractFile> selectedFilesList =
|
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if(selectedFilesList.size() == 1) {
|
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
if(isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
final Collection<BlackboardArtifact> selectedArtifactsList
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||||
if(selectedArtifactsList.size() == 1) {
|
if (selectedArtifactsList.size() == 1) {
|
||||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||||
return actionsList;
|
return actionsList;
|
||||||
}
|
}
|
||||||
@ -273,7 +282,13 @@ public class DataModelActionsFactory {
|
|||||||
final LocalFileNode localFileNode = new LocalFileNode(file);
|
final LocalFileNode localFileNode = new LocalFileNode(file);
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, localFileNode));
|
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, localFileNode));
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, localFileNode));
|
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, localFileNode));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(ExtractAction.getInstance());
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
@ -281,20 +296,16 @@ public class DataModelActionsFactory {
|
|||||||
if (isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
final Collection<AbstractFile> selectedFilesList =
|
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if(selectedFilesList.size() == 1) {
|
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
if(isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
final Collection<BlackboardArtifact> selectedArtifactsList
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||||
if(selectedArtifactsList.size() == 1) {
|
if (selectedArtifactsList.size() == 1) {
|
||||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||||
return actionsList;
|
return actionsList;
|
||||||
}
|
}
|
||||||
@ -305,7 +316,13 @@ public class DataModelActionsFactory {
|
|||||||
final LocalFileNode localFileNode = new LocalFileNode(file);
|
final LocalFileNode localFileNode = new LocalFileNode(file);
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, localFileNode));
|
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, localFileNode));
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, localFileNode));
|
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, localFileNode));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(ExtractAction.getInstance());
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
@ -313,20 +330,16 @@ public class DataModelActionsFactory {
|
|||||||
if (isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
final Collection<AbstractFile> selectedFilesList =
|
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if(selectedFilesList.size() == 1) {
|
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
if(isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
final Collection<BlackboardArtifact> selectedArtifactsList
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||||
if(selectedArtifactsList.size() == 1) {
|
if (selectedArtifactsList.size() == 1) {
|
||||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||||
return actionsList;
|
return actionsList;
|
||||||
}
|
}
|
||||||
@ -340,7 +353,6 @@ public class DataModelActionsFactory {
|
|||||||
if (isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
final Collection<BlackboardArtifact> selectedArtifactsList
|
final Collection<BlackboardArtifact> selectedArtifactsList
|
||||||
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||||
@ -348,19 +360,23 @@ public class DataModelActionsFactory {
|
|||||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||||
return actionsList;
|
return actionsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Action> getActions(ContentTag contentTag, boolean isArtifactSource) {
|
public static List<Action> getActions(ContentTag contentTag, boolean isArtifactSource) {
|
||||||
|
|
||||||
List<Action> actionsList = new ArrayList<>();
|
List<Action> actionsList = new ArrayList<>();
|
||||||
actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), contentTag.getContent()));
|
actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), contentTag.getContent()));
|
||||||
final ContentTagNode tagNode = new ContentTagNode(contentTag);
|
final ContentTagNode tagNode = new ContentTagNode(contentTag);
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, tagNode));
|
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, tagNode));
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, tagNode));
|
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, tagNode));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(ExtractAction.getInstance());
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
@ -368,35 +384,35 @@ public class DataModelActionsFactory {
|
|||||||
if (isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
final Collection<AbstractFile> selectedFilesList =
|
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if(selectedFilesList.size() == 1) {
|
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
if(isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
final Collection<BlackboardArtifact> selectedArtifactsList
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||||
if(selectedArtifactsList.size() == 1) {
|
if (selectedArtifactsList.size() == 1) {
|
||||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsList.add(DeleteContentTagAction.getInstance());
|
actionsList.add(DeleteContentTagAction.getInstance());
|
||||||
actionsList.add(ReplaceContentTagAction.getInstance());
|
actionsList.add(ReplaceContentTagAction.getInstance());
|
||||||
|
|
||||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||||
return actionsList;
|
return actionsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<Action> getActions(BlackboardArtifactTag artifactTag, boolean isArtifactSource) {
|
public static List<Action> getActions(BlackboardArtifactTag artifactTag, boolean isArtifactSource) {
|
||||||
List<Action> actionsList = new ArrayList<>();
|
List<Action> actionsList = new ArrayList<>();
|
||||||
actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), artifactTag.getContent()));
|
actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), artifactTag.getContent()));
|
||||||
final BlackboardArtifactTagNode tagNode = new BlackboardArtifactTagNode(artifactTag);
|
final BlackboardArtifactTagNode tagNode = new BlackboardArtifactTagNode(artifactTag);
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, tagNode));
|
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, tagNode));
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, tagNode));
|
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, tagNode));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(ExtractAction.getInstance());
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
@ -404,23 +420,18 @@ public class DataModelActionsFactory {
|
|||||||
if (isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
final Collection<AbstractFile> selectedFilesList =
|
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if(selectedFilesList.size() == 1) {
|
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
if(isArtifactSource) {
|
if (isArtifactSource) {
|
||||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
final Collection<BlackboardArtifact> selectedArtifactsList
|
||||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||||
if(selectedArtifactsList.size() == 1) {
|
if (selectedArtifactsList.size() == 1) {
|
||||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsList.add(DeleteBlackboardArtifactTagAction.getInstance());
|
actionsList.add(DeleteBlackboardArtifactTagAction.getInstance());
|
||||||
actionsList.add(ReplaceBlackboardArtifactTagAction.getInstance());
|
actionsList.add(ReplaceBlackboardArtifactTagAction.getInstance());
|
||||||
|
|
||||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||||
return actionsList;
|
return actionsList;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import java.beans.PropertyChangeListener;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -123,6 +124,17 @@ public class DataSourcesNode extends DisplayableItemNode {
|
|||||||
Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getDataSource(datasourceObjId);
|
Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getDataSource(datasourceObjId);
|
||||||
currentKeys = new ArrayList<>(Arrays.asList(content));
|
currentKeys = new ArrayList<>(Arrays.asList(content));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Collections.sort(currentKeys, new Comparator<Content>() {
|
||||||
|
@Override
|
||||||
|
public int compare(Content content1, Content content2) {
|
||||||
|
String content1Name = content1.getName().toLowerCase();
|
||||||
|
String content2Name = content2.getName().toLowerCase();
|
||||||
|
return content1Name.compareTo(content2Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
setKeys(currentKeys);
|
setKeys(currentKeys);
|
||||||
} catch (TskCoreException | NoCurrentCaseException | TskDataException ex) {
|
} catch (TskCoreException | NoCurrentCaseException | TskDataException ex) {
|
||||||
logger.log(Level.SEVERE, "Error getting data sources: {0}", ex.getMessage()); // NON-NLS
|
logger.log(Level.SEVERE, "Error getting data sources: {0}", ex.getMessage()); // NON-NLS
|
||||||
|
@ -424,6 +424,8 @@ public class DeletedContent implements AutopsyVisitableItem {
|
|||||||
+ " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType() //NON-NLS
|
+ " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType() //NON-NLS
|
||||||
+ " )"
|
+ " )"
|
||||||
+ " OR type = " + TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType() //NON-NLS
|
+ " OR type = " + TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType() //NON-NLS
|
||||||
|
+ " OR (dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()
|
||||||
|
+ " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE.getFileType() + " )"
|
||||||
+ " )";
|
+ " )";
|
||||||
//+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType()
|
//+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType()
|
||||||
//+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
|
//+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2018 Basis Technology Corp.
|
* Copyright 2011-2019 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");
|
||||||
@ -33,6 +33,7 @@ import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
|||||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||||
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||||
@ -148,7 +149,7 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
|||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"FileNode.getActions.viewFileInDir.text=View File in Directory",
|
"FileNode.getActions.viewFileInDir.text=View File in Directory",
|
||||||
"FileNode.getActions.viewInNewWin.text=View in New Window",
|
"FileNode.getActions.viewInNewWin.text=View in New Window",
|
||||||
"FileNode.getActions.openInExtViewer.text=Open in External Viewer",
|
"FileNode.getActions.openInExtViewer.text=Open in External Viewer Ctrl+E",
|
||||||
"FileNode.getActions.searchFilesSameMD5.text=Search for files with the same MD5 hash"})
|
"FileNode.getActions.searchFilesSameMD5.text=Search for files with the same MD5 hash"})
|
||||||
public Action[] getActions(boolean context) {
|
public Action[] getActions(boolean context) {
|
||||||
List<Action> actionsList = new ArrayList<>();
|
List<Action> actionsList = new ArrayList<>();
|
||||||
@ -160,7 +161,14 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actionsList.add(new NewWindowViewAction(Bundle.FileNode_getActions_viewInNewWin_text(), this));
|
actionsList.add(new NewWindowViewAction(Bundle.FileNode_getActions_viewInNewWin_text(), this));
|
||||||
actionsList.add(new ExternalViewerAction(Bundle.FileNode_getActions_openInExtViewer_text(), this));
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
|
actionsList.add(new ExternalViewerAction(
|
||||||
|
Bundle.FileNode_getActions_openInExtViewer_text(), this));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(ViewFileInTimelineAction.createViewFileAction(getContent()));
|
actionsList.add(ViewFileInTimelineAction.createViewFileAction(getContent()));
|
||||||
actionsList.add(null); // Creates an item separator
|
actionsList.add(null); // Creates an item separator
|
||||||
|
|
||||||
@ -168,7 +176,6 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
|||||||
actionsList.add(null); // Creates an item separator
|
actionsList.add(null); // Creates an item separator
|
||||||
|
|
||||||
actionsList.add(AddContentTagAction.getInstance());
|
actionsList.add(AddContentTagAction.getInstance());
|
||||||
final Collection<AbstractFile> selectedFilesList = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if (1 == selectedFilesList.size()) {
|
if (1 == selectedFilesList.size()) {
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,6 @@ import org.openide.util.lookup.Lookups;
|
|||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
|
||||||
import static org.sleuthkit.autopsy.core.UserPreferences.hideKnownFilesInViewsTree;
|
import static org.sleuthkit.autopsy.core.UserPreferences.hideKnownFilesInViewsTree;
|
||||||
import static org.sleuthkit.autopsy.core.UserPreferences.hideSlackFilesInViewsTree;
|
import static org.sleuthkit.autopsy.core.UserPreferences.hideSlackFilesInViewsTree;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
@ -100,6 +99,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
+ 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.LAYOUT_FILE.ordinal() + ","
|
||||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()
|
||||||
+ (hideSlackFilesInViewsTree() ? "" : ("," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
|
+ (hideSlackFilesInViewsTree() ? "" : ("," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
|
||||||
+ "))"
|
+ "))"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2018 Basis Technology Corp.
|
* Copyright 2011-2019 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -23,7 +23,6 @@ import java.util.Arrays;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.Utilities;
|
import org.openide.util.Utilities;
|
||||||
@ -31,6 +30,7 @@ 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.directorytree.ExternalViewerAction;
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||||
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
@ -64,6 +64,12 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
|
|||||||
|
|
||||||
if (lf.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED)) {
|
if (lf.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED)) {
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/carved-file-icon-16.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/carved-file-icon-16.png"); //NON-NLS
|
||||||
|
} else if (lf.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE)) {
|
||||||
|
if (lf.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
|
||||||
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
|
||||||
|
} else {
|
||||||
|
this.setIconBaseWithExtension(FileNode.getIconForFileType(lf));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
|
||||||
}
|
}
|
||||||
@ -89,15 +95,19 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
|
|||||||
actionsList.addAll(Arrays.asList(super.getActions(true)));
|
actionsList.addAll(Arrays.asList(super.getActions(true)));
|
||||||
actionsList.add(new NewWindowViewAction(
|
actionsList.add(new NewWindowViewAction(
|
||||||
NbBundle.getMessage(this.getClass(), "LayoutFileNode.getActions.viewInNewWin.text"), this));
|
NbBundle.getMessage(this.getClass(), "LayoutFileNode.getActions.viewInNewWin.text"), this));
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(new ExternalViewerAction(
|
actionsList.add(new ExternalViewerAction(
|
||||||
NbBundle.getMessage(this.getClass(), "LayoutFileNode.getActions.openInExtViewer.text"), this));
|
NbBundle.getMessage(this.getClass(), "LayoutFileNode.getActions.openInExtViewer.text"), this));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(ExtractAction.getInstance());
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(AddContentTagAction.getInstance());
|
actionsList.add(AddContentTagAction.getInstance());
|
||||||
|
|
||||||
final Collection<AbstractFile> selectedFilesList
|
|
||||||
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if (selectedFilesList.size() == 1) {
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013-2018 Basis Technology Corp.
|
* Copyright 2013-2019 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");
|
||||||
@ -32,6 +32,7 @@ import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
|||||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||||
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||||
@ -61,6 +62,7 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Action[] getActions(boolean context) {
|
public Action[] getActions(boolean context) {
|
||||||
List<Action> actionsList = new ArrayList<>();
|
List<Action> actionsList = new ArrayList<>();
|
||||||
actionsList.addAll(Arrays.asList(super.getActions(true)));
|
actionsList.addAll(Arrays.asList(super.getActions(true)));
|
||||||
@ -69,16 +71,20 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
|
|||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new NewWindowViewAction(
|
actionsList.add(new NewWindowViewAction(
|
||||||
NbBundle.getMessage(this.getClass(), "LocalFileNode.getActions.viewInNewWin.text"), this));
|
NbBundle.getMessage(this.getClass(), "LocalFileNode.getActions.viewInNewWin.text"), this));
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(new ExternalViewerAction(
|
actionsList.add(new ExternalViewerAction(
|
||||||
NbBundle.getMessage(this.getClass(), "LocalFileNode.getActions.openInExtViewer.text"), this));
|
NbBundle.getMessage(this.getClass(), "LocalFileNode.getActions.openInExtViewer.text"), this));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
|
|
||||||
actionsList.add(ExtractAction.getInstance());
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(AddContentTagAction.getInstance());
|
actionsList.add(AddContentTagAction.getInstance());
|
||||||
|
|
||||||
final Collection<AbstractFile> selectedFilesList
|
|
||||||
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if (selectedFilesList.size() == 1) {
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ ChangeViewAction.menuItem.view.string=String
|
|||||||
DataResultFilterNode.action.viewFileInDir.text=View File in Directory
|
DataResultFilterNode.action.viewFileInDir.text=View File in Directory
|
||||||
DataResultFilterNode.action.viewSrcFileInDir.text=View Source File in Directory
|
DataResultFilterNode.action.viewSrcFileInDir.text=View Source File in Directory
|
||||||
DataResultFilterNode.action.viewInNewWin.text=View in New Window
|
DataResultFilterNode.action.viewInNewWin.text=View in New Window
|
||||||
DataResultFilterNode.action.openInExtViewer.text=Open in External Viewer
|
DataResultFilterNode.action.openInExtViewer.text=Open in External Viewer Ctrl+E
|
||||||
DataResultFilterNode.action.searchFilesSameMd5.text=Search for files with the same MD5 hash
|
DataResultFilterNode.action.searchFilesSameMd5.text=Search for files with the same MD5 hash
|
||||||
DataResultFilterNode.action.viewInDir.text=View in Directory
|
DataResultFilterNode.action.viewInDir.text=View in Directory
|
||||||
DirectoryTreeFilterNode.action.collapseAll.text=Collapse All
|
DirectoryTreeFilterNode.action.collapseAll.text=Collapse All
|
||||||
|
@ -5,12 +5,16 @@ DirectoryTreeTopComponent.componentOpened.groupDataSources.text=This case contai
|
|||||||
DirectoryTreeTopComponent.componentOpened.groupDataSources.title=Group by data source?
|
DirectoryTreeTopComponent.componentOpened.groupDataSources.title=Group by data source?
|
||||||
DirectoryTreeTopComponent.emptyMimeNode.text=Data not available. Run file type identification module.
|
DirectoryTreeTopComponent.emptyMimeNode.text=Data not available. Run file type identification module.
|
||||||
DirectoryTreeTopComponent.resultsView.title=Listing
|
DirectoryTreeTopComponent.resultsView.title=Listing
|
||||||
|
ExternalViewerAction.actionPerformed.failure.exe.message=The file is an executable and will not be opened.
|
||||||
ExternalViewerAction.actionPerformed.failure.IO.message=There is no associated editor for files of this type or the associated application failed to launch.
|
ExternalViewerAction.actionPerformed.failure.IO.message=There is no associated editor for files of this type or the associated application failed to launch.
|
||||||
ExternalViewerAction.actionPerformed.failure.missingFile.message=The file no longer exists.
|
ExternalViewerAction.actionPerformed.failure.missingFile.message=The file no longer exists.
|
||||||
ExternalViewerAction.actionPerformed.failure.open.url=Cannot open URL
|
ExternalViewerAction.actionPerformed.failure.open.url=Cannot open URL
|
||||||
ExternalViewerAction.actionPerformed.failure.permission.message=Permission to open the file was denied.
|
ExternalViewerAction.actionPerformed.failure.permission.message=Permission to open the file was denied.
|
||||||
ExternalViewerAction.actionPerformed.failure.support.message=This platform (operating system) does not support opening a file in an editor this way.
|
ExternalViewerAction.actionPerformed.failure.support.message=This platform (operating system) does not support opening a file in an editor this way.
|
||||||
ExternalViewerAction.actionPerformed.failure.title=Open File Failure
|
# {0} - file name
|
||||||
|
ExternalViewerAction.actionPerformed.failure.title=Open File Failure {0}
|
||||||
|
ExternalViewerAction.actionPerformed.urlFailure.title=Open URL Failure
|
||||||
|
ExternalViewerShortcutAction.title.text=Open in External Viewer Ctrl+E
|
||||||
ExtractAction.noOpenCase.errMsg=No open case available.
|
ExtractAction.noOpenCase.errMsg=No open case available.
|
||||||
ExtractUnallocAction.imageError=Error extracting unallocated space from image
|
ExtractUnallocAction.imageError=Error extracting unallocated space from image
|
||||||
ExtractUnallocAction.noFiles=No unallocated files found on volume
|
ExtractUnallocAction.noFiles=No unallocated files found on volume
|
||||||
@ -80,7 +84,7 @@ ChangeViewAction.menuItem.view.string=String
|
|||||||
DataResultFilterNode.action.viewFileInDir.text=View File in Directory
|
DataResultFilterNode.action.viewFileInDir.text=View File in Directory
|
||||||
DataResultFilterNode.action.viewSrcFileInDir.text=View Source File in Directory
|
DataResultFilterNode.action.viewSrcFileInDir.text=View Source File in Directory
|
||||||
DataResultFilterNode.action.viewInNewWin.text=View in New Window
|
DataResultFilterNode.action.viewInNewWin.text=View in New Window
|
||||||
DataResultFilterNode.action.openInExtViewer.text=Open in External Viewer
|
DataResultFilterNode.action.openInExtViewer.text=Open in External Viewer Ctrl+E
|
||||||
DataResultFilterNode.action.searchFilesSameMd5.text=Search for files with the same MD5 hash
|
DataResultFilterNode.action.searchFilesSameMd5.text=Search for files with the same MD5 hash
|
||||||
DataResultFilterNode.action.viewInDir.text=View in Directory
|
DataResultFilterNode.action.viewInDir.text=View in Directory
|
||||||
DirectoryTreeFilterNode.action.collapseAll.text=Collapse All
|
DirectoryTreeFilterNode.action.collapseAll.text=Collapse All
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2018 Basis Technology Corp.
|
* Copyright 2011-2019 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");
|
||||||
@ -432,19 +432,23 @@ public class DataResultFilterNode extends FilterNode {
|
|||||||
actionsList.addAll(DataModelActionsFactory.getActions(c, false));
|
actionsList.addAll(DataModelActionsFactory.getActions(c, false));
|
||||||
}
|
}
|
||||||
if (n != null) {
|
if (n != null) {
|
||||||
|
final Collection<AbstractFile> selectedFilesList
|
||||||
|
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new NewWindowViewAction(
|
actionsList.add(new NewWindowViewAction(
|
||||||
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInNewWin.text"), n));
|
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInNewWin.text"), n));
|
||||||
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(new ExternalViewerAction(
|
actionsList.add(new ExternalViewerAction(
|
||||||
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.openInExtViewer.text"), n));
|
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.openInExtViewer.text"), n));
|
||||||
|
} else {
|
||||||
|
actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||||
|
}
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(ExtractAction.getInstance());
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(AddContentTagAction.getInstance());
|
actionsList.add(AddContentTagAction.getInstance());
|
||||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||||
|
|
||||||
final Collection<AbstractFile> selectedFilesList
|
|
||||||
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
|
||||||
if (selectedFilesList.size() == 1) {
|
if (selectedFilesList.size() == 1) {
|
||||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2018 Basis Technology Corp.
|
* Copyright 2011-2019 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");
|
||||||
@ -35,6 +35,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
|||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
import org.sleuthkit.autopsy.datamodel.SlackFileNode;
|
import org.sleuthkit.autopsy.datamodel.SlackFileNode;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts a File object to a temporary file in the case directory, and then
|
* Extracts a File object to a temporary file in the case directory, and then
|
||||||
@ -44,24 +45,20 @@ import org.sleuthkit.autopsy.datamodel.SlackFileNode;
|
|||||||
public class ExternalViewerAction extends AbstractAction {
|
public class ExternalViewerAction extends AbstractAction {
|
||||||
|
|
||||||
private final static Logger logger = Logger.getLogger(ExternalViewerAction.class.getName());
|
private final static Logger logger = Logger.getLogger(ExternalViewerAction.class.getName());
|
||||||
private final org.sleuthkit.datamodel.AbstractFile fileObject;
|
private final AbstractFile fileObject;
|
||||||
private String fileObjectExt;
|
private String fileObjectExt;
|
||||||
final static String[] EXECUTABLE_EXT = {".exe", ".dll", ".com", ".bat", ".msi", ".reg", ".scr", ".cmd"}; //NON-NLS
|
final static String[] EXECUTABLE_EXT = {".exe", ".dll", ".com", ".bat", ".msi", ".reg", ".scr", ".cmd"}; //NON-NLS
|
||||||
|
private boolean isExecutable;
|
||||||
|
|
||||||
/**
|
ExternalViewerAction(String title, AbstractFile file, boolean isSlackFile) {
|
||||||
*
|
|
||||||
* @param title Name of the action
|
|
||||||
* @param fileNode File to display
|
|
||||||
*/
|
|
||||||
public ExternalViewerAction(String title, Node fileNode) {
|
|
||||||
super(title);
|
super(title);
|
||||||
this.fileObject = fileNode.getLookup().lookup(org.sleuthkit.datamodel.AbstractFile.class);
|
this.fileObject = file;
|
||||||
|
|
||||||
long size = fileObject.getSize();
|
long size = fileObject.getSize();
|
||||||
String fileName = fileObject.getName();
|
String fileName = fileObject.getName();
|
||||||
int extPos = fileName.lastIndexOf('.');
|
int extPos = fileName.lastIndexOf('.');
|
||||||
|
|
||||||
boolean isExecutable = false;
|
isExecutable = false;
|
||||||
if (extPos != -1) {
|
if (extPos != -1) {
|
||||||
String extension = fileName.substring(extPos, fileName.length()).toLowerCase();
|
String extension = fileName.substring(extPos, fileName.length()).toLowerCase();
|
||||||
fileObjectExt = extension;
|
fileObjectExt = extension;
|
||||||
@ -79,13 +76,35 @@ public class ExternalViewerAction extends AbstractAction {
|
|||||||
// find an application for files without an extension
|
// find an application for files without an extension
|
||||||
// or if file is executable (for security reasons)
|
// or if file is executable (for security reasons)
|
||||||
// Also skip slack files since their extension is the original extension + "-slack"
|
// Also skip slack files since their extension is the original extension + "-slack"
|
||||||
if (!(size > 0) || extPos == -1 || isExecutable || (fileNode instanceof SlackFileNode)) {
|
if (!(size > 0) || extPos == -1 || isExecutable || isSlackFile) {
|
||||||
this.setEnabled(false);
|
this.setEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param title Name of the action
|
||||||
|
* @param fileNode File to display
|
||||||
|
*/
|
||||||
|
public ExternalViewerAction(String title, Node fileNode) {
|
||||||
|
this(title, fileNode.getLookup().lookup(org.sleuthkit.datamodel.AbstractFile.class), fileNode instanceof SlackFileNode);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Messages({
|
||||||
|
"# {0} - file name",
|
||||||
|
"ExternalViewerAction.actionPerformed.failure.title=Open File Failure {0}",
|
||||||
|
"ExternalViewerAction.actionPerformed.failure.exe.message=The file is an executable and will not be opened."
|
||||||
|
})
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (isExecutable) {
|
||||||
|
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
||||||
|
Bundle.ExternalViewerAction_actionPerformed_failure_exe_message(),
|
||||||
|
Bundle.ExternalViewerAction_actionPerformed_failure_title(this.fileObject.getName()),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the temp folder path of the case
|
// Get the temp folder path of the case
|
||||||
Case openCase;
|
Case openCase;
|
||||||
try {
|
try {
|
||||||
@ -124,7 +143,6 @@ public class ExternalViewerAction extends AbstractAction {
|
|||||||
* @param file the file object
|
* @param file the file object
|
||||||
*/
|
*/
|
||||||
@Messages({
|
@Messages({
|
||||||
"ExternalViewerAction.actionPerformed.failure.title=Open File Failure",
|
|
||||||
"ExternalViewerAction.actionPerformed.failure.IO.message=There is no associated editor for files of this type or the associated application failed to launch.",
|
"ExternalViewerAction.actionPerformed.failure.IO.message=There is no associated editor for files of this type or the associated application failed to launch.",
|
||||||
"ExternalViewerAction.actionPerformed.failure.support.message=This platform (operating system) does not support opening a file in an editor this way.",
|
"ExternalViewerAction.actionPerformed.failure.support.message=This platform (operating system) does not support opening a file in an editor this way.",
|
||||||
"ExternalViewerAction.actionPerformed.failure.missingFile.message=The file no longer exists.",
|
"ExternalViewerAction.actionPerformed.failure.missingFile.message=The file no longer exists.",
|
||||||
@ -146,14 +164,14 @@ public class ExternalViewerAction extends AbstractAction {
|
|||||||
runtime.exec(execArray);
|
runtime.exec(execArray);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.log(Level.WARNING, "Could not open the specified viewer for the given file: " + file.getName(), ex); //NON-NLS
|
logger.log(Level.WARNING, "Could not open the specified viewer for the given file: " + file.getName(), ex); //NON-NLS
|
||||||
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), Bundle.ExternalViewerAction_actionPerformed_failure_IO_message(), Bundle.ExternalViewerAction_actionPerformed_failure_title(), JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), Bundle.ExternalViewerAction_actionPerformed_failure_IO_message(), Bundle.ExternalViewerAction_actionPerformed_failure_title(file.getName()), JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
String localpath = file.getPath();
|
String localpath = file.getPath();
|
||||||
if (localpath.toLowerCase().contains("http")) {
|
if (localpath.toLowerCase().contains("http")) {
|
||||||
String url_path = file.getPath().replaceAll("\\\\","/");
|
String url_path = file.getPath().replaceAll("\\\\", "/");
|
||||||
Desktop.getDesktop().browse(new URI(url_path.replaceFirst("/","//")));
|
Desktop.getDesktop().browse(new URI(url_path.replaceFirst("/", "//")));
|
||||||
} else {
|
} else {
|
||||||
Desktop.getDesktop().open(file);
|
Desktop.getDesktop().open(file);
|
||||||
}
|
}
|
||||||
@ -162,31 +180,31 @@ public class ExternalViewerAction extends AbstractAction {
|
|||||||
logger.log(Level.WARNING, "Could not find a viewer for the given file: " + file.getName(), ex); //NON-NLS
|
logger.log(Level.WARNING, "Could not find a viewer for the given file: " + file.getName(), ex); //NON-NLS
|
||||||
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_IO_message(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_IO_message(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_title(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_title(file.getName()),
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
} catch (UnsupportedOperationException ex) {
|
} catch (UnsupportedOperationException ex) {
|
||||||
logger.log(Level.WARNING, "Platform cannot open " + file.getName() + " in the defined editor.", ex); //NON-NLS
|
logger.log(Level.WARNING, "Platform cannot open " + file.getName() + " in the defined editor.", ex); //NON-NLS
|
||||||
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_support_message(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_support_message(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_title(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_title(file.getName()),
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
logger.log(Level.WARNING, "Could not find the given file: " + file.getName(), ex); //NON-NLS
|
logger.log(Level.WARNING, "Could not find the given file: " + file.getName(), ex); //NON-NLS
|
||||||
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_missingFile_message(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_missingFile_message(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_title(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_title(file.getName()),
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
} catch (SecurityException ex) {
|
} catch (SecurityException ex) {
|
||||||
logger.log(Level.WARNING, "Could not get permission to open the given file: " + file.getName(), ex); //NON-NLS
|
logger.log(Level.WARNING, "Could not get permission to open the given file: " + file.getName(), ex); //NON-NLS
|
||||||
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_permission_message(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_permission_message(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_title(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_title(file.getName()),
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
} catch (URISyntaxException ex) {
|
} catch (URISyntaxException ex) {
|
||||||
logger.log(Level.WARNING, "Could not open URL provided: " + file.getPath(), ex);
|
logger.log(Level.WARNING, "Could not open URL provided: " + file.getPath(), ex);
|
||||||
JOptionPane.showMessageDialog(null,
|
JOptionPane.showMessageDialog(null,
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_open_url(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_open_url(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_title(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_title(file.getName()),
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,39 +215,41 @@ public class ExternalViewerAction extends AbstractAction {
|
|||||||
*
|
*
|
||||||
* @param path URL to open
|
* @param path URL to open
|
||||||
*/
|
*/
|
||||||
|
@Messages({
|
||||||
|
"ExternalViewerAction.actionPerformed.urlFailure.title=Open URL Failure"})
|
||||||
public static void openURL(String path) {
|
public static void openURL(String path) {
|
||||||
String url_path = path.replaceAll("\\\\","/");
|
String url_path = path.replaceAll("\\\\", "/");
|
||||||
try {
|
try {
|
||||||
Desktop.getDesktop().browse(new URI(url_path.replaceFirst("/","//")));
|
Desktop.getDesktop().browse(new URI(url_path.replaceFirst("/", "//")));
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.log(Level.WARNING, "Could not find a viewer for the given URL: " + url_path, ex); //NON-NLS
|
logger.log(Level.WARNING, "Could not find a viewer for the given URL: " + url_path, ex); //NON-NLS
|
||||||
JOptionPane.showMessageDialog(null,
|
JOptionPane.showMessageDialog(null,
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_IO_message(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_IO_message(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_title(),
|
Bundle.ExternalViewerAction_actionPerformed_urlFailure_title(),
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
} catch (UnsupportedOperationException ex) {
|
} catch (UnsupportedOperationException ex) {
|
||||||
logger.log(Level.WARNING, "Platform cannot open " + url_path + " in the defined editor.", ex); //NON-NLS
|
logger.log(Level.WARNING, "Platform cannot open " + url_path + " in the defined editor.", ex); //NON-NLS
|
||||||
JOptionPane.showMessageDialog(null,
|
JOptionPane.showMessageDialog(null,
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_support_message(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_support_message(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_title(),
|
Bundle.ExternalViewerAction_actionPerformed_urlFailure_title(),
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
logger.log(Level.WARNING, "Could not find the given URL: " + url_path, ex); //NON-NLS
|
logger.log(Level.WARNING, "Could not find the given URL: " + url_path, ex); //NON-NLS
|
||||||
JOptionPane.showMessageDialog(null,
|
JOptionPane.showMessageDialog(null,
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_missingFile_message(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_missingFile_message(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_title(),
|
Bundle.ExternalViewerAction_actionPerformed_urlFailure_title(),
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
} catch (SecurityException ex) {
|
} catch (SecurityException ex) {
|
||||||
logger.log(Level.WARNING, "Could not get permission to open the given URL: " + url_path, ex); //NON-NLS
|
logger.log(Level.WARNING, "Could not get permission to open the given URL: " + url_path, ex); //NON-NLS
|
||||||
JOptionPane.showMessageDialog(null,
|
JOptionPane.showMessageDialog(null,
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_permission_message(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_permission_message(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_title(),
|
Bundle.ExternalViewerAction_actionPerformed_urlFailure_title(),
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
} catch (URISyntaxException ex) {
|
} catch (URISyntaxException ex) {
|
||||||
logger.log(Level.WARNING, "Could not open URL provided: " + url_path, ex);
|
logger.log(Level.WARNING, "Could not open URL provided: " + url_path, ex);
|
||||||
JOptionPane.showMessageDialog(null,
|
JOptionPane.showMessageDialog(null,
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_open_url(),
|
Bundle.ExternalViewerAction_actionPerformed_failure_open_url(),
|
||||||
Bundle.ExternalViewerAction_actionPerformed_failure_title(),
|
Bundle.ExternalViewerAction_actionPerformed_urlFailure_title(),
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.directorytree;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.InputEvent;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import javax.swing.AbstractAction;
|
||||||
|
import javax.swing.KeyStroke;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.openide.util.Utilities;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts a File object to a temporary file in the case directory, and then
|
||||||
|
* tries to open it in the user's system with the default or user specified
|
||||||
|
* associated application.
|
||||||
|
*/
|
||||||
|
@Messages({"ExternalViewerShortcutAction.title.text=Open in External Viewer Ctrl+E"})
|
||||||
|
public class ExternalViewerShortcutAction extends AbstractAction {
|
||||||
|
|
||||||
|
public static final KeyStroke EXTERNAL_VIEWER_SHORTCUT = KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_MASK);
|
||||||
|
|
||||||
|
private ExternalViewerShortcutAction() {
|
||||||
|
super(Bundle.ExternalViewerShortcutAction_title_text());
|
||||||
|
}
|
||||||
|
|
||||||
|
// This class is a singleton to support multi-selection of nodes, since
|
||||||
|
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
|
||||||
|
// node in the array returns a reference to the same action object from Node.getActions(boolean).
|
||||||
|
private static ExternalViewerShortcutAction instance;
|
||||||
|
|
||||||
|
public static synchronized ExternalViewerShortcutAction getInstance() {
|
||||||
|
if (null == instance) {
|
||||||
|
instance = new ExternalViewerShortcutAction();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
final Collection<AbstractFile> selectedFiles = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||||
|
if (!selectedFiles.isEmpty()) {
|
||||||
|
for (AbstractFile file : selectedFiles) {
|
||||||
|
ExternalViewerAction action = new ExternalViewerAction(Bundle.ExternalViewerShortcutAction_title_text(), file, false);
|
||||||
|
action.actionPerformed(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2018 Basis Technology Corp.
|
* Copyright 2011-2019 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");
|
||||||
@ -65,6 +65,7 @@ import org.sleuthkit.autopsy.corecomponents.DataResultPanel;
|
|||||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||||
import org.sleuthkit.autopsy.timeline.actions.Back;
|
import org.sleuthkit.autopsy.timeline.actions.Back;
|
||||||
import org.sleuthkit.autopsy.timeline.actions.Forward;
|
import org.sleuthkit.autopsy.timeline.actions.Forward;
|
||||||
import org.sleuthkit.autopsy.timeline.explorernodes.EventNode;
|
import org.sleuthkit.autopsy.timeline.explorernodes.EventNode;
|
||||||
@ -103,7 +104,9 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer
|
|||||||
|
|
||||||
private final TimeLineController controller;
|
private final TimeLineController controller;
|
||||||
|
|
||||||
/** Lookup that will be exposed through the (Global Actions Context) */
|
/**
|
||||||
|
* Lookup that will be exposed through the (Global Actions Context)
|
||||||
|
*/
|
||||||
private final ModifiableProxyLookup proxyLookup = new ModifiableProxyLookup();
|
private final ModifiableProxyLookup proxyLookup = new ModifiableProxyLookup();
|
||||||
|
|
||||||
private final PropertyChangeListener focusPropertyListener = new PropertyChangeListener() {
|
private final PropertyChangeListener focusPropertyListener = new PropertyChangeListener() {
|
||||||
@ -261,7 +264,8 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer
|
|||||||
|
|
||||||
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(AddBookmarkTagAction.BOOKMARK_SHORTCUT, "addBookmarkTag"); //NON-NLS
|
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(AddBookmarkTagAction.BOOKMARK_SHORTCUT, "addBookmarkTag"); //NON-NLS
|
||||||
getActionMap().put("addBookmarkTag", new AddBookmarkTagAction()); //NON-NLS
|
getActionMap().put("addBookmarkTag", new AddBookmarkTagAction()); //NON-NLS
|
||||||
|
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ExternalViewerShortcutAction.EXTERNAL_VIEWER_SHORTCUT, "useExternalViewer"); //NON-NLS
|
||||||
|
getActionMap().put("useExternalViewer", ExternalViewerShortcutAction.getInstance()); //NON-NLS
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
|
|
||||||
//create linked result and content views
|
//create linked result and content views
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013-2018 Basis Technology Corp.
|
* Copyright 2013-2019 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");
|
||||||
@ -50,6 +50,7 @@ import javafx.scene.layout.VBox;
|
|||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.stage.Modality;
|
import javafx.stage.Modality;
|
||||||
import javax.annotation.concurrent.GuardedBy;
|
import javax.annotation.concurrent.GuardedBy;
|
||||||
|
import javax.swing.JComponent;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
|
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
|
||||||
import static org.apache.commons.lang3.ObjectUtils.notEqual;
|
import static org.apache.commons.lang3.ObjectUtils.notEqual;
|
||||||
@ -64,6 +65,7 @@ import org.openide.windows.TopComponent;
|
|||||||
import org.openide.windows.WindowManager;
|
import org.openide.windows.WindowManager;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager;
|
||||||
import org.sleuthkit.autopsy.imagegallery.gui.DataSourceCell;
|
import org.sleuthkit.autopsy.imagegallery.gui.DataSourceCell;
|
||||||
@ -238,6 +240,8 @@ public final class ImageGalleryTopComponent extends TopComponent implements Expl
|
|||||||
public ImageGalleryTopComponent() {
|
public ImageGalleryTopComponent() {
|
||||||
setName(Bundle.CTL_ImageGalleryTopComponent());
|
setName(Bundle.CTL_ImageGalleryTopComponent());
|
||||||
initComponents();
|
initComponents();
|
||||||
|
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ExternalViewerShortcutAction.EXTERNAL_VIEWER_SHORTCUT, "useExternalViewer"); //NON-NLS
|
||||||
|
getActionMap().put("useExternalViewer", ExternalViewerShortcutAction.getInstance()); //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2015 Basis Technology Corp.
|
* Copyright 2015-2019 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");
|
||||||
@ -21,6 +21,9 @@ package org.sleuthkit.autopsy.imagegallery.actions;
|
|||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyCodeCombination;
|
||||||
|
import javafx.scene.input.KeyCombination;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import org.controlsfx.control.action.Action;
|
import org.controlsfx.control.action.Action;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
@ -37,6 +40,7 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
|
|||||||
public class OpenExternalViewerAction extends Action {
|
public class OpenExternalViewerAction extends Action {
|
||||||
|
|
||||||
private static final Image EXTERNAL = new Image(OpenExternalViewerAction.class.getResource("/org/sleuthkit/autopsy/imagegallery/images/external.png").toExternalForm()); //NON-NLS
|
private static final Image EXTERNAL = new Image(OpenExternalViewerAction.class.getResource("/org/sleuthkit/autopsy/imagegallery/images/external.png").toExternalForm()); //NON-NLS
|
||||||
|
public static final KeyCombination EXTERNAL_VIEWER_SHORTCUT = new KeyCodeCombination(KeyCode.E, KeyCombination.CONTROL_DOWN);
|
||||||
private static final ActionEvent ACTION_EVENT = new ActionEvent(OpenExternalViewerAction.class, ActionEvent.ACTION_PERFORMED, ""); //Swing ActionEvent //NOI18N
|
private static final ActionEvent ACTION_EVENT = new ActionEvent(OpenExternalViewerAction.class, ActionEvent.ACTION_PERFORMED, ""); //Swing ActionEvent //NOI18N
|
||||||
|
|
||||||
public OpenExternalViewerAction(DrawableFile file) {
|
public OpenExternalViewerAction(DrawableFile file) {
|
||||||
@ -49,9 +53,12 @@ public class OpenExternalViewerAction extends Action {
|
|||||||
ExternalViewerAction externalViewerAction = new ExternalViewerAction(Bundle.MediaViewImagePanel_externalViewerButton_text(), new FileNode(file.getAbstractFile()));
|
ExternalViewerAction externalViewerAction = new ExternalViewerAction(Bundle.MediaViewImagePanel_externalViewerButton_text(), new FileNode(file.getAbstractFile()));
|
||||||
|
|
||||||
setLongText(Bundle.MediaViewImagePanel_externalViewerButton_text());
|
setLongText(Bundle.MediaViewImagePanel_externalViewerButton_text());
|
||||||
setEventHandler(actionEvent -> //fx ActionEvent
|
setEventHandler(actionEvent
|
||||||
|
-> //fx ActionEvent
|
||||||
SwingUtilities.invokeLater(() -> externalViewerAction.actionPerformed(ACTION_EVENT))
|
SwingUtilities.invokeLater(() -> externalViewerAction.actionPerformed(ACTION_EVENT))
|
||||||
);
|
);
|
||||||
setGraphic(new ImageView(EXTERNAL));
|
setGraphic(new ImageView(EXTERNAL));
|
||||||
|
setAccelerator(EXTERNAL_VIEWER_SHORTCUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013-2018 Basis Technology Corp.
|
* Copyright 2013-2019 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");
|
||||||
@ -47,7 +47,6 @@ import javafx.scene.layout.Region;
|
|||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import org.controlsfx.control.action.ActionUtils;
|
|
||||||
import org.openide.util.Lookup;
|
import org.openide.util.Lookup;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.Utilities;
|
import org.openide.util.Utilities;
|
||||||
@ -60,6 +59,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
|||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.ContextMenuActionsProvider;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.ContextMenuActionsProvider;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileNode;
|
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||||
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||||
import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel;
|
import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel;
|
||||||
@ -214,11 +214,13 @@ public abstract class DrawableTileBase extends DrawableUIBase {
|
|||||||
.actionPerformed(null);
|
.actionPerformed(null);
|
||||||
}));
|
}));
|
||||||
menuItems.add(contentViewer);
|
menuItems.add(contentViewer);
|
||||||
|
MenuItem externalViewer = new MenuItem("Open in External Viewer");
|
||||||
OpenExternalViewerAction openExternalViewerAction = new OpenExternalViewerAction(file);
|
externalViewer.setOnAction(actionEvent
|
||||||
MenuItem externalViewer = ActionUtils.createMenuItem(openExternalViewerAction);
|
-> SwingUtilities.invokeLater(() -> {
|
||||||
externalViewer.textProperty().unbind();
|
ExternalViewerShortcutAction.getInstance()
|
||||||
externalViewer.textProperty().bind(openExternalViewerAction.longTextProperty());
|
.actionPerformed(null);
|
||||||
|
}));
|
||||||
|
externalViewer.setAccelerator(OpenExternalViewerAction.EXTERNAL_VIEWER_SHORTCUT);
|
||||||
menuItems.add(externalViewer);
|
menuItems.add(externalViewer);
|
||||||
|
|
||||||
Collection<? extends ContextMenuActionsProvider> menuProviders = Lookup.getDefault().lookupAll(ContextMenuActionsProvider.class);
|
Collection<? extends ContextMenuActionsProvider> menuProviders = Lookup.getDefault().lookupAll(ContextMenuActionsProvider.class);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
OpenIDE-Module-Display-Category=Ingest Module
|
OpenIDE-Module-Display-Category=Ingest Module
|
||||||
|
|
||||||
OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found.
|
OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found.
|
||||||
OpenIDE-Module-Name=KeywordSearch
|
OpenIDE-Module-Name=KeywordSearch
|
||||||
OptionsCategory_Name_KeywordSearchOptions=Keyword Search
|
OptionsCategory_Name_KeywordSearchOptions=Keyword Search
|
||||||
@ -87,7 +88,7 @@ KeywordSearchEditListPanel.exportButtonActionPerformed.kwListExportedMsg=Keyword
|
|||||||
KeywordSearchEditListPanel.kwColName=Keyword
|
KeywordSearchEditListPanel.kwColName=Keyword
|
||||||
KeywordSearchEditListPanel.addKeyword.message=Add a new word to the keyword search list:
|
KeywordSearchEditListPanel.addKeyword.message=Add a new word to the keyword search list:
|
||||||
KeywordSearchEditListPanel.addKeyword.title=New Keyword
|
KeywordSearchEditListPanel.addKeyword.title=New Keyword
|
||||||
KeywordSearchFilterNode.getFileActions.openExternViewActLbl=Open in External Viewer
|
KeywordSearchFilterNode.getFileActions.openExternViewActLbl=Open in External Viewer Ctrl+E
|
||||||
KeywordSearchFilterNode.getFileActions.searchSameMd5=Search for files with the same MD5 hash
|
KeywordSearchFilterNode.getFileActions.searchSameMd5=Search for files with the same MD5 hash
|
||||||
KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl=View in New Window
|
KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl=View in New Window
|
||||||
KeywordSearchIngestModule.init.noKwInLstMsg=No keywords in keyword list.
|
KeywordSearchIngestModule.init.noKwInLstMsg=No keywords in keyword list.
|
||||||
|
@ -122,7 +122,7 @@ KeywordSearchEditListPanel.exportButtonActionPerformed.kwListExportedMsg=Keyword
|
|||||||
KeywordSearchEditListPanel.kwColName=Keyword
|
KeywordSearchEditListPanel.kwColName=Keyword
|
||||||
KeywordSearchEditListPanel.addKeyword.message=Add a new word to the keyword search list:
|
KeywordSearchEditListPanel.addKeyword.message=Add a new word to the keyword search list:
|
||||||
KeywordSearchEditListPanel.addKeyword.title=New Keyword
|
KeywordSearchEditListPanel.addKeyword.title=New Keyword
|
||||||
KeywordSearchFilterNode.getFileActions.openExternViewActLbl=Open in External Viewer
|
KeywordSearchFilterNode.getFileActions.openExternViewActLbl=Open in External Viewer Ctrl+E
|
||||||
KeywordSearchFilterNode.getFileActions.searchSameMd5=Search for files with the same MD5 hash
|
KeywordSearchFilterNode.getFileActions.searchSameMd5=Search for files with the same MD5 hash
|
||||||
KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl=View in New Window
|
KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl=View in New Window
|
||||||
KeywordSearchIngestModule.init.noKwInLstMsg=No keywords in keyword list.
|
KeywordSearchIngestModule.init.noKwInLstMsg=No keywords in keyword list.
|
||||||
|
287
ManifestTool/ManifestGenerationAlgorithms.au3
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
;==============================================================================
|
||||||
|
; Autopsy Forensic Browser
|
||||||
|
;
|
||||||
|
; Copyright 2019 Basis Technology Corp.
|
||||||
|
; Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
;
|
||||||
|
; Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
; you may not use this file except in compliance with the License.
|
||||||
|
; You may obtain a copy of the License at
|
||||||
|
;
|
||||||
|
; http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
;
|
||||||
|
; Unless required by applicable law or agreed to in writing, software
|
||||||
|
; distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
; See the License for the specific language governing permissions and
|
||||||
|
; limitations under the License.
|
||||||
|
;==============================================================================
|
||||||
|
#include <GUIConstantsEx.au3>
|
||||||
|
#include <MsgBoxConstants.au3>
|
||||||
|
#include <ProgressConstants.au3>
|
||||||
|
#include <File.au3>
|
||||||
|
#include <WinAPIFiles.au3>
|
||||||
|
#include <ScrollBarConstants.au3>
|
||||||
|
#include <GuiEdit.au3>
|
||||||
|
#include <Date.au3>
|
||||||
|
|
||||||
|
;Get the list of names of algorithms
|
||||||
|
Global $algorithms[3] ;increase size of array when adding new algorithms
|
||||||
|
$algorithms[0] = "Single Data Source"
|
||||||
|
$algorithms[1] = "Folder of Logical Files"
|
||||||
|
$algorithms[2] = "One Data Source Per Folder"
|
||||||
|
|
||||||
|
; $algorithms[2] = "All Files In One Folder"
|
||||||
|
Global $progressArea = Null
|
||||||
|
Global $manifestFileNameEnd = "Manifest"
|
||||||
|
Global $manifestExtension = ".xml"
|
||||||
|
|
||||||
|
|
||||||
|
;Return an array containing the names of all algorithms
|
||||||
|
Func GetAlgorithmNames()
|
||||||
|
Return $algorithms
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Return the name of the first algorithm as a default algorithm
|
||||||
|
Func GetDefaultAlgorithmName()
|
||||||
|
Return $algorithms[0]
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Run the function that corresponds to the specified Algorithm name
|
||||||
|
;Use Null for $progressArea if not called from a GUI with a $progressArea
|
||||||
|
Func RunAlgorithm($selectedAlgorithm, $settings, ByRef $progressAreaRef)
|
||||||
|
$progressArea = $progressAreaRef
|
||||||
|
UpdateProgressArea("Analyzing: " & $settings[0])
|
||||||
|
if ($selectedAlgorithm == $algorithms[2]) Then
|
||||||
|
OneDataSourcePerFolder($settings)
|
||||||
|
ElseIf ($selectedAlgorithm == $algorithms[0]) Then
|
||||||
|
SingleDataSource($settings)
|
||||||
|
ElseIf ($selectedAlgorithm == $algorithms[1]) Then
|
||||||
|
SingleDataSource($settings)
|
||||||
|
; ElseIf ($selectedAlgorithm == $algorithms[2]) Then
|
||||||
|
; AllFilesInOneFolder($settings)
|
||||||
|
EndIf
|
||||||
|
UpdateProgressArea("-------------------------------------------------------------------------------------------") ;blank line for some
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Create a manifest file in the specified $caseDir named $manifestDir _Manifest.xml
|
||||||
|
;if the $manifestFile is specified the datasource included will be the file instead of the entire folder
|
||||||
|
Func GenerateCaseNameAndWriteManifestFile($caseDir, $subDirName, $manifestFile)
|
||||||
|
Local $manifestName = ""
|
||||||
|
Local $caseName = ""
|
||||||
|
Local $dataSourcePath = ""
|
||||||
|
;If the manifestDirectory is not Null use it for the file name
|
||||||
|
if ($subDirName <> Null) Then
|
||||||
|
$manifestName = $subDirName
|
||||||
|
$dataSourcePath = $manifestName
|
||||||
|
if ($manifestFile <> Null) Then
|
||||||
|
$dataSourcePath = $dataSourcePath & "\" & $manifestFile
|
||||||
|
EndIf
|
||||||
|
;If the manifestDirectory was Null then use the file name
|
||||||
|
ElseIf ($manifestFile <> Null) Then
|
||||||
|
$manifestName = $manifestFile
|
||||||
|
$dataSourcePath = $manifestName
|
||||||
|
Else
|
||||||
|
UpdateProgressArea("ERROR: Invalid arguements provided, unable to create manifest file")
|
||||||
|
Return
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
Local $splitCaseDir = StringSplit($caseDir, "\", $STR_ENTIRESPLIT)
|
||||||
|
$caseName = $splitCaseDir[$splitCaseDir[0]]
|
||||||
|
|
||||||
|
Local $manfiestFilePath = $caseDir & "\" & $manifestName & "_" & $manifestFileNameEnd & $manifestExtension
|
||||||
|
WriteManifestFile($manfiestFilePath, $manifestName, $caseName, $dataSourcePath)
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Write the specified manifest file.
|
||||||
|
Func WriteManifestFile($manifestFilePath, $manifestName, $caseName, $dataSourcePath)
|
||||||
|
_FileCreate($manifestFilePath)
|
||||||
|
Local $fileHandle = FileOpen($manifestFilePath, $FO_APPEND)
|
||||||
|
If $fileHandle == -1 Then
|
||||||
|
UpdateProgressArea("ERROR: " & $manifestName & " Unable to create manifest file")
|
||||||
|
Return
|
||||||
|
EndIf
|
||||||
|
FileWrite($fileHandle,'<?xml version="1.0" encoding="UTF-8" standalone="no"?>' & @CRLF)
|
||||||
|
FileWrite($fileHandle,'<AutopsyManifest>' & @CRLF)
|
||||||
|
FileWrite($fileHandle,'<CaseName>' & $caseName &'</CaseName>' & @CRLF)
|
||||||
|
;Device ID is not a required field
|
||||||
|
FileWrite($fileHandle,'<DataSource>' & $dataSourcePath & '</DataSource>' & @CRLF)
|
||||||
|
FileWrite($fileHandle,'</AutopsyManifest>' & @CRLF)
|
||||||
|
FileClose($fileHandle)
|
||||||
|
UpdateProgressArea($manifestName & " manifest created")
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;get the extension of a file
|
||||||
|
Func GetFileExtension($fileName)
|
||||||
|
Local $fileExtension
|
||||||
|
_PathSplit ($fileName, "", "", "", $fileExtension)
|
||||||
|
Return $fileExtension
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Return 0 for false if no manifest files exist in the caseDir, or 1 for true if manifest files do exist
|
||||||
|
Func ManifestFilesAlreadyExist($fileList)
|
||||||
|
Local $fileName
|
||||||
|
Local $fileExtension
|
||||||
|
For $i = 1 To $fileList[0] Step 1
|
||||||
|
_PathSplit ($fileList[$i], "", "", $fileName, $fileExtension)
|
||||||
|
If StringCompare($fileExtension, $manifestExtension, $STR_NOCASESENSE) == 0 Then
|
||||||
|
Local $splitFileName = StringSplit($fileName, "_", $STR_ENTIRESPLIT)
|
||||||
|
if $splitFileName[0] > 1 Then ;It split into more than one chunk so the last chunk should match our _Manifest
|
||||||
|
If StringCompare($splitFileName[$splitFileName[0]], $manifestFileNameEnd, $STR_NOCASESENSE) == 0 Then
|
||||||
|
UpdateProgressArea("Folder already contains manifest file: " & $fileList[$i])
|
||||||
|
Return 1
|
||||||
|
EndIf
|
||||||
|
EndIf
|
||||||
|
EndIf
|
||||||
|
Next
|
||||||
|
Return 0
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Check if a manifest file already exists for a specific datasource in the case Dir
|
||||||
|
;Return 1 if a manifest exists
|
||||||
|
;Return 0 if no manifest exists
|
||||||
|
Func ManifestAlreadyExists($manifestFilePath)
|
||||||
|
If FileExists($manifestFilePath) == 1 Then
|
||||||
|
Return 1
|
||||||
|
Else
|
||||||
|
Return 0
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
|
||||||
|
;Algorithm for the "One Data Source Per Folder"
|
||||||
|
;Creates manifest files
|
||||||
|
Func OneDataSourcePerFolder($settings)
|
||||||
|
Local $validDirectory = 1
|
||||||
|
Local $caseDir = $settings[0]
|
||||||
|
;_FileListToArray returns the count of files/folders as the first value then the contents
|
||||||
|
Local $fileList = _FileListToArray($caseDir, Default, $FLTA_FILES, False)
|
||||||
|
Local $caseDirSplit = StringSplit($caseDir, "\", $STR_ENTIRESPLIT)
|
||||||
|
Local $caseDirName
|
||||||
|
if ($caseDirSplit[0] > 1) Then
|
||||||
|
;if case folder is longer than one directory display just the directory name in progress messages
|
||||||
|
$caseDirName = $caseDirSplit[$caseDirSplit[0]]
|
||||||
|
Else
|
||||||
|
;if there is only one directory use the entire case dir path
|
||||||
|
EndIf
|
||||||
|
If (@error == 1) Then
|
||||||
|
$validDirectory = 0
|
||||||
|
UpdateProgressArea("ERROR: " & $caseDirName & " not found")
|
||||||
|
MsgBox($MB_OK, "Directory Not Found", "Selected directory " & $caseDirName & " was not found.")
|
||||||
|
ElseIf (@error > 0) Then
|
||||||
|
;An acceptable condition as no files means no manifest files
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
Local $dirList = _FileListToArray($caseDir, Default, $FLTA_FOLDERS, True)
|
||||||
|
If (@error ==4) Then
|
||||||
|
UpdateProgressArea($caseDirName & " no folders found")
|
||||||
|
MsgBox($MB_OK, "Selected Directory Empty", "Selected directory " & $caseDirName & " did not contain any subfolders to use as data sources for manifest files.")
|
||||||
|
$validDirectory = 0
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
If $validDirectory = 1 Then
|
||||||
|
Local $validExtensions[4] = [".e01", ".l01", ".001", ".ad1"] ;valid extensions for the One Data Source Per Folder algorithm
|
||||||
|
Local $subDirectoryFileList
|
||||||
|
Local $validSubDirectory
|
||||||
|
For $fileNumber = 1 TO $dirList[0] Step 1
|
||||||
|
Local $manifestFile = Null
|
||||||
|
Local $manifestDir = $dirList[$fileNumber]
|
||||||
|
Local $splitManifestDir = StringSplit($manifestDir, "\", $STR_ENTIRESPLIT)
|
||||||
|
Local $manifestDirName = $splitManifestDir[$splitManifestDir[0]]
|
||||||
|
$subDirectoryFileList = _FileListToArray($dirList[$fileNumber], Default, Default, False)
|
||||||
|
$validSubDirectory = 1
|
||||||
|
If (@error == 1) Then
|
||||||
|
$validSubDirectory = 0
|
||||||
|
UpdateProgressArea("ERROR: " & $dirList[$fileNumber] & " not found")
|
||||||
|
ElseIf (@error ==4) Then
|
||||||
|
UpdateProgressArea($manifestDirName & " empty, no manifest created")
|
||||||
|
$validSubDirectory = 0
|
||||||
|
EndIf
|
||||||
|
If $validSubDirectory == 1 Then
|
||||||
|
For $i = 1 TO $subDirectoryFileList[0] Step 1
|
||||||
|
Local $currentFilesExtension = GetFileExtension($subDirectoryFileList[$i])
|
||||||
|
For $extension IN $validExtensions
|
||||||
|
;should only be one file or directory in this folder since we checked the number of contents previously
|
||||||
|
If StringCompare($extension, $currentFilesExtension, $STR_NOCASESENSE) == 0 Then
|
||||||
|
$manifestFile = $subDirectoryFileList[$i]
|
||||||
|
ExitLoop 2 ;match was found no reason to check remaining extensions or files in a One Data Source Per Folder algorithm
|
||||||
|
EndIf
|
||||||
|
Next
|
||||||
|
Next
|
||||||
|
Local $manifestFilePath = $caseDir & "\" & $manifestDirName & "_" & $manifestFileNameEnd & $manifestExtension
|
||||||
|
If (ManifestAlreadyExists($manifestFilePath) <> 1) Then
|
||||||
|
;should only be one file and it should end with a valid extension add as image file, or the whole directory is added as a logical file set
|
||||||
|
GenerateCaseNameAndWriteManifestFile($caseDir, $manifestDirName, $manifestFile)
|
||||||
|
Else
|
||||||
|
UpdateProgressArea($manifestDirName & " manifest exists, skipping")
|
||||||
|
EndIf
|
||||||
|
EndIf
|
||||||
|
Next
|
||||||
|
UpdateProgressArea($caseDirName & " manifest generation complete")
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Create a manifest file for a single data source in the same directory that contains the data source (also used for Folder of Logical Files)
|
||||||
|
Func SingleDataSource($settings)
|
||||||
|
Local $dataSourcePath = $settings[0]
|
||||||
|
Local $caseDir = ""
|
||||||
|
Local $caseDrive = ""
|
||||||
|
Local $dsName = ""
|
||||||
|
Local $dsExtension = ""
|
||||||
|
_PathSplit ($dataSourcePath, $caseDrive, $caseDir, $dsName, $dsExtension)
|
||||||
|
$caseDir = $caseDrive & $caseDir
|
||||||
|
Local $caseName = $settings[1]
|
||||||
|
Local $manfiestFilePath = $caseDir & "\" & $dsName & "_" & $manifestFileNameEnd & $manifestExtension
|
||||||
|
If (ManifestAlreadyExists($manfiestFilePath) <> 1) Then
|
||||||
|
;should only be one file and it should end with a valid extension add as image file, or the whole directory is added as a logical file set
|
||||||
|
WriteManifestFile($manfiestFilePath, $dsName, $caseName, $dsName & $dsExtension)
|
||||||
|
Else
|
||||||
|
UpdateProgressArea($dsName & " manifest exists, skipping")
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Algorithm for the All Files in One Folder
|
||||||
|
;Creates manifest files for all files and directories in a single directory
|
||||||
|
Func AllFilesInOneFolder($settings)
|
||||||
|
Local $validDirectory = 1
|
||||||
|
Local $caseDir = $settings[0]
|
||||||
|
;_FileListToArray returns the count of files/folders as the first value then the contents
|
||||||
|
Local $fileList = _FileListToArray($caseDir, Default, $FLTA_FILES, False)
|
||||||
|
If (@error == 1) Then
|
||||||
|
$validDirectory = 0
|
||||||
|
UpdateProgressArea("Selected directory " & $caseDir & " was not found")
|
||||||
|
MsgBox($MB_OK, "Directory Not Found", "Selected directory " & $caseDir & " was not found")
|
||||||
|
ElseIf (@error > 0) Then
|
||||||
|
Local $dirList = _FileListToArray($caseDir, Default, $FLTA_FOLDERS, True)
|
||||||
|
If (@error ==4) Then
|
||||||
|
UpdateProgressArea("Selected directory " & $caseDir & " was empty and contained nothing to generate manifest files for")
|
||||||
|
MsgBox($MB_OK, "Selected Directory Empty", "Selected directory " & $caseDir & " was empty and contained nothing to generate manifest files for")
|
||||||
|
$validDirectory = 0
|
||||||
|
EndIf
|
||||||
|
;An acceptable condition as no files means no manifest files
|
||||||
|
ElseIf ManifestFilesAlreadyExist($fileList) == 1 Then
|
||||||
|
UpdateProgressArea("Selected directory " & $caseDir & " already contains manifest files, they must be deleted before generating new ones")
|
||||||
|
MsgBox($MB_OK, "Manifest Files Exist", "Selected directory " & $caseDir & " already contains manifest files, they must be deleted before generating new ones")
|
||||||
|
$validDirectory = 0
|
||||||
|
EndIf
|
||||||
|
Local $contentsList = _FileListToArray ($caseDir, Default, Default, False)
|
||||||
|
If $validDirectory = 1 Then
|
||||||
|
For $fileNumber = 1 TO $contentsList[0] Step 1
|
||||||
|
Local $manifestDir = Null
|
||||||
|
Local $manifestFile = $contentsList[$fileNumber]
|
||||||
|
GenerateCaseNameAndWriteManifestFile($caseDir, $manifestDir, $manifestFile)
|
||||||
|
Next
|
||||||
|
UpdateProgressArea($caseDir & " manifest generation complete")
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;If the progress area is Null it will not be updated
|
||||||
|
Func UpdateProgressArea($textToAdd)
|
||||||
|
if ($progressArea <> Null) Then
|
||||||
|
Local $currentProgressAreaText = GUICtrlRead($progressArea)
|
||||||
|
$currentProgressAreaText = $currentProgressAreaText & @CRLF & "--" & $textToAdd
|
||||||
|
GUICtrlSetData($progressArea, $currentProgressAreaText)
|
||||||
|
_GUICtrlEdit_Scroll($progressArea, $SB_SCROLLCARET)
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
316
ManifestTool/ManifestTool.au3
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
;==============================================================================
|
||||||
|
; Autopsy Forensic Browser
|
||||||
|
;
|
||||||
|
; Copyright 2019 Basis Technology Corp.
|
||||||
|
; Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
;
|
||||||
|
; Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
; you may not use this file except in compliance with the License.
|
||||||
|
; You may obtain a copy of the License at
|
||||||
|
;
|
||||||
|
; http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
;
|
||||||
|
; Unless required by applicable law or agreed to in writing, software
|
||||||
|
; distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
; See the License for the specific language governing permissions and
|
||||||
|
; limitations under the License.
|
||||||
|
;==============================================================================
|
||||||
|
#include <GUIConstantsEx.au3>
|
||||||
|
#include <MsgBoxConstants.au3>
|
||||||
|
#include<ComboConstants.au3>
|
||||||
|
#include <EditConstants.au3>
|
||||||
|
#include<WindowsConstants.au3>
|
||||||
|
#include <ManifestGenerationAlgorithms.au3>
|
||||||
|
|
||||||
|
|
||||||
|
Opt("GUIOnEventMode", 1) ; Change to OnEvent mode
|
||||||
|
;==============================================
|
||||||
|
;
|
||||||
|
;Draw GUI and declare variables
|
||||||
|
;
|
||||||
|
;==============================================
|
||||||
|
local $windowHeight = 500
|
||||||
|
local $windowWidth = 400
|
||||||
|
local $windowTitle = "Autopsy AutoIngest Manifest File Generator"
|
||||||
|
Global $hMainGUI = GUICreate($windowTitle, $windowWidth, $windowHeight) ;To make GUI resize add following args -1, -1, $WS_OVERLAPPEDWINDOW)
|
||||||
|
;GUICtrlSetResizing ($hMainGUI, $GUI_DOCKBORDERS)
|
||||||
|
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEButton")
|
||||||
|
|
||||||
|
Global $propertiesFile = "ManifestTool.settings"
|
||||||
|
Global $workingDir = @WorkingDir
|
||||||
|
|
||||||
|
local $topMargin = 12
|
||||||
|
local $leftMargin = 12
|
||||||
|
local $labelOffset = 1
|
||||||
|
local $buttonOffset = -3
|
||||||
|
local $progressAreaInset = 8
|
||||||
|
local $distanceFromTop = $topMargin
|
||||||
|
local $distanceFromLeft = $leftMargin
|
||||||
|
Global $defaultDirectory = @MyDocumentsDir & "\"
|
||||||
|
local $labelWidth = 58
|
||||||
|
local $fieldWidth = 235
|
||||||
|
local $buttonWidth = 60
|
||||||
|
local $fieldHeight = 20
|
||||||
|
local $progressAreaWidth = $windowWidth - 2*($progressAreaInset+$leftMargin)
|
||||||
|
local $gapBetweenWidth = 10
|
||||||
|
local $gapBetweenHeight = 10
|
||||||
|
|
||||||
|
;Draw the GUI Code
|
||||||
|
GUICtrlCreateLabel("Algorithm", $distanceFromLeft, $distanceFromTop+$labelOffset)
|
||||||
|
$distanceFromLeft = $distanceFromLeft+$labelWidth+$gapBetweenWidth
|
||||||
|
|
||||||
|
Global $algorithmComboBox = GUICtrlCreateCombo(GetDefaultAlgorithmName(), $distanceFromLeft, $distanceFromTop, $fieldWidth, $fieldHeight, $CBS_DROPDOWNLIST)
|
||||||
|
GUICtrlSetOnEvent($algorithmComboBox, "Redraw")
|
||||||
|
Global $allAlgorithmNames = GetAlgorithmNames()
|
||||||
|
for $algorithmName IN $allAlgorithmNames
|
||||||
|
; Add additional items to the combobox.
|
||||||
|
GUICtrlSetData($algorithmComboBox, $algorithmName)
|
||||||
|
Next
|
||||||
|
|
||||||
|
|
||||||
|
$distanceFromLeft = $leftMargin
|
||||||
|
$distanceFromTop = $distanceFromTop + $fieldHeight + $gapBetweenHeight
|
||||||
|
|
||||||
|
Global $rootFolderLabel = GUICtrlCreateLabel("Root Folder", $distanceFromLeft, $distanceFromTop+$labelOffset)
|
||||||
|
$distanceFromLeft = $distanceFromLeft+$labelWidth+$gapBetweenWidth
|
||||||
|
Global $rootFolderField = GUICtrlCreateInput("", $distanceFromLeft, $distanceFromTop, $fieldWidth, $fieldHeight)
|
||||||
|
$distanceFromLeft = $distanceFromLeft +$fieldWidth+$gapBetweenWidth
|
||||||
|
Global $browseButton = GUICtrlCreateButton("Browse", $distanceFromLeft, $distanceFromTop+$buttonOffset, $buttonWidth)
|
||||||
|
$distanceFromLeft = $leftMargin
|
||||||
|
$distanceFromTop = $distanceFromTop + $fieldHeight + $gapBetweenHeight
|
||||||
|
|
||||||
|
Global $caseNameLabel = GUICtrlCreateLabel("Case Name", $distanceFromLeft, $distanceFromTop+$labelOffset)
|
||||||
|
$distanceFromLeft = $distanceFromLeft+$labelWidth+$gapBetweenWidth
|
||||||
|
Global $caseNameField = GUICtrlCreateInput("", $distanceFromLeft, $distanceFromTop, $fieldWidth, $fieldHeight)
|
||||||
|
$distanceFromLeft = $leftMargin
|
||||||
|
$distanceFromTop = $distanceFromTop + $fieldHeight + $gapBetweenHeight
|
||||||
|
|
||||||
|
$distanceFromTop = $distanceFromTop + $gapBetweenHeight ;add an extra gap before run button
|
||||||
|
Global $runButton = GUICtrlCreateButton("Run", $distanceFromLeft, $distanceFromTop+$buttonOffset, $buttonWidth)
|
||||||
|
GUICtrlSetOnEvent($runButton, "AlgorithmRunAction")
|
||||||
|
$distanceFromTop = $distanceFromTop + $fieldHeight + $gapBetweenHeight
|
||||||
|
|
||||||
|
$distanceFromTop = $distanceFromTop + $fieldHeight + $gapBetweenHeight ;add extra gap before progress area
|
||||||
|
local $ProgressLabel = GUICtrlCreateLabel("Progress", $distanceFromLeft, $distanceFromTop+$labelOffset)
|
||||||
|
$distanceFromTop = $distanceFromTop + $fieldHeight + $gapBetweenHeight
|
||||||
|
|
||||||
|
$distanceFromLeft = $distanceFromLeft + $progressAreaInset
|
||||||
|
$progressAreaHeight = $windowHeight -$distanceFromTop - $gapBetweenHeight - $gapBetweenHeight - $fieldHeight ;calculate height of progress area to use remaining space minus space for exit button
|
||||||
|
Global $progressField = GUICtrlCreateEdit("", $distanceFromLeft, $distanceFromTop, $progressAreaWidth, $progressAreaHeight, BitOr($ES_READONLY,$WS_VSCROLL, $ES_MULTILINE))
|
||||||
|
|
||||||
|
$distanceFromLeft = $distanceFromLeft + $progressAreaWidth - $buttonWidth
|
||||||
|
$distanceFromTop = $distanceFromTop + $progressAreaHeight + $gapBetweenHeight
|
||||||
|
Local $exitButton = GUICtrlCreateButton("Exit", $distanceFromLeft, $distanceFromTop+$buttonOffset, $buttonWidth)
|
||||||
|
GUICtrlSetOnEvent($exitButton, "CLOSEButton")
|
||||||
|
|
||||||
|
|
||||||
|
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEButton")
|
||||||
|
GUISwitch($hMainGUI)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
ChangeToDefaultGUI()
|
||||||
|
|
||||||
|
ReadPropertiesFile()
|
||||||
|
|
||||||
|
Local $oldCaseName = GUICtrlRead($caseNameField)
|
||||||
|
local $oldRootFolder = GUICtrlRead($rootFolderField)
|
||||||
|
While 1
|
||||||
|
Sleep(100) ; Sleep to reduce CPU usage
|
||||||
|
ValidateFields($oldCaseName, $oldRootFolder) ;validate here so that we check the current value of any input areas without requiring a change in focus
|
||||||
|
$oldCaseName = GUICtrlRead($caseNameField)
|
||||||
|
$oldRootFolder = GUICtrlRead($rootFolderField)
|
||||||
|
WEnd
|
||||||
|
|
||||||
|
|
||||||
|
;==============================================
|
||||||
|
;
|
||||||
|
;Functions
|
||||||
|
;
|
||||||
|
;==============================================
|
||||||
|
|
||||||
|
; Read the saved properties file, if none exist make one with the current settings
|
||||||
|
Func ReadPropertiesFile()
|
||||||
|
If FileExists($propertiesFile) <> 1 Then
|
||||||
|
FileChangeDir($workingDir)
|
||||||
|
_FileCreate($propertiesFile)
|
||||||
|
WritePropertiesFile()
|
||||||
|
Endif
|
||||||
|
Local $propertiesFileHandle = FileOpen($propertiesFile, $FO_READ)
|
||||||
|
Local $savedSelection = FileReadLine($propertiesFileHandle, 1)
|
||||||
|
Local $indexOfSelection = _ArraySearch($allAlgorithmNames, $savedSelection)
|
||||||
|
if ($indexOfSelection >= 0) Then
|
||||||
|
GUICtrlSetData($algorithmComboBox, $savedSelection, $savedSelection)
|
||||||
|
EndIf
|
||||||
|
Local $savedDirectory = FileReadLine($propertiesFileHandle, 2)
|
||||||
|
if (FileExists($savedDirectory)) Then
|
||||||
|
$defaultDirectory = $savedDirectory
|
||||||
|
EndIf
|
||||||
|
FileClose($propertiesFileHandle)
|
||||||
|
Redraw()
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
; Write the current settings to the properties file
|
||||||
|
Func WritePropertiesFile()
|
||||||
|
FileChangeDir($workingDir)
|
||||||
|
Local $propertiesFileHandle = FileOpen($propertiesFile, $FO_OVERWRITE)
|
||||||
|
If $propertiesFileHandle == -1 Then ;can't access the properties file so exit
|
||||||
|
Return
|
||||||
|
EndIf
|
||||||
|
FileWrite($propertiesFileHandle, GUICtrlRead($algorithmComboBox) & @CRLF)
|
||||||
|
FileWrite($propertiesFileHandle, $defaultDirectory & @CRLF)
|
||||||
|
FileClose($propertiesFileHandle)
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;Make only the settings and labels relevent to the selected Algorithm visible using $GUI_SHOW and $GUI_HIDE
|
||||||
|
Func Redraw()
|
||||||
|
; Note: At this point @GUI_CtrlId would equal algorithmComboBox
|
||||||
|
Local $selectedAlgName = GUICtrlRead($algorithmComboBox)
|
||||||
|
;Move controls based on what is hidden or shown using ControlGetPos() and GUICtrlSetPos()
|
||||||
|
If $selectedAlgName == $allAlgorithmNames[2] Then ;"One Data Source Per Folder"
|
||||||
|
ChangeToDefaultGUI()
|
||||||
|
ElseIf $selectedAlgName == $allAlgorithmNames[0] Then ;"Single Data Source"
|
||||||
|
ChangeToSingleDataSourceGUI()
|
||||||
|
ElseIf $selectedAlgName == $allAlgorithmNames[1] Then ;"Folder of Logical Files"
|
||||||
|
ChangeToFolderOfLogicalFilesGUI()
|
||||||
|
EndIf
|
||||||
|
EndFunc ;==>AlgorithmComboBox
|
||||||
|
|
||||||
|
;Change the controls displayed in the GUI to the ones needed for the Single Data Source algorithm
|
||||||
|
Func ChangeToSingleDataSourceGUI()
|
||||||
|
ClearFields()
|
||||||
|
GUICtrlSetData($rootFolderLabel, "Data Source")
|
||||||
|
GUICtrlSetState($caseNameField, $GUI_SHOW)
|
||||||
|
GUICtrlSetState($caseNameLabel, $GUI_SHOW)
|
||||||
|
GUICtrlSetOnEvent($browseButton, "BrowseForDataSourceFile")
|
||||||
|
GUICtrlSetState($runButton, $GUI_DISABLE)
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Change the controls displayed in the GUI to the ones needed for the Folder of Logical Files algorithm
|
||||||
|
Func ChangeToFolderOfLogicalFilesGUI()
|
||||||
|
ClearFields()
|
||||||
|
GUICtrlSetData($rootFolderLabel, "Data Source")
|
||||||
|
GUICtrlSetData($rootFolderLabel, "Data Source")
|
||||||
|
GUICtrlSetState($caseNameField, $GUI_SHOW)
|
||||||
|
GUICtrlSetState($caseNameLabel, $GUI_SHOW)
|
||||||
|
GUICtrlSetOnEvent($browseButton, "Browse")
|
||||||
|
GUICtrlSetState($runButton, $GUI_DISABLE)
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Change the controls displayed in the GUI to the ones needed for One
|
||||||
|
Func ChangeToDefaultGUI()
|
||||||
|
ClearFields()
|
||||||
|
GUICtrlSetData($rootFolderLabel, "Root Folder")
|
||||||
|
GUICtrlSetState($rootFolderField, $GUI_SHOW)
|
||||||
|
GUICtrlSetState($rootFolderLabel, $GUI_SHOW)
|
||||||
|
GUICtrlSetState($caseNameField, $GUI_HIDE)
|
||||||
|
GUICtrlSetState($caseNameLabel, $GUI_HIDE)
|
||||||
|
GUICtrlSetOnEvent($browseButton, "Browse")
|
||||||
|
;rename to RootDirectory to root directory
|
||||||
|
;hide case name field
|
||||||
|
GUICtrlSetState($runButton, $GUI_DISABLE)
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;ensure that all fields for the selected algorithm are valid
|
||||||
|
Func ValidateFields($oldCaseName, $oldRootFolder)
|
||||||
|
Local $dataSourcePath = GUICtrlRead($rootFolderField)
|
||||||
|
Local $caseName = GUICtrlRead($caseNameField)
|
||||||
|
if ($dataSourcePath <> $oldRootFolder Or $caseName <> $oldCaseName) Then
|
||||||
|
Local $selectedAlgName = GUICtrlRead($algorithmComboBox)
|
||||||
|
If $selectedAlgName == $allAlgorithmNames[2] Then ;"One Data Source Per Folder"
|
||||||
|
ValidateDefaultFields($dataSourcePath)
|
||||||
|
ElseIf $selectedAlgName == $allAlgorithmNames[0] Then ;"Single Data Source"
|
||||||
|
ValidateSingleDataSourceFields($dataSourcePath, $caseName)
|
||||||
|
ElseIf $selectedAlgName == $allAlgorithmNames[1] Then ;"Folder of Logical Files"
|
||||||
|
ValidateSingleDataSourceFields($dataSourcePath, $caseName)
|
||||||
|
EndIf
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;ensure that the settings for the default algorithm are valid before enabling it
|
||||||
|
Func ValidateDefaultFields($rootFolderPath)
|
||||||
|
if ($rootFolderPath <> "" And FileExists($rootFolderPath)) Then
|
||||||
|
GUICtrlSetState($runButton, $GUI_ENABLE)
|
||||||
|
Else
|
||||||
|
GUICtrlSetState($runButton, $GUI_DISABLE)
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;ensure that the settings for the Single Data Source and Folder of Logical Files algorithms are valid
|
||||||
|
Func ValidateSingleDataSourceFields($dataSourcePath, $caseName)
|
||||||
|
if ($dataSourcePath <> "" And FileExists($dataSourcePath) And $caseName <> "") Then
|
||||||
|
GUICtrlSetState($runButton, $GUI_ENABLE)
|
||||||
|
Else
|
||||||
|
GUICtrlSetState($runButton, $GUI_DISABLE)
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;clear all input fields, and reset them to an empty string
|
||||||
|
Func ClearFields()
|
||||||
|
GUICtrlSetData($rootFolderField, "")
|
||||||
|
GUICtrlSetData($caseNameField, "")
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Open a directory chooser
|
||||||
|
Func Browse()
|
||||||
|
; Note: At this point @GUI_CtrlId would equal $browseButton
|
||||||
|
GUICtrlSetState($browseButton, $GUI_DISABLE)
|
||||||
|
Local $selectedDirectory = FileSelectFolder("Select Folder", $defaultDirectory)
|
||||||
|
Local $caseDir = ""
|
||||||
|
Local $caseDrive = ""
|
||||||
|
If (FileExists($selectedDirectory)) Then
|
||||||
|
_PathSplit($selectedDirectory, $caseDrive, $caseDir, "", "")
|
||||||
|
$defaultDirectory = $caseDrive & $caseDir
|
||||||
|
GUICtrlSetData($rootFolderField, $selectedDirectory)
|
||||||
|
EndIf
|
||||||
|
GUICtrlSetState($caseNameField, $GUI_FOCUS)
|
||||||
|
GUICtrlSetState($browseButton, $GUI_ENABLE)
|
||||||
|
EndFunc ;==>BrowseButton
|
||||||
|
|
||||||
|
; Open a file chooser
|
||||||
|
Func BrowseForDataSourceFile()
|
||||||
|
; Note: At this point @GUI_CtrlId would equal $browseButton
|
||||||
|
GUICtrlSetState($browseButton, $GUI_DISABLE)
|
||||||
|
Local $selectedDataSource = FileOpenDialog("Select Data Source", $defaultDirectory, "All Supported Types (*.img; *.dd; *.001; *.aa; *.raw; *.bin; *.E01; *.vmdk; *.vhd) |Raw Images (*.img; *.dd; *.001; *.aa; *.raw; *.bin) |Encase Images (*.E01) |Virtual Machines (*.vmdk; *.vhd) |Logical Evidence File (*.L01) |All Files (*.*)", $FD_FILEMUSTEXIST)
|
||||||
|
Local $caseDir = ""
|
||||||
|
Local $caseDrive = ""
|
||||||
|
If (FileExists($selectedDataSource)) Then
|
||||||
|
_PathSplit ($selectedDataSource, $caseDrive, $caseDir, "", "")
|
||||||
|
$defaultDirectory = $caseDrive & $caseDir
|
||||||
|
GUICtrlSetData($rootFolderField, $selectedDataSource)
|
||||||
|
EndIf
|
||||||
|
GUICtrlSetState($caseNameField, $GUI_FOCUS)
|
||||||
|
GUICtrlSetState($browseButton, $GUI_ENABLE)
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Perform the action associated with the run button which should be defined in ManifestGenerationAlgorithms.au3
|
||||||
|
Func AlgorithmRunAction()
|
||||||
|
; Note: At this point @GUI_CtrlId would equal $runButton
|
||||||
|
GUICtrlSetState($runButton, $GUI_DISABLE)
|
||||||
|
RunAlgorithm(GUICtrlRead($algorithmComboBox), GetSettings(), $progressField)
|
||||||
|
GUICtrlSetState($runButton, $GUI_ENABLE)
|
||||||
|
EndFunc ;==>RunButton
|
||||||
|
|
||||||
|
;Get an array of settings as they are set on this panel
|
||||||
|
Func GetSettings()
|
||||||
|
Local $settings[2]
|
||||||
|
$settings[0] = GUICtrlRead($rootFolderField)
|
||||||
|
$settings[1] = GUICtrlRead($caseNameField)
|
||||||
|
Return $settings
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
;Close the tool
|
||||||
|
Func CLOSEButton()
|
||||||
|
; Note: at this point @GUI_CtrlId would equal $GUI_EVENT_CLOSE,
|
||||||
|
; @GUI_WinHandle will be either $hMainGUI or $hDummyGUI
|
||||||
|
GUICtrlSetState($exitButton, $GUI_DISABLE)
|
||||||
|
If @GUI_WinHandle = $hMainGUI Then
|
||||||
|
Local $msgBoxAnswer = MsgBox(1, "Close Tool Confirmation", "Press OK to confirm closing the tool")
|
||||||
|
if $msgBoxAnswer == 1 Then
|
||||||
|
WritePropertiesFile()
|
||||||
|
Exit
|
||||||
|
EndIf
|
||||||
|
EndIf
|
||||||
|
GUICtrlSetState($exitButton, $GUI_ENABLE)
|
||||||
|
EndFunc ;==>CLOSEButton
|
BIN
ManifestTool/ManifestTool.exe
Normal file
@ -2,7 +2,6 @@ cannotBuildXmlParser=Unable to build XML parser:
|
|||||||
cannotLoadSEUQA=Unable to load Search Engine URL Query Analyzer settings file, SEUQAMappings.xml:
|
cannotLoadSEUQA=Unable to load Search Engine URL Query Analyzer settings file, SEUQAMappings.xml:
|
||||||
cannotParseXml=Unable to parse XML file:
|
cannotParseXml=Unable to parse XML file:
|
||||||
ChromeCacheExtractor.moduleName=ChromeCacheExtractor
|
ChromeCacheExtractor.moduleName=ChromeCacheExtractor
|
||||||
# {0} - OS name
|
|
||||||
DataSourceUsageAnalyzer.customVolume.label=OS Drive ({0})
|
DataSourceUsageAnalyzer.customVolume.label=OS Drive ({0})
|
||||||
DataSourceUsageAnalyzer.parentModuleName=Recent Activity
|
DataSourceUsageAnalyzer.parentModuleName=Recent Activity
|
||||||
Extract.indexError.message=Failed to index artifact for keyword search.
|
Extract.indexError.message=Failed to index artifact for keyword search.
|
||||||
@ -48,8 +47,16 @@ ExtractSafari_Error_Getting_History=An error occurred while processing Safari hi
|
|||||||
ExtractSafari_Error_Parsing_Bookmark=An error occured while processing Safari Bookmark files
|
ExtractSafari_Error_Parsing_Bookmark=An error occured while processing Safari Bookmark files
|
||||||
ExtractSafari_Error_Parsing_Cookies=An error occured while processing Safari Cookies files
|
ExtractSafari_Error_Parsing_Cookies=An error occured while processing Safari Cookies files
|
||||||
ExtractSafari_Module_Name=Safari
|
ExtractSafari_Module_Name=Safari
|
||||||
|
ExtractZone_Internet=Internet Zone
|
||||||
|
ExtractZone_Local_Intranet=Local Intranet Zone
|
||||||
|
ExtractZone_Local_Machine=Local Machine Zone
|
||||||
|
ExtractZone_process_errMsg=An error occured processing ':Zone.Indentifier' files.
|
||||||
|
ExtractZone_process_errMsg_find=A failure occured while searching for :Zone.Indentifier files.
|
||||||
|
ExtractZone_progress_Msg=Extracting :Zone.Identifer files
|
||||||
|
ExtractZone_Restricted=Restricted Sites Zone
|
||||||
|
ExtractZone_Trusted=Trusted Sites Zone
|
||||||
OpenIDE-Module-Display-Category=Ingest Module
|
OpenIDE-Module-Display-Category=Ingest Module
|
||||||
OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\n\The module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web acitivity (sites visited, stored cookies, bookmarked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\n\The module currently supports Windows only disk images.\n\The plugin is also fully functional when deployed on Windows version of Autopsy.
|
OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\nThe module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web acitivity (sites visited, stored cookies, bookmarked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy.
|
||||||
OpenIDE-Module-Name=RecentActivity
|
OpenIDE-Module-Name=RecentActivity
|
||||||
OpenIDE-Module-Short-Description=Recent Activity finder ingest module
|
OpenIDE-Module-Short-Description=Recent Activity finder ingest module
|
||||||
Chrome.moduleName=Chrome
|
Chrome.moduleName=Chrome
|
||||||
@ -173,12 +180,11 @@ RecentDocumentsByLnk.parentModuleName.noSpace=RecentActivity
|
|||||||
RecentDocumentsByLnk.parentModuleName=Recent Activity
|
RecentDocumentsByLnk.parentModuleName=Recent Activity
|
||||||
RegRipperFullNotFound=Full version RegRipper executable not found.
|
RegRipperFullNotFound=Full version RegRipper executable not found.
|
||||||
RegRipperNotFound=Autopsy RegRipper executable not found.
|
RegRipperNotFound=Autopsy RegRipper executable not found.
|
||||||
# {0} - file name
|
|
||||||
SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}.
|
SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}.
|
||||||
SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine
|
SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine
|
||||||
SearchEngineURLQueryAnalyzer.engineName.none=NONE
|
SearchEngineURLQueryAnalyzer.engineName.none=NONE
|
||||||
SearchEngineURLQueryAnalyzer.domainSubStr.none=NONE
|
SearchEngineURLQueryAnalyzer.domainSubStr.none=NONE
|
||||||
SearchEngineURLQueryAnalyzer.toString=Name: {0}\nDomain Substring: {1}\n\count: {2}\nSplit Tokens: \n{3}
|
SearchEngineURLQueryAnalyzer.toString=Name: {0}\nDomain Substring: {1}\ncount: {2}\nSplit Tokens: \n{3}
|
||||||
SearchEngineURLQueryAnalyzer.parentModuleName.noSpace=RecentActivity
|
SearchEngineURLQueryAnalyzer.parentModuleName.noSpace=RecentActivity
|
||||||
SearchEngineURLQueryAnalyzer.parentModuleName=Recent Activity
|
SearchEngineURLQueryAnalyzer.parentModuleName=Recent Activity
|
||||||
UsbDeviceIdMapper.parseAndLookup.text=Product: {0}
|
UsbDeviceIdMapper.parseAndLookup.text=Product: {0}
|
||||||
|
@ -37,6 +37,7 @@ import java.io.File;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
@ -514,12 +515,13 @@ class Chrome extends Extract {
|
|||||||
tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V30);
|
tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V30);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log(Level.INFO, "{0}- Now getting downloads from {1} with {2}artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS
|
logger.log(Level.INFO, "{0}- Now getting downloads from {1} with {2} artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS
|
||||||
for (HashMap<String, Object> result : tempList) {
|
for (HashMap<String, Object> result : tempList) {
|
||||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
||||||
|
String fullPath = result.get("full_path").toString(); //NON-NLS
|
||||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
|
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
|
||||||
RecentActivityExtracterModuleFactory.getModuleName(), (result.get("full_path").toString()))); //NON-NLS
|
RecentActivityExtracterModuleFactory.getModuleName(), fullPath));
|
||||||
long pathID = Util.findID(dataSource, (result.get("full_path").toString())); //NON-NLS
|
long pathID = Util.findID(dataSource, fullPath);
|
||||||
if (pathID != -1) {
|
if (pathID != -1) {
|
||||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
|
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
|
||||||
NbBundle.getMessage(this.getClass(),
|
NbBundle.getMessage(this.getClass(),
|
||||||
@ -546,6 +548,19 @@ class Chrome extends Extract {
|
|||||||
if (bbart != null) {
|
if (bbart != null) {
|
||||||
bbartifacts.add(bbart);
|
bbartifacts.add(bbart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find the downloaded file and create a TSK_DOWNLOAD_SOURCE for it..
|
||||||
|
try {
|
||||||
|
for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(fullPath), FilenameUtils.getPath(fullPath))) {
|
||||||
|
BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
|
||||||
|
downloadSourceArt.addAttributes(createDownloadSourceAttributes(result.get("url").toString()));
|
||||||
|
|
||||||
|
bbartifacts.add(downloadSourceArt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.SEVERE, String.format("Error creating download source artifact for file '%s'", fullPath), ex); //NON-NLS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dbFile.delete();
|
dbFile.delete();
|
||||||
|
@ -379,7 +379,7 @@ abstract class Extract {
|
|||||||
* @param accessTime Time the download occurred
|
* @param accessTime Time the download occurred
|
||||||
* @param domain Domain of the URL
|
* @param domain Domain of the URL
|
||||||
* @param programName Name of the module creating the attribute
|
* @param programName Name of the module creating the attribute
|
||||||
* @return A collection of attributed of a downloaded file
|
* @return A collection of attributes of a downloaded file
|
||||||
*/
|
*/
|
||||||
protected Collection<BlackboardAttribute> createDownloadAttributes(String path, Long pathID, String url, Long accessTime, String domain, String programName) {
|
protected Collection<BlackboardAttribute> createDownloadAttributes(String path, Long pathID, String url, Long accessTime, String domain, String programName) {
|
||||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
||||||
@ -414,6 +414,22 @@ abstract class Extract {
|
|||||||
return bbattributes;
|
return bbattributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a list of the attributes for source of a downloaded file
|
||||||
|
*
|
||||||
|
* @param url source URL of the downloaded file
|
||||||
|
* @return A collection of attributes for source of a downloaded file
|
||||||
|
*/
|
||||||
|
protected Collection<BlackboardAttribute> createDownloadSourceAttributes(String url) {
|
||||||
|
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
||||||
|
|
||||||
|
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL,
|
||||||
|
RecentActivityExtracterModuleFactory.getModuleName(),
|
||||||
|
(url != null) ? url : "")); //NON-NLS
|
||||||
|
|
||||||
|
return bbattributes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create temporary file for the given AbstractFile. The new file will be
|
* Create temporary file for the given AbstractFile. The new file will be
|
||||||
* created in the temp directory for the module with a unique file name.
|
* created in the temp directory for the module with a unique file name.
|
||||||
|
@ -36,6 +36,7 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
@ -48,6 +49,7 @@ import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
|||||||
import org.sleuthkit.autopsy.recentactivity.BinaryCookieReader.Cookie;
|
import org.sleuthkit.autopsy.recentactivity.BinaryCookieReader.Cookie;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
@ -503,7 +505,7 @@ final class ExtractSafari extends Extract {
|
|||||||
|
|
||||||
for(NSObject obj: objectArray){
|
for(NSObject obj: objectArray){
|
||||||
if(obj instanceof NSDictionary){
|
if(obj instanceof NSDictionary){
|
||||||
bbartifacts.add(parseDownloadDictionary(dataSource, origFile, (NSDictionary)obj));
|
bbartifacts.addAll(parseDownloadDictionary(dataSource, origFile, (NSDictionary)obj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -612,12 +614,15 @@ final class ExtractSafari extends Extract {
|
|||||||
* @return a Blackboard Artifact for the download.
|
* @return a Blackboard Artifact for the download.
|
||||||
* @throws TskCoreException
|
* @throws TskCoreException
|
||||||
*/
|
*/
|
||||||
private BlackboardArtifact parseDownloadDictionary(Content dataSource, AbstractFile origFile, NSDictionary entry) throws TskCoreException {
|
private Collection<BlackboardArtifact> parseDownloadDictionary(Content dataSource, AbstractFile origFile, NSDictionary entry) throws TskCoreException {
|
||||||
|
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||||
String url = null;
|
String url = null;
|
||||||
String path = null;
|
String path = null;
|
||||||
Long time = null;
|
Long time = null;
|
||||||
Long pathID = null;
|
Long pathID = null;
|
||||||
|
|
||||||
|
FileManager fileManager = getCurrentCase().getServices().getFileManager();
|
||||||
|
|
||||||
NSString nsstring = (NSString) entry.get(PLIST_KEY_DOWNLOAD_URL);
|
NSString nsstring = (NSString) entry.get(PLIST_KEY_DOWNLOAD_URL);
|
||||||
if (nsstring != null) {
|
if (nsstring != null) {
|
||||||
url = nsstring.toString();
|
url = nsstring.toString();
|
||||||
@ -636,7 +641,16 @@ final class ExtractSafari extends Extract {
|
|||||||
|
|
||||||
BlackboardArtifact bbart = origFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD);
|
BlackboardArtifact bbart = origFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD);
|
||||||
bbart.addAttributes(this.createDownloadAttributes(path, pathID, url, time, NetworkUtils.extractDomain(url), getName()));
|
bbart.addAttributes(this.createDownloadAttributes(path, pathID, url, time, NetworkUtils.extractDomain(url), getName()));
|
||||||
|
bbartifacts.add(bbart);
|
||||||
|
|
||||||
return bbart;
|
// find the downloaded file and create a TSK_DOWNLOAD_SOURCE for it.
|
||||||
|
for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(path), FilenameUtils.getPath(path))) {
|
||||||
|
BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
|
||||||
|
downloadSourceArt.addAttributes(createDownloadSourceAttributes(url));
|
||||||
|
bbartifacts.add(downloadSourceArt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bbartifacts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,388 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.recentactivity;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||||
|
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
|
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE;
|
||||||
|
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
|
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN;
|
||||||
|
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION;
|
||||||
|
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID;
|
||||||
|
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL;
|
||||||
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the <i>:Zone.Indentifier<i> alternate data stream files. A file with
|
||||||
|
* a <i>:Zone.Indentifier<i> extention contains information about the similarly
|
||||||
|
* named (with out zone identifer extension) downloaded file.
|
||||||
|
*/
|
||||||
|
final class ExtractZoneIdentifier extends Extract {
|
||||||
|
|
||||||
|
private static final Logger LOG = Logger.getLogger(ExtractEdge.class.getName());
|
||||||
|
|
||||||
|
private static final String ZONE_IDENTIFIER_FILE = "%:Zone.Identifier"; //NON-NLS
|
||||||
|
private static final String ZONE_IDENTIFIER = ":Zone.Identifier"; //NON-NLS
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"ExtractZone_process_errMsg_find=A failure occured while searching for :Zone.Indentifier files.",
|
||||||
|
"ExtractZone_process_errMsg=An error occured processing ':Zone.Indentifier' files.",
|
||||||
|
"ExtractZone_progress_Msg=Extracting :Zone.Identifer files"
|
||||||
|
})
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
|
||||||
|
|
||||||
|
progressBar.progress(Bundle.ExtractZone_progress_Msg());
|
||||||
|
|
||||||
|
List<AbstractFile> zoneFiles = null;
|
||||||
|
try {
|
||||||
|
zoneFiles = currentCase.getServices().getFileManager().findFiles(dataSource, ZONE_IDENTIFIER_FILE);
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
addErrorMessage(Bundle.ExtractZone_process_errMsg_find());
|
||||||
|
LOG.log(Level.SEVERE, "Unable to find zone identifier files, exception thrown. ", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zoneFiles == null || zoneFiles.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Long> knownPathIDs = null;
|
||||||
|
try {
|
||||||
|
knownPathIDs = getPathIDsForType(TSK_WEB_DOWNLOAD);
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
addErrorMessage(Bundle.ExtractZone_process_errMsg());
|
||||||
|
LOG.log(Level.SEVERE, "Failed to build PathIDs List for TSK_WEB_DOWNLOAD", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
if (knownPathIDs == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<BlackboardArtifact> sourceArtifacts = new ArrayList<>();
|
||||||
|
Collection<BlackboardArtifact> downloadArtifacts = new ArrayList<>();
|
||||||
|
|
||||||
|
for (AbstractFile zoneFile : zoneFiles) {
|
||||||
|
try {
|
||||||
|
processZoneFile(context, dataSource, zoneFile, sourceArtifacts, downloadArtifacts, knownPathIDs);
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
addErrorMessage(Bundle.ExtractZone_process_errMsg());
|
||||||
|
String message = String.format("Failed to process zone identifier file %s", zoneFile.getName()); //NON-NLS
|
||||||
|
LOG.log(Level.WARNING, message, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IngestServices services = IngestServices.getInstance();
|
||||||
|
|
||||||
|
if (!sourceArtifacts.isEmpty()) {
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent(
|
||||||
|
RecentActivityExtracterModuleFactory.getModuleName(),
|
||||||
|
TSK_DOWNLOAD_SOURCE, sourceArtifacts));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!downloadArtifacts.isEmpty()) {
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent(
|
||||||
|
RecentActivityExtracterModuleFactory.getModuleName(),
|
||||||
|
TSK_WEB_DOWNLOAD, downloadArtifacts));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a single Zone Identifier file.
|
||||||
|
*
|
||||||
|
* @param context IngetJobContext
|
||||||
|
* @param dataSource Content
|
||||||
|
* @param zoneFile Zone Indentifier file
|
||||||
|
* @param sourceArtifacts List for TSK_DOWNLOAD_SOURCE artifacts
|
||||||
|
* @param downloadArtifacts List for TSK_WEB_DOWNLOAD aritfacts
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
private void processZoneFile(IngestJobContext context, Content dataSource,
|
||||||
|
AbstractFile zoneFile, Collection<BlackboardArtifact> sourceArtifacts,
|
||||||
|
Collection<BlackboardArtifact> downloadArtifacts,
|
||||||
|
Set<Long> knownPathIDs) throws TskCoreException {
|
||||||
|
|
||||||
|
ZoneIdentifierInfo zoneInfo = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
zoneInfo = new ZoneIdentifierInfo(zoneFile);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
String message = String.format("Unable to parse temporary File for %s", zoneFile.getName()); //NON-NLS
|
||||||
|
LOG.log(Level.WARNING, message, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zoneInfo == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractFile downloadFile = getDownloadFile(dataSource, zoneFile);
|
||||||
|
|
||||||
|
if (downloadFile != null) {
|
||||||
|
// Only create a new TSK_WEB_DOWNLOAD artifact if one does not exist for downloadFile
|
||||||
|
if (!knownPathIDs.contains(downloadFile.getDataSourceObjectId())) {
|
||||||
|
// The zone identifier file is the parent of this artifact
|
||||||
|
// because it is the file we parsed to get the data
|
||||||
|
BlackboardArtifact downloadBba = createDownloadArtifact(zoneFile, zoneInfo);
|
||||||
|
if (downloadBba != null) {
|
||||||
|
downloadArtifacts.add(downloadBba);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if download has a child TSK_DOWNLOAD_SOURCE artifact, if not create one
|
||||||
|
if (downloadFile.getArtifactsCount(TSK_DOWNLOAD_SOURCE) == 0) {
|
||||||
|
BlackboardArtifact sourceBba = createDownloadSourceArtifact(downloadFile, zoneInfo);
|
||||||
|
if (sourceBba != null) {
|
||||||
|
sourceArtifacts.add(sourceBba);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the file that the Zone.Identifer file was created alongside.
|
||||||
|
*
|
||||||
|
* @param dataSource Content
|
||||||
|
* @param zoneFile The zone identifier case file
|
||||||
|
*
|
||||||
|
* @return The downloaded file or null if a file was not found
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
private AbstractFile getDownloadFile(Content dataSource, AbstractFile zoneFile) throws TskCoreException {
|
||||||
|
AbstractFile downloadFile = null;
|
||||||
|
|
||||||
|
org.sleuthkit.autopsy.casemodule.services.FileManager fileManager
|
||||||
|
= currentCase.getServices().getFileManager();
|
||||||
|
|
||||||
|
String downloadFileName = zoneFile.getName().replace(ZONE_IDENTIFIER, ""); //NON-NLS
|
||||||
|
|
||||||
|
List<AbstractFile> fileList = fileManager.findFiles(dataSource, downloadFileName, zoneFile.getParentPath());
|
||||||
|
|
||||||
|
if (fileList.size() == 1) {
|
||||||
|
downloadFile = fileList.get(0);
|
||||||
|
|
||||||
|
// Check that the download file and the zone file came from the same dir
|
||||||
|
if (!downloadFile.getParentPath().equals(zoneFile.getParentPath())) {
|
||||||
|
downloadFile = null;
|
||||||
|
} else if (zoneFile.getMetaAddr() != downloadFile.getMetaAddr()) {
|
||||||
|
downloadFile = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return downloadFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Download Source Artifact for the given ZoneIdentifierInfo
|
||||||
|
* object.
|
||||||
|
*
|
||||||
|
* @param downloadFile AbstractFile representing the file downloaded, not
|
||||||
|
* the zone indentifier file.
|
||||||
|
* @param zoneInfo Zone Indentifer file wrapper object
|
||||||
|
*
|
||||||
|
* @return TSK_DOWNLOAD_SOURCE object for given parameters
|
||||||
|
*/
|
||||||
|
private BlackboardArtifact createDownloadSourceArtifact(AbstractFile downloadFile, ZoneIdentifierInfo zoneInfo) {
|
||||||
|
|
||||||
|
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
||||||
|
|
||||||
|
bbattributes.addAll(Arrays.asList(
|
||||||
|
new BlackboardAttribute(TSK_URL,
|
||||||
|
RecentActivityExtracterModuleFactory.getModuleName(),
|
||||||
|
StringUtils.defaultString(zoneInfo.getURL(), "")),
|
||||||
|
|
||||||
|
new BlackboardAttribute(TSK_DOMAIN,
|
||||||
|
RecentActivityExtracterModuleFactory.getModuleName(),
|
||||||
|
(zoneInfo.getURL() != null) ? NetworkUtils.extractDomain(zoneInfo.getURL()) : ""),
|
||||||
|
|
||||||
|
new BlackboardAttribute(TSK_LOCATION,
|
||||||
|
RecentActivityExtracterModuleFactory.getModuleName(),
|
||||||
|
StringUtils.defaultString(zoneInfo.getZoneIdAsString(), "")))); //NON-NLS
|
||||||
|
|
||||||
|
return addArtifact(TSK_DOWNLOAD_SOURCE, downloadFile, bbattributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TSK_WEB_DOWNLOAD Artifact for the given zone indentifier file.
|
||||||
|
*
|
||||||
|
* @param zoneFile Zone identifier file
|
||||||
|
* @param zoneInfo ZoneIdentifierInfo file wrapper object
|
||||||
|
*
|
||||||
|
* @return BlackboardArifact for the given parameters
|
||||||
|
*/
|
||||||
|
private BlackboardArtifact createDownloadArtifact(AbstractFile zoneFile, ZoneIdentifierInfo zoneInfo) {
|
||||||
|
|
||||||
|
Collection<BlackboardAttribute> bbattributes = createDownloadAttributes(
|
||||||
|
null, null,
|
||||||
|
zoneInfo.getURL(), null,
|
||||||
|
(zoneInfo.getURL() != null ? NetworkUtils.extractDomain(zoneInfo.getURL()) : ""),
|
||||||
|
null);
|
||||||
|
return addArtifact(TSK_WEB_DOWNLOAD, zoneFile, bbattributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a list of PathIDs for the given Artifact type.
|
||||||
|
*
|
||||||
|
* @param type BlackboardArtifact.ARTIFACT_TYPE
|
||||||
|
*
|
||||||
|
* @return A list of PathIDs
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
private Set<Long> getPathIDsForType(BlackboardArtifact.ARTIFACT_TYPE type) throws TskCoreException {
|
||||||
|
Set<Long> idList = new HashSet<>();
|
||||||
|
for (BlackboardArtifact artifact : currentCase.getSleuthkitCase().getBlackboardArtifacts(type)) {
|
||||||
|
BlackboardAttribute pathIDAttribute = artifact.getAttribute(new BlackboardAttribute.Type(TSK_PATH_ID));
|
||||||
|
|
||||||
|
if (pathIDAttribute != null) {
|
||||||
|
long contentID = pathIDAttribute.getValueLong();
|
||||||
|
if (contentID != -1) {
|
||||||
|
idList.add(contentID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return idList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"ExtractZone_Local_Machine=Local Machine Zone",
|
||||||
|
"ExtractZone_Local_Intranet=Local Intranet Zone",
|
||||||
|
"ExtractZone_Trusted=Trusted Sites Zone",
|
||||||
|
"ExtractZone_Internet=Internet Zone",
|
||||||
|
"ExtractZone_Restricted=Restricted Sites Zone"
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class for information in the :ZoneIdentifier file. The
|
||||||
|
* Zone.Identifier file has a simple format of <i>key<i>=<i>value<i>. There
|
||||||
|
* are four known keys: ZoneId, ReferrerUrl, HostUrl, and
|
||||||
|
* LastWriterPackageFamilyName. Not all browsers will put all values in the
|
||||||
|
* file, in fact most will only supply the ZoneId. Only Edge supplies the
|
||||||
|
* LastWriterPackageFamilyName.
|
||||||
|
*/
|
||||||
|
private final static class ZoneIdentifierInfo {
|
||||||
|
|
||||||
|
private static final String ZONE_ID = "ZoneId"; //NON-NLS
|
||||||
|
private static final String REFERRER_URL = "ReferrerUrl"; //NON-NLS
|
||||||
|
private static final String HOST_URL = "HostUrl"; //NON-NLS
|
||||||
|
private static final String FAMILY_NAME = "LastWriterPackageFamilyName"; //NON-NLS
|
||||||
|
|
||||||
|
private final Properties properties = new Properties(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the zone file, reading for the key\value pairs and puts them
|
||||||
|
* into a HashMap.
|
||||||
|
*
|
||||||
|
* @param zoneFile The ZoneIdentifier file
|
||||||
|
*
|
||||||
|
* @throws FileNotFoundException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
ZoneIdentifierInfo(AbstractFile zoneFile) throws IOException {
|
||||||
|
properties.load(new ReadContentInputStream(zoneFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the integer zone id
|
||||||
|
*
|
||||||
|
* @return interger zone id or -1 if unknown
|
||||||
|
*/
|
||||||
|
private int getZoneId() {
|
||||||
|
int zoneValue = -1;
|
||||||
|
String value = properties.getProperty(ZONE_ID);
|
||||||
|
if (value != null) {
|
||||||
|
zoneValue = Integer.parseInt(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return zoneValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the string description of the zone id.
|
||||||
|
*
|
||||||
|
* @return String description or null if a zone id was not found
|
||||||
|
*/
|
||||||
|
private String getZoneIdAsString() {
|
||||||
|
switch (getZoneId()) {
|
||||||
|
case 0:
|
||||||
|
return Bundle.ExtractZone_Local_Machine();
|
||||||
|
case 1:
|
||||||
|
return Bundle.ExtractZone_Local_Intranet();
|
||||||
|
case 2:
|
||||||
|
return Bundle.ExtractZone_Trusted();
|
||||||
|
case 3:
|
||||||
|
return Bundle.ExtractZone_Internet();
|
||||||
|
case 4:
|
||||||
|
return Bundle.ExtractZone_Restricted();
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the URL from which the file was downloaded.
|
||||||
|
*
|
||||||
|
* @return String url or null if a host url was not found
|
||||||
|
*/
|
||||||
|
private String getURL() {
|
||||||
|
return properties.getProperty(HOST_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the referrer url.
|
||||||
|
*
|
||||||
|
* @return String url or null if a host url was not found
|
||||||
|
*/
|
||||||
|
private String getReferrer() {
|
||||||
|
return properties.getProperty(REFERRER_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the string value for the key LastWriterPackageFamilyName.
|
||||||
|
*
|
||||||
|
* @return String value or null if the value was not found
|
||||||
|
*/
|
||||||
|
private String getFamilyName() {
|
||||||
|
return properties.getProperty(FAMILY_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -42,6 +42,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
@ -499,14 +500,14 @@ class Firefox extends Extract {
|
|||||||
(Long.valueOf(result.get("startTime").toString())))); //NON-NLS
|
(Long.valueOf(result.get("startTime").toString())))); //NON-NLS
|
||||||
|
|
||||||
String target = result.get("target").toString(); //NON-NLS
|
String target = result.get("target").toString(); //NON-NLS
|
||||||
|
String downloadedFilePath = "";
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
try {
|
try {
|
||||||
String decodedTarget = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
|
downloadedFilePath = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
|
||||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
|
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
|
||||||
RecentActivityExtracterModuleFactory.getModuleName(),
|
RecentActivityExtracterModuleFactory.getModuleName(),
|
||||||
decodedTarget));
|
downloadedFilePath));
|
||||||
long pathID = Util.findID(dataSource, decodedTarget);
|
long pathID = Util.findID(dataSource, downloadedFilePath);
|
||||||
if (pathID != -1) {
|
if (pathID != -1) {
|
||||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
|
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
|
||||||
RecentActivityExtracterModuleFactory.getModuleName(),
|
RecentActivityExtracterModuleFactory.getModuleName(),
|
||||||
@ -532,6 +533,19 @@ class Firefox extends Extract {
|
|||||||
if (bbart != null) {
|
if (bbart != null) {
|
||||||
bbartifacts.add(bbart);
|
bbartifacts.add(bbart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find the downloaded file and create a TSK_DOWNLOAD_SOURCE for it.
|
||||||
|
try {
|
||||||
|
for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
|
||||||
|
BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
|
||||||
|
downloadSourceArt.addAttributes(createDownloadSourceAttributes(source));
|
||||||
|
bbartifacts.add(downloadSourceArt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.SEVERE, String.format("Error creating download source artifact for file '%s'",
|
||||||
|
downloadedFilePath), ex); //NON-NLS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (errors > 0) {
|
if (errors > 0) {
|
||||||
this.addErrorMessage(
|
this.addErrorMessage(
|
||||||
@ -619,13 +633,14 @@ class Firefox extends Extract {
|
|||||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("startTime").toString()))));
|
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("startTime").toString()))));
|
||||||
|
|
||||||
String target = result.get("target").toString(); //NON-NLS
|
String target = result.get("target").toString(); //NON-NLS
|
||||||
|
String downloadedFilePath = "";
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
try {
|
try {
|
||||||
String decodedTarget = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
|
downloadedFilePath = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
|
||||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
|
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
|
||||||
RecentActivityExtracterModuleFactory.getModuleName(),
|
RecentActivityExtracterModuleFactory.getModuleName(),
|
||||||
decodedTarget));
|
downloadedFilePath));
|
||||||
long pathID = Util.findID(dataSource, decodedTarget);
|
long pathID = Util.findID(dataSource, downloadedFilePath);
|
||||||
if (pathID != -1) {
|
if (pathID != -1) {
|
||||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
|
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
|
||||||
RecentActivityExtracterModuleFactory.getModuleName(),
|
RecentActivityExtracterModuleFactory.getModuleName(),
|
||||||
@ -652,6 +667,19 @@ class Firefox extends Extract {
|
|||||||
if (bbart != null) {
|
if (bbart != null) {
|
||||||
bbartifacts.add(bbart);
|
bbartifacts.add(bbart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find the downloaded file and create a TSK_DOWNLOAD_SOURCE for it.
|
||||||
|
try {
|
||||||
|
for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
|
||||||
|
BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
|
||||||
|
downloadSourceArt.addAttributes(createDownloadSourceAttributes(url));
|
||||||
|
bbartifacts.add(downloadSourceArt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.SEVERE, String.format("Error creating download source artifact for file '%s'",
|
||||||
|
downloadedFilePath), ex); //NON-NLS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (errors > 0) {
|
if (errors > 0) {
|
||||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts",
|
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts",
|
||||||
|
@ -76,6 +76,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
|
|||||||
Extract osExtract = new ExtractOs();
|
Extract osExtract = new ExtractOs();
|
||||||
Extract dataSourceAnalyzer = new DataSourceUsageAnalyzer();
|
Extract dataSourceAnalyzer = new DataSourceUsageAnalyzer();
|
||||||
Extract safari = new ExtractSafari();
|
Extract safari = new ExtractSafari();
|
||||||
|
Extract zoneInfo = new ExtractZoneIdentifier();
|
||||||
|
|
||||||
extractors.add(chrome);
|
extractors.add(chrome);
|
||||||
extractors.add(firefox);
|
extractors.add(firefox);
|
||||||
@ -87,6 +88,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
|
|||||||
extractors.add(registry); // this should run after quicker modules like the browser modules and needs to run before the DataSourceUsageAnalyzer
|
extractors.add(registry); // this should run after quicker modules like the browser modules and needs to run before the DataSourceUsageAnalyzer
|
||||||
extractors.add(osExtract); // this needs to run before the DataSourceUsageAnalyzer
|
extractors.add(osExtract); // this needs to run before the DataSourceUsageAnalyzer
|
||||||
extractors.add(dataSourceAnalyzer); //this needs to run after ExtractRegistry and ExtractOs
|
extractors.add(dataSourceAnalyzer); //this needs to run after ExtractRegistry and ExtractOs
|
||||||
|
extractors.add(zoneInfo); // this needs to run after the web browser modules
|
||||||
|
|
||||||
browserExtractors.add(chrome);
|
browserExtractors.add(chrome);
|
||||||
browserExtractors.add(firefox);
|
browserExtractors.add(firefox);
|
||||||
|
@ -102,6 +102,7 @@
|
|||||||
<copy file="${basedir}/NEWS.txt" tofile="${zip-tmp}/${app.name}/NEWS.txt"/>
|
<copy file="${basedir}/NEWS.txt" tofile="${zip-tmp}/${app.name}/NEWS.txt"/>
|
||||||
<copy file="${basedir}/Running_Linux_OSX.txt" tofile="${zip-tmp}/${app.name}/Running_Linux_OSX.txt"/>
|
<copy file="${basedir}/Running_Linux_OSX.txt" tofile="${zip-tmp}/${app.name}/Running_Linux_OSX.txt"/>
|
||||||
<copy file="${basedir}/unix_setup.sh" tofile="${zip-tmp}/${app.name}/unix_setup.sh"/>
|
<copy file="${basedir}/unix_setup.sh" tofile="${zip-tmp}/${app.name}/unix_setup.sh"/>
|
||||||
|
<copy file="${basedir}/ManifestTool/ManifestTool.exe" todir="${zip-tmp}/${app.name}/bin"/>
|
||||||
|
|
||||||
|
|
||||||
<copy file="${basedir}/icons/icon.ico" tofile="${zip-tmp}/${app.name}/icon.ico" overwrite="true"/>
|
<copy file="${basedir}/icons/icon.ico" tofile="${zip-tmp}/${app.name}/icon.ico" overwrite="true"/>
|
||||||
|
After Width: | Height: | Size: 20 KiB |
BIN
docs/doxygen-user/images/AutoIngest/manifest_tool_ui.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
docs/doxygen-user/images/portable_case_empty_image.png
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
docs/doxygen-user/images/portable_case_folder.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
docs/doxygen-user/images/portable_case_original_version.png
Normal file
After Width: | Height: | Size: 291 KiB |
BIN
docs/doxygen-user/images/portable_case_portable_version.png
Normal file
After Width: | Height: | Size: 274 KiB |
BIN
docs/doxygen-user/images/portable_case_report_panel.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
docs/doxygen-user/images/portable_case_tags.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 23 KiB |
62
docs/doxygen-user/manifest_tool.dox
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*! \page manifest_tool_page Manifest Tool
|
||||||
|
|
||||||
|
\section manifest_tool_overview Overview
|
||||||
|
|
||||||
|
Manifest Tool is an executable designed to assist in the automated creation of manifest files which are necessary to run Auto Ingest on a data source. There is no installation necessary. To use the tool double click on Manifest Tool executable, when it opens select the option with the algorithm you wish to run from the combo box, and fill in all the available settings before clicking the Run button. A log with the success or failure of each manifest file it attempts to create will appear in the progress area.
|
||||||
|
|
||||||
|
\section manifest_tool_output Output
|
||||||
|
|
||||||
|
The output of the Manifest Tool will be XML files ending in _Manifest.xml.
|
||||||
|
|
||||||
|
\subsection manifest_tool_one_ds_per_folder One Data Source Per Folder
|
||||||
|
|
||||||
|
The One Data Source Per Folder algorithm is designed for a specific use case when the case folder contains multiple subfolders, with each generally containing one data data source of a short list of types. Please see \ref manifest_tool_algorithm_specifics for details on this algorithm.
|
||||||
|
|
||||||
|
To use this algorithm, use the Browse button to select a root folder as the case directory. Then select the Run button to generate manifest files for each of the data sources detected. A manifest file will be generated for each subfolder of the selected root folder, the manifest files will be placed inside the selected root folder.
|
||||||
|
|
||||||
|
\subsection manifest_tool_single_ds Single Data Source
|
||||||
|
|
||||||
|
The Single Data Source algorithm is for creating a manifest file for a single image or logical file with a user specified case name.
|
||||||
|
|
||||||
|
To use this algorithm, use the Browse button to select a file to use as your data source, and enter a case name in the case name field. Then select the Run button to generate a manifest file. The manifest file will be created in the same folder as your selected data source.
|
||||||
|
|
||||||
|
\subsection manifest_tool_logical_file_folder Folder of Logical Files
|
||||||
|
|
||||||
|
The Folder of Logical Files algorithm is for creating a single manifest file for an entire folder of files which will all be ingested as logical files.
|
||||||
|
|
||||||
|
To use this algorithm, use the Browse button to select a folder to add as a folder of logical files, and enter a case name in the case name field. Then select the Run button to generate a manifest file. The manifest file will be created in the parent folder of your selected folder of logical files.
|
||||||
|
|
||||||
|
\section manifest_tol_example Example
|
||||||
|
|
||||||
|
Given a root folder that looks like this:
|
||||||
|
|
||||||
|
\image html AutoIngest/manifest_tool_root_folder.png
|
||||||
|
|
||||||
|
A user having selected the One Data Source Per Folder algorithm will get output that looks like the following, where a manifest now exists for each non-empty subfolder. The root folder's name will be used as the case name in the manifest files (in this example the case name will be TestCaseFolder.)
|
||||||
|
|
||||||
|
\image html AutoIngest/manifest_tool_ui.png
|
||||||
|
|
||||||
|
The contents of an XML file will have the following format:
|
||||||
|
|
||||||
|
\verbatim
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<AutopsyManifest>
|
||||||
|
<CaseName>TestCaseFolder</CaseName>
|
||||||
|
<DataSource>interestingL01\interesting_files2.L01</DataSource>
|
||||||
|
</AutopsyManifest>
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
\section manifest_tool_algorithm_specifics One Data Source Per Folder Algorithm Specifics
|
||||||
|
<ul>
|
||||||
|
<li>The only configuration setting the user needs to choose is a root folder.
|
||||||
|
<li>The name of the specified root folder will become the case name used in the manifest files.
|
||||||
|
<li>Each non-empty subfolder in the root folder will have a manifest file created for it.
|
||||||
|
<li>All manifest files will be created in the root folder.
|
||||||
|
<li>Files directly in the root folder will be ignored and remain unprocessed.
|
||||||
|
<li>Subfolders which contain an .E01, .L01, .001, or .AD1 file, will have the first file of this type used as the data source in the manifest file.
|
||||||
|
<li>Subfolders which have more than one .E01, .L01, .001, or .AD1 file will have the additional files ignored and they will remain unprocessed.
|
||||||
|
<li>Subfolders without an .E01, .L01, .001, or .AD1 file will have the entire subfolder added as the data source.
|
||||||
|
<li>If the root folder already contains a specific _Manifest.xml file then it will not be replaced or modified.
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
*/
|
48
docs/doxygen-user/portable_case.dox
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*! \page portable_case_page Portable Cases
|
||||||
|
|
||||||
|
\section portable_case_overview Overview
|
||||||
|
|
||||||
|
A portable case is a partial copy of a normal Autopsy case that can be opened from anywhere. The general use case is as follows:
|
||||||
|
<ol>
|
||||||
|
<li>Alice is analyzing one or more data sources using Autopsy. She tags files and results that are of particular interest.
|
||||||
|
<li>Alice wants to share her findings with Bob but is unable to send him the original data sources.
|
||||||
|
<li>Alice creates a portable case which will contain only her tagged files and results, plus any files associated with those results, and sends it to Bob.
|
||||||
|
<li>Bob can open the portable case in Autopsy and view all files and results Alice tagged, and run any of the normal Autopsy features.
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
For example, Alice's original case could look like this:
|
||||||
|
|
||||||
|
\image html portable_case_original_version.png
|
||||||
|
|
||||||
|
The portable version could like this:
|
||||||
|
|
||||||
|
\image html portable_case_portable_version.png
|
||||||
|
|
||||||
|
Alice only tagged eight files and results, so most of the original content is no longer in the case. Some of the data sources had no tagged items so they're not included at all. The file structure of any tagged files is preserved - you can see that the tagged image in the screenshot is still in the same location, but the non-tagged files are gone. Note that although the original images (such as "image1.vhd") appear in the tree, their contents are not included in the portable case.
|
||||||
|
|
||||||
|
\section portable_case_creation Creating a Portable Case
|
||||||
|
|
||||||
|
First you'll want to make sure that all the files and results you want included in the portable case are tagged - see the \ref tagging_page page for more details.
|
||||||
|
You can see what tags you've added in the \ref tree_viewer_page.
|
||||||
|
|
||||||
|
\image html portable_case_tags.png
|
||||||
|
|
||||||
|
Portable cases are created through the \ref reporting_page feature. The Generate Report dialog will display a list of all tags that are in use in the current case and you can choose which ones you would like to include. At the bottom you can select the output folder for the new case. By default it will be placed in the "Reports" folder in the current case.
|
||||||
|
|
||||||
|
\image html portable_case_report_panel.png
|
||||||
|
|
||||||
|
Here you can see the new portable case. It will be named with the original case name plus "(Portable)". The portable case is initially missing many of the normal Autopsy folders - these will be created the first time a user opens it. The portable case folder can be zipped and sent to a different user.
|
||||||
|
|
||||||
|
\image html portable_case_folder.png
|
||||||
|
|
||||||
|
\section portable_case_usage Using a Portable Case
|
||||||
|
|
||||||
|
Portable cases generally behave like any other Autopsy case. You can run ingest, do keyword searches, use the timeline viewer, etc. One point to note is that while the original data source names appear in the case, the data sources themselves were not copied into the portable case.
|
||||||
|
|
||||||
|
\image html portable_case_empty_image.png
|
||||||
|
|
||||||
|
This may cause warning or error messages when using ingest modules that run on the full image, such as the \ref data_source_integrity_page. You will also not be able to view the data sources in the content viewer.
|
||||||
|
|
||||||
|
You can also add additonal data sources to the portable case if you wish. The case will no longer be portable, but if desired you could generate a new portable case that will include tagged files and results from the new data sources as well as the original case.
|
||||||
|
|
||||||
|
*/
|
@ -82,6 +82,10 @@ This report module generates a KML file from any GPS data in the case. This file
|
|||||||
|
|
||||||
\image html reports_kml.png
|
\image html reports_kml.png
|
||||||
|
|
||||||
|
\subsection report_portable_case Portable Case
|
||||||
|
|
||||||
|
This report module generates a new Autopsy case from any tagged files and results. See the \ref portable_case_page page for additional information.
|
||||||
|
|
||||||
\subsection report_stix STIX
|
\subsection report_stix STIX
|
||||||
|
|
||||||
The STIX module allows you to generate a report and Interesting File artifacts by running a STIX file (or files) against the data sources in the case.
|
The STIX module allows you to generate a report and Interesting File artifacts by running a STIX file (or files) against the data sources in the case.
|
||||||
|