mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Conflicts: (due to line ending problems) Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java build-windows.xml build.xml
This commit is contained in:
commit
65bb4a05ed
@ -1,4 +1,5 @@
|
|||||||
Changes to make to API when we are ready to make backward incompatible changes:
|
Changes to make to API when we are ready to make backward incompatible changes:
|
||||||
|
|
||||||
- HTMLReport has special API for more context on columns and special handling in REportGenerator. Change all reports to the new API.
|
- HTMLReport has special API for more context on columns and special handling in REportGenerator. Change all reports to the new API.
|
||||||
- DataaContentViewer.isPreferred does not need isSupported to be passed in
|
- DataContentViewer.isPreferred does not need isSupported to be passed in
|
||||||
|
- DataContentViewerHex and STrings can have the public setDataView methods removed in favor of the new private ones
|
@ -109,7 +109,7 @@ public final class AddImageAction extends CallableSystemAction implements Presen
|
|||||||
Logger.noteAction(AddImageAction.class);
|
Logger.noteAction(AddImageAction.class);
|
||||||
|
|
||||||
final IngestConfigurator ingestConfig = Lookup.getDefault().lookup(IngestConfigurator.class);
|
final IngestConfigurator ingestConfig = Lookup.getDefault().lookup(IngestConfigurator.class);
|
||||||
if (ingestConfig.isIngestRunning()) {
|
if (null != ingestConfig && ingestConfig.isIngestRunning()) {
|
||||||
final String msg = "<html>Ingest is ongoing on another data source. Adding a new source now might slow down the current ingest.<br />Do you want to proceed and add a new data source now?</html>";
|
final String msg = "<html>Ingest is ongoing on another data source. Adding a new source now might slow down the current ingest.<br />Do you want to proceed and add a new data source now?</html>";
|
||||||
if (JOptionPane.showConfirmDialog(null, msg, "Ingest in progress", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.NO_OPTION) {
|
if (JOptionPane.showConfirmDialog(null, msg, "Ingest in progress", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.NO_OPTION) {
|
||||||
return;
|
return;
|
||||||
@ -128,7 +128,6 @@ public final class AddImageAction extends CallableSystemAction implements Presen
|
|||||||
dialog.setVisible(true);
|
dialog.setVisible(true);
|
||||||
dialog.toFront();
|
dialog.toFront();
|
||||||
|
|
||||||
|
|
||||||
// Do any cleanup that needs to happen (potentially: stopping the
|
// Do any cleanup that needs to happen (potentially: stopping the
|
||||||
//add-image process, reverting an image)
|
//add-image process, reverting an image)
|
||||||
runCleanupTasks();
|
runCleanupTasks();
|
||||||
|
@ -55,7 +55,7 @@ import org.sleuthkit.datamodel.TskException;
|
|||||||
class AddImageWizardPanel3 implements WizardDescriptor.Panel<WizardDescriptor> {
|
class AddImageWizardPanel3 implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(AddImageWizardPanel3.class.getName());
|
private static final Logger logger = Logger.getLogger(AddImageWizardPanel3.class.getName());
|
||||||
private IngestConfigurator ingestConfig = Lookup.getDefault().lookup(IngestConfigurator.class);
|
private IngestConfigurator ingestConfig;
|
||||||
/**
|
/**
|
||||||
* The visual component that displays this panel. If you need to access the
|
* The visual component that displays this panel. If you need to access the
|
||||||
* component from this class, just use getComponent().
|
* component from this class, just use getComponent().
|
||||||
@ -85,6 +85,8 @@ class AddImageWizardPanel3 implements WizardDescriptor.Panel<WizardDescriptor> {
|
|||||||
AddImageWizardPanel3(AddImageAction action, AddImageWizardPanel2 wizPanel) {
|
AddImageWizardPanel3(AddImageAction action, AddImageWizardPanel2 wizPanel) {
|
||||||
this.action = action;
|
this.action = action;
|
||||||
this.wizPanel = wizPanel;
|
this.wizPanel = wizPanel;
|
||||||
|
ingestConfig = Lookup.getDefault().lookup(IngestConfigurator.class);
|
||||||
|
ingestConfig.setContext(AddImageWizardPanel3.class.getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -326,7 +326,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
|||||||
* @param imgId the ID of the image that being added
|
* @param imgId the ID of the image that being added
|
||||||
* @param timeZone the timeZone of the image where it's added
|
* @param timeZone the timeZone of the image where it's added
|
||||||
*/
|
*/
|
||||||
Image addImage(String imgPath, long imgId, String timeZone) throws CaseActionException {
|
public Image addImage(String imgPath, long imgId, String timeZone) throws CaseActionException {
|
||||||
logger.log(Level.INFO, "Adding image to Case. imgPath: {0} ID: {1} TimeZone: {2}", new Object[]{imgPath, imgId, timeZone});
|
logger.log(Level.INFO, "Adding image to Case. imgPath: {0} ID: {1} TimeZone: {2}", new Object[]{imgPath, imgId, timeZone});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -372,7 +372,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
|||||||
/**
|
/**
|
||||||
* Closes this case. This methods close the xml and clear all the fields.
|
* Closes this case. This methods close the xml and clear all the fields.
|
||||||
*/
|
*/
|
||||||
void closeCase() throws CaseActionException {
|
public void closeCase() throws CaseActionException {
|
||||||
changeCase(null);
|
changeCase(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2013 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.casemodule;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestDialogPanel;
|
||||||
|
import static org.sleuthkit.autopsy.ingest.IngestDialogPanel.DISABLED_MOD;
|
||||||
|
import static org.sleuthkit.autopsy.ingest.IngestDialogPanel.PARSE_UNALLOC;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleAbstract;
|
||||||
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
|
||||||
|
@ServiceProvider(service = IngestConfigurator.class)
|
||||||
|
public class GeneralIngestConfigurator implements IngestConfigurator {
|
||||||
|
private List<Content> contentToIngest;
|
||||||
|
private IngestManager manager;
|
||||||
|
private IngestDialogPanel ingestDialogPanel;
|
||||||
|
private String moduleContext;
|
||||||
|
|
||||||
|
public GeneralIngestConfigurator() {
|
||||||
|
this.moduleContext = IngestManager.MODULE_PROPERTIES; // Hard-code this for now.
|
||||||
|
ingestDialogPanel = new IngestDialogPanel();
|
||||||
|
ingestDialogPanel.setContext(moduleContext);
|
||||||
|
manager = IngestManager.getDefault();
|
||||||
|
loadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setContext(String context) {
|
||||||
|
moduleContext = context;
|
||||||
|
ingestDialogPanel.setContext(moduleContext);
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JPanel getIngestConfigPanel() {
|
||||||
|
return ingestDialogPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setContent(List<Content> inputContent) {
|
||||||
|
this.contentToIngest = inputContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
// Get the list of ingest modules selected by the user.
|
||||||
|
List<IngestModuleAbstract> modulesToStart = ingestDialogPanel.getModulesToStart();
|
||||||
|
|
||||||
|
// Get the user's selection of whether or not to process unallocated space.
|
||||||
|
manager.setProcessUnallocSpace(ingestDialogPanel.processUnallocSpaceEnabled());
|
||||||
|
|
||||||
|
// Start the ingest.
|
||||||
|
if (!modulesToStart.isEmpty()) {
|
||||||
|
manager.execute(modulesToStart, contentToIngest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() {
|
||||||
|
// Save the user's configuration of the currently selected module.
|
||||||
|
IngestModuleAbstract currentModule = ingestDialogPanel.getCurrentIngestModule();
|
||||||
|
if (currentModule != null && currentModule.hasSimpleConfiguration()) {
|
||||||
|
currentModule.saveSimpleConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a list of the modules the user wants to be disabled.
|
||||||
|
List<IngestModuleAbstract> disabledModules = IngestManager.getDefault().enumerateAllModules();
|
||||||
|
disabledModules.removeAll(ingestDialogPanel.getModulesToStart());
|
||||||
|
String disabledModulesCsv = moduleListToCsv(disabledModules);
|
||||||
|
|
||||||
|
// Save the user's general ingest configuration.
|
||||||
|
ModuleSettings.setConfigSetting(moduleContext, DISABLED_MOD, disabledModulesCsv);
|
||||||
|
String processUnalloc = Boolean.toString(ingestDialogPanel.processUnallocSpaceEnabled());
|
||||||
|
ModuleSettings.setConfigSetting(moduleContext, PARSE_UNALLOC, processUnalloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() {
|
||||||
|
loadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isIngestRunning() {
|
||||||
|
return manager.isIngestRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String moduleListToCsv(List<IngestModuleAbstract> lst) {
|
||||||
|
if (lst == null || lst.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < lst.size() - 1; ++i) {
|
||||||
|
sb.append(lst.get(i).getName()).append(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// and the last one
|
||||||
|
sb.append(lst.get(lst.size() - 1).getName());
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<IngestModuleAbstract> csvToModuleList(String csv) {
|
||||||
|
List<IngestModuleAbstract> modules = new ArrayList<>();
|
||||||
|
|
||||||
|
if (csv == null || csv.isEmpty()) {
|
||||||
|
return modules;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] moduleNames = csv.split(", ");
|
||||||
|
List<IngestModuleAbstract> allModules = IngestManager.getDefault().enumerateAllModules();
|
||||||
|
for (String moduleName : moduleNames) {
|
||||||
|
for (IngestModuleAbstract module : allModules) {
|
||||||
|
if (moduleName.equals(module.getName())) {
|
||||||
|
modules.add(module);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modules;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadSettings() {
|
||||||
|
// get the csv list of disabled modules
|
||||||
|
String disabledModulesCsv = ModuleSettings.getConfigSetting(moduleContext, DISABLED_MOD);
|
||||||
|
|
||||||
|
// create a list of modules from it
|
||||||
|
List<IngestModuleAbstract> disabledModules = csvToModuleList(disabledModulesCsv);
|
||||||
|
|
||||||
|
// tell the ingestDialogPanel to unselect these modules
|
||||||
|
ingestDialogPanel.setDisabledModules(disabledModules);
|
||||||
|
|
||||||
|
boolean processUnalloc = Boolean.parseBoolean(ModuleSettings.getConfigSetting(moduleContext, PARSE_UNALLOC));
|
||||||
|
ingestDialogPanel.setProcessUnallocSpaceEnabled(processUnalloc);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2011-2013 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");
|
||||||
@ -60,4 +60,10 @@ public interface IngestConfigurator {
|
|||||||
*/
|
*/
|
||||||
boolean isIngestRunning();
|
boolean isIngestRunning();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the context for the configuration.
|
||||||
|
* @param context
|
||||||
|
*/
|
||||||
|
public void setContext(String context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -77,9 +77,11 @@ public class FileManager implements Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param dataSource data source Content (Image, parent-less
|
* Finds a set of files that meets the name criteria.
|
||||||
* VirtualDirectory) where to find files
|
* @param dataSource Root data source to limit search results to (Image,
|
||||||
* @param fileName the name of the file or directory to match
|
* VirtualDirectory, etc.).
|
||||||
|
* @param fileName Pattern of the name of the file or directory to match (case
|
||||||
|
* insensitive, used in LIKE SQL statement).
|
||||||
* @return a list of AbstractFile for files/directories whose name matches
|
* @return a list of AbstractFile for files/directories whose name matches
|
||||||
* the given fileName
|
* the given fileName
|
||||||
*/
|
*/
|
||||||
@ -90,11 +92,15 @@ public class FileManager implements Closeable {
|
|||||||
return tskCase.findFiles(dataSource, fileName);
|
return tskCase.findFiles(dataSource, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param dataSource data source Content (Image, parent-less
|
* Finds a set of files that meets the name criteria.
|
||||||
* VirtualDirectory) where to find files
|
* @param dataSource Root data source to limit search results to (Image,
|
||||||
* @param fileName the name of the file or directory to match
|
* VirtualDirectory, etc.).
|
||||||
* @param dirName the name of a parent directory of fileName
|
* @param fileName Pattern of the name of the file or directory to match (case
|
||||||
|
* insensitive, used in LIKE SQL statement).
|
||||||
|
* @param dirName Pattern of the name of the parent directory to use as the root
|
||||||
|
* of the search (case insensitive, used in LIKE SQL statement).
|
||||||
* @return a list of AbstractFile for files/directories whose name matches
|
* @return a list of AbstractFile for files/directories whose name matches
|
||||||
* fileName and whose parent directory contains dirName.
|
* fileName and whose parent directory contains dirName.
|
||||||
*/
|
*/
|
||||||
@ -106,10 +112,12 @@ public class FileManager implements Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param dataSource data source Content (Image, parent-less
|
* Finds a set of files that meets the name criteria.
|
||||||
* VirtualDirectory) where to find files
|
* @param dataSource Root data source to limit search results to (Image,
|
||||||
* @param fileName the name of the file or directory to match
|
* VirtualDirectory, etc.).
|
||||||
* @param parentFile parent file/dir of the file to find
|
* @param fileName Pattern of the name of the file or directory to match (case
|
||||||
|
* insensitive, used in LIKE SQL statement).
|
||||||
|
* @param parentFile Object of root/parent directory to restrict search to.
|
||||||
* @return a list of AbstractFile for files/directories whose name matches
|
* @return a list of AbstractFile for files/directories whose name matches
|
||||||
* fileName and that were inside a directory described by parentFsContent.
|
* fileName and that were inside a directory described by parentFsContent.
|
||||||
*/
|
*/
|
||||||
|
@ -27,7 +27,6 @@ import org.openide.nodes.Node;
|
|||||||
* Interface for the different viewers that show a set of nodes in the DataResult area.
|
* Interface for the different viewers that show a set of nodes in the DataResult area.
|
||||||
* AbstractDataResultViewer has default implementations for the action handlers.
|
* AbstractDataResultViewer has default implementations for the action handlers.
|
||||||
*
|
*
|
||||||
* @author jantonius
|
|
||||||
*/
|
*/
|
||||||
public interface DataResultViewer {
|
public interface DataResultViewer {
|
||||||
/**
|
/**
|
||||||
@ -47,7 +46,7 @@ public interface DataResultViewer {
|
|||||||
public DataResultViewer createInstance();
|
public DataResultViewer createInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Component to display this DataResultViewer
|
* Get the Swing component (i.e. JPanel) for this viewer
|
||||||
*/
|
*/
|
||||||
public Component getComponent();
|
public Component getComponent();
|
||||||
|
|
||||||
@ -74,7 +73,7 @@ public interface DataResultViewer {
|
|||||||
public void setSelectedNodes(Node[] selected);
|
public void setSelectedNodes(Node[] selected);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the currently selected node
|
* Checks whether the currently selected root node
|
||||||
* is supported by this viewer
|
* is supported by this viewer
|
||||||
* @param selectedNode the selected node
|
* @param selectedNode the selected node
|
||||||
* @return True if supported, else false
|
* @return True if supported, else false
|
||||||
|
@ -36,7 +36,8 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
|||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds commonalities between all DataResultViewers
|
* Holds commonalities between all DataResultViewers, such as:
|
||||||
|
* - Pushes selection to DataContentViewers
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractDataResultViewer extends JPanel implements
|
public abstract class AbstractDataResultViewer extends JPanel implements
|
||||||
DataResultViewer, Provider {
|
DataResultViewer, Provider {
|
||||||
@ -81,21 +82,17 @@ public abstract class AbstractDataResultViewer extends JPanel implements
|
|||||||
// change the cursor to "waiting cursor" for this operation
|
// change the cursor to "waiting cursor" for this operation
|
||||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||||
try {
|
try {
|
||||||
Node selectedNode = getSelectedNode();
|
Node[] selectedNodes = getExplorerManager().getSelectedNodes();
|
||||||
|
if (selectedNodes.length == 1) {
|
||||||
nodeSelected(selectedNode);
|
nodeSelected(selectedNodes[0]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (selectedNode != null) {
|
|
||||||
// there's a new/changed node to display
|
// there's a new/changed node to display
|
||||||
Node newSelectedNode = selectedNode; // get the selected Node on the table
|
|
||||||
// push the node to default "DataContent"
|
// push the node to default "DataContent"
|
||||||
//TODO only the active viewer should be calling setNode
|
//TODO only the active viewer should be calling setNode
|
||||||
//not all of them, otherwise it results in multiple setNode() invocations
|
//not all of them, otherwise it results in multiple setNode() invocations
|
||||||
//alternative is to use a single instance of the event listener
|
//alternative is to use a single instance of the event listener
|
||||||
//, per top component and not the tab perhaps
|
//, per top component and not the tab perhaps
|
||||||
contentViewer.setNode(newSelectedNode);
|
contentViewer.setNode(selectedNodes[0]);
|
||||||
} else {
|
} else {
|
||||||
// clear the node viewer
|
// clear the node viewer
|
||||||
contentViewer.setNode(null);
|
contentViewer.setNode(null);
|
||||||
@ -131,6 +128,7 @@ public abstract class AbstractDataResultViewer extends JPanel implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public Node getSelectedNode() {
|
public Node getSelectedNode() {
|
||||||
Node result = null;
|
Node result = null;
|
||||||
Node[] selectedNodes = this.getExplorerManager().getSelectedNodes();
|
Node[] selectedNodes = this.getExplorerManager().getSelectedNodes();
|
||||||
|
@ -178,7 +178,7 @@ public class DataContentPanel extends javax.swing.JPanel implements DataContent,
|
|||||||
jTabbedPane1.setEnabledAt(i, true);
|
jTabbedPane1.setEnabledAt(i, true);
|
||||||
|
|
||||||
// remember the viewer with the highest preference value
|
// remember the viewer with the highest preference value
|
||||||
int currentPreferred = dcv.isPreferred(selectedNode, false);
|
int currentPreferred = dcv.isPreferred(selectedNode, true);
|
||||||
if (currentPreferred > maxPreferred) {
|
if (currentPreferred > maxPreferred) {
|
||||||
preferredViewerIndex = i;
|
preferredViewerIndex = i;
|
||||||
maxPreferred = currentPreferred;
|
maxPreferred = currentPreferred;
|
||||||
@ -191,7 +191,14 @@ public class DataContentPanel extends javax.swing.JPanel implements DataContent,
|
|||||||
|
|
||||||
// set the tab to the one the user wants, then set that viewer's node.
|
// set the tab to the one the user wants, then set that viewer's node.
|
||||||
jTabbedPane1.setSelectedIndex(tabIndex);
|
jTabbedPane1.setSelectedIndex(tabIndex);
|
||||||
viewers.get(tabIndex).setNode(selectedNode);
|
UpdateWrapper dcv = viewers.get(tabIndex);
|
||||||
|
// this is really only needed if no tabs were enabled
|
||||||
|
if (jTabbedPane1.isEnabledAt(tabIndex) == false) {
|
||||||
|
dcv.resetComponent();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dcv.setNode(selectedNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -231,18 +231,21 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
|||||||
@Override
|
@Override
|
||||||
public void setNode(Node selectedNode) {
|
public void setNode(Node selectedNode) {
|
||||||
if (selectedNode == null) {
|
if (selectedNode == null) {
|
||||||
this.setDataView(new ArrayList<BlackboardArtifact>(), 1);
|
resetComponent();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lookup lookup = selectedNode.getLookup();
|
Lookup lookup = selectedNode.getLookup();
|
||||||
Content content = lookup.lookup(Content.class);
|
Content content = lookup.lookup(Content.class);
|
||||||
if (content != null) {
|
if (content == null) {
|
||||||
try {
|
resetComponent();
|
||||||
this.setDataView(content.getAllArtifacts(), 1);
|
return;
|
||||||
} catch (TskException ex) {
|
}
|
||||||
logger.log(Level.WARNING, "Couldn't get artifacts: ", ex);
|
|
||||||
}
|
try {
|
||||||
|
this.setDataView(content.getAllArtifacts(), 1);
|
||||||
|
} catch (TskException ex) {
|
||||||
|
logger.log(Level.WARNING, "Couldn't get artifacts: ", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// focus on a specific artifact if it is in the node
|
// focus on a specific artifact if it is in the node
|
||||||
@ -279,9 +282,11 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
|||||||
this.artifacts = new ArrayList<BlackboardArtifact>();
|
this.artifacts = new ArrayList<BlackboardArtifact>();
|
||||||
currentPageLabel.setText("");
|
currentPageLabel.setText("");
|
||||||
totalPageLabel.setText("");
|
totalPageLabel.setText("");
|
||||||
|
outputViewPane.setText("");
|
||||||
prevPageButton.setEnabled(false);
|
prevPageButton.setEnabled(false);
|
||||||
nextPageButton.setEnabled(false);
|
nextPageButton.setEnabled(false);
|
||||||
setComponentsVisibility(false); // hides the components that not needed
|
setComponentsVisibility(false); // hides the components that not needed
|
||||||
|
this.setCursor(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -380,9 +385,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
|||||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||||
|
|
||||||
if(artifacts.isEmpty()){
|
if(artifacts.isEmpty()){
|
||||||
setComponentsVisibility(false);
|
resetComponent();
|
||||||
this.setCursor(null);
|
|
||||||
outputViewPane.setText("");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.artifacts = artifacts;
|
this.artifacts = artifacts;
|
||||||
|
@ -247,7 +247,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
|
|||||||
currentOffset -= pageLength;
|
currentOffset -= pageLength;
|
||||||
currentPage = currentPage - 1;
|
currentPage = currentPage - 1;
|
||||||
currentPageLabel.setText(Integer.toString(currentPage));
|
currentPageLabel.setText(Integer.toString(currentPage));
|
||||||
setDataView(dataSource, currentOffset, false);
|
setDataView(dataSource, currentOffset);
|
||||||
}//GEN-LAST:event_prevPageButtonActionPerformed
|
}//GEN-LAST:event_prevPageButtonActionPerformed
|
||||||
|
|
||||||
private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed
|
private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed
|
||||||
@ -255,7 +255,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
|
|||||||
currentOffset += pageLength;
|
currentOffset += pageLength;
|
||||||
currentPage = currentPage + 1;
|
currentPage = currentPage + 1;
|
||||||
currentPageLabel.setText(Integer.toString(currentPage));
|
currentPageLabel.setText(Integer.toString(currentPage));
|
||||||
setDataView(dataSource, currentOffset, false);
|
setDataView(dataSource, currentOffset);
|
||||||
}//GEN-LAST:event_nextPageButtonActionPerformed
|
}//GEN-LAST:event_nextPageButtonActionPerformed
|
||||||
|
|
||||||
private void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goToPageTextFieldActionPerformed
|
private void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goToPageTextFieldActionPerformed
|
||||||
@ -275,7 +275,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
|
|||||||
currentOffset = (pageNumber - 1) * pageLength;
|
currentOffset = (pageNumber - 1) * pageLength;
|
||||||
currentPage = pageNumber;
|
currentPage = pageNumber;
|
||||||
currentPageLabel.setText(Integer.toString(currentPage));
|
currentPageLabel.setText(Integer.toString(currentPage));
|
||||||
setDataView(dataSource, currentOffset, false);
|
setDataView(dataSource, currentOffset);
|
||||||
}//GEN-LAST:event_goToPageTextFieldActionPerformed
|
}//GEN-LAST:event_goToPageTextFieldActionPerformed
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JMenuItem copyMenuItem;
|
private javax.swing.JMenuItem copyMenuItem;
|
||||||
@ -295,14 +295,23 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
|
|||||||
private javax.swing.JLabel totalPageLabel;
|
private javax.swing.JLabel totalPageLabel;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void setDataView(Content dataSource, long offset, boolean reset) {
|
||||||
|
if (reset) {
|
||||||
|
resetComponent();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setDataView(dataSource, offset);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the DataView (The tabbed panel)
|
* Sets the DataView (The tabbed panel)
|
||||||
*
|
*
|
||||||
* @param dataSource the content that want to be shown
|
* @param dataSource the content that want to be shown
|
||||||
* @param offset the starting offset
|
* @param offset the starting offset
|
||||||
* @param reset whether to reset the dataView or not
|
|
||||||
*/
|
*/
|
||||||
public void setDataView(Content dataSource, long offset, boolean reset) {
|
private void setDataView(Content dataSource, long offset) {
|
||||||
if (dataSource == null) {
|
if (dataSource == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -312,14 +321,12 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
|
|||||||
|
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
String errorText = null;
|
String errorText = null;
|
||||||
Boolean setVisible = false;
|
|
||||||
|
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
if (!reset && dataSource.getSize() > 0) {
|
if (dataSource.getSize() > 0) {
|
||||||
try {
|
try {
|
||||||
bytesRead = dataSource.read(data, offset, pageLength); // read the data
|
bytesRead = dataSource.read(data, offset, pageLength); // read the data
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
setVisible = true;
|
|
||||||
errorText = "(offset " + currentOffset + "-" + (currentOffset + pageLength)
|
errorText = "(offset " + currentOffset + "-" + (currentOffset + pageLength)
|
||||||
+ " could not be read)";
|
+ " could not be read)";
|
||||||
logger.log(Level.WARNING, "Error while trying to show the hex content.", ex);
|
logger.log(Level.WARNING, "Error while trying to show the hex content.", ex);
|
||||||
@ -327,73 +334,58 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set the data on the bottom and show it
|
// set the data on the bottom and show it
|
||||||
if (bytesRead > 0) {
|
if (bytesRead <= 0) {
|
||||||
setVisible = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
errorText = "(offset " + currentOffset + "-" + (currentOffset + pageLength)
|
errorText = "(offset " + currentOffset + "-" + (currentOffset + pageLength)
|
||||||
+ " could not be read)";
|
+ " could not be read)";
|
||||||
setVisible = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// disable or enable the next button
|
// disable or enable the next button
|
||||||
if (!reset && offset + pageLength < dataSource.getSize()) {
|
if ((errorText != null) && (offset + pageLength < dataSource.getSize())) {
|
||||||
nextPageButton.setEnabled(true);
|
nextPageButton.setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
nextPageButton.setEnabled(false);
|
nextPageButton.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset == 0) {
|
if ((offset == 0) || (errorText == null)) {
|
||||||
prevPageButton.setEnabled(false);
|
prevPageButton.setEnabled(false);
|
||||||
currentPage = 1; // reset the page number
|
currentPage = 1; // reset the page number
|
||||||
} else {
|
} else {
|
||||||
prevPageButton.setEnabled(true);
|
prevPageButton.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setVisible) {
|
int totalPage = Math.round((dataSource.getSize() - 1) / pageLength) + 1;
|
||||||
int totalPage = Math.round((dataSource.getSize() - 1) / pageLength) + 1;
|
totalPageLabel.setText(Integer.toString(totalPage));
|
||||||
totalPageLabel.setText(Integer.toString(totalPage));
|
currentPageLabel.setText(Integer.toString(currentPage));
|
||||||
currentPageLabel.setText(Integer.toString(currentPage));
|
setComponentsVisibility(true); // shows the components that not needed
|
||||||
setComponentsVisibility(true); // shows the components that not needed
|
|
||||||
|
|
||||||
// set the output view
|
// set the output view
|
||||||
|
if (errorText == null) {
|
||||||
int showLength = bytesRead < pageLength ? bytesRead : (int) pageLength;
|
int showLength = bytesRead < pageLength ? bytesRead : (int) pageLength;
|
||||||
if (errorText == null) {
|
outputViewPane.setText(DataConversion.byteArrayToHex(data, showLength, offset, outputViewPane.getFont()));
|
||||||
outputViewPane.setText(DataConversion.byteArrayToHex(data, showLength, offset, outputViewPane.getFont()));
|
}
|
||||||
}
|
else {
|
||||||
else {
|
outputViewPane.setText(errorText);
|
||||||
outputViewPane.setText(errorText);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// reset or hide the labels
|
|
||||||
totalPageLabel.setText("");
|
|
||||||
currentPageLabel.setText("");
|
|
||||||
outputViewPane.setText(""); // reset the output view
|
|
||||||
setComponentsVisibility(false); // hides the components that not needed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
outputViewPane.moveCaretPosition(0);
|
outputViewPane.moveCaretPosition(0);
|
||||||
|
|
||||||
this.setCursor(null);
|
this.setCursor(null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setNode(Node selectedNode) {
|
public void setNode(Node selectedNode) {
|
||||||
if ((selectedNode == null) || (!isSupported(selectedNode))) {
|
if ((selectedNode == null) || (!isSupported(selectedNode))) {
|
||||||
setDataView(null, 0, true);
|
resetComponent();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Content content = (selectedNode).getLookup().lookup(Content.class);
|
Content content = (selectedNode).getLookup().lookup(Content.class);
|
||||||
if (content == null) {
|
if (content == null) {
|
||||||
this.setDataView(null, 0, true);
|
resetComponent();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setDataView(content, 0, false);
|
this.setDataView(content, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -420,8 +412,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
|
|||||||
this.dataSource = null;
|
this.dataSource = null;
|
||||||
currentPageLabel.setText("");
|
currentPageLabel.setText("");
|
||||||
totalPageLabel.setText("");
|
totalPageLabel.setText("");
|
||||||
prevPageButton.setEnabled(false);
|
outputViewPane.setText("");
|
||||||
nextPageButton.setEnabled(false);
|
|
||||||
setComponentsVisibility(false); // hides the components that not needed
|
setComponentsVisibility(false); // hides the components that not needed
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,8 +439,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Content content = node.getLookup().lookup(Content.class);
|
Content content = node.getLookup().lookup(Content.class);
|
||||||
|
if (content != null && content.getSize() > 0) {
|
||||||
if (content != null && content.getSize() != 0) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,259 +1,256 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2013 Basis Technology Corp.
|
* Copyright 2011-2013 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.corecomponents;
|
package org.sleuthkit.autopsy.corecomponents;
|
||||||
|
|
||||||
import java.awt.CardLayout;
|
import java.awt.CardLayout;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.Exceptions;
|
import org.openide.util.Exceptions;
|
||||||
import org.openide.util.lookup.ServiceProvider;
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
import org.openide.util.lookup.ServiceProviders;
|
import org.openide.util.lookup.ServiceProviders;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
|
import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Media content viewer for videos, sounds and images.
|
* Media content viewer for videos, sounds and images.
|
||||||
*/
|
*/
|
||||||
@ServiceProviders(value = {
|
@ServiceProviders(value = {
|
||||||
@ServiceProvider(service = DataContentViewer.class, position = 5)
|
@ServiceProvider(service = DataContentViewer.class, position = 5)
|
||||||
})
|
})
|
||||||
public class DataContentViewerMedia extends javax.swing.JPanel implements DataContentViewer {
|
public class DataContentViewerMedia extends javax.swing.JPanel implements DataContentViewer {
|
||||||
|
|
||||||
private String[] IMAGES; // use javafx supported
|
private String[] IMAGES; // use javafx supported
|
||||||
private static final String[] VIDEOS = new String[]{".swf", ".mov", ".m4v", ".flv", ".mp4", ".3gp", ".avi", ".mpg", ".mpeg", ".wmv"};
|
private static final String[] VIDEOS = new String[]{".swf", ".mov", ".m4v", ".flv", ".mp4", ".3gp", ".avi", ".mpg", ".mpeg", ".wmv"};
|
||||||
private static final String[] AUDIOS = new String[]{".mp3", ".wav", ".wma"};
|
private static final String[] AUDIOS = new String[]{".mp3", ".wav", ".wma"};
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(DataContentViewerMedia.class.getName());
|
private static final Logger logger = Logger.getLogger(DataContentViewerMedia.class.getName());
|
||||||
|
|
||||||
private AbstractFile lastFile;
|
private AbstractFile lastFile;
|
||||||
//UI
|
//UI
|
||||||
private final MediaViewVideoPanel videoPanel;
|
private final MediaViewVideoPanel videoPanel;
|
||||||
private final MediaViewImagePanel imagePanel;
|
private final MediaViewImagePanel imagePanel;
|
||||||
private boolean videoPanelInited;
|
private boolean videoPanelInited;
|
||||||
private boolean imagePanelInited;
|
private boolean imagePanelInited;
|
||||||
|
|
||||||
private static final String IMAGE_VIEWER_LAYER = "IMAGE";
|
private static final String IMAGE_VIEWER_LAYER = "IMAGE";
|
||||||
private static final String VIDEO_VIEWER_LAYER = "VIDEO";
|
private static final String VIDEO_VIEWER_LAYER = "VIDEO";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form DataContentViewerVideo
|
* Creates new form DataContentViewerVideo
|
||||||
*/
|
*/
|
||||||
public DataContentViewerMedia() {
|
public DataContentViewerMedia() {
|
||||||
|
|
||||||
initComponents();
|
initComponents();
|
||||||
|
|
||||||
videoPanel = MediaViewVideoPanel.createVideoPanel();
|
videoPanel = MediaViewVideoPanel.createVideoPanel();
|
||||||
imagePanel = new MediaViewImagePanel();
|
imagePanel = new MediaViewImagePanel();
|
||||||
videoPanelInited = videoPanel.isInited();
|
videoPanelInited = videoPanel.isInited();
|
||||||
imagePanelInited = imagePanel.isInited();
|
imagePanelInited = imagePanel.isInited();
|
||||||
|
|
||||||
customizeComponents();
|
customizeComponents();
|
||||||
logger.log(Level.INFO, "Created MediaView instance: " + this);
|
logger.log(Level.INFO, "Created MediaView instance: " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void customizeComponents() {
|
private void customizeComponents() {
|
||||||
logger.log(Level.INFO, "Supported image formats by javafx image viewer: ");
|
logger.log(Level.INFO, "Supported image formats by javafx image viewer: ");
|
||||||
//initialize supported image types
|
//initialize supported image types
|
||||||
//TODO use mime-types instead once we have support
|
//TODO use mime-types instead once we have support
|
||||||
String[] fxSupportedImagesSuffixes = ImageIO.getReaderFileSuffixes();
|
String[] fxSupportedImagesSuffixes = ImageIO.getReaderFileSuffixes();
|
||||||
IMAGES = new String[fxSupportedImagesSuffixes.length];
|
IMAGES = new String[fxSupportedImagesSuffixes.length];
|
||||||
for (int i = 0; i < fxSupportedImagesSuffixes.length; ++i) {
|
for (int i = 0; i < fxSupportedImagesSuffixes.length; ++i) {
|
||||||
String suffix = fxSupportedImagesSuffixes[i];
|
String suffix = fxSupportedImagesSuffixes[i];
|
||||||
logger.log(Level.INFO, "suffix: " + suffix);
|
logger.log(Level.INFO, "suffix: " + suffix);
|
||||||
IMAGES[i] = "." + suffix;
|
IMAGES[i] = "." + suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(imagePanel, IMAGE_VIEWER_LAYER);
|
add(imagePanel, IMAGE_VIEWER_LAYER);
|
||||||
add(videoPanel, VIDEO_VIEWER_LAYER);
|
add(videoPanel, VIDEO_VIEWER_LAYER);
|
||||||
|
|
||||||
switchPanels(false);
|
switchPanels(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from within the constructor to initialize the form.
|
* This method is called from within the constructor to initialize the form.
|
||||||
* WARNING: Do NOT modify this code. The content of this method is always
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
* regenerated by the Form Editor.
|
* regenerated by the Form Editor.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
|
|
||||||
setLayout(new java.awt.CardLayout());
|
setLayout(new java.awt.CardLayout());
|
||||||
getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(DataContentViewerMedia.class, "DataContentViewerMedia.AccessibleContext.accessibleDescription")); // NOI18N
|
getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(DataContentViewerMedia.class, "DataContentViewerMedia.AccessibleContext.accessibleDescription")); // NOI18N
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setNode(Node selectedNode) {
|
public void setNode(Node selectedNode) {
|
||||||
try {
|
try {
|
||||||
if (selectedNode == null) {
|
if (selectedNode == null) {
|
||||||
videoPanel.reset();
|
resetComponent();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractFile file = selectedNode.getLookup().lookup(AbstractFile.class);
|
AbstractFile file = selectedNode.getLookup().lookup(AbstractFile.class);
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
return;
|
resetComponent();
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
if (file.equals(lastFile)) {
|
|
||||||
return; //prevent from loading twice if setNode() called mult. times
|
if (file.equals(lastFile)) {
|
||||||
} else {
|
return; //prevent from loading twice if setNode() called mult. times
|
||||||
lastFile = file;
|
} else {
|
||||||
}
|
lastFile = file;
|
||||||
|
}
|
||||||
videoPanel.reset();
|
|
||||||
|
videoPanel.reset();
|
||||||
final Dimension dims = DataContentViewerMedia.this.getSize();
|
|
||||||
|
final Dimension dims = DataContentViewerMedia.this.getSize();
|
||||||
if (imagePanelInited && containsExt(file.getName(), IMAGES)) {
|
|
||||||
imagePanel.showImageFx(file, dims);
|
if (imagePanelInited && containsExt(file.getName(), IMAGES)) {
|
||||||
this.switchPanels(false);
|
imagePanel.showImageFx(file, dims);
|
||||||
} else if (videoPanelInited
|
this.switchPanels(false);
|
||||||
&& (containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS))) {
|
} else if (videoPanelInited
|
||||||
videoPanel.setupVideo(file, dims);
|
&& (containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS))) {
|
||||||
switchPanels(true);
|
videoPanel.setupVideo(file, dims);
|
||||||
}
|
switchPanels(true);
|
||||||
} catch (Exception e) {
|
}
|
||||||
logger.log(Level.SEVERE, "Exception while setting node", e);
|
} catch (Exception e) {
|
||||||
}
|
logger.log(Level.SEVERE, "Exception while setting node", e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* switch to visible video or image panel
|
/**
|
||||||
*
|
* switch to visible video or image panel
|
||||||
* @param showVideo true if video panel, false if image panel
|
*
|
||||||
*/
|
* @param showVideo true if video panel, false if image panel
|
||||||
private void switchPanels(boolean showVideo) {
|
*/
|
||||||
CardLayout layout = (CardLayout)this.getLayout();
|
private void switchPanels(boolean showVideo) {
|
||||||
if (showVideo) {
|
CardLayout layout = (CardLayout)this.getLayout();
|
||||||
layout.show(this, VIDEO_VIEWER_LAYER);
|
if (showVideo) {
|
||||||
} else {
|
layout.show(this, VIDEO_VIEWER_LAYER);
|
||||||
layout.show(this, IMAGE_VIEWER_LAYER);
|
} else {
|
||||||
}
|
layout.show(this, IMAGE_VIEWER_LAYER);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public String getTitle() {
|
@Override
|
||||||
return "Media View";
|
public String getTitle() {
|
||||||
}
|
return "Media View";
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public String getToolTip() {
|
@Override
|
||||||
return "Displays supported multimedia files (images, videos, audio)";
|
public String getToolTip() {
|
||||||
}
|
return "Displays supported multimedia files (images, videos, audio)";
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public DataContentViewer createInstance() {
|
@Override
|
||||||
return new DataContentViewerMedia();
|
public DataContentViewer createInstance() {
|
||||||
}
|
return new DataContentViewerMedia();
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public Component getComponent() {
|
@Override
|
||||||
return this;
|
public Component getComponent() {
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void resetComponent() {
|
@Override
|
||||||
// we don't want this to do anything
|
public void resetComponent() {
|
||||||
// because we already reset on each selected node
|
videoPanel.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSupported(Node node) {
|
public boolean isSupported(Node node) {
|
||||||
|
if (node == null) {
|
||||||
if (node == null) {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
|
||||||
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
|
if (file == null) {
|
||||||
if (file == null) {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
if (file.getSize() == 0) {
|
||||||
|
return false;
|
||||||
if (file.getSize() == 0) {
|
}
|
||||||
return false;
|
|
||||||
}
|
String name = file.getName().toLowerCase();
|
||||||
|
if (imagePanelInited && containsExt(name, IMAGES)) {
|
||||||
String name = file.getName().toLowerCase();
|
return true;
|
||||||
|
} //for gstreamer formats, check if initialized first, then
|
||||||
if (imagePanelInited && containsExt(name, IMAGES)) {
|
//support audio formats, and video formats
|
||||||
return true;
|
else if (videoPanelInited && videoPanel.isInited()
|
||||||
} //for gstreamer formats, check if initialized first, then
|
&& (containsExt(name, AUDIOS)
|
||||||
//support audio formats, and video formats
|
|| (containsExt(name, VIDEOS)))) {
|
||||||
else if (videoPanelInited && videoPanel.isInited()
|
return true;
|
||||||
&& (containsExt(name, AUDIOS)
|
}
|
||||||
|| (containsExt(name, VIDEOS)))) {
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
@Override
|
||||||
}
|
public int isPreferred(Node node, boolean isSupported) {
|
||||||
|
if (isSupported) {
|
||||||
@Override
|
//special case, check if deleted video, then do not make it preferred
|
||||||
public int isPreferred(Node node, boolean isSupported) {
|
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
|
||||||
if (isSupported) {
|
if (file == null) {
|
||||||
//special case, check if deleted video, then do not make it preferred
|
return 0;
|
||||||
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
|
}
|
||||||
if (file == null) {
|
String name = file.getName().toLowerCase();
|
||||||
return 0;
|
|
||||||
}
|
boolean deleted = file.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC);
|
||||||
String name = file.getName().toLowerCase();
|
if (containsExt(name, VIDEOS) && deleted) {
|
||||||
|
return 0;
|
||||||
boolean deleted = file.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC);
|
} else {
|
||||||
if (containsExt(name, VIDEOS) && deleted) {
|
return 7;
|
||||||
return 0;
|
}
|
||||||
} else {
|
} else {
|
||||||
return 7;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
return 0;
|
|
||||||
}
|
private static boolean containsExt(String name, String[] exts) {
|
||||||
}
|
int extStart = name.lastIndexOf(".");
|
||||||
|
String ext = "";
|
||||||
private static boolean containsExt(String name, String[] exts) {
|
if (extStart != -1) {
|
||||||
int extStart = name.lastIndexOf(".");
|
ext = name.substring(extStart, name.length()).toLowerCase();
|
||||||
String ext = "";
|
}
|
||||||
if (extStart != -1) {
|
return Arrays.asList(exts).contains(ext);
|
||||||
ext = name.substring(extStart, name.length()).toLowerCase();
|
}
|
||||||
}
|
}
|
||||||
return Arrays.asList(exts).contains(ext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
|
|||||||
currentOffset -= pageLength;
|
currentOffset -= pageLength;
|
||||||
currentPage = currentPage - 1;
|
currentPage = currentPage - 1;
|
||||||
currentPageLabel.setText(Integer.toString(currentPage));
|
currentPageLabel.setText(Integer.toString(currentPage));
|
||||||
setDataView(dataSource, currentOffset, false);
|
setDataView(dataSource, currentOffset);
|
||||||
}//GEN-LAST:event_prevPageButtonActionPerformed
|
}//GEN-LAST:event_prevPageButtonActionPerformed
|
||||||
|
|
||||||
private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed
|
private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed
|
||||||
@ -273,7 +273,7 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
|
|||||||
currentOffset += pageLength;
|
currentOffset += pageLength;
|
||||||
currentPage = currentPage + 1;
|
currentPage = currentPage + 1;
|
||||||
currentPageLabel.setText(Integer.toString(currentPage));
|
currentPageLabel.setText(Integer.toString(currentPage));
|
||||||
setDataView(dataSource, currentOffset, false);
|
setDataView(dataSource, currentOffset);
|
||||||
}//GEN-LAST:event_nextPageButtonActionPerformed
|
}//GEN-LAST:event_nextPageButtonActionPerformed
|
||||||
|
|
||||||
private void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goToPageTextFieldActionPerformed
|
private void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goToPageTextFieldActionPerformed
|
||||||
@ -293,13 +293,13 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
|
|||||||
currentOffset = (pageNumber - 1) * pageLength;
|
currentOffset = (pageNumber - 1) * pageLength;
|
||||||
currentPage = pageNumber;
|
currentPage = pageNumber;
|
||||||
currentPageLabel.setText(Integer.toString(currentPage));
|
currentPageLabel.setText(Integer.toString(currentPage));
|
||||||
setDataView(dataSource, currentOffset, false);
|
setDataView(dataSource, currentOffset);
|
||||||
}//GEN-LAST:event_goToPageTextFieldActionPerformed
|
}//GEN-LAST:event_goToPageTextFieldActionPerformed
|
||||||
|
|
||||||
private void languageComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_languageComboActionPerformed
|
private void languageComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_languageComboActionPerformed
|
||||||
|
|
||||||
if (dataSource != null) {
|
if (dataSource != null) {
|
||||||
setDataView(dataSource, currentOffset, false);
|
setDataView(dataSource, currentOffset);
|
||||||
}
|
}
|
||||||
}//GEN-LAST:event_languageComboActionPerformed
|
}//GEN-LAST:event_languageComboActionPerformed
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
@ -322,14 +322,22 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
|
|||||||
private javax.swing.JLabel totalPageLabel;
|
private javax.swing.JLabel totalPageLabel;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void setDataView(Content dataSource, long offset, boolean reset) {
|
||||||
|
if (reset) {
|
||||||
|
resetComponent();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setDataView(dataSource, offset);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the DataView (The tabbed panel)
|
* Sets the DataView (The tabbed panel)
|
||||||
*
|
*
|
||||||
* @param dataSource the content that want to be shown
|
* @param dataSource the content that want to be shown
|
||||||
* @param offset the starting offset
|
* @param offset the starting offset
|
||||||
* @param reset whether to reset the dataView or not
|
|
||||||
*/
|
*/
|
||||||
public void setDataView(Content dataSource, long offset, boolean reset) {
|
private void setDataView(Content dataSource, long offset) {
|
||||||
if (dataSource == null) {
|
if (dataSource == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -342,14 +350,12 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
|
|||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
// set the data on the bottom and show it
|
// set the data on the bottom and show it
|
||||||
String text = "";
|
String text = "";
|
||||||
Boolean setVisible = false;
|
if (dataSource.getSize() > 0) {
|
||||||
if (!reset && dataSource.getSize() > 0) {
|
|
||||||
try {
|
try {
|
||||||
bytesRead = dataSource.read(data, offset, pageLength); // read the data
|
bytesRead = dataSource.read(data, offset, pageLength); // read the data
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
text = "(offset " + currentOffset + "-" + (currentOffset + pageLength)
|
text = "(offset " + currentOffset + "-" + (currentOffset + pageLength)
|
||||||
+ " could not be read)";
|
+ " could not be read)";
|
||||||
setVisible = true;
|
|
||||||
logger.log(Level.WARNING, "Error while trying to show the String content.", ex);
|
logger.log(Level.WARNING, "Error while trying to show the String content.", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,16 +370,13 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
|
|||||||
text = "(offset " + currentOffset + "-" + (currentOffset + pageLength)
|
text = "(offset " + currentOffset + "-" + (currentOffset + pageLength)
|
||||||
+ " contains no text)";
|
+ " contains no text)";
|
||||||
}
|
}
|
||||||
|
|
||||||
setVisible = true;
|
|
||||||
} else {
|
} else {
|
||||||
text = "(offset " + currentOffset + "-" + (currentOffset + pageLength)
|
text = "(offset " + currentOffset + "-" + (currentOffset + pageLength)
|
||||||
+ " could not be read)";
|
+ " could not be read)";
|
||||||
setVisible = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable or enable the next button
|
// disable or enable the next button
|
||||||
if (!reset && offset + pageLength < dataSource.getSize()) {
|
if (offset + pageLength < dataSource.getSize()) {
|
||||||
nextPageButton.setEnabled(true);
|
nextPageButton.setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
nextPageButton.setEnabled(false);
|
nextPageButton.setEnabled(false);
|
||||||
@ -386,23 +389,15 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
|
|||||||
prevPageButton.setEnabled(true);
|
prevPageButton.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setVisible) {
|
|
||||||
int totalPage = Math.round((dataSource.getSize() - 1) / pageLength) + 1;
|
int totalPage = Math.round((dataSource.getSize() - 1) / pageLength) + 1;
|
||||||
totalPageLabel.setText(Integer.toString(totalPage));
|
totalPageLabel.setText(Integer.toString(totalPage));
|
||||||
currentPageLabel.setText(Integer.toString(currentPage));
|
currentPageLabel.setText(Integer.toString(currentPage));
|
||||||
outputViewPane.setText(text); // set the output view
|
outputViewPane.setText(text); // set the output view
|
||||||
setComponentsVisibility(true); // shows the components that not needed
|
setComponentsVisibility(true); // shows the components that not needed
|
||||||
} else {
|
|
||||||
// reset or hide the labels
|
|
||||||
totalPageLabel.setText("");
|
|
||||||
currentPageLabel.setText("");
|
|
||||||
outputViewPane.setText(""); // reset the output view
|
|
||||||
setComponentsVisibility(false); // hides the components that not needed
|
|
||||||
}
|
|
||||||
outputViewPane.moveCaretPosition(0);
|
outputViewPane.moveCaretPosition(0);
|
||||||
|
|
||||||
this.setCursor(null);
|
this.setCursor(null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -422,31 +417,28 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
|
|||||||
goToPageLabel.setVisible(isVisible);
|
goToPageLabel.setVisible(isVisible);
|
||||||
languageCombo.setVisible(isVisible);
|
languageCombo.setVisible(isVisible);
|
||||||
languageLabel.setVisible(isVisible);
|
languageLabel.setVisible(isVisible);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setNode(Node selectedNode) {
|
public void setNode(Node selectedNode) {
|
||||||
if (!isSupported(selectedNode)) {
|
if ((selectedNode == null) || (!isSupported(selectedNode))) {
|
||||||
setDataView(null, 0, true);
|
resetComponent();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (selectedNode != null) {
|
|
||||||
Lookup lookup = selectedNode.getLookup();
|
Lookup lookup = selectedNode.getLookup();
|
||||||
Content content = lookup.lookup(Content.class);
|
Content content = lookup.lookup(Content.class);
|
||||||
if (content
|
if (content != null) {
|
||||||
!= null) {
|
this.setDataView(content, 0);
|
||||||
this.setDataView(content, 0, false);
|
return;
|
||||||
|
} else {
|
||||||
|
StringContent scontent = selectedNode.getLookup().lookup(StringContent.class);
|
||||||
|
if (scontent != null) {
|
||||||
|
this.setDataView(scontent);
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
StringContent scontent = selectedNode.getLookup().lookup(StringContent.class);
|
|
||||||
if (scontent != null) {
|
|
||||||
this.setDataView(scontent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setDataView(null, 0, true);
|
resetComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -474,6 +466,7 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
|
|||||||
totalPageLabel.setText("");
|
totalPageLabel.setText("");
|
||||||
prevPageButton.setEnabled(false);
|
prevPageButton.setEnabled(false);
|
||||||
nextPageButton.setEnabled(false);
|
nextPageButton.setEnabled(false);
|
||||||
|
outputViewPane.setText(""); // reset the output view
|
||||||
setComponentsVisibility(false); // hides the components that not needed
|
setComponentsVisibility(false); // hides the components that not needed
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,14 +474,9 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
|
|||||||
public boolean isSupported(Node node) {
|
public boolean isSupported(Node node) {
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Content content = node.getLookup().lookup(Content.class);
|
Content content = node.getLookup().lookup(Content.class);
|
||||||
|
if (content != null && content.getSize() > 0) {
|
||||||
if (content
|
|
||||||
!= null && content.getSize()
|
|
||||||
!= 0) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResult;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResult;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import org.openide.explorer.ExplorerUtils;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.windows.TopComponent;
|
import org.openide.windows.TopComponent;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
@ -54,6 +55,7 @@ public class DataResultTopComponent extends TopComponent implements DataResult {
|
|||||||
private static final Logger logger = Logger.getLogger(DataResultTopComponent.class.getName());
|
private static final Logger logger = Logger.getLogger(DataResultTopComponent.class.getName());
|
||||||
private DataResultPanel dataResultPanel; //embedded component with all the logic
|
private DataResultPanel dataResultPanel; //embedded component with all the logic
|
||||||
private boolean isMain;
|
private boolean isMain;
|
||||||
|
private boolean lookupSet = false;
|
||||||
private String customModeName;
|
private String customModeName;
|
||||||
|
|
||||||
//keep track of tcs openeded for menu presenters
|
//keep track of tcs openeded for menu presenters
|
||||||
@ -96,9 +98,9 @@ public class DataResultTopComponent extends TopComponent implements DataResult {
|
|||||||
|
|
||||||
initComponents();
|
initComponents();
|
||||||
customizeComponent(isMain, name);;
|
customizeComponent(isMain, name);;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void customizeComponent(boolean isMain, String title) {
|
private void customizeComponent(boolean isMain, String title) {
|
||||||
this.isMain = isMain;
|
this.isMain = isMain;
|
||||||
this.customModeName = null;
|
this.customModeName = null;
|
||||||
@ -260,6 +262,21 @@ public class DataResultTopComponent extends TopComponent implements DataResult {
|
|||||||
super.componentOpened();
|
super.componentOpened();
|
||||||
|
|
||||||
this.dataResultPanel.open();
|
this.dataResultPanel.open();
|
||||||
|
|
||||||
|
/* @@@ Short-term hack to associate lookup with the table view so that we can do multi-select.
|
||||||
|
* Longer-term solution is to use same explorer Manager for all viewers.
|
||||||
|
*/
|
||||||
|
if (!this.lookupSet) {
|
||||||
|
List <DataResultViewer> resultViewers = this.dataResultPanel.getViewers();
|
||||||
|
for (DataResultViewer viewer : resultViewers) {
|
||||||
|
if (viewer instanceof DataResultViewerTable) {
|
||||||
|
associateLookup(ExplorerUtils.createLookup(((DataResultViewerTable)viewer).getExplorerManager(), getActionMap()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lookupSet = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
|||||||
ov.setAllowedDropActions(DnDConstants.ACTION_NONE);
|
ov.setAllowedDropActions(DnDConstants.ACTION_NONE);
|
||||||
|
|
||||||
// only allow one item to be selected at a time
|
// only allow one item to be selected at a time
|
||||||
ov.getOutline().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
ov.getOutline().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||||
|
|
||||||
// don't show the root node
|
// don't show the root node
|
||||||
ov.getOutline().setRootVisible(false);
|
ov.getOutline().setRootVisible(false);
|
||||||
|
@ -144,6 +144,10 @@ public class MediaViewImagePanel extends javax.swing.JPanel {
|
|||||||
try {
|
try {
|
||||||
//original input stream
|
//original input stream
|
||||||
BufferedImage bi = ImageIO.read(inputStream);
|
BufferedImage bi = ImageIO.read(inputStream);
|
||||||
|
if (bi == null) {
|
||||||
|
logger.log(Level.WARNING, "Could image reader not found for file: " + fileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
//scale image using Scalr
|
//scale image using Scalr
|
||||||
BufferedImage biScaled = ScalrWrapper.resizeHighQuality(bi, (int) dims.getWidth(), (int) dims.getHeight());
|
BufferedImage biScaled = ScalrWrapper.resizeHighQuality(bi, (int) dims.getWidth(), (int) dims.getHeight());
|
||||||
//convert from awt imageto fx image
|
//convert from awt imageto fx image
|
||||||
|
@ -86,6 +86,9 @@ class ThumbnailViewNode extends FilterNode {
|
|||||||
if (getFile(content.getId()).exists()) {
|
if (getFile(content.getId()).exists()) {
|
||||||
try {
|
try {
|
||||||
icon = ImageIO.read(getFile(content.getId()));
|
icon = ImageIO.read(getFile(content.getId()));
|
||||||
|
if (icon == null) {
|
||||||
|
icon = ThumbnailViewNode.defaultIcon;
|
||||||
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
icon = ThumbnailViewNode.defaultIcon;
|
icon = ThumbnailViewNode.defaultIcon;
|
||||||
}
|
}
|
||||||
@ -120,6 +123,10 @@ class ThumbnailViewNode extends FilterNode {
|
|||||||
try {
|
try {
|
||||||
inputStream = new ReadContentInputStream(content);
|
inputStream = new ReadContentInputStream(content);
|
||||||
BufferedImage bi = ImageIO.read(inputStream);
|
BufferedImage bi = ImageIO.read(inputStream);
|
||||||
|
if (bi == null) {
|
||||||
|
logger.log(Level.WARNING, "No image reader for file: " + content.getName());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
BufferedImage biScaled = ScalrWrapper.resizeFast(bi, 100, 100);
|
BufferedImage biScaled = ScalrWrapper.resizeFast(bi, 100, 100);
|
||||||
return biScaled;
|
return biScaled;
|
||||||
}catch (OutOfMemoryError e) {
|
}catch (OutOfMemoryError e) {
|
||||||
|
@ -19,12 +19,17 @@
|
|||||||
|
|
||||||
package org.sleuthkit.autopsy.coreutils;
|
package org.sleuthkit.autopsy.coreutils;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class contains the framework to read, add, update, and remove
|
* This class contains the framework to read, add, update, and remove
|
||||||
* from the property files located at %USERDIR%/Config/x.properties
|
* from the property files located at %USERDIR%/Config/x.properties
|
||||||
@ -33,15 +38,12 @@ public class ModuleSettings {
|
|||||||
|
|
||||||
// The directory where the properties file is lcoated
|
// The directory where the properties file is lcoated
|
||||||
private final static String moduleDirPath = PlatformUtil.getUserConfigDirectory();
|
private final static String moduleDirPath = PlatformUtil.getUserConfigDirectory();
|
||||||
public static final String MAIN_SETTINGS="Case";
|
public static final String DEFAULT_CONTEXT = "GeneralContext";
|
||||||
|
public static final String MAIN_SETTINGS = "Case";
|
||||||
|
|
||||||
|
|
||||||
/** the constructor */
|
/** the constructor */
|
||||||
private ModuleSettings() {
|
private ModuleSettings() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a new config file of the specified name. Do not include the extension.
|
* Makes a new config file of the specified name. Do not include the extension.
|
||||||
* @param moduleName - The name of the config file to make
|
* @param moduleName - The name of the config file to make
|
||||||
@ -161,9 +163,7 @@ public class ModuleSettings {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the given properties file to the given setting map.
|
* Sets the given properties file to the given setting map.
|
||||||
* @param moduleName - The name of the module to be written to.
|
* @param moduleName - The name of the module to be written to.
|
||||||
@ -215,14 +215,12 @@ public class ModuleSettings {
|
|||||||
Logger.getLogger(ModuleSettings.class.getName()).log(Level.WARNING, "Property file exists for [" + moduleName + "] at [" + getPropertyPath(moduleName) + "] but could not be loaded.", e);
|
Logger.getLogger(ModuleSettings.class.getName()).log(Level.WARNING, "Property file exists for [" + moduleName + "] at [" + getPropertyPath(moduleName) + "] but could not be loaded.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the given key from the given properties file.
|
* Removes the given key from the given properties file.
|
||||||
* @param moduleName - The name of the properties file to be modified.
|
* @param moduleName - The name of the properties file to be modified.
|
||||||
* @param key - the name of the key to remove.
|
* @param key - the name of the key to remove.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static synchronized void removeProperty(String moduleName, String key){
|
public static synchronized void removeProperty(String moduleName, String key){
|
||||||
try{
|
try{
|
||||||
if(getConfigSetting(moduleName, key) != null){
|
if(getConfigSetting(moduleName, key) != null){
|
||||||
@ -268,5 +266,4 @@ public class ModuleSettings {
|
|||||||
return new File(getPropertyPath(moduleName));
|
return new File(getPropertyPath(moduleName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
194
Core/src/org/sleuthkit/autopsy/datamodel/DirectoryNode.java
Normal file → Executable file
194
Core/src/org/sleuthkit/autopsy/datamodel/DirectoryNode.java
Normal file → Executable file
@ -1,97 +1,97 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2011 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
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.TagAction;
|
import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.Directory;
|
import org.sleuthkit.datamodel.Directory;
|
||||||
import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
|
import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is used to represent the "Node" for the directory. Its children
|
* This class is used to represent the "Node" for the directory. Its children
|
||||||
* are more directories.
|
* are more directories.
|
||||||
*/
|
*/
|
||||||
public class DirectoryNode extends AbstractFsContentNode<AbstractFile> {
|
public class DirectoryNode extends AbstractFsContentNode<AbstractFile> {
|
||||||
|
|
||||||
public static final String DOTDOTDIR = "[parent folder]";
|
public static final String DOTDOTDIR = "[parent folder]";
|
||||||
public static final String DOTDIR = "[current folder]";
|
public static final String DOTDIR = "[current folder]";
|
||||||
|
|
||||||
public DirectoryNode(Directory dir) {
|
public DirectoryNode(Directory dir) {
|
||||||
this(dir, true);
|
this(dir, true);
|
||||||
|
|
||||||
setIcon(dir);
|
setIcon(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectoryNode(AbstractFile dir, boolean directoryBrowseMode) {
|
public DirectoryNode(AbstractFile dir, boolean directoryBrowseMode) {
|
||||||
super(dir, directoryBrowseMode);
|
super(dir, directoryBrowseMode);
|
||||||
|
|
||||||
setIcon(dir);
|
setIcon(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setIcon(AbstractFile dir) {
|
private void setIcon(AbstractFile dir) {
|
||||||
// set name, display name, and icon
|
// set name, display name, and icon
|
||||||
if (dir.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
|
if (dir.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-deleted.png");
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-deleted.png");
|
||||||
} else {
|
} else {
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/Folder-icon.png");
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/Folder-icon.png");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Right click action for this node
|
* Right click action for this node
|
||||||
*
|
*
|
||||||
* @param popup
|
* @param popup
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Action[] getActions(boolean popup) {
|
public Action[] getActions(boolean popup) {
|
||||||
List<Action> actions = new ArrayList<Action>();
|
List<Action> actions = new ArrayList<>();
|
||||||
if (!getDirectoryBrowseMode()) {
|
if (!getDirectoryBrowseMode()) {
|
||||||
actions.add(new ViewContextAction("View File in Directory", this));
|
actions.add(new ViewContextAction("View File in Directory", this));
|
||||||
actions.add(null); // creates a menu separator
|
actions.add(null); // creates a menu separator
|
||||||
}
|
}
|
||||||
actions.add(new NewWindowViewAction("View in New Window", this));
|
actions.add(new NewWindowViewAction("View in New Window", this));
|
||||||
actions.add(null); // creates a menu separator
|
actions.add(null); // creates a menu separator
|
||||||
actions.add(new ExtractAction("Extract Directory", this));
|
actions.add(ExtractAction.getInstance());
|
||||||
actions.add(null); // creates a menu separator
|
actions.add(null); // creates a menu separator
|
||||||
actions.add(new TagAction(this));
|
actions.add(TagAbstractFileAction.getInstance());
|
||||||
return actions.toArray(new Action[0]);
|
return actions.toArray(new Action[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(ContentNodeVisitor<T> v) {
|
public <T> T accept(ContentNodeVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TYPE getDisplayableItemNodeType() {
|
public TYPE getDisplayableItemNodeType() {
|
||||||
return TYPE.CONTENT;
|
return TYPE.CONTENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
361
Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java
Normal file → Executable file
361
Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java
Normal file → Executable file
@ -1,181 +1,180 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2011 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.HashSearchAction;
|
import org.sleuthkit.autopsy.directorytree.HashSearchAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.TagAction;
|
import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.FsContent;
|
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
|
||||||
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
|
import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
|
||||||
import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
|
|
||||||
|
/**
|
||||||
/**
|
* This class is used to represent the "Node" for the file. It may have derived
|
||||||
* This class is used to represent the "Node" for the file. It may have derived
|
* files children.
|
||||||
* files children.
|
*/
|
||||||
*/
|
public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
||||||
public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
|
||||||
|
/**
|
||||||
/**
|
* @param file underlying Content
|
||||||
* @param file underlying Content
|
*/
|
||||||
*/
|
public FileNode(AbstractFile file) {
|
||||||
public FileNode(AbstractFile file) {
|
this(file, true);
|
||||||
this(file, true);
|
|
||||||
|
setIcon(file);
|
||||||
setIcon(file);
|
}
|
||||||
}
|
|
||||||
|
public FileNode(AbstractFile file, boolean directoryBrowseMode) {
|
||||||
public FileNode(AbstractFile file, boolean directoryBrowseMode) {
|
super(file, directoryBrowseMode);
|
||||||
super(file, directoryBrowseMode);
|
|
||||||
|
setIcon(file);
|
||||||
setIcon(file);
|
}
|
||||||
}
|
|
||||||
|
private void setIcon(AbstractFile file) {
|
||||||
private void setIcon(AbstractFile file) {
|
// set name, display name, and icon
|
||||||
// set name, display name, and icon
|
if (file.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
|
||||||
if (file.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
|
if (file.getType().equals(TSK_DB_FILES_TYPE_ENUM.CARVED)) {
|
||||||
if (file.getType().equals(TSK_DB_FILES_TYPE_ENUM.CARVED)) {
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/carved-file-icon-16.png");
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/carved-file-icon-16.png");
|
} else {
|
||||||
} else {
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png");
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png");
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
this.setIconBaseWithExtension(getIconForFileType(file));
|
||||||
this.setIconBaseWithExtension(getIconForFileType(file));
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Right click action for this node
|
||||||
* Right click action for this node
|
*
|
||||||
*
|
* @param popup
|
||||||
* @param popup
|
* @return
|
||||||
* @return
|
*/
|
||||||
*/
|
@Override
|
||||||
@Override
|
public Action[] getActions(boolean popup) {
|
||||||
public Action[] getActions(boolean popup) {
|
List<Action> actionsList = new ArrayList<>();
|
||||||
List<Action> actionsList = new ArrayList<Action>();
|
if (!this.getDirectoryBrowseMode()) {
|
||||||
if (!this.getDirectoryBrowseMode()) {
|
actionsList.add(new ViewContextAction("View File in Directory", this));
|
||||||
actionsList.add(new ViewContextAction("View File in Directory", this));
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(null); // creates a menu separator
|
}
|
||||||
}
|
actionsList.add(new NewWindowViewAction("View in New Window", this));
|
||||||
actionsList.add(new NewWindowViewAction("View in New Window", this));
|
actionsList.add(new ExternalViewerAction("Open in External Viewer", this));
|
||||||
actionsList.add(new ExternalViewerAction("Open in External Viewer", this));
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(new ExtractAction("Extract File", this));
|
actionsList.add(new HashSearchAction("Search for files with the same MD5 hash", this));
|
||||||
actionsList.add(new HashSearchAction("Search for files with the same MD5 hash", this));
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(TagAbstractFileAction.getInstance());
|
||||||
actionsList.add(new TagAction(this));
|
return actionsList.toArray(new Action[0]);
|
||||||
return actionsList.toArray(new Action[0]);
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
public <T> T accept(ContentNodeVisitor< T> v) {
|
||||||
public <T> T accept(ContentNodeVisitor< T> v) {
|
return v.visit(this);
|
||||||
return v.visit(this);
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
public <T> T accept(DisplayableItemNodeVisitor< T> v) {
|
||||||
public <T> T accept(DisplayableItemNodeVisitor< T> v) {
|
return v.visit(this);
|
||||||
return v.visit(this);
|
}
|
||||||
}
|
|
||||||
|
// Given a file, returns the correct icon for said
|
||||||
// Given a file, returns the correct icon for said
|
// file based off it's extension
|
||||||
// file based off it's extension
|
static String getIconForFileType(AbstractFile file) {
|
||||||
static String getIconForFileType(AbstractFile file) {
|
// Get the name, extension
|
||||||
// Get the name, extension
|
String name = file.getName();
|
||||||
String name = file.getName();
|
int dotIndex = name.lastIndexOf(".");
|
||||||
int dotIndex = name.lastIndexOf(".");
|
if (dotIndex == -1) {
|
||||||
if (dotIndex == -1) {
|
return "org/sleuthkit/autopsy/images/file-icon.png";
|
||||||
return "org/sleuthkit/autopsy/images/file-icon.png";
|
}
|
||||||
}
|
String ext = name.substring(dotIndex).toLowerCase();
|
||||||
String ext = name.substring(dotIndex).toLowerCase();
|
|
||||||
|
// Images
|
||||||
// Images
|
for (String s : FileTypeExtensions.getImageExtensions()) {
|
||||||
for (String s : FileTypeExtensions.getImageExtensions()) {
|
if (ext.equals(s)) {
|
||||||
if (ext.equals(s)) {
|
return "org/sleuthkit/autopsy/images/image-file.png";
|
||||||
return "org/sleuthkit/autopsy/images/image-file.png";
|
}
|
||||||
}
|
}
|
||||||
}
|
// Videos
|
||||||
// Videos
|
for (String s : FileTypeExtensions.getVideoExtensions()) {
|
||||||
for (String s : FileTypeExtensions.getVideoExtensions()) {
|
if (ext.equals(s)) {
|
||||||
if (ext.equals(s)) {
|
return "org/sleuthkit/autopsy/images/video-file.png";
|
||||||
return "org/sleuthkit/autopsy/images/video-file.png";
|
}
|
||||||
}
|
}
|
||||||
}
|
// Audio Files
|
||||||
// Audio Files
|
for (String s : FileTypeExtensions.getAudioExtensions()) {
|
||||||
for (String s : FileTypeExtensions.getAudioExtensions()) {
|
if (ext.equals(s)) {
|
||||||
if (ext.equals(s)) {
|
return "org/sleuthkit/autopsy/images/audio-file.png";
|
||||||
return "org/sleuthkit/autopsy/images/audio-file.png";
|
}
|
||||||
}
|
}
|
||||||
}
|
// Documents
|
||||||
// Documents
|
for (String s : FileTypeExtensions.getDocumentExtensions()) {
|
||||||
for (String s : FileTypeExtensions.getDocumentExtensions()) {
|
if (ext.equals(s)) {
|
||||||
if (ext.equals(s)) {
|
return "org/sleuthkit/autopsy/images/doc-file.png";
|
||||||
return "org/sleuthkit/autopsy/images/doc-file.png";
|
}
|
||||||
}
|
}
|
||||||
}
|
// Executables / System Files
|
||||||
// Executables / System Files
|
for (String s : FileTypeExtensions.getExecutableExtensions()) {
|
||||||
for (String s : FileTypeExtensions.getExecutableExtensions()) {
|
if (ext.equals(s)) {
|
||||||
if (ext.equals(s)) {
|
return "org/sleuthkit/autopsy/images/exe-file.png";
|
||||||
return "org/sleuthkit/autopsy/images/exe-file.png";
|
}
|
||||||
}
|
}
|
||||||
}
|
// Text Files
|
||||||
// Text Files
|
for (String s : FileTypeExtensions.getTextExtensions()) {
|
||||||
for (String s : FileTypeExtensions.getTextExtensions()) {
|
if (ext.equals(s)) {
|
||||||
if (ext.equals(s)) {
|
return "org/sleuthkit/autopsy/images/text-file.png";
|
||||||
return "org/sleuthkit/autopsy/images/text-file.png";
|
}
|
||||||
}
|
}
|
||||||
}
|
// Web Files
|
||||||
// Web Files
|
for (String s : FileTypeExtensions.getWebExtensions()) {
|
||||||
for (String s : FileTypeExtensions.getWebExtensions()) {
|
if (ext.equals(s)) {
|
||||||
if (ext.equals(s)) {
|
return "org/sleuthkit/autopsy/images/web-file.png";
|
||||||
return "org/sleuthkit/autopsy/images/web-file.png";
|
}
|
||||||
}
|
}
|
||||||
}
|
// PDFs
|
||||||
// PDFs
|
for (String s : FileTypeExtensions.getPDFExtensions()) {
|
||||||
for (String s : FileTypeExtensions.getPDFExtensions()) {
|
if (ext.equals(s)) {
|
||||||
if (ext.equals(s)) {
|
return "org/sleuthkit/autopsy/images/pdf-file.png";
|
||||||
return "org/sleuthkit/autopsy/images/pdf-file.png";
|
}
|
||||||
}
|
}
|
||||||
}
|
// Archives
|
||||||
// Archives
|
for (String s : FileTypeExtensions.getArchiveExtensions()) {
|
||||||
for (String s : FileTypeExtensions.getArchiveExtensions()) {
|
if (ext.equals(s)) {
|
||||||
if (ext.equals(s)) {
|
return "org/sleuthkit/autopsy/images/archive-file.png";
|
||||||
return "org/sleuthkit/autopsy/images/archive-file.png";
|
}
|
||||||
}
|
}
|
||||||
}
|
// Else return the default
|
||||||
// Else return the default
|
return "org/sleuthkit/autopsy/images/file-icon.png";
|
||||||
return "org/sleuthkit/autopsy/images/file-icon.png";
|
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
public TYPE getDisplayableItemNodeType() {
|
||||||
public TYPE getDisplayableItemNodeType() {
|
return TYPE.CONTENT;
|
||||||
return TYPE.CONTENT;
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
public boolean isLeafTypeNode() {
|
||||||
public boolean isLeafTypeNode() {
|
return true; //false;
|
||||||
return true; //false;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -24,11 +24,10 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExplorerNodeActionVisitor;
|
|
||||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.TagAction;
|
import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction;
|
||||||
import org.sleuthkit.datamodel.LayoutFile;
|
import org.sleuthkit.datamodel.LayoutFile;
|
||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
@ -104,14 +103,12 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
|
|||||||
@Override
|
@Override
|
||||||
public Action[] getActions(boolean context) {
|
public Action[] getActions(boolean context) {
|
||||||
List<Action> actionsList = new ArrayList<Action>();
|
List<Action> actionsList = new ArrayList<Action>();
|
||||||
|
|
||||||
actionsList.add(new NewWindowViewAction("View in New Window", this));
|
actionsList.add(new NewWindowViewAction("View in New Window", this));
|
||||||
actionsList.add(new ExternalViewerAction("Open in External Viewer", this));
|
actionsList.add(new ExternalViewerAction("Open in External Viewer", this));
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new ExtractAction("Extract File", content));
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new TagAction(content));
|
actionsList.add(TagAbstractFileAction.getInstance());
|
||||||
|
|
||||||
return actionsList.toArray(new Action[0]);
|
return actionsList.toArray(new Action[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,9 +30,8 @@ import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
|||||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.HashSearchAction;
|
import org.sleuthkit.autopsy.directorytree.HashSearchAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.TagAction;
|
import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.LocalFile;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Node for a LocalFile or DerivedFile content object.
|
* A Node for a LocalFile or DerivedFile content object.
|
||||||
@ -86,16 +85,14 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Action[] getActions(boolean context) {
|
public Action[] getActions(boolean context) {
|
||||||
List<Action> actionsList = new ArrayList<Action>();
|
List<Action> actionsList = new ArrayList<>();
|
||||||
|
|
||||||
actionsList.add(new NewWindowViewAction("View in New Window", this));
|
actionsList.add(new NewWindowViewAction("View in New Window", this));
|
||||||
actionsList.add(new ExternalViewerAction("Open in External Viewer", this));
|
actionsList.add(new ExternalViewerAction("Open in External Viewer", this));
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new ExtractAction("Extract", content)); //might not need this actions - already local file
|
actionsList.add(ExtractAction.getInstance());
|
||||||
actionsList.add(new HashSearchAction("Search for files with the same MD5 hash", this));
|
actionsList.add(new HashSearchAction("Search for files with the same MD5 hash", this));
|
||||||
actionsList.add(null); // creates a menu separator
|
actionsList.add(null); // creates a menu separator
|
||||||
actionsList.add(new TagAction(content));
|
actionsList.add(TagAbstractFileAction.getInstance());
|
||||||
|
|
||||||
return actionsList.toArray(new Action[0]);
|
return actionsList.toArray(new Action[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ import java.awt.event.ActionEvent;
|
|||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -656,36 +655,4 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
return tagNames;
|
return tagNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Taggable {
|
|
||||||
void createTag(String name, String comment);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TaggableFile implements Taggable {
|
|
||||||
|
|
||||||
private AbstractFile file;
|
|
||||||
|
|
||||||
public TaggableFile(AbstractFile file) {
|
|
||||||
this.file = file;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void createTag(String name, String comment) {
|
|
||||||
Tags.createTag(file, name, comment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TaggableBlackboardArtifact implements Taggable {
|
|
||||||
|
|
||||||
private BlackboardArtifact bba;
|
|
||||||
|
|
||||||
public TaggableBlackboardArtifact(BlackboardArtifact bba) {
|
|
||||||
this.bba = bba;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void createTag(String name, String comment) {
|
|
||||||
Tags.createTag(bba, name, comment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import org.openide.nodes.Sheet;
|
|||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
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.TagAction;
|
import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction;
|
||||||
import org.sleuthkit.datamodel.VirtualDirectory;
|
import org.sleuthkit.datamodel.VirtualDirectory;
|
||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
@ -76,16 +76,15 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirect
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Action[] getActions(boolean popup) {
|
public Action[] getActions(boolean popup) {
|
||||||
List<Action> actions = new ArrayList<Action>();
|
List<Action> actions = new ArrayList<>();
|
||||||
|
|
||||||
actions.add(new NewWindowViewAction("View in New Window", this));
|
actions.add(new NewWindowViewAction("View in New Window", this));
|
||||||
actions.add(null); // creates a menu separator
|
actions.add(null); // creates a menu separator
|
||||||
actions.add(new ExtractAction("Extract Directory", this));
|
actions.add(ExtractAction.getInstance());
|
||||||
actions.add(null); // creates a menu separator
|
actions.add(null); // creates a menu separator
|
||||||
actions.add(new TagAction(this));
|
actions.add(TagAbstractFileAction.getInstance());
|
||||||
return actions.toArray(new Action[0]);
|
return actions.toArray(new Action[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Sheet createSheet() {
|
protected Sheet createSheet() {
|
||||||
Sheet s = super.createSheet();
|
Sheet s = super.createSheet();
|
||||||
|
1038
Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java
Normal file → Executable file
1038
Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
317
Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java
Normal file → Executable file
317
Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java
Normal file → Executable file
@ -1,160 +1,159 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2011 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.directorytree;
|
package org.sleuthkit.autopsy.directorytree;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import org.openide.nodes.FilterNode;
|
import org.openide.nodes.FilterNode;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.openide.util.lookup.ProxyLookup;
|
import org.openide.util.lookup.ProxyLookup;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.AbstractContentNode;
|
import org.sleuthkit.autopsy.datamodel.AbstractContentNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestDialog;
|
import org.sleuthkit.autopsy.ingest.IngestDialog;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.Directory;
|
import org.sleuthkit.datamodel.Directory;
|
||||||
import org.sleuthkit.datamodel.Image;
|
import org.sleuthkit.datamodel.Image;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class sets the actions for the nodes in the directory tree and creates
|
* This class sets the actions for the nodes in the directory tree and creates
|
||||||
* the children filter so that files and such are hidden from the tree.
|
* the children filter so that files and such are hidden from the tree.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class DirectoryTreeFilterNode extends FilterNode {
|
class DirectoryTreeFilterNode extends FilterNode {
|
||||||
|
|
||||||
private static final Action collapseAll = new CollapseAction("Collapse All");
|
private static final Action collapseAll = new CollapseAction("Collapse All");
|
||||||
private static final Logger logger = Logger.getLogger(DirectoryTreeFilterNode.class.getName());
|
private static final Logger logger = Logger.getLogger(DirectoryTreeFilterNode.class.getName());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the constructor
|
* the constructor
|
||||||
*/
|
*/
|
||||||
DirectoryTreeFilterNode(Node arg, boolean createChildren) {
|
DirectoryTreeFilterNode(Node arg, boolean createChildren) {
|
||||||
super(arg, DirectoryTreeFilterChildren.createInstance(arg, createChildren),
|
super(arg, DirectoryTreeFilterChildren.createInstance(arg, createChildren),
|
||||||
new ProxyLookup(Lookups.singleton(new OriginalNode(arg)),
|
new ProxyLookup(Lookups.singleton(new OriginalNode(arg)),
|
||||||
arg.getLookup()));
|
arg.getLookup()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDisplayName() {
|
public String getDisplayName() {
|
||||||
final Node orig = getOriginal();
|
final Node orig = getOriginal();
|
||||||
|
|
||||||
String name = orig.getDisplayName();
|
String name = orig.getDisplayName();
|
||||||
|
|
||||||
//do not show children counts for non content nodes
|
//do not show children counts for non content nodes
|
||||||
if (orig instanceof AbstractContentNode) {
|
if (orig instanceof AbstractContentNode) {
|
||||||
//show only for file content nodes
|
//show only for file content nodes
|
||||||
AbstractFile file = getLookup().lookup(AbstractFile.class);
|
AbstractFile file = getLookup().lookup(AbstractFile.class);
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
try {
|
try {
|
||||||
final int numChildren = file.getChildrenCount();
|
final int numChildren = file.getChildrenCount();
|
||||||
name = name + " (" + numChildren + ")";
|
name = name + " (" + numChildren + ")";
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, "Error getting children count to display for file: " + file, ex);
|
logger.log(Level.SEVERE, "Error getting children count to display for file: " + file, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Right click action for the nodes in the directory tree.
|
* Right click action for the nodes in the directory tree.
|
||||||
*
|
*
|
||||||
* @param popup
|
* @param popup
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Action[] getActions(boolean popup) {
|
public Action[] getActions(boolean popup) {
|
||||||
List<Action> actions = new ArrayList<Action>();
|
List<Action> actions = new ArrayList<Action>();
|
||||||
|
|
||||||
final Content content = this.getLookup().lookup(Content.class);
|
final Content content = this.getLookup().lookup(Content.class);
|
||||||
if (content != null) {
|
if (content != null) {
|
||||||
actions.addAll(DirectoryTreeFilterNode.getDetailActions(content));
|
actions.addAll(DirectoryTreeFilterNode.getDetailActions(content));
|
||||||
|
|
||||||
//extract dir action
|
//extract dir action
|
||||||
Directory dir = this.getLookup().lookup(Directory.class);
|
Directory dir = this.getLookup().lookup(Directory.class);
|
||||||
if (dir != null) {
|
if (dir != null) {
|
||||||
actions.add(new ExtractAction("Extract Directory",
|
actions.add(ExtractAction.getInstance());
|
||||||
getOriginal()));
|
}
|
||||||
}
|
|
||||||
|
// file search action
|
||||||
// file search action
|
final Image img = this.getLookup().lookup(Image.class);
|
||||||
final Image img = this.getLookup().lookup(Image.class);
|
if (img != null) {
|
||||||
if (img != null) {
|
actions.add(new FileSearchAction("Open File Search by Attributes"));
|
||||||
actions.add(new FileSearchAction("Open File Search by Attributes"));
|
}
|
||||||
}
|
|
||||||
|
//ingest action
|
||||||
//ingest action
|
actions.add(new AbstractAction("Run Ingest Modules") {
|
||||||
actions.add(new AbstractAction("Run Ingest Modules") {
|
@Override
|
||||||
@Override
|
public void actionPerformed(ActionEvent e) {
|
||||||
public void actionPerformed(ActionEvent e) {
|
final IngestDialog ingestDialog = new IngestDialog();
|
||||||
final IngestDialog ingestDialog = new IngestDialog();
|
ingestDialog.setContent(Collections.<Content>singletonList(content));
|
||||||
ingestDialog.setContent(Collections.<Content>singletonList(content));
|
ingestDialog.display();
|
||||||
ingestDialog.display();
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
//check if delete actions should be added
|
||||||
//check if delete actions should be added
|
final Node orig = getOriginal();
|
||||||
final Node orig = getOriginal();
|
//TODO add a mechanism to determine if DisplayableItemNode
|
||||||
//TODO add a mechanism to determine if DisplayableItemNode
|
if (orig instanceof DisplayableItemNode) {
|
||||||
if (orig instanceof DisplayableItemNode) {
|
actions.addAll(getDeleteActions((DisplayableItemNode) orig));
|
||||||
actions.addAll(getDeleteActions((DisplayableItemNode) orig));
|
}
|
||||||
}
|
|
||||||
|
actions.add(collapseAll);
|
||||||
actions.add(collapseAll);
|
return actions.toArray(new Action[actions.size()]);
|
||||||
return actions.toArray(new Action[actions.size()]);
|
}
|
||||||
}
|
|
||||||
|
private static List<Action> getDeleteActions(DisplayableItemNode original) {
|
||||||
private static List<Action> getDeleteActions(DisplayableItemNode original) {
|
List<Action> actions = new ArrayList<Action>();
|
||||||
List<Action> actions = new ArrayList<Action>();
|
//actions.addAll(original.accept(getDeleteActionVisitor));
|
||||||
//actions.addAll(original.accept(getDeleteActionVisitor));
|
return actions;
|
||||||
return actions;
|
}
|
||||||
}
|
|
||||||
|
private static List<Action> getDetailActions(Content c) {
|
||||||
private static List<Action> getDetailActions(Content c) {
|
List<Action> actions = new ArrayList<Action>();
|
||||||
List<Action> actions = new ArrayList<Action>();
|
|
||||||
|
actions.addAll(ExplorerNodeActionVisitor.getActions(c));
|
||||||
actions.addAll(ExplorerNodeActionVisitor.getActions(c));
|
|
||||||
|
return actions;
|
||||||
return actions;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
class OriginalNode {
|
||||||
class OriginalNode {
|
|
||||||
|
private Node original;
|
||||||
private Node original;
|
|
||||||
|
OriginalNode(Node original) {
|
||||||
OriginalNode(Node original) {
|
this.original = original;
|
||||||
this.original = original;
|
}
|
||||||
}
|
|
||||||
|
Node getNode() {
|
||||||
Node getNode() {
|
return original;
|
||||||
return original;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
764
Core/src/org/sleuthkit/autopsy/directorytree/ExplorerNodeActionVisitor.java
Normal file → Executable file
764
Core/src/org/sleuthkit/autopsy/directorytree/ExplorerNodeActionVisitor.java
Normal file → Executable file
@ -1,383 +1,383 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2011 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.directorytree;
|
package org.sleuthkit.autopsy.directorytree;
|
||||||
|
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
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.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.table.DefaultTableModel;
|
import javax.swing.table.DefaultTableModel;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.ContentVisitor;
|
import org.sleuthkit.datamodel.ContentVisitor;
|
||||||
import org.sleuthkit.datamodel.DerivedFile;
|
import org.sleuthkit.datamodel.DerivedFile;
|
||||||
import org.sleuthkit.datamodel.Directory;
|
import org.sleuthkit.datamodel.Directory;
|
||||||
import org.sleuthkit.datamodel.FileSystem;
|
import org.sleuthkit.datamodel.FileSystem;
|
||||||
import org.sleuthkit.datamodel.Image;
|
import org.sleuthkit.datamodel.Image;
|
||||||
import org.sleuthkit.datamodel.LocalFile;
|
import org.sleuthkit.datamodel.LocalFile;
|
||||||
import org.sleuthkit.datamodel.VirtualDirectory;
|
import org.sleuthkit.datamodel.VirtualDirectory;
|
||||||
import org.sleuthkit.datamodel.Volume;
|
import org.sleuthkit.datamodel.Volume;
|
||||||
|
|
||||||
public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? extends Action>> {
|
public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? extends Action>> {
|
||||||
|
|
||||||
private static ExplorerNodeActionVisitor instance = new ExplorerNodeActionVisitor();
|
private static ExplorerNodeActionVisitor instance = new ExplorerNodeActionVisitor();
|
||||||
|
|
||||||
public static List<Action> getActions(Content c) {
|
public static List<Action> getActions(Content c) {
|
||||||
List<Action> actions = new ArrayList<Action>();
|
List<Action> actions = new ArrayList<Action>();
|
||||||
|
|
||||||
actions.addAll(c.accept(instance));
|
actions.addAll(c.accept(instance));
|
||||||
//TODO: fix this
|
//TODO: fix this
|
||||||
/*
|
/*
|
||||||
while (c.isOnto()) {
|
while (c.isOnto()) {
|
||||||
try {
|
try {
|
||||||
List<? extends Content> children = c.getChildren();
|
List<? extends Content> children = c.getChildren();
|
||||||
if (!children.isEmpty()) {
|
if (!children.isEmpty()) {
|
||||||
c = c.getChildren().get(0);
|
c = c.getChildren().get(0);
|
||||||
} else {
|
} else {
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
Log.get(ExplorerNodeActionVisitor.class).log(Level.WARNING, "Error getting show detail actions.", ex);
|
Log.get(ExplorerNodeActionVisitor.class).log(Level.WARNING, "Error getting show detail actions.", ex);
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
actions.addAll(c.accept(instance));
|
actions.addAll(c.accept(instance));
|
||||||
}*/
|
}*/
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExplorerNodeActionVisitor() {
|
ExplorerNodeActionVisitor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<? extends Action> visit(final Image img) {
|
public List<? extends Action> visit(final Image img) {
|
||||||
List<Action> lst = new ArrayList<Action>();
|
List<Action> lst = new ArrayList<Action>();
|
||||||
lst.add(new ImageDetails("Image Details", img));
|
lst.add(new ImageDetails("Image Details", img));
|
||||||
//TODO lst.add(new ExtractAction("Extract Image", img));
|
//TODO lst.add(new ExtractAction("Extract Image", img));
|
||||||
lst.add(new ExtractUnallocAction("Extract Unallocated Space to Single Files", img));
|
lst.add(new ExtractUnallocAction("Extract Unallocated Space to Single Files", img));
|
||||||
return lst;
|
return lst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<? extends Action> visit(final FileSystem fs) {
|
public List<? extends Action> visit(final FileSystem fs) {
|
||||||
return Collections.singletonList(new FileSystemDetails("File System Details", fs));
|
return Collections.singletonList(new FileSystemDetails("File System Details", fs));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<? extends Action> visit(final Volume vol) {
|
public List<? extends Action> visit(final Volume vol) {
|
||||||
List<AbstractAction> lst = new ArrayList<AbstractAction>();
|
List<AbstractAction> lst = new ArrayList<AbstractAction>();
|
||||||
lst.add(new VolumeDetails("Volume Details", vol));
|
lst.add(new VolumeDetails("Volume Details", vol));
|
||||||
lst.add(new ExtractUnallocAction("Extract Unallocated Space to Single File", vol));
|
lst.add(new ExtractUnallocAction("Extract Unallocated Space to Single File", vol));
|
||||||
return lst;
|
return lst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<? extends Action> visit(final Directory d) {
|
public List<? extends Action> visit(final Directory d) {
|
||||||
List<Action> actions = new ArrayList<Action>();
|
List<Action> actions = new ArrayList<Action>();
|
||||||
actions.add(new TagAction(d));
|
actions.add(TagAbstractFileAction.getInstance());
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<? extends Action> visit(final VirtualDirectory d) {
|
public List<? extends Action> visit(final VirtualDirectory d) {
|
||||||
List<Action> actions = new ArrayList<Action>();
|
List<Action> actions = new ArrayList<Action>();
|
||||||
actions.add(new TagAction(d));
|
actions.add(ExtractAction.getInstance());
|
||||||
actions.add(new ExtractAction("Extract Directory", d));
|
actions.add(TagAbstractFileAction.getInstance());
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<? extends Action> visit(final DerivedFile d) {
|
public List<? extends Action> visit(final DerivedFile d) {
|
||||||
List<Action> actions = new ArrayList<Action>();
|
List<Action> actions = new ArrayList<Action>();
|
||||||
actions.add(new ExtractAction("Extract File", d));
|
actions.add(ExtractAction.getInstance());
|
||||||
actions.add(new TagAction(d));
|
actions.add(TagAbstractFileAction.getInstance());
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<? extends Action> visit(final LocalFile d) {
|
public List<? extends Action> visit(final LocalFile d) {
|
||||||
List<Action> actions = new ArrayList<Action>();
|
List<Action> actions = new ArrayList<Action>();
|
||||||
actions.add(new ExtractAction("Extract File", d));
|
actions.add(ExtractAction.getInstance());
|
||||||
actions.add(new TagAction(d));
|
actions.add(TagAbstractFileAction.getInstance());
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<? extends Action> visit(final org.sleuthkit.datamodel.File d) {
|
public List<? extends Action> visit(final org.sleuthkit.datamodel.File d) {
|
||||||
List<Action> actions = new ArrayList<Action>();
|
List<Action> actions = new ArrayList<Action>();
|
||||||
actions.add(new ExtractAction("Extract File", d));
|
actions.add(ExtractAction.getInstance());
|
||||||
actions.add(new TagAction(d));
|
actions.add(TagAbstractFileAction.getInstance());
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<? extends Action> defaultVisit(Content di) {
|
protected List<? extends Action> defaultVisit(Content di) {
|
||||||
return Collections.<Action>emptyList();
|
return Collections.<Action>emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Below here are classes regarding node-specific actions
|
//Below here are classes regarding node-specific actions
|
||||||
/**
|
/**
|
||||||
* VolumeDetails class
|
* VolumeDetails class
|
||||||
*/
|
*/
|
||||||
private class VolumeDetails extends AbstractAction {
|
private class VolumeDetails extends AbstractAction {
|
||||||
|
|
||||||
private final String title;
|
private final String title;
|
||||||
private final Volume vol;
|
private final Volume vol;
|
||||||
|
|
||||||
VolumeDetails(String title, Volume vol) {
|
VolumeDetails(String title, Volume vol) {
|
||||||
super(title);
|
super(title);
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.vol = vol;
|
this.vol = vol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
Logger.noteAction(ExplorerNodeActionVisitor.class);
|
Logger.noteAction(ExplorerNodeActionVisitor.class);
|
||||||
|
|
||||||
final JFrame frame = new JFrame(title);
|
final JFrame frame = new JFrame(title);
|
||||||
final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
|
final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
|
||||||
|
|
||||||
|
|
||||||
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||||
|
|
||||||
// set the popUp window / JFrame
|
// set the popUp window / JFrame
|
||||||
popUpWindow.setSize(800, 400);
|
popUpWindow.setSize(800, 400);
|
||||||
|
|
||||||
int w = popUpWindow.getSize().width;
|
int w = popUpWindow.getSize().width;
|
||||||
int h = popUpWindow.getSize().height;
|
int h = popUpWindow.getSize().height;
|
||||||
|
|
||||||
// set the location of the popUp Window on the center of the screen
|
// set the location of the popUp Window on the center of the screen
|
||||||
popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
||||||
|
|
||||||
VolumeDetailsPanel volumeDetailPanel = new VolumeDetailsPanel();
|
VolumeDetailsPanel volumeDetailPanel = new VolumeDetailsPanel();
|
||||||
Boolean counter = false;
|
Boolean counter = false;
|
||||||
|
|
||||||
volumeDetailPanel.setVolumeIDValue(Long.toString(vol.getAddr()));
|
volumeDetailPanel.setVolumeIDValue(Long.toString(vol.getAddr()));
|
||||||
volumeDetailPanel.setStartValue(Long.toString(vol.getStart()));
|
volumeDetailPanel.setStartValue(Long.toString(vol.getStart()));
|
||||||
volumeDetailPanel.setLengthValue(Long.toString(vol.getLength()));
|
volumeDetailPanel.setLengthValue(Long.toString(vol.getLength()));
|
||||||
volumeDetailPanel.setDescValue(vol.getDescription());
|
volumeDetailPanel.setDescValue(vol.getDescription());
|
||||||
volumeDetailPanel.setFlagsValue(vol.getFlagsAsString());
|
volumeDetailPanel.setFlagsValue(vol.getFlagsAsString());
|
||||||
counter = true;
|
counter = true;
|
||||||
|
|
||||||
if (counter) {
|
if (counter) {
|
||||||
// add the volume detail panel to the popUp window
|
// add the volume detail panel to the popUp window
|
||||||
popUpWindow.add(volumeDetailPanel);
|
popUpWindow.add(volumeDetailPanel);
|
||||||
} else {
|
} else {
|
||||||
// error handler if no volume matches
|
// error handler if no volume matches
|
||||||
JLabel error = new JLabel("Error: No Volume Matches.");
|
JLabel error = new JLabel("Error: No Volume Matches.");
|
||||||
error.setFont(new Font("Arial", Font.BOLD, 24));
|
error.setFont(new Font("Arial", Font.BOLD, 24));
|
||||||
popUpWindow.add(error);
|
popUpWindow.add(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the command to close the window to the button on the Volume Detail Panel
|
// add the command to close the window to the button on the Volume Detail Panel
|
||||||
volumeDetailPanel.setOKButtonActionListener(new ActionListener() {
|
volumeDetailPanel.setOKButtonActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
popUpWindow.dispose();
|
popUpWindow.dispose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
popUpWindow.pack();
|
popUpWindow.pack();
|
||||||
popUpWindow.setResizable(false);
|
popUpWindow.setResizable(false);
|
||||||
popUpWindow.setVisible(true);
|
popUpWindow.setVisible(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageDetails panel class
|
* ImageDetails panel class
|
||||||
*/
|
*/
|
||||||
private class ImageDetails extends AbstractAction {
|
private class ImageDetails extends AbstractAction {
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
final Image img;
|
final Image img;
|
||||||
|
|
||||||
ImageDetails(String title, Image img) {
|
ImageDetails(String title, Image img) {
|
||||||
super(title);
|
super(title);
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.img = img;
|
this.img = img;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
Logger.noteAction(ExplorerNodeActionVisitor.class);
|
Logger.noteAction(ExplorerNodeActionVisitor.class);
|
||||||
|
|
||||||
final JFrame frame = new JFrame(title);
|
final JFrame frame = new JFrame(title);
|
||||||
final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
|
final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
|
||||||
// if we select the Image Details menu
|
// if we select the Image Details menu
|
||||||
|
|
||||||
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||||
|
|
||||||
// set the popUp window / JFrame
|
// set the popUp window / JFrame
|
||||||
popUpWindow.setSize(750, 400);
|
popUpWindow.setSize(750, 400);
|
||||||
|
|
||||||
int w = popUpWindow.getSize().width;
|
int w = popUpWindow.getSize().width;
|
||||||
int h = popUpWindow.getSize().height;
|
int h = popUpWindow.getSize().height;
|
||||||
|
|
||||||
// set the location of the popUp Window on the center of the screen
|
// set the location of the popUp Window on the center of the screen
|
||||||
popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
||||||
|
|
||||||
ImageDetailsPanel imgDetailPanel = new ImageDetailsPanel();
|
ImageDetailsPanel imgDetailPanel = new ImageDetailsPanel();
|
||||||
Boolean counter = false;
|
Boolean counter = false;
|
||||||
|
|
||||||
imgDetailPanel.setImgNameValue(img.getName());
|
imgDetailPanel.setImgNameValue(img.getName());
|
||||||
imgDetailPanel.setImgTypeValue(Image.imageTypeToString(img.getType()));
|
imgDetailPanel.setImgTypeValue(Image.imageTypeToString(img.getType()));
|
||||||
imgDetailPanel.setImgSectorSizeValue(Long.toString(img.getSsize()));
|
imgDetailPanel.setImgSectorSizeValue(Long.toString(img.getSsize()));
|
||||||
counter = true;
|
counter = true;
|
||||||
|
|
||||||
if (counter) {
|
if (counter) {
|
||||||
// add the volume detail panel to the popUp window
|
// add the volume detail panel to the popUp window
|
||||||
popUpWindow.add(imgDetailPanel);
|
popUpWindow.add(imgDetailPanel);
|
||||||
} else {
|
} else {
|
||||||
// error handler if no volume matches
|
// error handler if no volume matches
|
||||||
JLabel error = new JLabel("Error: No Volume Matches.");
|
JLabel error = new JLabel("Error: No Volume Matches.");
|
||||||
error.setFont(new Font("Arial", Font.BOLD, 24));
|
error.setFont(new Font("Arial", Font.BOLD, 24));
|
||||||
popUpWindow.add(error);
|
popUpWindow.add(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the command to close the window to the button on the Volume Detail Panel
|
// add the command to close the window to the button on the Volume Detail Panel
|
||||||
imgDetailPanel.setOKButtonActionListener(new ActionListener() {
|
imgDetailPanel.setOKButtonActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
popUpWindow.dispose();
|
popUpWindow.dispose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
popUpWindow.pack();
|
popUpWindow.pack();
|
||||||
popUpWindow.setResizable(false);
|
popUpWindow.setResizable(false);
|
||||||
popUpWindow.setVisible(true);
|
popUpWindow.setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FileSystemDetails class
|
* FileSystemDetails class
|
||||||
*/
|
*/
|
||||||
private class FileSystemDetails extends AbstractAction {
|
private class FileSystemDetails extends AbstractAction {
|
||||||
|
|
||||||
private final FileSystem fs;
|
private final FileSystem fs;
|
||||||
private final String title;
|
private final String title;
|
||||||
|
|
||||||
FileSystemDetails(String title, FileSystem fs) {
|
FileSystemDetails(String title, FileSystem fs) {
|
||||||
super(title);
|
super(title);
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.fs = fs;
|
this.fs = fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||||
|
|
||||||
Logger.noteAction(ExplorerNodeActionVisitor.class);
|
Logger.noteAction(ExplorerNodeActionVisitor.class);
|
||||||
|
|
||||||
final JFrame frame = new JFrame(title);
|
final JFrame frame = new JFrame(title);
|
||||||
final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
|
final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
|
||||||
|
|
||||||
// set the popUp window / JFrame
|
// set the popUp window / JFrame
|
||||||
|
|
||||||
popUpWindow.setSize(1000, 500);
|
popUpWindow.setSize(1000, 500);
|
||||||
|
|
||||||
int w = popUpWindow.getSize().width;
|
int w = popUpWindow.getSize().width;
|
||||||
int h = popUpWindow.getSize().height;
|
int h = popUpWindow.getSize().height;
|
||||||
|
|
||||||
// set the location of the popUp Window on the center of the screen
|
// set the location of the popUp Window on the center of the screen
|
||||||
popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
||||||
|
|
||||||
String[] columnNames = new String[]{
|
String[] columnNames = new String[]{
|
||||||
"fs_id",
|
"fs_id",
|
||||||
"img_offset",
|
"img_offset",
|
||||||
"par_id",
|
"par_id",
|
||||||
"fs_type",
|
"fs_type",
|
||||||
"block_size",
|
"block_size",
|
||||||
"block_count",
|
"block_count",
|
||||||
"root_inum",
|
"root_inum",
|
||||||
"first_inum",
|
"first_inum",
|
||||||
"last_inum"
|
"last_inum"
|
||||||
};
|
};
|
||||||
|
|
||||||
Object[][] rowValues = new Object[1][9];
|
Object[][] rowValues = new Object[1][9];
|
||||||
|
|
||||||
Content parent = null;
|
Content parent = null;
|
||||||
try {
|
try {
|
||||||
parent = fs.getParent();
|
parent = fs.getParent();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new RuntimeException("Problem getting parent from " + FileSystem.class.getName() + ": " + fs, ex);
|
throw new RuntimeException("Problem getting parent from " + FileSystem.class.getName() + ": " + fs, ex);
|
||||||
}
|
}
|
||||||
long id = -1;
|
long id = -1;
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
id = parent.getId();
|
id = parent.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
Arrays.fill(rowValues, 0, 1, new Object[]{
|
Arrays.fill(rowValues, 0, 1, new Object[]{
|
||||||
fs.getId(),
|
fs.getId(),
|
||||||
fs.getImageOffset(),
|
fs.getImageOffset(),
|
||||||
id,
|
id,
|
||||||
fs.getFsType(),
|
fs.getFsType(),
|
||||||
fs.getBlock_size(),
|
fs.getBlock_size(),
|
||||||
fs.getBlock_count(),
|
fs.getBlock_count(),
|
||||||
fs.getRoot_inum(),
|
fs.getRoot_inum(),
|
||||||
fs.getFirst_inum(),
|
fs.getFirst_inum(),
|
||||||
fs.getLastInum()
|
fs.getLastInum()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
JTable table = new JTable(new DefaultTableModel(rowValues, columnNames));
|
JTable table = new JTable(new DefaultTableModel(rowValues, columnNames));
|
||||||
|
|
||||||
FileSystemDetailsPanel fsdPanel = new FileSystemDetailsPanel();
|
FileSystemDetailsPanel fsdPanel = new FileSystemDetailsPanel();
|
||||||
|
|
||||||
// add the command to close the window to the button on the Volume Detail Panel
|
// add the command to close the window to the button on the Volume Detail Panel
|
||||||
fsdPanel.setOKButtonActionListener(new ActionListener() {
|
fsdPanel.setOKButtonActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
popUpWindow.dispose();
|
popUpWindow.dispose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fsdPanel.setFileSystemTypeValue(table.getValueAt(0, 3).toString());
|
fsdPanel.setFileSystemTypeValue(table.getValueAt(0, 3).toString());
|
||||||
fsdPanel.setImageOffsetValue(table.getValueAt(0, 1).toString());
|
fsdPanel.setImageOffsetValue(table.getValueAt(0, 1).toString());
|
||||||
fsdPanel.setVolumeIDValue(table.getValueAt(0, 2).toString()); //TODO: fix this to parent id, not vol id
|
fsdPanel.setVolumeIDValue(table.getValueAt(0, 2).toString()); //TODO: fix this to parent id, not vol id
|
||||||
fsdPanel.setBlockSizeValue(table.getValueAt(0, 4).toString());
|
fsdPanel.setBlockSizeValue(table.getValueAt(0, 4).toString());
|
||||||
fsdPanel.setBlockCountValue(table.getValueAt(0, 5).toString());
|
fsdPanel.setBlockCountValue(table.getValueAt(0, 5).toString());
|
||||||
fsdPanel.setRootInumValue(table.getValueAt(0, 6).toString());
|
fsdPanel.setRootInumValue(table.getValueAt(0, 6).toString());
|
||||||
fsdPanel.setFirstInumValue(table.getValueAt(0, 7).toString());
|
fsdPanel.setFirstInumValue(table.getValueAt(0, 7).toString());
|
||||||
fsdPanel.setLastInumValue(table.getValueAt(0, 8).toString());
|
fsdPanel.setLastInumValue(table.getValueAt(0, 8).toString());
|
||||||
|
|
||||||
popUpWindow.add(fsdPanel);
|
popUpWindow.add(fsdPanel);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.getLogger(ExplorerNodeActionVisitor.class.getName()).log(Level.WARNING, "Error setting up File System Details panel.", ex);
|
Logger.getLogger(ExplorerNodeActionVisitor.class.getName()).log(Level.WARNING, "Error setting up File System Details panel.", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
popUpWindow.pack();
|
popUpWindow.pack();
|
||||||
popUpWindow.setResizable(false);
|
popUpWindow.setResizable(false);
|
||||||
popUpWindow.setVisible(true);
|
popUpWindow.setVisible(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2013 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,7 @@ package org.sleuthkit.autopsy.directorytree;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.concurrent.CancellationException;
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
@ -30,83 +31,37 @@ import javax.swing.JOptionPane;
|
|||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
import org.netbeans.api.progress.ProgressHandle;
|
import org.netbeans.api.progress.ProgressHandle;
|
||||||
import org.netbeans.api.progress.ProgressHandleFactory;
|
import org.netbeans.api.progress.ProgressHandleFactory;
|
||||||
import org.openide.nodes.Node;
|
|
||||||
import org.openide.util.Cancellable;
|
import org.openide.util.Cancellable;
|
||||||
|
import org.openide.util.Utilities;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.FileUtil;
|
import org.sleuthkit.autopsy.coreutils.FileUtil;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.Content;
|
|
||||||
import org.sleuthkit.datamodel.ContentVisitor;
|
|
||||||
import org.sleuthkit.datamodel.Directory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exports files and folders
|
* Exports files and folders
|
||||||
*/
|
*/
|
||||||
public final class ExtractAction extends AbstractAction {
|
public final class ExtractAction extends AbstractAction {
|
||||||
|
|
||||||
private static final InitializeContentVisitor initializeCV = new InitializeContentVisitor();
|
|
||||||
private AbstractFile content;
|
|
||||||
private Logger logger = Logger.getLogger(ExtractAction.class.getName());
|
private Logger logger = Logger.getLogger(ExtractAction.class.getName());
|
||||||
|
|
||||||
public ExtractAction(String title, Node contentNode) {
|
// This class is a singleton to support multi-selection of nodes, since
|
||||||
super(title);
|
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
|
||||||
Content tempContent = contentNode.getLookup().lookup(Content.class);
|
// node in the array returns a reference to the same action object from Node.getActions(boolean).
|
||||||
|
private static ExtractAction instance;
|
||||||
|
|
||||||
this.content = tempContent.accept(initializeCV);
|
public static synchronized ExtractAction getInstance() {
|
||||||
this.setEnabled(content != null);
|
if (null == instance) {
|
||||||
}
|
instance = new ExtractAction();
|
||||||
|
}
|
||||||
public ExtractAction(String title, Content content) {
|
|
||||||
super(title);
|
|
||||||
|
|
||||||
this.content = content.accept(initializeCV);
|
return instance;
|
||||||
this.setEnabled(this.content != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private ExtractAction() {
|
||||||
* Returns the FsContent if it is supported, otherwise null
|
super("Extract");
|
||||||
*/
|
|
||||||
private static class InitializeContentVisitor extends ContentVisitor.Default<AbstractFile> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractFile visit(org.sleuthkit.datamodel.File f) {
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractFile visit(org.sleuthkit.datamodel.LayoutFile lf) {
|
|
||||||
return lf;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractFile visit(org.sleuthkit.datamodel.DerivedFile df) {
|
|
||||||
return df;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractFile visit(org.sleuthkit.datamodel.LocalFile lf) {
|
|
||||||
return lf;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractFile visit(org.sleuthkit.datamodel.VirtualDirectory vd) {
|
|
||||||
return vd;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractFile visit(Directory dir) {
|
|
||||||
return ContentUtils.isDotDirectory(dir) ? null : dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbstractFile defaultVisit(Content cntnt) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks user to choose destination, then extracts content/directory to
|
* Asks user to choose destination, then extracts content/directory to
|
||||||
* destination (recursing on directories)
|
* destination (recursing on directories)
|
||||||
@ -114,10 +69,17 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
Collection<? extends AbstractFile> selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class);
|
||||||
|
for (AbstractFile file : selectedFiles) {
|
||||||
|
extractFile(e, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void extractFile(ActionEvent e, AbstractFile file) {
|
||||||
// Get content and check that it's okay to overwrite existing content
|
// Get content and check that it's okay to overwrite existing content
|
||||||
JFileChooser fc = new JFileChooser();
|
JFileChooser fc = new JFileChooser();
|
||||||
fc.setCurrentDirectory(new File(Case.getCurrentCase().getCaseDirectory()));
|
fc.setCurrentDirectory(new File(Case.getCurrentCase().getCaseDirectory()));
|
||||||
fc.setSelectedFile(new File(this.content.getName()));
|
fc.setSelectedFile(new File(file.getName()));
|
||||||
int returnValue = fc.showSaveDialog((Component) e.getSource());
|
int returnValue = fc.showSaveDialog((Component) e.getSource());
|
||||||
|
|
||||||
if (returnValue == JFileChooser.APPROVE_OPTION) {
|
if (returnValue == JFileChooser.APPROVE_OPTION) {
|
||||||
@ -144,12 +106,12 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
ExtractFileThread extract = new ExtractFileThread();
|
ExtractFileThread extract = new ExtractFileThread();
|
||||||
extract.init(this.content, e, destination);
|
extract.init(file, e, destination);
|
||||||
extract.execute();
|
extract.execute();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.log(Level.WARNING, "Unable to start background thread.", ex);
|
logger.log(Level.WARNING, "Unable to start background thread.", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExtractFileThread extends SwingWorker<Object,Void> {
|
private class ExtractFileThread extends SwingWorker<Object,Void> {
|
||||||
@ -230,6 +192,5 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
70
Core/src/org/sleuthkit/autopsy/directorytree/TagAbstractFileAction.java
Executable file
70
Core/src/org/sleuthkit/autopsy/directorytree/TagAbstractFileAction.java
Executable file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2013 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.util.Collection;
|
||||||
|
import javax.swing.AbstractAction;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
import org.openide.util.Utilities;
|
||||||
|
import org.openide.util.actions.Presenter;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
|
public class TagAbstractFileAction extends AbstractAction implements Presenter.Popup {
|
||||||
|
// 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 TagAbstractFileAction instance;
|
||||||
|
|
||||||
|
public static synchronized TagAbstractFileAction getInstance() {
|
||||||
|
if (null == instance) {
|
||||||
|
instance = new TagAbstractFileAction();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TagAbstractFileAction() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JMenuItem getPopupPresenter() {
|
||||||
|
return new TagAbstractFileMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
// Do nothing - this action should never be performed.
|
||||||
|
// Submenu actions are invoked instead.
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TagAbstractFileMenu extends TagMenu {
|
||||||
|
public TagAbstractFileMenu() {
|
||||||
|
super(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class).size() > 1 ? "Tag Files" : "Tag File");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applyTag(String tagName, String comment) {
|
||||||
|
Collection<? extends AbstractFile> selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class);
|
||||||
|
for (AbstractFile file : selectedFiles) {
|
||||||
|
Tags.createTag(file, tagName, comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
* Autopsy Forensic Browser
|
|
||||||
*
|
|
||||||
* Copyright 2013 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.util.logging.Level;
|
|
||||||
import javax.swing.AbstractAction;
|
|
||||||
import javax.swing.JMenu;
|
|
||||||
import javax.swing.JMenuItem;
|
|
||||||
import org.openide.nodes.Node;
|
|
||||||
import org.openide.util.actions.Presenter;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
|
||||||
import org.sleuthkit.datamodel.Content;
|
|
||||||
import org.sleuthkit.datamodel.ContentVisitor;
|
|
||||||
import org.sleuthkit.datamodel.Directory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action on a file or artifact that adds a tag and
|
|
||||||
* reloads the directory tree. Supports tagging of AbstractFiles and
|
|
||||||
* BlackboardArtifacts.
|
|
||||||
*
|
|
||||||
* TODO add use enters description and hierarchy (TSK_TAG_NAME with slashes)
|
|
||||||
*/
|
|
||||||
public class TagAction extends AbstractAction implements Presenter.Popup {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(TagAction.class.getName());
|
|
||||||
private JMenu tagMenu;
|
|
||||||
private final InitializeBookmarkFileV initializer = new InitializeBookmarkFileV();
|
|
||||||
|
|
||||||
public TagAction(Node contentNode) {
|
|
||||||
AbstractFile file = contentNode.getLookup().lookup(AbstractFile.class);
|
|
||||||
if (file != null) {
|
|
||||||
tagMenu = new TagMenu(file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlackboardArtifact bba = contentNode.getLookup().lookup(BlackboardArtifact.class);
|
|
||||||
if (bba != null) {
|
|
||||||
tagMenu = new TagMenu(bba);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.log(Level.SEVERE, "Tried to create a " + TagAction.class.getName()
|
|
||||||
+ " using a Node whose lookup did not contain an AbstractFile or a BlackboardArtifact.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public TagAction(AbstractFile file) {
|
|
||||||
tagMenu = new TagMenu(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TagAction(BlackboardArtifact bba) {
|
|
||||||
tagMenu = new TagMenu(bba);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JMenuItem getPopupPresenter() {
|
|
||||||
return tagMenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the FsContent if it is supported, otherwise null
|
|
||||||
*/
|
|
||||||
private static class InitializeBookmarkFileV extends ContentVisitor.Default<AbstractFile> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractFile visit(org.sleuthkit.datamodel.File f) {
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractFile visit(org.sleuthkit.datamodel.LayoutFile lf) {
|
|
||||||
return lf;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractFile visit(org.sleuthkit.datamodel.DerivedFile lf) {
|
|
||||||
return lf;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractFile visit(org.sleuthkit.datamodel.LocalFile lf) {
|
|
||||||
return lf;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractFile visit(org.sleuthkit.datamodel.VirtualDirectory ld) {
|
|
||||||
return ld;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractFile visit(Directory dir) {
|
|
||||||
return ContentUtils.isDotDirectory(dir) ? null : dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbstractFile defaultVisit(Content cntnt) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
// Do nothing - this action should never be performed
|
|
||||||
// Submenu actions are invoked instead
|
|
||||||
}
|
|
||||||
}
|
|
@ -30,28 +30,50 @@ import javax.swing.JFrame;
|
|||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
import org.openide.windows.WindowManager;
|
import org.openide.windows.WindowManager;
|
||||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||||
import org.sleuthkit.autopsy.datamodel.Tags.Taggable;
|
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tag dialog for tagging files and results. User enters an optional comment.
|
* Tag dialog for tagging files and results. User enters an optional comment.
|
||||||
*/
|
*/
|
||||||
public class TagAndCommentDialog extends JDialog {
|
public class TagAndCommentDialog extends JDialog {
|
||||||
|
|
||||||
private static final String TAG_ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png";
|
private static final String NO_TAG_MESSAGE = "No Tags";
|
||||||
private static final String BOOKMARK_ICON_PATH = "org/sleuthkit/autopsy/images/star-bookmark-icon-16.png";
|
private String tagName = "";
|
||||||
private static final String NO_TAG_MESSAGE = "No Tags";
|
private String comment = "";
|
||||||
|
|
||||||
private Taggable taggable;
|
|
||||||
|
|
||||||
|
public static class CommentedTag {
|
||||||
|
private String name;
|
||||||
|
private String comment;
|
||||||
|
|
||||||
|
CommentedTag(String name, String comment) {
|
||||||
|
this.name = name;
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommentedTag doDialog() {
|
||||||
|
TagAndCommentDialog dialog = new TagAndCommentDialog();
|
||||||
|
if (!dialog.tagName.isEmpty()) {
|
||||||
|
return new CommentedTag(dialog.tagName, dialog.comment);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form TagDialog
|
* Creates new form TagDialog
|
||||||
*/
|
*/
|
||||||
public TagAndCommentDialog(Taggable taggable) {
|
private TagAndCommentDialog() {
|
||||||
super((JFrame)WindowManager.getDefault().getMainWindow(), "Tag and Comment", true);
|
super((JFrame)WindowManager.getDefault().getMainWindow(), "Tag and Comment", true);
|
||||||
|
|
||||||
this.taggable = taggable;
|
|
||||||
|
|
||||||
initComponents();
|
initComponents();
|
||||||
|
|
||||||
// Close the dialog when Esc is pressed
|
// Close the dialog when Esc is pressed
|
||||||
@ -60,8 +82,8 @@ public class TagAndCommentDialog extends JDialog {
|
|||||||
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName);
|
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName);
|
||||||
ActionMap actionMap = getRootPane().getActionMap();
|
ActionMap actionMap = getRootPane().getActionMap();
|
||||||
actionMap.put(cancelName, new AbstractAction() {
|
actionMap.put(cancelName, new AbstractAction() {
|
||||||
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
//doClose(RET_CANCEL);
|
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -81,15 +103,10 @@ public class TagAndCommentDialog extends JDialog {
|
|||||||
|
|
||||||
//center it
|
//center it
|
||||||
this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
||||||
|
|
||||||
customizeComponent();
|
|
||||||
|
|
||||||
setVisible(true); // blocks
|
setVisible(true); // blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
private void customizeComponent() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from within the constructor to initialize the form.
|
* This method is called from within the constructor to initialize the form.
|
||||||
* WARNING: Do NOT modify this code. The content of this method is always
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
@ -195,22 +212,12 @@ public class TagAndCommentDialog extends JDialog {
|
|||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||||
//doClose(RET_OK);
|
tagName = (String)tagCombo.getSelectedItem();
|
||||||
|
comment = commentText.getText();
|
||||||
// get the selected tag and comment
|
|
||||||
String selectedTag = (String)tagCombo.getSelectedItem();
|
|
||||||
String comment = commentText.getText();
|
|
||||||
|
|
||||||
// create the tag
|
|
||||||
taggable.createTag(selectedTag, comment);
|
|
||||||
|
|
||||||
refreshDirectoryTree();
|
|
||||||
|
|
||||||
dispose();
|
dispose();
|
||||||
}//GEN-LAST:event_okButtonActionPerformed
|
}//GEN-LAST:event_okButtonActionPerformed
|
||||||
|
|
||||||
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||||
//doClose(RET_CANCEL);
|
|
||||||
dispose();
|
dispose();
|
||||||
}//GEN-LAST:event_cancelButtonActionPerformed
|
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||||
|
|
||||||
@ -218,14 +225,12 @@ public class TagAndCommentDialog extends JDialog {
|
|||||||
* Closes the dialog
|
* Closes the dialog
|
||||||
*/
|
*/
|
||||||
private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
|
private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
|
||||||
//doClose(RET_CANCEL);
|
|
||||||
dispose();
|
dispose();
|
||||||
}//GEN-LAST:event_closeDialog
|
}//GEN-LAST:event_closeDialog
|
||||||
|
|
||||||
private void newTagButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagButtonActionPerformed
|
private void newTagButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagButtonActionPerformed
|
||||||
String newTagName = CreateTagDialog.getNewTagNameDialog(null);
|
String newTagName = CreateTagDialog.getNewTagNameDialog(null);
|
||||||
if (newTagName != null) {
|
if (newTagName != null) {
|
||||||
//tagsModel.addElement(newTagName);
|
|
||||||
tagCombo.addItem(newTagName);
|
tagCombo.addItem(newTagName);
|
||||||
tagCombo.setSelectedItem(newTagName);
|
tagCombo.setSelectedItem(newTagName);
|
||||||
}
|
}
|
||||||
@ -240,12 +245,4 @@ public class TagAndCommentDialog extends JDialog {
|
|||||||
private javax.swing.JComboBox tagCombo;
|
private javax.swing.JComboBox tagCombo;
|
||||||
private javax.swing.JLabel tagLabel;
|
private javax.swing.JLabel tagLabel;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
//private int returnStatus = RET_CANCEL;
|
|
||||||
|
|
||||||
private void refreshDirectoryTree() {
|
|
||||||
//TODO instead should send event to node children, which will call its refresh() / refreshKeys()
|
|
||||||
DirectoryTreeTopComponent viewer = DirectoryTreeTopComponent.findInstance();
|
|
||||||
viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE);
|
|
||||||
viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2013 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.util.Collection;
|
||||||
|
import javax.swing.AbstractAction;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
import org.openide.util.Utilities;
|
||||||
|
import org.openide.util.actions.Presenter;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
|
||||||
|
public class TagBlackboardArtifactAction extends AbstractAction implements Presenter.Popup {
|
||||||
|
// 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 TagBlackboardArtifactAction instance;
|
||||||
|
|
||||||
|
public static synchronized TagBlackboardArtifactAction getInstance() {
|
||||||
|
if (null == instance) {
|
||||||
|
instance = new TagBlackboardArtifactAction();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TagBlackboardArtifactAction() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JMenuItem getPopupPresenter() {
|
||||||
|
return new TagBlackboardArtifactMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
// Do nothing - this action should never be performed.
|
||||||
|
// Submenu actions are invoked instead.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class TagBlackboardArtifactMenu extends TagMenu {
|
||||||
|
public TagBlackboardArtifactMenu() {
|
||||||
|
super(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class).size() > 1 ? "Tag Results" : "Tag Result");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applyTag(String tagName, String comment) {
|
||||||
|
Collection<? extends BlackboardArtifact> selectedArtifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
|
||||||
|
for (BlackboardArtifact artifact : selectedArtifacts) {
|
||||||
|
Tags.createTag(artifact, tagName, comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -24,38 +24,20 @@ import java.util.List;
|
|||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||||
import org.sleuthkit.autopsy.datamodel.Tags.Taggable;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.Tags.TaggableBlackboardArtifact;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.Tags.TaggableFile;
|
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The menu that results when one right-clicks on a file or artifact.
|
* The menu that results when one right-clicks on a file or artifact.
|
||||||
*/
|
*/
|
||||||
public class TagMenu extends JMenu {
|
public abstract class TagMenu extends JMenu {
|
||||||
|
public TagMenu(String menuItemText) {
|
||||||
private Taggable tagCreator;
|
super(menuItemText);
|
||||||
|
|
||||||
public TagMenu(AbstractFile file) {
|
|
||||||
super("Tag File");
|
|
||||||
tagCreator = new TaggableFile(file);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TagMenu(BlackboardArtifact bba) {
|
|
||||||
super("Tag Result");
|
|
||||||
tagCreator = new TaggableBlackboardArtifact(bba);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
// Create the 'Quick Tag' sub-menu and add it to the tag menu.
|
||||||
|
|
||||||
// create the 'Quick Tag' menu and add it to the 'Tag File' menu
|
|
||||||
JMenu quickTagMenu = new JMenu("Quick Tag");
|
JMenu quickTagMenu = new JMenu("Quick Tag");
|
||||||
add(quickTagMenu);
|
add(quickTagMenu);
|
||||||
|
|
||||||
// create the 'Quick Tag' sub-menu items and add them to the 'Quick Tag' menu
|
// Get the existing tag names.
|
||||||
List<String> tagNames = Tags.getTagNames();
|
List<String> tagNames = Tags.getTagNames();
|
||||||
if (tagNames.isEmpty()) {
|
if (tagNames.isEmpty()) {
|
||||||
JMenuItem empty = new JMenuItem("No tags");
|
JMenuItem empty = new JMenuItem("No tags");
|
||||||
@ -63,50 +45,56 @@ public class TagMenu extends JMenu {
|
|||||||
quickTagMenu.add(empty);
|
quickTagMenu.add(empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a menu item for each existing tag name to the 'Quick Tag' menu.
|
||||||
for (final String tagName : tagNames) {
|
for (final String tagName : tagNames) {
|
||||||
JMenuItem tagItem = new JMenuItem(tagName);
|
JMenuItem tagNameItem = new JMenuItem(tagName);
|
||||||
tagItem.addActionListener(new ActionListener() {
|
tagNameItem.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
tagCreator.createTag(tagName, "");
|
applyTag(tagName, "");
|
||||||
refreshDirectoryTree();
|
refreshDirectoryTree();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
quickTagMenu.add(tagItem);
|
quickTagMenu.add(tagNameItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
quickTagMenu.addSeparator();
|
quickTagMenu.addSeparator();
|
||||||
|
|
||||||
// create the 'New Tag' menu item
|
// Create the 'New Tag' menu item and add it to the 'Quick Tag' menu.
|
||||||
JMenuItem newTagMenuItem = new JMenuItem("New Tag");
|
JMenuItem newTagMenuItem = new JMenuItem("New Tag");
|
||||||
newTagMenuItem.addActionListener(new ActionListener() {
|
newTagMenuItem.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
String newTagName = CreateTagDialog.getNewTagNameDialog(null);
|
String tagName = CreateTagDialog.getNewTagNameDialog(null);
|
||||||
if (newTagName != null) {
|
if (tagName != null) {
|
||||||
tagCreator.createTag(newTagName, "");
|
applyTag(tagName, "");
|
||||||
refreshDirectoryTree();
|
refreshDirectoryTree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// add the 'New Tag' menu item to the 'Quick Tag' menu
|
|
||||||
quickTagMenu.add(newTagMenuItem);
|
quickTagMenu.add(newTagMenuItem);
|
||||||
|
|
||||||
JMenuItem newTagItem = new JMenuItem("Tag and Comment");
|
// Create the 'Tag and Comment' menu item and add it to the tag menu.
|
||||||
newTagItem.addActionListener(new ActionListener() {
|
JMenuItem tagAndCommentItem = new JMenuItem("Tag and Comment");
|
||||||
|
tagAndCommentItem.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
new TagAndCommentDialog(tagCreator);
|
TagAndCommentDialog.CommentedTag commentedTag = TagAndCommentDialog.doDialog();
|
||||||
|
if (null != commentedTag) {
|
||||||
|
applyTag(commentedTag.getName(), commentedTag.getComment());
|
||||||
|
refreshDirectoryTree();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
add(newTagItem);
|
add(tagAndCommentItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshDirectoryTree() {
|
private void refreshDirectoryTree() {
|
||||||
//TODO instead should send event to node children, which will call its refresh() / refreshKeys()
|
//TODO instead should send event to node children, which will call its refresh() / refreshKeys()
|
||||||
DirectoryTreeTopComponent viewer = DirectoryTreeTopComponent.findInstance();
|
DirectoryTreeTopComponent viewer = DirectoryTreeTopComponent.findInstance();
|
||||||
viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE);
|
viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE);
|
||||||
viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT);
|
viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void applyTag(String tagName, String comment);
|
||||||
}
|
}
|
||||||
|
125
Core/src/org/sleuthkit/autopsy/examples/SampleDataSourceIngestModule.java
Executable file
125
Core/src/org/sleuthkit/autopsy/examples/SampleDataSourceIngestModule.java
Executable file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* Sample module in the public domain. Feel free to use this as a template
|
||||||
|
* for your modules.
|
||||||
|
*
|
||||||
|
* Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
|
||||||
|
*
|
||||||
|
* This is free and unencumbered software released into the public domain.
|
||||||
|
*
|
||||||
|
* Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
* distribute this software, either in source code form or as a compiled
|
||||||
|
* binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
* means.
|
||||||
|
*
|
||||||
|
* In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
* of this software dedicate any and all copyright interest in the
|
||||||
|
* software to the public domain. We make this dedication for the benefit
|
||||||
|
* of the public at large and to the detriment of our heirs and
|
||||||
|
* successors. We intend this dedication to be an overt act of
|
||||||
|
* relinquishment in perpetuity of all present and future rights to this
|
||||||
|
* software under copyright law.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.sleuthkit.autopsy.examples;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.openide.util.Exceptions;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.services.Services;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestDataSourceWorkerController;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleDataSource;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
|
import org.sleuthkit.autopsy.ingest.PipelineContext;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
import org.sleuthkit.datamodel.FsContent;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sample DataSource-level ingest module that doesn't do much at all.
|
||||||
|
* Just exists to show basic idea of these modules
|
||||||
|
*/
|
||||||
|
public class SampleDataSourceIngestModule extends org.sleuthkit.autopsy.ingest.IngestModuleDataSource {
|
||||||
|
|
||||||
|
/* Data Source modules operate on a disk or set of logical files. They
|
||||||
|
* are passed in teh data source refernce and query it for things they want.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void process(PipelineContext<IngestModuleDataSource> pipelineContext, Content dataSource, IngestDataSourceWorkerController controller) {
|
||||||
|
|
||||||
|
Case case1 = Case.getCurrentCase();
|
||||||
|
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
|
||||||
|
|
||||||
|
Services services = new Services(sleuthkitCase);
|
||||||
|
FileManager fm = services.getFileManager();
|
||||||
|
try {
|
||||||
|
/* you can use the findFiles method in FileManager (or similar ones in
|
||||||
|
* SleuthkitCase to find files based only on their name. This
|
||||||
|
* one finds files that have a .doc extension. */
|
||||||
|
List<AbstractFile> docFiles = fm.findFiles(dataSource, "%.doc");
|
||||||
|
for (AbstractFile file : docFiles) {
|
||||||
|
// do something with each doc file
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We can also do more general queries with findFilesWhere, which
|
||||||
|
* allows us to make our own WHERE clause in the database.
|
||||||
|
*/
|
||||||
|
long currentTime = System.currentTimeMillis()/1000;
|
||||||
|
// go back 2 weeks
|
||||||
|
long minTime = currentTime - (14 * 24 * 60 * 60);
|
||||||
|
List<FsContent> otherFiles = sleuthkitCase.findFilesWhere("crtime > " + minTime);
|
||||||
|
// do something with these files...
|
||||||
|
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
Logger log = Logger.getLogger(SampleDataSourceIngestModule.class);
|
||||||
|
log.fatal("Error retrieving files from database: " + ex.getLocalizedMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(IngestModuleInit initContext) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void complete() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "SampleDataSourceIngestModule";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getVersion() {
|
||||||
|
return "1.0";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Doesn't do much";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasBackgroundJobsRunning() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
178
Core/src/org/sleuthkit/autopsy/examples/SampleFileIngestModule.java
Executable file
178
Core/src/org/sleuthkit/autopsy/examples/SampleFileIngestModule.java
Executable file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* Sample module in the public domain. Feel free to use this as a template
|
||||||
|
* for your modules.
|
||||||
|
*
|
||||||
|
* Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
|
||||||
|
*
|
||||||
|
* This is free and unencumbered software released into the public domain.
|
||||||
|
*
|
||||||
|
* Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
* distribute this software, either in source code form or as a compiled
|
||||||
|
* binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
* means.
|
||||||
|
*
|
||||||
|
* In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
* of this software dedicate any and all copyright interest in the
|
||||||
|
* software to the public domain. We make this dedication for the benefit
|
||||||
|
* of the public at large and to the detriment of our heirs and
|
||||||
|
* successors. We intend this dedication to be an overt act of
|
||||||
|
* relinquishment in perpetuity of all present and future rights to this
|
||||||
|
* software under copyright law.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.sleuthkit.autopsy.examples;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.openide.util.Exceptions;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
|
import org.sleuthkit.autopsy.ingest.PipelineContext;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a sample and simple module. It is a file-level ingest module, meaning
|
||||||
|
* that it will get called on each file in the disk image / logical file set.
|
||||||
|
* It does a stupid calculation of the number of null bytes in the beginning of the
|
||||||
|
* file in order to show the basic flow.
|
||||||
|
*
|
||||||
|
* Autopsy has been hard coded to ignore this module based on the it's package name.
|
||||||
|
* IngestModuleLoader will not load things from the org.sleuthkit.autopsy.examples package.
|
||||||
|
* Either change the package or the loading code to make this module actually run.
|
||||||
|
*/
|
||||||
|
public class SampleFileIngestModule extends org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile {
|
||||||
|
private int attrId = -1;
|
||||||
|
private static SampleFileIngestModule defaultInstance = null;
|
||||||
|
|
||||||
|
// Private to ensure Singleton status
|
||||||
|
private SampleFileIngestModule() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// File-level ingest modules are currently singleton -- this is required
|
||||||
|
public static synchronized SampleFileIngestModule getDefault() {
|
||||||
|
//defaultInstance is a private static class variable
|
||||||
|
if (defaultInstance == null) {
|
||||||
|
defaultInstance = new SampleFileIngestModule();
|
||||||
|
}
|
||||||
|
return defaultInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(IngestModuleInit initContext) {
|
||||||
|
/* For this demo, we are going to make a private attribute to post our
|
||||||
|
* results to the blackbaord with. There are many standard blackboard artifact
|
||||||
|
* and attribute types and you should first consider using one of those before
|
||||||
|
* making private ones because other modules won't know about provate ones.
|
||||||
|
* Because our demo has results that have no real value, we do not have an
|
||||||
|
* official attribute for them.
|
||||||
|
*/
|
||||||
|
Case case1 = Case.getCurrentCase();
|
||||||
|
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
|
||||||
|
|
||||||
|
// see if the type already exists in the blackboard.
|
||||||
|
try {
|
||||||
|
attrId = sleuthkitCase.getAttrTypeID("ATTR_SAMPLE");
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
// create it if not
|
||||||
|
try {
|
||||||
|
attrId = sleuthkitCase.addAttrType("ATTR_SAMPLE", "Sample Attribute");
|
||||||
|
} catch (TskCoreException ex1) {
|
||||||
|
Logger log = Logger.getLogger(SampleFileIngestModule.class);
|
||||||
|
log.fatal("Error adding attribute type: " + ex1.getLocalizedMessage());
|
||||||
|
attrId = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessResult process(PipelineContext<IngestModuleAbstractFile> pipelineContext, AbstractFile abstractFile) {
|
||||||
|
// skip non-files
|
||||||
|
if ((abstractFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) ||
|
||||||
|
(abstractFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)) {
|
||||||
|
return ProcessResult.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip NSRL / known files
|
||||||
|
if (abstractFile.getKnown() == TskData.FileKnown.KNOWN) {
|
||||||
|
return ProcessResult.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Do a non-sensical calculation of the number of 0x00 bytes
|
||||||
|
* in the first 1024-bytes of the file. This is for demo
|
||||||
|
* purposes only.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
byte buffer[] = new byte[1024];
|
||||||
|
int len = abstractFile.read(buffer, 0, 1024);
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
if (buffer[i] == 0x00) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrId != -1) {
|
||||||
|
// Make an attribute using the ID for the private type that we previously created.
|
||||||
|
BlackboardAttribute attr = new BlackboardAttribute(attrId, getName(), count);
|
||||||
|
|
||||||
|
/* add it to the general info artifact. In real modules, you would likely have
|
||||||
|
* more complex data types and be making more specific artifacts.
|
||||||
|
*/
|
||||||
|
BlackboardArtifact art = abstractFile.getGenInfoArtifact();
|
||||||
|
art.addAttribute(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessResult.OK;
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
Exceptions.printStackTrace(ex);
|
||||||
|
return ProcessResult.ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void complete() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getVersion() {
|
||||||
|
return "1.0";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "SampleFileIngestModule";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Doesn't do much";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasBackgroundJobsRunning() {
|
||||||
|
// we're single threaded...
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2013 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");
|
||||||
@ -26,36 +26,37 @@ import java.awt.event.ActionListener;
|
|||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import org.openide.util.Lookup;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.GeneralIngestConfigurator;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.IngestConfigurator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IngestDialog shown on Case.CASE_ADD_IMAGE property change
|
* Dialog box that allows ingest modules to be run on an image.
|
||||||
|
* Used outside of the wizards.
|
||||||
*/
|
*/
|
||||||
public class IngestDialog extends JDialog {
|
public class IngestDialog extends JDialog {
|
||||||
|
|
||||||
private static final String TITLE = "Ingest Modules";
|
private static final String TITLE = "Ingest Modules";
|
||||||
private static Dimension DIMENSIONS = new Dimension(500, 300);
|
private static Dimension DIMENSIONS = new Dimension(500, 300);
|
||||||
private IngestDialogPanel panel = null;
|
private IngestConfigurator ingestConfigurator;
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(IngestDialog.class.getName());
|
|
||||||
|
|
||||||
public IngestDialog(JFrame frame, String title, boolean modal) {
|
public IngestDialog(JFrame frame, String title, boolean modal) {
|
||||||
super(frame, title, modal);
|
super(frame, title, modal);
|
||||||
panel = new IngestDialogPanel();
|
ingestConfigurator = new GeneralIngestConfigurator();
|
||||||
|
ingestConfigurator.setContext(IngestDialog.class.getCanonicalName());
|
||||||
|
ingestConfigurator.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IngestDialog(){
|
public IngestDialog(){
|
||||||
this(new JFrame(TITLE), TITLE, true);
|
this(new JFrame(TITLE), TITLE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the Ingest dialog.
|
* Shows the Ingest dialog.
|
||||||
*/
|
*/
|
||||||
@ -71,17 +72,15 @@ public class IngestDialog extends JDialog {
|
|||||||
// set the location of the popUp Window on the center of the screen
|
// set the location of the popUp Window on the center of the screen
|
||||||
setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
||||||
|
|
||||||
panel.reload(); // reload the simple panel
|
add(ingestConfigurator.getIngestConfigPanel(), BorderLayout.PAGE_START);
|
||||||
add(panel, BorderLayout.PAGE_START);
|
|
||||||
JButton startButton = new JButton("Start");
|
JButton startButton = new JButton("Start");
|
||||||
JButton closeButton = new JButton("Close");
|
JButton closeButton = new JButton("Close");
|
||||||
startButton.addActionListener(new ActionListener() {
|
startButton.addActionListener(new ActionListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
ingestConfigurator.save();
|
||||||
panel.save();
|
ingestConfigurator.start();
|
||||||
panel.start();
|
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -89,7 +88,7 @@ public class IngestDialog extends JDialog {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
panel.save();
|
ingestConfigurator.save();
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -97,7 +96,7 @@ public class IngestDialog extends JDialog {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void windowClosing(WindowEvent e) {
|
public void windowClosing(WindowEvent e) {
|
||||||
panel.save();
|
ingestConfigurator.save();
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -113,11 +112,10 @@ public class IngestDialog extends JDialog {
|
|||||||
setResizable(false);
|
setResizable(false);
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContent(List<Content> inputContent) {
|
public void setContent(List<Content> inputContent) {
|
||||||
panel.setContent(inputContent);
|
ingestConfigurator.setContent(inputContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the Ingest dialog
|
* Closes the Ingest dialog
|
||||||
@ -126,6 +124,4 @@ public class IngestDialog extends JDialog {
|
|||||||
setVisible(false);
|
setVisible(false);
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2011-2013 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -18,24 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.ingest;
|
package org.sleuthkit.autopsy.ingest;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics;
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.util.AbstractMap;
|
||||||
import java.beans.PropertyChangeListener;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.ListSelectionModel;
|
import javax.swing.ListSelectionModel;
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
@ -43,80 +34,55 @@ import javax.swing.event.ListSelectionListener;
|
|||||||
import javax.swing.table.AbstractTableModel;
|
import javax.swing.table.AbstractTableModel;
|
||||||
import javax.swing.table.DefaultTableCellRenderer;
|
import javax.swing.table.DefaultTableCellRenderer;
|
||||||
import javax.swing.table.TableColumn;
|
import javax.swing.table.TableColumn;
|
||||||
import org.openide.util.lookup.ServiceProvider;
|
|
||||||
import org.sleuthkit.autopsy.casemodule.IngestConfigurator;
|
|
||||||
import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog;
|
import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog;
|
||||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestModuleAbstract.ModuleType;
|
|
||||||
import org.sleuthkit.datamodel.Content;
|
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* main configuration panel for all ingest modules, reusable JPanel component
|
* main configuration panel for all ingest modules, reusable JPanel component
|
||||||
*/
|
*/
|
||||||
@ServiceProvider(service = IngestConfigurator.class)
|
public class IngestDialogPanel extends javax.swing.JPanel {
|
||||||
public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfigurator {
|
|
||||||
|
|
||||||
private IngestManager manager = null;
|
|
||||||
private List<IngestModuleAbstract> modules;
|
|
||||||
private IngestModuleAbstract currentModule;
|
private IngestModuleAbstract currentModule;
|
||||||
private Map<String, Boolean> moduleStates;
|
|
||||||
private ModulesTableModel tableModel;
|
private ModulesTableModel tableModel;
|
||||||
private static final Logger logger = Logger.getLogger(IngestDialogPanel.class.getName());
|
|
||||||
public static final String DISABLED_MOD = "Disabled_Ingest_Modules";
|
public static final String DISABLED_MOD = "Disabled_Ingest_Modules";
|
||||||
public static final String PARSE_UNALLOC = "Process_Unallocated_Space";
|
public static final String PARSE_UNALLOC = "Process_Unallocated_Space";
|
||||||
// The input content that's just been added to the database
|
private String context;
|
||||||
private List<Content> inputContent;
|
|
||||||
// private static IngestDialogPanel instance = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form IngestDialogPanel
|
* Creates new form IngestDialogPanel
|
||||||
*/
|
*/
|
||||||
public IngestDialogPanel() {
|
public IngestDialogPanel() {
|
||||||
tableModel = new ModulesTableModel();
|
tableModel = new ModulesTableModel();
|
||||||
modules = new ArrayList<IngestModuleAbstract>();
|
context = ModuleSettings.DEFAULT_CONTEXT;
|
||||||
moduleStates = new HashMap<String, Boolean>();
|
|
||||||
initComponents();
|
initComponents();
|
||||||
customizeComponents();
|
customizeComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setContext(String context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void loadModules() {
|
public IngestModuleAbstract getCurrentIngestModule() {
|
||||||
this.modules.clear();
|
return currentModule;
|
||||||
//this.moduleStates.clear(); maintain the state
|
}
|
||||||
Collection<IngestModuleDataSource> imageModules = manager.enumerateDataSourceModules();
|
|
||||||
for (final IngestModuleDataSource module : imageModules) {
|
public List<IngestModuleAbstract> getModulesToStart() {
|
||||||
addModule(module);
|
return tableModel.getSelectedModules();
|
||||||
}
|
}
|
||||||
Collection<IngestModuleAbstractFile> fsModules = manager.enumerateAbstractFileModules();
|
|
||||||
for (final IngestModuleAbstractFile module : fsModules) {
|
public boolean processUnallocSpaceEnabled() {
|
||||||
addModule(module);
|
return processUnallocCheckbox.isSelected();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void customizeComponents() {
|
private void customizeComponents() {
|
||||||
modulesTable.setModel(tableModel);
|
modulesTable.setModel(tableModel);
|
||||||
this.manager = IngestManager.getDefault();
|
|
||||||
|
|
||||||
loadModules();
|
|
||||||
try {
|
|
||||||
IngestModuleLoader.getDefault().addModulesReloadedListener(new PropertyChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
|
||||||
if (evt.getPropertyName().equals(IngestModuleLoader.Event.ModulesReloaded.toString())) {
|
|
||||||
loadModules();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (IngestModuleLoaderException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Could not initialize ingest module loader to listen for module config changes", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
modulesTable.setTableHeader(null);
|
modulesTable.setTableHeader(null);
|
||||||
modulesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
modulesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
|
||||||
//custom renderer for tooltips
|
//custom renderer for tooltips
|
||||||
|
|
||||||
ModulesTableRenderer renderer = new ModulesTableRenderer();
|
ModulesTableRenderer renderer = new ModulesTableRenderer();
|
||||||
|
|
||||||
//customize column witdhs
|
//customize column witdhs
|
||||||
final int width = modulesScrollPane.getPreferredSize().width;
|
final int width = modulesScrollPane.getPreferredSize().width;
|
||||||
TableColumn column = null;
|
TableColumn column = null;
|
||||||
@ -135,40 +101,30 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
public void valueChanged(ListSelectionEvent e) {
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
ListSelectionModel listSelectionModel = (ListSelectionModel) e.getSource();
|
ListSelectionModel listSelectionModel = (ListSelectionModel) e.getSource();
|
||||||
if (!listSelectionModel.isSelectionEmpty()) {
|
if (!listSelectionModel.isSelectionEmpty()) {
|
||||||
save();
|
|
||||||
int index = listSelectionModel.getMinSelectionIndex();
|
int index = listSelectionModel.getMinSelectionIndex();
|
||||||
currentModule = modules.get(index);
|
currentModule = tableModel.getModule(index);
|
||||||
reload();
|
|
||||||
|
// add the module-specific configuration panel, if there is one
|
||||||
|
simplePanel.removeAll();
|
||||||
|
if (currentModule.hasSimpleConfiguration()) {
|
||||||
|
simplePanel.add(currentModule.getSimpleConfiguration(context));
|
||||||
|
}
|
||||||
|
simplePanel.revalidate();
|
||||||
|
simplePanel.repaint();
|
||||||
advancedButton.setEnabled(currentModule.hasAdvancedConfiguration());
|
advancedButton.setEnabled(currentModule.hasAdvancedConfiguration());
|
||||||
} else {
|
} else {
|
||||||
currentModule = null;
|
currentModule = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
processUnallocCheckbox.setSelected(manager.getProcessUnallocSpace());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setProcessUnallocSpaceEnabled(boolean enabled) {
|
public void setProcessUnallocSpaceEnabled(final boolean enabled) {
|
||||||
processUnallocCheckbox.setEnabled(enabled);
|
processUnallocCheckbox.setSelected(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setDisabledModules(List<IngestModuleAbstract> disabledModules) {
|
||||||
public void paint(Graphics g) {
|
tableModel.setUnselectedModules(disabledModules);
|
||||||
super.paint(g);
|
|
||||||
if (manager.isIngestRunning()) {
|
|
||||||
setProcessUnallocSpaceEnabled(false);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
setProcessUnallocSpaceEnabled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addModule(IngestModuleAbstract module) {
|
|
||||||
final String moduleName = module.getName();
|
|
||||||
modules.add(module);
|
|
||||||
moduleStates.put(moduleName, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -311,22 +267,19 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
dialog.close();
|
dialog.close();
|
||||||
currentModule.saveAdvancedConfiguration();
|
currentModule.saveAdvancedConfiguration();
|
||||||
reload();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dialog.addWindowListener(new WindowAdapter() {
|
dialog.addWindowListener(new WindowAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void windowClosing(WindowEvent e) {
|
public void windowClosing(WindowEvent e) {
|
||||||
dialog.close();
|
dialog.close();
|
||||||
reload();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
save(); // save the simple panel
|
dialog.display(currentModule.getAdvancedConfiguration(context));
|
||||||
dialog.display(currentModule.getAdvancedConfiguration(null));
|
|
||||||
}//GEN-LAST:event_advancedButtonActionPerformed
|
}//GEN-LAST:event_advancedButtonActionPerformed
|
||||||
|
|
||||||
private void processUnallocCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_processUnallocCheckboxActionPerformed
|
private void processUnallocCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_processUnallocCheckboxActionPerformed
|
||||||
// TODO add your handling code here:
|
// nothing to do here
|
||||||
}//GEN-LAST:event_processUnallocCheckboxActionPerformed
|
}//GEN-LAST:event_processUnallocCheckboxActionPerformed
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JButton advancedButton;
|
private javax.swing.JButton advancedButton;
|
||||||
@ -342,10 +295,19 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
private class ModulesTableModel extends AbstractTableModel {
|
private class ModulesTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
|
private List<Map.Entry<IngestModuleAbstract, Boolean>>moduleData = new ArrayList<>();
|
||||||
|
|
||||||
|
public ModulesTableModel() {
|
||||||
|
List<IngestModuleAbstract> modules = IngestManager.getDefault().enumerateAllModules();
|
||||||
|
for (IngestModuleAbstract ingestModuleAbstract : modules) {
|
||||||
|
moduleData.add(new AbstractMap.SimpleEntry<>(ingestModuleAbstract, Boolean.TRUE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRowCount() {
|
public int getRowCount() {
|
||||||
return modules.size();
|
return moduleData.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -355,11 +317,11 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||||
String name = modules.get(rowIndex).getName();
|
Map.Entry<IngestModuleAbstract, Boolean> entry = moduleData.get(rowIndex);
|
||||||
if (columnIndex == 0) {
|
if (columnIndex == 0) {
|
||||||
return moduleStates.get(name);
|
return entry.getValue();
|
||||||
} else {
|
} else {
|
||||||
return name;
|
return entry.getKey().getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,8 +333,7 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
@Override
|
@Override
|
||||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||||
if (columnIndex == 0) {
|
if (columnIndex == 0) {
|
||||||
moduleStates.put((String) getValueAt(rowIndex, 1), (Boolean) aValue);
|
moduleData.get(rowIndex).setValue((Boolean)aValue);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,183 +341,96 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
public Class<?> getColumnClass(int c) {
|
public Class<?> getColumnClass(int c) {
|
||||||
return getValueAt(0, c).getClass();
|
return getValueAt(0, c).getClass();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public List<IngestModuleAbstract> getSelectedModules() {
|
||||||
List<IngestModuleAbstract> getModulesToStart() {
|
List<IngestModuleAbstract> selectedModules = new ArrayList<>();
|
||||||
List<IngestModuleAbstract> modulesToStart = new ArrayList<IngestModuleAbstract>();
|
for (Map.Entry<IngestModuleAbstract, Boolean> entry : moduleData) {
|
||||||
for (IngestModuleAbstract module : modules) {
|
if (entry.getValue().booleanValue()) {
|
||||||
boolean moduleEnabled = moduleStates.get(module.getName());
|
selectedModules.add(entry.getKey());
|
||||||
if (moduleEnabled) {
|
|
||||||
modulesToStart.add(module);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return modulesToStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean processUnallocSpaceEnabled() {
|
|
||||||
return processUnallocCheckbox.isEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To be called whenever the next, close, or start buttons are pressed.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void save() {
|
|
||||||
// Save the current module
|
|
||||||
if (currentModule != null && currentModule.hasSimpleConfiguration()) {
|
|
||||||
currentModule.saveSimpleConfiguration();
|
|
||||||
}
|
|
||||||
// Save this panel
|
|
||||||
List<String> modulesDisabled = new ArrayList<String>();
|
|
||||||
for (int i = 0; i < modulesTable.getRowCount(); i++) {
|
|
||||||
// Column 0 is always the module's checkbox (which is retreived as a boolean)
|
|
||||||
Boolean enabled = (Boolean) modulesTable.getValueAt(i, 0);
|
|
||||||
if (!enabled) {
|
|
||||||
// Column 1 is always the module name
|
|
||||||
String moduleName = (String) modulesTable.getValueAt(i, 1);
|
|
||||||
modulesDisabled.add(moduleName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Add all the enabled modules to the properties separated by a coma
|
|
||||||
String list = "";
|
|
||||||
for (int i = 0; i < modulesDisabled.size(); i++) {
|
|
||||||
list += modulesDisabled.get(i);
|
|
||||||
if (i + 1 < modulesDisabled.size()) {
|
|
||||||
list += ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ModuleSettings.setConfigSetting(IngestManager.MODULE_PROPERTIES, DISABLED_MOD, list);
|
|
||||||
String processUnalloc = Boolean.toString(processUnallocCheckbox.isSelected());
|
|
||||||
ModuleSettings.setConfigSetting(IngestManager.MODULE_PROPERTIES, PARSE_UNALLOC, processUnalloc);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the dialog needs to be reloaded. Most commonly used to
|
|
||||||
* refresh the simple panel.
|
|
||||||
*
|
|
||||||
* Called every time this panel is displayed.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void reload() {
|
|
||||||
// Reload the simple panel
|
|
||||||
if (this.modulesTable.getSelectedRow() != -1) {
|
|
||||||
simplePanel.removeAll();
|
|
||||||
if (currentModule.hasSimpleConfiguration()) {
|
|
||||||
simplePanel.add(currentModule.getSimpleConfiguration(null));
|
|
||||||
}
|
|
||||||
simplePanel.revalidate();
|
|
||||||
simplePanel.repaint();
|
|
||||||
}
|
|
||||||
// Reload this panel
|
|
||||||
String list = ModuleSettings.getConfigSetting(IngestManager.MODULE_PROPERTIES, DISABLED_MOD);
|
|
||||||
if (list != null) { // if no property is found, list will be null
|
|
||||||
List<String> modulesDisabled = new ArrayList<String>(Arrays.asList(list.split(", ")));
|
|
||||||
// For every row, see if that module name is in the ArrayList
|
|
||||||
for (int i = 0; i < modulesTable.getRowCount(); i++) {
|
|
||||||
String moduleName = (String) modulesTable.getValueAt(i, 1);
|
|
||||||
if (modulesDisabled.contains(moduleName)) {
|
|
||||||
modulesTable.setValueAt(false, i, 0); // we found it, disable the module
|
|
||||||
} else {
|
|
||||||
modulesTable.setValueAt(true, i, 0); // not on disabled list, or a new module, enable it
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return selectedModules;
|
||||||
}
|
}
|
||||||
String processUnalloc = ModuleSettings.getConfigSetting(IngestManager.MODULE_PROPERTIES, PARSE_UNALLOC);
|
|
||||||
if (processUnalloc != null) {
|
/**
|
||||||
processUnallocCheckbox.setSelected(Boolean.parseBoolean(processUnalloc));
|
* Sets the given modules as selected in the modules table
|
||||||
|
* @param selectedModules
|
||||||
|
*/
|
||||||
|
public void setSelectedModules(List<IngestModuleAbstract> selectedModules) {
|
||||||
|
// unselect all modules
|
||||||
|
for (Map.Entry<IngestModuleAbstract, Boolean> entry : moduleData) {
|
||||||
|
entry.setValue(Boolean.FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// select only the given modules
|
||||||
|
for (IngestModuleAbstract selectedModule : selectedModules) {
|
||||||
|
getEntryForModule(selectedModule).setValue(Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// tell everyone about it
|
||||||
|
fireTableDataChanged();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
@Override
|
* Sets the given modules as NOT selected in the modules table
|
||||||
public JPanel getIngestConfigPanel() {
|
* @param selectedModules
|
||||||
this.reload();
|
*/
|
||||||
return this;
|
public void setUnselectedModules(List<IngestModuleAbstract> unselectedModules) {
|
||||||
}
|
// select all modules
|
||||||
|
for (Map.Entry<IngestModuleAbstract, Boolean> entry : moduleData) {
|
||||||
@Override
|
entry.setValue(Boolean.TRUE);
|
||||||
public void setContent(List<Content> inputContent) {
|
}
|
||||||
this.inputContent = inputContent;
|
|
||||||
}
|
// unselect only the given modules
|
||||||
|
for (IngestModuleAbstract unselectedModule : unselectedModules) {
|
||||||
@Override
|
getEntryForModule(unselectedModule).setValue(Boolean.FALSE);
|
||||||
public void start() {
|
}
|
||||||
//pick the modules
|
|
||||||
List<IngestModuleAbstract> modulesToStart = getModulesToStart();
|
// tell everyone about it
|
||||||
|
fireTableDataChanged();
|
||||||
//update ingest proc. unalloc space
|
|
||||||
if (processUnallocSpaceEnabled()) {
|
|
||||||
manager.setProcessUnallocSpace(processUnallocCheckbox.isSelected());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!modulesToStart.isEmpty()) {
|
public IngestModuleAbstract getModule(int row) {
|
||||||
manager.execute(modulesToStart, inputContent);
|
return moduleData.get(row).getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map.Entry<IngestModuleAbstract, Boolean> getEntryForModule(IngestModuleAbstract module) {
|
||||||
|
Map.Entry<IngestModuleAbstract, Boolean> entry = null;
|
||||||
|
for (Map.Entry<IngestModuleAbstract, Boolean> anEntry : moduleData) {
|
||||||
|
if (anEntry.getKey().equals(module)) {
|
||||||
|
entry = anEntry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isIngestRunning() {
|
|
||||||
return manager.isIngestRunning();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom cell renderer for tooltips with module description
|
* Custom cell renderer for tooltips with module description
|
||||||
*/
|
*/
|
||||||
private class ModulesTableRenderer extends DefaultTableCellRenderer {
|
private class ModulesTableRenderer extends DefaultTableCellRenderer {
|
||||||
|
|
||||||
|
List<String> tooltips = new ArrayList<>();
|
||||||
|
|
||||||
|
public ModulesTableRenderer() {
|
||||||
|
List<IngestModuleAbstract> modules = IngestManager.getDefault().enumerateAllModules();
|
||||||
|
for (IngestModuleAbstract ingestModuleAbstract : modules) {
|
||||||
|
tooltips.add(ingestModuleAbstract.getDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Component getTableCellRendererComponent(
|
public Component getTableCellRendererComponent(
|
||||||
JTable table, Object value,
|
JTable table, Object value,
|
||||||
boolean isSelected, boolean hasFocus,
|
boolean isSelected, boolean hasFocus,
|
||||||
int row, int column) {
|
int row, int column) {
|
||||||
|
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||||
final Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
|
||||||
|
|
||||||
if (column == 1) {
|
if (column == 1) {
|
||||||
//String moduleName = (String) table.getModel().getValueAt(row, column);
|
setToolTipText(tooltips.get(row));
|
||||||
IngestModuleAbstract module = modules.get(row);
|
|
||||||
String moduleDescr = module.getDescription();
|
|
||||||
String toolTip = moduleDescr;
|
|
||||||
|
|
||||||
if (inputContent != null && module.getType().equals(ModuleType.DataSource)) {
|
|
||||||
|
|
||||||
//DataSource module accepts only data source, does not work on any child
|
|
||||||
//show warning to user and set fg red for that module
|
|
||||||
boolean isDataSource = true;
|
|
||||||
for (Content content : inputContent) {
|
|
||||||
try {
|
|
||||||
if (content.getParent() != null) {
|
|
||||||
isDataSource = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (TskCoreException e) {
|
|
||||||
logger.log(Level.SEVERE, "Error checking if module input content is parentless data source", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! isDataSource ) {
|
|
||||||
cell.setForeground(Color.red);
|
|
||||||
toolTip = toolTip + "<br />WARNING: this module will not run on current selection because it operates only on root-level data-source (such as Image, Filesets).";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cell.setForeground(Color.black);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} //end data source
|
|
||||||
else {
|
|
||||||
cell.setForeground(Color.black);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
|
|
||||||
setToolTipText("<html>" + toolTip+ "</html>");
|
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
return cell;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2012 Basis Technology Corp.
|
* Copyright 2013 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");
|
||||||
@ -154,8 +154,6 @@ public class IngestManager {
|
|||||||
} catch (IngestModuleLoaderException ex) {
|
} catch (IngestModuleLoaderException ex) {
|
||||||
logger.log(Level.SEVERE, "Error getting module loader");
|
logger.log(Level.SEVERE, "Error getting module loader");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,7 +241,6 @@ public class IngestManager {
|
|||||||
if (ui != null) {
|
if (ui != null) {
|
||||||
ui.restoreMessages();
|
ui.restoreMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -346,17 +343,15 @@ public class IngestManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
//AbstractFile ingester
|
//AbstractFile ingester
|
||||||
boolean startAbstractFileIngester = false;
|
boolean startAbstractFileIngester = false;
|
||||||
if (fileScheduler.hasNext()) {
|
if (fileScheduler.hasNext()) {
|
||||||
if (abstractFileIngester
|
if (abstractFileIngester == null) {
|
||||||
== null) {
|
|
||||||
startAbstractFileIngester = true;
|
startAbstractFileIngester = true;
|
||||||
logger.log(Level.INFO, "Starting initial AbstractFile ingester");
|
logger.log(Level.INFO, "Starting initial AbstractFile ingester");
|
||||||
} //if worker had completed, restart it in case data is still enqueued
|
}
|
||||||
|
//if worker had completed, restart it in case data is still enqueued
|
||||||
else if (abstractFileIngester.isDone()) {
|
else if (abstractFileIngester.isDone()) {
|
||||||
startAbstractFileIngester = true;
|
startAbstractFileIngester = true;
|
||||||
logger.log(Level.INFO, "Restarting AbstractFile ingester");
|
logger.log(Level.INFO, "Restarting AbstractFile ingester");
|
||||||
@ -369,6 +364,9 @@ public class IngestManager {
|
|||||||
stats = new IngestManagerStats();
|
stats = new IngestManagerStats();
|
||||||
abstractFileIngester = new IngestAbstractFileProcessor();
|
abstractFileIngester = new IngestAbstractFileProcessor();
|
||||||
//init all fs modules, everytime new worker starts
|
//init all fs modules, everytime new worker starts
|
||||||
|
/* @@@ I don't understand why we do an init on each module. Should do only modules
|
||||||
|
* that we are going to be using in the pipeline
|
||||||
|
*/
|
||||||
for (IngestModuleAbstractFile s : abstractFileModules) {
|
for (IngestModuleAbstractFile s : abstractFileModules) {
|
||||||
IngestModuleInit moduleInit = new IngestModuleInit();
|
IngestModuleInit moduleInit = new IngestModuleInit();
|
||||||
try {
|
try {
|
||||||
@ -421,7 +419,6 @@ public class IngestManager {
|
|||||||
List<IngestDataSourceThread> toStop = new ArrayList<IngestDataSourceThread>();
|
List<IngestDataSourceThread> toStop = new ArrayList<IngestDataSourceThread>();
|
||||||
toStop.addAll(dataSourceIngesters);
|
toStop.addAll(dataSourceIngesters);
|
||||||
|
|
||||||
|
|
||||||
for (IngestDataSourceThread dataSourceWorker : toStop) {
|
for (IngestDataSourceThread dataSourceWorker : toStop) {
|
||||||
IngestModuleDataSource s = dataSourceWorker.getModule();
|
IngestModuleDataSource s = dataSourceWorker.getModule();
|
||||||
|
|
||||||
@ -440,7 +437,6 @@ public class IngestManager {
|
|||||||
logger.log(Level.WARNING, "Exception while stopping module: " + s.getName(), e);
|
logger.log(Level.WARNING, "Exception while stopping module: " + s.getName(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log(Level.INFO, "stopped all");
|
logger.log(Level.INFO, "stopped all");
|
||||||
@ -545,7 +541,6 @@ public class IngestManager {
|
|||||||
return module.hasBackgroundJobsRunning();
|
return module.hasBackgroundJobsRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//data source module
|
//data source module
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
@ -570,10 +565,7 @@ public class IngestManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -607,7 +599,7 @@ public class IngestManager {
|
|||||||
*
|
*
|
||||||
* @param processUnallocSpace
|
* @param processUnallocSpace
|
||||||
*/
|
*/
|
||||||
void setProcessUnallocSpace(boolean processUnallocSpace) {
|
public void setProcessUnallocSpace(boolean processUnallocSpace) {
|
||||||
this.processUnallocSpace = processUnallocSpace;
|
this.processUnallocSpace = processUnallocSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,6 +663,13 @@ public class IngestManager {
|
|||||||
public List<IngestModuleAbstractFile> enumerateAbstractFileModules() {
|
public List<IngestModuleAbstractFile> enumerateAbstractFileModules() {
|
||||||
return moduleLoader.getAbstractFileIngestModules();
|
return moduleLoader.getAbstractFileIngestModules();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<IngestModuleAbstract> enumerateAllModules() {
|
||||||
|
List<IngestModuleAbstract> modules = new ArrayList<>();
|
||||||
|
modules.addAll(enumerateDataSourceModules());
|
||||||
|
modules.addAll(enumerateAbstractFileModules());
|
||||||
|
return modules;
|
||||||
|
}
|
||||||
|
|
||||||
//data source worker to remove itself when complete or interrupted
|
//data source worker to remove itself when complete or interrupted
|
||||||
void removeDataSourceIngestWorker(IngestDataSourceThread worker) {
|
void removeDataSourceIngestWorker(IngestDataSourceThread worker) {
|
||||||
@ -697,7 +696,6 @@ public class IngestManager {
|
|||||||
|
|
||||||
IngestManagerStats() {
|
IngestManagerStats() {
|
||||||
errors = new HashMap<IngestModuleAbstract, Integer>();
|
errors = new HashMap<IngestModuleAbstract, Integer>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -775,19 +773,8 @@ public class IngestManager {
|
|||||||
public String toHtmlString() {
|
public String toHtmlString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("<html><body>");
|
sb.append("<html><body>");
|
||||||
|
|
||||||
sb.append("Ingest time: ").append(getTotalTimeString()).append("<br />");
|
sb.append("Ingest time: ").append(getTotalTimeString()).append("<br />");
|
||||||
sb.append("Total errors: ").append(errorsTotal).append("<br />");
|
sb.append("Total errors: ").append(errorsTotal).append("<br />");
|
||||||
/*
|
|
||||||
if (errorsTotal > 0) {
|
|
||||||
sb.append("Errors per module:");
|
|
||||||
for (IngestModuleAbstract module : errors.keySet()) {
|
|
||||||
final int errorsModule = errors.get(module);
|
|
||||||
sb.append("\t").append(module.getName()).append(": ").append(errorsModule).append("<br />");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
* */
|
|
||||||
|
|
||||||
sb.append("</body></html>");
|
sb.append("</body></html>");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
@ -1082,10 +1069,7 @@ public class IngestManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void queueAll(List<IngestModuleAbstract> modules, final List<Content> inputs) {
|
private void queueAll(List<IngestModuleAbstract> modules, final List<Content> inputs) {
|
||||||
|
|
||||||
final IngestScheduler.DataSourceScheduler dataSourceScheduler = scheduler.getDataSourceScheduler();
|
|
||||||
final IngestScheduler.FileScheduler fileScheduler = scheduler.getFileScheduler();
|
|
||||||
|
|
||||||
int processed = 0;
|
int processed = 0;
|
||||||
for (Content input : inputs) {
|
for (Content input : inputs) {
|
||||||
final String inputName = input.getName();
|
final String inputName = input.getName();
|
||||||
@ -1112,16 +1096,16 @@ public class IngestManager {
|
|||||||
logger.log(Level.INFO, "Error loading module and adding input " + inputName
|
logger.log(Level.INFO, "Error loading module and adding input " + inputName
|
||||||
+ " with module " + module.getName());
|
+ " with module " + module.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AbstractFile:
|
case AbstractFile:
|
||||||
//enqueue the same singleton AbstractFile module
|
//enqueue the same singleton AbstractFile module
|
||||||
logger.log(Level.INFO, "Adding input " + inputName
|
logger.log(Level.INFO, "Adding input " + inputName
|
||||||
+ " number of AbstractFile to module " + module.getName());
|
+ " for AbstractFileModule " + module.getName());
|
||||||
|
|
||||||
fileMods.add((IngestModuleAbstractFile) module);
|
fileMods.add((IngestModuleAbstractFile) module);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
logger.log(Level.SEVERE, "Unexpected module type: " + module.getType().name());
|
logger.log(Level.SEVERE, "Unexpected module type: " + module.getType().name());
|
||||||
}
|
}
|
||||||
@ -1138,6 +1122,7 @@ public class IngestManager {
|
|||||||
new PipelineContext<IngestModuleDataSource>(dataSourceTask, processUnalloc);
|
new PipelineContext<IngestModuleDataSource>(dataSourceTask, processUnalloc);
|
||||||
logger.log(Level.INFO, "Queing data source ingest task: " + dataSourceTask);
|
logger.log(Level.INFO, "Queing data source ingest task: " + dataSourceTask);
|
||||||
progress.progress("DataSource Ingest" + " " + inputName, processed);
|
progress.progress("DataSource Ingest" + " " + inputName, processed);
|
||||||
|
final IngestScheduler.DataSourceScheduler dataSourceScheduler = scheduler.getDataSourceScheduler();
|
||||||
dataSourceScheduler.schedule(dataSourcePipelineContext);
|
dataSourceScheduler.schedule(dataSourcePipelineContext);
|
||||||
progress.progress("DataSource Ingest" + " " + inputName, ++processed);
|
progress.progress("DataSource Ingest" + " " + inputName, ++processed);
|
||||||
|
|
||||||
@ -1148,6 +1133,7 @@ public class IngestManager {
|
|||||||
= new PipelineContext<IngestModuleAbstractFile>(fTask, processUnalloc);
|
= new PipelineContext<IngestModuleAbstractFile>(fTask, processUnalloc);
|
||||||
logger.log(Level.INFO, "Queing file ingest task: " + fTask);
|
logger.log(Level.INFO, "Queing file ingest task: " + fTask);
|
||||||
progress.progress("File Ingest" + " " + inputName, processed);
|
progress.progress("File Ingest" + " " + inputName, processed);
|
||||||
|
final IngestScheduler.FileScheduler fileScheduler = scheduler.getFileScheduler();
|
||||||
fileScheduler.schedule(filepipelineContext);
|
fileScheduler.schedule(filepipelineContext);
|
||||||
progress.progress("File Ingest" + " " + inputName, ++processed);
|
progress.progress("File Ingest" + " " + inputName, ++processed);
|
||||||
|
|
||||||
|
@ -145,35 +145,38 @@ public abstract class IngestModuleAbstract {
|
|||||||
*/
|
*/
|
||||||
public void saveAdvancedConfiguration() {}
|
public void saveAdvancedConfiguration() {}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a panel that displays the simple (run-time) configuration
|
* Returns a panel that displays the simple (run-time) configuration for the
|
||||||
* for the given configuration context (such as pipeline instance).
|
* given configuration context (such as pipeline instance). This is
|
||||||
* This is presented to the user before ingest starts and only basic
|
* presented to the user before ingest starts and only basic settings should
|
||||||
* settings should be given here. Use the advanced (general) configuration
|
* be given here. Use the advanced (general) configuration panel for more
|
||||||
* panel for more in-depth interfaces.
|
* in-depth interfaces. The module (or its configuration controller object)
|
||||||
* The module (or its configuration controller object) is responsible for preserving / saving its configuration state
|
* is responsible for preserving / saving its configuration state In
|
||||||
* In addition, saveSimpleConfiguration() can be used as the trigger.
|
* addition, saveSimpleConfiguration() can be used as the trigger.
|
||||||
*
|
*
|
||||||
* @param context the configuration context to use in the panel
|
* @param context the configuration context to use in the panel
|
||||||
* @return JPanel containing basic configuration widgets or null if simple configuration is not available
|
* @return JPanel containing basic configuration widgets or null if simple
|
||||||
|
* configuration is not available
|
||||||
*/
|
*/
|
||||||
public javax.swing.JPanel getSimpleConfiguration(String context) {
|
public javax.swing.JPanel getSimpleConfiguration(String context) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a panel that displays the advanced (run-time) configuration
|
* Returns a panel that displays the advanced (run-time) configuration for
|
||||||
* for the given configuration context (such as pipeline instance).
|
* the given configuration context (such as pipeline instance). Implements
|
||||||
* Implements advanced module configuration exposed to the user before ingest starts.
|
* advanced module configuration exposed to the user before ingest starts.
|
||||||
*
|
*
|
||||||
* The module (or its configuration controller object)
|
* The module (or its configuration controller object) is responsible for
|
||||||
* is responsible for preserving / saving its configuration state
|
* preserving / saving its configuration state In addition,
|
||||||
* In addition, saveAdvancedConfiguration() can be used as the trigger.
|
* saveAdvancedConfiguration() can be used as the trigger.
|
||||||
*
|
*
|
||||||
* @param context the configuration context to use in the panel
|
* @param context the configuration context to use in the panel
|
||||||
* @return JPanel containing advanced configuration widgets or null if advanced configuration is not available
|
* @return JPanel containing advanced configuration widgets or null if
|
||||||
|
* advanced configuration is not available
|
||||||
*/
|
*/
|
||||||
public javax.swing.JPanel getAdvancedConfiguration(String context) {
|
public javax.swing.JPanel getAdvancedConfiguration(String context) {
|
||||||
return null;
|
return null;
|
||||||
};
|
}
|
||||||
}
|
}
|
@ -466,11 +466,13 @@ public final class IngestModuleLoader {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void autodiscover() throws IngestModuleLoaderException {
|
private void autodiscover() throws IngestModuleLoaderException {
|
||||||
|
|
||||||
|
// Use Lookup to find the other NBM modules. We'll later search them for ingest modules
|
||||||
Collection<? extends ModuleInfo> moduleInfos = Lookup.getDefault().lookupAll(ModuleInfo.class);
|
Collection<? extends ModuleInfo> moduleInfos = Lookup.getDefault().lookupAll(ModuleInfo.class);
|
||||||
logger.log(Level.INFO, "Autodiscovery, found #platform modules: " + moduleInfos.size());
|
logger.log(Level.INFO, "Autodiscovery, found #platform modules: " + moduleInfos.size());
|
||||||
|
|
||||||
Set<URL> urls = getJarPaths(moduleInfos);
|
Set<URL> urls = getJarPaths(moduleInfos);
|
||||||
|
ArrayList<Reflections> reflectionsSet = new ArrayList<>();
|
||||||
|
|
||||||
for (final ModuleInfo moduleInfo : moduleInfos) {
|
for (final ModuleInfo moduleInfo : moduleInfos) {
|
||||||
if (moduleInfo.isEnabled()) {
|
if (moduleInfo.isEnabled()) {
|
||||||
String basePackageName = moduleInfo.getCodeNameBase();
|
String basePackageName = moduleInfo.getCodeNameBase();
|
||||||
@ -489,104 +491,115 @@ public final class IngestModuleLoader {
|
|||||||
cb.filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(basePackageName)));
|
cb.filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(basePackageName)));
|
||||||
cb.setUrls(urls);
|
cb.setUrls(urls);
|
||||||
cb.setScanners(new SubTypesScanner(), new ResourcesScanner());
|
cb.setScanners(new SubTypesScanner(), new ResourcesScanner());
|
||||||
Reflections reflections = new Reflections(cb);
|
reflectionsSet.add(new Reflections(cb));
|
||||||
|
|
||||||
Set<?> fileModules = reflections.getSubTypesOf(IngestModuleAbstractFile.class);
|
|
||||||
Iterator<?> it = fileModules.iterator();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
logger.log(Level.INFO, "Found file ingest module in: " + basePackageName + ": " + it.next().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<?> dataSourceModules = reflections.getSubTypesOf(IngestModuleDataSource.class);
|
|
||||||
it = dataSourceModules.iterator();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
logger.log(Level.INFO, "Found DataSource ingest module in: " + basePackageName + ": " + it.next().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
//find out which modules to add
|
|
||||||
//TODO check which modules to remove (which modules were uninstalled)
|
|
||||||
boolean modulesChanged = false;
|
|
||||||
|
|
||||||
it = fileModules.iterator();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
boolean exists = false;
|
|
||||||
Class<IngestModuleAbstractFile> foundClass = (Class<IngestModuleAbstractFile>) it.next();
|
|
||||||
|
|
||||||
for (IngestModuleLoader.XmlPipelineRaw rawP : pipelinesXML) {
|
|
||||||
if (!rawP.type.equals(IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.FILE_ANALYSIS.toString())) {
|
|
||||||
continue; //skip
|
|
||||||
}
|
|
||||||
|
|
||||||
for (IngestModuleLoader.XmlModuleRaw rawM : rawP.modules) {
|
|
||||||
//logger.log(Level.INFO, "CLASS NAME : " + foundClass.getName());
|
|
||||||
if (foundClass.getName().equals(rawM.location)) {
|
|
||||||
exists = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (exists == true) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exists == false) {
|
|
||||||
logger.log(Level.INFO, "Discovered a new file module to load: " + foundClass.getName());
|
|
||||||
//ADD MODULE
|
|
||||||
addModuleToRawPipeline(foundClass, IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.FILE_ANALYSIS);
|
|
||||||
modulesChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
it = dataSourceModules.iterator();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
boolean exists = false;
|
|
||||||
Class<IngestModuleDataSource> foundClass = (Class<IngestModuleDataSource>) it.next();
|
|
||||||
|
|
||||||
for (IngestModuleLoader.XmlPipelineRaw rawP : pipelinesXML) {
|
|
||||||
if (!rawP.type.equals(IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.DATA_SOURCE_ANALYSIS.toString())) {
|
|
||||||
continue; //skip
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (IngestModuleLoader.XmlModuleRaw rawM : rawP.modules) {
|
|
||||||
//logger.log(Level.INFO, "CLASS NAME : " + foundClass.getName());
|
|
||||||
if (foundClass.getName().equals(rawM.location)) {
|
|
||||||
exists = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (exists == true) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exists == false) {
|
|
||||||
logger.log(Level.INFO, "Discovered a new DataSource module to load: " + foundClass.getName());
|
|
||||||
//ADD MODULE
|
|
||||||
addModuleToRawPipeline(foundClass, IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.DATA_SOURCE_ANALYSIS);
|
|
||||||
modulesChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modulesChanged) {
|
|
||||||
save();
|
|
||||||
pcs.firePropertyChange(IngestModuleLoader.Event.ModulesReloaded.toString(), 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
//Enumeration<URL> resources = moduleClassLoader.getResources(basePackageName);
|
|
||||||
Enumeration<URL> resources = classLoader.getResources(basePackageName);
|
|
||||||
while (resources.hasMoreElements()) {
|
|
||||||
System.out.println(resources.nextElement());
|
|
||||||
} */
|
|
||||||
|
|
||||||
} else {
|
|
||||||
//logger.log(Level.INFO, "Module disabled: " + moduleInfo.getDisplayName() );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This area is used to load the example modules. They are not found via lookup since they
|
||||||
|
* are in this NBM module.
|
||||||
|
* Uncomment this section to rum the examples.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
ConfigurationBuilder cb = new ConfigurationBuilder();
|
||||||
|
cb.filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("org.sleuthkit.autopsy.examples")));
|
||||||
|
cb.setUrls(urls);
|
||||||
|
cb.setScanners(new SubTypesScanner(), new ResourcesScanner());
|
||||||
|
reflectionsSet.add(new Reflections(cb));
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (Reflections reflections : reflectionsSet) {
|
||||||
|
|
||||||
|
Set<?> fileModules = reflections.getSubTypesOf(IngestModuleAbstractFile.class);
|
||||||
|
Iterator<?> it = fileModules.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
logger.log(Level.INFO, "Found file ingest module in: " + reflections.getClass().getSimpleName() + ": " + it.next().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<?> dataSourceModules = reflections.getSubTypesOf(IngestModuleDataSource.class);
|
||||||
|
it = dataSourceModules.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
logger.log(Level.INFO, "Found DataSource ingest module in: " + reflections.getClass().getSimpleName() + ": " + it.next().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
//find out which modules to add
|
||||||
|
//TODO check which modules to remove (which modules were uninstalled)
|
||||||
|
boolean modulesChanged = false;
|
||||||
|
|
||||||
|
it = fileModules.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
boolean exists = false;
|
||||||
|
Class<IngestModuleAbstractFile> foundClass = (Class<IngestModuleAbstractFile>) it.next();
|
||||||
|
|
||||||
|
for (IngestModuleLoader.XmlPipelineRaw rawP : pipelinesXML) {
|
||||||
|
if (!rawP.type.equals(IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.FILE_ANALYSIS.toString())) {
|
||||||
|
continue; //skip
|
||||||
|
}
|
||||||
|
|
||||||
|
for (IngestModuleLoader.XmlModuleRaw rawM : rawP.modules) {
|
||||||
|
//logger.log(Level.INFO, "CLASS NAME : " + foundClass.getName());
|
||||||
|
if (foundClass.getName().equals(rawM.location)) {
|
||||||
|
exists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (exists == true) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists == false) {
|
||||||
|
logger.log(Level.INFO, "Discovered a new file module to load: " + foundClass.getName());
|
||||||
|
//ADD MODULE
|
||||||
|
addModuleToRawPipeline(foundClass, IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.FILE_ANALYSIS);
|
||||||
|
modulesChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
it = dataSourceModules.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
boolean exists = false;
|
||||||
|
Class<IngestModuleDataSource> foundClass = (Class<IngestModuleDataSource>) it.next();
|
||||||
|
|
||||||
|
for (IngestModuleLoader.XmlPipelineRaw rawP : pipelinesXML) {
|
||||||
|
if (!rawP.type.equals(IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.DATA_SOURCE_ANALYSIS.toString())) {
|
||||||
|
continue; //skip
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (IngestModuleLoader.XmlModuleRaw rawM : rawP.modules) {
|
||||||
|
//logger.log(Level.INFO, "CLASS NAME : " + foundClass.getName());
|
||||||
|
if (foundClass.getName().equals(rawM.location)) {
|
||||||
|
exists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (exists == true) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists == false) {
|
||||||
|
logger.log(Level.INFO, "Discovered a new DataSource module to load: " + foundClass.getName());
|
||||||
|
//ADD MODULE
|
||||||
|
addModuleToRawPipeline(foundClass, IngestModuleLoader.XmlPipelineRaw.PIPELINE_TYPE.DATA_SOURCE_ANALYSIS);
|
||||||
|
modulesChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modulesChanged) {
|
||||||
|
save();
|
||||||
|
pcs.firePropertyChange(IngestModuleLoader.Event.ModulesReloaded.toString(), 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
//Enumeration<URL> resources = moduleClassLoader.getResources(basePackageName);
|
||||||
|
Enumeration<URL> resources = classLoader.getResources(basePackageName);
|
||||||
|
while (resources.hasMoreElements()) {
|
||||||
|
System.out.println(resources.nextElement());
|
||||||
|
} */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,7 +105,160 @@ public class ReportHTML implements TableReportModule {
|
|||||||
}
|
}
|
||||||
out = null;
|
out = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a file name for the given datatype, by replacing any
|
||||||
|
* undesirable chars, like /, or spaces
|
||||||
|
* @param dataType data type for which to generate a file name
|
||||||
|
*/
|
||||||
|
private String dataTypeToFileName(String dataType) {
|
||||||
|
|
||||||
|
String fileName = org.sleuthkit.autopsy.coreutils.FileUtil.escapeFileName(dataType);
|
||||||
|
// replace all ' ' with '_'
|
||||||
|
fileName = fileName.replaceAll(" ", "_");
|
||||||
|
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies a suitable icon for the given data type in the output directory and
|
||||||
|
* returns the icon file name to use for the given data type.
|
||||||
|
*/
|
||||||
|
private String useDataTypeIcon(String dataType)
|
||||||
|
{
|
||||||
|
String iconFilePath;
|
||||||
|
String iconFileName;
|
||||||
|
InputStream in = null;
|
||||||
|
OutputStream output = null;
|
||||||
|
|
||||||
|
logger.log(Level.INFO, "useDataTypeIcon: dataType = " + dataType);
|
||||||
|
|
||||||
|
// find the artifact with matching display name
|
||||||
|
BlackboardArtifact.ARTIFACT_TYPE artifactType = null;
|
||||||
|
for (ARTIFACT_TYPE v : ARTIFACT_TYPE.values()) {
|
||||||
|
if (v.getDisplayName().equals(dataType)) {
|
||||||
|
artifactType = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null != artifactType)
|
||||||
|
{
|
||||||
|
// set the icon file name
|
||||||
|
iconFileName = dataTypeToFileName(artifactType.getDisplayName()) + ".png";
|
||||||
|
iconFilePath = path + File.separator + iconFileName;
|
||||||
|
|
||||||
|
// determine the source image to use
|
||||||
|
switch (artifactType) {
|
||||||
|
case TSK_WEB_BOOKMARK:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/bookmarks.png");
|
||||||
|
break;
|
||||||
|
case TSK_WEB_COOKIE:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/cookies.png");
|
||||||
|
break;
|
||||||
|
case TSK_WEB_HISTORY:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/history.png");
|
||||||
|
break;
|
||||||
|
case TSK_WEB_DOWNLOAD:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/downloads.png");
|
||||||
|
break;
|
||||||
|
case TSK_RECENT_OBJECT:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/recent.png");
|
||||||
|
break;
|
||||||
|
case TSK_INSTALLED_PROG:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/installed.png");
|
||||||
|
break;
|
||||||
|
case TSK_KEYWORD_HIT:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/keywords.png");
|
||||||
|
break;
|
||||||
|
case TSK_HASHSET_HIT:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/hash.png");
|
||||||
|
break;
|
||||||
|
case TSK_DEVICE_ATTACHED:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/devices.png");
|
||||||
|
break;
|
||||||
|
case TSK_WEB_SEARCH_QUERY:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/search.png");
|
||||||
|
break;
|
||||||
|
case TSK_METADATA_EXIF:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/exif.png");
|
||||||
|
break;
|
||||||
|
case TSK_TAG_FILE:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/userbookmarks.png");
|
||||||
|
break;
|
||||||
|
case TSK_TAG_ARTIFACT:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/userbookmarks.png");
|
||||||
|
break;
|
||||||
|
case TSK_SERVICE_ACCOUNT:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/account-icon-16.png");
|
||||||
|
break;
|
||||||
|
case TSK_CONTACT:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/contact.png");
|
||||||
|
break;
|
||||||
|
case TSK_MESSAGE:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/message.png");
|
||||||
|
break;
|
||||||
|
case TSK_CALLLOG:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/calllog.png");
|
||||||
|
break;
|
||||||
|
case TSK_CALENDAR_ENTRY:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/calendar.png");
|
||||||
|
break;
|
||||||
|
case TSK_SPEED_DIAL_ENTRY:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/speeddialentry.png");
|
||||||
|
break;
|
||||||
|
case TSK_BLUETOOTH_PAIRING:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/bluetooth.png");
|
||||||
|
break;
|
||||||
|
case TSK_GPS_BOOKMARK:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/gpsfav.png");
|
||||||
|
break;
|
||||||
|
case TSK_GPS_LAST_KNOWN_LOCATION:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/gps-lastlocation.png");
|
||||||
|
break;
|
||||||
|
case TSK_GPS_SEARCH:
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/gps-search.png");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logger.log(Level.WARNING, "useDataTypeIcon: unhandled artifact type = " + dataType);
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png");
|
||||||
|
iconFileName = "star.png";
|
||||||
|
iconFilePath = path + File.separator + iconFileName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // no defined artifact found for this dataType
|
||||||
|
logger.log(Level.WARNING, "useDataTypeIcon: no artifact found for data type = " + dataType);
|
||||||
|
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png");
|
||||||
|
iconFileName = "star.png";
|
||||||
|
iconFilePath = path + File.separator + iconFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
output = new FileOutputStream(iconFilePath);
|
||||||
|
FileUtil.copy(in, output);
|
||||||
|
in.close();
|
||||||
|
output.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Failed to extract images for HTML report.", ex);
|
||||||
|
} finally {
|
||||||
|
if (output != null) {
|
||||||
|
try {
|
||||||
|
output.flush();
|
||||||
|
output.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
}
|
||||||
|
} if (in != null) {
|
||||||
|
try {
|
||||||
|
in.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return iconFileName;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Start this report by setting the path, refreshing member variables,
|
* Start this report by setting the path, refreshing member variables,
|
||||||
* and writing the skeleton for the HTML report.
|
* and writing the skeleton for the HTML report.
|
||||||
@ -151,7 +304,7 @@ public class ReportHTML implements TableReportModule {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void startDataType(String title) {
|
public void startDataType(String title) {
|
||||||
String fTitle = org.sleuthkit.autopsy.coreutils.FileUtil.escapeFileName(title);
|
String fTitle = dataTypeToFileName(title);
|
||||||
// Make a new out for this page
|
// Make a new out for this page
|
||||||
try {
|
try {
|
||||||
//escape out slashes tha that appear in title
|
//escape out slashes tha that appear in title
|
||||||
@ -186,7 +339,7 @@ public class ReportHTML implements TableReportModule {
|
|||||||
* @param comment Comment on the data type, may be the empty string
|
* @param comment Comment on the data type, may be the empty string
|
||||||
*/
|
*/
|
||||||
public void startDataType(String name, String comment) {
|
public void startDataType(String name, String comment) {
|
||||||
String title = org.sleuthkit.autopsy.coreutils.FileUtil.escapeFileName(name);
|
String title = dataTypeToFileName(name);
|
||||||
try {
|
try {
|
||||||
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path + title + getExtension()), "UTF-8"));
|
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path + title + getExtension()), "UTF-8"));
|
||||||
} catch (FileNotFoundException ex) {
|
} catch (FileNotFoundException ex) {
|
||||||
@ -614,9 +767,10 @@ public class ReportHTML implements TableReportModule {
|
|||||||
nav.append("<li style=\"background: url(summary.png) left center no-repeat;\"><a href=\"summary.html\" target=\"content\">Case Summary</a></li>\n");
|
nav.append("<li style=\"background: url(summary.png) left center no-repeat;\"><a href=\"summary.html\" target=\"content\">Case Summary</a></li>\n");
|
||||||
|
|
||||||
for (String dataType : dataTypes.keySet()) {
|
for (String dataType : dataTypes.keySet()) {
|
||||||
String dataTypeEsc = org.sleuthkit.autopsy.coreutils.FileUtil.escapeFileName(dataType);
|
String dataTypeEsc = dataTypeToFileName(dataType);
|
||||||
nav.append("<li style=\"background: url('").append(dataType)
|
String iconFileName = useDataTypeIcon(dataType);
|
||||||
.append(".png') left center no-repeat;\"><a href=\"")
|
nav.append("<li style=\"background: url('").append(iconFileName)
|
||||||
|
.append("') left center no-repeat;\"><a href=\"")
|
||||||
.append(dataTypeEsc).append(".html\" target=\"content\">")
|
.append(dataTypeEsc).append(".html\" target=\"content\">")
|
||||||
.append(dataType).append(" (").append(dataTypes.get(dataType))
|
.append(dataType).append(" (").append(dataTypes.get(dataType))
|
||||||
.append(")</a></li>\n");
|
.append(")</a></li>\n");
|
||||||
@ -668,146 +822,7 @@ public class ReportHTML implements TableReportModule {
|
|||||||
in.close();
|
in.close();
|
||||||
output.close();
|
output.close();
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/bookmarks.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Bookmarks.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/cookies.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Cookies.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/history.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Web History.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/downloads.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Downloads.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/search.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Web Search Engine Queries.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/recent.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Recent Documents.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/installed.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Installed Programs.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/keywords.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Keyword Hits.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/devices.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Devices Attached.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/exif.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "EXIF Metadata.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/userbookmarks.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "File Tags.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/userbookmarks.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Result Tags.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/hash.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Hashset Hits.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/contact.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Contacts.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/message.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Messages.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/calllog.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Call Logs.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/calendar.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Calendar Entries.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/speeddialentry.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Speed Dial Entries.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/bluetooth.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "BlueTooth.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/gpsfav.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "GPS Bookmarks.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/gps-lastlocation.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "GPS Last Location.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/gps-search.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "GPS Search.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/account-icon-16.png");
|
|
||||||
output = new FileOutputStream(new File(path + File.separator + "Accounts.png"));
|
|
||||||
FileUtil.copy(in, output);
|
|
||||||
in.close();
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.log(Level.SEVERE, "Failed to extract images for HTML report.", ex);
|
logger.log(Level.SEVERE, "Failed to extract images for HTML report.", ex);
|
||||||
} finally {
|
} finally {
|
||||||
|
BIN
Core/src/org/sleuthkit/autopsy/report/images/star.png
Normal file
BIN
Core/src/org/sleuthkit/autopsy/report/images/star.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 674 B |
@ -46,6 +46,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
|
|||||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||||
import org.sleuthkit.datamodel.ReadContentInputStream;
|
import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.datamodel.TskData;
|
||||||
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
|
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,6 +93,11 @@ public final class ExifParserFileIngestModule extends IngestModuleAbstractFile {
|
|||||||
return IngestModuleAbstractFile.ProcessResult.OK;
|
return IngestModuleAbstractFile.ProcessResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// skip known
|
||||||
|
if (content.getKnown().equals(TskData.FileKnown.KNOWN)) {
|
||||||
|
return IngestModuleAbstractFile.ProcessResult.OK;
|
||||||
|
}
|
||||||
|
|
||||||
//skip unsupported
|
//skip unsupported
|
||||||
if (! parsableFormat(content)) {
|
if (! parsableFormat(content)) {
|
||||||
return IngestModuleAbstractFile.ProcessResult.OK;
|
return IngestModuleAbstractFile.ProcessResult.OK;
|
||||||
|
@ -504,37 +504,42 @@
|
|||||||
when adding a document.
|
when adding a document.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<!-- object id of the file -->
|
||||||
<field name="id" type="string" indexed="true" stored="true" required="true" />
|
<field name="id" type="string" indexed="true" stored="true" required="true" />
|
||||||
|
|
||||||
<!-- use image_id to easily search a specific image only -->
|
<!-- use image_id to easily search a specific image only -->
|
||||||
<field name="image_id" type="string" indexed="true" stored="true" required="true" />
|
<field name="image_id" type="string" indexed="true" stored="false" required="true" />
|
||||||
<!-- The content field holds the text extracted by SolrCell -->
|
|
||||||
|
<!-- Autopsy pushes text to the content field and gets the text to display from it. It is copied to other places -->
|
||||||
<field name="content" type="text_general" indexed="true" stored="true" termVectors="true" termPositions="true" termOffsets="true" />
|
<field name="content" type="text_general" indexed="true" stored="true" termVectors="true" termPositions="true" termOffsets="true" />
|
||||||
|
|
||||||
<!-- The strings field holds strings extracted from files that SolrCell doesn't support -->
|
<!-- The strings field holds strings extracted from files that SolrCell doesn't support -->
|
||||||
<field name="strings" type="text_general" indexed="true" stored="true"/>
|
<!--<field name="strings" type="text_general" indexed="true" stored="true"/>-->
|
||||||
<field name="file_name" type="text_general" indexed="true" stored="true"/>
|
|
||||||
<field name="ctime" type="tdate" indexed="true" stored="true"/>
|
<field name="file_name" type="text_general" indexed="false" stored="true"/>
|
||||||
<field name="atime" type="tdate" indexed="true" stored="true"/>
|
<field name="ctime" type="tdate" indexed="false" stored="false"/>
|
||||||
<field name="mtime" type="tdate" indexed="true" stored="true"/>
|
<field name="atime" type="tdate" indexed="false" stored="false"/>
|
||||||
<field name="crtime" type="tdate" indexed="true" stored="true"/>
|
<field name="mtime" type="tdate" indexed="false" stored="false"/>
|
||||||
<!-- file chunk-specific fields (optional for others) -->
|
<field name="crtime" type="tdate" indexed="false" stored="false"/>
|
||||||
<!-- for a parent file with no content, number of chunks are specified -->
|
<!-- file chunk-specific fields (optional for others) -->
|
||||||
<field name="num_chunks" type="int" indexed="true" stored="true" required="false" />
|
<!-- for a parent file with no content, number of chunks are specified -->
|
||||||
|
<field name="num_chunks" type="int" indexed="true" stored="true" required="false" />
|
||||||
|
|
||||||
<!-- Common metadata fields, named specifically to match up with
|
<!-- Common metadata fields, named specifically to match up with
|
||||||
SolrCell metadata when parsing rich documents such as Word, PDF.
|
SolrCell metadata when parsing rich documents such as Word, PDF.
|
||||||
Some fields are multiValued only because Tika currently may return
|
Some fields are multiValued only because Tika currently may return
|
||||||
multiple values for them.
|
multiple values for them.
|
||||||
-->
|
-->
|
||||||
<field name="title" type="text_general" indexed="true" stored="true" multiValued="true"/>
|
<field name="title" type="text_general" indexed="false" stored="false" multiValued="true"/>
|
||||||
<field name="subject" type="text_general" indexed="true" stored="true"/>
|
<field name="subject" type="text_general" indexed="false" stored="false"/>
|
||||||
<field name="description" type="text_general" indexed="true" stored="true"/>
|
<field name="description" type="text_general" indexed="false" stored="false"/>
|
||||||
<field name="comments" type="text_general" indexed="true" stored="true"/>
|
<field name="comments" type="text_general" indexed="false" stored="false"/>
|
||||||
<field name="author" type="text_general" indexed="true" stored="true"/>
|
<field name="author" type="text_general" indexed="false" stored="false"/>
|
||||||
<field name="keywords" type="text_general" indexed="true" stored="true"/>
|
<field name="keywords" type="text_general" indexed="false" stored="false"/>
|
||||||
<field name="category" type="text_general" indexed="true" stored="true"/>
|
<field name="category" type="text_general" indexed="false" stored="false"/>
|
||||||
<field name="content_type" type="string" indexed="true" stored="true" multiValued="true"/>
|
<field name="content_type" type="string" indexed="false" stored="false" multiValued="true"/>
|
||||||
<field name="last_modified" type="date" indexed="true" stored="true"/>
|
<field name="last_modified" type="date" indexed="false" stored="false"/>
|
||||||
<field name="links" type="string" indexed="true" stored="true" multiValued="true"/>
|
<field name="links" type="string" indexed="false" stored="false" multiValued="true"/>
|
||||||
|
|
||||||
<!-- Tika places all metadata into a multivalued field named "meta" -->
|
<!-- Tika places all metadata into a multivalued field named "meta" -->
|
||||||
<field name="meta" type="text_general" indexed="true" stored="true" multiValued="true"/>
|
<field name="meta" type="text_general" indexed="true" stored="true" multiValued="true"/>
|
||||||
@ -545,10 +550,11 @@
|
|||||||
|
|
||||||
<!-- catchall text field that indexes tokens both normally and in reverse for efficient
|
<!-- catchall text field that indexes tokens both normally and in reverse for efficient
|
||||||
leading wildcard queries. -->
|
leading wildcard queries. -->
|
||||||
<field name="text_rev" type="text_general_rev" indexed="true" stored="false" multiValued="true"/>
|
<!--<field name="text_rev" type="text_general_rev" indexed="true" stored="false" multiValued="true"/>-->
|
||||||
|
|
||||||
<!-- field with white-space tokenized words for TermsComponent regex search (useful for fast search of IP addresses, URLs, certain phone numbers)
|
<!-- field with white-space tokenized words for TermsComponent regex search (useful for fast search of IP addresses, URLs, certain phone numbers)
|
||||||
also be useful for Lucene based queries containing special characters-->
|
also be useful for Lucene based queries containing special characters-->
|
||||||
|
<!-- populated via copyField -->
|
||||||
<field name="content_ws" type="text_ws" indexed="true" stored="false" />
|
<field name="content_ws" type="text_ws" indexed="true" stored="false" />
|
||||||
|
|
||||||
<!-- Uncommenting the following will create a "timestamp" field using
|
<!-- Uncommenting the following will create a "timestamp" field using
|
||||||
@ -621,7 +627,7 @@
|
|||||||
<copyField source="content" dest="text"/>
|
<copyField source="content" dest="text"/>
|
||||||
<copyField source="file_name" dest="text"/>
|
<copyField source="file_name" dest="text"/>
|
||||||
<copyField source="meta" dest="text"/>
|
<copyField source="meta" dest="text"/>
|
||||||
<copyField source="strings" dest="text"/>
|
<!--<copyField source="strings" dest="text"/>-->
|
||||||
<copyField source="content" dest="content_ws"/>
|
<copyField source="content" dest="content_ws"/>
|
||||||
|
|
||||||
<!-- Above, multiple source fields are copied to the [text] field.
|
<!-- Above, multiple source fields are copied to the [text] field.
|
||||||
|
@ -120,12 +120,11 @@ public class AbstractFileTikaTextExtract implements AbstractFileExtract {
|
|||||||
|
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
Reader reader = null;
|
Reader reader = null;
|
||||||
|
|
||||||
|
|
||||||
final InputStream stream = new ReadContentInputStream(sourceFile);
|
final InputStream stream = new ReadContentInputStream(sourceFile);
|
||||||
try {
|
try {
|
||||||
Metadata meta = new Metadata();
|
Metadata meta = new Metadata();
|
||||||
//Tika parse request with timeout
|
|
||||||
|
//Parse the file in a task
|
||||||
Tika tika = new Tika(); //new tika instance for every file, to workaround tika memory issues
|
Tika tika = new Tika(); //new tika instance for every file, to workaround tika memory issues
|
||||||
ParseRequestTask parseTask = new ParseRequestTask(tika, stream, meta, sourceFile);
|
ParseRequestTask parseTask = new ParseRequestTask(tika, stream, meta, sourceFile);
|
||||||
final Future<?> future = tikaParseExecutor.submit(parseTask);
|
final Future<?> future = tikaParseExecutor.submit(parseTask);
|
||||||
@ -145,14 +144,16 @@ public class AbstractFileTikaTextExtract implements AbstractFileExtract {
|
|||||||
throw new IngesterException(msg);
|
throw new IngesterException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the reader with the results
|
||||||
reader = parseTask.getReader();
|
reader = parseTask.getReader();
|
||||||
|
|
||||||
if (reader == null) {
|
if (reader == null) {
|
||||||
//likely due to exception in parse()
|
//likely due to exception in parse()
|
||||||
logger.log(Level.WARNING, "No reader available from Tika parse");
|
logger.log(Level.WARNING, "No reader available from Tika parse");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// break the results into chunks and index
|
||||||
success = true;
|
success = true;
|
||||||
long readSize;
|
long readSize;
|
||||||
long totalRead = 0;
|
long totalRead = 0;
|
||||||
@ -180,8 +181,6 @@ public class AbstractFileTikaTextExtract implements AbstractFileExtract {
|
|||||||
//this is the last chunk
|
//this is the last chunk
|
||||||
eof = true;
|
eof = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//logger.log(Level.INFO, "TOTAL READ SIZE: " + totalRead + " file: " + sourceFile.getName());
|
//logger.log(Level.INFO, "TOTAL READ SIZE: " + totalRead + " file: " + sourceFile.getName());
|
||||||
@ -214,7 +213,7 @@ public class AbstractFileTikaTextExtract implements AbstractFileExtract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extracted = sb.toString();
|
extracted = sb.toString();
|
||||||
|
|
||||||
//converts BOM automatically to charSet encoding
|
//converts BOM automatically to charSet encoding
|
||||||
byte[] encodedBytes = extracted.getBytes(OUTPUT_CHARSET);
|
byte[] encodedBytes = extracted.getBytes(OUTPUT_CHARSET);
|
||||||
AbstractFileChunk chunk = new AbstractFileChunk(this, this.numChunks + 1);
|
AbstractFileChunk chunk = new AbstractFileChunk(this, this.numChunks + 1);
|
||||||
@ -293,8 +292,8 @@ public class AbstractFileTikaTextExtract implements AbstractFileExtract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runnable and timeable task that calls tika to parse the content using
|
* Runnable task that calls tika to parse the content using
|
||||||
* streaming
|
* the input stream. Provides reader for results.
|
||||||
*/
|
*/
|
||||||
private static class ParseRequestTask implements Runnable {
|
private static class ParseRequestTask implements Runnable {
|
||||||
|
|
||||||
|
@ -29,7 +29,8 @@ import org.sleuthkit.autopsy.keywordsearch.KeywordSearch.QueryType;
|
|||||||
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchQueryManager.Presentation;
|
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchQueryManager.Presentation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common functionality among keyword search performers / widgets
|
* Common functionality among keyword search performers / widgets.
|
||||||
|
* This is extended by the various panels and interfaces that perform the keyword searches.
|
||||||
*/
|
*/
|
||||||
abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel implements KeywordSearchPerformerInterface {
|
abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel implements KeywordSearchPerformerInterface {
|
||||||
|
|
||||||
@ -105,7 +106,8 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
man = new KeywordSearchQueryManager(keywords, Presentation.COLLAPSE);
|
man = new KeywordSearchQueryManager(keywords, Presentation.COLLAPSE);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
QueryType queryType = null;
|
QueryType queryType = null;
|
||||||
if (isLuceneQuerySelected()) {
|
if (isLuceneQuerySelected()) {
|
||||||
queryType = QueryType.WORD;
|
queryType = QueryType.WORD;
|
||||||
|
@ -416,14 +416,16 @@ public class ExtractedContentViewer implements DataContentViewer {
|
|||||||
//because we are storing extracted text in chunks only
|
//because we are storing extracted text in chunks only
|
||||||
//and the non-chunk stores meta-data only
|
//and the non-chunk stores meta-data only
|
||||||
String name = contentObj.getName();
|
String name = contentObj.getName();
|
||||||
String msg = "<p style='font-style:italic'>No extracted text present in the index for file: " + name + " </p>";
|
String msg = null;
|
||||||
if (contentObj instanceof AbstractFile) {
|
if (contentObj instanceof AbstractFile) {
|
||||||
//we know it's AbstractFile, but do quick check to make sure if we index other objects in future
|
//we know it's AbstractFile, but do quick check to make sure if we index other objects in future
|
||||||
boolean isKnown = FileKnown.KNOWN.equals(((AbstractFile)contentObj).getKnown());
|
boolean isKnown = FileKnown.KNOWN.equals(((AbstractFile)contentObj).getKnown());
|
||||||
if (isKnown && KeywordSearchSettings.getSkipKnown()) {
|
if (isKnown && KeywordSearchSettings.getSkipKnown()) {
|
||||||
msg += "<p style='font-style:italic'>It is a 'known' file and the current settings opt to skip indexing 'known' files during ingest. </p>";
|
msg = "<p style='font-style:italic'>" + name + " is a known file (based on MD5 hash) and does not have text in the index.</p>";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (msg == null) {
|
||||||
|
msg = "<p style='font-style:italic'>" + name + "does not have text in the index.<br/>It may have no text, not been analyzed yet, or keyword search was not enabled during ingest.</p>";
|
||||||
}
|
}
|
||||||
String htmlMsg = "<span style='font-style:italic'>" + msg + "</span>";
|
String htmlMsg = "<span style='font-style:italic'>" + msg + "</span>";
|
||||||
return htmlMsg;
|
return htmlMsg;
|
||||||
|
@ -17,24 +17,34 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Representation of keyword query as input by user
|
|
||||||
*/
|
|
||||||
package org.sleuthkit.autopsy.keywordsearch;
|
package org.sleuthkit.autopsy.keywordsearch;
|
||||||
|
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of single keyword to search for
|
||||||
|
*/
|
||||||
public class Keyword {
|
public class Keyword {
|
||||||
|
private String keywordString; // keyword to search for
|
||||||
private String query;
|
private boolean isLiteral; // false if reg exp
|
||||||
private boolean isLiteral;
|
|
||||||
private BlackboardAttribute.ATTRIBUTE_TYPE keywordType = null;
|
private BlackboardAttribute.ATTRIBUTE_TYPE keywordType = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param query Keyword to search for
|
||||||
|
* @param isLiteral false if reg exp
|
||||||
|
*/
|
||||||
Keyword(String query, boolean isLiteral) {
|
Keyword(String query, boolean isLiteral) {
|
||||||
this.query = query;
|
this.keywordString = query;
|
||||||
this.isLiteral = isLiteral;
|
this.isLiteral = isLiteral;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param query Keyword to search for
|
||||||
|
* @param isLiteral false if reg exp
|
||||||
|
* @param keywordType
|
||||||
|
*/
|
||||||
Keyword(String query, boolean isLiteral, BlackboardAttribute.ATTRIBUTE_TYPE keywordType) {
|
Keyword(String query, boolean isLiteral, BlackboardAttribute.ATTRIBUTE_TYPE keywordType) {
|
||||||
this(query, isLiteral);
|
this(query, isLiteral);
|
||||||
this.keywordType = keywordType;
|
this.keywordType = keywordType;
|
||||||
@ -48,8 +58,12 @@ public class Keyword {
|
|||||||
return this.keywordType;
|
return this.keywordType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return Keyword to search for
|
||||||
|
*/
|
||||||
String getQuery() {
|
String getQuery() {
|
||||||
return query;
|
return keywordString;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isLiteral() {
|
boolean isLiteral() {
|
||||||
@ -58,7 +72,7 @@ public class Keyword {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Keyword{" + "query=" + query + ", isLiteral=" + isLiteral + ", keywordType=" + keywordType + '}';
|
return "Keyword{" + "query=" + keywordString + ", isLiteral=" + isLiteral + ", keywordType=" + keywordType + '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -72,7 +86,7 @@ public class Keyword {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final Keyword other = (Keyword) obj;
|
final Keyword other = (Keyword) obj;
|
||||||
if ((this.query == null) ? (other.query != null) : !this.query.equals(other.query)) {
|
if ((this.keywordString == null) ? (other.keywordString != null) : !this.keywordString.equals(other.keywordString)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this.isLiteral != other.isLiteral) {
|
if (this.isLiteral != other.isLiteral) {
|
||||||
@ -84,7 +98,7 @@ public class Keyword {
|
|||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int hash = 7;
|
int hash = 7;
|
||||||
hash = 17 * hash + (this.query != null ? this.query.hashCode() : 0);
|
hash = 17 * hash + (this.keywordString != null ? this.keywordString.hashCode() : 0);
|
||||||
hash = 17 * hash + (this.isLiteral ? 1 : 0);
|
hash = 17 * hash + (this.isLiteral ? 1 : 0);
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2013 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");
|
||||||
@ -28,9 +28,9 @@ import org.openide.nodes.PropertySupport;
|
|||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.openide.util.lookup.ProxyLookup;
|
import org.openide.util.lookup.ProxyLookup;
|
||||||
import org.sleuthkit.autopsy.directorytree.TagAction;
|
|
||||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||||
|
import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.HashSearchAction;
|
import org.sleuthkit.autopsy.directorytree.HashSearchAction;
|
||||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
@ -128,8 +128,6 @@ class KeywordSearchFilterNode extends FilterNode {
|
|||||||
Content content = this.getOriginal().getLookup().lookup(Content.class);
|
Content content = this.getOriginal().getLookup().lookup(Content.class);
|
||||||
actions.addAll(content.accept(new GetPopupActionsContentVisitor()));
|
actions.addAll(content.accept(new GetPopupActionsContentVisitor()));
|
||||||
|
|
||||||
//actions.add(new IndexContentFilesAction(nodeContent, "Index"));
|
|
||||||
|
|
||||||
return actions.toArray(new Action[actions.size()]);
|
return actions.toArray(new Action[actions.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,33 +135,29 @@ class KeywordSearchFilterNode extends FilterNode {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Action> visit(File f) {
|
public List<Action> visit(File f) {
|
||||||
List<Action> actions = new ArrayList<Action>();
|
return getFileActions();
|
||||||
actions.add(new NewWindowViewAction("View in New Window", KeywordSearchFilterNode.this));
|
|
||||||
actions.add(new ExternalViewerAction("Open in External Viewer", getOriginal()));
|
|
||||||
actions.add(null);
|
|
||||||
actions.add(new ExtractAction("Extract File", getOriginal()));
|
|
||||||
actions.add(new HashSearchAction("Search for files with the same MD5 hash", getOriginal()));
|
|
||||||
actions.add(null); // creates a menu separator
|
|
||||||
actions.add(new TagAction(getOriginal()));
|
|
||||||
return actions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Action> visit(DerivedFile f) {
|
public List<Action> visit(DerivedFile f) {
|
||||||
List<Action> actions = new ArrayList<Action>();
|
return getFileActions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Action> getFileActions() {
|
||||||
|
List<Action> actions = new ArrayList<>();
|
||||||
actions.add(new NewWindowViewAction("View in New Window", KeywordSearchFilterNode.this));
|
actions.add(new NewWindowViewAction("View in New Window", KeywordSearchFilterNode.this));
|
||||||
actions.add(new ExternalViewerAction("Open in External Viewer", getOriginal()));
|
actions.add(new ExternalViewerAction("Open in External Viewer", getOriginal()));
|
||||||
actions.add(null);
|
actions.add(null);
|
||||||
actions.add(new ExtractAction("Extract File", getOriginal()));
|
actions.add(ExtractAction.getInstance());
|
||||||
actions.add(new HashSearchAction("Search for files with the same MD5 hash", getOriginal()));
|
actions.add(new HashSearchAction("Search for files with the same MD5 hash", getOriginal()));
|
||||||
actions.add(null); // creates a menu separator
|
actions.add(null); // creates a menu separator
|
||||||
actions.add(new TagAction(getOriginal()));
|
actions.add(TagAbstractFileAction.getInstance());
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Action> defaultVisit(Content c) {
|
protected List<Action> defaultVisit(Content c) {
|
||||||
return new ArrayList<Action>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ import org.sleuthkit.autopsy.ingest.IngestManager;
|
|||||||
import org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent;
|
import org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Viewer panel widget for keyword lists
|
* Viewer panel widget for keyword lists that is used in the ingest config and options area.
|
||||||
*/
|
*/
|
||||||
class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
|
class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
|
||||||
|
|
||||||
|
@ -22,16 +22,46 @@ import java.util.List;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* common methods for the KeywordSearch performers
|
* KeywordSearchPerformers are perform different searches from
|
||||||
*
|
* different interfaces and places in the application. Its
|
||||||
|
* results are then passed to a KeywordSearchQuery implementation
|
||||||
|
* to perform the actual search.
|
||||||
*/
|
*/
|
||||||
interface KeywordSearchPerformerInterface {
|
interface KeywordSearchPerformerInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this interface support multi-word queries?
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
boolean isMultiwordQuery();
|
boolean isMultiwordQuery();
|
||||||
boolean isLuceneQuerySelected();
|
|
||||||
String getQueryText();
|
|
||||||
List<Keyword> getQueryList();
|
|
||||||
void setFilesIndexed(int filesIndexed);
|
|
||||||
void search();
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the user did not choose to do a regular expression search
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean isLuceneQuerySelected();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the query/keyword string that the user entered/selected
|
||||||
|
* @return Keyword to search
|
||||||
|
*/
|
||||||
|
String getQueryText();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of Keyword objects that the user entered/selected
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<Keyword> getQueryList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the number of files that have been indexed
|
||||||
|
* @param filesIndexed
|
||||||
|
*/
|
||||||
|
void setFilesIndexed(int filesIndexed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the search using the selected keywords.
|
||||||
|
* Creates a DataResultTopComponent with the results.
|
||||||
|
*/
|
||||||
|
void search();
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,11 @@ import java.util.Map;
|
|||||||
import org.apache.solr.client.solrj.response.TermsResponse.Term;
|
import org.apache.solr.client.solrj.response.TermsResponse.Term;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for a search query. Implemented by various
|
||||||
|
* engines or methods of using the same engine. One of these
|
||||||
|
* is created for each query.
|
||||||
|
*/
|
||||||
public interface KeywordSearchQuery {
|
public interface KeywordSearchQuery {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,7 +56,7 @@ public interface KeywordSearchQuery {
|
|||||||
public void addFilter(KeywordQueryFilter filter);
|
public void addFilter(KeywordQueryFilter filter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an optional field to narrow down the search
|
* Set an optional SOLR field to narrow down the search
|
||||||
* @param field field to set on the query
|
* @param field field to set on the query
|
||||||
*/
|
*/
|
||||||
public void setField(String field);
|
public void setField(String field);
|
||||||
@ -75,13 +80,13 @@ public interface KeywordSearchQuery {
|
|||||||
public boolean isLiteral();
|
public boolean isLiteral();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return original query string
|
* return original keyword/query string
|
||||||
* @return the query String supplied originally
|
* @return the query String supplied originally
|
||||||
*/
|
*/
|
||||||
public String getQueryString();
|
public String getQueryString();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return escaped query string if escaping was done
|
* return escaped keyword/query string if escaping was done
|
||||||
* @return the escaped query string, or original string if no escaping done
|
* @return the escaped query string, or original string if no escaping done
|
||||||
*/
|
*/
|
||||||
public String getEscapedQueryString();
|
public String getEscapedQueryString();
|
||||||
|
@ -34,73 +34,99 @@ import org.sleuthkit.autopsy.datamodel.KeyValue;
|
|||||||
import org.sleuthkit.autopsy.keywordsearch.KeywordSearch.QueryType;
|
import org.sleuthkit.autopsy.keywordsearch.KeywordSearch.QueryType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query manager responsible for running appropriate queries and displaying
|
* Responsible for running a keyword search query and displaying
|
||||||
* results for single, multi keyword queries, with detailed or collapsed results
|
* the results.
|
||||||
*/
|
*/
|
||||||
public class KeywordSearchQueryManager {
|
public class KeywordSearchQueryManager {
|
||||||
|
|
||||||
|
// how to display the results
|
||||||
public enum Presentation {
|
public enum Presentation {
|
||||||
|
|
||||||
COLLAPSE, DETAIL
|
COLLAPSE, DETAIL
|
||||||
};
|
};
|
||||||
private List<Keyword> queries;
|
|
||||||
|
private List<Keyword> keywords;
|
||||||
private Presentation presentation;
|
private Presentation presentation;
|
||||||
private List<KeywordSearchQuery> queryDelegates;
|
private List<KeywordSearchQuery> queryDelegates;
|
||||||
private QueryType queryType;
|
private QueryType queryType;
|
||||||
private static int resultWindowCount = 0; //keep track of unique window ids to display
|
private static int resultWindowCount = 0; //keep track of unique window ids to display
|
||||||
private static Logger logger = Logger.getLogger(KeywordSearchQueryManager.class.getName());
|
private static Logger logger = Logger.getLogger(KeywordSearchQueryManager.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param queries Keywords to search for
|
||||||
|
* @param presentation Presentation layout
|
||||||
|
*/
|
||||||
public KeywordSearchQueryManager(List<Keyword> queries, Presentation presentation) {
|
public KeywordSearchQueryManager(List<Keyword> queries, Presentation presentation) {
|
||||||
this.queries = queries;
|
this.keywords = queries;
|
||||||
this.presentation = presentation;
|
this.presentation = presentation;
|
||||||
queryType = QueryType.REGEX;
|
queryType = QueryType.REGEX;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param query Keyword to search for
|
||||||
|
* @param qt Query type
|
||||||
|
* @param presentation Presentation Layout
|
||||||
|
*/
|
||||||
public KeywordSearchQueryManager(String query, QueryType qt, Presentation presentation) {
|
public KeywordSearchQueryManager(String query, QueryType qt, Presentation presentation) {
|
||||||
queries = new ArrayList<Keyword>();
|
keywords = new ArrayList<Keyword>();
|
||||||
queries.add(new Keyword(query, qt == QueryType.REGEX ? false : true));
|
keywords.add(new Keyword(query, qt == QueryType.REGEX ? false : true));
|
||||||
this.presentation = presentation;
|
this.presentation = presentation;
|
||||||
queryType = qt;
|
queryType = qt;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param query Keyword to search for
|
||||||
|
* @param isLiteral false if reg-exp
|
||||||
|
* @param presentation Presentation layout
|
||||||
|
*/
|
||||||
public KeywordSearchQueryManager(String query, boolean isLiteral, Presentation presentation) {
|
public KeywordSearchQueryManager(String query, boolean isLiteral, Presentation presentation) {
|
||||||
queries = new ArrayList<Keyword>();
|
keywords = new ArrayList<Keyword>();
|
||||||
queries.add(new Keyword(query, isLiteral));
|
keywords.add(new Keyword(query, isLiteral));
|
||||||
this.presentation = presentation;
|
this.presentation = presentation;
|
||||||
queryType = isLiteral ? QueryType.WORD : QueryType.REGEX;
|
queryType = isLiteral ? QueryType.WORD : QueryType.REGEX;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize internal settings based on constructor arguments.
|
||||||
|
* Create a list of queries to later run
|
||||||
|
*/
|
||||||
private void init() {
|
private void init() {
|
||||||
queryDelegates = new ArrayList<KeywordSearchQuery>();
|
queryDelegates = new ArrayList<KeywordSearchQuery>();
|
||||||
for (Keyword query : queries) {
|
for (Keyword keyword : keywords) {
|
||||||
KeywordSearchQuery del = null;
|
KeywordSearchQuery query = null;
|
||||||
switch (queryType) {
|
switch (queryType) {
|
||||||
case WORD:
|
case WORD:
|
||||||
del = new LuceneQuery(query);
|
query = new LuceneQuery(keyword);
|
||||||
break;
|
break;
|
||||||
case REGEX:
|
case REGEX:
|
||||||
if (query.isLiteral()) {
|
if (keyword.isLiteral()) {
|
||||||
del = new LuceneQuery(query);
|
query = new LuceneQuery(keyword);
|
||||||
} else {
|
} else {
|
||||||
del = new TermComponentQuery(query);
|
query = new TermComponentQuery(keyword);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
if (query.isLiteral()) {
|
if (query != null) {
|
||||||
del.escape();
|
if (keyword.isLiteral()) {
|
||||||
|
query.escape();
|
||||||
|
}
|
||||||
|
queryDelegates.add(query);
|
||||||
}
|
}
|
||||||
queryDelegates.add(del);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//escape();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the keyword search based on keywords passed into constructor.
|
||||||
|
* Post results into a new DataResultViewer.
|
||||||
|
*/
|
||||||
public void execute() {
|
public void execute() {
|
||||||
//execute and present the query
|
//execute and present the query
|
||||||
//delegate query to query objects and presentation child factories
|
//delegate query to query objects and presentation child factories
|
||||||
@ -109,10 +135,11 @@ public class KeywordSearchQueryManager {
|
|||||||
// q.execute();
|
// q.execute();
|
||||||
// }
|
// }
|
||||||
// } else {
|
// } else {
|
||||||
|
|
||||||
//Collapsed view
|
//Collapsed view
|
||||||
Collection<KeyValueQuery> things = new ArrayList<KeyValueQuery>();
|
Collection<KeyValueQuery> things = new ArrayList<KeyValueQuery>();
|
||||||
int queryID = 0;
|
int queryID = 0;
|
||||||
StringBuilder queryConcat = new StringBuilder();
|
StringBuilder queryConcat = new StringBuilder(); // concatenation of all query strings
|
||||||
for (KeywordSearchQuery q : queryDelegates) {
|
for (KeywordSearchQuery q : queryDelegates) {
|
||||||
Map<String, Object> kvs = new LinkedHashMap<String, Object>();
|
Map<String, Object> kvs = new LinkedHashMap<String, Object>();
|
||||||
final String queryStr = q.getQueryString();
|
final String queryStr = q.getQueryString();
|
||||||
@ -129,7 +156,7 @@ public class KeywordSearchQueryManager {
|
|||||||
DataResultTopComponent searchResultWin = DataResultTopComponent.createInstance(windowTitle);
|
DataResultTopComponent searchResultWin = DataResultTopComponent.createInstance(windowTitle);
|
||||||
if (things.size() > 0) {
|
if (things.size() > 0) {
|
||||||
Children childThingNodes =
|
Children childThingNodes =
|
||||||
Children.create(new KeywordSearchResultFactory(queries, things, Presentation.COLLAPSE, searchResultWin), true);
|
Children.create(new KeywordSearchResultFactory(keywords, things, Presentation.COLLAPSE, searchResultWin), true);
|
||||||
|
|
||||||
rootNode = new AbstractNode(childThingNodes);
|
rootNode = new AbstractNode(childThingNodes);
|
||||||
} else {
|
} else {
|
||||||
@ -144,6 +171,10 @@ public class KeywordSearchQueryManager {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* validate the queries before they are run
|
||||||
|
* @return false if any are invalid
|
||||||
|
*/
|
||||||
public boolean validate() {
|
public boolean validate() {
|
||||||
boolean allValid = true;
|
boolean allValid = true;
|
||||||
for (KeywordSearchQuery tcq : queryDelegates) {
|
for (KeywordSearchQuery tcq : queryDelegates) {
|
||||||
|
@ -42,11 +42,15 @@ import org.sleuthkit.datamodel.AbstractFile;
|
|||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskException;
|
import org.sleuthkit.datamodel.TskException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a normal string (i.e. non-regexp) query to SOLR/Lucene.
|
||||||
|
* By default, matches in all fields.
|
||||||
|
*/
|
||||||
public class LuceneQuery implements KeywordSearchQuery {
|
public class LuceneQuery implements KeywordSearchQuery {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(LuceneQuery.class.getName());
|
private static final Logger logger = Logger.getLogger(LuceneQuery.class.getName());
|
||||||
private String query; //original unescaped query
|
private String keywordString; //original unescaped query
|
||||||
private String queryEscaped;
|
private String keywordStringEscaped;
|
||||||
private boolean isEscaped;
|
private boolean isEscaped;
|
||||||
private Keyword keywordQuery = null;
|
private Keyword keywordQuery = null;
|
||||||
private final List <KeywordQueryFilter> filters = new ArrayList<KeywordQueryFilter>();
|
private final List <KeywordQueryFilter> filters = new ArrayList<KeywordQueryFilter>();
|
||||||
@ -61,14 +65,22 @@ public class LuceneQuery implements KeywordSearchQuery {
|
|||||||
|
|
||||||
private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT);
|
private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor with query to process.
|
||||||
|
* @param keywordQuery
|
||||||
|
*/
|
||||||
public LuceneQuery(Keyword keywordQuery) {
|
public LuceneQuery(Keyword keywordQuery) {
|
||||||
this(keywordQuery.getQuery());
|
this(keywordQuery.getQuery());
|
||||||
this.keywordQuery = keywordQuery;
|
this.keywordQuery = keywordQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor with keyword string to process
|
||||||
|
* @param queryStr Keyword to search for
|
||||||
|
*/
|
||||||
public LuceneQuery(String queryStr) {
|
public LuceneQuery(String queryStr) {
|
||||||
this.query = queryStr;
|
this.keywordString = queryStr;
|
||||||
this.queryEscaped = queryStr;
|
this.keywordStringEscaped = queryStr;
|
||||||
isEscaped = false;
|
isEscaped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +96,7 @@ public class LuceneQuery implements KeywordSearchQuery {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void escape() {
|
public void escape() {
|
||||||
queryEscaped = KeywordSearchUtil.escapeLuceneQuery(query);
|
keywordStringEscaped = KeywordSearchUtil.escapeLuceneQuery(keywordString);
|
||||||
isEscaped = true;
|
isEscaped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,12 +112,12 @@ public class LuceneQuery implements KeywordSearchQuery {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getEscapedQueryString() {
|
public String getEscapedQueryString() {
|
||||||
return this.queryEscaped;
|
return this.keywordStringEscaped;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getQueryString() {
|
public String getQueryString() {
|
||||||
return this.query;
|
return this.keywordString;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -117,7 +129,7 @@ public class LuceneQuery implements KeywordSearchQuery {
|
|||||||
public Map<String, List<ContentHit>> performQuery() throws NoOpenCoreException {
|
public Map<String, List<ContentHit>> performQuery() throws NoOpenCoreException {
|
||||||
Map<String, List<ContentHit>> results = new HashMap<String, List<ContentHit>>();
|
Map<String, List<ContentHit>> results = new HashMap<String, List<ContentHit>>();
|
||||||
//in case of single term literal query there is only 1 term
|
//in case of single term literal query there is only 1 term
|
||||||
results.put(query, performLuceneQuery());
|
results.put(keywordString, performLuceneQuery());
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@ -125,7 +137,7 @@ public class LuceneQuery implements KeywordSearchQuery {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validate() {
|
public boolean validate() {
|
||||||
return query != null && !query.equals("");
|
return keywordString != null && !keywordString.equals("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -192,7 +204,7 @@ public class LuceneQuery implements KeywordSearchQuery {
|
|||||||
q.setShowDebugInfo(DEBUG); //debug
|
q.setShowDebugInfo(DEBUG); //debug
|
||||||
|
|
||||||
//set query, force quotes/grouping around all literal queries
|
//set query, force quotes/grouping around all literal queries
|
||||||
final String groupedQuery = KeywordSearchUtil.quoteQuery(queryEscaped);
|
final String groupedQuery = KeywordSearchUtil.quoteQuery(keywordStringEscaped);
|
||||||
String theQueryStr = groupedQuery;
|
String theQueryStr = groupedQuery;
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
//use the optional field
|
//use the optional field
|
||||||
@ -262,10 +274,10 @@ public class LuceneQuery implements KeywordSearchQuery {
|
|||||||
|
|
||||||
|
|
||||||
} catch (NoOpenCoreException ex) {
|
} catch (NoOpenCoreException ex) {
|
||||||
logger.log(Level.WARNING, "Error executing Lucene Solr Query: " + query, ex);
|
logger.log(Level.WARNING, "Error executing Lucene Solr Query: " + keywordString, ex);
|
||||||
throw ex;
|
throw ex;
|
||||||
} catch (KeywordSearchModuleException ex) {
|
} catch (KeywordSearchModuleException ex) {
|
||||||
logger.log(Level.WARNING, "Error executing Lucene Solr Query: " + query, ex);
|
logger.log(Level.WARNING, "Error executing Lucene Solr Query: " + keywordString, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -67,8 +67,8 @@ import org.apache.solr.client.solrj.impl.XMLResponseParser;
|
|||||||
*/
|
*/
|
||||||
public class Server {
|
public class Server {
|
||||||
|
|
||||||
|
// field names that are used in SOLR schema
|
||||||
public static enum Schema {
|
public static enum Schema {
|
||||||
|
|
||||||
ID {
|
ID {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@ -99,24 +99,28 @@ public class Server {
|
|||||||
return "file_name";
|
return "file_name";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// note that we no longer index this field
|
||||||
CTIME {
|
CTIME {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ctime";
|
return "ctime";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// note that we no longer index this field
|
||||||
ATIME {
|
ATIME {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "atime";
|
return "atime";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// note that we no longer index this field
|
||||||
MTIME {
|
MTIME {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "mtime";
|
return "mtime";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// note that we no longer index this field
|
||||||
CRTIME {
|
CRTIME {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@ -151,7 +155,7 @@ public class Server {
|
|||||||
static final int DEFAULT_SOLR_STOP_PORT = 34343;
|
static final int DEFAULT_SOLR_STOP_PORT = 34343;
|
||||||
private int currentSolrServerPort = 0;
|
private int currentSolrServerPort = 0;
|
||||||
private int currentSolrStopPort = 0;
|
private int currentSolrStopPort = 0;
|
||||||
private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT);
|
private static final boolean DEBUG = false;//(Version.getBuildType() == Version.Type.DEVELOPMENT);
|
||||||
|
|
||||||
public enum CORE_EVT_STATES {
|
public enum CORE_EVT_STATES {
|
||||||
|
|
||||||
@ -802,7 +806,7 @@ public class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute Solr query to get content text
|
* Get the text contents of the given file as stored in SOLR.
|
||||||
*
|
*
|
||||||
* @param content to get the text for
|
* @param content to get the text for
|
||||||
* @return content text string or null on error
|
* @return content text string or null on error
|
||||||
@ -816,7 +820,7 @@ public class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute Solr query to get content text from content chunk
|
* Get the text contents of a single chunk for the given file as stored in SOLR.
|
||||||
*
|
*
|
||||||
* @param content to get the text for
|
* @param content to get the text for
|
||||||
* @param chunkID chunk number to query (starting at 1), or 0 if there is no
|
* @param chunkID chunk number to query (starting at 1), or 0 if there is no
|
||||||
@ -962,6 +966,12 @@ public class Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the text from the content field for the given file
|
||||||
|
* @param contentID
|
||||||
|
* @param chunkID
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private String getSolrContent(long contentID, int chunkID) {
|
private String getSolrContent(long contentID, int chunkID) {
|
||||||
final SolrQuery q = new SolrQuery();
|
final SolrQuery q = new SolrQuery();
|
||||||
q.setQuery("*:*");
|
q.setQuery("*:*");
|
||||||
|
@ -41,6 +41,10 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
|
|||||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||||
import org.sleuthkit.datamodel.TskException;
|
import org.sleuthkit.datamodel.TskException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a regular expression query to the SOLR/Lucene instance.
|
||||||
|
*/
|
||||||
public class TermComponentQuery implements KeywordSearchQuery {
|
public class TermComponentQuery implements KeywordSearchQuery {
|
||||||
|
|
||||||
private static final int TERMS_UNLIMITED = -1;
|
private static final int TERMS_UNLIMITED = -1;
|
||||||
|
@ -58,6 +58,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
|||||||
import org.sleuthkit.datamodel.DerivedFile;
|
import org.sleuthkit.datamodel.DerivedFile;
|
||||||
import org.sleuthkit.datamodel.ReadContentInputStream;
|
import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 7Zip ingest module Extracts supported archives, adds extracted DerivedFiles,
|
* 7Zip ingest module Extracts supported archives, adds extracted DerivedFiles,
|
||||||
@ -164,6 +165,16 @@ public final class SevenZipIngestModule extends IngestModuleAbstractFile {
|
|||||||
logger.log(Level.WARNING, "Skipping processing, module not initialized, file: " + abstractFile.getName());
|
logger.log(Level.WARNING, "Skipping processing, module not initialized, file: " + abstractFile.getName());
|
||||||
return ProcessResult.OK;
|
return ProcessResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//skip unalloc
|
||||||
|
if(abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)) {
|
||||||
|
return IngestModuleAbstractFile.ProcessResult.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip known
|
||||||
|
if (abstractFile.getKnown().equals(TskData.FileKnown.KNOWN)) {
|
||||||
|
return IngestModuleAbstractFile.ProcessResult.OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (abstractFile.isFile() == false || !isSupported(abstractFile)) {
|
if (abstractFile.isFile() == false || !isSupported(abstractFile)) {
|
||||||
//do not process dirs and files that are not supported
|
//do not process dirs and files that are not supported
|
||||||
|
@ -1,118 +1,125 @@
|
|||||||
<project name="AutopsyTSKTargets">
|
<project name="AutopsyTSKTargets">
|
||||||
|
|
||||||
<!-- Need a way to specify TSK Debug versus Release -->
|
<!-- Need a way to specify TSK Debug versus Release -->
|
||||||
<property name="TSK_BUILD_TYPE">Release</property>
|
<property name="TSK_BUILD_TYPE">Release</property>
|
||||||
|
|
||||||
<target name="autoAIPath" >
|
<target name="autoAIPath" >
|
||||||
<property name="AI.path">C:\Program Files (x86)\Caphyon\Advanced Installer 10.2\bin\x86\AdvancedInstaller.com</property>
|
<property name="AI.path">C:\Program Files (x86)\Caphyon\Advanced Installer 10.3\bin\x86\AdvancedInstaller.com</property>
|
||||||
<available file="${AI.path}"
|
<available file="${AI.path}"
|
||||||
property="aiPath"
|
property="ai-exe-path"
|
||||||
value="${AI.path}"/>
|
value="${AI.path}"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="inputAIPath" unless="aiPath">
|
<target name="inputAIPath" unless="ai-exe-path">
|
||||||
<input addProperty="aiPath"
|
<input addProperty="ai-exe-path"
|
||||||
message="Enter the location of AdvancedInstaller.com"/>
|
message="Enter the location of AdvancedInstaller.com"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="run-advanced-installer" depends="autoAIPath,inputAIPath">
|
<target name="run-advanced-installer" depends="autoAIPath,inputAIPath">
|
||||||
<fail unless="aiPath" message="Could not locate Advanced Installer."/>
|
<fail unless="ai-exe-path" message="Could not locate Advanced Installer."/>
|
||||||
<copy file="${basedir}/installer_${app.name}/installer_${app.name}.aip" tofile="${nbdist.dir}/installer_${app.name}.aip"/>
|
<!-- Copy the template file to add details to -->
|
||||||
<scriptdef name="generateguid" language="javascript">
|
<copy file="${basedir}/installer_${app.name}/installer_${app.name}.aip" tofile="${nbdist.dir}/installer_${app.name}.aip" overwrite="true"/>
|
||||||
<attribute name="property" />
|
<scriptdef name="generateguid" language="javascript">
|
||||||
<![CDATA[
|
<attribute name="property" />
|
||||||
importClass( java.util.UUID );
|
<![CDATA[
|
||||||
|
importClass( java.util.UUID );
|
||||||
project.setProperty( attributes.get( "property" ), UUID.randomUUID() );
|
|
||||||
]]>
|
project.setProperty( attributes.get( "property" ), UUID.randomUUID() );
|
||||||
</scriptdef>
|
]]>
|
||||||
<generateguid property="guid1" />
|
</scriptdef>
|
||||||
<property name="inst-path" value="${nbdist.dir}\${app.name}-installer"/>
|
<generateguid property="guid1" />
|
||||||
<property name="proj-path" value="${nbdist.dir}\installer_${app.name}.aip"/>
|
<property name="inst-path" value="${nbdist.dir}\${app.name}-installer"/>
|
||||||
<!-- automatically replace version name and productcode in the .aip file -->
|
<property name="aip-path" value="${nbdist.dir}\installer_${app.name}.aip"/>
|
||||||
<echo>Product Code: ${guid1}</echo>
|
<!-- automatically replace version name and productcode in the .aip file -->
|
||||||
<replaceregexp file="${proj-path}"
|
<echo>Product Code: ${guid1}</echo>
|
||||||
match="ProductCode" Value="(\d{4}+:.)\w{8}+-\w{4}+-\w{4}+-\w{4}+-\w{12}+"
|
<echo>Product Version: ${app.version}</echo>
|
||||||
replace="ProductCode" Value="\1${guid1}" />
|
|
||||||
<echo>Product Version: ${app.version}</echo>
|
<!-- Edit the API file to update versions: manual approach allows us to use non-X.Y.Z versions -->
|
||||||
<replaceregexp file="${proj-path}"
|
<replaceregexp file="${aip-path}"
|
||||||
match="ProductVersion" Value="\d+\.{1}\d+\.{1}\d+"
|
match="ProductCode" Value="(\d{4}+:.)\w{8}+-\w{4}+-\w{4}+-\w{4}+-\w{12}+"
|
||||||
replace="ProductVersion" Value="${app.version}" />
|
replace="ProductCode" Value="\1${guid1}" />
|
||||||
<echo message="Adding files to installer..."/>
|
|
||||||
<exec executable="${aiPath}">
|
<replaceregexp file="${aip-path}"
|
||||||
<arg line="/edit ${proj-path} /AddFolder APPDIR ${inst-path}\bin"/>
|
match="ProductVersion" Value="\d+\.{1}\d+\.{1}\d+"
|
||||||
</exec>
|
replace="ProductVersion" Value="${app.version}" />
|
||||||
<exec executable="${aiPath}">
|
|
||||||
<arg line="/edit ${proj-path} /AddFolder APPDIR ${inst-path}\etc"/>
|
<!-- Use Advanced Installer to configure files to add -->
|
||||||
</exec>
|
<echo message="Adding files to installer..."/>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /AddFolder APPDIR ${inst-path}\gstreamer"/>
|
<arg line="/edit ${aip-path} /AddFolder APPDIR ${inst-path}\bin"/>
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /AddFolder APPDIR ${inst-path}\harness"/>
|
<arg line="/edit ${aip-path} /AddFolder APPDIR ${inst-path}\etc"/>
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /AddFolder APPDIR ${inst-path}\java"/>
|
<arg line="/edit ${aip-path} /AddFolder APPDIR ${inst-path}\gstreamer"/>
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /AddFolder APPDIR ${inst-path}\jre"/>
|
<arg line="/edit ${aip-path} /AddFolder APPDIR ${inst-path}\harness"/>
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /AddFolder APPDIR ${inst-path}\platform"/>
|
<arg line="/edit ${aip-path} /AddFolder APPDIR ${inst-path}\java"/>
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /AddFolder APPDIR ${inst-path}\${app.name}"/>
|
<arg line="/edit ${aip-path} /AddFolder APPDIR ${inst-path}\jre"/>
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /AddFile APPDIR ${inst-path}\icon.ico"/>
|
<arg line="/edit ${aip-path} /AddFolder APPDIR ${inst-path}\platform"/>
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /AddFile APPDIR ${inst-path}\KNOWN_ISSUES.txt"/>
|
<arg line="/edit ${aip-path} /AddFolder APPDIR ${inst-path}\${app.name}"/>
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /AddFile APPDIR ${inst-path}\LICENSE-2.0.txt"/>
|
<arg line="/edit ${aip-path} /AddFile APPDIR ${inst-path}\icon.ico"/>
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /AddFile APPDIR ${inst-path}\NEWS.txt"/>
|
<arg line="/edit ${aip-path} /AddFile APPDIR ${inst-path}\KNOWN_ISSUES.txt"/>
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /AddFile APPDIR ${inst-path}\README.txt"/>
|
<arg line="/edit ${aip-path} /AddFile APPDIR ${inst-path}\LICENSE-2.0.txt"/>
|
||||||
</exec>
|
</exec>
|
||||||
|
<exec executable="${ai-exe-path}">
|
||||||
<!-- Need to find a way to deal with beta version -->
|
<arg line="/edit ${aip-path} /AddFile APPDIR ${inst-path}\NEWS.txt"/>
|
||||||
<!--<echo message="Setting ${app.name} version to ${app.version}..."/>
|
</exec>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /SetVersion ${app.version}"/>
|
<arg line="/edit ${aip-path} /AddFile APPDIR ${inst-path}\README.txt"/>
|
||||||
</exec>-->
|
</exec>
|
||||||
|
|
||||||
<echo message="Adding desktop/menu shortcuts..."/>
|
<!-- Need to find a way to deal with beta version -->
|
||||||
<exec executable="${aiPath}">
|
<!--<echo message="Setting ${app.name} version to ${app.version}..."/>
|
||||||
<arg line="/edit ${proj-path} /NewShortcut -name ${app.title} -dir DesktopFolder -target APPDIR\bin\${app.name}.exe -icon ${inst-path}\icon.ico"/>
|
<exec executable="${ai-exe-path}">
|
||||||
</exec>
|
<arg line="/edit ${aip-path} /SetVersion ${app.version}"/>
|
||||||
<exec executable="${aiPath}">
|
</exec>-->
|
||||||
<arg line="/edit ${proj-path} /NewShortcut -name ${app.title} -dir SHORTCUTDIR -target APPDIR\bin\${app.name}.exe -icon ${inst-path}\icon.ico"/>
|
|
||||||
</exec>
|
<echo message="Adding desktop/menu shortcuts..."/>
|
||||||
|
<exec executable="${ai-exe-path}">
|
||||||
<echo message="Setting environment variables..."/>
|
<arg line="/edit ${aip-path} /NewShortcut -name ${app.title} -dir DesktopFolder -target APPDIR\bin\${app.name}.exe -icon ${inst-path}\icon.ico"/>
|
||||||
<exec executable="${aiPath}">
|
</exec>
|
||||||
<arg line="/edit ${proj-path} /NewEnvironment -name GSTREAMER_PATH -value [APPDIR]gstreamer\bin -install_operation CreateUpdate -behavior Append -system_variable"/>
|
<exec executable="${ai-exe-path}">
|
||||||
</exec>
|
<arg line="/edit ${aip-path} /NewShortcut -name ${app.title} -dir SHORTCUTDIR -target APPDIR\bin\${app.name}.exe -icon ${inst-path}\icon.ico"/>
|
||||||
<exec executable="${aiPath}">
|
</exec>
|
||||||
<arg line="/edit ${proj-path} /NewEnvironment -name GSTREAMER_PATH -value [APPDIR]gstreamer\lib\gstreamer-0.10 -install_operation CreateUpdate -behavior Append -system_variable"/>
|
|
||||||
</exec>
|
<echo message="Setting environment variables..."/>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/edit ${proj-path} /NewEnvironment -name PATH -value %GSTREAMER_PATH% -install_operation CreateUpdate -behavior Append -system_variable"/>
|
<arg line="/edit ${aip-path} /NewEnvironment -name GSTREAMER_PATH -value [APPDIR]gstreamer\bin -install_operation CreateUpdate -behavior Append -system_variable"/>
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="${aiPath}">
|
<exec executable="${ai-exe-path}">
|
||||||
<arg line="/build ${proj-path}"/>
|
<arg line="/edit ${aip-path} /NewEnvironment -name GSTREAMER_PATH -value [APPDIR]gstreamer\lib\gstreamer-0.10 -install_operation CreateUpdate -behavior Append -system_variable"/>
|
||||||
</exec>
|
</exec>
|
||||||
<delete file="${proj-path}"/>
|
<exec executable="${ai-exe-path}">
|
||||||
</target>
|
<arg line="/edit ${aip-path} /NewEnvironment -name PATH -value %GSTREAMER_PATH% -install_operation CreateUpdate -behavior Append -system_variable"/>
|
||||||
|
</exec>
|
||||||
<target name="build-installer-windows">
|
<exec executable="${ai-exe-path}">
|
||||||
<antcall target="run-advanced-installer" />
|
<arg line="/build ${aip-path}"/>
|
||||||
<!--<delete dir="${nbdist.dir}/${app.name}-installer"/>-->
|
</exec>
|
||||||
<delete dir="${nbdist.dir}/installer_${app.name}-cache"/>
|
<!--<delete file="${aip-path}"/>-->
|
||||||
<move file="${nbdist.dir}/installer_${app.name}-SetupFiles/installer_${app.name}.msi" tofile="${nbdist.dir}/installer_${app.name}-${app.version}.msi" />
|
</target>
|
||||||
</target>
|
|
||||||
</project>
|
<!-- Makes an installer from the opened ZIP file -->
|
||||||
|
<target name="build-installer-windows">
|
||||||
|
<antcall target="run-advanced-installer" />
|
||||||
|
<!--<delete dir="${nbdist.dir}/${app.name}-installer"/>-->
|
||||||
|
<delete dir="${nbdist.dir}/installer_${app.name}-cache"/>
|
||||||
|
<move file="${nbdist.dir}/installer_${app.name}-SetupFiles/installer_${app.name}.msi" tofile="${nbdist.dir}/installer_${app.name}-${app.version}.msi" />
|
||||||
|
</target>
|
||||||
|
</project>
|
||||||
|
542
build.xml
542
build.xml
@ -1,271 +1,271 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
|
<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
|
||||||
<!-- for some information on what you could do (e.g. targets to override). -->
|
<!-- for some information on what you could do (e.g. targets to override). -->
|
||||||
<!-- If you delete this file and reopen the project it will be recreated. -->
|
<!-- If you delete this file and reopen the project it will be recreated. -->
|
||||||
<project name="Autopsy3" basedir=".">
|
<project name="Autopsy3" basedir=".">
|
||||||
<description>Builds the module suite Autopsy3.</description>
|
<description>Builds the module suite Autopsy3.</description>
|
||||||
|
|
||||||
<import file="nbproject/build-impl.xml"/>
|
<import file="nbproject/build-impl.xml"/>
|
||||||
|
|
||||||
<property name="netbeans-plat-version" value="7.3" />
|
<property name="netbeans-plat-version" value="7.3" />
|
||||||
<property name="nbplatform.active.dir" value="${basedir}/netbeans-plat/${netbeans-plat-version}" />
|
<property name="nbplatform.active.dir" value="${basedir}/netbeans-plat/${netbeans-plat-version}" />
|
||||||
|
|
||||||
<condition property="os.family" value="unix">
|
<condition property="os.family" value="unix">
|
||||||
<os family="unix"/>
|
<os family="unix"/>
|
||||||
</condition>
|
</condition>
|
||||||
<condition property="os.family" value="windows">
|
<condition property="os.family" value="windows">
|
||||||
<os family="windows"/>
|
<os family="windows"/>
|
||||||
</condition>
|
</condition>
|
||||||
<import file="build-${os.family}.xml"/>
|
<import file="build-${os.family}.xml"/>
|
||||||
<property name="test-input" location="Test/input"/>
|
<property name="test-input" location="Test/input"/>
|
||||||
<property name="thirdparty.dir" value="${basedir}/thirdparty" />
|
<property name="thirdparty.dir" value="${basedir}/thirdparty" />
|
||||||
|
|
||||||
<!-- import ant-contrib tools -->
|
<!-- import ant-contrib tools -->
|
||||||
<property name="ant-contrib.dir" value="${thirdparty.dir}/ant-contrib/1.0b3" />
|
<property name="ant-contrib.dir" value="${thirdparty.dir}/ant-contrib/1.0b3" />
|
||||||
<property name="ant.contrib.jar" value="${ant-contrib.dir}/ant-contrib.jar" />
|
<property name="ant.contrib.jar" value="${ant-contrib.dir}/ant-contrib.jar" />
|
||||||
<taskdef resource="net/sf/antcontrib/antlib.xml">
|
<taskdef resource="net/sf/antcontrib/antlib.xml">
|
||||||
<classpath>
|
<classpath>
|
||||||
<pathelement location="${ant.contrib.jar}"/>
|
<pathelement location="${ant.contrib.jar}"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
</taskdef>
|
</taskdef>
|
||||||
|
|
||||||
|
|
||||||
<!-- This seems really bad to be hard coded, but I couldn't find a better solution -->
|
<!-- This seems really bad to be hard coded, but I couldn't find a better solution -->
|
||||||
<path id="jni-path">
|
<path id="jni-path">
|
||||||
<pathelement location="${basedir}/build/cluster/modules/org-sleuthkit-datamodel.jar"/>
|
<pathelement location="${basedir}/build/cluster/modules/org-sleuthkit-datamodel.jar"/>
|
||||||
<path refid="cluster.path.id" />
|
<path refid="cluster.path.id" />
|
||||||
</path>
|
</path>
|
||||||
|
|
||||||
<!-- Verify that the TSK_HOME env variable is set -->
|
<!-- Verify that the TSK_HOME env variable is set -->
|
||||||
<target name="findTSK">
|
<target name="findTSK">
|
||||||
<property environment="env"/>
|
<property environment="env"/>
|
||||||
<condition property="tskFound">
|
<condition property="tskFound">
|
||||||
<isset property="env.TSK_HOME"/>
|
<isset property="env.TSK_HOME"/>
|
||||||
</condition>
|
</condition>
|
||||||
<fail unless="tskFound" message="TSK_HOME must be set as an environment variable."/>
|
<fail unless="tskFound" message="TSK_HOME must be set as an environment variable."/>
|
||||||
<echo> TSK_HOME: ${env.TSK_HOME}</echo>
|
<echo> TSK_HOME: ${env.TSK_HOME}</echo>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- Verify that the JRE_HOME env variable is set -->
|
<!-- Verify that the JRE_HOME env variable is set -->
|
||||||
<target name="findJRE">
|
<target name="findJRE">
|
||||||
<property environment="env"/>
|
<property environment="env"/>
|
||||||
<condition property="jreFound">
|
<condition property="jreFound">
|
||||||
<isset property="env.JRE_HOME"/>
|
<isset property="env.JRE_HOME"/>
|
||||||
</condition>
|
</condition>
|
||||||
<fail unless="jreFound" message="JRE_HOME must be set as an environment variable."/>
|
<fail unless="jreFound" message="JRE_HOME must be set as an environment variable."/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="getJunit">
|
<target name="getJunit">
|
||||||
<property name="junit.dir" value="${thirdparty.dir}/junit/${netbeans-plat-version}" />
|
<property name="junit.dir" value="${thirdparty.dir}/junit/${netbeans-plat-version}" />
|
||||||
<unzip src="${junit.dir}/junit.zip" dest="${nbplatform.active.dir}"/>
|
<unzip src="${junit.dir}/junit.zip" dest="${nbplatform.active.dir}"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- This target will create a custom ZIP file for us. It first uses the general
|
<!-- This target will create a custom ZIP file for us. It first uses the general
|
||||||
ZIP target and then opens it up and adds in any files that we want. This is where we customize the
|
ZIP target and then opens it up and adds in any files that we want. This is where we customize the
|
||||||
version number. -->
|
version number. -->
|
||||||
<target name="build-zip" depends="suite.build-zip,findJRE">
|
<target name="build-zip" depends="suite.build-zip,findJRE">
|
||||||
<property name="nbdist.dir" value="dist"/>
|
<property name="nbdist.dir" value="dist"/>
|
||||||
<property name="release.dir" value="${nbdist.dir}/${app.name}"/>
|
<property name="release.dir" value="${nbdist.dir}/${app.name}"/>
|
||||||
|
|
||||||
<!-- step (2) unzip the result -->
|
<!-- step (2) unzip the result -->
|
||||||
<property name="zip-tmp" value="${nbdist.dir}/tmp"/>
|
<property name="zip-tmp" value="${nbdist.dir}/tmp"/>
|
||||||
<delete dir="${zip-tmp}"/>
|
<delete dir="${zip-tmp}"/>
|
||||||
<mkdir dir="${zip-tmp}"/>
|
<mkdir dir="${zip-tmp}"/>
|
||||||
<unzip src="${nbdist.dir}/${app.name}.zip" dest="${zip-tmp}"/>
|
<unzip src="${nbdist.dir}/${app.name}.zip" dest="${zip-tmp}"/>
|
||||||
|
|
||||||
<!-- step (3) do your copying stuff here, check the ant doc for copy, move, etc file -->
|
<!-- step (3) do your copying stuff here, check the ant doc for copy, move, etc file -->
|
||||||
<copy file="${basedir}/README.txt" tofile="${zip-tmp}/${app.name}/README.txt"/>
|
<copy file="${basedir}/README.txt" tofile="${zip-tmp}/${app.name}/README.txt"/>
|
||||||
<copy file="${basedir}/LICENSE-2.0.txt" tofile="${zip-tmp}/${app.name}/LICENSE-2.0.txt"/>
|
<copy file="${basedir}/LICENSE-2.0.txt" tofile="${zip-tmp}/${app.name}/LICENSE-2.0.txt"/>
|
||||||
<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}/KNOWN_ISSUES.txt" tofile="${zip-tmp}/${app.name}/KNOWN_ISSUES.txt"/>
|
<copy file="${basedir}/KNOWN_ISSUES.txt" tofile="${zip-tmp}/${app.name}/KNOWN_ISSUES.txt"/>
|
||||||
|
|
||||||
<unzip src="${thirdparty.dir}/gstreamer/${os.family}/i386/0.10.7/gstreamer.zip" dest="${zip-tmp}/${app.name}/gstreamer"/>
|
<unzip src="${thirdparty.dir}/gstreamer/${os.family}/i386/0.10.7/gstreamer.zip" dest="${zip-tmp}/${app.name}/gstreamer"/>
|
||||||
<copy todir="${zip-tmp}/${app.name}/jre">
|
<copy todir="${zip-tmp}/${app.name}/jre">
|
||||||
<fileset dir="${env.JRE_HOME}"/>
|
<fileset dir="${env.JRE_HOME}"/>
|
||||||
</copy>
|
</copy>
|
||||||
<copy file="${basedir}/branding_${app.name}/icon.ico" tofile="${zip-tmp}/${app.name}/icon.ico" overwrite="true"/>
|
<copy file="${basedir}/branding_${app.name}/icon.ico" tofile="${zip-tmp}/${app.name}/icon.ico" overwrite="true"/>
|
||||||
|
|
||||||
<property name="app.property.file" value="${zip-tmp}/${app.name}/etc/${app.name}.conf" />
|
<property name="app.property.file" value="${zip-tmp}/${app.name}/etc/${app.name}.conf" />
|
||||||
<property name="jvm.options" value=""--branding ${app.name} -J-Xms24m -J-Xmx512m -J-XX:MaxPermSize=128M -J-Xverify:none"" />
|
<property name="jvm.options" value=""--branding ${app.name} -J-Xms24m -J-Xmx512m -J-XX:MaxPermSize=128M -J-Xverify:none"" />
|
||||||
<propertyfile file="${app.property.file}">
|
<propertyfile file="${app.property.file}">
|
||||||
<!-- Note: can be higher on 64 bit systems, should be in sync with project.properties -->
|
<!-- Note: can be higher on 64 bit systems, should be in sync with project.properties -->
|
||||||
<entry key="default_options" value="@JVM_OPTIONS" />
|
<entry key="default_options" value="@JVM_OPTIONS" />
|
||||||
<entry key="jdkhome" value=""jre"" />
|
<entry key="jdkhome" value=""jre"" />
|
||||||
</propertyfile>
|
</propertyfile>
|
||||||
<!-- workaround for ant escaping : and = when setting properties -->
|
<!-- workaround for ant escaping : and = when setting properties -->
|
||||||
<replace file="${app.property.file}" token="@JVM_OPTIONS" value="${jvm.options}" />
|
<replace file="${app.property.file}" token="@JVM_OPTIONS" value="${jvm.options}" />
|
||||||
|
|
||||||
<!-- We want to remove the dlls in autopsy/modules/lib because they will
|
<!-- We want to remove the dlls in autopsy/modules/lib because they will
|
||||||
shadow the files in the autopsy/modules/lib/ARCHITECTURE folder -->
|
shadow the files in the autopsy/modules/lib/ARCHITECTURE folder -->
|
||||||
<delete failonerror="false">
|
<delete failonerror="false">
|
||||||
<fileset dir="${zip-tmp}/${app.name}/autopsy/modules/lib">
|
<fileset dir="${zip-tmp}/${app.name}/autopsy/modules/lib">
|
||||||
<include name="libtsk_jni.dll" />
|
<include name="libtsk_jni.dll" />
|
||||||
<include name="libewf.dll" />
|
<include name="libewf.dll" />
|
||||||
<include name="zlib.dll" />
|
<include name="zlib.dll" />
|
||||||
</fileset>
|
</fileset>
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
<!-- step (4) zip again, but with the version numbers in the dir -->
|
<!-- step (4) zip again, but with the version numbers in the dir -->
|
||||||
<zip destfile="${nbdist.dir}/${app.name}-${app.version}.zip">
|
<zip destfile="${nbdist.dir}/${app.name}-${app.version}.zip">
|
||||||
<zipfileset dir="${zip-tmp}/${app.name}"/>
|
<zipfileset dir="${zip-tmp}/${app.name}"/>
|
||||||
</zip>
|
</zip>
|
||||||
|
|
||||||
<delete dir="${zip-tmp}"/>
|
<delete dir="${zip-tmp}"/>
|
||||||
<!-- <delete file="${nbdist.dir}/${app.name}.zip"/> -->
|
<!-- <delete file="${nbdist.dir}/${app.name}.zip"/> -->
|
||||||
|
|
||||||
<echo message=" "/>
|
<echo message=" "/>
|
||||||
<echo message="cleaning and finalizing release" />
|
<echo message="cleaning and finalizing release" />
|
||||||
<delete dir="${release.dir}"/>
|
<delete dir="${release.dir}"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="getProps" depends="prop-files,input-build-type,input-version"></target>
|
<target name="getProps" depends="prop-files,input-build-type,input-version"></target>
|
||||||
|
|
||||||
<target name="prop-files">
|
<target name="prop-files">
|
||||||
<property file="nbproject/private/private.properties"/>
|
<property file="nbproject/private/private.properties"/>
|
||||||
<property file="nbproject/project.properties"/>
|
<property file="nbproject/project.properties"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="input-build-type" unless="build.type">
|
<target name="input-build-type" unless="build.type">
|
||||||
<input addProperty="build.type"
|
<input addProperty="build.type"
|
||||||
message="Enter the desired build type:"
|
message="Enter the desired build type:"
|
||||||
validargs="DEVELOPMENT,RELEASE"
|
validargs="DEVELOPMENT,RELEASE"
|
||||||
defaultvalue="DEVELOPMENT"/>
|
defaultvalue="DEVELOPMENT"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="input-version" unless="app.version">
|
<target name="input-version" unless="app.version">
|
||||||
<tstamp/>
|
<tstamp/>
|
||||||
<property name="app.version" value="${DSTAMP}"/>
|
<property name="app.version" value="${DSTAMP}"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="-init" depends="-taskdefs,-convert-old-project,getProps,getJunit">
|
<target name="-init" depends="-taskdefs,-convert-old-project,getProps,getJunit">
|
||||||
<convertclusterpath from="${cluster.path.evaluated}" to="cluster.path.final" id="cluster.path.id"/>
|
<convertclusterpath from="${cluster.path.evaluated}" to="cluster.path.final" id="cluster.path.id"/>
|
||||||
<sortsuitemodules unsortedmodules="${modules}" sortedmodulesproperty="modules.sorted"/>
|
<sortsuitemodules unsortedmodules="${modules}" sortedmodulesproperty="modules.sorted"/>
|
||||||
<property name="cluster" location="build/cluster"/>
|
<property name="cluster" location="build/cluster"/>
|
||||||
<echo level="verbose">Suite in ${basedir} with clusters ${cluster.path.final}, build cluster ${cluster}, and sorted modules ${modules.sorted}</echo>
|
<echo level="verbose">Suite in ${basedir} with clusters ${cluster.path.final}, build cluster ${cluster}, and sorted modules ${modules.sorted}</echo>
|
||||||
<!-- synchronize with SuiteProject -->
|
<!-- synchronize with SuiteProject -->
|
||||||
<property name="disabled.modules" value=""/>
|
<property name="disabled.modules" value=""/>
|
||||||
<property name="enabled.clusters" value=""/>
|
<property name="enabled.clusters" value=""/>
|
||||||
<property name="disabled.clusters" value=""/>
|
<property name="disabled.clusters" value=""/>
|
||||||
<condition property="branding.dir" value="branding_${app.name}">
|
<condition property="branding.dir" value="branding_${app.name}">
|
||||||
<not>
|
<not>
|
||||||
<equals arg1="${app.name}" arg2="autopsy"/>
|
<equals arg1="${app.name}" arg2="autopsy"/>
|
||||||
</not>
|
</not>
|
||||||
</condition>
|
</condition>
|
||||||
<property name="branding.dir" location="branding"/>
|
<property name="branding.dir" location="branding"/>
|
||||||
<property name="dist.dir" location="dist"/>
|
<property name="dist.dir" location="dist"/>
|
||||||
<!-- MOVE THE .DLL FILES TO THE NETBEANS DIRECTORY -->
|
<!-- MOVE THE .DLL FILES TO THE NETBEANS DIRECTORY -->
|
||||||
|
|
||||||
<condition property="run.branding"> <!-- #84689 -->
|
<condition property="run.branding"> <!-- #84689 -->
|
||||||
<and>
|
<and>
|
||||||
<available file="${branding.dir}" type="dir"/>
|
<available file="${branding.dir}" type="dir"/>
|
||||||
<isset property="branding.token"/>
|
<isset property="branding.token"/>
|
||||||
</and>
|
</and>
|
||||||
</condition>
|
</condition>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- override build to add branding -->
|
<!-- override build to add branding -->
|
||||||
<target name="build" depends="build-brand,suite.build" description="Compiles autopsy and produces a basic branded build that can run on a dev. system" />
|
<target name="build" depends="build-brand,suite.build" description="Compiles autopsy and produces a basic branded build that can run on a dev. system" />
|
||||||
|
|
||||||
<target name="build-brand" depends="-init">
|
<target name="build-brand" depends="-init">
|
||||||
|
|
||||||
<echo>${app.name} branding</echo>
|
<echo>${app.name} branding</echo>
|
||||||
|
|
||||||
<copy file="${basedir}/branding_${app.name}/welcome_logo.png" tofile="${basedir}/Core/src/org/sleuthkit/autopsy/casemodule/welcome_logo.png" overwrite="true"/>
|
<copy file="${basedir}/branding_${app.name}/welcome_logo.png" tofile="${basedir}/Core/src/org/sleuthkit/autopsy/casemodule/welcome_logo.png" overwrite="true"/>
|
||||||
|
|
||||||
<propertyfile
|
<propertyfile
|
||||||
file="${branding.dir}/core/core.jar/org/netbeans/core/startup/Bundle.properties"
|
file="${branding.dir}/core/core.jar/org/netbeans/core/startup/Bundle.properties"
|
||||||
comment="Updated by build script">
|
comment="Updated by build script">
|
||||||
<entry key="currentVersion" value="${app.title} ${app.version}" />
|
<entry key="currentVersion" value="${app.title} ${app.version}" />
|
||||||
</propertyfile>
|
</propertyfile>
|
||||||
|
|
||||||
<propertyfile
|
<propertyfile
|
||||||
file="${branding.dir}/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties"
|
file="${branding.dir}/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties"
|
||||||
comment="Updated by build script">
|
comment="Updated by build script">
|
||||||
<entry key="CTL_MainWindow_Title" value="${app.title} ${app.version}" />
|
<entry key="CTL_MainWindow_Title" value="${app.title} ${app.version}" />
|
||||||
<entry key="CTL_MainWindow_Title_No_Project" value="${app.title} ${app.version}" />
|
<entry key="CTL_MainWindow_Title_No_Project" value="${app.title} ${app.version}" />
|
||||||
</propertyfile>
|
</propertyfile>
|
||||||
|
|
||||||
<propertyfile
|
<propertyfile
|
||||||
file="${basedir}/Core/src/org/sleuthkit/autopsy/coreutils/Version.properties"
|
file="${basedir}/Core/src/org/sleuthkit/autopsy/coreutils/Version.properties"
|
||||||
comment="Updated by build script">
|
comment="Updated by build script">
|
||||||
<entry key="app.name" value="${app.title}" />
|
<entry key="app.name" value="${app.title}" />
|
||||||
<entry key="app.version" value="${app.version}" />
|
<entry key="app.version" value="${app.version}" />
|
||||||
<entry key="build.type" value="${build.type}" />
|
<entry key="build.type" value="${build.type}" />
|
||||||
</propertyfile>
|
</propertyfile>
|
||||||
|
|
||||||
<copy todir="${basedir}" failonerror="false">
|
<copy todir="${basedir}" failonerror="false">
|
||||||
<fileset dir="${branding.dir}/bundles"
|
<fileset dir="${branding.dir}/bundles"
|
||||||
includes="**/*"/>
|
includes="**/*"/>
|
||||||
</copy>
|
</copy>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="jni" depends="build,findTSK">
|
<target name="jni" depends="build,findTSK">
|
||||||
<javah verbose="yes" outputFile="${env.TSK_HOME}/bindings/java/tsk_jni/tsk_jni/dataModel_SleuthkitJNI.h">
|
<javah verbose="yes" outputFile="${env.TSK_HOME}/bindings/java/tsk_jni/tsk_jni/dataModel_SleuthkitJNI.h">
|
||||||
<class name="org.sleuthkit.datamodel.SleuthkitJNI" />
|
<class name="org.sleuthkit.datamodel.SleuthkitJNI" />
|
||||||
<classpath refid="jni-path"/>
|
<classpath refid="jni-path"/>
|
||||||
</javah>
|
</javah>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
<target name="doxygen" description="build doxygen docs, requires doxygen in PATH" depends="-init,-hide-excluded-modules">
|
<target name="doxygen" description="build doxygen docs, requires doxygen in PATH" depends="-init,-hide-excluded-modules">
|
||||||
<exec executable="doxygen" dir="${basedir}/docs/doxygen">
|
<exec executable="doxygen" dir="${basedir}/docs/doxygen">
|
||||||
<arg value="Doxyfile"/>
|
<arg value="Doxyfile"/>
|
||||||
</exec>
|
</exec>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="check-release">
|
<target name="check-release">
|
||||||
<condition property="is-release">
|
<condition property="is-release">
|
||||||
<and>
|
<and>
|
||||||
<equals arg1="${build.type}" arg2="RELEASE"/>
|
<equals arg1="${build.type}" arg2="RELEASE"/>
|
||||||
<isset property="update_versions"/>
|
<isset property="update_versions"/>
|
||||||
<equals arg1="${update_versions}" arg2="true"/>
|
<equals arg1="${update_versions}" arg2="true"/>
|
||||||
</and>
|
</and>
|
||||||
</condition>
|
</condition>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="versioning-script-if-release" if="is-release">
|
<target name="versioning-script-if-release" if="is-release">
|
||||||
<exec dir="${basedir}" executable="python" failonerror="true">
|
<exec dir="${basedir}" executable="python" failonerror="true">
|
||||||
<arg line="update_versions.py -a" />
|
<arg line="update_versions.py -a" />
|
||||||
</exec>
|
</exec>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="versioning-script-if-not-release" unless="is-release">
|
<target name="versioning-script-if-not-release" unless="is-release">
|
||||||
<exec dir="${basedir}" executable="python" failonerror="true">
|
<exec dir="${basedir}" executable="python" failonerror="true">
|
||||||
<arg value="update_versions.py" />
|
<arg value="update_versions.py" />
|
||||||
</exec>
|
</exec>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="versioning-script" depends="check-release, versioning-script-if-release, versioning-script-if-not-release"/>
|
<target name="versioning-script" depends="check-release, versioning-script-if-release, versioning-script-if-not-release"/>
|
||||||
|
|
||||||
<target name="build-installer-dir" depends="getProps, versioning-script, build-zip" description="Builds Autopsy with branding and all dependencies" >
|
<target name="build-installer-dir" depends="getProps, versioning-script, build-zip" description="Builds Autopsy with branding and all dependencies" >
|
||||||
<unzip src="${nbdist.dir}/${app.name}-${app.version}.zip" dest="${nbdist.dir}/${app.name}-installer"/>
|
<unzip src="${nbdist.dir}/${app.name}-${app.version}.zip" dest="${nbdist.dir}/${app.name}-installer"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="build-installer" depends="build-installer-dir" description="Builds Autopsy installer.">
|
<target name="build-installer" depends="build-installer-dir" description="Builds Autopsy installer.">
|
||||||
<antcall target="build-installer-${os.family}" />
|
<antcall target="build-installer-${os.family}" />
|
||||||
</target>
|
</target>
|
||||||
<target name="test-download-imgs" description="Get test images and store them in the path represented by the test-input variable.">
|
<target name="test-download-imgs" description="Get test images and store them in the path represented by the test-input variable.">
|
||||||
<available file="${test-input}/nps-2008-jean.E01" property="img-present-1"/>
|
<available file="${test-input}/nps-2008-jean.E01" property="img-present-1"/>
|
||||||
<available file="${test-input}/nps-2008-jean.E02" property="img-present-2"/>
|
<available file="${test-input}/nps-2008-jean.E02" property="img-present-2"/>
|
||||||
<if>
|
<if>
|
||||||
<equals arg1="${img-present-1}" arg2="true"/>
|
<equals arg1="${img-present-1}" arg2="true"/>
|
||||||
<then>
|
<then>
|
||||||
<echo message = "nps-2008-jean.E01 already present."/>
|
<echo message = "nps-2008-jean.E01 already present."/>
|
||||||
</then>
|
</then>
|
||||||
<else>
|
<else>
|
||||||
<mkdir dir="${test-input}" />
|
<mkdir dir="${test-input}" />
|
||||||
<get src="http://digitalcorpora.org/corp/nps/drives/nps-2008-jean/nps-2008-jean.E01" dest="${test-input}"/>
|
<get src="http://digitalcorpora.org/corp/nps/drives/nps-2008-jean/nps-2008-jean.E01" dest="${test-input}"/>
|
||||||
</else>
|
</else>
|
||||||
</if>
|
</if>
|
||||||
<if>
|
<if>
|
||||||
<equals arg1="${img-present-2}" arg2="true"/>
|
<equals arg1="${img-present-2}" arg2="true"/>
|
||||||
<then>
|
<then>
|
||||||
<echo message = "nps-2008-jean.E02 already present."/>
|
<echo message = "nps-2008-jean.E02 already present."/>
|
||||||
</then>
|
</then>
|
||||||
<else>
|
<else>
|
||||||
<mkdir dir="${test-input}" />
|
<mkdir dir="${test-input}" />
|
||||||
<get src="http://digitalcorpora.org/corp/nps/drives/nps-2008-jean/nps-2008-jean.E02" dest="${test-input}"/>
|
<get src="http://digitalcorpora.org/corp/nps/drives/nps-2008-jean/nps-2008-jean.E02" dest="${test-input}"/>
|
||||||
</else>
|
</else>
|
||||||
</if>
|
</if>
|
||||||
</target>
|
</target>
|
||||||
</project>
|
</project>
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
any type of module. Information about specific types of modules should
|
any type of module. Information about specific types of modules should
|
||||||
go into the page for that module type. -->
|
go into the page for that module type. -->
|
||||||
|
|
||||||
<!-- @@@ Update -->
|
|
||||||
|
|
||||||
This page describes the basic concepts and setup that are needed regardless of the module type that you are building.
|
This page describes the basic concepts and setup that are needed regardless of the module type that you are building.
|
||||||
|
|
||||||
\section mod_dev_setup Basic Setup
|
\section mod_dev_setup Basic Setup
|
||||||
@ -66,11 +64,7 @@ You now have a NetBeans module that is using Autopsy as its build platform. Tha
|
|||||||
There are several optional things in the Properties section. You can add a description and specify the version. You can do all of this later though and it does not need to be done before you start development.
|
There are several optional things in the Properties section. You can add a description and specify the version. You can do all of this later though and it does not need to be done before you start development.
|
||||||
|
|
||||||
A link about the NetBeans versioning scheme can be found here http://wiki.netbeans.org/VersioningPolicy.
|
A link about the NetBeans versioning scheme can be found here http://wiki.netbeans.org/VersioningPolicy.
|
||||||
Autopsy follows this scheme and we will make a wiki page about it.
|
Autopsy follows this scheme and a link to the details can be found at http://wiki.sleuthkit.org/index.php?title=Autopsy_3_Module_Versions.
|
||||||
|
|
||||||
TODO: @@@ Add link to our wiki with Autopsy's versioning scheme
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\subsection mod_dev_mod_other Other Links
|
\subsection mod_dev_mod_other Other Links
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ blackboard and with inbox messages to the user.
|
|||||||
\section ingest_datasrc Data Source-level Modules
|
\section ingest_datasrc Data Source-level Modules
|
||||||
|
|
||||||
To make a data source-level module, make a new Java class either manually or using the NetBeans wizards. Edit the class to extend "org.sleuthkit.autopsy.ingest.IngestModuleDataSource". NetBeans will likely complain that you have not implemented the necessary methods and you can use its "hints" to automatically generate stubs for them. Use the documentation for the org.sleuthkit.autopsy.ingest.IngestModuleDataSource class for details on what each needs to do.
|
To make a data source-level module, make a new Java class either manually or using the NetBeans wizards. Edit the class to extend "org.sleuthkit.autopsy.ingest.IngestModuleDataSource". NetBeans will likely complain that you have not implemented the necessary methods and you can use its "hints" to automatically generate stubs for them. Use the documentation for the org.sleuthkit.autopsy.ingest.IngestModuleDataSource class for details on what each needs to do.
|
||||||
|
You can also refer to org.sleuthkit.autopsy.examples.SampleDataSourceIngestModule as an example module.
|
||||||
|
|
||||||
Example snippet of an ingest-level module process() method:
|
Example snippet of an ingest-level module process() method:
|
||||||
|
|
||||||
@ -87,6 +88,7 @@ public void process(Content dataSource, IngestDataSourceWorkerController control
|
|||||||
\section ingest_file File-level Modules
|
\section ingest_file File-level Modules
|
||||||
|
|
||||||
To make a File-level module, make a new Java class either manually or using the NetBeans wizards. Edit the class to extend "org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile". NetBeans will likely complain that you have not implemented the necessary methods and you can use its "hints" to automatically generate stubs for them. Use the method documentation in the org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile class to fill in the details.
|
To make a File-level module, make a new Java class either manually or using the NetBeans wizards. Edit the class to extend "org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile". NetBeans will likely complain that you have not implemented the necessary methods and you can use its "hints" to automatically generate stubs for them. Use the method documentation in the org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile class to fill in the details.
|
||||||
|
You can also refer to org.sleuthkit.autopsy.examples.SampleFileIngestModule as an example module.
|
||||||
|
|
||||||
Unlike Data Source-level modules, file-level modules are singletons. Only a single instance is created for all files.
|
Unlike Data Source-level modules, file-level modules are singletons. Only a single instance is created for all files.
|
||||||
The same file-level module instance will be used for files in different images and even different cases if new cases are opened.
|
The same file-level module instance will be used for files in different images and even different cases if new cases are opened.
|
||||||
|
@ -1,31 +1,51 @@
|
|||||||
/*! \page mod_result_page Developing Result Viewer Modules
|
/*! \page mod_result_page Developing Result Viewer Modules
|
||||||
|
|
||||||
NOTE: This has been moved from a package-level description and needs cleanup and updating.
|
\section result_overview Overview
|
||||||
|
DataResultViewer modules exist in the upper-right area of the default Autopsy interface, as shown below.
|
||||||
|
|
||||||
<h3>Creating a DataResultViewer</h3>
|
\image html viewer_image.jpg "Module Viewer Areas"
|
||||||
<p>DataResultTopComponent is the high-level window in the DataResult area. The DataResult area is in the upper right of Autopsy and shows a set of nodes (i.e. in table form or thumbnail, by default). You will want to create a new module in this area if you have a new way to display a set of files or nodes. For example, in a graph form or different layout beyond the simple table.
|
|
||||||
|
|
||||||
<ol>
|
They display a set of files that are passed into the viewer from the tree on the left, keyword searching, or other searches. The main idea is that the same set of files can be viewed in table form, thumbnail form, or any other form that you can think of. Once a file is selected from the DataResult area, it is passed to the DataContent area for display.
|
||||||
<li>Create a module from within NetBeans. It must be dependent on these modules:
|
|
||||||
<ul>
|
|
||||||
<li>Case
|
|
||||||
<li>CoreComponentInterfaces
|
|
||||||
<li>CoreComponents
|
|
||||||
<li>DataModel
|
|
||||||
<li>DialogsAPI (if pop-ups and such are going to be used)
|
|
||||||
<li>Explorer & Property Sheet API
|
|
||||||
<li>Lookup
|
|
||||||
<li>Nodes API
|
|
||||||
<li>Setting API
|
|
||||||
<li>UI Utilities API
|
|
||||||
<li>Utilities API
|
|
||||||
<li>Window System API
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<li>Make a class that extends org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer and is registered as a service provider for the org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer class by specifying "@ServiceProvider(service = DataResultViewer.class)" or by using layer.xml. This class will extend JPanel. </li>
|
\section result_dataflow Data Flow
|
||||||
|
This section provides some basics on DataResult viewers. DataResult viewers are created as needed. The directory tree on the left creates one when it loads and uses it for the life of the application. The keyword search module creates on each time it performs a keyword search. Data is explicitly passed into it.
|
||||||
|
|
||||||
<li>See the previous sections on default actions. (note that this refers to the CoreComponentINterfaces package-level description).</li>
|
By default, when a node is selected, it is then passed to the default DataContent viewer (this is done in org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer). There can be many data content viewers, but only one default one exists.
|
||||||
|
|
||||||
</ol>
|
The org.sleuthkit.autopsy.corecomponents.DataResultViewerTopComponent class is the NetBeans TopComponent that encapsulates the various DataResult viewer modules. It creates tabs for each DataResult viewer module.
|
||||||
|
|
||||||
|
\section result_nb NetBeans Module Configuration
|
||||||
|
The rest of the document assumes that you have already created your NetBeans module, as outlined in \ref mod_dev_module.
|
||||||
|
|
||||||
|
DataResultViewer modules will have additional NetBeans dependencies. Right click on the module, choose "Properties" -> "Libraries" -> "Module Dependencies". Add "Lookup API" and "Nodes API".
|
||||||
|
|
||||||
|
\section result_mod Module Development
|
||||||
|
|
||||||
|
You will need a class that extends org.sleuthkit.autopsy.corecomponents.AbstractDataResultViewer. You can use NetBeans to make a class, manually extend it, and then let NetBeans complain about missing methods. It will provide default implementations for them if you click on the error messages in the UI.
|
||||||
|
Refer to the documentation in org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer on what each method should do. Note that AbstractDataResultViewer extends JPanel.
|
||||||
|
|
||||||
|
Autopsy will find your module using the NetBeans Lookup infrastructure. To be found, you will need to register as a service provider for DataResultViewer.class by annotating your class as follows:
|
||||||
|
|
||||||
|
\code
|
||||||
|
@ServiceProvider(service = DataResultViewer.class)
|
||||||
|
public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
If you get errors about not knowing about ServiceProviders and such, ensure that you configured your NetBeans module to depend on the Nodes and Lookup APIs as outlined in the previous section.
|
||||||
|
|
||||||
|
The current modules in this viewer area heavily use the NetBeans ExplorerManger and Node concepts. You do not need to use ExplorerManager concepts, but you will need to use Node concepts to identify the set of nodes to display and to extract the datamodel objects from each Node object. Refer to \ref content_hints_objects for hints on getting the datamodel objects from the Node.
|
||||||
|
|
||||||
|
\section result_examples Example Modules
|
||||||
|
You can refer to the org.sleuthkit.autopsy.corecomponents.DataResultViewerTable and org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail modules to follow as examples.
|
||||||
|
|
||||||
|
\section result_hint Hints
|
||||||
|
|
||||||
|
Note that we have made the least number of these types of modules, so some work could be done to make the framework and infrastuture for them better.
|
||||||
|
|
||||||
|
These modules are currently the most challenging to develop because they require the most NetBeans knowledge about Nodes and ExplorerManagers. Make sure you read some of the tutorials (or books) first:
|
||||||
|
- NetBeans Nodes API Tutorial (https://platform.netbeans.org/tutorials/nbm-nodesapi2.html)
|
||||||
|
- NetBeans Nodes, Explorer Manager, and Component Palette Tutorial (https://platform.netbeans.org/tutorials/nbm-nodesapi3.html)
|
||||||
|
|
||||||
|
We have plans to change the design a bit in the future so that an ExplorerManager is created for each DataResultViewerTopComponent instance and each individual module does not need to make one. Instead, one will be given to it.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -52,6 +52,7 @@ services are provided:
|
|||||||
- FileManager: the org.sleuthkit.autopsy.casemodule.services.FileManager service provides an API to access any file in the case. You can access FileManager by calling org.sleuthkit.autopsy.casemodule.services.Services.getFileManager(). Data Source-level Ingest modules and Report modules typically use this service because the other modules are passed in a reference to a specific file to do something with.
|
- FileManager: the org.sleuthkit.autopsy.casemodule.services.FileManager service provides an API to access any file in the case. You can access FileManager by calling org.sleuthkit.autopsy.casemodule.services.Services.getFileManager(). Data Source-level Ingest modules and Report modules typically use this service because the other modules are passed in a reference to a specific file to do something with.
|
||||||
- org.sleuthkit.autopsy.coreutils.Logger - for adding log messages to central logger
|
- org.sleuthkit.autopsy.coreutils.Logger - for adding log messages to central logger
|
||||||
- IngestModules also have a class that provides additional services. See \ref ingestmodule_services.
|
- IngestModules also have a class that provides additional services. See \ref ingestmodule_services.
|
||||||
|
- MessageNotifyUtil.Notify.show() can be used to send messages to the user in the lower right-hand area.
|
||||||
|
|
||||||
|
|
||||||
\subsection mod_dev_other_utilities Framework Utilities
|
\subsection mod_dev_other_utilities Framework Utilities
|
||||||
|
@ -820,18 +820,16 @@ def usage():
|
|||||||
return \
|
return \
|
||||||
"""
|
"""
|
||||||
USAGE:
|
USAGE:
|
||||||
Run this script to generate a jdiff XML summary for every module
|
Compares the API of the current Autopsy source code with a previous
|
||||||
in the current Autopsy source and in a previous source specified
|
tagged version. By default, it will detect the previous tag from
|
||||||
by the given tag. Then, compare the XML files to see which modules
|
the NEWS file and will not update the versions in the source code.
|
||||||
need updated version numbers. If the dry run tag is not given, the
|
|
||||||
module numbers will be automatically updated.
|
|
||||||
|
|
||||||
OPTIONAL FLAGS:
|
OPTIONAL FLAGS:
|
||||||
-t --tag The tag name in git. Otherwise the NEWS file in source
|
-t --tag Specify a previous tag to compare to.
|
||||||
will be used to determine the previous tag.
|
Otherwise the NEWS file will be used.
|
||||||
|
|
||||||
-d --dir The output directory for the jdiff JavaDocs. If no
|
-d --dir The output directory for the jdiff JavaDocs. If no
|
||||||
directory is given, the default is /javadocs/{module}.
|
directory is given, the default is jdiff-javadocs/{module}.
|
||||||
|
|
||||||
-s --source The directory containing Autopsy's source code.
|
-s --source The directory containing Autopsy's source code.
|
||||||
|
|
||||||
@ -904,6 +902,7 @@ def main():
|
|||||||
printt("Comparing jdiff outputs...")
|
printt("Comparing jdiff outputs...")
|
||||||
for module in similar_modules:
|
for module in similar_modules:
|
||||||
module.set_ret(compare_xml(module, apiname_tag, apiname_cur))
|
module.set_ret(compare_xml(module, apiname_tag, apiname_cur))
|
||||||
|
print("Refer to the jdiff-javadocs folder for more details")
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
# 1) Do versioning
|
# 1) Do versioning
|
||||||
|
Loading…
x
Reference in New Issue
Block a user