mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-20 03:24:55 +00:00
Merge pull request #2568 from APriestman/imageWriterListener
Refactor image writer
This commit is contained in:
commit
cbb7ee515b
@ -31,6 +31,14 @@
|
||||
<specification-version>1.46.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.netbeans.api.templates</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<specification-version>1.6.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.netbeans.core</code-name-base>
|
||||
<build-prerequisite/>
|
||||
@ -155,6 +163,14 @@
|
||||
<specification-version>9.7.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.openide.loaders</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<specification-version>7.63.2</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.openide.modules</code-name-base>
|
||||
<build-prerequisite/>
|
||||
@ -242,6 +258,7 @@
|
||||
<package>org.sleuthkit.autopsy.events</package>
|
||||
<package>org.sleuthkit.autopsy.externalresults</package>
|
||||
<package>org.sleuthkit.autopsy.filesearch</package>
|
||||
<package>org.sleuthkit.autopsy.framework</package>
|
||||
<package>org.sleuthkit.autopsy.ingest</package>
|
||||
<package>org.sleuthkit.autopsy.keywordsearchservice</package>
|
||||
<package>org.sleuthkit.autopsy.menuactions</package>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -25,27 +25,37 @@ import org.openide.LifecycleManager;
|
||||
import org.openide.awt.ActionID;
|
||||
import org.openide.awt.ActionReference;
|
||||
import org.openide.awt.ActionRegistration;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CaseActionException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* The action associated with the Case/Exit menu item. It closes the current
|
||||
* case, if any, and shuts down the application.
|
||||
*/
|
||||
@ActionRegistration(displayName = "Exit", iconInMenu = true)
|
||||
@ActionReference(path = "Menu/Case", position = 1000, separatorBefore = 999)
|
||||
@ActionID(id = "org.sleuthkit.autopsy.casemodule.ExitAction", category = "Case")
|
||||
|
||||
final public class ExitAction implements ActionListener {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"ExitAction.confirmationDialog.title=Ingest is Running",
|
||||
"ExitAction.confirmationDialog.message=Ingest is running, are you sure you want to exit?"
|
||||
|
||||
})
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (IngestRunningCheck.checkAndConfirmProceed(Bundle.ExitAction_confirmationDialog_title(), Bundle.ExitAction_confirmationDialog_message())) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Case currentCase = Case.getCurrentCase();
|
||||
if (currentCase != null) {
|
||||
currentCase.closeCase();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(ExitAction.class.getName()).log(Level.SEVERE, "Had a problem closing the case.", ex); //NON-NLS
|
||||
Case.closeCurrentCase();
|
||||
} catch (CaseActionException ex) {
|
||||
Logger.getLogger(ExitAction.class.getName()).log(Level.SEVERE, "Error closing the current case on exit", ex); //NON-NLS
|
||||
} finally {
|
||||
LifecycleManager.getDefault().exit();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.actions;
|
||||
|
||||
import org.openide.DialogDescriptor;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
|
||||
/**
|
||||
* A helper for actions that checks to see if ingest is running. If it is,
|
||||
* prompts the user to confirm they want to proceed with whatever operation was
|
||||
* initiated (e.g., closing the case).
|
||||
*/
|
||||
public class IngestRunningCheck {
|
||||
|
||||
/**
|
||||
* Checks to see if ingest is running. If it is, prompts the user to confirm
|
||||
* they want to proceed with whatever operation was initiated (e.g., closing
|
||||
* the case).
|
||||
*
|
||||
* @param optionsDlgTitle The title for the options dialog used to confirm
|
||||
* the iser's intentions.
|
||||
* @param optionsDlgMessage The message for the options dialog used to
|
||||
* confirm the iser's intentions.
|
||||
*
|
||||
* @return True to proceed, false otherwise.
|
||||
*/
|
||||
public static boolean checkAndConfirmProceed(String optionsDlgTitle, String optionsDlgMessage) {
|
||||
if (IngestManager.getInstance().isIngestRunning()) {
|
||||
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
|
||||
optionsDlgMessage,
|
||||
optionsDlgTitle,
|
||||
NotifyDescriptor.YES_NO_OPTION,
|
||||
NotifyDescriptor.WARNING_MESSAGE);
|
||||
descriptor.setValue(NotifyDescriptor.NO_OPTION);
|
||||
Object response = DialogDisplayer.getDefault().notify(descriptor);
|
||||
return (DialogDescriptor.YES_OPTION == response);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private contructor to prevent instantiation of a utility class.
|
||||
*/
|
||||
private IngestRunningCheck() {
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,9 +18,9 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.actions;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.Desktop;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
@ -35,10 +35,14 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Action in menu to open the folder containing the log files
|
||||
* The action associated with the Help/Open Log Folder menu item. It opens a
|
||||
* file explorer window for either the log subdirectory for the currently open
|
||||
* case, or the log subdirectory of the user directory, if there is no current
|
||||
* case.
|
||||
*
|
||||
* This action should only be invoked in the event dispatch thread (EDT).
|
||||
*/
|
||||
@ActionRegistration(
|
||||
displayName = "#CTL_OpenLogFolder", iconInMenu = true)
|
||||
@ActionRegistration(displayName = "#CTL_OpenLogFolder", iconInMenu = true)
|
||||
@ActionReference(path = "Menu/Help", position = 1750)
|
||||
@ActionID(id = "org.sleuthkit.autopsy.actions.OpenLogFolderAction", category = "Help")
|
||||
public final class OpenLogFolderAction implements ActionListener {
|
||||
@ -47,25 +51,42 @@ public final class OpenLogFolderAction implements ActionListener {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
File logDir;
|
||||
if (Case.isCaseOpen()) {
|
||||
logDir = new File(Case.getCurrentCase().getLogDirectoryPath());
|
||||
try {
|
||||
/*
|
||||
* Open the log directory for the case.
|
||||
*/
|
||||
Case currentCase = Case.getCurrentCase();
|
||||
logDir = new File(currentCase.getLogDirectoryPath());
|
||||
} catch (IllegalStateException ex) {
|
||||
/*
|
||||
* There is no open case, open the application level log
|
||||
* directory.
|
||||
*/
|
||||
logDir = new File(Places.getUserDirectory().getAbsolutePath() + File.separator + "var" + File.separator + "log");
|
||||
}
|
||||
} else {
|
||||
logDir = new File(Places.getUserDirectory().getAbsolutePath() + File.separator + "var" + File.separator + "log");
|
||||
}
|
||||
if (logDir.exists() == false) {
|
||||
NotifyDescriptor d
|
||||
= new NotifyDescriptor.Message(
|
||||
|
||||
try {
|
||||
if (logDir.exists()) {
|
||||
Desktop.getDesktop().open(logDir);
|
||||
} else {
|
||||
logger.log(Level.SEVERE, String.format("The log directory %s does not exist", logDir));
|
||||
NotifyDescriptor notifyDescriptor = new NotifyDescriptor.Message(
|
||||
NbBundle.getMessage(this.getClass(), "OpenLogFolder.error1", logDir.getAbsolutePath()),
|
||||
NotifyDescriptor.ERROR_MESSAGE);
|
||||
DialogDisplayer.getDefault().notify(d);
|
||||
} else {
|
||||
Desktop.getDesktop().open(logDir);
|
||||
DialogDisplayer.getDefault().notify(notifyDescriptor);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "OpenLogFolder.CouldNotOpenLogFolder"), ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, String.format("Could not open log directory %s", logDir), ex);
|
||||
NotifyDescriptor notifyDescriptor = new NotifyDescriptor.Message(
|
||||
NbBundle.getMessage(this.getClass(), "OpenLogFolder.CouldNotOpenLogFolder", logDir.getAbsolutePath()),
|
||||
NotifyDescriptor.ERROR_MESSAGE);
|
||||
DialogDisplayer.getDefault().notify(notifyDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -35,37 +35,45 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Action in menu to open the folder containing the output files
|
||||
* The action associated with the Tools/Open Output Folder menu item. It opens a
|
||||
* file explorer window for the root output directory for the currently open
|
||||
* case. If the case is a single-user case, this is the case directory. If the
|
||||
* case is a multi-user case, this is a subdirectory of the case directory
|
||||
* specific to the host machine.
|
||||
*
|
||||
* This action should only be invoked in the event dispatch thread (EDT).
|
||||
*/
|
||||
@ActionRegistration(
|
||||
displayName = "#CTL_OpenOutputFolder", iconInMenu = true, lazy=true)
|
||||
@ActionRegistration(displayName = "#CTL_OpenOutputFolder", iconInMenu = true, lazy = false)
|
||||
@ActionReference(path = "Menu/Tools", position = 1850, separatorBefore = 1849)
|
||||
@ActionID(id = "org.sleuthkit.autopsy.actions.OpenOutputFolderAction", category = "Help")
|
||||
public final class OpenOutputFolderAction extends CallableSystemAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(OpenOutputFolderAction.class.getName());
|
||||
|
||||
@Override
|
||||
public void performAction() {
|
||||
|
||||
try {
|
||||
File outputDir;
|
||||
if (Case.isCaseOpen()) {
|
||||
outputDir = new File(Case.getCurrentCase().getOutputDirectory());
|
||||
if (outputDir.exists() == false) {
|
||||
NotifyDescriptor d
|
||||
= new NotifyDescriptor.Message(NbBundle.getMessage(this.getClass(),
|
||||
"OpenOutputFolder.error1", outputDir.getAbsolutePath()),
|
||||
NotifyDescriptor.ERROR_MESSAGE);
|
||||
DialogDisplayer.getDefault().notify(d);
|
||||
} else {
|
||||
try {
|
||||
Case currentCase = Case.getCurrentCase();
|
||||
outputDir = new File(currentCase.getOutputDirectory());
|
||||
if (outputDir.exists()) {
|
||||
try {
|
||||
Desktop.getDesktop().open(outputDir);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Failed to open output folder %s", outputDir), ex); //NON-NLS
|
||||
NotifyDescriptor descriptor = new NotifyDescriptor.Message(
|
||||
NbBundle.getMessage(this.getClass(), "OpenOutputFolder.CouldNotOpenOutputFolder", outputDir.getAbsolutePath()), NotifyDescriptor.ERROR_MESSAGE);
|
||||
DialogDisplayer.getDefault().notify(descriptor);
|
||||
}
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "OpenOutputFolder.noCaseOpen"));
|
||||
NotifyDescriptor descriptor = new NotifyDescriptor.Message(
|
||||
NbBundle.getMessage(this.getClass(), "OpenOutputFolder.error1", outputDir.getAbsolutePath()), NotifyDescriptor.ERROR_MESSAGE);
|
||||
DialogDisplayer.getDefault().notify(descriptor);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "OpenOutputFolder.CouldNotOpenOutputFolder"), ex); //NON-NLS
|
||||
} catch (IllegalStateException ex) {
|
||||
logger.log(Level.SEVERE, "OpenOutputFolderAction enabled with no current case", ex); //NON-NLS
|
||||
JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "OpenOutputFolder.noCaseOpen"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,8 +89,9 @@ public final class OpenOutputFolderAction extends CallableSystemAction {
|
||||
|
||||
@Override
|
||||
public boolean asynchronous() {
|
||||
return false; // run on edt
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NbBundle.getMessage(OpenOutputFolderAction.class, "CTL_OpenOutputFolder");
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -29,23 +29,24 @@ import org.openide.util.actions.CallableSystemAction;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
|
||||
|
||||
@ActionID(
|
||||
category = "Help",
|
||||
id = "org.sleuthkit.autopsy.actions.ShowIngestProgressSnapshotAction"
|
||||
)
|
||||
@ActionRegistration(
|
||||
displayName = "#CTL_ShowIngestProgressSnapshotAction",
|
||||
lazy = false
|
||||
)
|
||||
/**
|
||||
* The action associated with the Help/Get Ingest Progress Snapshot menu item.
|
||||
* It opens a the Ingest Progress Snapshot dialog.
|
||||
*
|
||||
* This action should only be invoked in the event dispatch thread (EDT).
|
||||
*/
|
||||
@ActionID(category = "Help", id = "org.sleuthkit.autopsy.actions.ShowIngestProgressSnapshotAction")
|
||||
@ActionRegistration(displayName = "#CTL_ShowIngestProgressSnapshotAction", lazy = false)
|
||||
@ActionReference(path = "Menu/Help", position = 1125)
|
||||
@Messages("CTL_ShowIngestProgressSnapshotAction=Ingest Status Details")
|
||||
public final class ShowIngestProgressSnapshotAction extends CallableSystemAction implements ActionListener {
|
||||
|
||||
private static final String ACTION_NAME = NbBundle.getMessage(ShowIngestProgressSnapshotAction.class, "ShowIngestProgressSnapshotAction.actionName.text");
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void performAction() {
|
||||
IngestProgressSnapshotDialog dialog = new IngestProgressSnapshotDialog();
|
||||
new IngestProgressSnapshotDialog();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -65,6 +66,6 @@ public final class ShowIngestProgressSnapshotAction extends CallableSystemAction
|
||||
|
||||
@Override
|
||||
public boolean asynchronous() {
|
||||
return false; // run on edt
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,6 +19,7 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
@ -28,7 +29,6 @@ import java.util.logging.Level;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
@ -44,26 +44,26 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.util.actions.Presenter;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
|
||||
/**
|
||||
* The action to add an image to the current Case. This action should be
|
||||
* disabled on creation and it will be enabled on new case creation or case
|
||||
* opened.
|
||||
* An action that invokes the Add Data Source wizard.
|
||||
*
|
||||
* @author jantonius
|
||||
* This action should only be invoked in the event dispatch thread (EDT).
|
||||
*/
|
||||
// TODO: need annotation because there's a "Lookup.getDefault().lookup(AddImageAction.class)"
|
||||
// used in AddImageWizardPanel1 (among other places). It really shouldn't be done like that.
|
||||
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.casemodule.AddImageAction")
|
||||
@ActionRegistration(displayName = "#CTL_AddImage", lazy = false)
|
||||
@ActionReferences(value = {
|
||||
@ActionReference(path = "Toolbars/Case", position = 100)})
|
||||
@ActionReferences(value = {@ActionReference(path = "Toolbars/Case", position = 100)})
|
||||
@ServiceProvider(service = AddImageAction.class)
|
||||
public final class AddImageAction extends CallableSystemAction implements Presenter.Toolbar {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Dimension SIZE = new Dimension(875, 550);
|
||||
private final ChangeSupport cleanupSupport = new ChangeSupport(this);
|
||||
|
||||
// Keys into the WizardDescriptor properties that pass information between stages of the wizard
|
||||
// <TYPE>: <DESCRIPTION>
|
||||
// String: time zone that the image is from
|
||||
@ -84,15 +84,13 @@ public final class AddImageAction extends CallableSystemAction implements Presen
|
||||
static final String NOFATORPHANS_PROP = "nofatorphans"; //NON-NLS
|
||||
|
||||
static final Logger logger = Logger.getLogger(AddImageAction.class.getName());
|
||||
static final Dimension SIZE = new Dimension(875, 550);
|
||||
|
||||
private WizardDescriptor wizardDescriptor;
|
||||
private WizardDescriptor.Iterator<WizardDescriptor> iterator;
|
||||
private Dialog dialog;
|
||||
private JButton toolbarButton = new JButton();
|
||||
private final JButton toolbarButton = new JButton();
|
||||
|
||||
/**
|
||||
* The constructor for AddImageAction class
|
||||
* Constructs an action that invokes the Add Data Source wizard.
|
||||
*/
|
||||
public AddImageAction() {
|
||||
putValue(Action.NAME, NbBundle.getMessage(AddImageAction.class, "CTL_AddImage")); // set the action Name
|
||||
@ -106,26 +104,19 @@ public final class AddImageAction extends CallableSystemAction implements Presen
|
||||
}
|
||||
});
|
||||
|
||||
this.setEnabled(false); // disable this action class
|
||||
/*
|
||||
* Disable this action until a case is opened. Currently, the Case class
|
||||
* enables the action.
|
||||
*/
|
||||
this.setEnabled(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop-up the "Add Image" wizard panel.
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (IngestManager.getInstance().isIngestRunning()) {
|
||||
final String msg = NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.msg");
|
||||
if (JOptionPane.showConfirmDialog(null, msg,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"AddImageAction.ingestConfig.ongoingIngest.title"),
|
||||
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.NO_OPTION) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String optionsDlgTitle = NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.title");
|
||||
String optionsDlgMessage = NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.msg");
|
||||
if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
iterator = new AddImageWizardIterator(this);
|
||||
wizardDescriptor = new WizardDescriptor(iterator);
|
||||
wizardDescriptor.setTitle(NbBundle.getMessage(this.getClass(), "AddImageAction.wizard.title"));
|
||||
@ -138,6 +129,7 @@ public final class AddImageAction extends CallableSystemAction implements Presen
|
||||
dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
|
||||
Dimension d = dialog.getSize();
|
||||
dialog.setSize(SIZE);
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
dialog.setVisible(true);
|
||||
dialog.toFront();
|
||||
|
||||
@ -145,6 +137,7 @@ public final class AddImageAction extends CallableSystemAction implements Presen
|
||||
//add-image process, reverting an image)
|
||||
runCleanupTasks();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the current dialog and wizard, and opens a new one. Used in the
|
||||
@ -172,12 +165,9 @@ public final class AddImageAction extends CallableSystemAction implements Presen
|
||||
void runTask(Image newImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does nothing. Use the "actionPerformed(ActionEvent e)"
|
||||
* instead of this method.
|
||||
*/
|
||||
@Override
|
||||
public void performAction() {
|
||||
actionPerformed(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -191,9 +181,9 @@ public final class AddImageAction extends CallableSystemAction implements Presen
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the HelpCtx associated with implementing object
|
||||
* Gets the help context for this action.
|
||||
*
|
||||
* @return HelpCtx or HelpCtx.DEFAULT_HELP
|
||||
* @return The help context.
|
||||
*/
|
||||
@Override
|
||||
public HelpCtx getHelpCtx() {
|
||||
@ -201,9 +191,9 @@ public final class AddImageAction extends CallableSystemAction implements Presen
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the toolbar component of this action
|
||||
* Gets the toolbar component for this action.
|
||||
*
|
||||
* @return component the toolbar button
|
||||
* @return The toolbar button
|
||||
*/
|
||||
@Override
|
||||
public Component getToolbarPresenter() {
|
||||
@ -214,7 +204,7 @@ public final class AddImageAction extends CallableSystemAction implements Presen
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this action to be enabled/disabled
|
||||
* Enables and disables this action.
|
||||
*
|
||||
* @param value whether to enable this action or not
|
||||
*/
|
||||
@ -236,8 +226,8 @@ public final class AddImageAction extends CallableSystemAction implements Presen
|
||||
public void requestFocusButton(String buttonText) {
|
||||
// get all buttons on this wizard panel
|
||||
Object[] wizardButtons = wizardDescriptor.getOptions();
|
||||
for (int i = 0; i < wizardButtons.length; i++) {
|
||||
JButton tempButton = (JButton) wizardButtons[i];
|
||||
for (Object wizardButton : wizardButtons) {
|
||||
JButton tempButton = (JButton) wizardButton;
|
||||
if (tempButton.getText().equals(buttonText)) {
|
||||
tempButton.setDefaultCapable(true);
|
||||
tempButton.requestFocus();
|
||||
@ -254,8 +244,6 @@ public final class AddImageAction extends CallableSystemAction implements Presen
|
||||
cleanupSupport.fireChange();
|
||||
}
|
||||
|
||||
ChangeSupport cleanupSupport = new ChangeSupport(this);
|
||||
|
||||
/**
|
||||
* Instances of this class implement the cleanup() method to run cleanup
|
||||
* code when the wizard exits.
|
||||
|
@ -26,6 +26,8 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datasourceprocessors.ImageWriter;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
import org.sleuthkit.datamodel.SleuthkitJNI;
|
||||
@ -207,7 +209,8 @@ class AddImageTask implements Runnable {
|
||||
errorMessages.add(verificationError);
|
||||
}
|
||||
if(! imageWriterPath.isEmpty()){
|
||||
Case.getCurrentCase().scheduleImageWriterFinish(imageId);
|
||||
ImageWriter writer = new ImageWriter(imageId);
|
||||
writer.subscribeToEvents();
|
||||
}
|
||||
newDataSources.add(newImage);
|
||||
} else {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -30,6 +30,7 @@ import org.openide.util.HelpCtx;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
||||
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescriptorPanel;
|
||||
|
||||
/**
|
||||
* The final panel of the add image wizard. It displays a progress bar and
|
||||
@ -39,7 +40,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgress
|
||||
* {@link AddImageWizardIngestConfigPanel} (which is a bit weird if you ask m
|
||||
* -jm)
|
||||
*/
|
||||
class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePanel<WizardDescriptor> {
|
||||
class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
|
||||
|
||||
/**
|
||||
* flag to indicate that the image adding process is finished and this panel
|
||||
@ -53,7 +54,7 @@ class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePa
|
||||
private AddImageWizardAddingProgressVisual component;
|
||||
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
|
||||
|
||||
private DSPProgressMonitorImpl dspProgressMonitorImpl = new DSPProgressMonitorImpl();
|
||||
private final DSPProgressMonitorImpl dspProgressMonitorImpl = new DSPProgressMonitorImpl();
|
||||
|
||||
public DSPProgressMonitorImpl getDSPProgressMonitorImpl() {
|
||||
return dspProgressMonitorImpl;
|
||||
@ -192,7 +193,7 @@ class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePa
|
||||
protected final void fireChangeEvent() {
|
||||
Iterator<ChangeListener> it;
|
||||
synchronized (listeners) {
|
||||
it = new HashSet<ChangeListener>(listeners).iterator();
|
||||
it = new HashSet<>(listeners).iterator();
|
||||
}
|
||||
ChangeEvent ev = new ChangeEvent(this);
|
||||
while (it.hasNext()) {
|
||||
@ -239,8 +240,4 @@ class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePa
|
||||
getComponent().showErrors(errorString, critical);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinishPanel() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -33,18 +33,19 @@ import org.openide.util.HelpCtx;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.windows.WindowManager;
|
||||
import java.awt.Cursor;
|
||||
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescriptorPanel;
|
||||
|
||||
/**
|
||||
* The "Add Image" wizard panel1 handling the logic of selecting image file(s)
|
||||
* to add to Case, and pick the time zone.
|
||||
*/
|
||||
class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<WizardDescriptor>, PropertyChangeListener {
|
||||
class AddImageWizardChooseDataSourcePanel extends ShortcutWizardDescriptorPanel implements PropertyChangeListener {
|
||||
|
||||
/**
|
||||
* The visual component that displays this panel. If you need to access the
|
||||
* component from this class, just use getComponent().
|
||||
*/
|
||||
private AddImageWizardAddingProgressPanel progressPanel;
|
||||
private final AddImageWizardAddingProgressPanel progressPanel;
|
||||
private AddImageWizardChooseDataSourceVisual component;
|
||||
private boolean isNextEnable = false;
|
||||
private static final String PROP_LASTDATASOURCE_PATH = "LBL_LastDataSource_PATH"; //NON-NLS
|
||||
@ -122,7 +123,7 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
|
||||
isNextEnable = isEnabled;
|
||||
fireChangeEvent();
|
||||
}
|
||||
private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
|
||||
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
|
||||
|
||||
/**
|
||||
* Adds a listener to changes of the panel's validity.
|
||||
@ -155,7 +156,7 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
|
||||
protected final void fireChangeEvent() {
|
||||
Iterator<ChangeListener> it;
|
||||
synchronized (listeners) {
|
||||
it = new HashSet<ChangeListener>(listeners).iterator();
|
||||
it = new HashSet<>(listeners).iterator();
|
||||
}
|
||||
ChangeEvent ev = new ChangeEvent(this);
|
||||
while (it.hasNext()) {
|
||||
@ -218,8 +219,6 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
|
||||
*/
|
||||
@Override
|
||||
public void storeSettings(WizardDescriptor settings) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -32,13 +32,17 @@ import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.IngestProfileSelectionWizardPanel;
|
||||
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescriptorPanel;
|
||||
|
||||
/**
|
||||
* second panel of add image wizard, allows user to configure ingest modules.
|
||||
@ -46,20 +50,19 @@ import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
* TODO: review this for dead code. think about moving logic of adding image to
|
||||
* 3rd panel( {@link AddImageWizardAddingProgressPanel}) separate class -jm
|
||||
*/
|
||||
class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
|
||||
private final IngestJobSettingsPanel ingestJobSettingsPanel;
|
||||
class AddImageWizardIngestConfigPanel extends ShortcutWizardDescriptorPanel {
|
||||
|
||||
@Messages("AddImageWizardIngestConfigPanel.name.text=Configure Ingest Modules")
|
||||
private IngestJobSettingsPanel ingestJobSettingsPanel;
|
||||
/**
|
||||
* The visual component that displays this panel. If you need to access the
|
||||
* component from this class, just use getComponent().
|
||||
*/
|
||||
private Component component = null;
|
||||
|
||||
private String lastProfileUsed = AddImageWizardIngestConfigPanel.class.getCanonicalName();
|
||||
private final List<Content> newContents = Collections.synchronizedList(new ArrayList<Content>());
|
||||
private boolean ingested = false;
|
||||
private boolean readyToIngest = false;
|
||||
|
||||
// task that will clean up the created database file if the wizard is cancelled before it finishes
|
||||
private AddImageAction.CleanupTask cleanupTask;
|
||||
|
||||
@ -75,10 +78,12 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
this.addImageAction = action;
|
||||
this.progressPanel = proPanel;
|
||||
this.dataSourcePanel = dsPanel;
|
||||
|
||||
IngestJobSettings ingestJobSettings = new IngestJobSettings(AddImageWizardIngestConfigPanel.class.getCanonicalName());
|
||||
showWarnings(ingestJobSettings);
|
||||
//When this panel is viewed by the user it will always be displaying the
|
||||
//IngestJobSettingsPanel with the AddImageWizardIngestConfigPanel.class.getCanonicalName();
|
||||
this.ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,6 +98,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
public Component getComponent() {
|
||||
if (component == null) {
|
||||
component = new AddImageWizardIngestConfigVisual(this.ingestJobSettingsPanel);
|
||||
component.setName(Bundle.AddImageWizardIngestConfigPanel_name_text());
|
||||
}
|
||||
return component;
|
||||
}
|
||||
@ -166,12 +172,10 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
settings.setOptions(new Object[]{WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, WizardDescriptor.FINISH_OPTION, cancel});
|
||||
cleanupTask = null;
|
||||
readyToIngest = false;
|
||||
|
||||
newContents.clear();
|
||||
|
||||
// Start processing the data source by handing it off to the selected DSP,
|
||||
// so it gets going in the background while the user is still picking the Ingest modules
|
||||
startDataSourceProcessing(settings);
|
||||
startDataSourceProcessing();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -185,7 +189,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
*/
|
||||
@Override
|
||||
public void storeSettings(WizardDescriptor settings) {
|
||||
IngestJobSettings ingestJobSettings = this.ingestJobSettingsPanel.getSettings();
|
||||
IngestJobSettings ingestJobSettings = ingestJobSettingsPanel.getSettings();
|
||||
ingestJobSettings.save();
|
||||
showWarnings(ingestJobSettings);
|
||||
|
||||
@ -205,6 +209,28 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the proper settings for this panel to use the previously selected
|
||||
* Ingest profile when this panel would be skipped due to a profile being
|
||||
* chosen.
|
||||
*/
|
||||
@Override
|
||||
public void processThisPanelBeforeSkipped() {
|
||||
if (!(ModuleSettings.getConfigSetting(IngestProfileSelectionWizardPanel.getLastProfilePropertiesFile(), AddImageWizardIterator.getPropLastprofileName()) == null)
|
||||
&& !ModuleSettings.getConfigSetting(IngestProfileSelectionWizardPanel.getLastProfilePropertiesFile(), AddImageWizardIterator.getPropLastprofileName()).isEmpty()) {
|
||||
lastProfileUsed = ModuleSettings.getConfigSetting(IngestProfileSelectionWizardPanel.getLastProfilePropertiesFile(), AddImageWizardIterator.getPropLastprofileName());
|
||||
}
|
||||
//Because this panel kicks off ingest during the wizard we need to
|
||||
//swap out the ingestJobSettings for the ones of the chosen profile before
|
||||
//we start processing
|
||||
IngestJobSettings ingestJobSettings = new IngestJobSettings(lastProfileUsed);
|
||||
ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings);
|
||||
showWarnings(ingestJobSettings);
|
||||
component = new AddImageWizardIngestConfigVisual(this.ingestJobSettingsPanel);
|
||||
readyToIngest = true;
|
||||
startDataSourceProcessing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start ingest after verifying we have a new image, we are ready to ingest,
|
||||
* and we haven't already ingested.
|
||||
@ -221,7 +247,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
* Starts the Data source processing by kicking off the selected
|
||||
* DataSourceProcessor
|
||||
*/
|
||||
private void startDataSourceProcessing(WizardDescriptor settings) {
|
||||
private void startDataSourceProcessing() {
|
||||
final UUID dataSourceId = UUID.randomUUID();
|
||||
|
||||
// Add a cleanup task to interrupt the background process if the
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -26,6 +26,9 @@ import javax.swing.JComponent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.ingest.IngestProfiles;
|
||||
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.IngestProfileSelectionWizardPanel;
|
||||
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescriptorPanel;
|
||||
|
||||
/**
|
||||
* The iterator class for the "Add Image" wizard panel. This class is used to
|
||||
@ -34,8 +37,10 @@ import org.openide.util.NbBundle;
|
||||
class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescriptor> {
|
||||
|
||||
private int index = 0;
|
||||
private List<WizardDescriptor.Panel<WizardDescriptor>> panels;
|
||||
private AddImageAction action;
|
||||
private List<ShortcutWizardDescriptorPanel> panels;
|
||||
private final AddImageAction action;
|
||||
private int progressPanelIndex;
|
||||
private final static String PROP_LASTPROFILE_NAME = "AIW_LASTPROFILE_NAME"; //NON-NLS
|
||||
|
||||
AddImageWizardIterator(AddImageAction action) {
|
||||
this.action = action;
|
||||
@ -45,19 +50,22 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
|
||||
* Initialize panels representing individual wizard's steps and sets various
|
||||
* properties for them influencing wizard appearance.
|
||||
*/
|
||||
private List<WizardDescriptor.Panel<WizardDescriptor>> getPanels() {
|
||||
private List<ShortcutWizardDescriptorPanel> getPanels() {
|
||||
if (panels == null) {
|
||||
panels = new ArrayList<WizardDescriptor.Panel<WizardDescriptor>>();
|
||||
panels = new ArrayList<>();
|
||||
|
||||
AddImageWizardAddingProgressPanel progressPanel = new AddImageWizardAddingProgressPanel();
|
||||
|
||||
AddImageWizardChooseDataSourcePanel dsPanel = new AddImageWizardChooseDataSourcePanel(progressPanel);
|
||||
AddImageWizardIngestConfigPanel ingestConfigPanel = new AddImageWizardIngestConfigPanel(dsPanel, action, progressPanel);
|
||||
|
||||
panels.add(dsPanel);
|
||||
List<IngestProfiles.IngestProfile> profiles = IngestProfiles.getIngestProfiles();
|
||||
if (!profiles.isEmpty()) {
|
||||
panels.add(new IngestProfileSelectionWizardPanel(AddImageWizardIngestConfigPanel.class.getCanonicalName(), getPropLastprofileName()));
|
||||
}
|
||||
panels.add(ingestConfigPanel);
|
||||
panels.add(progressPanel);
|
||||
|
||||
progressPanelIndex = panels.indexOf(progressPanel); //Doing programatically because number of panels is variable
|
||||
String[] steps = new String[panels.size()];
|
||||
for (int i = 0; i < panels.size(); i++) {
|
||||
Component c = panels.get(i).getComponent();
|
||||
@ -66,7 +74,7 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
|
||||
if (c instanceof JComponent) { // assume Swing components
|
||||
JComponent jc = (JComponent) c;
|
||||
// Sets step number of a component
|
||||
jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i));
|
||||
jc.putClientProperty("WizardPanel_contentSelectedIndex", i);
|
||||
// Sets steps names for a panel
|
||||
jc.putClientProperty("WizardPanel_contentData", steps);
|
||||
// Turn on subtitle creation on each step
|
||||
@ -91,13 +99,30 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the property which stores the name of the last profile
|
||||
* used by the Add Image Wizard.
|
||||
*
|
||||
* @return the PROP_LASTPROFILE_NAME
|
||||
*/
|
||||
static String getPropLastprofileName() {
|
||||
return PROP_LASTPROFILE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the PROP_LASTPROFILE_NAME
|
||||
*/
|
||||
static String getPROP_LASTPROFILE_NAME() {
|
||||
return PROP_LASTPROFILE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current panel.
|
||||
*
|
||||
* @return panel the current panel
|
||||
*/
|
||||
@Override
|
||||
public WizardDescriptor.Panel<WizardDescriptor> current() {
|
||||
public ShortcutWizardDescriptorPanel current() {
|
||||
if (panels != null) {
|
||||
return panels.get(index);
|
||||
} else {
|
||||
@ -146,7 +171,14 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
boolean panelEnablesSkipping = current().panelEnablesSkipping();
|
||||
boolean skipNextPanel = current().skipNextPanel();
|
||||
index++;
|
||||
if (panelEnablesSkipping && skipNextPanel) {
|
||||
current().processThisPanelBeforeSkipped();
|
||||
nextPanel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -158,7 +190,7 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
|
||||
if (!hasPrevious()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
if (index == 2) {
|
||||
if (index == progressPanelIndex) {
|
||||
index--;
|
||||
}
|
||||
index--;
|
||||
|
@ -15,12 +15,6 @@ NewCaseVisualPanel1.caseNameTextField.text_1=
|
||||
NewCaseVisualPanel1.jLabel2.text_1=Case data will be stored in the following directory:
|
||||
NewCaseVisualPanel1.caseParentDirTextField.text=
|
||||
NewCaseVisualPanel1.caseDirTextField.text_1=
|
||||
CasePropertiesForm.caseDirLabel.text=Case Directory:
|
||||
CasePropertiesForm.crDateLabel.text=Created Date:
|
||||
CasePropertiesForm.caseNameLabel.text=Case Name:
|
||||
CasePropertiesForm.caseNameTextField.text=
|
||||
CasePropertiesForm.updateCaseNameButton.text=Update Name
|
||||
CasePropertiesForm.deleteCaseButton.text=Delete Case
|
||||
CueBannerPanel.autopsyLogo.text=
|
||||
CueBannerPanel.createNewLabel.text=Create New Case
|
||||
CueBannerPanel.openLabel.text=Open Existing Case
|
||||
@ -31,8 +25,6 @@ CueBannerPanel.openCaseButton.text=
|
||||
CueBannerPanel.openRecentButton.text=
|
||||
OpenRecentCasePanel.cancelButton.text=Cancel
|
||||
OpenRecentCasePanel.jLabel1.text=Recent Cases
|
||||
CasePropertiesForm.caseNumberLabel.text=Case Number:
|
||||
CasePropertiesForm.examinerLabel.text=Examiner:
|
||||
NewCaseVisualPanel2.caseNumberTextField.text=
|
||||
NewCaseVisualPanel2.examinerLabel.text=Examiner:
|
||||
NewCaseVisualPanel2.caseNumberLabel.text=Case Number:
|
||||
@ -102,12 +94,9 @@ AddImageWizardIngestConfigVisual.getName.text=Configure Ingest Modules
|
||||
AddImageWizardIterator.stepXofN=Step {0} of {1}
|
||||
AddLocalFilesTask.localFileAdd.progress.text=Adding\: {0}/{1}
|
||||
Case.getCurCase.exception.noneOpen=Cannot get the current case; there is no case open\!
|
||||
Case.create.exception.msg=Error creating a case\: {0} in dir {1}
|
||||
Case.databaseConnectionInfo.error.msg=Error accessing database server connection info. See Tools, Options, Multi-user.
|
||||
Case.open.exception.blankCase.msg=Case name is blank.
|
||||
Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the database with the following path has been made\:\n {0}
|
||||
Case.open.msgDlg.updated.title=Case Database Schema Update
|
||||
Case.open.exception.checkFile.msg=Case file must have {0} extension.
|
||||
Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-user.
|
||||
Case.checkImgExist.confDlg.doesntExist.msg={0} has detected that one of the images associated with \n\
|
||||
this case are missing. Would you like to search for them now?\n\
|
||||
@ -117,9 +106,6 @@ Please note that you will still be able to browse directories and generate repor
|
||||
if you choose No, but you will not be able to view file content or run the ingest process.
|
||||
Case.checkImgExist.confDlg.doesntExist.title=Missing Image
|
||||
Case.addImg.exception.msg=Error adding image to the case
|
||||
Case.closeCase.exception.msg=Error while trying to close the current case.
|
||||
Case.deleteCase.exception.msg=Error deleting the case dir\: {0}
|
||||
Case.deleteCase.exception.msg2=Error deleting the case dir\: {0}
|
||||
Case.updateCaseName.exception.msg=Error while trying to update the case name.
|
||||
Case.updateExaminer.exception.msg=Error while trying to update the examiner.
|
||||
Case.updateCaseNum.exception.msg=Error while trying to update the case number.
|
||||
@ -137,7 +123,6 @@ Case.GetCaseTypeGivenPath.Failure=Unable to get case type
|
||||
Case.metaDataFileCorrupt.exception.msg=The case metadata file (.aut) is corrupted.
|
||||
Case.deleteReports.deleteFromDiskException.log.msg=Unable to delete the report from the disk.
|
||||
Case.deleteReports.deleteFromDiskException.msg=Unable to delete the report {0} from the disk.\nYou may manually delete it from {1}
|
||||
Case.exception.errorLocking=Unable to open case being updated by another user.
|
||||
CaseDeleteAction.closeConfMsg.text=Are you sure want to close and delete this case? \n\
|
||||
Case Name\: {0}\n\
|
||||
Case Directory\: {1}
|
||||
@ -229,8 +214,6 @@ NewCaseVisualPanel1.caseParentDirWarningLabel.text=
|
||||
NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-user
|
||||
NewCaseVisualPanel1.singleUserCaseRadioButton.text=Single-user
|
||||
NewCaseVisualPanel1.caseTypeLabel.text=Case Type:
|
||||
CasePropertiesForm.lbDbType.text=Case Type:
|
||||
CasePropertiesForm.lbDbName.text=Database Name:
|
||||
SingleUserCaseConverter.BadDatabaseFileName=Database file does not exist!
|
||||
SingleUserCaseConverter.AlreadyMultiUser=Case is already multi-user!
|
||||
SingleUserCaseConverter.NonUniqueDatabaseName=Database name not unique.
|
||||
@ -250,3 +233,13 @@ LocalDiskPanel.imageWriterErrorLabel.text=Error Label
|
||||
LocalDiskPanel.jLabel1.text=Note that at least one ingest module must be run to create a complete copy
|
||||
LocalDiskPanel.pathTextField.text=
|
||||
LocalDiskPanel.browseButton.text=Browse
|
||||
CasePropertiesPanel.updateCaseNameButton.text=Update Name
|
||||
CasePropertiesPanel.caseNameTextField.text=
|
||||
CasePropertiesPanel.caseDirLabel.text=Case Directory:
|
||||
CasePropertiesPanel.crDateLabel.text=Created Date:
|
||||
CasePropertiesPanel.caseNameLabel.text=Case Name:
|
||||
CasePropertiesPanel.lbDbName.text=Database Name:
|
||||
CasePropertiesPanel.lbDbType.text=Case Type:
|
||||
CasePropertiesPanel.examinerLabel.text=Examiner:
|
||||
CasePropertiesPanel.caseNumberLabel.text=Case Number:
|
||||
CasePropertiesPanel.deleteCaseButton.text=Delete Case
|
||||
|
@ -1,4 +1,3 @@
|
||||
CTL_AddImage=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0...
|
||||
CTL_AddImageButton=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0
|
||||
CTL_CaseCloseAct=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b
|
||||
CTL_CaseNewAction=\u65b0\u898f\u30b1\u30fc\u30b9...
|
||||
@ -12,19 +11,12 @@ NewCaseVisualPanel1.caseNameLabel.text_1=\u30b1\u30fc\u30b9\u540d\uff1a
|
||||
NewCaseVisualPanel1.caseDirLabel.text=\u30d9\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\uff1a
|
||||
NewCaseVisualPanel1.caseDirBrowseButton.text=\u95b2\u89a7
|
||||
NewCaseVisualPanel1.jLabel2.text_1=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u306f\u6b21\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306b\u4fdd\u5b58\u3055\u308c\u307e\u3059\uff1a
|
||||
CasePropertiesForm.caseDirLabel.text=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\uff1a
|
||||
CasePropertiesForm.crDateLabel.text=\u4f5c\u6210\u65e5\uff1a
|
||||
CasePropertiesForm.caseNameLabel.text=\u30b1\u30fc\u30b9\u540d\uff1a
|
||||
CasePropertiesForm.updateCaseNameButton.text=\u66f4\u65b0
|
||||
CasePropertiesForm.deleteCaseButton.text=\u30b1\u30fc\u30b9\u3092\u524a\u9664
|
||||
CueBannerPanel.createNewLabel.text=\u65b0\u898f\u30b1\u30fc\u30b9\u3092\u4f5c\u6210
|
||||
CueBannerPanel.openLabel.text=\u65e2\u5b58\u30b1\u30fc\u30b9\u3092\u958b\u304f
|
||||
CueBannerPanel.closeButton.text=\u9589\u3058\u308b
|
||||
CueBannerPanel.openRecentLabel.text=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f
|
||||
OpenRecentCasePanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb
|
||||
OpenRecentCasePanel.jLabel1.text=\u6700\u8fd1\u958b\u3044\u305f\u30d5\u30a1\u30a4\u30eb
|
||||
CasePropertiesForm.caseNumberLabel.text=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a
|
||||
CasePropertiesForm.examinerLabel.text=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a
|
||||
NewCaseVisualPanel2.examinerLabel.text=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a
|
||||
NewCaseVisualPanel2.caseNumberLabel.text=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a
|
||||
NewCaseVisualPanel2.optionalLabel.text=\u30aa\u30d7\u30b7\u30e7\u30ca\u30eb\uff1a\u30b1\u30fc\u30b9\u756a\u53f7\u304a\u3088\u3073\u8abf\u67fb\u62c5\u5f53\u8005\u3092\u8a2d\u5b9a
|
||||
@ -80,21 +72,15 @@ AddImageWizardIngestConfigVisual.getName.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30
|
||||
AddImageWizardIterator.stepXofN=\u30b9\u30c6\u30c3\u30d7{0}\uff0f{1}
|
||||
AddLocalFilesTask.localFileAdd.progress.text=\u8ffd\u52a0\u4e2d\uff1a{0}/{1}
|
||||
Case.getCurCase.exception.noneOpen=\u4f5c\u696d\u4e2d\u306e\u30b1\u30fc\u30b9\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\uff1b\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\uff01
|
||||
Case.create.exception.msg=\u30b1\u30fc\u30b9\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{1}\u306e{0}
|
||||
Case.open.exception.blankCase.msg=\u30b1\u30fc\u30b9\u540d\u304c\u7a7a\u767d\u3067\u3059\u3002
|
||||
Case.open.msgDlg.updated.msg=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002\n\u6b21\u306e\u30d1\u30b9\u3092\u6301\u3064\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30b3\u30d4\u30fc\u304c\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\uff1a\n\
|
||||
{0}
|
||||
Case.open.msgDlg.updated.title=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0
|
||||
Case.open.exception.checkFile.msg=\u30b1\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u306f{0}\u62e1\u5f35\u5b50\u304c\u5fc5\u8981\u3067\u3059\u3002
|
||||
Case.checkImgExist.confDlg.doesntExist.msg={0} \u304c\u3053\u306e\u30b1\u30fc\u30b9\u306b\u95a2\u9023\u3059\u308b\u30a4\u30e1\u30fc\u30b8\u306e\u3046\u3061\uff11\u3064\u304c\u6b20\u843d\u3057\u3066\u3044\u308b\u306e\u3092\u691c\u51fa\u3057\u307e\u3057\u305f\u3002\u305d\u308c\u3092\u4eca\u304b\u3089\u691c\u7d22\u3057\u307e\u3059\u304b\uff1f\n\n\
|
||||
\u4ee5\u524d\u3001\u30a4\u30e1\u30fc\u30b8\u306f\u6b21\u306b\u3042\u308a\u307e\u3057\u305f\uff1a\n\
|
||||
{1}\n\
|
||||
\u3044\u3044\u3048\u3092\u9078\u629e\u3057\u3066\u3082\u3001\u4eca\u5f8c\u3082\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u95b2\u89a7\u3057\u3001\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u304c\u3067\u304d\u307e\u3059\u304c\u3001\n\u30d5\u30a1\u30a4\u30eb\u30b3\u30f3\u30c6\u30f3\u30c4\u306e\u8868\u793a\u307e\u305f\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30d7\u30ed\u30bb\u30b9\u306e\u5b9f\u884c\u304c\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002
|
||||
Case.checkImgExist.confDlg.doesntExist.title=\u6b20\u843d\u3057\u3066\u3044\u308b\u30a4\u30e1\u30fc\u30b8
|
||||
Case.addImg.exception.msg=\u30b1\u30fc\u30b9\u306b\u30a4\u30e1\u30fc\u30b8\u3092\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
|
||||
Case.closeCase.exception.msg=\u4f5c\u696d\u4e2d\u306e\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b\u6700\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
|
||||
Case.deleteCase.exception.msg=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}
|
||||
Case.deleteCase.exception.msg2=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}
|
||||
Case.updateCaseName.exception.msg=\u30b1\u30fc\u30b9\u540d\u3092\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
|
||||
Case.updateExaminer.exception.msg=\u8abf\u67fb\u62c5\u5f53\u8005\u3092\u66f4\u65b0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
|
||||
Case.updateCaseNum.exception.msg=\u30b1\u30fc\u30b9\u756a\u53f7\u3092\u66f4\u65b0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
|
||||
@ -203,8 +189,6 @@ CollaborationMonitor.addingDataSourceStatus.msg={0}\u304c\u30c7\u30fc\u30bf\u30d
|
||||
CollaborationMonitor.analyzingDataSourceStatus.msg={0}\u304c{1}\u3092\u89e3\u6790\u4e2d
|
||||
NewCaseVisualPanel1.multiUserCaseRadioButton.text=\u8907\u6570\u30e6\u30fc\u30b6\u30fc
|
||||
NewCaseVisualPanel1.singleUserCaseRadioButton.text=\u5358\u6570\u30e6\u30fc\u30b6\u30fc
|
||||
CasePropertiesForm.lbDbType.text=\u30b1\u30fc\u30b9\u30bf\u30a4\u30d7\uff1a
|
||||
CasePropertiesForm.lbDbName.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\uff1a
|
||||
SingleUserCaseConverter.BadDatabaseFileName=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u307e\u305b\u3093\uff01
|
||||
SingleUserCaseConverter.AlreadyMultiUser=\u30b1\u30fc\u30b9\u306f\u65e2\u306b\u8907\u6570\u30e6\u30fc\u30b6\u30fc\u3067\u3059\uff01
|
||||
SingleUserCaseConverter.NonUniqueDatabaseName=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\u304c\u30e6\u30cb\u30fc\u30af\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
|
||||
@ -216,3 +200,12 @@ Case_caseType_multiUser=\u8907\u6570\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9
|
||||
Case_caseType_singleUser=\u5358\u6570\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9
|
||||
CasePropertiesForm.imagesTable.columnModel.title0=\u30d1\u30b9
|
||||
CasePropertiesForm.imagesTable.columnModel.title1=\u524a\u9664
|
||||
CasePropertiesPanel.updateCaseNameButton.text=\u66f4\u65b0
|
||||
CasePropertiesPanel.caseDirLabel.text=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\uff1a
|
||||
CasePropertiesPanel.crDateLabel.text=\u4f5c\u6210\u65e5\uff1a
|
||||
CasePropertiesPanel.caseNameLabel.text=\u30b1\u30fc\u30b9\u540d\uff1a
|
||||
CasePropertiesPanel.lbDbName.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\uff1a
|
||||
CasePropertiesPanel.lbDbType.text=\u30b1\u30fc\u30b9\u30bf\u30a4\u30d7\uff1a
|
||||
CasePropertiesPanel.examinerLabel.text=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a
|
||||
CasePropertiesPanel.caseNumberLabel.text=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a
|
||||
CasePropertiesPanel.deleteCaseButton.text=\u30b1\u30fc\u30b9\u3092\u524a\u9664
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,31 +19,33 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.SwingWorker;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.util.actions.Presenter;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.DialogDescriptor;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.windows.WindowManager;
|
||||
import java.awt.Cursor;
|
||||
import org.openide.awt.ActionID;
|
||||
import org.openide.awt.ActionReference;
|
||||
import org.openide.awt.ActionReferences;
|
||||
import org.openide.awt.ActionRegistration;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.util.actions.Presenter;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
|
||||
/**
|
||||
* The action to close the current Case. This class should be disabled on
|
||||
* creation and it will be enabled on new case creation or case opened.
|
||||
* The action associated with the Case/Close Case menu item and the Close Case
|
||||
* toolbar button. It closes the current case and pops up the start up window
|
||||
* that allows a user to open another case.
|
||||
*
|
||||
* This action should only be invoked in the event dispatch thread (EDT).
|
||||
*/
|
||||
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.casemodule.CaseCloseAction")
|
||||
@ActionRegistration(displayName = "#CTL_CaseCloseAct", lazy = false)
|
||||
@ -51,87 +53,69 @@ import org.openide.awt.ActionRegistration;
|
||||
@ActionReference(path = "Toolbars/Case", position = 104)})
|
||||
public final class CaseCloseAction extends CallableSystemAction implements Presenter.Toolbar {
|
||||
|
||||
JButton toolbarButton = new JButton();
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(CaseCloseAction.class.getName());
|
||||
private final JButton toolbarButton = new JButton();
|
||||
|
||||
/**
|
||||
* The constructor for this class
|
||||
* Constructs the action associated with the Case/Close Case menu item and
|
||||
* the Close Case toolbar button.
|
||||
*/
|
||||
public CaseCloseAction() {
|
||||
putValue("iconBase", "org/sleuthkit/autopsy/images/close-icon.png"); // put the icon NON-NLS
|
||||
putValue(Action.NAME, NbBundle.getMessage(CaseCloseAction.class, "CTL_CaseCloseAct")); // put the action Name
|
||||
|
||||
// set action of the toolbar button
|
||||
putValue("iconBase", "org/sleuthkit/autopsy/images/close-icon.png"); //NON-NLS
|
||||
putValue(Action.NAME, NbBundle.getMessage(CaseCloseAction.class, "CTL_CaseCloseAct")); //NON-NLS
|
||||
toolbarButton.addActionListener(CaseCloseAction.this::actionPerformed);
|
||||
|
||||
this.setEnabled(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the current opened case.
|
||||
* Closes the current case.
|
||||
*
|
||||
* @param e the action event for this method
|
||||
* @param e The action event.
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
// if ingest is ongoing, warn and get confirmaion before opening a different case
|
||||
if (IngestManager.getInstance().isIngestRunning()) {
|
||||
// show the confirmation first to close the current case and open the "New Case" wizard panel
|
||||
String closeCurrentCase = NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning");
|
||||
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(closeCurrentCase,
|
||||
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning.title"),
|
||||
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
|
||||
descriptor.setValue(NotifyDescriptor.NO_OPTION);
|
||||
|
||||
Object res = DialogDisplayer.getDefault().notify(descriptor);
|
||||
if (res != null && res == DialogDescriptor.YES_OPTION) {
|
||||
try {
|
||||
Case.getCurrentCase().closeCase(); // close the current case
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(NewCaseWizardAction.class.getName()).log(Level.WARNING, "Error closing case.", ex); //NON-NLS
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Case.isCaseOpen() == false) {
|
||||
return;
|
||||
}
|
||||
String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
|
||||
String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
|
||||
if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
new SwingWorker<Void, Void>() {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
try {
|
||||
Case result = Case.getCurrentCase();
|
||||
result.closeCase();
|
||||
} catch (CaseActionException | IllegalStateException unused) {
|
||||
// Already logged.
|
||||
}
|
||||
Case.closeCurrentCase();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
get();
|
||||
} catch (InterruptedException ex) {
|
||||
logger.log(Level.SEVERE, "Unexpected interrupt closing the current case", ex);
|
||||
} catch (ExecutionException ex) {
|
||||
logger.log(Level.SEVERE, "Error closing the current case", ex);
|
||||
MessageNotifyUtil.Message.error(Bundle.Case_closeException_couldNotCloseCase(ex.getMessage()));
|
||||
}
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
StartupWindowProvider.getInstance().open();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does nothing. Use the "actionPerformed(ActionEvent e)"
|
||||
* instead of this method.
|
||||
*/
|
||||
@Override
|
||||
public void performAction() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this action. This may be presented as an item in a menu.
|
||||
* Closes the current case.
|
||||
*/
|
||||
@Override
|
||||
public void performAction() {
|
||||
actionPerformed(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the action name.
|
||||
*
|
||||
* @return actionName
|
||||
* @return The action name.
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
@ -139,9 +123,9 @@ public final class CaseCloseAction extends CallableSystemAction implements Prese
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the HelpCtx associated with implementing object
|
||||
* Gets the help context.
|
||||
*
|
||||
* @return HelpCtx or HelpCtx.DEFAULT_HELP
|
||||
* @return The help context.
|
||||
*/
|
||||
@Override
|
||||
public HelpCtx getHelpCtx() {
|
||||
@ -149,9 +133,9 @@ public final class CaseCloseAction extends CallableSystemAction implements Prese
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the toolbar component of this action
|
||||
* Returns the toolbar component of this action.
|
||||
*
|
||||
* @return component the toolbar button
|
||||
* @return The toolbar button
|
||||
*/
|
||||
@Override
|
||||
public Component getToolbarPresenter() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,138 +19,106 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import org.openide.DialogDescriptor;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingWorker;
|
||||
import org.openide.DialogDescriptor;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import org.openide.DialogDescriptor;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
|
||||
/**
|
||||
* The action to delete the current Case. This class should be disabled on
|
||||
* creation and it will be enabled on new case creation or case opened.
|
||||
* The action associated with the Delete button of the Case Properties panel. It
|
||||
* deletes the current case.
|
||||
*
|
||||
* This action should only be invoked in the event dispatch thread (EDT).
|
||||
*/
|
||||
|
||||
|
||||
final class CaseDeleteAction extends CallableSystemAction {
|
||||
|
||||
private JPanel caller; // for error handling
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(CaseDeleteAction.class.getName());
|
||||
|
||||
/**
|
||||
* The constructor for this class
|
||||
*/
|
||||
public CaseDeleteAction() {
|
||||
putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction")); // put the action Name
|
||||
CaseDeleteAction() {
|
||||
putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction"));
|
||||
this.setEnabled(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the current opened case.
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
@Override
|
||||
@Messages({
|
||||
"Case.deleteCaseConfirmationDialog.title=Delete Current Case?",
|
||||
"Case.deleteCaseConfirmationDialog.message=Are you sure you want to close and delete the current case?",
|
||||
"Case.deleteCaseFailureMessageBox.title=Failed to Delete Case",
|
||||
"# {0} - exception message", "Case.deleteCaseFailureMessageBox.message=Error deleting case: {0}",})
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Case currentCase = Case.getCurrentCase();
|
||||
File caseFolder = new File(currentCase.getCaseDirectory());
|
||||
String caseName = currentCase.getName();
|
||||
if (!caseFolder.exists()) {
|
||||
// throw an error
|
||||
|
||||
logger.log(Level.WARNING, "Couldn't delete case.", new Exception("The case directory doesn't exist.")); //NON-NLS
|
||||
} else {
|
||||
// show the confirmation first to close the current case and open the "New Case" wizard panel
|
||||
String closeCurrentCase = NbBundle.getMessage(this.getClass(), "CaseDeleteAction.closeConfMsg.text", caseName, caseFolder.getPath());
|
||||
NotifyDescriptor d = new NotifyDescriptor.Confirmation(closeCurrentCase,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"CaseDeleteAction.closeConfMsg.title"),
|
||||
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
|
||||
d.setValue(NotifyDescriptor.NO_OPTION);
|
||||
|
||||
Object res = DialogDisplayer.getDefault().notify(d);
|
||||
if (res != null && res == DialogDescriptor.YES_OPTION) {
|
||||
boolean success = false;
|
||||
|
||||
try {
|
||||
Case.getCurrentCase().deleteCase(caseFolder); // delete the current case
|
||||
success = true;
|
||||
} catch (CaseActionException ex) {
|
||||
logger.log(Level.WARNING, "Could not delete the case folder: " + caseFolder); //NON-NLS
|
||||
}
|
||||
Case currentCase = Case.getCurrentCase();
|
||||
String caseName = currentCase.getName();
|
||||
String caseDirectory = currentCase.getCaseDirectory();
|
||||
|
||||
// show notification whether the case has been deleted or it failed to delete...
|
||||
if (!success) {
|
||||
JOptionPane.showMessageDialog(caller,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"CaseDeleteAction.msgDlg.fileInUse.msg"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"CaseDeleteAction.msgDlg.fileInUse.title"),
|
||||
JOptionPane.ERROR_MESSAGE); // throw an error
|
||||
} else {
|
||||
CasePropertiesAction.closeCasePropertiesWindow(); // because the "Delete Case" button is in the "CaseProperties" window, we have to close that window when we delete the case.
|
||||
JOptionPane.showMessageDialog(caller, NbBundle.getMessage(this.getClass(),
|
||||
"CaseDeleteAction.msgDlg.caseDelete.msg",
|
||||
caseName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does nothing. Use the "actionPerformed(ActionEvent e)"
|
||||
* instead of this method.
|
||||
/*
|
||||
* Do a confirmation dialog and close the current case if the user
|
||||
* confirms he/she wants to proceed.
|
||||
*/
|
||||
Object response = DialogDisplayer.getDefault().notify(new NotifyDescriptor(
|
||||
Bundle.Case_deleteCaseConfirmationDialog_message(),
|
||||
Bundle.Case_deleteCaseConfirmationDialog_title(),
|
||||
NotifyDescriptor.YES_NO_OPTION,
|
||||
NotifyDescriptor.WARNING_MESSAGE,
|
||||
null,
|
||||
NotifyDescriptor.NO_OPTION));
|
||||
if (null != response && DialogDescriptor.YES_OPTION == response) {
|
||||
|
||||
new SwingWorker<Void, Void>() {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
Case.deleteCurrentCase();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
get();
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Failed to delete case %s at %s", caseName, caseDirectory), ex);
|
||||
JOptionPane.showMessageDialog(
|
||||
null,
|
||||
Bundle.Case_deleteCaseFailureMessageBox_message(ex.getMessage()),
|
||||
Bundle.Case_deleteCaseFailureMessageBox_title(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
/*
|
||||
* Close the Case Properties dialog that is the parent
|
||||
* of the Delete button that invokes this action.
|
||||
*/
|
||||
CasePropertiesAction.closeCasePropertiesWindow();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
} catch (IllegalStateException ex) {
|
||||
logger.log(Level.SEVERE, "Case delete action called with no current case", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAction() {
|
||||
// Note: I use the actionPerformed above instead of this method
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this action. This may be presented as an item in a menu.
|
||||
*
|
||||
* @return actionName
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the HelpCtx associated with implementing object
|
||||
*
|
||||
* @return HelpCtx or HelpCtx.DEFAULT_HELP
|
||||
*/
|
||||
@Override
|
||||
public HelpCtx getHelpCtx() {
|
||||
return HelpCtx.DEFAULT_HELP;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ class CaseInformationPanel extends javax.swing.JPanel {
|
||||
|
||||
// put the image paths information into hashmap
|
||||
Map<Long, String> imgPaths = Case.getImagePaths(currentCase.getSleuthkitCase());
|
||||
CasePropertiesForm cpf = new CasePropertiesForm(currentCase, crDate, caseDir, imgPaths);
|
||||
CasePropertiesPanel cpf = new CasePropertiesPanel(currentCase, crDate, caseDir, imgPaths);
|
||||
cpf.setSize(cpf.getPreferredSize());
|
||||
this.tabbedPane.addTab(Bundle.CaseInformationPanel_caseDetails_header(), cpf);
|
||||
this.tabbedPane.addTab(Bundle.CaseInformationPanel_ingestJobInfo_header(), new IngestJobInfoPanel());
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -54,10 +54,11 @@ public final class CaseMetadata {
|
||||
private static final String FILE_EXTENSION = ".aut";
|
||||
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)");
|
||||
private static final String SCHEMA_VERSION_ONE = "1.0";
|
||||
private final static String AUTOPSY_CREATED_VERSION_ELEMENT_NAME = "AutopsyCreatedVersion"; //NON-NLS
|
||||
private static final String SCHEMA_VERSION_TWO = "2.0";
|
||||
private final static String AUTOPSY_VERSION_ELEMENT_NAME = "AutopsyCreatedVersion"; //NON-NLS
|
||||
private final static String CASE_DATABASE_NAME_ELEMENT_NAME = "DatabaseName"; //NON-NLS
|
||||
private final static String TEXT_INDEX_NAME_ELEMENT = "TextIndexName"; //NON-NLS
|
||||
private static final String CURRENT_SCHEMA_VERSION = "2.0";
|
||||
private static final String CURRENT_SCHEMA_VERSION = "3.0";
|
||||
private final static String ROOT_ELEMENT_NAME = "AutopsyCase"; //NON-NLS
|
||||
private final static String SCHEMA_VERSION_ELEMENT_NAME = "SchemaVersion"; //NON-NLS
|
||||
private final static String CREATED_DATE_ELEMENT_NAME = "CreatedDate"; //NON-NLS
|
||||
@ -66,6 +67,7 @@ public final class CaseMetadata {
|
||||
private final static String AUTOPSY_SAVED_BY_ELEMENT_NAME = "SavedByAutopsyVersion"; //NON-NLS
|
||||
private final static String CASE_ELEMENT_NAME = "Case"; //NON-NLS
|
||||
private final static String CASE_NAME_ELEMENT_NAME = "Name"; //NON-NLS
|
||||
private final static String CASE_DISPLAY_NAME_ELEMENT_NAME = "DisplayName"; //NON-NLS
|
||||
private final static String CASE_NUMBER_ELEMENT_NAME = "Number"; //NON-NLS
|
||||
private final static String EXAMINER_ELEMENT_NAME = "Examiner"; //NON-NLS
|
||||
private final static String CASE_TYPE_ELEMENT_NAME = "CaseType"; //NON-NLS
|
||||
@ -74,9 +76,10 @@ public final class CaseMetadata {
|
||||
private final Path metadataFilePath;
|
||||
private Case.CaseType caseType;
|
||||
private String caseName;
|
||||
private String caseDisplayName;
|
||||
private String caseNumber;
|
||||
private String examiner;
|
||||
private String caseDatabase;
|
||||
private String caseDatabaseName;
|
||||
private String textIndexName;
|
||||
private String createdDate;
|
||||
private String createdByVersion;
|
||||
@ -96,25 +99,26 @@ public final class CaseMetadata {
|
||||
*
|
||||
* @param caseDirectory The case directory.
|
||||
* @param caseType The type of case.
|
||||
* @param caseName The name of the case.
|
||||
* @param caseName The immutable name of the case.
|
||||
* @param caseDisplayName The display name of the case, can be changed by a
|
||||
* user.
|
||||
* @param caseNumber The case number.
|
||||
* @param examiner The name of the case examiner.
|
||||
* @param caseDatabase For a single-user case, the full path to the
|
||||
* case database file. For a multi-user case, the
|
||||
* case database name.
|
||||
* @param caseTextIndexName The text index name.
|
||||
* @param caseDatabase For a single-user case, the full path to the case
|
||||
* database file. For a multi-user case, the case
|
||||
* database name.
|
||||
*
|
||||
* @throws CaseMetadataException If the new case metadata file cannot be
|
||||
* created.
|
||||
*/
|
||||
CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseNumber, String examiner, String caseDatabase, String caseTextIndexName) throws CaseMetadataException {
|
||||
CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseDisplayName, String caseNumber, String examiner, String caseDatabase) throws CaseMetadataException {
|
||||
metadataFilePath = Paths.get(caseDirectory, caseName + FILE_EXTENSION);
|
||||
this.caseType = caseType;
|
||||
this.caseName = caseName;
|
||||
this.caseDisplayName = caseDisplayName;
|
||||
this.caseNumber = caseNumber;
|
||||
this.examiner = examiner;
|
||||
this.caseDatabase = caseDatabase;
|
||||
this.textIndexName = caseTextIndexName;
|
||||
this.caseDatabaseName = caseDatabase;
|
||||
createdByVersion = Version.getVersion();
|
||||
createdDate = CaseMetadata.DATE_FORMAT.format(new Date());
|
||||
writeToFile();
|
||||
@ -162,7 +166,7 @@ public final class CaseMetadata {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the case display name.
|
||||
* Gets the immutable case name, set at case creation.
|
||||
*
|
||||
* @return The case display name.
|
||||
*/
|
||||
@ -170,19 +174,28 @@ public final class CaseMetadata {
|
||||
return caseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the case display name.
|
||||
*
|
||||
* @return The case display name.
|
||||
*/
|
||||
public String getCaseDisplayName() {
|
||||
return this.caseDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the case display name. This does not change the name of the case
|
||||
* directory, the case database, or the text index name.
|
||||
*
|
||||
* @param caseName A case display name.
|
||||
*/
|
||||
void setCaseName(String caseName) throws CaseMetadataException {
|
||||
void setCaseDisplayName(String caseName) throws CaseMetadataException {
|
||||
String oldCaseName = caseName;
|
||||
this.caseName = caseName;
|
||||
this.caseDisplayName = caseName;
|
||||
try {
|
||||
writeToFile();
|
||||
} catch (CaseMetadataException ex) {
|
||||
this.caseName = oldCaseName;
|
||||
this.caseDisplayName = oldCaseName;
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
@ -206,31 +219,27 @@ public final class CaseMetadata {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the case case database.
|
||||
* Gets the name of the case database.
|
||||
*
|
||||
* @return The case database name.
|
||||
*/
|
||||
public String getCaseDatabaseName() {
|
||||
if (caseType == Case.CaseType.MULTI_USER_CASE) {
|
||||
return caseDatabase;
|
||||
} else {
|
||||
return Paths.get(caseDatabase).getFileName().toString();
|
||||
}
|
||||
return caseDatabaseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the full path to the case database file if the case is a single-user
|
||||
* case.
|
||||
* Sets the text index name.
|
||||
*
|
||||
* @return The full path to the case database file for a single-user case.
|
||||
*
|
||||
* @throws UnsupportedOperationException If called for a multi-user case.
|
||||
* @param caseTextIndexName The text index name.
|
||||
*/
|
||||
public String getCaseDatabasePath() throws UnsupportedOperationException {
|
||||
if (caseType == Case.CaseType.SINGLE_USER_CASE) {
|
||||
return caseDatabase;
|
||||
} else {
|
||||
throw new UnsupportedOperationException();
|
||||
void setTextIndexName(String caseTextIndexName) throws CaseMetadataException {
|
||||
String oldIndexName = caseTextIndexName;
|
||||
this.textIndexName = caseTextIndexName;
|
||||
try {
|
||||
writeToFile();
|
||||
} catch (CaseMetadataException ex) {
|
||||
this.textIndexName = oldIndexName;
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,10 +364,11 @@ public final class CaseMetadata {
|
||||
* Create the children of the case element.
|
||||
*/
|
||||
createChildElement(doc, caseElement, CASE_NAME_ELEMENT_NAME, caseName);
|
||||
createChildElement(doc, caseElement, CASE_DISPLAY_NAME_ELEMENT_NAME, caseDisplayName);
|
||||
createChildElement(doc, caseElement, CASE_NUMBER_ELEMENT_NAME, caseNumber);
|
||||
createChildElement(doc, caseElement, EXAMINER_ELEMENT_NAME, examiner);
|
||||
createChildElement(doc, caseElement, CASE_TYPE_ELEMENT_NAME, caseType.toString());
|
||||
createChildElement(doc, caseElement, CASE_DATABASE_ELEMENT_NAME, caseDatabase);
|
||||
createChildElement(doc, caseElement, CASE_DATABASE_ELEMENT_NAME, caseDatabaseName);
|
||||
createChildElement(doc, caseElement, TEXT_INDEX_ELEMENT, textIndexName);
|
||||
}
|
||||
|
||||
@ -402,7 +412,7 @@ public final class CaseMetadata {
|
||||
String schemaVersion = getElementTextContent(rootElement, SCHEMA_VERSION_ELEMENT_NAME, true);
|
||||
this.createdDate = getElementTextContent(rootElement, CREATED_DATE_ELEMENT_NAME, true);
|
||||
if (schemaVersion.equals(SCHEMA_VERSION_ONE)) {
|
||||
this.createdByVersion = getElementTextContent(rootElement, AUTOPSY_CREATED_VERSION_ELEMENT_NAME, true);
|
||||
this.createdByVersion = getElementTextContent(rootElement, AUTOPSY_VERSION_ELEMENT_NAME, true);
|
||||
} else {
|
||||
this.createdByVersion = getElementTextContent(rootElement, AUTOPSY_CREATED_BY_ELEMENT_NAME, true);
|
||||
}
|
||||
@ -416,6 +426,11 @@ public final class CaseMetadata {
|
||||
}
|
||||
Element caseElement = (Element) caseElements.item(0);
|
||||
this.caseName = getElementTextContent(caseElement, CASE_NAME_ELEMENT_NAME, true);
|
||||
if (schemaVersion.equals(SCHEMA_VERSION_ONE) || schemaVersion.equals(SCHEMA_VERSION_TWO)) {
|
||||
this.caseDisplayName = caseName;
|
||||
} else {
|
||||
this.caseDisplayName = getElementTextContent(caseElement, CASE_DISPLAY_NAME_ELEMENT_NAME, true);
|
||||
}
|
||||
this.caseNumber = getElementTextContent(caseElement, CASE_NUMBER_ELEMENT_NAME, false);
|
||||
this.examiner = getElementTextContent(caseElement, EXAMINER_ELEMENT_NAME, false);
|
||||
this.caseType = Case.CaseType.fromString(getElementTextContent(caseElement, CASE_TYPE_ELEMENT_NAME, true));
|
||||
@ -423,18 +438,21 @@ public final class CaseMetadata {
|
||||
throw new CaseMetadataException("Case metadata file corrupted");
|
||||
}
|
||||
if (schemaVersion.equals(SCHEMA_VERSION_ONE)) {
|
||||
this.caseDatabase = getElementTextContent(caseElement, CASE_DATABASE_NAME_ELEMENT_NAME, true);
|
||||
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_NAME_ELEMENT_NAME, true);
|
||||
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_NAME_ELEMENT, true);
|
||||
} else {
|
||||
this.caseDatabase = getElementTextContent(caseElement, CASE_DATABASE_ELEMENT_NAME, true);
|
||||
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, true);
|
||||
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_ELEMENT_NAME, true);
|
||||
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the file to the current schema, if necessary.
|
||||
* Fix up the case database name due to a bug that for a time caused
|
||||
* the absolute paths of single-user case databases to be stored.
|
||||
*/
|
||||
if (!schemaVersion.equals(CURRENT_SCHEMA_VERSION)) {
|
||||
writeToFile();
|
||||
Path possibleAbsoluteCaseDbPath = Paths.get(this.caseDatabaseName);
|
||||
if (possibleAbsoluteCaseDbPath.getNameCount() > 1) {
|
||||
Path caseDirectoryPath = Paths.get(getCaseDirectory());
|
||||
this.caseDatabaseName = caseDirectoryPath.relativize(possibleAbsoluteCaseDbPath).toString();
|
||||
}
|
||||
|
||||
} catch (ParserConfigurationException | SAXException | IOException ex) {
|
||||
@ -483,4 +501,22 @@ public final class CaseMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the full path to the case database file if the case is a single-user
|
||||
* case.
|
||||
*
|
||||
* @return The full path to the case database file for a single-user case.
|
||||
*
|
||||
* @throws UnsupportedOperationException If called for a multi-user case.
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public String getCaseDatabasePath() throws UnsupportedOperationException {
|
||||
if (Case.CaseType.SINGLE_USER_CASE == caseType) {
|
||||
return Paths.get(getCaseDirectory(), caseDatabaseName).toString();
|
||||
} else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -26,27 +26,25 @@ import org.openide.util.actions.SystemAction;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
|
||||
/**
|
||||
* The action to create a new case. This action class is always enabled.
|
||||
* The action associated with the Case/New Case menu item and the Create New
|
||||
* Case button of the start up window that allows a user to open a case. It
|
||||
* invokes the New Case wizard.
|
||||
*
|
||||
* @author jantonius
|
||||
* This action should only be invoked in the event dispatch thread (EDT).
|
||||
*/
|
||||
@ServiceProvider(service = CaseNewActionInterface.class)
|
||||
public final class CaseNewAction extends CallableSystemAction implements CaseNewActionInterface {
|
||||
|
||||
private NewCaseWizardAction wizard = SystemAction.get(NewCaseWizardAction.class);
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Calls the "New Case" wizard panel action.
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
wizard.performAction();
|
||||
SystemAction.get(NewCaseWizardAction.class).performAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAction() {
|
||||
actionPerformed(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -22,39 +22,45 @@ import java.awt.Cursor;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.coreutils.Version;
|
||||
import org.openide.DialogDescriptor;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
|
||||
/**
|
||||
* An action that opens an existing case.
|
||||
* The action associated with the Case/Open Case menu item via the layer.xml
|
||||
* file, a toolbar button, and the Create New Case button of the start up window
|
||||
* that allows a user to open a case. It opens an existing case.
|
||||
*
|
||||
* This action should only be invoked in the event dispatch thread (EDT).
|
||||
*/
|
||||
@ServiceProvider(service = CaseOpenAction.class)
|
||||
public final class CaseOpenAction extends CallableSystemAction implements ActionListener {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CaseOpenAction.class.getName());
|
||||
private static final String PROP_BASECASE = "LBL_BaseCase_PATH"; //NON-NLS
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String PROP_BASECASE = "LBL_BaseCase_PATH"; //NON-NLS
|
||||
private static final Logger logger = Logger.getLogger(CaseOpenAction.class.getName());
|
||||
private final JFileChooser fileChooser = new JFileChooser();
|
||||
private final FileFilter caseMetadataFileFilter;
|
||||
|
||||
/**
|
||||
* Constructs an action that opens an existing case.
|
||||
* Constructs the action associated with the Case/Open Case menu item via
|
||||
* the layer.xml file, a toolbar button, and the Create New Case button of
|
||||
* the start up window that allows a user to open a case. It opens an
|
||||
* existing case.
|
||||
*
|
||||
*/
|
||||
public CaseOpenAction() {
|
||||
caseMetadataFileFilter = new FileNameExtensionFilter(NbBundle.getMessage(CaseOpenAction.class, "CaseOpenAction.autFilter.title", Version.getName(), CaseMetadata.getFileExtension()), CaseMetadata.getFileExtension().substring(1));
|
||||
@ -75,35 +81,9 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
/*
|
||||
* If ingest is running, do a dialog to warn the user and confirm the
|
||||
* intent to close the current case and leave the ingest process
|
||||
* incomplete.
|
||||
*/
|
||||
if (IngestManager.getInstance().isIngestRunning()) {
|
||||
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
|
||||
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning"),
|
||||
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning.title"),
|
||||
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
|
||||
descriptor.setValue(NotifyDescriptor.NO_OPTION);
|
||||
Object res = DialogDisplayer.getDefault().notify(descriptor);
|
||||
if (res != null && res == DialogDescriptor.YES_OPTION) {
|
||||
Case currentCase = null;
|
||||
try {
|
||||
currentCase = Case.getCurrentCase();
|
||||
currentCase.closeCase();
|
||||
} catch (IllegalStateException ignored) {
|
||||
/*
|
||||
* No current case.
|
||||
*/
|
||||
} catch (CaseActionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error closing case at %s while ingest was running", (null != currentCase ? currentCase.getCaseDirectory() : "?")), ex); //NON-NLS
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
|
||||
String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
|
||||
if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
|
||||
/**
|
||||
* Pop up a file chooser to allow the user to select a case metadata
|
||||
* file (.aut file).
|
||||
@ -116,36 +96,54 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
|
||||
StartupWindowProvider.getInstance().close();
|
||||
|
||||
/*
|
||||
* Try to open the case associated with the case metadata file the
|
||||
* user selected.
|
||||
* Try to open the case associated with the case metadata file
|
||||
* the user selected.
|
||||
*/
|
||||
final String path = fileChooser.getSelectedFile().getPath();
|
||||
String dirPath = fileChooser.getSelectedFile().getParent();
|
||||
ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE, dirPath.substring(0, dirPath.lastIndexOf(File.separator)));
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
new Thread(() -> {
|
||||
new SwingWorker<Void, Void>() {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
Case.openAsCurrentCase(path);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
Case.open(path);
|
||||
} catch (CaseActionException ex) {
|
||||
get();
|
||||
} catch (InterruptedException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
JOptionPane.showMessageDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
ex.getMessage(), // Should be user-friendly
|
||||
ex.getMessage(),
|
||||
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
StartupWindowProvider.getInstance().open();
|
||||
} catch (ExecutionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
JOptionPane.showMessageDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
ex.getCause().getMessage(), //get the message of the wrapped exception
|
||||
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
if (!Case.isCaseOpen()) {
|
||||
StartupWindowProvider.getInstance().open();
|
||||
}
|
||||
});
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAction() {
|
||||
actionPerformed(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,98 +23,70 @@ import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* The action to pop up the Case Properties Form window. By using this form,
|
||||
* user can update the case properties (for example: updates the case name and
|
||||
* removes the image from the current case)
|
||||
*
|
||||
* @author jantonius
|
||||
* The action associated with the Case/Case Properties menu item. It invokes the
|
||||
* Case Properties dialog.
|
||||
*/
|
||||
final class CasePropertiesAction extends CallableSystemAction {
|
||||
|
||||
private static JDialog popUpWindow;
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static JDialog casePropertiesDialog;
|
||||
|
||||
/**
|
||||
* The CasePropertiesAction constructor
|
||||
*/
|
||||
CasePropertiesAction() {
|
||||
putValue(Action.NAME, NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction")); // put the action Name
|
||||
putValue(Action.NAME, NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction"));
|
||||
this.setEnabled(false);
|
||||
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
popUpWindow = null;
|
||||
setEnabled(null != evt.getNewValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop-up the Case Properties Form window where user can change the case
|
||||
* properties (example: update case name and remove the image from the case)
|
||||
*/
|
||||
@Override
|
||||
public void performAction() {
|
||||
if (popUpWindow == null) {
|
||||
// create the popUp window for it
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (null == casePropertiesDialog) {
|
||||
String title = NbBundle.getMessage(this.getClass(), "CasePropertiesAction.window.title");
|
||||
popUpWindow = new JDialog((JFrame) WindowManager.getDefault().getMainWindow(), title, false);
|
||||
try {
|
||||
|
||||
casePropertiesDialog = new JDialog(WindowManager.getDefault().getMainWindow(), title, false);
|
||||
CaseInformationPanel caseInformationPanel = new CaseInformationPanel();
|
||||
caseInformationPanel.addCloseButtonAction((ActionEvent e) -> {
|
||||
popUpWindow.dispose();
|
||||
casePropertiesDialog.setVisible(false);
|
||||
});
|
||||
casePropertiesDialog.add(caseInformationPanel);
|
||||
casePropertiesDialog.setResizable(true);
|
||||
casePropertiesDialog.pack();
|
||||
|
||||
popUpWindow.add(caseInformationPanel);
|
||||
popUpWindow.setResizable(true);
|
||||
popUpWindow.pack();
|
||||
|
||||
// set the location of the popUp Window on the center of the screen
|
||||
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
double w = popUpWindow.getSize().getWidth();
|
||||
double h = popUpWindow.getSize().getHeight();
|
||||
popUpWindow.setLocation((int) ((screenDimension.getWidth() - w) / 2), (int) ((screenDimension.getHeight() - h) / 2));
|
||||
|
||||
popUpWindow.setVisible(true);
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(CasePropertiesAction.class.getName()).log(Level.WARNING, "Error displaying Case Properties window.", ex); //NON-NLS
|
||||
double w = casePropertiesDialog.getSize().getWidth();
|
||||
double h = casePropertiesDialog.getSize().getHeight();
|
||||
casePropertiesDialog.setLocation((int) ((screenDimension.getWidth() - w) / 2), (int) ((screenDimension.getHeight() - h) / 2));
|
||||
casePropertiesDialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
popUpWindow.setVisible(true);
|
||||
popUpWindow.toFront();
|
||||
casePropertiesDialog.setVisible(true);
|
||||
casePropertiesDialog.toFront();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this action. This may be presented as an item in a menu.
|
||||
*
|
||||
* @return actionName
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the HelpCtx associated with implementing object
|
||||
*
|
||||
* @return HelpCtx or HelpCtx.DEFAULT_HELP
|
||||
*/
|
||||
@Override
|
||||
public HelpCtx getHelpCtx() {
|
||||
return HelpCtx.DEFAULT_HELP;
|
||||
}
|
||||
|
||||
static void closeCasePropertiesWindow() {
|
||||
popUpWindow.dispose();
|
||||
casePropertiesDialog.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.caseNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -173,7 +173,7 @@
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.crDateLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.crDateLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -185,7 +185,7 @@
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseDirLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.caseDirLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -197,12 +197,9 @@
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.caseNameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="caseNameTextFieldActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="updateCaseNameButton">
|
||||
<Properties>
|
||||
@ -212,7 +209,7 @@
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.updateCaseNameButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.updateCaseNameButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -227,7 +224,7 @@
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.deleteCaseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.deleteCaseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -242,7 +239,7 @@
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNumberLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.caseNumberLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -254,7 +251,7 @@
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.examinerLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.examinerLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -266,7 +263,7 @@
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.lbDbType.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.lbDbType.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -278,7 +275,7 @@
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.lbDbName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.lbDbName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -17,14 +17,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* CasePropertiesForm.java
|
||||
*
|
||||
* Created on Mar 14, 2011, 1:48:20 PM
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JOptionPane;
|
||||
@ -37,55 +32,26 @@ import org.openide.util.actions.CallableSystemAction;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* The form where user can change / update the properties of the current case
|
||||
* metadata.
|
||||
* A panel that allows the user to view various properties of the current case
|
||||
* and change the display name of the case.
|
||||
*/
|
||||
class CasePropertiesForm extends javax.swing.JPanel {
|
||||
class CasePropertiesPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Case current = null;
|
||||
private static JPanel caller; // panel for error
|
||||
|
||||
// Shrink a path to fit in targetLength (if necessary), by replaceing part
|
||||
// of the path with "...". Ex: "C:\Users\bob\...\folder\other\Image.img"
|
||||
private String shrinkPath(String path, int targetLength) {
|
||||
if (path.length() > targetLength) {
|
||||
String fill = "...";
|
||||
|
||||
int partsLength = targetLength - fill.length();
|
||||
|
||||
String front = path.substring(0, partsLength / 4);
|
||||
int frontSep = front.lastIndexOf(File.separatorChar);
|
||||
if (frontSep != -1) {
|
||||
front = front.substring(0, frontSep + 1);
|
||||
}
|
||||
|
||||
String back = path.substring(partsLength * 3 / 4);
|
||||
int backSep = back.indexOf(File.separatorChar);
|
||||
if (backSep != -1) {
|
||||
back = back.substring(backSep);
|
||||
}
|
||||
return back + fill + front;
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new form CasePropertiesForm
|
||||
*/
|
||||
CasePropertiesForm(Case currentCase, String crDate, String caseDir, Map<Long, String> imgPaths) throws CaseMetadata.CaseMetadataException {
|
||||
CasePropertiesPanel(Case currentCase, String crDate, String caseDir, Map<Long, String> imgPaths) throws CaseMetadata.CaseMetadataException {
|
||||
initComponents();
|
||||
caseNameTextField.setText(currentCase.getName());
|
||||
caseNameTextField.setText(currentCase.getDisplayName());
|
||||
String caseNumber = currentCase.getNumber();
|
||||
if (!caseNumber.equals("")) {
|
||||
if (!caseNumber.isEmpty()) {
|
||||
caseNumberField.setText(caseNumber);
|
||||
} else {
|
||||
caseNumberField.setText("N/A");
|
||||
}
|
||||
String examiner = currentCase.getExaminer();
|
||||
if (!examiner.equals("")) {
|
||||
if (!examiner.isEmpty()) {
|
||||
examinerField.setText(examiner);
|
||||
} else {
|
||||
examinerField.setText("N/A");
|
||||
@ -96,7 +62,7 @@ class CasePropertiesForm extends javax.swing.JPanel {
|
||||
|
||||
CaseMetadata caseMetadata = currentCase.getCaseMetadata();
|
||||
if (caseMetadata.getCaseType() == Case.CaseType.SINGLE_USER_CASE) {
|
||||
dbNameField.setText(caseMetadata.getCaseDatabasePath());
|
||||
dbNameField.setText(Paths.get(caseMetadata.getCaseDirectory(), caseMetadata.getCaseDatabaseName()).toString());
|
||||
} else {
|
||||
dbNameField.setText(caseMetadata.getCaseDatabaseName());
|
||||
}
|
||||
@ -152,24 +118,19 @@ class CasePropertiesForm extends javax.swing.JPanel {
|
||||
jScrollPane1.setViewportView(jTextArea1);
|
||||
|
||||
caseNameLabel.setFont(caseNameLabel.getFont().deriveFont(caseNameLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
caseNameLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNameLabel.text")); // NOI18N
|
||||
caseNameLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesPanel.class, "CasePropertiesPanel.caseNameLabel.text")); // NOI18N
|
||||
|
||||
crDateLabel.setFont(crDateLabel.getFont().deriveFont(crDateLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
crDateLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.crDateLabel.text")); // NOI18N
|
||||
crDateLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesPanel.class, "CasePropertiesPanel.crDateLabel.text")); // NOI18N
|
||||
|
||||
caseDirLabel.setFont(caseDirLabel.getFont().deriveFont(caseDirLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
caseDirLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseDirLabel.text")); // NOI18N
|
||||
caseDirLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesPanel.class, "CasePropertiesPanel.caseDirLabel.text")); // NOI18N
|
||||
|
||||
caseNameTextField.setFont(caseNameTextField.getFont().deriveFont(caseNameTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
caseNameTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNameTextField.text")); // NOI18N
|
||||
caseNameTextField.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
caseNameTextFieldActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
caseNameTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesPanel.class, "CasePropertiesPanel.caseNameTextField.text")); // NOI18N
|
||||
|
||||
updateCaseNameButton.setFont(updateCaseNameButton.getFont().deriveFont(updateCaseNameButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
updateCaseNameButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.updateCaseNameButton.text")); // NOI18N
|
||||
updateCaseNameButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesPanel.class, "CasePropertiesPanel.updateCaseNameButton.text")); // NOI18N
|
||||
updateCaseNameButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
updateCaseNameButtonActionPerformed(evt);
|
||||
@ -177,7 +138,7 @@ class CasePropertiesForm extends javax.swing.JPanel {
|
||||
});
|
||||
|
||||
deleteCaseButton.setFont(deleteCaseButton.getFont().deriveFont(deleteCaseButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
deleteCaseButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.deleteCaseButton.text")); // NOI18N
|
||||
deleteCaseButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesPanel.class, "CasePropertiesPanel.deleteCaseButton.text")); // NOI18N
|
||||
deleteCaseButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
deleteCaseButtonActionPerformed(evt);
|
||||
@ -185,16 +146,16 @@ class CasePropertiesForm extends javax.swing.JPanel {
|
||||
});
|
||||
|
||||
caseNumberLabel.setFont(caseNumberLabel.getFont().deriveFont(caseNumberLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
caseNumberLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNumberLabel.text")); // NOI18N
|
||||
caseNumberLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesPanel.class, "CasePropertiesPanel.caseNumberLabel.text")); // NOI18N
|
||||
|
||||
examinerLabel.setFont(examinerLabel.getFont().deriveFont(examinerLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
examinerLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.examinerLabel.text")); // NOI18N
|
||||
examinerLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesPanel.class, "CasePropertiesPanel.examinerLabel.text")); // NOI18N
|
||||
|
||||
lbDbType.setFont(lbDbType.getFont().deriveFont(lbDbType.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
lbDbType.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.lbDbType.text")); // NOI18N
|
||||
lbDbType.setText(org.openide.util.NbBundle.getMessage(CasePropertiesPanel.class, "CasePropertiesPanel.lbDbType.text")); // NOI18N
|
||||
|
||||
lbDbName.setFont(lbDbName.getFont().deriveFont(lbDbName.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
lbDbName.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.lbDbName.text")); // NOI18N
|
||||
lbDbName.setText(org.openide.util.NbBundle.getMessage(CasePropertiesPanel.class, "CasePropertiesPanel.lbDbName.text")); // NOI18N
|
||||
|
||||
caseDirField.setMinimumSize(new java.awt.Dimension(25, 14));
|
||||
|
||||
@ -303,13 +264,13 @@ class CasePropertiesForm extends javax.swing.JPanel {
|
||||
* @param evt The action event
|
||||
*/
|
||||
private void updateCaseNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateCaseNameButtonActionPerformed
|
||||
String oldCaseName = Case.getCurrentCase().getName();
|
||||
String oldCaseName = Case.getCurrentCase().getDisplayName();
|
||||
String newCaseName = caseNameTextField.getText();
|
||||
// check if the old and new case name is not equal
|
||||
if (!oldCaseName.equals(newCaseName)) {
|
||||
|
||||
// check if the case name is empty
|
||||
if (newCaseName.trim().equals("")) {
|
||||
if (newCaseName.trim().isEmpty()) {
|
||||
JOptionPane.showMessageDialog(caller,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"CasePropertiesForm.updateCaseName.msgDlg.empty.msg"),
|
||||
@ -318,6 +279,7 @@ class CasePropertiesForm extends javax.swing.JPanel {
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else // check if case Name contain one of this following symbol:
|
||||
// \ / : * ? " < > |
|
||||
{
|
||||
if (newCaseName.contains("\\") || newCaseName.contains("/") || newCaseName.contains(":")
|
||||
|| newCaseName.contains("*") || newCaseName.contains("?") || newCaseName.contains("\"")
|
||||
|| newCaseName.contains("<") || newCaseName.contains(">") || newCaseName.contains("|")) {
|
||||
@ -344,8 +306,9 @@ class CasePropertiesForm extends javax.swing.JPanel {
|
||||
String oldPath = current.getCaseMetadata().getFilePath().toString();
|
||||
try {
|
||||
current.updateCaseName(oldCaseName, oldPath, newCaseName, oldPath);
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(CasePropertiesForm.class.getName()).log(Level.WARNING, "Error: problem updating case name.", ex); //NON-NLS
|
||||
} catch (CaseActionException ex) {
|
||||
Logger.getLogger(CasePropertiesPanel.class.getName()).log(Level.WARNING, "Error: problem updating case name.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -356,10 +319,6 @@ class CasePropertiesForm extends javax.swing.JPanel {
|
||||
CallableSystemAction.get(CaseDeleteAction.class).actionPerformed(evt);
|
||||
}//GEN-LAST:event_deleteCaseButtonActionPerformed
|
||||
|
||||
private void caseNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_caseNameTextFieldActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_caseNameTextFieldActionPerformed
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JLabel caseDirField;
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -77,8 +77,13 @@ final class CollaborationMonitor {
|
||||
* collaborating nodes, informs the user of collaboration tasks on other
|
||||
* nodes using progress bars, and monitors the health of key collaboration
|
||||
* services.
|
||||
*
|
||||
* @param eventChannelPrefix The prefix for the remote events channel.
|
||||
*
|
||||
* @throws
|
||||
* org.sleuthkit.autopsy.casemodule.CollaborationMonitor.CollaborationMonitorException
|
||||
*/
|
||||
CollaborationMonitor() throws CollaborationMonitorException {
|
||||
CollaborationMonitor(String eventChannelPrefix) throws CollaborationMonitorException {
|
||||
/**
|
||||
* Get the local host name so it can be used to identify the source of
|
||||
* collaboration tasks broadcast by this node.
|
||||
@ -91,9 +96,7 @@ final class CollaborationMonitor {
|
||||
*/
|
||||
eventPublisher = new AutopsyEventPublisher();
|
||||
try {
|
||||
Case openedCase = Case.getCurrentCase();
|
||||
String channelPrefix = openedCase.getTextIndexName();
|
||||
eventPublisher.openRemoteEventChannel(String.format(EVENT_CHANNEL_NAME, channelPrefix));
|
||||
eventPublisher.openRemoteEventChannel(String.format(EVENT_CHANNEL_NAME, eventChannelPrefix));
|
||||
} catch (AutopsyEventException ex) {
|
||||
throw new CollaborationMonitorException("Failed to initialize", ex);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,34 +18,41 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.KeyStroke;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.windows.WindowManager;
|
||||
|
||||
/**
|
||||
*
|
||||
/*
|
||||
* The panel in the default Autopsy startup window.
|
||||
*/
|
||||
public class CueBannerPanel extends javax.swing.JPanel {
|
||||
|
||||
final private static String title = NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.title.text");
|
||||
final private static JFrame frame = new JFrame(title);
|
||||
final static JDialog recentCasesWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
|
||||
private static final long serialVersionUID = 1L;
|
||||
/*
|
||||
* This is field is static for the sake of the closeOpenRecentCasesWindow
|
||||
* method.
|
||||
*/
|
||||
private static JDialog recentCasesWindow;
|
||||
|
||||
// for error handling
|
||||
private static JPanel caller = new JPanel();
|
||||
public static void closeOpenRecentCasesWindow() {
|
||||
if (null != recentCasesWindow) {
|
||||
recentCasesWindow.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
public CueBannerPanel() {
|
||||
initComponents();
|
||||
refresh();
|
||||
customizeComponents();
|
||||
enableComponents();
|
||||
}
|
||||
|
||||
public CueBannerPanel(String welcomeLogo) {
|
||||
@ -55,7 +62,53 @@ public class CueBannerPanel extends javax.swing.JPanel {
|
||||
ImageIcon icon = new ImageIcon(cl.getResource(welcomeLogo));
|
||||
autopsyLogo.setIcon(icon);
|
||||
}
|
||||
refresh();
|
||||
customizeComponents();
|
||||
enableComponents();
|
||||
}
|
||||
|
||||
public void setCloseButtonActionListener(ActionListener e) {
|
||||
closeButton.addActionListener(e);
|
||||
}
|
||||
|
||||
public void setCloseButtonText(String text) {
|
||||
closeButton.setText(text);
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
enableComponents();
|
||||
}
|
||||
|
||||
private void customizeComponents() {
|
||||
recentCasesWindow = new JDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.title.text"),
|
||||
Dialog.ModalityType.APPLICATION_MODAL);
|
||||
recentCasesWindow.setSize(new Dimension(750, 400));
|
||||
recentCasesWindow.getRootPane().registerKeyboardAction(
|
||||
e -> {
|
||||
recentCasesWindow.setVisible(false);
|
||||
},
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
OpenRecentCasePanel recentCasesPanel = OpenRecentCasePanel.getInstance();
|
||||
recentCasesPanel.setCloseButtonActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
recentCasesWindow.setVisible(false);
|
||||
}
|
||||
});
|
||||
recentCasesWindow.add(recentCasesPanel);
|
||||
recentCasesWindow.pack();
|
||||
recentCasesWindow.setResizable(false);
|
||||
}
|
||||
|
||||
private void enableComponents() {
|
||||
if (RecentCases.getInstance().getTotalRecentCases() == 0) {
|
||||
openRecentButton.setEnabled(false);
|
||||
openRecentLabel.setEnabled(false);
|
||||
} else {
|
||||
openRecentButton.setEnabled(true);
|
||||
openRecentLabel.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,15 +233,6 @@ public class CueBannerPanel extends javax.swing.JPanel {
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
public void refresh() {
|
||||
if (RecentCases.getInstance().getTotalRecentCases() == 0) {
|
||||
openRecentButton.setEnabled(false);
|
||||
openRecentLabel.setEnabled(false);
|
||||
} else {
|
||||
openRecentButton.setEnabled(true);
|
||||
openRecentLabel.setEnabled(true);
|
||||
}
|
||||
}
|
||||
private void newCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newCaseButtonActionPerformed
|
||||
Lookup.getDefault().lookup(CaseNewActionInterface.class).actionPerformed(evt);
|
||||
}//GEN-LAST:event_newCaseButtonActionPerformed
|
||||
@ -198,37 +242,8 @@ public class CueBannerPanel extends javax.swing.JPanel {
|
||||
}//GEN-LAST:event_openCaseButtonActionPerformed
|
||||
|
||||
private void openRecentButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openRecentButtonActionPerformed
|
||||
|
||||
// open the recent cases dialog
|
||||
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
|
||||
// set the popUp window / JFrame
|
||||
recentCasesWindow.setSize(750, 400);
|
||||
|
||||
int w = recentCasesWindow.getSize().width;
|
||||
int h = recentCasesWindow.getSize().height;
|
||||
|
||||
// set the location of the popUp Window on the center of the screen
|
||||
recentCasesWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
||||
recentCasesWindow.setLocationRelativeTo(this);
|
||||
recentCasesWindow.getRootPane().registerKeyboardAction(e -> {
|
||||
recentCasesWindow.dispose();
|
||||
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
OpenRecentCasePanel welcomeWindow = OpenRecentCasePanel.getInstance();
|
||||
|
||||
// add the command to close the window to the button on the Volume Detail Panel
|
||||
welcomeWindow.setCloseButtonActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
recentCasesWindow.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
recentCasesWindow.add(welcomeWindow);
|
||||
recentCasesWindow.pack();
|
||||
recentCasesWindow.setResizable(false);
|
||||
recentCasesWindow.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||
recentCasesWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
||||
OpenRecentCasePanel.getInstance(); //refreshes the recent cases table
|
||||
recentCasesWindow.setVisible(true);
|
||||
}//GEN-LAST:event_openRecentButtonActionPerformed
|
||||
|
||||
@ -244,29 +259,4 @@ public class CueBannerPanel extends javax.swing.JPanel {
|
||||
private javax.swing.JLabel openRecentLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
* Sets the Close button action listener.
|
||||
*
|
||||
* @param e the action listener
|
||||
*/
|
||||
public void setCloseButtonActionListener(ActionListener e) {
|
||||
closeButton.addActionListener(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Close button label (default is "Close").
|
||||
*
|
||||
* @param text The new label for the button.
|
||||
*/
|
||||
public void setCloseButtonText(String text) {
|
||||
closeButton.setText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the open recent cases window.
|
||||
*/
|
||||
public static void closeOpenRecentCasesWindow() {
|
||||
//startupWindow.setVisible(false);
|
||||
recentCasesWindow.dispose();
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgress
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.DataSourceUtils;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.AutoIngestDataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
|
||||
|
||||
/**
|
||||
* A image file data source processor that implements the DataSourceProcessor
|
||||
|
@ -30,7 +30,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.DriveUtils;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.AutoIngestDataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
|
||||
|
||||
/**
|
||||
* A local drive data source processor that implements the DataSourceProcessor
|
||||
|
@ -29,7 +29,7 @@ import org.openide.util.lookup.ServiceProviders;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.AutoIngestDataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
|
||||
|
||||
/**
|
||||
* A local/logical files and/or directories data source processor that
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,31 +19,33 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dialog;
|
||||
import java.io.File;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.DialogDescriptor;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.util.actions.SystemAction;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import javax.swing.JOptionPane;
|
||||
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
|
||||
import org.openide.windows.WindowManager;
|
||||
import java.awt.Cursor;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
|
||||
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
|
||||
import org.sleuthkit.autopsy.coreutils.FileUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* An action that creates and runs the new case wizard.
|
||||
* The action associated with the Case/New Case menu item, t toolbar button, and
|
||||
* the button in the start up window that allows users to open cases action. It
|
||||
* runs first the New Case wizard, then the Add Data Source wizard.
|
||||
*
|
||||
* This action should only be invoked in the event dispatch thread (EDT).
|
||||
*/
|
||||
final class NewCaseWizardAction extends CallableSystemAction {
|
||||
|
||||
@ -53,39 +55,15 @@ final class NewCaseWizardAction extends CallableSystemAction {
|
||||
|
||||
@Override
|
||||
public void performAction() {
|
||||
/*
|
||||
* If ingest is running, do a dialog to warn the user and confirm the
|
||||
* intent to close the current case and leave the ingest process
|
||||
* incomplete.
|
||||
*/
|
||||
if (IngestManager.getInstance().isIngestRunning()) {
|
||||
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
|
||||
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning"),
|
||||
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning.title"),
|
||||
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
|
||||
descriptor.setValue(NotifyDescriptor.NO_OPTION);
|
||||
Object res = DialogDisplayer.getDefault().notify(descriptor);
|
||||
if (res != null && res == DialogDescriptor.YES_OPTION) {
|
||||
Case currentCase = null;
|
||||
try {
|
||||
currentCase = Case.getCurrentCase();
|
||||
currentCase.closeCase();
|
||||
} catch (IllegalStateException ignored) {
|
||||
/*
|
||||
* No current case.
|
||||
*/
|
||||
} catch (CaseActionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error closing case at %s while ingest was running", (null != currentCase ? currentCase.getCaseDirectory() : "?")), ex); //NON-NLS
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
|
||||
String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
|
||||
if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
|
||||
runNewCaseWizard();
|
||||
}
|
||||
}
|
||||
|
||||
private void runNewCaseWizard() {
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
final WizardDescriptor wizardDescriptor = new WizardDescriptor(getNewCaseWizardPanels());
|
||||
wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
|
||||
wizardDescriptor.setTitle(NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.newCase.windowTitle.text"));
|
||||
@ -101,7 +79,7 @@ final class NewCaseWizardAction extends CallableSystemAction {
|
||||
final String caseName = (String) wizardDescriptor.getProperty("caseName"); //NON-NLS
|
||||
String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS
|
||||
CaseType caseType = CaseType.values()[(int) wizardDescriptor.getProperty("caseType")]; //NON-NLS
|
||||
Case.create(createdDirectory, caseName, caseNumber, examiner, caseType);
|
||||
Case.createAsCurrentCase(createdDirectory, caseName, caseNumber, examiner, caseType);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -109,26 +87,29 @@ final class NewCaseWizardAction extends CallableSystemAction {
|
||||
protected void done() {
|
||||
try {
|
||||
get();
|
||||
/*
|
||||
* Run the Add Data Source wizard by invoking the Add
|
||||
* Data Source wizard.
|
||||
*/
|
||||
AddImageAction addImageAction = SystemAction.get(AddImageAction.class);
|
||||
addImageAction.actionPerformed(null);
|
||||
} catch (Exception ex) {
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error creating case %s", wizardDescriptor.getProperty("caseName")), ex); //NON-NLS
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
(ex instanceof ExecutionException ? ex.getCause().getMessage() : ex.getMessage()),
|
||||
NbBundle.getMessage(this.getClass(), "CaseCreateAction.msgDlg.cantCreateCase.msg"), //NON-NLS
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
StartupWindowProvider.getInstance().close(); // RC: Why close and open?
|
||||
if (!Case.isCaseOpen()) {
|
||||
StartupWindowProvider.getInstance().close();
|
||||
StartupWindowProvider.getInstance().open();
|
||||
}
|
||||
});
|
||||
doFailedCaseCleanup(wizardDescriptor);
|
||||
} finally {
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
} else {
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
new Thread(() -> {
|
||||
doFailedCaseCleanup(wizardDescriptor);
|
||||
}).start();
|
||||
@ -138,11 +119,8 @@ final class NewCaseWizardAction extends CallableSystemAction {
|
||||
private void doFailedCaseCleanup(WizardDescriptor wizardDescriptor) {
|
||||
String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS
|
||||
if (createdDirectory != null) {
|
||||
Case.deleteCaseDirectory(new File(createdDirectory));
|
||||
FileUtil.deleteDir(new File(createdDirectory));
|
||||
}
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,9 +23,6 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.openide.DialogDescriptor;
|
||||
@ -34,7 +31,10 @@ import org.openide.NotifyDescriptor;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.WizardValidationException;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
|
||||
import org.sleuthkit.autopsy.coreutils.FileUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
|
||||
/**
|
||||
@ -101,7 +101,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
// fireChangeEvent();
|
||||
// and uncomment the complicated stuff below.
|
||||
}
|
||||
private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
|
||||
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
|
||||
|
||||
/**
|
||||
* Adds a listener to changes of the panel's validity.
|
||||
@ -134,7 +134,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
protected final void fireChangeEvent() {
|
||||
Iterator<ChangeListener> it;
|
||||
synchronized (listeners) {
|
||||
it = new HashSet<ChangeListener>(listeners).iterator();
|
||||
it = new HashSet<>(listeners).iterator();
|
||||
}
|
||||
ChangeEvent ev = new ChangeEvent(this);
|
||||
while (it.hasNext()) {
|
||||
@ -167,15 +167,15 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
*/
|
||||
@Override
|
||||
public void readSettings(WizardDescriptor settings) {
|
||||
NewCaseVisualPanel1 component = getComponent();
|
||||
NewCaseVisualPanel1 panel = getComponent();
|
||||
try {
|
||||
String lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE);
|
||||
component.setCaseParentDir(lastBaseDirectory);
|
||||
component.readSettings();
|
||||
panel.setCaseParentDir(lastBaseDirectory);
|
||||
panel.readSettings();
|
||||
createdDirectory = (String) settings.getProperty("createdDirectory"); //NON-NLS
|
||||
if (createdDirectory != null && !createdDirectory.equals("")) {
|
||||
logger.log(Level.INFO, "Deleting a case dir in readSettings(): " + createdDirectory); //NON-NLS
|
||||
Case.deleteCaseDirectory(new File(createdDirectory));
|
||||
if (createdDirectory != null && !createdDirectory.isEmpty()) {
|
||||
logger.log(Level.INFO, "Deleting a case dir in readSettings(): {0}", createdDirectory); //NON-NLS
|
||||
FileUtil.deleteDir(new File(createdDirectory));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Could not read wizard settings in NewCaseWizardPanel1, ", e); //NON-NLS
|
||||
@ -242,7 +242,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
// if user says yes
|
||||
try {
|
||||
createDirectory(caseDirPath, getComponent().getCaseType());
|
||||
} catch (Exception ex) {
|
||||
} catch (WizardValidationException ex) {
|
||||
String errorMsg = NbBundle.getMessage(this.getClass(),
|
||||
"NewCaseWizardPanel1.validate.errMsg.cantCreateParDir.msg",
|
||||
caseParentDir);
|
||||
@ -259,7 +259,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
} else {
|
||||
try {
|
||||
createDirectory(caseDirPath, getComponent().getCaseType());
|
||||
} catch (Exception ex) {
|
||||
} catch (WizardValidationException ex) {
|
||||
String errorMsg = NbBundle
|
||||
.getMessage(this.getClass(), "NewCaseWizardPanel1.validate.errMsg.cantCreateDir");
|
||||
logger.log(Level.WARNING, errorMsg, ex);
|
||||
@ -298,7 +298,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
|
||||
// delete the folder if we already created the folder and the error shows up
|
||||
if (new File(caseDirPath).exists()) {
|
||||
Case.deleteCaseDirectory(new File(caseDirPath));
|
||||
FileUtil.deleteDir(new File(caseDirPath));
|
||||
}
|
||||
|
||||
String errorMsg = NbBundle.getMessage(this.getClass(),
|
||||
@ -316,7 +316,6 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
logger.log(Level.WARNING, "Startup window didn't close as expected.", ex); //NON-NLS
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -27,9 +27,8 @@ import javax.swing.JTable;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.openide.windows.WindowManager;
|
||||
import java.awt.Cursor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Panel used by the the open recent case option of the start window.
|
||||
@ -103,7 +102,7 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
}
|
||||
final String casePath = casePaths[imagesTable.getSelectedRow()];
|
||||
final String caseName = caseNames[imagesTable.getSelectedRow()];
|
||||
if (!casePath.equals("")) {
|
||||
if (!casePath.isEmpty()) {
|
||||
try {
|
||||
StartupWindowProvider.getInstance().close();
|
||||
CueBannerPanel.closeOpenRecentCasesWindow();
|
||||
@ -114,34 +113,26 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
/*
|
||||
* Open the case.
|
||||
*/
|
||||
if (caseName.equals("") || casePath.equals("") || (!new File(casePath).exists())) {
|
||||
if (caseName.isEmpty() || casePath.isEmpty() || (!new File(casePath).exists())) {
|
||||
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
||||
NbBundle.getMessage(this.getClass(), "RecentItems.openRecentCase.msgDlg.text", caseName),
|
||||
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
RecentCases.getInstance().removeRecentCase(caseName, casePath); // remove the recent case if it doesn't exist anymore
|
||||
if (Case.isCaseOpen() == false) {
|
||||
StartupWindowProvider.getInstance().open();
|
||||
}
|
||||
} else {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
});
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Case.open(casePath);
|
||||
Case.openAsCurrentCase(casePath);
|
||||
} catch (CaseActionException ex) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", casePath), ex); //NON-NLS
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
ex.getMessage(), // Should be user-friendly
|
||||
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
if (!Case.isCaseOpen()) {
|
||||
StartupWindowProvider.getInstance().open();
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
@ -160,7 +151,7 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
public int getRowCount() {
|
||||
int count = 0;
|
||||
for (String s : caseNames) {
|
||||
if (!s.equals("")) {
|
||||
if (!s.isEmpty()) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -30,13 +30,13 @@ import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.openide.filesystems.FileUtil;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.util.actions.Presenter;
|
||||
import org.openide.filesystems.FileUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
|
||||
/**
|
||||
* The action in this class is to clear the list of "Recent Cases". The
|
||||
@ -45,14 +45,13 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
*/
|
||||
final class RecentCases extends CallableSystemAction implements Presenter.Menu {
|
||||
|
||||
static final int LENGTH = 6;
|
||||
static final String NAME_PROP_KEY = "LBL_RecentCase_Name"; //NON-NLS
|
||||
static final String PATH_PROP_KEY = "LBL_RecentCase_Path"; //NON-NLS
|
||||
static final RecentCase BLANK_RECENTCASE = new RecentCase("", "");
|
||||
|
||||
private final static RecentCases INSTANCE = new RecentCases();
|
||||
|
||||
private Deque<RecentCase> recentCases; // newest case is last case
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final int LENGTH = 6;
|
||||
private static final String NAME_PROP_KEY = "LBL_RecentCase_Name"; //NON-NLS
|
||||
private static final String PATH_PROP_KEY = "LBL_RecentCase_Path"; //NON-NLS
|
||||
private static final RecentCase BLANK_RECENTCASE = new RecentCase("", "");
|
||||
private final static RecentCases instance = new RecentCases();
|
||||
private final Deque<RecentCase> recentCases; // newest case is last case
|
||||
|
||||
/**
|
||||
* Gets the instance of the RecentCases singleton.
|
||||
@ -61,8 +60,8 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
|
||||
* @return INSTANCE the RecentCases singleton
|
||||
*/
|
||||
static public RecentCases getInstance() {
|
||||
INSTANCE.refreshRecentCases();
|
||||
return INSTANCE;
|
||||
instance.refreshRecentCases();
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,7 +83,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
|
||||
}
|
||||
|
||||
// Load recentCases from properties
|
||||
recentCases = new LinkedList<RecentCase>();
|
||||
recentCases = new LinkedList<>();
|
||||
|
||||
for (int i = 0; i < LENGTH; i++) {
|
||||
final RecentCase rc = new RecentCase(getName(i), getPath(i));
|
||||
@ -175,7 +174,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
|
||||
* @return true if the case exists, false otherwise
|
||||
*/
|
||||
boolean exists() {
|
||||
return !(name.equals("") || path.equals("") || !new File(path).exists());
|
||||
return !(name.isEmpty() || path.isEmpty() || !new File(path).exists());
|
||||
}
|
||||
|
||||
// netbeans autogenerated hashCode
|
||||
@ -211,7 +210,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
|
||||
* exist.
|
||||
*/
|
||||
private void refreshRecentCases() {
|
||||
List<RecentCase> toDelete = new ArrayList<RecentCase>();
|
||||
List<RecentCase> toDelete = new ArrayList<>();
|
||||
for (RecentCase rc : recentCases) {
|
||||
if (!rc.exists()) {
|
||||
toDelete.add(rc);
|
||||
@ -256,14 +255,14 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
UpdateRecentCases.hasRecentCase = false;
|
||||
UpdateRecentCases.setHasRecentCase(false);
|
||||
|
||||
recentCases.clear();
|
||||
|
||||
try {
|
||||
// clear the properties file
|
||||
storeRecentCases();
|
||||
} catch (Exception ex) {
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(RecentCases.class.getName()).log(Level.WARNING, "Error: Could not clear the properties file.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
@ -297,7 +296,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
|
||||
|
||||
try {
|
||||
storeRecentCases();
|
||||
} catch (Exception ex) {
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(RecentCases.class.getName()).log(Level.WARNING, "Error: Could not update the properties file.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
@ -325,7 +324,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
|
||||
|
||||
try {
|
||||
storeRecentCases();
|
||||
} catch (Exception ex) {
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(RecentCases.class.getName()).log(Level.WARNING, "Error: Could not update the properties file.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
@ -357,7 +356,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
|
||||
// write the properties file
|
||||
try {
|
||||
storeRecentCases();
|
||||
} catch (Exception ex) {
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(RecentCases.class.getName()).log(Level.WARNING, "Error: Could not update the properties file.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
@ -375,7 +374,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
|
||||
int i = 0;
|
||||
String currentCaseName = null;
|
||||
try {
|
||||
currentCaseName = Case.getCurrentCase().getName();
|
||||
currentCaseName = Case.getCurrentCase().getDisplayName();
|
||||
} catch (IllegalStateException ex) {
|
||||
// in case there is no current case.
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,111 +18,61 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.windows.WindowManager;
|
||||
import java.awt.Cursor;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.DialogDescriptor;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
|
||||
/**
|
||||
* An action listener that opens a recent case.
|
||||
* An action listener for a specific case, associated with a Recent Cases menu
|
||||
* item for the case by a DynamicMenuContent content JMenuItem.
|
||||
*
|
||||
* This action should only be invoked in the event dispatch thread (EDT).
|
||||
*/
|
||||
class RecentItems implements ActionListener {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(RecentItems.class.getName());
|
||||
private final String caseName;
|
||||
private final String caseMetaDataFilePath;
|
||||
|
||||
/**
|
||||
* Constructs an action listener that opens a recent case.
|
||||
* Constructs an action listener for a specific case, associated with a
|
||||
* Recent Cases menu item for the case by a DynamicMenuContent content
|
||||
* JMenuItem.
|
||||
*
|
||||
* @param caseName The name of the case.
|
||||
* @param caseMetaDataFilePath The path to the case metadata file.
|
||||
*/
|
||||
public RecentItems(String caseName, String caseMetaDataFilePath) {
|
||||
this.caseName = caseName;
|
||||
RecentItems(String caseName, String caseMetaDataFilePath) {
|
||||
this.caseMetaDataFilePath = caseMetaDataFilePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the recent case.
|
||||
* Opens the case associated with the action.
|
||||
*
|
||||
* @param e the action event
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
/*
|
||||
* If ingest is running, do a dialog to warn the user and confirm the
|
||||
* intent to close the current case and leave the ingest process
|
||||
* incomplete.
|
||||
*/
|
||||
if (IngestManager.getInstance().isIngestRunning()) {
|
||||
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
|
||||
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning"),
|
||||
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning.title"),
|
||||
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
|
||||
descriptor.setValue(NotifyDescriptor.NO_OPTION);
|
||||
Object res = DialogDisplayer.getDefault().notify(descriptor);
|
||||
if (res != null && res == DialogDescriptor.YES_OPTION) {
|
||||
Case currentCase = null;
|
||||
try {
|
||||
currentCase = Case.getCurrentCase();
|
||||
currentCase.closeCase();
|
||||
} catch (IllegalStateException ignored) {
|
||||
/*
|
||||
* No current case.
|
||||
*/
|
||||
} catch (CaseActionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error closing case at %s while ingest was running", (null!= currentCase ? currentCase.getCaseDirectory() : "?")),ex); //NON-NLS
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the case.
|
||||
*/
|
||||
if (caseName.equals("") || caseMetaDataFilePath.equals("") || (!new File(caseMetaDataFilePath).exists())) {
|
||||
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
||||
NbBundle.getMessage(this.getClass(), "RecentItems.openRecentCase.msgDlg.text", caseName),
|
||||
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
RecentCases.getInstance().removeRecentCase(caseName, caseMetaDataFilePath);
|
||||
if (Case.isCaseOpen() == false) {
|
||||
EventQueue.invokeLater(() -> {
|
||||
StartupWindowProvider.getInstance().open();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
});
|
||||
String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
|
||||
String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
|
||||
if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Case.open(caseMetaDataFilePath);
|
||||
Case.openAsCurrentCase(caseMetaDataFilePath);
|
||||
} catch (CaseActionException ex) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetaDataFilePath), ex); //NON-NLS
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
ex.getMessage(), // Should be user-friendly
|
||||
ex.getMessage(),
|
||||
NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
if (!Case.isCaseOpen()) {
|
||||
StartupWindowProvider.getInstance().open();
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -34,19 +34,21 @@ import java.util.Date;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
|
||||
import static org.sleuthkit.autopsy.casemodule.Case.MODULE_FOLDER;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.core.UserPreferencesException;
|
||||
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Import a case from single-user to multi-user.
|
||||
*
|
||||
* DO NOT USE, NEEDS TO BE UPDATED
|
||||
*/
|
||||
public class SingleUserCaseConverter {
|
||||
|
||||
private static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS
|
||||
private static final String AUTOPSY_DB_FILE = "autopsy.db"; //NON-NLS
|
||||
private static final String DOTAUT = CaseMetadata.getFileExtension(); //NON-NLS
|
||||
private static final String TIMELINE_FOLDER = "Timeline"; //NON-NLS
|
||||
@ -176,7 +178,6 @@ public class SingleUserCaseConverter {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); //NON-NLS
|
||||
Date date = new Date();
|
||||
String dbName = Case.sanitizeCaseName(icd.getNewCaseName()) + "_" + dateFormat.format(date); //NON-NLS
|
||||
String solrName = dbName;
|
||||
icd.setPostgreSQLDbName(dbName);
|
||||
|
||||
// Copy items to new hostname folder structure
|
||||
@ -195,9 +196,10 @@ public class SingleUserCaseConverter {
|
||||
CaseMetadata newCaseMetadata = new CaseMetadata(icd.getCaseOutputFolder().toString(),
|
||||
CaseType.MULTI_USER_CASE,
|
||||
icd.getNewCaseName(),
|
||||
icd.getNewCaseName(),
|
||||
oldCaseMetadata.getCaseNumber(),
|
||||
oldCaseMetadata.getExaminer(),
|
||||
dbName, solrName);
|
||||
dbName);
|
||||
// Set created date. This calls writefile, no need to call it again
|
||||
newCaseMetadata.setCreatedDate(oldCaseMetadata.getCreatedDate());
|
||||
newCaseMetadata.setCreatedByVersion(oldCaseMetadata.getCreatedByVersion());
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,51 +18,43 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
|
||||
/**
|
||||
* This class enables capturing errors and batching them for reporting on a
|
||||
* no-more-than-x number of seconds basis. When created, you specify the minimum
|
||||
* time between user notifications. When the time between notifications has
|
||||
* expired, the next error encountered will cause a report to be shown to the
|
||||
* user.
|
||||
* Acts as a bridge between the Sleuthkit Java bindings classes and Autopsy by
|
||||
* implementing the SleuthkitCase$ErrorObserver interface. All errors are
|
||||
* written to the Autopsy logs. If a GUI is running, errors are also batched up
|
||||
* and reported periodically to the user via the notification area in the lower
|
||||
* right hand corner of the main application window.
|
||||
*/
|
||||
class IntervalErrorReportData {
|
||||
class SleuthkitErrorReporter implements SleuthkitCase.ErrorObserver {
|
||||
|
||||
private final Case currentCase;
|
||||
private static final Logger LOGGER = Logger.getLogger(SleuthkitErrorReporter.class.getName());
|
||||
private final int milliSecondsBetweenReports;
|
||||
private final String message;
|
||||
private long newProblems;
|
||||
private long totalProblems;
|
||||
private long lastReportedDate;
|
||||
private final int milliSecondsBetweenReports;
|
||||
private final String message;
|
||||
|
||||
/**
|
||||
* Create a new IntervalErrorReprotData instance and subscribe for TSK error
|
||||
* notifications for the current case.
|
||||
*
|
||||
* @param currentCase Case for which TSK errors should be tracked
|
||||
* and displayed.
|
||||
* @param secondsBetweenReports Minimum number of seconds between reports.
|
||||
* It will not warn more frequently than this.
|
||||
* @param message The message that will be shown when warning
|
||||
* the user
|
||||
* the user.
|
||||
*/
|
||||
IntervalErrorReportData(Case currentCase, int secondsBetweenReports, String message) {
|
||||
SleuthkitErrorReporter(int secondsBetweenReports, String message) {
|
||||
this.newProblems = 0;
|
||||
this.totalProblems = 0;
|
||||
this.lastReportedDate = 0; // arm the first warning by choosing zero
|
||||
this.milliSecondsBetweenReports = secondsBetweenReports * 1000; // convert to milliseconds
|
||||
this.message = message;
|
||||
this.currentCase = currentCase;
|
||||
this.currentCase.getSleuthkitCase().addErrorObserver(this.currentCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Un-subscribe from TSK error notifications for current case.
|
||||
*/
|
||||
void shutdown() {
|
||||
this.currentCase.getSleuthkitCase().removeErrorObserver(this.currentCase);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,18 +65,19 @@ class IntervalErrorReportData {
|
||||
* @param context The context in which the error occurred.
|
||||
* @param errorMessage A description of the error that occurred.
|
||||
*/
|
||||
void addProblems(String context, String errorMessage) {
|
||||
@Override
|
||||
public void receiveError(String context, String errorMessage) {
|
||||
LOGGER.log(Level.SEVERE, String.format("%s error in the SleuthKit layer: %s", context, errorMessage));
|
||||
this.newProblems += 1;
|
||||
this.totalProblems += newProblems;
|
||||
|
||||
long currentTimeStamp = System.currentTimeMillis();
|
||||
if ((currentTimeStamp - lastReportedDate) > milliSecondsBetweenReports) {
|
||||
this.lastReportedDate = currentTimeStamp;
|
||||
MessageNotifyUtil.Notify.error(message, context + ", " + errorMessage + " "
|
||||
+ this.newProblems + " "
|
||||
+ NbBundle.getMessage(IntervalErrorReportData.class, "IntervalErrorReport.NewIssues")
|
||||
+ NbBundle.getMessage(SleuthkitErrorReporter.class, "IntervalErrorReport.NewIssues")
|
||||
+ " " + this.totalProblems + " "
|
||||
+ NbBundle.getMessage(IntervalErrorReportData.class, "IntervalErrorReport.TotalIssues")
|
||||
+ NbBundle.getMessage(SleuthkitErrorReporter.class, "IntervalErrorReport.TotalIssues")
|
||||
+ ".");
|
||||
this.newProblems = 0;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,25 +19,22 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.openide.windows.WindowManager;
|
||||
|
||||
/**
|
||||
* The default implementation of the Autopsy startup window
|
||||
* The default implementation of the Autopsy startup window.
|
||||
*/
|
||||
@ServiceProvider(service = StartupWindowInterface.class)
|
||||
public final class StartupWindow extends JDialog implements StartupWindowInterface {
|
||||
|
||||
private static StartupWindow instance;
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String TITLE = NbBundle.getMessage(StartupWindow.class, "StartupWindow.title.text");
|
||||
private static Dimension DIMENSIONS = new Dimension(750, 400);
|
||||
private static final Dimension DIMENSIONS = new Dimension(750, 400);
|
||||
private static CueBannerPanel welcomeWindow;
|
||||
|
||||
public StartupWindow() {
|
||||
@ -45,37 +42,18 @@ public final class StartupWindow extends JDialog implements StartupWindowInterfa
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the startup window.
|
||||
*/
|
||||
private void init() {
|
||||
|
||||
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
|
||||
// set the popUp window / JFrame
|
||||
setSize(DIMENSIONS);
|
||||
int w = this.getSize().width;
|
||||
int h = this.getSize().height;
|
||||
|
||||
// set the location of the popUp Window on the center of the screen
|
||||
setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
||||
setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
||||
|
||||
welcomeWindow = new CueBannerPanel();
|
||||
|
||||
// add the command to close the window to the button on the Volume Detail Panel
|
||||
welcomeWindow.setCloseButtonActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
close();
|
||||
}
|
||||
});
|
||||
|
||||
add(welcomeWindow);
|
||||
pack();
|
||||
setResizable(false);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,9 +63,6 @@ public final class StartupWindow extends JDialog implements StartupWindowInterfa
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the startup window.
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
this.setVisible(false);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -30,15 +30,20 @@ import org.openide.util.actions.SystemAction;
|
||||
*/
|
||||
class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
|
||||
|
||||
int length;
|
||||
static boolean hasRecentCase = false;
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static int NUM_CASES_TO_DISPLAY;
|
||||
private static boolean hasRecentCase = false;
|
||||
|
||||
/**
|
||||
* the constructor
|
||||
*/
|
||||
UpdateRecentCases() {
|
||||
// display last 5 cases.
|
||||
length = RecentCases.LENGTH - 1;
|
||||
NUM_CASES_TO_DISPLAY = 5;
|
||||
}
|
||||
|
||||
static void setHasRecentCase(boolean value) {
|
||||
hasRecentCase = value;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -53,10 +58,10 @@ class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
|
||||
public JComponent[] getMenuPresenters() {
|
||||
String[] caseName = RecentCases.getInstance().getRecentCaseNames();
|
||||
String[] casePath = RecentCases.getInstance().getRecentCasePaths();
|
||||
JComponent[] comps = new JComponent[length + 2]; // + 2 for separator and clear menu
|
||||
JComponent[] comps = new JComponent[NUM_CASES_TO_DISPLAY + 2]; // + 2 for separator and clear menu
|
||||
|
||||
// if it has the recent menus, add them to the component list
|
||||
for (int i = 0; i < length; i++) {
|
||||
for (int i = 0; i < NUM_CASES_TO_DISPLAY; i++) {
|
||||
if ((!caseName[i].equals(""))) {
|
||||
JMenuItem menuItem = new JMenuItem(caseName[i]);
|
||||
menuItem.setActionCommand(caseName[i].toUpperCase());
|
||||
@ -68,11 +73,11 @@ class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
|
||||
|
||||
// if it has recent case, create clear menu
|
||||
if (hasRecentCase) {
|
||||
comps[length] = new JSeparator();
|
||||
comps[NUM_CASES_TO_DISPLAY] = new JSeparator();
|
||||
JMenuItem clearMenu = new JMenuItem(
|
||||
NbBundle.getMessage(UpdateRecentCases.class, "UpdateRecentCases.menuItem.clearRecentCases.text"));
|
||||
clearMenu.addActionListener(SystemAction.get(RecentCases.class));
|
||||
comps[length + 1] = clearMenu;
|
||||
comps[NUM_CASES_TO_DISPLAY + 1] = clearMenu;
|
||||
} // otherwise, just create a disabled empty menu
|
||||
else {
|
||||
comps = new JComponent[1];
|
||||
@ -85,17 +90,15 @@ class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates main menu presenters. This method is called only by the main menu
|
||||
* processing.
|
||||
* Updates the Recent Cases menu items.
|
||||
*
|
||||
* @param jcs the previously used menu items returned by previous call to
|
||||
* getMenuPresenters() or synchMenuPresenters()
|
||||
* @param menuItems A set of Recent Case menu items to be updated.
|
||||
*
|
||||
* @return menu a new set of items to show in menu. Can be either an updated
|
||||
* old set of instances or a completely new one.
|
||||
* @return A updated set of recent case menu items to show in the Recent
|
||||
* Cases menu.
|
||||
*/
|
||||
@Override
|
||||
public JComponent[] synchMenuPresenters(JComponent[] jcs) {
|
||||
public JComponent[] synchMenuPresenters(JComponent[] menuItems) {
|
||||
return getMenuPresenters();
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
* Copyright 2012 42six Solutions.
|
||||
* Contact: aebadirad <at> 42six <dot> com
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -31,7 +31,7 @@ import org.openide.util.Lookup;
|
||||
iconBase = "org/sleuthkit/autopsy/casemodule/services/tag-options-panel-icon.png",
|
||||
keywords = "#OptionsCategory_TagNames",
|
||||
keywordsCategory = "CustomTagNames",
|
||||
position = 8
|
||||
position = 10
|
||||
)
|
||||
public final class TagsOptionsPanelController extends OptionsPanelController {
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,129 +18,89 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.coordinationservice;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.apache.zookeeper.CreateMode;
|
||||
import org.apache.zookeeper.ZooDefs;
|
||||
import org.apache.curator.RetryPolicy;
|
||||
import org.apache.curator.retry.ExponentialBackoffRetry;
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.framework.CuratorFrameworkFactory;
|
||||
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
|
||||
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;
|
||||
import org.apache.curator.retry.ExponentialBackoffRetry;
|
||||
import org.apache.zookeeper.CreateMode;
|
||||
import org.apache.zookeeper.KeeperException;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import java.io.IOException;
|
||||
import org.apache.zookeeper.WatchedEvent;
|
||||
import org.apache.zookeeper.ZooKeeper;
|
||||
import org.apache.zookeeper.KeeperException.NoNodeException;
|
||||
import org.apache.zookeeper.WatchedEvent;
|
||||
import org.apache.zookeeper.ZooDefs;
|
||||
import org.apache.zookeeper.ZooKeeper;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
|
||||
/**
|
||||
* A centralized service for maintaining configuration information and providing
|
||||
* distributed synchronization using a shared hierarchical namespace of nodes.
|
||||
* A coordination service for maintaining configuration information and
|
||||
* providing distributed synchronization using a shared hierarchical namespace
|
||||
* of nodes.
|
||||
*
|
||||
* TODO (JIRA 2205): Simple refactoring for general use.
|
||||
*/
|
||||
public final class CoordinationService {
|
||||
|
||||
/**
|
||||
* Category nodes are the immediate children of the root node of a shared
|
||||
* hierarchical namespace managed by the coordination service.
|
||||
*/
|
||||
public enum CategoryNode { // RJCTODO: Move this to CoordinationServiceNamespace
|
||||
|
||||
CASES("cases"),
|
||||
MANIFESTS("manifests"),
|
||||
CONFIG("config"),
|
||||
RESOURCE("resource");
|
||||
|
||||
private final String displayName;
|
||||
|
||||
private CategoryNode(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception type thrown by the coordination service.
|
||||
*/
|
||||
public final static class CoordinationServiceException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private CoordinationServiceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
private CoordinationServiceException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An opaque encapsulation of a lock for use in distributed synchronization.
|
||||
* Instances are obtained by calling a get lock method and must be passed to
|
||||
* a release lock method.
|
||||
*/
|
||||
public static class Lock implements AutoCloseable {
|
||||
|
||||
/**
|
||||
* This implementation uses the Curator read/write lock. see
|
||||
* http://curator.apache.org/curator-recipes/shared-reentrant-read-write-lock.html
|
||||
*/
|
||||
private final InterProcessMutex interProcessLock;
|
||||
private final String nodePath;
|
||||
|
||||
private Lock(String nodePath, InterProcessMutex lock) {
|
||||
this.nodePath = nodePath;
|
||||
this.interProcessLock = lock;
|
||||
}
|
||||
|
||||
public String getNodePath() {
|
||||
return nodePath;
|
||||
}
|
||||
|
||||
public void release() throws CoordinationServiceException {
|
||||
try {
|
||||
this.interProcessLock.release();
|
||||
} catch (Exception ex) {
|
||||
throw new CoordinationServiceException(String.format("Failed to release the lock on %s", nodePath), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws CoordinationServiceException {
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
||||
private static CuratorFramework curator = null;
|
||||
private static final Map<String, CoordinationService> rootNodesToServices = new HashMap<>();
|
||||
private final Map<String, String> categoryNodeToPath = new HashMap<>();
|
||||
private static final int SESSION_TIMEOUT_MILLISECONDS = 300000;
|
||||
private static final int CONNECTION_TIMEOUT_MILLISECONDS = 300000;
|
||||
private static final int ZOOKEEPER_SESSION_TIMEOUT_MILLIS = 3000;
|
||||
private static final int ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS = 15000;
|
||||
private static final int PORT_OFFSET = 1000;
|
||||
private static final int PORT_OFFSET = 1000; // When run in Solr, ZooKeeper defaults to Solr port + 1000
|
||||
private final Map<String, String> categoryNodeToPath = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Gets an instance of the centralized coordination service for a specific
|
||||
* namespace.
|
||||
* Determines if ZooKeeper is accessible with the current settings. Closes
|
||||
* the connection prior to returning.
|
||||
*
|
||||
* @return true if a connection was achieved, false otherwise
|
||||
*
|
||||
* @throws InterruptedException
|
||||
* @throws IOException
|
||||
*/
|
||||
private static boolean isZooKeeperAccessible() throws InterruptedException, IOException {
|
||||
boolean result = false;
|
||||
Object workerThreadWaitNotifyLock = new Object();
|
||||
int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET;
|
||||
String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort;
|
||||
ZooKeeper zooKeeper = new ZooKeeper(connectString, ZOOKEEPER_SESSION_TIMEOUT_MILLIS,
|
||||
(WatchedEvent event) -> {
|
||||
synchronized (workerThreadWaitNotifyLock) {
|
||||
workerThreadWaitNotifyLock.notify();
|
||||
}
|
||||
});
|
||||
synchronized (workerThreadWaitNotifyLock) {
|
||||
workerThreadWaitNotifyLock.wait(ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS);
|
||||
}
|
||||
ZooKeeper.States state = zooKeeper.getState();
|
||||
if (state == ZooKeeper.States.CONNECTED || state == ZooKeeper.States.CONNECTEDREADONLY) {
|
||||
result = true;
|
||||
}
|
||||
zooKeeper.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a coordination service for a specific namespace.
|
||||
*
|
||||
* @param rootNode The name of the root node that defines the namespace.
|
||||
*
|
||||
* @return The service for the namespace defined by the root node name.
|
||||
* @return The coordination service.
|
||||
*
|
||||
* @throws CoordinationServiceException If an instaNce of the coordination
|
||||
* @throws CoordinationServiceException If an instance of the coordination
|
||||
* service cannot be created.
|
||||
*/
|
||||
public static synchronized CoordinationService getInstance(String rootNode) throws CoordinationServiceException {
|
||||
public static synchronized CoordinationService getServiceForNamespace(String rootNode) throws CoordinationServiceException {
|
||||
/*
|
||||
* Connect to ZooKeeper via Curator.
|
||||
*/
|
||||
if (null == curator) {
|
||||
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
|
||||
// When run in Solr, ZooKeeper defaults to Solr port + 1000
|
||||
int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET;
|
||||
String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort;
|
||||
curator = CuratorFrameworkFactory.newClient(connectString, SESSION_TIMEOUT_MILLISECONDS, CONNECTION_TIMEOUT_MILLISECONDS, retryPolicy);
|
||||
@ -157,7 +117,7 @@ public final class CoordinationService {
|
||||
CoordinationService service;
|
||||
try {
|
||||
service = new CoordinationService(rootNode);
|
||||
} catch (Exception ex) {
|
||||
} catch (IOException | InterruptedException | KeeperException | CoordinationServiceException ex) {
|
||||
curator = null;
|
||||
throw new CoordinationServiceException("Failed to create coordination service", ex);
|
||||
}
|
||||
@ -167,15 +127,18 @@ public final class CoordinationService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of the centralized coordination service for a
|
||||
* specific namespace.
|
||||
* Constructs an instance of the coordination service for a specific
|
||||
* namespace.
|
||||
*
|
||||
* @param rootNodeName The name of the root node that defines the namespace.
|
||||
*
|
||||
* @throws Exception (calls Curator methods that throw Exception instead of
|
||||
* more specific exceptions)
|
||||
*/
|
||||
private CoordinationService(String rootNodeName) throws Exception {
|
||||
private CoordinationService(String rootNodeName) throws InterruptedException, IOException, KeeperException, CoordinationServiceException {
|
||||
|
||||
if (false == isZooKeeperAccessible()) {
|
||||
throw new Exception("Unable to access ZooKeeper");
|
||||
throw new CoordinationServiceException("Unable to access ZooKeeper");
|
||||
}
|
||||
|
||||
String rootNode = rootNodeName;
|
||||
@ -191,6 +154,8 @@ public final class CoordinationService {
|
||||
if (ex.code() != KeeperException.Code.NODEEXISTS) {
|
||||
throw ex;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new CoordinationServiceException("Curator experienced an error", ex);
|
||||
}
|
||||
categoryNodeToPath.put(node.getDisplayName(), nodePath);
|
||||
}
|
||||
@ -201,6 +166,9 @@ public final class CoordinationService {
|
||||
* in the namespace managed by this coordination service. Blocks until the
|
||||
* lock is obtained or the time out expires.
|
||||
*
|
||||
* IMPORTANT: The lock needs to be released in the same thread in which it
|
||||
* is acquired.
|
||||
*
|
||||
* @param category The desired category in the namespace.
|
||||
* @param nodePath The node path to use as the basis for the lock.
|
||||
* @param timeOut Length of the time out.
|
||||
@ -236,6 +204,9 @@ public final class CoordinationService {
|
||||
* in the namespace managed by this coordination service. Returns
|
||||
* immediately if the lock can not be acquired.
|
||||
*
|
||||
* IMPORTANT: The lock needs to be released in the same thread in which it
|
||||
* is acquired.
|
||||
*
|
||||
* @param category The desired category in the namespace.
|
||||
* @param nodePath The node path to use as the basis for the lock.
|
||||
*
|
||||
@ -262,6 +233,9 @@ public final class CoordinationService {
|
||||
* the namespace managed by this coordination service. Blocks until the lock
|
||||
* is obtained or the time out expires.
|
||||
*
|
||||
* IMPORTANT: The lock needs to be released in the same thread in which it
|
||||
* is acquired.
|
||||
*
|
||||
* @param category The desired category in the namespace.
|
||||
* @param nodePath The node path to use as the basis for the lock.
|
||||
* @param timeOut Length of the time out.
|
||||
@ -297,6 +271,9 @@ public final class CoordinationService {
|
||||
* the namespace managed by this coordination service. Returns immediately
|
||||
* if the lock can not be acquired.
|
||||
*
|
||||
* IMPORTANT: The lock needs to be released in the same thread in which it
|
||||
* is acquired.
|
||||
*
|
||||
* @param category The desired category in the namespace.
|
||||
* @param nodePath The node path to use as the basis for the lock.
|
||||
*
|
||||
@ -385,35 +362,77 @@ public final class CoordinationService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if ZooKeeper is accessible with the current settings. Closes
|
||||
* the connection prior to returning.
|
||||
*
|
||||
* @return true if a connection was achieved, false otherwise
|
||||
* Exception type thrown by the coordination service.
|
||||
*/
|
||||
private static boolean isZooKeeperAccessible() {
|
||||
boolean result = false;
|
||||
Object workerThreadWaitNotifyLock = new Object();
|
||||
int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET;
|
||||
String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort;
|
||||
public final static class CoordinationServiceException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private CoordinationServiceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
private CoordinationServiceException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An opaque encapsulation of a lock for use in distributed synchronization.
|
||||
* Instances are obtained by calling a get lock method and must be passed to
|
||||
* a release lock method.
|
||||
*/
|
||||
public static class Lock implements AutoCloseable {
|
||||
|
||||
/**
|
||||
* This implementation uses the Curator read/write lock. see
|
||||
* http://curator.apache.org/curator-recipes/shared-reentrant-read-write-lock.html
|
||||
*/
|
||||
private final InterProcessMutex interProcessLock;
|
||||
private final String nodePath;
|
||||
|
||||
private Lock(String nodePath, InterProcessMutex lock) {
|
||||
this.nodePath = nodePath;
|
||||
this.interProcessLock = lock;
|
||||
}
|
||||
|
||||
public String getNodePath() {
|
||||
return nodePath;
|
||||
}
|
||||
|
||||
public void release() throws CoordinationServiceException {
|
||||
try {
|
||||
ZooKeeper zooKeeper = new ZooKeeper(connectString, ZOOKEEPER_SESSION_TIMEOUT_MILLIS,
|
||||
(WatchedEvent event) -> {
|
||||
this.interProcessLock.release();
|
||||
} catch (Exception ex) {
|
||||
throw new CoordinationServiceException(String.format("Failed to release the lock on %s", nodePath), ex);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (workerThreadWaitNotifyLock) {
|
||||
workerThreadWaitNotifyLock.notify();
|
||||
}
|
||||
});
|
||||
synchronized (workerThreadWaitNotifyLock) {
|
||||
workerThreadWaitNotifyLock.wait(ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS);
|
||||
}
|
||||
ZooKeeper.States state = zooKeeper.getState();
|
||||
if (state == ZooKeeper.States.CONNECTED || state == ZooKeeper.States.CONNECTEDREADONLY) {
|
||||
result = true;
|
||||
}
|
||||
zooKeeper.close();
|
||||
} catch (InterruptedException | IOException ignored) {
|
||||
}
|
||||
return result;
|
||||
@Override
|
||||
public void close() throws CoordinationServiceException {
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Category nodes are the immediate children of the root node of a shared
|
||||
* hierarchical namespace managed by a coordination service.
|
||||
*/
|
||||
public enum CategoryNode {
|
||||
|
||||
CASES("cases"),
|
||||
MANIFESTS("manifests"),
|
||||
CONFIG("config"),
|
||||
RESOURCE("resource");
|
||||
|
||||
private final String displayName;
|
||||
|
||||
private CategoryNode(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 Basis Technology Corp.
|
||||
* Copyright 2016-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,7 +19,7 @@
|
||||
package org.sleuthkit.autopsy.coordinationservice;
|
||||
|
||||
/**
|
||||
* Namespace elements for auto ingest coordination service nodes.
|
||||
* Root node for Autopsy coordination service namespace.
|
||||
*/
|
||||
public final class CoordinationServiceNamespace {
|
||||
private static final String ROOT = "autopsy";
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2015 Basis Technology Corp.
|
||||
* Copyright 2013-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -24,46 +24,70 @@ package org.sleuthkit.autopsy.core;
|
||||
*/
|
||||
public class RuntimeProperties {
|
||||
|
||||
private static boolean coreComponentsActive = true;
|
||||
private static boolean coreComponentsActiveSet = false;
|
||||
private static boolean runningWithGUI = true;
|
||||
private static boolean runningWithGUIFlagHasBeenSet = false;
|
||||
|
||||
/**
|
||||
* Sets or unsets a flag indicating whether or not the core Autopsy UI
|
||||
* components and user interactions with those components via menus, message
|
||||
* boxes, NetBeans progress handles, etc., are enabled.
|
||||
* <p>
|
||||
* This flag exists as a mechanism to allow use of Autopsy as a platform
|
||||
* with the core Autopsy user interface disabled, until such time as the
|
||||
* user interface is made separable and optional.
|
||||
* Sets or unsets a flag indicating whether or not the application is
|
||||
* running with a GUI. The flag can only be set once per application
|
||||
* innvocation.
|
||||
*
|
||||
* @param coreComponentsActive True or false.
|
||||
* @param runningWithGUI True or false.
|
||||
*
|
||||
* @throws RuntimePropertiesException if the flag has already been set.
|
||||
*/
|
||||
public synchronized static void setCoreComponentsActive(boolean coreComponentsActive) {
|
||||
if (!coreComponentsActiveSet) {
|
||||
RuntimeProperties.coreComponentsActive = coreComponentsActive;
|
||||
coreComponentsActiveSet = true;
|
||||
public synchronized static void setRunningWithGUI(boolean runningWithGUI) throws RuntimePropertiesException {
|
||||
if (!runningWithGUIFlagHasBeenSet) {
|
||||
RuntimeProperties.runningWithGUI = runningWithGUI;
|
||||
runningWithGUIFlagHasBeenSet = true;
|
||||
} else {
|
||||
throw new RuntimePropertiesException("The runningWithGUI flag has already been set and cannot be changed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a flag indicating whether or not the core Autopsy UI components and
|
||||
* user interactions with those components via menus, message boxes,
|
||||
* NetBeans progress handles, etc., are enabled.
|
||||
* <p>
|
||||
* This flag exists as a mechanism to allow use of Autopsy as a platform
|
||||
* with the core Autopsy user interface disabled, until such time as the
|
||||
* user interface is made separable and optional.
|
||||
* Gets a flag indicating whether or not the application is running with a
|
||||
* GUI.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
public synchronized static boolean coreComponentsAreActive() {
|
||||
return coreComponentsActive;
|
||||
public synchronized static boolean runningWithGUI() {
|
||||
return runningWithGUI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to prevent creation of instances of this class.
|
||||
*/
|
||||
private RuntimeProperties() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception to throw if there is an error setting a runtime property.
|
||||
*/
|
||||
public final static class RuntimePropertiesException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructor for an exception to throw if there is an error setting
|
||||
* a runtime property.
|
||||
*
|
||||
* @param message The exception message.
|
||||
*/
|
||||
public RuntimePropertiesException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for an exception to throw if there is an error setting
|
||||
* a runtime property.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param cause The cause of the error.
|
||||
*/
|
||||
public RuntimePropertiesException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -49,55 +49,6 @@
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="numberOfFileIngestThreadsComboBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="restartRequiredLabel" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabelTimeDisplay" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabelNumThreads" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabelSetProcessTimeOut" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="useLocalTimeRB" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="useGMTTimeRB" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jCheckBoxEnableProcTimeout" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jFormattedTextFieldProcTimeOutHrs" min="-2" pref="27" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jLabelProcessTimeOutUnits" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="213" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabelHideKnownFiles" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabelSelectFile" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="keepCurrentViewerRB" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="useBestViewerRB" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="dataSourcesHideKnownCB" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="viewsHideKnownCB" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="395" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabelHideSlackFiles" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
@ -111,6 +62,30 @@
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabelTimeDisplay" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="useLocalTimeRB" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="useGMTTimeRB" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="jLabelHideKnownFiles" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabelSelectFile" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="keepCurrentViewerRB" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="useBestViewerRB" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="dataSourcesHideKnownCB" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="viewsHideKnownCB" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -142,24 +117,7 @@
|
||||
<Component id="useLocalTimeRB" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="useGMTTimeRB" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="jLabelNumThreads" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="numberOfFileIngestThreadsComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="restartRequiredLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="jLabelSetProcessTimeOut" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jCheckBoxEnableProcTimeout" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
|
||||
<Component id="jFormattedTextFieldProcTimeOutHrs" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabelProcessTimeOutUnits" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace pref="49" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="148" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -264,73 +222,6 @@
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="viewsHideKnownCBActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabelNumThreads">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jLabelNumThreads.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="numberOfFileIngestThreadsComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="numberOfFileIngestThreadsComboBoxActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<Integer>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="restartRequiredLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/warning16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.restartRequiredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabelSetProcessTimeOut">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jLabelSetProcessTimeOut.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="jCheckBoxEnableProcTimeout">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jCheckBoxEnableProcTimeoutActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabelProcessTimeOutUnits">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JFormattedTextField" name="jFormattedTextFieldProcTimeOutHrs">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jFormattedTextFieldProcTimeOutHrs.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jFormattedTextFieldProcTimeOutHrsActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new JFormattedTextField(NumberFormat.getIntegerInstance());"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="dataSourcesHideSlackCB">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
|
@ -18,13 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.corecomponents;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
|
||||
/**
|
||||
@ -36,55 +30,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
|
||||
AutopsyOptionsPanel() {
|
||||
initComponents();
|
||||
|
||||
/*
|
||||
* Profiling has shown that contention for I/O resources and for the
|
||||
* case database limits the number of threads that can do meaningful
|
||||
* work during ingest. If Autopsy was compute-bound, adding more threads
|
||||
* on machines with enough processors might help, but currently, after
|
||||
* four threads, performance actually stays flat and then starts to
|
||||
* degrade.
|
||||
*/
|
||||
int availableProcessors = Runtime.getRuntime().availableProcessors();
|
||||
Integer fileIngestThreadCountChoices[];
|
||||
int recommendedFileIngestThreadCount;
|
||||
if (availableProcessors >= 6) {
|
||||
fileIngestThreadCountChoices = new Integer[]{1, 2, 4};
|
||||
recommendedFileIngestThreadCount = 4;
|
||||
} else if (availableProcessors >= 4 && availableProcessors < 6) {
|
||||
fileIngestThreadCountChoices = new Integer[]{1, 2, 4};
|
||||
recommendedFileIngestThreadCount = 2;
|
||||
} else if (availableProcessors >= 2 && availableProcessors < 4) {
|
||||
fileIngestThreadCountChoices = new Integer[]{1, 2};
|
||||
recommendedFileIngestThreadCount = 1;
|
||||
} else {
|
||||
fileIngestThreadCountChoices = new Integer[]{1};
|
||||
recommendedFileIngestThreadCount = 1;
|
||||
}
|
||||
numberOfFileIngestThreadsComboBox.setModel(new DefaultComboBoxModel<>(fileIngestThreadCountChoices));
|
||||
|
||||
restartRequiredLabel.setText(NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.restartRequiredLabel.text", recommendedFileIngestThreadCount));
|
||||
|
||||
// TODO listen to changes in form fields and call controller.changed()
|
||||
DocumentListener docListener = new DocumentListener() {
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}
|
||||
};
|
||||
this.jFormattedTextFieldProcTimeOutHrs.getDocument().addDocumentListener(docListener);
|
||||
|
||||
}
|
||||
|
||||
void load() {
|
||||
@ -98,20 +43,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
boolean useLocalTime = UserPreferences.displayTimesInLocalTime();
|
||||
useLocalTimeRB.setSelected(useLocalTime);
|
||||
useGMTTimeRB.setSelected(!useLocalTime);
|
||||
numberOfFileIngestThreadsComboBox.setSelectedItem(UserPreferences.numberOfFileIngestThreads());
|
||||
if (UserPreferences.getIsTimeOutEnabled()) {
|
||||
// user specified time out
|
||||
jCheckBoxEnableProcTimeout.setSelected(true);
|
||||
jFormattedTextFieldProcTimeOutHrs.setEditable(true);
|
||||
int timeOutHrs = UserPreferences.getProcessTimeOutHrs();
|
||||
jFormattedTextFieldProcTimeOutHrs.setValue((long) timeOutHrs);
|
||||
} else {
|
||||
// never time out
|
||||
jCheckBoxEnableProcTimeout.setSelected(false);
|
||||
jFormattedTextFieldProcTimeOutHrs.setEditable(false);
|
||||
int timeOutHrs = UserPreferences.getProcessTimeOutHrs();
|
||||
jFormattedTextFieldProcTimeOutHrs.setValue((long) timeOutHrs);
|
||||
}
|
||||
}
|
||||
|
||||
void store() {
|
||||
@ -121,14 +52,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
UserPreferences.setHideSlackFilesInDataSourcesTree(dataSourcesHideSlackCB.isSelected());
|
||||
UserPreferences.setHideSlackFilesInViewsTree(viewsHideSlackCB.isSelected());
|
||||
UserPreferences.setDisplayTimesInLocalTime(useLocalTimeRB.isSelected());
|
||||
UserPreferences.setNumberOfFileIngestThreads((Integer) numberOfFileIngestThreadsComboBox.getSelectedItem());
|
||||
|
||||
UserPreferences.setIsTimeOutEnabled(jCheckBoxEnableProcTimeout.isSelected());
|
||||
if (jCheckBoxEnableProcTimeout.isSelected()) {
|
||||
// only store time out if it is enabled
|
||||
long timeOutHrs = (long) jFormattedTextFieldProcTimeOutHrs.getValue();
|
||||
UserPreferences.setProcessTimeOutHrs((int) timeOutHrs);
|
||||
}
|
||||
}
|
||||
|
||||
boolean valid() {
|
||||
@ -156,13 +79,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
jLabelHideKnownFiles = new javax.swing.JLabel();
|
||||
dataSourcesHideKnownCB = new javax.swing.JCheckBox();
|
||||
viewsHideKnownCB = new javax.swing.JCheckBox();
|
||||
jLabelNumThreads = new javax.swing.JLabel();
|
||||
numberOfFileIngestThreadsComboBox = new javax.swing.JComboBox<>();
|
||||
restartRequiredLabel = new javax.swing.JLabel();
|
||||
jLabelSetProcessTimeOut = new javax.swing.JLabel();
|
||||
jCheckBoxEnableProcTimeout = new javax.swing.JCheckBox();
|
||||
jLabelProcessTimeOutUnits = new javax.swing.JLabel();
|
||||
jFormattedTextFieldProcTimeOutHrs = new JFormattedTextField(NumberFormat.getIntegerInstance());
|
||||
dataSourcesHideSlackCB = new javax.swing.JCheckBox();
|
||||
viewsHideSlackCB = new javax.swing.JCheckBox();
|
||||
jLabelHideSlackFiles = new javax.swing.JLabel();
|
||||
@ -223,35 +139,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabelNumThreads, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelNumThreads.text")); // NOI18N
|
||||
|
||||
numberOfFileIngestThreadsComboBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
numberOfFileIngestThreadsComboBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
restartRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/warning16.png"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(restartRequiredLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.restartRequiredLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabelSetProcessTimeOut, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelSetProcessTimeOut.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jCheckBoxEnableProcTimeout, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text")); // NOI18N
|
||||
jCheckBoxEnableProcTimeout.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
jCheckBoxEnableProcTimeoutActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabelProcessTimeOutUnits, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text")); // NOI18N
|
||||
|
||||
jFormattedTextFieldProcTimeOutHrs.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jFormattedTextFieldProcTimeOutHrs.text")); // NOI18N
|
||||
jFormattedTextFieldProcTimeOutHrs.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
jFormattedTextFieldProcTimeOutHrsActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(dataSourcesHideSlackCB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.dataSourcesHideSlackCB.text")); // NOI18N
|
||||
dataSourcesHideSlackCB.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
@ -276,30 +163,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(numberOfFileIngestThreadsComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(restartRequiredLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabelTimeDisplay)
|
||||
.addComponent(jLabelNumThreads)
|
||||
.addComponent(jLabelSetProcessTimeOut)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(useLocalTimeRB)
|
||||
.addComponent(useGMTTimeRB)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addComponent(jCheckBoxEnableProcTimeout)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jFormattedTextFieldProcTimeOutHrs, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabelProcessTimeOutUnits)))))
|
||||
.addGap(213, 213, 213)))
|
||||
.addContainerGap())
|
||||
.addComponent(useGMTTimeRB))))
|
||||
.addContainerGap(512, Short.MAX_VALUE))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabelHideKnownFiles)
|
||||
@ -349,21 +220,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
.addComponent(useLocalTimeRB)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(useGMTTimeRB)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(jLabelNumThreads)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(numberOfFileIngestThreadsComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(restartRequiredLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(jLabelSetProcessTimeOut)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jCheckBoxEnableProcTimeout)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(jFormattedTextFieldProcTimeOutHrs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jLabelProcessTimeOutUnits)))
|
||||
.addContainerGap(49, Short.MAX_VALUE))
|
||||
.addContainerGap(148, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
jScrollPane1.setViewportView(jPanel1);
|
||||
@ -380,11 +237,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void jCheckBoxEnableProcTimeoutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBoxEnableProcTimeoutActionPerformed
|
||||
jFormattedTextFieldProcTimeOutHrs.setEditable(jCheckBoxEnableProcTimeout.isSelected());
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}//GEN-LAST:event_jCheckBoxEnableProcTimeoutActionPerformed
|
||||
|
||||
private void useBestViewerRBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useBestViewerRBActionPerformed
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}//GEN-LAST:event_useBestViewerRBActionPerformed
|
||||
@ -409,14 +261,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}//GEN-LAST:event_useGMTTimeRBActionPerformed
|
||||
|
||||
private void numberOfFileIngestThreadsComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_numberOfFileIngestThreadsComboBoxActionPerformed
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}//GEN-LAST:event_numberOfFileIngestThreadsComboBoxActionPerformed
|
||||
|
||||
private void jFormattedTextFieldProcTimeOutHrsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jFormattedTextFieldProcTimeOutHrsActionPerformed
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}//GEN-LAST:event_jFormattedTextFieldProcTimeOutHrsActionPerformed
|
||||
|
||||
private void dataSourcesHideSlackCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataSourcesHideSlackCBActionPerformed
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}//GEN-LAST:event_dataSourcesHideSlackCBActionPerformed
|
||||
@ -430,20 +274,13 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
private javax.swing.ButtonGroup buttonGroup3;
|
||||
private javax.swing.JCheckBox dataSourcesHideKnownCB;
|
||||
private javax.swing.JCheckBox dataSourcesHideSlackCB;
|
||||
private javax.swing.JCheckBox jCheckBoxEnableProcTimeout;
|
||||
private javax.swing.JFormattedTextField jFormattedTextFieldProcTimeOutHrs;
|
||||
private javax.swing.JLabel jLabelHideKnownFiles;
|
||||
private javax.swing.JLabel jLabelHideSlackFiles;
|
||||
private javax.swing.JLabel jLabelNumThreads;
|
||||
private javax.swing.JLabel jLabelProcessTimeOutUnits;
|
||||
private javax.swing.JLabel jLabelSelectFile;
|
||||
private javax.swing.JLabel jLabelSetProcessTimeOut;
|
||||
private javax.swing.JLabel jLabelTimeDisplay;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JRadioButton keepCurrentViewerRB;
|
||||
private javax.swing.JComboBox<Integer> numberOfFileIngestThreadsComboBox;
|
||||
private javax.swing.JLabel restartRequiredLabel;
|
||||
private javax.swing.JRadioButton useBestViewerRB;
|
||||
private javax.swing.JRadioButton useGMTTimeRB;
|
||||
private javax.swing.JRadioButton useLocalTimeRB;
|
||||
|
@ -1,7 +1,7 @@
|
||||
CTL_DataContentAction=DataContent
|
||||
CTL_DataContentTopComponent=Data Content
|
||||
CTL_CustomAboutAction=About
|
||||
OptionsCategory_Name_General=Autopsy
|
||||
OptionsCategory_Name_General=View
|
||||
OptionsCategory_Keywords_General=Autopsy Options
|
||||
HINT_DataContentTopComponent=This is a DataContent window
|
||||
HINT_NodeTableTopComponent=This is a DataResult window
|
||||
@ -139,11 +139,9 @@ AutopsyOptionsPanel.useGMTTimeRB.text=Use GMT
|
||||
AutopsyOptionsPanel.useLocalTimeRB.text=Use local time zone
|
||||
AutopsyOptionsPanel.keepCurrentViewerRB.toolTipText=For example, stay in Hex view when a JPEG is selected.
|
||||
AutopsyOptionsPanel.keepCurrentViewerRB.text=Stay on the same file viewer
|
||||
AutopsyOptionsPanel.restartRequiredLabel.text=For this computer, a maximum of {0} file ingest threads should be used. Application restart required to take effect.
|
||||
AutopsyOptionsPanel.jLabelSelectFile.text=When selecting a file:
|
||||
AutopsyOptionsPanel.jLabelHideKnownFiles.text=Hide known files (i.e. those in the NIST NSRL) in the:
|
||||
AutopsyOptionsPanel.jLabelTimeDisplay.text=When displaying times:
|
||||
AutopsyOptionsPanel.jLabelNumThreads.text=Number of threads to use for file ingest:
|
||||
FXVideoPanel.progress.bufferingCancelled=media buffering was canceled
|
||||
FXVideoPanel.progress.bufferingInterrupted=media buffering was interrupted
|
||||
FXVideoPanel.progress.errorWritingVideoToDisk=Error writing video to disk
|
||||
@ -158,10 +156,6 @@ MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database por
|
||||
MultiUserSettingsPanel.validationErrMsg.invalidMessageServicePort=Invalid message service port number
|
||||
MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort=Invalid Solr server port number
|
||||
MultiUserSettingsPanel.validationErrMsg.invalidMessgeServiceURI=Message service host and/or port not valid
|
||||
AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text=
|
||||
AutopsyOptionsPanel.jFormattedTextFieldProcTimeOutHrs.text=60
|
||||
AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text=hour(s)
|
||||
AutopsyOptionsPanel.jLabelSetProcessTimeOut.text=Enable timeout to allow modules to automatically terminate after a set amount of time\:
|
||||
DataContentViewerHex.goToOffsetLabel.text=Jump to Offset
|
||||
DataContentViewerHex.goToOffsetTextField.text=
|
||||
DataContentViewerHex.goToOffsetTextField.msgDlg=Invalid Offset\: {0}
|
||||
|
@ -1,5 +1,4 @@
|
||||
CTL_DataContentAction=\u30c7\u30fc\u30bf\u30b3\u30f3\u30c6\u30f3\u30c4
|
||||
OptionsCategory_Name_General=Autopsy
|
||||
OptionsCategory_Keywords_General=Autopsy\u30aa\u30d7\u30b7\u30e7\u30f3
|
||||
CTL_CustomAboutAction=Autopsy\u306b\u3064\u3044\u3066
|
||||
CTL_DataContentTopComponent=\u30c7\u30fc\u30bf\u30b3\u30f3\u30c6\u30f3\u30c4
|
||||
@ -116,11 +115,9 @@ AutopsyOptionsPanel.useGMTTimeRB.text=GMT\u3092\u4f7f\u7528
|
||||
AutopsyOptionsPanel.useLocalTimeRB.text=\u30ed\u30fc\u30ab\u30eb\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\u3092\u4f7f\u7528
|
||||
AutopsyOptionsPanel.keepCurrentViewerRB.toolTipText=\u4f8b\u3048\u3070\u3001JPEG\u304c\u9078\u629e\u3055\u308c\u305f\u5834\u5408\u306b\u305d\u306e\u307e\u307eHEX\u30d3\u30e5\u30fc\u3092\u4f7f\u7528\u3002
|
||||
AutopsyOptionsPanel.keepCurrentViewerRB.text=\u305d\u306e\u307e\u307e\u540c\u3058\u30d5\u30a1\u30a4\u30eb\u30d3\u30e5\u30fc\u30a2\u3092\u4f7f\u7528
|
||||
AutopsyOptionsPanel.restartRequiredLabel.text=\u3053\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u30fc\u3067\u306f\u6700\u5927{0}\u306e\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b9\u30ec\u30c3\u30c9\u3092\u4f7f\u7528\u3059\u3079\u304d\u3067\u3059\u3002\u6709\u52b9\u306b\u3059\u308b\u306b\u306f\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u3067\u3059\u3002
|
||||
AutopsyOptionsPanel.jLabelSelectFile.text=\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3059\u308b\u5834\u5408\uff1a
|
||||
AutopsyOptionsPanel.jLabelHideKnownFiles.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb\uff08NIST NSRL\u5185\u306e\uff09\u3092\u6b21\u306b\u96a0\u3059\uff1a
|
||||
AutopsyOptionsPanel.jLabelTimeDisplay.text=\u6642\u9593\u3092\u8868\u793a\u3059\u308b\u5834\u5408\uff1a
|
||||
AutopsyOptionsPanel.jLabelNumThreads.text=\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306b\u4f7f\u7528\u3059\u308b\u30b9\u30ec\u30c3\u30c9\u6570\uff1a
|
||||
FXVideoPanel.progress.bufferingCancelled=\u30e1\u30c7\u30a3\u30a2\u306e\u30d0\u30c3\u30d5\u30a1\u30ea\u30f3\u30b0\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f
|
||||
FXVideoPanel.progress.bufferingInterrupted=\u30e1\u30c7\u30a3\u30a2\u306e\u30d0\u30c3\u30d5\u30a1\u30ea\u30f3\u30b0\u304c\u4e2d\u65ad\u3055\u308c\u307e\u3057\u305f
|
||||
FXVideoPanel.progress.errorWritingVideoToDisk=\u30d3\u30c7\u30aa\u3092\u30c7\u30a3\u30b9\u30af\u3078\u66f8\u304d\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
|
||||
@ -135,8 +132,6 @@ MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort=\u7121\u52b9\u306a\u
|
||||
MultiUserSettingsPanel.validationErrMsg.invalidMessageServicePort=\u7121\u52b9\u306a\u30e1\u30c3\u30bb\u30fc\u30b8\u30b5\u30fc\u30d3\u30b9\u30dd\u30fc\u30c8\u756a\u53f7
|
||||
MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort=\u7121\u52b9\u306aSolr\u30b5\u30fc\u30d0\u30fc\u30dd\u30fc\u30c8\u756a\u53f7
|
||||
MultiUserSettingsPanel.validationErrMsg.invalidMessgeServiceURI=\u7121\u52b9\u306a\u30e1\u30c3\u30bb\u30fc\u30b8\u30b5\u30fc\u30d3\u30b9\u30db\u30b9\u30c8\u3084\u30dd\u30fc\u30c8\u756a\u53f7
|
||||
AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text=\u6642\u9593
|
||||
AutopsyOptionsPanel.jLabelSetProcessTimeOut.text=\u4e00\u5b9a\u306e\u6642\u9593\u304c\u904e\u304e\u305f\u5f8c\u306b\u81ea\u52d5\u7684\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u505c\u6b62\u3067\u304d\u308b\u3088\u3046\u306b\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u3092\u6709\u52b9\u5316\uff1a
|
||||
DataContentViewerHex.goToOffsetLabel.text=\u30aa\u30d5\u30bb\u30c3\u30c8\u306b\u30b8\u30e3\u30f3\u30d7
|
||||
DataContentViewerHex.goToOffsetTextField.msgDlg=\u7121\u52b9\u306a\u30aa\u30d5\u30bb\u30c3\u30c8\uff1a{0}
|
||||
DataContentViewerHex.setDataView.invalidOffset.negativeOffsetValue=\u8a08\u7b97\u3055\u308c\u305f\u30aa\u30d5\u30bb\u30c3\u30c8\u306b\u30b8\u30e3\u30f3\u30d7\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -22,7 +22,6 @@ import java.beans.PropertyChangeEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import javax.swing.JTabbedPane;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
@ -30,6 +29,7 @@ import org.openide.windows.TopComponent;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Top component that organizes all of the data content viewers. Doing a lookup
|
||||
@ -42,17 +42,18 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent;
|
||||
//@TopComponent.OpenActionRegistration(displayName = "#CTL_DataContentAction", preferredID = "DataContentTopComponent")
|
||||
public final class DataContentTopComponent extends TopComponent implements DataContent {
|
||||
|
||||
private static Logger logger = Logger.getLogger(DataContentTopComponent.class.getName());
|
||||
private static final Logger logger = Logger.getLogger(DataContentTopComponent.class.getName());
|
||||
|
||||
// reference to the "default" TC that always stays open
|
||||
private static DataContentTopComponent defaultInstance;
|
||||
private static final long serialVersionUID = 1L;
|
||||
// set to true if this is the TC that always stays open and is the default place to display content
|
||||
private boolean isDefault;
|
||||
private final boolean isDefault;
|
||||
// the content panel holding tabs with content viewers
|
||||
private final DataContentPanel dataContentPanel;
|
||||
|
||||
// contains a list of the undocked TCs
|
||||
private static ArrayList<DataContentTopComponent> newWindowList = new ArrayList<DataContentTopComponent>();
|
||||
private static final ArrayList<DataContentTopComponent> newWindowList = new ArrayList<>();
|
||||
private static final String PREFERRED_ID = "DataContentTopComponent"; //NON-NLS
|
||||
private static final String DEFAULT_NAME = NbBundle.getMessage(DataContentTopComponent.class, "CTL_DataContentTopComponent");
|
||||
private static final String TOOLTIP_TEXT = NbBundle.getMessage(DataContentTopComponent.class, "HINT_DataContentTopComponent");
|
||||
@ -67,8 +68,8 @@ public final class DataContentTopComponent extends TopComponent implements DataC
|
||||
dataContentPanel = new DataContentPanel(isDefault);
|
||||
add(dataContentPanel);
|
||||
|
||||
putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.valueOf(isDefault)); // prevent option to close compoment in GUI
|
||||
logger.log(Level.INFO, "Created DataContentTopComponent instance: " + this); //NON-NLS
|
||||
putClientProperty(TopComponent.PROP_CLOSING_DISABLED, isDefault); // prevent option to close compoment in GUI
|
||||
logger.log(Level.INFO, "Created DataContentTopComponent instance: {0}", this); //NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,24 +92,13 @@ public final class DataContentTopComponent extends TopComponent implements DataC
|
||||
return dctc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.Y_AXIS));
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
* Gets default instance. Do not use directly: reserved for *.settings files
|
||||
* only, i.e. deserialization routines; otherwise you could get a
|
||||
* non-deserialized defaultInstance. To obtain the singleton instance, use
|
||||
* {@link #findInstance}.
|
||||
* findInstance.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static synchronized DataContentTopComponent getDefault() {
|
||||
if (defaultInstance == null) {
|
||||
@ -118,8 +108,10 @@ public final class DataContentTopComponent extends TopComponent implements DataC
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the default DataContentTopComponent defaultInstance. Never call
|
||||
* {@link #getDefault} directly!
|
||||
* Obtain the default DataContentTopComponent default instance. Never call
|
||||
* getDefault directly!
|
||||
*
|
||||
* @return The default DataContentTopComponent.
|
||||
*/
|
||||
public static synchronized DataContentTopComponent findInstance() {
|
||||
TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
|
||||
@ -171,7 +163,12 @@ public final class DataContentTopComponent extends TopComponent implements DataC
|
||||
|
||||
@Override
|
||||
public boolean canClose() {
|
||||
return (!this.isDefault) || !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image in this case
|
||||
/*
|
||||
* If this is the main content viewers top component in the bottom of
|
||||
* the main window, only it to be closed when there's no case opened or
|
||||
* no data sources in the open case.
|
||||
*/
|
||||
return (!this.isDefault) || !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -195,4 +192,18 @@ public final class DataContentTopComponent extends TopComponent implements DataC
|
||||
public static List<DataContentTopComponent> getNewWindowList() {
|
||||
return newWindowList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.Y_AXIS));
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -276,7 +276,9 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (!Case.isCaseOpen()) {
|
||||
try {
|
||||
Case.getCurrentCase();
|
||||
} catch (IllegalStateException ex) {
|
||||
// Handle the in-between condition when case is being closed
|
||||
// and legacy selection events are pumped.
|
||||
return;
|
||||
@ -443,7 +445,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
|
||||
|
||||
@Override
|
||||
public List<DataResultViewer> getViewers() {
|
||||
List<DataResultViewer> ret = new ArrayList<DataResultViewer>();
|
||||
List<DataResultViewer> ret = new ArrayList<>();
|
||||
for (UpdateWrapper w : viewers) {
|
||||
ret.add(w.getViewer());
|
||||
}
|
||||
@ -452,7 +454,12 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
|
||||
}
|
||||
|
||||
public boolean canClose() {
|
||||
return (!this.isMain) || !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image in this case
|
||||
/*
|
||||
* If this is the main results panel in the main top component in the
|
||||
* upper right of the main window, only allow it to be closed when
|
||||
* there's no case opened or no data sources in the open case.
|
||||
*/
|
||||
return (!this.isMain) || !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -314,7 +314,12 @@ public class DataResultTopComponent extends TopComponent implements DataResult,
|
||||
|
||||
@Override
|
||||
public boolean canClose() {
|
||||
return (!this.isMain) || !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image in this case
|
||||
/*
|
||||
* If this is the results top component in the upper right of the main
|
||||
* window, only allow it to be closed when there's no case opened or no
|
||||
* data sources in the open case.
|
||||
*/
|
||||
return (!this.isMain) || !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -25,6 +25,7 @@ import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UIManager.LookAndFeelInfo;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
@ -32,7 +33,9 @@ import org.netbeans.spi.sendopts.OptionProcessor;
|
||||
import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI;
|
||||
import org.openide.modules.ModuleInstall;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CaseActionException;
|
||||
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
|
||||
@ -50,7 +53,7 @@ public class Installer extends ModuleInstall {
|
||||
private static Installer instance;
|
||||
|
||||
public synchronized static Installer getDefault() {
|
||||
if (instance == null) {
|
||||
if (null == instance) {
|
||||
instance = new Installer();
|
||||
}
|
||||
return instance;
|
||||
@ -80,21 +83,18 @@ public class Installer extends ModuleInstall {
|
||||
if (processor instanceof OpenFromArguments) {
|
||||
OpenFromArguments argsProcessor = (OpenFromArguments) processor;
|
||||
final String caseFile = argsProcessor.getDefaultArg();
|
||||
if (caseFile != null && !caseFile.equals("") && caseFile.endsWith(CaseMetadata.getFileExtension()) && new File(caseFile).exists()) { //NON-NLS
|
||||
new Thread(() -> {
|
||||
if (caseFile != null && !caseFile.isEmpty() && caseFile.endsWith(CaseMetadata.getFileExtension()) && new File(caseFile).exists()) { //NON-NLS
|
||||
try {
|
||||
Case.open(caseFile);
|
||||
} catch (Exception ex) {
|
||||
Case.openAsCurrentCase(caseFile);
|
||||
} catch (CaseActionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseFile), ex); //NON-NLS
|
||||
}
|
||||
}).start();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
StartupWindowProvider.getInstance().open();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -105,19 +105,10 @@ public class Installer extends ModuleInstall {
|
||||
@Override
|
||||
public void close() {
|
||||
new Thread(() -> {
|
||||
String caseDirName = null;
|
||||
try {
|
||||
if (Case.isCaseOpen()) {
|
||||
Case currentCase = Case.getCurrentCase();
|
||||
caseDirName = currentCase.getCaseDirectory();
|
||||
currentCase.closeCase();
|
||||
}
|
||||
Case.closeCurrentCase();
|
||||
} catch (CaseActionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error closing case with case directory %s", (null != caseDirName ? caseDirName : "?")), ex); //NON-NLS
|
||||
} catch (IllegalStateException ignored) {
|
||||
/*
|
||||
* No current case. Case.isCaseOpen is not reliable.
|
||||
*/
|
||||
logger.log(Level.SEVERE, "Error closing current case", ex); //NON-NLS
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-15 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -140,12 +140,12 @@ public class MediaViewImagePanel extends JPanel implements DataContentViewerMedi
|
||||
|
||||
private void showErrorNode(String errorMessage, AbstractFile file) {
|
||||
final Button externalViewerButton = new Button(Bundle.MediaViewImagePanel_externalViewerButton_text(), new ImageView(EXTERNAL));
|
||||
externalViewerButton.setOnAction(actionEvent -> //fx ActionEvent
|
||||
externalViewerButton.setOnAction(actionEvent
|
||||
-> //fx ActionEvent
|
||||
/*
|
||||
* TODO: why is the name passed into the action constructor? it
|
||||
* means we duplicate this string all over the place -jm
|
||||
*/
|
||||
new ExternalViewerAction(Bundle.MediaViewImagePanel_externalViewerButton_text(), new FileNode(file))
|
||||
*/ new ExternalViewerAction(Bundle.MediaViewImagePanel_externalViewerButton_text(), new FileNode(file))
|
||||
.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "")) //Swing ActionEvent
|
||||
);
|
||||
|
||||
@ -171,11 +171,10 @@ public class MediaViewImagePanel extends JPanel implements DataContentViewerMedi
|
||||
}
|
||||
readImageTask = ImageUtils.newReadImageTask(file);
|
||||
readImageTask.setOnSucceeded(succeeded -> {
|
||||
//Note that all error conditions are allready logged in readImageTask.succeeded()
|
||||
if (!Case.isCaseOpen()) {
|
||||
/*
|
||||
* handle in-between condition when case is being closed and
|
||||
* an image was previously selected
|
||||
* Handle the in-between condition when case is being closed
|
||||
* and an image was previously selected
|
||||
*
|
||||
* NOTE: I think this is unnecessary -jm
|
||||
*/
|
||||
@ -200,7 +199,7 @@ public class MediaViewImagePanel extends JPanel implements DataContentViewerMedi
|
||||
readImageTask.setOnFailed(failed -> {
|
||||
if (!Case.isCaseOpen()) {
|
||||
/*
|
||||
* handle in-between condition when case is being closed and
|
||||
* Handle in-between condition when case is being closed and
|
||||
* an image was previously selected
|
||||
*
|
||||
* NOTE: I think this is unnecessary -jm
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2014 Basis Technology Corp.
|
||||
* Copyright 2013-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -31,7 +31,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_Multi_User_Settings",
|
||||
iconBase = "org/sleuthkit/autopsy/images/User-Group-icon-green32.png",
|
||||
position = 2,
|
||||
position = 3,
|
||||
keywords = "#OptionsCategory_Keywords_Multi_User_Options",
|
||||
keywordsCategory = "Multi-user")
|
||||
public final class MultiUserSettingsPanelController extends OptionsPanelController {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.corecomponents;
|
||||
import org.openide.nodes.FilterNode;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
|
||||
/**
|
||||
* A filter node that creates at most one layer of child nodes for the node it
|
||||
@ -44,7 +45,7 @@ public class TableFilterNode extends FilterNode {
|
||||
* The constructor should include column order key. (See getColumnOrderKey)
|
||||
*/
|
||||
public TableFilterNode(Node wrappedNode, boolean createChildren) {
|
||||
super(wrappedNode, TableFilterChildren.createInstance(wrappedNode, createChildren));
|
||||
super(wrappedNode, TableFilterChildren.createInstance(wrappedNode, createChildren) , Lookups.proxy(wrappedNode));
|
||||
this.createChildren = createChildren;
|
||||
}
|
||||
|
||||
|
@ -163,12 +163,22 @@ public final class ExecUtil {
|
||||
process.waitFor(timeOut, units);
|
||||
if (process.isAlive() && terminator.shouldTerminateProcess()) {
|
||||
killProcess(process);
|
||||
try {
|
||||
process.waitFor(); //waiting to help ensure process is shutdown before calling interrupt() or returning
|
||||
} catch (InterruptedException exx) {
|
||||
Logger.getLogger(ExecUtil.class.getName()).log(Level.INFO, String.format("Wait for process termination following killProcess was interrupted for command %s", processBuilder.command().get(0)));
|
||||
}
|
||||
}
|
||||
} while (process.isAlive());
|
||||
} catch (InterruptedException ex) {
|
||||
if (process.isAlive()) {
|
||||
killProcess(process);
|
||||
}
|
||||
try {
|
||||
process.waitFor(); //waiting to help ensure process is shutdown before calling interrupt() or returning
|
||||
} catch (InterruptedException exx) {
|
||||
Logger.getLogger(ExecUtil.class.getName()).log(Level.INFO, String.format("Wait for process termination following killProcess was interrupted for command %s", processBuilder.command().get(0)));
|
||||
}
|
||||
Logger.getLogger(ExecUtil.class.getName()).log(Level.INFO, "Thread interrupted while running {0}", processBuilder.command().get(0)); // NON-NLS
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
@ -315,4 +315,29 @@ public class UNCPathUtilities {
|
||||
}
|
||||
return driveMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a path to UNC, if possible. This is accomplished by checking the
|
||||
* mapped drives list the operating system maintains and substituting where
|
||||
* required. If the drive of the path passed in does not exist in the cached
|
||||
* mapped drives list, a rescan of the mapped drives list is forced, and
|
||||
* mapping is attempted one more time.
|
||||
*
|
||||
* @param indexDir the String of the absolute path to be converted to UNC,
|
||||
* if possible
|
||||
*
|
||||
* @return UNC path if able to convert to UNC, original input path otherwise
|
||||
*/
|
||||
synchronized public String convertPathToUNC(String indexDir) {
|
||||
// if we can check for UNC paths, do so, otherwise just return the indexDir
|
||||
String result = mappedDriveToUNC(indexDir);
|
||||
if (result == null) {
|
||||
rescanDrives();
|
||||
result = mappedDriveToUNC(indexDir);
|
||||
}
|
||||
if (result == null) {
|
||||
return indexDir;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,62 +19,105 @@
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.TimeZone;
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
|
||||
/**
|
||||
* StringContent object for a blackboard artifact, that can be looked up and
|
||||
* used to display text for the DataContent viewers. Displays values in artifact
|
||||
* in HTML. Note that it has no style associated with it and assumes that the
|
||||
* pane showing the HTML has styles set (such as with HTMLEditorKit).
|
||||
* An HTML representation of an artifact. The representation is plain vanilla
|
||||
* HTML, so any styling needs to be supplied by the display mechansim. For
|
||||
* example, GUI components such as content viewers might use HTMLEditorKit to
|
||||
* add styling.
|
||||
*/
|
||||
public class ArtifactStringContent implements StringContent {
|
||||
|
||||
BlackboardArtifact artifact;
|
||||
private final static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
private final static Logger logger = Logger.getLogger(ArtifactStringContent.class.getName());
|
||||
private final BlackboardArtifact artifact;
|
||||
private String stringContent = "";
|
||||
static final Logger logger = Logger.getLogger(ArtifactStringContent.class.getName());
|
||||
private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public ArtifactStringContent(BlackboardArtifact art) {
|
||||
artifact = art;
|
||||
/**
|
||||
* Constructs an HTML representation of an artifact. The representation is
|
||||
* plain vanilla HTML, so any styling needs to be supplied by the display
|
||||
* mechansim. For example, GUI components such as content viewers might use
|
||||
* HTMLEditorKit to add styling.
|
||||
*
|
||||
* @param artifact The artifact to be represented as HTML.
|
||||
*/
|
||||
public ArtifactStringContent(BlackboardArtifact artifact) {
|
||||
this.artifact = artifact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the HTML representation of the artifact.
|
||||
*
|
||||
* @return The HTML representation of the artifact as a string.
|
||||
*/
|
||||
@Messages({
|
||||
"ArtifactStringContent.attrsTableHeader.attribute=Attribute",
|
||||
"ArtifactStringContent.attrsTableHeader.value=Value",
|
||||
"ArtifactStringContent.attrsTableHeader.sources=Source(s)",
|
||||
"ArtifactStringContent.failedToGetSourcePath.message=Failed to get source file path from case database",
|
||||
"ArtifactStringContent.failedToGetAttributes.message=Failed to get some or all attributes from case database"
|
||||
})
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public String getString() {
|
||||
if (stringContent.isEmpty()) {
|
||||
try {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
/*
|
||||
* Start the document.
|
||||
*/
|
||||
StringBuilder buffer = new StringBuilder(1024);
|
||||
buffer.append("<html>\n"); //NON-NLS
|
||||
buffer.append("<body>\n"); //NON-NLS
|
||||
|
||||
// artifact name header
|
||||
buffer.append("<h4>"); //NON-NLS
|
||||
/*
|
||||
* Use the artifact display name as a header.
|
||||
*/
|
||||
buffer.append("<h3>"); //NON-NLS
|
||||
buffer.append(artifact.getDisplayName());
|
||||
buffer.append("</h4>\n"); //NON-NLS
|
||||
buffer.append("</h3>\n"); //NON-NLS
|
||||
|
||||
// start table for attributes
|
||||
buffer.append("<table border='0'>"); //NON-NLS
|
||||
/*
|
||||
* Put the attributes, source content path and artifact id in a
|
||||
* table.
|
||||
*/
|
||||
buffer.append("<table border='1'>"); //NON-NLS
|
||||
buffer.append("<tr>"); //NON-NLS
|
||||
buffer.append("<td>"); //NON-NLS
|
||||
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_attribute());
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
buffer.append("<td>"); //NON-NLS
|
||||
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_value());
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
buffer.append("<td>"); //NON-NLS
|
||||
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_sources());
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
buffer.append("</tr>\n"); //NON-NLS
|
||||
try {
|
||||
Content content = artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
|
||||
|
||||
// cycle through each attribute and display in a row in the table.
|
||||
/*
|
||||
* Add rows for each attribute.
|
||||
*/
|
||||
for (BlackboardAttribute attr : artifact.getAttributes()) {
|
||||
|
||||
// name column
|
||||
/*
|
||||
* Attribute display name column.
|
||||
*/
|
||||
buffer.append("<tr><td>"); //NON-NLS
|
||||
buffer.append(attr.getAttributeType().getDisplayName());
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
|
||||
// value column
|
||||
/*
|
||||
* Attribute value column.
|
||||
*/
|
||||
buffer.append("<td>"); //NON-NLS
|
||||
switch (attr.getAttributeType().getValueType()) {
|
||||
case STRING:
|
||||
@ -88,48 +131,57 @@ public class ArtifactStringContent implements StringContent {
|
||||
case INTEGER:
|
||||
case LONG:
|
||||
case DOUBLE:
|
||||
case BYTE:
|
||||
buffer.append(attr.getDisplayString());
|
||||
break;
|
||||
case BYTE:
|
||||
buffer.append(Arrays.toString(attr.getValueBytes()));
|
||||
break;
|
||||
case DATETIME:
|
||||
long epoch = attr.getValueLong();
|
||||
String time = "0000-00-00 00:00:00";
|
||||
if (epoch != 0) {
|
||||
dateFormatter.setTimeZone(getTimeZone(artifact));
|
||||
if (null != content && 0 != epoch) {
|
||||
dateFormatter.setTimeZone(ContentUtils.getTimeZone(content));
|
||||
time = dateFormatter.format(new java.util.Date(epoch * 1000));
|
||||
}
|
||||
buffer.append(time);
|
||||
break;
|
||||
}
|
||||
if (!"".equals(attr.getContext())) {
|
||||
buffer.append(" (");
|
||||
buffer.append(attr.getContext());
|
||||
buffer.append(")");
|
||||
}
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
|
||||
/*
|
||||
* Attribute sources column.
|
||||
*/
|
||||
buffer.append("<td>"); //NON-NLS
|
||||
buffer.append(StringUtils.join(attr.getSources(), ", "));
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
|
||||
buffer.append("</tr>\n"); //NON-NLS
|
||||
}
|
||||
|
||||
final Content content = getAssociatedContent(artifact);
|
||||
|
||||
String path = "";
|
||||
try {
|
||||
path = content.getUniquePath();
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Exception while calling Content.getUniquePath() on {0} : {1}", new Object[]{content, ex.getLocalizedMessage()}); //NON-NLS
|
||||
}
|
||||
|
||||
//add file path
|
||||
/*
|
||||
* Add a row for the source content path.
|
||||
*/
|
||||
buffer.append("<tr>"); //NON-NLS
|
||||
buffer.append("<td>"); //NON-NLS
|
||||
buffer.append(NbBundle.getMessage(this.getClass(), "ArtifactStringContent.getStr.srcFilePath.text"));
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
buffer.append("<td>"); //NON-NLS
|
||||
String path = "";
|
||||
try {
|
||||
if (null != content) {
|
||||
path = content.getUniquePath();
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error getting source content path for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
|
||||
path = Bundle.ArtifactStringContent_failedToGetSourcePath_message();
|
||||
}
|
||||
buffer.append(path);
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
buffer.append("</tr>\n"); //NON-NLS
|
||||
|
||||
// add artifact ID (useful for debugging)
|
||||
/*
|
||||
* Add a row for the artifact id.
|
||||
*/
|
||||
buffer.append("<tr><td>"); //NON-NLS
|
||||
buffer.append(NbBundle.getMessage(this.getClass(), "ArtifactStringContent.getStr.artifactId.text"));
|
||||
buffer.append("</td><td>"); //NON-NLS
|
||||
@ -137,29 +189,26 @@ public class ArtifactStringContent implements StringContent {
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
buffer.append("</tr>\n"); //NON-NLS
|
||||
|
||||
/*
|
||||
* Finish the document
|
||||
*/
|
||||
buffer.append("</table>"); //NON-NLS
|
||||
buffer.append("</html>\n"); //NON-NLS
|
||||
stringContent = buffer.toString();
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error getting data for artifact (artifact_id=%d)", artifact.getArtifactID()), ex);
|
||||
buffer.append("<tr><td>"); //NON-NLS
|
||||
buffer.append(Bundle.ArtifactStringContent_failedToGetAttributes_message());
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
buffer.append("</tr>\n"); //NON-NLS
|
||||
buffer.append("</table>"); //NON-NLS
|
||||
buffer.append("</html>\n"); //NON-NLS
|
||||
|
||||
stringContent = buffer.toString();
|
||||
} catch (TskException ex) {
|
||||
stringContent = NbBundle.getMessage(this.getClass(), "ArtifactStringContent.getStr.err");
|
||||
}
|
||||
}
|
||||
|
||||
return stringContent;
|
||||
}
|
||||
|
||||
private static Content getAssociatedContent(BlackboardArtifact artifact) {
|
||||
try {
|
||||
return artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
|
||||
} catch (TskException ex) {
|
||||
logger.log(Level.WARNING, "Getting file failed", ex); //NON-NLS
|
||||
}
|
||||
throw new IllegalArgumentException(NbBundle.getMessage(ArtifactStringContent.class, "ArtifactStringContent.exception.msg"));
|
||||
}
|
||||
|
||||
private static TimeZone getTimeZone(BlackboardArtifact artifact) {
|
||||
return ContentUtils.getTimeZone(getAssociatedContent(artifact));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -404,7 +404,8 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()
|
||||
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE.getTypeID()) {
|
||||
} else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
|
||||
map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
|
||||
} else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID()
|
||||
@ -452,13 +453,6 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
forLookup.add(content);
|
||||
}
|
||||
|
||||
// if there is a text highlighted version, of the content, add it too
|
||||
// currently happens from keyword search module
|
||||
TextMarkupLookup highlight = getHighlightLookup(artifact, content);
|
||||
if (highlight != null) {
|
||||
forLookup.add(highlight);
|
||||
}
|
||||
|
||||
return Lookups.fixed(forLookup.toArray(new Object[forLookup.size()]));
|
||||
}
|
||||
|
||||
@ -472,39 +466,6 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.getAssocCont.exception.msg"));
|
||||
}
|
||||
|
||||
private static TextMarkupLookup getHighlightLookup(BlackboardArtifact artifact, Content content) {
|
||||
if (artifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
long objectId = content.getId();
|
||||
|
||||
Lookup lookup = Lookup.getDefault();
|
||||
TextMarkupLookup highlightFactory = lookup.lookup(TextMarkupLookup.class);
|
||||
try {
|
||||
List<BlackboardAttribute> attributes = artifact.getAttributes();
|
||||
String keyword = null;
|
||||
String regexp = null;
|
||||
for (BlackboardAttribute att : attributes) {
|
||||
final int attributeTypeID = att.getAttributeType().getTypeID();
|
||||
if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
|
||||
keyword = att.getValueString();
|
||||
} else if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()) {
|
||||
regexp = att.getValueString();
|
||||
} else if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
|
||||
objectId = att.getValueLong();
|
||||
}
|
||||
}
|
||||
if (keyword != null) {
|
||||
boolean isRegexp = StringUtils.isNotBlank(regexp);
|
||||
String origQuery = isRegexp ? regexp : keyword;
|
||||
return highlightFactory.createInstance(objectId, keyword, isRegexp, origQuery);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.WARNING, "Failed to retrieve Blackboard Attributes", ex); //NON-NLS
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeafTypeNode() {
|
||||
|
@ -12,7 +12,7 @@ AbstractAbstractFileNode.modeColLbl=Mode
|
||||
AbstractAbstractFileNode.useridColLbl=UserID
|
||||
AbstractAbstractFileNode.groupidColLbl=GroupID
|
||||
AbstractAbstractFileNode.metaAddrColLbl=Meta Addr.
|
||||
AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.
|
||||
AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.ArtifactStringContent.getStr.err
|
||||
AbstractAbstractFileNode.typeDirColLbl=Type(Dir)
|
||||
AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)
|
||||
AbstractAbstractFileNode.knownColLbl=Known
|
||||
@ -25,7 +25,6 @@ AbstractContentNode.exception.cannotChangeSysName.msg=Cannot change the system n
|
||||
AbstractFsContentNode.noDesc.text=no description
|
||||
ArtifactStringContent.getStr.srcFilePath.text=Source File Path
|
||||
ArtifactStringContent.getStr.err=Error getting content
|
||||
ArtifactStringContent.exception.msg=Could not get file from database
|
||||
ArtifactTypeNode.createSheet.artType.name=Artifact Type
|
||||
ArtifactTypeNode.createSheet.artType.displayName=Artifact Type
|
||||
ArtifactTypeNode.createSheet.artType.desc=no description
|
||||
@ -172,8 +171,6 @@ KeywordHits.createNodeForKey.chgTime.desc=Change Time
|
||||
KeywordHits.createNodeForKey.chgTime.name=ChangeTime
|
||||
KeywordHits.createNodeForKey.accessTime.name=AccessTime
|
||||
KeywordHits.createNodeForKey.modTime.name=ModifiedTime
|
||||
KnownFileFilterNode.selectionContext.dataSources=Data Sources
|
||||
KnownFileFilterNode.selectionContext.views=Views
|
||||
LayoutFileNode.propertyType.parts=Parts
|
||||
LayoutFileNode.createSheet.name.name=Name
|
||||
LayoutFileNode.createSheet.name.displayName=Name
|
||||
@ -222,8 +219,6 @@ ReportNode.reportNameProperty.name=Report Name
|
||||
ReportNode.reportNameProperty.displayName=Report Name
|
||||
ReportNode.reportNameProperty.desc=Name of the report
|
||||
ReportsListNode.displayName=Reports
|
||||
SlackFileFilterNode.selectionContext.dataSources=Data Sources
|
||||
SlackFileFilterNode.selectionContext.views=Views
|
||||
SlackFileNode.getActions.viewInNewWin.text=View in New Window
|
||||
SlackFileNode.getActions.viewFileInDir.text=View File in Directory
|
||||
TagNameNode.namePlusTags.text={0} Tags
|
||||
|
@ -18,7 +18,6 @@ AbstractContentNode.exception.cannotChangeSysName.msg=\u30b7\u30b9\u30c6\u30e0\u
|
||||
AbstractFsContentNode.noDesc.text=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
||||
ArtifactStringContent.getStr.srcFilePath.text=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9
|
||||
ArtifactStringContent.getStr.err=\u30b3\u30f3\u30c6\u30f3\u30c4\u53d6\u5f97\u30a8\u30e9\u30fc
|
||||
ArtifactStringContent.exception.msg=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f
|
||||
ArtifactTypeNode.createSheet.artType.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
||||
ArtifactTypeNode.createSheet.childCnt.name=\u30c1\u30e3\u30a4\u30eb\u30c9\u6570
|
||||
ArtifactTypeNode.createSheet.childCnt.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
||||
|
@ -147,7 +147,9 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
final String mime_type = resultSet.getString("mime_type"); //NON-NLS
|
||||
if (!mime_type.isEmpty()) {
|
||||
String mimeType[] = mime_type.split("/");
|
||||
if (!mimeType[0].isEmpty() && !mimeType[1].isEmpty()) {
|
||||
//Note: Users are able to define custom mime types in Autopsy that do not
|
||||
//contain a "/" or possibly have multiple slashes
|
||||
if (mimeType.length > 1 && !mimeType[0].isEmpty() && !mimeType[1].isEmpty()) {
|
||||
if (!existingMimeTypes.containsKey(mimeType[0])) {
|
||||
existingMimeTypes.put(mimeType[0], new ArrayList<>());
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.sql.ResultSet;
|
||||
@ -27,7 +26,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Sheet;
|
||||
@ -40,7 +38,7 @@ import org.sleuthkit.autopsy.directorytree.FileSearchAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
|
||||
import org.sleuthkit.autopsy.ingest.RunIngestModulesDialog;
|
||||
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
|
||||
@ -101,22 +99,14 @@ public class ImageNode extends AbstractContentNode<Image> {
|
||||
"ImageNode.getActions.openFileSearchByAttr.text=Open File Search by Attributes",})
|
||||
public Action[] getActions(boolean context) {
|
||||
|
||||
List<Action> actionsList = new ArrayList<Action>();
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
for (Action a : super.getActions(true)) {
|
||||
actionsList.add(a);
|
||||
}
|
||||
actionsList.addAll(ExplorerNodeActionVisitor.getActions(content));
|
||||
actionsList.add(new FileSearchAction(
|
||||
Bundle.ImageNode_getActions_openFileSearchByAttr_text()));
|
||||
actionsList.add(new AbstractAction(
|
||||
Bundle.ImageNode_action_runIngestMods_text()) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog(Collections.<Content>singletonList(content));
|
||||
ingestDialog.display();
|
||||
}
|
||||
});
|
||||
|
||||
actionsList.add(new RunIngestModulesAction(Collections.<Content>singletonList(content)));
|
||||
actionsList.add(new NewWindowViewAction(
|
||||
NbBundle.getMessage(this.getClass(), "ImageNode.getActions.viewInNewWin.text"), this));
|
||||
return actionsList.toArray(new Action[0]);
|
||||
|
@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2014 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.util.prefs.PreferenceChangeEvent;
|
||||
import java.util.prefs.PreferenceChangeListener;
|
||||
import org.openide.nodes.FilterNode;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* A Filter Node responsible for conditionally filtering out Nodes that
|
||||
* represent known files.
|
||||
*
|
||||
* Filters known files IF the option to Filter Known files for the given
|
||||
* SelectionContext is set. Otherwise, does nothing.
|
||||
*
|
||||
* @author jwallace
|
||||
*/
|
||||
public class KnownFileFilterNode extends FilterNode {
|
||||
|
||||
private static boolean filterFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
|
||||
private static boolean filterFromViews = UserPreferences.hideKnownFilesInViewsTree();
|
||||
|
||||
static {
|
||||
UserPreferences.addChangeListener(new PreferenceChangeListener() {
|
||||
@Override
|
||||
public void preferenceChange(PreferenceChangeEvent evt) {
|
||||
switch (evt.getKey()) {
|
||||
case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE:
|
||||
filterFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
|
||||
break;
|
||||
case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE:
|
||||
filterFromViews = UserPreferences.hideKnownFilesInViewsTree();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public enum SelectionContext {
|
||||
|
||||
DATA_SOURCES(NbBundle.getMessage(KnownFileFilterNode.class, "KnownFileFilterNode.selectionContext.dataSources")),
|
||||
VIEWS(NbBundle.getMessage(KnownFileFilterNode.class, "KnownFileFilterNode.selectionContext.views")),
|
||||
OTHER(""); // Subnode of another node.
|
||||
|
||||
private final String displayName;
|
||||
|
||||
SelectionContext(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public static SelectionContext getContextFromName(String name) {
|
||||
if (name.equals(DATA_SOURCES.getName())) {
|
||||
return DATA_SOURCES;
|
||||
} else if (name.equals(VIEWS.getName())) {
|
||||
return VIEWS;
|
||||
} else {
|
||||
return OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
private String getName() {
|
||||
return displayName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a KnownFileFilterNode from the given Node. Note that the Node
|
||||
* should be from the directory tree.
|
||||
*
|
||||
* @param arg
|
||||
* @param context
|
||||
*/
|
||||
public KnownFileFilterNode(Node arg, SelectionContext context) {
|
||||
super(arg, new KnownFileFilterChildren(arg, context));
|
||||
}
|
||||
|
||||
private KnownFileFilterNode(Node arg, boolean filter) {
|
||||
super(arg, new KnownFileFilterChildren(arg, filter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selection context of a Node in the DirectoryTree.
|
||||
*
|
||||
* @param n
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static SelectionContext getSelectionContext(Node n) {
|
||||
if (n == null || n.getParentNode() == null) {
|
||||
// Parent of root node or root node. Occurs during case open / close.
|
||||
return SelectionContext.OTHER;
|
||||
} else if (n.getParentNode().getParentNode() == null) {
|
||||
// One level below root node. Should be one of DataSources, Views, or Results
|
||||
return SelectionContext.getContextFromName(n.getDisplayName());
|
||||
} else {
|
||||
return getSelectionContext(n.getParentNode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Complementary class to KnownFileFilterNode.
|
||||
*
|
||||
* Filters out children Nodes that represent known files. Otherwise, returns
|
||||
* the original node wrapped in another instance of the KnownFileFilterNode.
|
||||
*
|
||||
* @author jwallace
|
||||
*/
|
||||
private static class KnownFileFilterChildren extends FilterNode.Children {
|
||||
|
||||
/**
|
||||
* True if this KnownFileFilterChildren should filter out known files.
|
||||
*/
|
||||
private boolean filter;
|
||||
|
||||
/**
|
||||
* Constructor used when the context has already been determined.
|
||||
*
|
||||
* @param arg
|
||||
* @param filter
|
||||
*/
|
||||
private KnownFileFilterChildren(Node arg, boolean filter) {
|
||||
super(arg);
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used when the context has not been determined.
|
||||
*
|
||||
* @param arg
|
||||
* @param context
|
||||
*/
|
||||
private KnownFileFilterChildren(Node arg, KnownFileFilterNode.SelectionContext context) {
|
||||
super(arg);
|
||||
|
||||
switch (context) {
|
||||
case DATA_SOURCES:
|
||||
filter = filterFromDataSources;
|
||||
break;
|
||||
case VIEWS:
|
||||
filter = filterFromViews;
|
||||
break;
|
||||
default:
|
||||
filter = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node[] createNodes(Node arg) {
|
||||
if (filter) {
|
||||
// Filter out child nodes that represent known files
|
||||
AbstractFile file = arg.getLookup().lookup(AbstractFile.class);
|
||||
if (file != null && (file.getKnown() == TskData.FileKnown.KNOWN)) {
|
||||
return new Node[]{};
|
||||
}
|
||||
}
|
||||
return new Node[]{new KnownFileFilterNode(arg, filter)};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,180 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2014 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.util.prefs.PreferenceChangeEvent;
|
||||
import java.util.prefs.PreferenceChangeListener;
|
||||
import org.openide.nodes.FilterNode;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* A Filter Node responsible for conditionally filtering out Nodes that
|
||||
* represent slack files.
|
||||
*
|
||||
* Filters known files IF the option to Filter Slack files for the given
|
||||
* SelectionContext is set. Otherwise, does nothing.
|
||||
*
|
||||
*/
|
||||
public class SlackFileFilterNode extends FilterNode {
|
||||
|
||||
private static boolean filterFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree();
|
||||
private static boolean filterFromViews = UserPreferences.hideSlackFilesInViewsTree();
|
||||
|
||||
static {
|
||||
UserPreferences.addChangeListener(new PreferenceChangeListener() {
|
||||
@Override
|
||||
public void preferenceChange(PreferenceChangeEvent evt) {
|
||||
switch (evt.getKey()) {
|
||||
case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SRCS_TREE:
|
||||
filterFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree();
|
||||
break;
|
||||
case UserPreferences.HIDE_SLACK_FILES_IN_VIEWS_TREE:
|
||||
filterFromViews = UserPreferences.hideSlackFilesInViewsTree();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public enum SelectionContext {
|
||||
|
||||
DATA_SOURCES(NbBundle.getMessage(SlackFileFilterNode.class, "SlackFileFilterNode.selectionContext.dataSources")),
|
||||
VIEWS(NbBundle.getMessage(SlackFileFilterNode.class, "SlackFileFilterNode.selectionContext.views")),
|
||||
OTHER(""); // Subnode of another node.
|
||||
|
||||
private final String displayName;
|
||||
|
||||
SelectionContext(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public static SelectionContext getContextFromName(String name) {
|
||||
if (name.equals(DATA_SOURCES.getName())) {
|
||||
return DATA_SOURCES;
|
||||
} else if (name.equals(VIEWS.getName())) {
|
||||
return VIEWS;
|
||||
} else {
|
||||
return OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
private String getName() {
|
||||
return displayName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SlackFileFilterNode from the given Node. Note that the Node
|
||||
* should be from the directory tree.
|
||||
*
|
||||
* @param arg
|
||||
* @param context
|
||||
*/
|
||||
public SlackFileFilterNode(Node arg, SelectionContext context) {
|
||||
super(arg, new SlackFileFilterChildren(arg, context));
|
||||
}
|
||||
|
||||
private SlackFileFilterNode(Node arg, boolean filter) {
|
||||
super(arg, new SlackFileFilterChildren(arg, filter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selection context of a Node in the DirectoryTree.
|
||||
*
|
||||
* @param n
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static SelectionContext getSelectionContext(Node n) {
|
||||
if (n == null || n.getParentNode() == null) {
|
||||
// Parent of root node or root node. Occurs during case open / close.
|
||||
return SelectionContext.OTHER;
|
||||
} else if (n.getParentNode().getParentNode() == null) {
|
||||
// One level below root node. Should be one of DataSources, Views, or Results
|
||||
return SelectionContext.getContextFromName(n.getDisplayName());
|
||||
} else {
|
||||
return getSelectionContext(n.getParentNode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Complementary class to SlackFileFilterNode.
|
||||
*
|
||||
* Filters out children Nodes that represent slack files. Otherwise, returns
|
||||
* the original node wrapped in another instance of the SlackFileFilterNode.
|
||||
*
|
||||
* @author jwallace
|
||||
*/
|
||||
private static class SlackFileFilterChildren extends FilterNode.Children {
|
||||
|
||||
/**
|
||||
* True if this SlackFileFilterChildren should filter out slack files.
|
||||
*/
|
||||
private boolean filter;
|
||||
|
||||
/**
|
||||
* Constructor used when the context has already been determined.
|
||||
*
|
||||
* @param arg
|
||||
* @param filter
|
||||
*/
|
||||
private SlackFileFilterChildren(Node arg, boolean filter) {
|
||||
super(arg);
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used when the context has not been determined.
|
||||
*
|
||||
* @param arg
|
||||
* @param context
|
||||
*/
|
||||
private SlackFileFilterChildren(Node arg, SlackFileFilterNode.SelectionContext context) {
|
||||
super(arg);
|
||||
|
||||
switch (context) {
|
||||
case DATA_SOURCES:
|
||||
filter = filterFromDataSources;
|
||||
break;
|
||||
case VIEWS:
|
||||
filter = filterFromViews;
|
||||
break;
|
||||
default:
|
||||
filter = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node[] createNodes(Node arg) {
|
||||
if (filter) {
|
||||
// Filter out child nodes that represent slack files
|
||||
AbstractFile file = arg.getLookup().lookup(AbstractFile.class);
|
||||
if ((file != null) && file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
|
||||
return new Node[]{};
|
||||
}
|
||||
}
|
||||
return new Node[]{new SlackFileFilterNode(arg, filter)};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
/**
|
||||
* This interface acts as a sort of bridge between the Autopsy Core NetBeans
|
||||
* Module (NBM) and the Autopsy KeywordSearch NBM. It is used to get indexed
|
||||
* text marked up with HTML to highlight search hits for a particular keyword.
|
||||
*
|
||||
* Here is an example of how it works. It is used to put highlighted markup into
|
||||
* the Lookups of the BlackboardArtifactNodes for keyword search hit artifacts.
|
||||
* The BlackboardArtifactNode code that populates the node's Lookup asks the
|
||||
* default global Lookup for an instance of TextMarkupLookup. The
|
||||
* org.sleuthkit.autopsy.keywordsearch.HighlightedText class is the sole
|
||||
* implementation of the interface, so the BlackboardArtifactNode gets a default
|
||||
* constructed instance of HighlightedText. This otherwise useless
|
||||
* instance is then used to call createInstance with parameters that are used to
|
||||
* employ the Solr highlighting capability to create the markup. The
|
||||
* TextMarkupLookup object goes in the BlackboardArtifactNode Lookup for later
|
||||
* use by the ExtractedContentViewer, a DataContentViewer in the KeywordSearch
|
||||
* NBM.
|
||||
*/
|
||||
public interface TextMarkupLookup {
|
||||
|
||||
/**
|
||||
* Factory method for getting an object that encapsulates indexed text
|
||||
* marked up (HTML) to highlight search hits for a particular keyword.
|
||||
*
|
||||
* @param objectId ID of the object (file or artifact) that is the
|
||||
* source of the indexed text.
|
||||
* @param keyword The keyword to be highlighted in the text.
|
||||
* @param isRegex Whether or not the query that follows is a regex.
|
||||
* @param originalQuery The query that produces the keyword hit.
|
||||
*
|
||||
* @return An object that encapsulates indexed text marked up (HTML) to
|
||||
* highlight search hits for a particular keyword.
|
||||
*/
|
||||
public TextMarkupLookup createInstance(long objectId, String keyword, boolean isRegex, String originalQuery);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
@ -27,7 +26,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
@ -38,7 +36,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.FileSearchAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.ingest.RunIngestModulesDialog;
|
||||
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
@ -50,7 +48,7 @@ import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
*/
|
||||
public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirectory> {
|
||||
|
||||
private static Logger logger = Logger.getLogger(VirtualDirectoryNode.class.getName());
|
||||
private static final Logger logger = Logger.getLogger(VirtualDirectoryNode.class.getName());
|
||||
//prefix for special VirtualDirectory root nodes grouping local files
|
||||
public final static String LOGICAL_FILE_SET_PREFIX = "LogicalFileSet"; //NON-NLS
|
||||
|
||||
@ -100,14 +98,7 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirect
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new FileSearchAction(
|
||||
Bundle.ImageNode_getActions_openFileSearchByAttr_text()));
|
||||
actions.add(new AbstractAction(
|
||||
Bundle.VirtualDirectoryNode_action_runIngestMods_text()) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog(Collections.<Content>singletonList(content));
|
||||
ingestDialog.display();
|
||||
}
|
||||
});
|
||||
actions.add(new RunIngestModulesAction(Collections.<Content>singletonList(content)));
|
||||
actions.addAll(ContextMenuExtensionPoint.getActions());
|
||||
return actions.toArray(new Action[0]);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ package org.sleuthkit.autopsy.datasourceprocessors;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
@ -41,111 +41,140 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* The ImageWriter class is used to complete VHD copies created from local disks
|
||||
* after the ingest process completes.
|
||||
* after the ingest process completes. The AddImageTask for this data source must have included
|
||||
* a non-empty imageWriterPath parameter to enable Image Writer.
|
||||
*/
|
||||
public class ImageWriter {
|
||||
public class ImageWriter implements PropertyChangeListener{
|
||||
|
||||
private final Logger logger = Logger.getLogger(ImageWriter.class.getName());
|
||||
|
||||
private final HashSet<Long> dataSourceIds = new HashSet<>();
|
||||
private final Object dataSourceIdsLock; // Get this lock before accessing dataSourceIds
|
||||
private final Long dataSourceId;
|
||||
|
||||
private final HashSet<ScheduledFuture<?>> progressUpdaters = new HashSet<>();
|
||||
private final HashSet<Long> imagesBeingFinished = new HashSet<>();
|
||||
private final HashSet<ProgressHandle> progressBars = new HashSet<>();
|
||||
private final HashSet<Future<?>> finishTasksInProgress = new HashSet<>();
|
||||
private boolean isCancelled;
|
||||
private final Object currentTasksLock; // Get this lock before accessing imagesBeingFinished, progressBars, progressUpdaters, finishTasksInProgress or isCancelled
|
||||
private Long imageHandle = null;
|
||||
private Future<?> finishTask = null;
|
||||
private ProgressHandle progressHandle = null;
|
||||
private ScheduledFuture<?> progressUpdateTask = null;
|
||||
private boolean isCancelled = false;
|
||||
private boolean isStarted = false;
|
||||
private boolean isFinished = false;
|
||||
private final Object currentTasksLock = new Object(); // Get this lock before accessing imageHandle, finishTask, progressHandle, progressUpdateTask,
|
||||
// isCancelled, isStarted, or isFinished
|
||||
|
||||
private boolean listenerStarted;
|
||||
private ScheduledThreadPoolExecutor periodicTasksExecutor = null;
|
||||
private final boolean doUI;
|
||||
|
||||
public ImageWriter(){
|
||||
dataSourceIdsLock = new Object();
|
||||
currentTasksLock = new Object();
|
||||
listenerStarted = false;
|
||||
isCancelled = false;
|
||||
private static final AtomicInteger numFinishJobsInProgress = new AtomicInteger(0);
|
||||
|
||||
doUI = RuntimeProperties.coreComponentsAreActive();
|
||||
if(doUI){
|
||||
periodicTasksExecutor = new ScheduledThreadPoolExecutor(5, new ThreadFactoryBuilder().setNameFormat("image-writer-progress-update-%d").build()); //NON-NLS
|
||||
}
|
||||
/**
|
||||
* Create the Image Writer object.
|
||||
* After creation, startListeners() should be called.
|
||||
* @param dataSourceId
|
||||
*/
|
||||
public ImageWriter(Long dataSourceId){
|
||||
this.dataSourceId = dataSourceId;
|
||||
doUI = RuntimeProperties.runningWithGUI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a listener on IngestJobEvents if it hasn't already been started.
|
||||
* When a DataSourceAnalysisCompletedEvent arrives, if it matches
|
||||
* the data source ID of an image that is using Image Writer, then finish the image
|
||||
* (fill in any gaps). The AddImageTask for this data source must have included
|
||||
* a non-empty imageWriterPath parameter to enable Image Writer.
|
||||
* Add this ImageWriter object as a listener to the necessary events
|
||||
*/
|
||||
public void subscribeToEvents(){
|
||||
IngestManager.getInstance().addIngestJobEventListener(this);
|
||||
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deregister this object from the events. This is ok to call multiple times.
|
||||
*/
|
||||
public void unsubscribeFromEvents(){
|
||||
IngestManager.getInstance().removeIngestJobEventListener(this);
|
||||
Case.removeEventSubscriber(Case.Events.CURRENT_CASE.toString(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the events:
|
||||
* DATA_SOURCE_ANALYSIS_COMPLETED - start the finish image process and clean up after it is complete
|
||||
* CURRENT_CASE (case closing) - cancel the finish image process (if necessary)
|
||||
*/
|
||||
private synchronized void startListener(){
|
||||
if(! listenerStarted){
|
||||
IngestManager.getInstance().addIngestJobEventListener(new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if(evt.getPropertyName().equals(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED.toString())){
|
||||
if(evt instanceof DataSourceAnalysisCompletedEvent){
|
||||
|
||||
DataSourceAnalysisCompletedEvent event = (DataSourceAnalysisCompletedEvent)evt;
|
||||
|
||||
if(event.getDataSource() != null){
|
||||
long imageId = event.getDataSource().getId();
|
||||
String name = event.getDataSource().getName();
|
||||
|
||||
// Check whether we need to run finishImage for this data source
|
||||
synchronized(dataSourceIdsLock){
|
||||
if( ! ImageWriter.this.dataSourceIds.contains(imageId)){
|
||||
// Image writer was not used on this data source or we've already finished it
|
||||
// Check that the event corresponds to this datasource
|
||||
if(imageId != dataSourceId){
|
||||
return;
|
||||
} else {
|
||||
// Remove the imageId from the list here so we can't get past this point twice
|
||||
// for the same image. Multiple DataSourceAnalysisCompletedEvent events can come from
|
||||
// the same image if more ingest modules are run later, but the imageId is only added
|
||||
// to the list during the intial task to add the image to the database.
|
||||
ImageWriter.this.dataSourceIds.remove(imageId);
|
||||
}
|
||||
}
|
||||
logger.log(Level.INFO, String.format("Finishing VHD image for %s",
|
||||
event.getDataSource().getName())); //NON-NLS
|
||||
|
||||
new Thread(() -> {
|
||||
try{
|
||||
Image image = Case.getCurrentCase().getSleuthkitCase().getImageById(imageId);
|
||||
ProgressHandle progressHandle = null;
|
||||
ScheduledFuture<?> progressUpdateTask = null;
|
||||
startFinishImage(name);
|
||||
}).start();
|
||||
|
||||
if(doUI){
|
||||
progressHandle = ProgressHandle.createHandle("Image writer - " + name);
|
||||
progressHandle.start(100);
|
||||
progressUpdateTask = periodicTasksExecutor.scheduleAtFixedRate(
|
||||
new ProgressUpdateTask(progressHandle, image.getImageHandle()), 0, 250, TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
logger.log(Level.SEVERE, "DataSourceAnalysisCompletedEvent did not contain a dataSource object"); //NON-NLS
|
||||
}
|
||||
}
|
||||
else if(evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())){
|
||||
// Technically this could be a case open event (and not the expected case close event) but
|
||||
// that would probably mean something bad is going on, and we'd still want to cancel
|
||||
// Image Writer.
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
private void startFinishImage(String dataSourceName){
|
||||
|
||||
synchronized(currentTasksLock){
|
||||
ImageWriter.this.imagesBeingFinished.add(image.getImageHandle());
|
||||
|
||||
if(doUI){
|
||||
if(isCancelled){
|
||||
progressUpdateTask.cancel(true);
|
||||
return;
|
||||
}
|
||||
ImageWriter.this.progressUpdaters.add(progressUpdateTask);
|
||||
ImageWriter.this.progressBars.add(progressHandle);
|
||||
|
||||
// If we've already started the finish process for this datasource, return.
|
||||
// Multiple DataSourceAnalysisCompletedEvent events can come from
|
||||
// the same image if more ingest modules are run later
|
||||
if(isStarted){
|
||||
return;
|
||||
} else {
|
||||
isStarted = true;
|
||||
}
|
||||
|
||||
Image image;
|
||||
try{
|
||||
image = Case.getCurrentCase().getSleuthkitCase().getImageById(dataSourceId);
|
||||
imageHandle = image.getImageHandle();
|
||||
} catch (TskCoreException ex){
|
||||
logger.log(Level.SEVERE, "Error loading image", ex);
|
||||
|
||||
// Stay subscribed to the events for now. Case close will clean everything up.
|
||||
return;
|
||||
}
|
||||
|
||||
logger.log(Level.INFO, String.format("Finishing VHD image for %s",
|
||||
dataSourceName)); //NON-NLS
|
||||
|
||||
if(doUI){
|
||||
periodicTasksExecutor = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("image-writer-progress-update-%d").build()); //NON-NLS
|
||||
progressHandle = ProgressHandle.createHandle("Image writer - " + dataSourceName);
|
||||
progressHandle.start(100);
|
||||
progressUpdateTask = periodicTasksExecutor.scheduleAtFixedRate(
|
||||
new ProgressUpdateTask(progressHandle, imageHandle), 0, 250, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
// The added complexity here with the Future is because we absolutely need to make sure
|
||||
// the call to finishImageWriter returns before allowing the TSK data structures to be freed
|
||||
// during case close.
|
||||
Future<?> finishTask = Executors.newSingleThreadExecutor().submit(() -> {
|
||||
numFinishJobsInProgress.incrementAndGet();
|
||||
finishTask = Executors.newSingleThreadExecutor().submit(() -> {
|
||||
try{
|
||||
SleuthkitJNI.finishImageWriter(image.getImageHandle());
|
||||
SleuthkitJNI.finishImageWriter(imageHandle);
|
||||
} catch (TskCoreException ex){
|
||||
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
|
||||
}
|
||||
});
|
||||
synchronized(currentTasksLock){
|
||||
ImageWriter.this.finishTasksInProgress.add(finishTask);
|
||||
}
|
||||
|
||||
// Wait for finishImageWriter to complete
|
||||
@ -155,84 +184,75 @@ public class ImageWriter {
|
||||
} catch (InterruptedException | ExecutionException ex){
|
||||
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
|
||||
}
|
||||
numFinishJobsInProgress.decrementAndGet();
|
||||
|
||||
synchronized(currentTasksLock){
|
||||
ImageWriter.this.finishTasksInProgress.remove(finishTask);
|
||||
ImageWriter.this.imagesBeingFinished.remove(image.getImageHandle());
|
||||
|
||||
unsubscribeFromEvents();
|
||||
if(doUI){
|
||||
// Some of these may be called twice if the user closes the case
|
||||
progressUpdateTask.cancel(true);
|
||||
ImageWriter.this.progressUpdaters.remove(progressUpdateTask);
|
||||
progressHandle.finish();
|
||||
ImageWriter.this.progressBars.remove(progressHandle);
|
||||
periodicTasksExecutor.shutdown();
|
||||
}
|
||||
isFinished = true;
|
||||
}
|
||||
|
||||
logger.log(Level.INFO, String.format("Finished writing VHD image for %s", event.getDataSource().getName())); //NON-NLS
|
||||
} catch (TskCoreException ex){
|
||||
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
|
||||
}
|
||||
}).start();
|
||||
} else {
|
||||
logger.log(Level.SEVERE, "DataSourceAnalysisCompletedEvent did not contain a dataSource object"); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
listenerStarted = true;
|
||||
logger.log(Level.INFO, String.format("Finished writing VHD image for %s", dataSourceName)); //NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a data source ID to the list of images to run finishImage on.
|
||||
* Also starts the listener if needed.
|
||||
* @param id The dataSource/Image ID
|
||||
* Tell the finishImage process to stop and wait for it to do so.
|
||||
*/
|
||||
public void addDataSourceId(Long id){
|
||||
startListener();
|
||||
synchronized(dataSourceIdsLock){
|
||||
dataSourceIds.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop any open progress update task, finish the progress bars, and tell
|
||||
* the finishImage process to stop
|
||||
*/
|
||||
public void close(){
|
||||
private void close(){
|
||||
synchronized(currentTasksLock){
|
||||
isCancelled = true;
|
||||
|
||||
for(ScheduledFuture<?> task:ImageWriter.this.progressUpdaters){
|
||||
task.cancel(true);
|
||||
unsubscribeFromEvents();
|
||||
|
||||
// The case either got closed during ingest (before the startFinishImage got called)
|
||||
// or an error occurred. If imageHandle is not null, we know that the first block of
|
||||
// startFinishImage() completed so all the tasks have also been initialized.
|
||||
if(imageHandle == null){
|
||||
return;
|
||||
}
|
||||
|
||||
for(Long handle:imagesBeingFinished){
|
||||
SleuthkitJNI.cancelFinishImage(handle);
|
||||
if(!isFinished){
|
||||
SleuthkitJNI.cancelFinishImage(imageHandle);
|
||||
logger.log(Level.SEVERE, "Case closed before VHD image could be finished"); //NON-NLS
|
||||
}
|
||||
|
||||
// Wait for all the finish tasks to end
|
||||
for(Future<?> task:ImageWriter.this.finishTasksInProgress){
|
||||
// Wait for the finish task to end
|
||||
try{
|
||||
task.get();
|
||||
finishTask.get();
|
||||
} catch (InterruptedException | ExecutionException ex){
|
||||
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
for(ProgressHandle progressHandle:ImageWriter.this.progressBars){
|
||||
// Stop the progress bar update task.
|
||||
// The thread from startFinishImage will also stop it
|
||||
// once the task completes, but we have to make absolutely sure
|
||||
// this gets done before the Sleuthkit data structures are freed.
|
||||
// Since we've stopped the update task, we'll stop the associated progress
|
||||
// bar now, too.
|
||||
progressUpdateTask.cancel(true);
|
||||
progressHandle.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of images currently being finished.
|
||||
* @return number of images in progress
|
||||
*/
|
||||
public static int numberOfJobsInProgress(){
|
||||
return numFinishJobsInProgress.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Task to query the Sleuthkit processing to get the percentage done.
|
||||
*/
|
||||
private final class ProgressUpdateTask implements Runnable {
|
||||
long imageHandle;
|
||||
ProgressHandle progressHandle;
|
||||
final long imageHandle;
|
||||
final ProgressHandle progressHandle;
|
||||
|
||||
ProgressUpdateTask(ProgressHandle progressHandle, long imageHandle){
|
||||
this.imageHandle = imageHandle;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -27,17 +27,13 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
|
||||
@ActionID(
|
||||
category = "Help",
|
||||
id = "org.sleuthkit.autopsy.diagnostics.PerformancePanelAction"
|
||||
)
|
||||
@ActionRegistration(
|
||||
displayName = "#CTL_PerformancePanelAction",
|
||||
lazy=true
|
||||
)
|
||||
@ActionID(category = "Help", id = "org.sleuthkit.autopsy.diagnostics.PerformancePanelAction")
|
||||
@ActionRegistration(displayName = "#CTL_PerformancePanelAction", lazy = true)
|
||||
@ActionReference(path = "Menu/Help", position = 1437)
|
||||
public final class PerformancePanelAction extends CallableSystemAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void performAction() {
|
||||
JDialog dialog = new PerformancePanel();
|
||||
@ -56,8 +52,9 @@ public final class PerformancePanelAction extends CallableSystemAction {
|
||||
|
||||
@Override
|
||||
public boolean asynchronous() {
|
||||
return false; // run on edt
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NbBundle.getMessage(PerformancePanelAction.class, "CTL_PerformancePanelAction");
|
||||
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 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 org.openide.explorer.ExplorerManager;
|
||||
import org.openide.nodes.FilterNode;
|
||||
import org.openide.nodes.Node;
|
||||
|
||||
/**
|
||||
* This class is used for the creation of all the children for the
|
||||
* DataResultFilterNode that created in the DataResultFilterNode.java.
|
||||
*
|
||||
*/
|
||||
class DataResultFilterChildren extends FilterNode.Children {
|
||||
|
||||
ExplorerManager sourceEm;
|
||||
|
||||
/**
|
||||
* the constructor
|
||||
*/
|
||||
public DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
|
||||
super(arg);
|
||||
this.sourceEm = sourceEm;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node copyNode(Node arg0) {
|
||||
return new DataResultFilterNode(arg0, sourceEm);
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,6 +23,8 @@ import java.beans.PropertyVetoException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.prefs.PreferenceChangeEvent;
|
||||
import java.util.prefs.PreferenceChangeListener;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
@ -33,6 +35,7 @@ import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType;
|
||||
@ -58,6 +61,7 @@ import org.sleuthkit.datamodel.File;
|
||||
import org.sleuthkit.datamodel.LayoutFile;
|
||||
import org.sleuthkit.datamodel.LocalFile;
|
||||
import org.sleuthkit.datamodel.SlackFile;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
|
||||
@ -67,11 +71,37 @@ import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
*/
|
||||
public class DataResultFilterNode extends FilterNode {
|
||||
|
||||
private ExplorerManager sourceEm;
|
||||
private static boolean filterKnownFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
|
||||
private static boolean filterKnownFromViews = UserPreferences.hideKnownFilesInViewsTree();
|
||||
private static boolean filterSlackFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree();
|
||||
private static boolean filterSlackFromViews = UserPreferences.hideSlackFilesInViewsTree();
|
||||
|
||||
private final DisplayableItemNodeVisitor<List<Action>> getActionsDIV;
|
||||
static {
|
||||
UserPreferences.addChangeListener(new PreferenceChangeListener() {
|
||||
@Override
|
||||
public void preferenceChange(PreferenceChangeEvent evt) {
|
||||
switch (evt.getKey()) {
|
||||
case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE:
|
||||
filterKnownFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
|
||||
break;
|
||||
case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE:
|
||||
filterKnownFromViews = UserPreferences.hideKnownFilesInViewsTree();
|
||||
break;
|
||||
case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SRCS_TREE:
|
||||
filterSlackFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree();
|
||||
break;
|
||||
case UserPreferences.HIDE_SLACK_FILES_IN_VIEWS_TREE:
|
||||
filterSlackFromViews = UserPreferences.hideSlackFilesInViewsTree();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final DisplayableItemNodeVisitor<AbstractAction> getPreferredActionsDIV;
|
||||
static private final DisplayableItemNodeVisitor<List<Action>> getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor();
|
||||
private final DisplayableItemNodeVisitor<AbstractAction> getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor();
|
||||
|
||||
private final ExplorerManager sourceEm;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -81,8 +111,17 @@ public class DataResultFilterNode extends FilterNode {
|
||||
public DataResultFilterNode(Node node, ExplorerManager em) {
|
||||
super(node, new DataResultFilterChildren(node, em));
|
||||
this.sourceEm = em;
|
||||
getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor();
|
||||
getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param node Root node to be passed to DataResult viewers
|
||||
* @param em ExplorerManager for component that is creating the node
|
||||
*/
|
||||
private DataResultFilterNode(Node node, ExplorerManager em, boolean filterKnown, boolean filterSlack) {
|
||||
super(node, new DataResultFilterChildren(node, em, filterKnown, filterSlack));
|
||||
this.sourceEm = em;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,6 +189,64 @@ public class DataResultFilterNode extends FilterNode {
|
||||
return propertySets;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used for the creation of all the children for the
|
||||
* DataResultFilterNode that created in the DataResultFilterNode.java.
|
||||
*
|
||||
*/
|
||||
private static class DataResultFilterChildren extends FilterNode.Children {
|
||||
|
||||
private final ExplorerManager sourceEm;
|
||||
|
||||
private boolean filterKnown;
|
||||
private boolean filterSlack;
|
||||
|
||||
/**
|
||||
* the constructor
|
||||
*/
|
||||
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
|
||||
super(arg);
|
||||
switch (SelectionContext.getSelectionContext(arg)) {
|
||||
case DATA_SOURCES:
|
||||
filterSlack = filterSlackFromDataSources;
|
||||
filterKnown = filterKnownFromDataSources;
|
||||
break;
|
||||
case VIEWS:
|
||||
filterSlack = filterSlackFromViews;
|
||||
filterKnown = filterKnownFromViews;
|
||||
break;
|
||||
default:
|
||||
filterSlack = false;
|
||||
filterKnown = false;
|
||||
break;
|
||||
}
|
||||
this.sourceEm = sourceEm;
|
||||
}
|
||||
|
||||
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm, boolean filterKnown, boolean filterSlack) {
|
||||
super(arg);
|
||||
this.filterKnown = filterKnown;
|
||||
this.filterSlack = filterSlack;
|
||||
this.sourceEm = sourceEm;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node[] createNodes(Node key) {
|
||||
AbstractFile file = key.getLookup().lookup(AbstractFile.class);
|
||||
if (file != null) {
|
||||
if (filterKnown && (file.getKnown() == TskData.FileKnown.KNOWN)) {
|
||||
// Filter out child nodes that represent known files
|
||||
return new Node[]{};
|
||||
}
|
||||
if (filterSlack && file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
|
||||
// Filter out child nodes that represent slack files
|
||||
return new Node[]{};
|
||||
}
|
||||
}
|
||||
return new Node[]{new DataResultFilterNode(key, sourceEm, filterKnown, filterSlack)};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the default nodes actions per node, adds some custom ones and
|
||||
* returns them per visited node type
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,12 +18,10 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.directorytree;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import org.openide.nodes.FilterNode;
|
||||
import org.openide.nodes.Node;
|
||||
@ -32,8 +30,7 @@ import org.openide.util.lookup.Lookups;
|
||||
import org.openide.util.lookup.ProxyLookup;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.AbstractContentNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||
import org.sleuthkit.autopsy.ingest.RunIngestModulesDialog;
|
||||
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.Directory;
|
||||
@ -42,86 +39,83 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* A node filter (decorator) that sets the actions for the nodes in the
|
||||
* directory tree and wraps the node children with a
|
||||
* DirectoryTreeFilterChildren.
|
||||
*/
|
||||
class DirectoryTreeFilterNode extends FilterNode {
|
||||
|
||||
private static final Action collapseAll = new CollapseAction(
|
||||
NbBundle.getMessage(DirectoryTreeFilterNode.class, "DirectoryTreeFilterNode.action.collapseAll.text"));
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DirectoryTreeFilterNode.class.getName());
|
||||
private static final Action collapseAllAction = new CollapseAction(NbBundle.getMessage(DirectoryTreeFilterNode.class, "DirectoryTreeFilterNode.action.collapseAll.text"));
|
||||
|
||||
/**
|
||||
* the constructor
|
||||
* A node filter (decorator) that sets the actions for the nodes in the
|
||||
* directory tree and wraps the node children with a
|
||||
* DirectoryTreeFilterChildren.
|
||||
*
|
||||
* @param nodeToWrap The node to wrap.
|
||||
* @param createChildren Whether to create the children of the wrapped node
|
||||
* or treat it a a leaf node.
|
||||
*/
|
||||
DirectoryTreeFilterNode(Node arg, boolean createChildren) {
|
||||
super(arg, DirectoryTreeFilterChildren.createInstance(arg, createChildren),
|
||||
new ProxyLookup(Lookups.singleton(new OriginalNode(arg)),
|
||||
arg.getLookup()));
|
||||
DirectoryTreeFilterNode(Node nodeToWrap, boolean createChildren) {
|
||||
super(nodeToWrap,
|
||||
DirectoryTreeFilterChildren.createInstance(nodeToWrap, createChildren),
|
||||
new ProxyLookup(Lookups.singleton(new OriginalNode(nodeToWrap)), nodeToWrap.getLookup()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the display name for the node, possibly including a child count in
|
||||
* parentheses.
|
||||
*
|
||||
* @return The display name for the node.
|
||||
*/
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
final Node orig = getOriginal();
|
||||
|
||||
String name = orig.getDisplayName();
|
||||
|
||||
//do not show children counts for non content nodes
|
||||
if (orig instanceof AbstractContentNode) {
|
||||
//show only for file content nodes
|
||||
AbstractFile file = getLookup().lookup(AbstractFile.class);
|
||||
if (file != null) {
|
||||
try {
|
||||
final int numChildren = file.getChildrenCount();
|
||||
/*
|
||||
* Left-to-right marks here are necessary to keep the count
|
||||
* and parens together for mixed right-to-left and
|
||||
* left-to-right names.
|
||||
*/
|
||||
name = name + " \u200E(\u200E" + numChildren + ")\u200E"; //NON-NLS
|
||||
|
||||
// left-to-right marks here are necessary to keep the count and parens together
|
||||
// for mixed right-to-left and left-to-right names
|
||||
name = name + " \u200E(\u200E" + numChildren + ")\u200E";
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting children count to display for file: " + file, ex); //NON-NLS
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Right click action for the nodes in the directory tree.
|
||||
* Gets the context mneu (right click menu) actions for the node.
|
||||
*
|
||||
* @param popup
|
||||
* @param context Whether to find actions for context meaning or for the
|
||||
* node itself.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Action[] getActions(boolean popup) {
|
||||
public Action[] getActions(boolean context) {
|
||||
List<Action> actions = new ArrayList<>();
|
||||
|
||||
final Content content = this.getLookup().lookup(Content.class);
|
||||
if (content != null) {
|
||||
actions.addAll(DirectoryTreeFilterNode.getDetailActions(content));
|
||||
actions.addAll(ExplorerNodeActionVisitor.getActions(content));
|
||||
|
||||
//extract dir action
|
||||
Directory dir = this.getLookup().lookup(Directory.class);
|
||||
if (dir != null) {
|
||||
actions.add(ExtractAction.getInstance());
|
||||
actions.add(new AbstractAction(
|
||||
NbBundle.getMessage(this.getClass(), "DirectoryTreeFilterNode.action.runIngestMods.text")) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog(dir);
|
||||
ingestDialog.display();
|
||||
}
|
||||
});
|
||||
actions.add(new RunIngestModulesAction(dir));
|
||||
}
|
||||
|
||||
final Image img = this.getLookup().lookup(Image.class);
|
||||
|
||||
VirtualDirectory virtualDirectory = this.getLookup().lookup(VirtualDirectory.class);
|
||||
// determine if the virtualDireory is at root-level (Logical File Set).
|
||||
final VirtualDirectory virtualDirectory = this.getLookup().lookup(VirtualDirectory.class);
|
||||
boolean isRootVD = false;
|
||||
if (virtualDirectory != null) {
|
||||
try {
|
||||
@ -132,48 +126,15 @@ class DirectoryTreeFilterNode extends FilterNode {
|
||||
logger.log(Level.WARNING, "Error determining the parent of the virtual directory", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
// 'run ingest' action and 'file search' action are added only if the
|
||||
// selected node is img node or a root level virtual directory.
|
||||
if (img != null || isRootVD) {
|
||||
actions.add(new FileSearchAction(
|
||||
NbBundle.getMessage(this.getClass(), "DirectoryTreeFilterNode.action.openFileSrcByAttr.text")));
|
||||
actions.add(new AbstractAction(
|
||||
NbBundle.getMessage(this.getClass(), "DirectoryTreeFilterNode.action.runIngestMods.text")) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog(Collections.<Content>singletonList(content));
|
||||
ingestDialog.display();
|
||||
}
|
||||
});
|
||||
actions.add(new FileSearchAction(NbBundle.getMessage(this.getClass(), "DirectoryTreeFilterNode.action.openFileSrcByAttr.text")));
|
||||
actions.add(new RunIngestModulesAction(Collections.<Content>singletonList(content)));
|
||||
}
|
||||
}
|
||||
|
||||
//check if delete actions should be added
|
||||
final Node orig = getOriginal();
|
||||
//TODO add a mechanism to determine if DisplayableItemNode
|
||||
if (orig instanceof DisplayableItemNode) {
|
||||
actions.addAll(getDeleteActions((DisplayableItemNode) orig));
|
||||
}
|
||||
|
||||
actions.add(collapseAll);
|
||||
actions.add(collapseAllAction);
|
||||
return actions.toArray(new Action[actions.size()]);
|
||||
}
|
||||
|
||||
private static List<Action> getDeleteActions(DisplayableItemNode original) {
|
||||
List<Action> actions = new ArrayList<>();
|
||||
//actions.addAll(original.accept(getDeleteActionVisitor));
|
||||
return actions;
|
||||
}
|
||||
|
||||
private static List<Action> getDetailActions(Content c) {
|
||||
List<Action> actions = new ArrayList<>();
|
||||
|
||||
actions.addAll(ExplorerNodeActionVisitor.getActions(c));
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
//FIXME: this seems like a big hack -jm
|
||||
public static class OriginalNode {
|
||||
|
||||
|
@ -37,9 +37,9 @@
|
||||
<Component id="backButton" min="-2" pref="26" max="-2" attributes="1"/>
|
||||
<Component id="showRejectedCheckBox" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" min="-2" pref="838" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="854" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.directorytree;
|
||||
|
||||
import org.sleuthkit.autopsy.datamodel.EmptyNode;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.EventQueue;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
@ -62,15 +61,14 @@ import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DataSources;
|
||||
import org.sleuthkit.autopsy.datamodel.DataSourcesNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||
import org.sleuthkit.autopsy.datamodel.EmptyNode;
|
||||
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
|
||||
import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType;
|
||||
import org.sleuthkit.autopsy.datamodel.KeywordHits;
|
||||
import org.sleuthkit.autopsy.datamodel.KnownFileFilterNode;
|
||||
import org.sleuthkit.autopsy.datamodel.Reports;
|
||||
import org.sleuthkit.autopsy.datamodel.Results;
|
||||
import org.sleuthkit.autopsy.datamodel.ResultsNode;
|
||||
import org.sleuthkit.autopsy.datamodel.RootContentChildren;
|
||||
import org.sleuthkit.autopsy.datamodel.SlackFileFilterNode;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||
import org.sleuthkit.autopsy.datamodel.Views;
|
||||
import org.sleuthkit.autopsy.datamodel.ViewsNode;
|
||||
@ -231,8 +229,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
.addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(showRejectedCheckBox))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 838, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 854, Short.MAX_VALUE)
|
||||
.addGap(0, 0, 0))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -297,6 +295,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
* only, i.e. deserialization routines; otherwise you could get a
|
||||
* non-deserialized instance. To obtain the singleton instance, use
|
||||
* {@link #findInstance}.
|
||||
*
|
||||
* @return instance - the default instance
|
||||
*/
|
||||
public static synchronized DirectoryTreeTopComponent getDefault() {
|
||||
if (instance == null) {
|
||||
@ -308,6 +308,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
/**
|
||||
* Obtain the DirectoryTreeTopComponent instance. Never call
|
||||
* {@link #getDefault} directly!
|
||||
*
|
||||
* @return getDefault() - the default instance
|
||||
*/
|
||||
public static synchronized DirectoryTreeTopComponent findInstance() {
|
||||
WindowManager winManager = WindowManager.getDefault();
|
||||
@ -349,13 +351,18 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
// change the cursor to "waiting cursor" for this operation
|
||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
try {
|
||||
if (Case.isCaseOpen()) {
|
||||
Case currentCase = Case.getCurrentCase();
|
||||
Case currentCase = null;
|
||||
try {
|
||||
currentCase = Case.getCurrentCase();
|
||||
} catch (IllegalStateException ex) {
|
||||
/*
|
||||
* No open case.
|
||||
*/
|
||||
}
|
||||
|
||||
// close the top component if there's no image in this case
|
||||
if (currentCase.hasData() == false) {
|
||||
//this.close();
|
||||
((BeanTreeView) this.jScrollPane1).setRootVisible(false); // hide the root
|
||||
if (null == currentCase || currentCase.hasData() == false) {
|
||||
((TreeView) this.jScrollPane1).setRootVisible(false); // hide the root
|
||||
} else {
|
||||
// if there's at least one image, load the image and open the top component
|
||||
List<Object> items = new ArrayList<>();
|
||||
@ -395,7 +402,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
em.setRootContext(root);
|
||||
em.getRootContext().setName(currentCase.getName());
|
||||
em.getRootContext().setDisplayName(currentCase.getName());
|
||||
((BeanTreeView) this.jScrollPane1).setRootVisible(false); // hide the root
|
||||
((TreeView) this.jScrollPane1).setRootVisible(false); // hide the root
|
||||
|
||||
// Reset the forward and back lists because we're resetting the root context
|
||||
resetHistory();
|
||||
@ -434,13 +441,12 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
if (childNodes.getNodesCount() > 0) {
|
||||
try {
|
||||
em.setSelectedNodes(new Node[]{childNodes.getNodeAt(0)});
|
||||
} catch (Exception ex) {
|
||||
} catch (PropertyVetoException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error setting default selected node.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.setCursor(null);
|
||||
}
|
||||
@ -490,7 +496,12 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
|
||||
@Override
|
||||
public boolean canClose() {
|
||||
return !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image in this case
|
||||
/*
|
||||
* Only allow the main tree view in the left side of the main window to
|
||||
* be closed if there is no opne case or the open case has no data
|
||||
* sources.
|
||||
*/
|
||||
return !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -536,7 +547,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
*/
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (RuntimeProperties.coreComponentsAreActive()) {
|
||||
if (RuntimeProperties.runningWithGUI()) {
|
||||
String changed = evt.getPropertyName();
|
||||
if (changed.equals(Case.Events.CURRENT_CASE.toString())) { // changed current case
|
||||
// When a case is closed, the old value of this property is the
|
||||
@ -643,22 +654,17 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
|
||||
//set node, wrap in filter node first to filter out children
|
||||
Node drfn = new DataResultFilterNode(originNode, DirectoryTreeTopComponent.this.em);
|
||||
Node kffn = new KnownFileFilterNode(drfn, KnownFileFilterNode.getSelectionContext(originNode));
|
||||
Node sffn = new SlackFileFilterNode(kffn, SlackFileFilterNode.getSelectionContext(originNode));
|
||||
|
||||
// Create a TableFilterNode with knowledge of the node's type to allow for column order settings
|
||||
if (FileTypesByMimeType.isEmptyMimeTypeNode(originNode)) {
|
||||
//Special case for when File Type Identification has not yet been run and
|
||||
//there are no mime types to populate Files by Mime Type Tree
|
||||
if (FileTypesByMimeType.isEmptyMimeTypeNode(originNode)) {
|
||||
EmptyNode emptyNode = new EmptyNode(Bundle.DirectoryTreeTopComponent_emptyMimeNode_text());
|
||||
Node emptyDrfn = new DataResultFilterNode(emptyNode, DirectoryTreeTopComponent.this.em);
|
||||
Node emptyKffn = new KnownFileFilterNode(emptyDrfn, KnownFileFilterNode.getSelectionContext(emptyNode));
|
||||
Node emptySffn = new SlackFileFilterNode(emptyKffn, SlackFileFilterNode.getSelectionContext(originNode));
|
||||
dataResult.setNode(new TableFilterNode(emptySffn, true, "This Node Is Empty")); //NON-NLS
|
||||
dataResult.setNode(new TableFilterNode(emptyNode, true, "This Node Is Empty")); //NON-NLS
|
||||
} else if (originNode instanceof DisplayableItemNode) {
|
||||
dataResult.setNode(new TableFilterNode(sffn, true, ((DisplayableItemNode) originNode).getItemType()));
|
||||
dataResult.setNode(new TableFilterNode(drfn, true, ((DisplayableItemNode) originNode).getItemType()));
|
||||
} else {
|
||||
dataResult.setNode(new TableFilterNode(sffn, true));
|
||||
dataResult.setNode(new TableFilterNode(drfn, true));
|
||||
}
|
||||
|
||||
String displayName = "";
|
||||
@ -667,7 +673,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
try {
|
||||
displayName = content.getUniquePath();
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: " + originNode); //NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: {0}", originNode); //NON-NLS
|
||||
}
|
||||
} else if (originNode.getLookup().lookup(String.class) != null) {
|
||||
displayName = originNode.getLookup().lookup(String.class);
|
||||
@ -799,7 +805,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
* Set the selected node using a path to a previously selected node.
|
||||
*
|
||||
* @param previouslySelectedNodePath Path to a previously selected node.
|
||||
* @param rootNodeName Name of the root node to match, may be null.
|
||||
* @param rootNodeName Name of the root node to match, may be
|
||||
* null.
|
||||
*/
|
||||
private void setSelectedNode(final String[] previouslySelectedNodePath, final String rootNodeName) {
|
||||
if (previouslySelectedNodePath == null) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -34,7 +34,7 @@ import org.openide.util.Lookup;
|
||||
iconBase = "org/sleuthkit/autopsy/directorytree/external-viewer-rules-32x32.png",
|
||||
keywords = "#OptionsCategory_Keywords_ExternalViewer",
|
||||
keywordsCategory = "ExternalViewer",
|
||||
position = 9
|
||||
position = 11
|
||||
)
|
||||
public final class ExternalViewerOptionsPanelController extends OptionsPanelController {
|
||||
|
||||
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 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 org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
import static org.sleuthkit.autopsy.directorytree.Bundle.*;
|
||||
|
||||
@NbBundle.Messages({"SelectionContext.dataSources=Data Sources",
|
||||
"SelectionContext.views=Views"})
|
||||
enum SelectionContext {
|
||||
DATA_SOURCES(SelectionContext_dataSources()),
|
||||
VIEWS(SelectionContext_views()),
|
||||
OTHER(""); // Subnode of another node.
|
||||
|
||||
private final String displayName;
|
||||
|
||||
private SelectionContext(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public static SelectionContext getContextFromName(String name) {
|
||||
if (name.equals(DATA_SOURCES.getName())) {
|
||||
return DATA_SOURCES;
|
||||
} else if (name.equals(VIEWS.getName())) {
|
||||
return VIEWS;
|
||||
} else {
|
||||
return OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
private String getName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selection context of a Node in the DirectoryTree.
|
||||
*
|
||||
* @param n
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static SelectionContext getSelectionContext(Node n) {
|
||||
if (n == null || n.getParentNode() == null) {
|
||||
// Parent of root node or root node. Occurs during case open / close.
|
||||
return SelectionContext.OTHER;
|
||||
} else if (n.getParentNode().getParentNode() == null) {
|
||||
// One level below root node. Should be one of DataSources, Views, or Results
|
||||
return SelectionContext.getContextFromName(n.getDisplayName());
|
||||
} else {
|
||||
return getSelectionContext(n.getParentNode());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -94,7 +94,7 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
|
||||
} catch (ParseException ex) {
|
||||
// for now, no need to show the error message to the user here
|
||||
}
|
||||
if (!startDateValue.equals("")) {
|
||||
if (!startDateValue.isEmpty()) {
|
||||
if (startDate != null) {
|
||||
fromDate = startDate.getTimeInMillis() / 1000; // divided by 1000 because we want to get the seconds, not miliseconds
|
||||
}
|
||||
@ -114,7 +114,7 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
|
||||
} catch (ParseException ex) {
|
||||
// for now, no need to show the error message to the user here
|
||||
}
|
||||
if (!endDateValue.equals("")) {
|
||||
if (!endDateValue.isEmpty()) {
|
||||
if (endDate != null) {
|
||||
toDate = endDate.getTimeInMillis() / 1000; // divided by 1000 because we want to get the seconds, not miliseconds
|
||||
}
|
||||
@ -166,7 +166,7 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
|
||||
|
||||
List<String> timeZones = new ArrayList<>();
|
||||
|
||||
if (Case.isCaseOpen()) {
|
||||
try {
|
||||
// get the latest case
|
||||
Case currentCase = Case.getCurrentCase(); // get the most updated case
|
||||
|
||||
@ -195,6 +195,8 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
|
||||
String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id); //NON-NLS
|
||||
timeZones.add(item);
|
||||
}
|
||||
} catch (IllegalStateException ex) {
|
||||
// No current case.
|
||||
}
|
||||
|
||||
return timeZones;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -29,14 +29,13 @@ import org.sleuthkit.autopsy.directorytree.FileSearchProvider;
|
||||
|
||||
final class FileSearchAction extends CallableSystemAction implements FileSearchProvider {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static FileSearchAction instance = null;
|
||||
|
||||
FileSearchAction() {
|
||||
super();
|
||||
setEnabled(Case.isCaseOpen()); //no guarantee listener executed, so check here
|
||||
|
||||
setEnabled(Case.isCaseOpen());
|
||||
Case.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
|
@ -16,9 +16,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.corecomponentinterfaces;
|
||||
package org.sleuthkit.autopsy.framework;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
||||
|
||||
/**
|
||||
* Interface implemented by DataSourceProcessors in order to be supported by
|
171
Core/src/org/sleuthkit/autopsy/framework/AutopsyService.java
Normal file
171
Core/src/org/sleuthkit/autopsy/framework/AutopsyService.java
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.framework;
|
||||
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
|
||||
/**
|
||||
* An interface for services that report status and may manage case and
|
||||
* application resources such a text index, a database, etc. A service provider
|
||||
* may have resources of both types, of only one type, or no resources at all.
|
||||
*/
|
||||
public interface AutopsyService {
|
||||
|
||||
/**
|
||||
* Gets the service name.
|
||||
*
|
||||
* @return The service name.
|
||||
*/
|
||||
String getServiceName();
|
||||
|
||||
// Status getStatus() {
|
||||
//
|
||||
// }
|
||||
// default void openAppResources(ApplicationContext context) throws AutopsyServiceException {
|
||||
// /*
|
||||
// * Autopsy services may not have application-level resources.
|
||||
// */
|
||||
// }
|
||||
/**
|
||||
* Creates, opens or upgrades any case-level resources managed by the
|
||||
* service.
|
||||
*
|
||||
* @param context The case context which includes things such as the case, a
|
||||
* progress indicator for the operation, a cancellation
|
||||
* request flag, etc.
|
||||
* @throws org.sleuthkit.autopsy.framework.AutopsyService.AutopsyServiceException
|
||||
*/
|
||||
default void openCaseResources(CaseContext context) throws AutopsyServiceException {
|
||||
/*
|
||||
* Autopsy services may not have case-level resources.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes any case-level resources managed by the service.
|
||||
*
|
||||
* @param context The case context which includes things such as the case, a
|
||||
* progress indicator for the operation, a cancellation
|
||||
* request flag, etc.
|
||||
* @throws org.sleuthkit.autopsy.framework.AutopsyService.AutopsyServiceException
|
||||
*/
|
||||
default void closeCaseResources(CaseContext context) throws AutopsyServiceException {
|
||||
/*
|
||||
* Autopsy services may not have case-level resources.
|
||||
*/
|
||||
}
|
||||
|
||||
// default void closeAppResources(ApplicationContext context) throws AutopsyServiceException {
|
||||
// /*
|
||||
// * Autopsy services may not have case-level resources.
|
||||
// */
|
||||
// }
|
||||
/**
|
||||
* The context for the creation/opening/upgrading of case-level resources by
|
||||
* a service.
|
||||
*/
|
||||
public static class CaseContext {
|
||||
|
||||
private final Case theCase;
|
||||
private final ProgressIndicator progressIndicator;
|
||||
private volatile boolean cancelRequested;
|
||||
|
||||
/**
|
||||
* Constructs the context for the creation/opening/upgrading of
|
||||
* case-level resources by a service.
|
||||
*
|
||||
* @param theCase The case.
|
||||
* @param progressIndicator A progress indicator for the opening of the
|
||||
* case-level resources
|
||||
*/
|
||||
public CaseContext(Case theCase, ProgressIndicator progressIndicator) {
|
||||
this.theCase = theCase;
|
||||
this.progressIndicator = progressIndicator;
|
||||
this.cancelRequested = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the case for the creation/opening/upgrading of case-level
|
||||
* resources by a service.
|
||||
*
|
||||
* @return The case.
|
||||
*/
|
||||
public Case getCase() {
|
||||
return this.theCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the progress indicator for the creation/opening/upgrading of
|
||||
* case-level resources by a service.
|
||||
*
|
||||
* @return The progress indicator.
|
||||
*/
|
||||
public ProgressIndicator getProgressIndicator() {
|
||||
return this.progressIndicator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests cancellation of the creation/opening/upgrading of case-level
|
||||
* resources by a service. The request is not guaranteed to be honored.
|
||||
*/
|
||||
public void requestCancel() {
|
||||
this.cancelRequested = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not cancellation of the
|
||||
* creation/opening/upgrading of case-level resources by a service has
|
||||
* been requested.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
public boolean cancelRequested() {
|
||||
return this.cancelRequested;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown by autopsy service methods.
|
||||
*/
|
||||
public static class AutopsyServiceException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructs an exception to be thrown by an autopsy service provider
|
||||
* method.
|
||||
*
|
||||
* @param message Exception message.
|
||||
*/
|
||||
public AutopsyServiceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an exception to be thrown by an autopsy service provider
|
||||
* method.
|
||||
*
|
||||
* @param message Exception message.
|
||||
* @param cause Exception cause.
|
||||
*/
|
||||
public AutopsyServiceException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
# To change this license header, choose License Headers in Project Properties.
|
||||
# To change this template file, choose Tools | Templates
|
||||
# and open the template in the editor.
|
||||
|
||||
ProgressPanel.progressMessage.text=Message
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 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.framework;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* A progress indicator that writes progress to the Autopsy application log.
|
||||
*/
|
||||
public final class LoggingProgressIndicator implements ProgressIndicator {
|
||||
|
||||
private final Logger LOGGER = Logger.getLogger(LoggingProgressIndicator.class.getName());
|
||||
private int totalWorkUnits;
|
||||
|
||||
@Override
|
||||
public void start(String message, int totalWorkUnits) {
|
||||
this.totalWorkUnits = totalWorkUnits;
|
||||
LOGGER.log(Level.INFO, "{0} started, {1} total work units", new Object[]{message, this.totalWorkUnits});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(String message) {
|
||||
LOGGER.log(Level.INFO, "{0}", message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void switchToIndeterminate(String message) {
|
||||
this.totalWorkUnits = 0;
|
||||
LOGGER.log(Level.INFO, "{0}", message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void switchToDeterminate(String message, int workUnitsCompleted, int totalWorkUnits) {
|
||||
this.totalWorkUnits = totalWorkUnits;
|
||||
LOGGER.log(Level.INFO, "{0}, {1} of {2} total work units completed", new Object[]{message, workUnitsCompleted, this.totalWorkUnits});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void progress(String message) {
|
||||
LOGGER.log(Level.INFO, "{0}", message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void progress(int workUnitsCompleted) {
|
||||
LOGGER.log(Level.INFO, "{1} of {2} total work units completed", new Object[]{workUnitsCompleted, this.totalWorkUnits});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void progress(String message, int workUnitsCompleted) {
|
||||
LOGGER.log(Level.INFO, "{0}, {1} of {2} total work units completed", new Object[]{message, workUnitsCompleted, this.totalWorkUnits});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(String message) {
|
||||
LOGGER.log(Level.INFO, "{0} finished", message);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 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.framework;
|
||||
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Frame;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.DialogDescriptor;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.util.HelpCtx;
|
||||
|
||||
/**
|
||||
* A progress indicator that displays progress using a modal dialog with a
|
||||
* message label, a progress bar, and optionally, a configurable set of buttons
|
||||
* with a button listener.
|
||||
*/
|
||||
public final class ModalDialogProgressIndicator implements ProgressIndicator {
|
||||
|
||||
private final Frame parent;
|
||||
private final ProgressPanel progressPanel;
|
||||
private final Dialog dialog;
|
||||
private final ActionListener buttonListener;
|
||||
|
||||
/**
|
||||
* Creates a progress indicator that displays progress using a modal dialog
|
||||
* with a message label, a progress bar with a configurable set of buttons
|
||||
* with a button listener.
|
||||
*
|
||||
* @param parent The parent frame.
|
||||
* @param title The title for the dialog.
|
||||
* @param buttonLabels The labels for the desired buttons.
|
||||
* @param focusedButtonLabel The label of the button that should have
|
||||
* initial focus.
|
||||
* @param buttonListener An ActionListener for the buttons.
|
||||
*/
|
||||
public ModalDialogProgressIndicator(Frame parent, String title, Object[] buttonLabels, Object focusedButtonLabel, ActionListener buttonListener) {
|
||||
this.parent = parent;
|
||||
progressPanel = new ProgressPanel();
|
||||
DialogDescriptor dialogDescriptor = new DialogDescriptor(
|
||||
progressPanel,
|
||||
title,
|
||||
true,
|
||||
buttonLabels,
|
||||
focusedButtonLabel,
|
||||
DialogDescriptor.BOTTOM_ALIGN,
|
||||
HelpCtx.DEFAULT_HELP,
|
||||
buttonListener);
|
||||
dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor);
|
||||
this.buttonListener = buttonListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a progress indicator that displays progress using a modal dialog
|
||||
* with a message label and a progress bar with no buttons.
|
||||
*
|
||||
* @param parent The parent frame.
|
||||
* @param title The title for the dialog.
|
||||
*/
|
||||
public ModalDialogProgressIndicator(Frame parent, String title) {
|
||||
this.parent = parent;
|
||||
progressPanel = new ProgressPanel();
|
||||
dialog = new JDialog(parent, title, true);
|
||||
dialog.add(progressPanel);
|
||||
dialog.pack();
|
||||
buttonListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls setVisible on the underlying modal dialog.
|
||||
*
|
||||
* @param isVisible True or false.
|
||||
*/
|
||||
public void setVisible(boolean isVisible) {
|
||||
if (isVisible) {
|
||||
dialog.setLocationRelativeTo(parent);
|
||||
}
|
||||
this.dialog.setVisible(isVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the button listener for the dialog, if there is one.
|
||||
*
|
||||
* @return The button listener or null.
|
||||
*/
|
||||
public ActionListener getButtonListener() {
|
||||
return buttonListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the progress indicator in determinate mode (the total number of
|
||||
* work units to be completed is known).
|
||||
*
|
||||
* @param message The initial progress message.
|
||||
* @param totalWorkUnits The total number of work units.
|
||||
*/
|
||||
@Override
|
||||
public void start(String message, int totalWorkUnits) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setInderminate(false);
|
||||
progressPanel.setMessage(message);
|
||||
progressPanel.setMaximum(totalWorkUnits);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the progress indicator in indeterminate mode (the total number of
|
||||
* work units to be completed is unknown).
|
||||
*
|
||||
* @param message The initial progress message.
|
||||
*/
|
||||
@Override
|
||||
public void start(String message) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setInderminate(true);
|
||||
progressPanel.setMessage(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the progress indicator to indeterminate mode (the total number
|
||||
* of work units to be completed is unknown).
|
||||
*
|
||||
* @param message The initial progress message.
|
||||
*/
|
||||
@Override
|
||||
public void switchToIndeterminate(String message) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setInderminate(true);
|
||||
progressPanel.setMessage(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the progress indicator to determinate mode (the total number of
|
||||
* work units to be completed is known).
|
||||
*
|
||||
* @param message The initial progress message.
|
||||
* @param workUnitsCompleted The number of work units completed so far.
|
||||
* @param totalWorkUnits The total number of work units to be completed.
|
||||
*/
|
||||
@Override
|
||||
public void switchToDeterminate(String message, int workUnitsCompleted, int totalWorkUnits) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setInderminate(false);
|
||||
progressPanel.setMessage(message);
|
||||
progressPanel.setMaximum(totalWorkUnits);
|
||||
progressPanel.setCurrent(workUnitsCompleted);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the progress indicator with a progress message.
|
||||
*
|
||||
* @param message The progress message.
|
||||
*/
|
||||
@Override
|
||||
public void progress(String message) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setMessage(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the progress indicator with the number of work units completed so
|
||||
* far when in determinate mode (the total number of work units to be
|
||||
* completed is known).
|
||||
*
|
||||
* @param workUnitsCompleted Number of work units completed so far.
|
||||
*/
|
||||
@Override
|
||||
public void progress(int workUnitsCompleted) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setCurrent(workUnitsCompleted);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the progress indicator with a progress message and the number of
|
||||
* work units completed so far when in determinate mode (the total number of
|
||||
* work units to be completed is known).
|
||||
*
|
||||
* @param message The progress message.
|
||||
* @param workUnitsCompleted Number of work units completed so far.
|
||||
*/
|
||||
@Override
|
||||
public void progress(String message, int workUnitsCompleted) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setMessage(message);
|
||||
progressPanel.setCurrent(workUnitsCompleted);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the progress indicator when the task is completed.
|
||||
*
|
||||
* @param message The finished message.
|
||||
*/
|
||||
@Override
|
||||
public void finish(String message) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setMessage(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 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.framework;
|
||||
|
||||
/**
|
||||
* An interface for progress indicators. A progress indicator can run in
|
||||
* determinate mode (the total number of work units to be completed is known) or
|
||||
* indeterminate mode. Switching back and forth between the two modes is
|
||||
* supported. Starting, finishing, and starting again is supported.
|
||||
*/
|
||||
public interface ProgressIndicator {
|
||||
|
||||
/**
|
||||
* Starts the progress indicator in determinate mode (the total number of
|
||||
* work units to be completed is known).
|
||||
*
|
||||
* @param message The initial progress message.
|
||||
* @param totalWorkUnits The total number of work units.
|
||||
*/
|
||||
void start(String message, int totalWorkUnits);
|
||||
|
||||
/**
|
||||
* Starts the progress indicator in indeterminate mode (the total number of
|
||||
* work units to be completed is unknown).
|
||||
*
|
||||
* @param message The initial progress message.
|
||||
*/
|
||||
void start(String message);
|
||||
|
||||
/**
|
||||
* Switches the progress indicator to indeterminate mode (the total number
|
||||
* of work units to be completed is unknown).
|
||||
* @param message The initial progress message.
|
||||
*/
|
||||
public void switchToIndeterminate(String message);
|
||||
|
||||
/**
|
||||
* Switches the progress indicator to determinate mode (the total number of
|
||||
* work units to be completed is known).
|
||||
*
|
||||
* @param message The initial progress message.
|
||||
* @param workUnitsCompleted The number of work units completed so far.
|
||||
* @param totalWorkUnits The total number of work units to be completed.
|
||||
*/
|
||||
public void switchToDeterminate(String message, int workUnitsCompleted, int totalWorkUnits);
|
||||
|
||||
/**
|
||||
* Updates the progress indicator with a progress message.
|
||||
*
|
||||
* @param message The progress message.
|
||||
*/
|
||||
public void progress(String message);
|
||||
|
||||
/**
|
||||
* Updates the progress indicator with the number of work units completed so
|
||||
* far when in determinate mode (the total number of work units to be
|
||||
* completed is known).
|
||||
*
|
||||
* @param workUnitsCompleted Number of work units completed so far.
|
||||
*/
|
||||
public void progress(int workUnitsCompleted);
|
||||
|
||||
/**
|
||||
* Updates the progress indicator with a progress message and the number of
|
||||
* work units completed so far when in determinate mode (the total number of
|
||||
* work units to be completed is known).
|
||||
*
|
||||
* @param message The progress message.
|
||||
* @param workUnitsCompleted Number of work units completed so far.
|
||||
*/
|
||||
public void progress(String message, int workUnitsCompleted);
|
||||
|
||||
/**
|
||||
* Finishes the progress indicator when the task is completed.
|
||||
*
|
||||
* @param message The finished message.
|
||||
*/
|
||||
void finish(String message);
|
||||
|
||||
}
|
52
Core/src/org/sleuthkit/autopsy/framework/ProgressPanel.form
Normal file
52
Core/src/org/sleuthkit/autopsy/framework/ProgressPanel.form
Normal file
@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="22" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="progressMessage" max="32767" attributes="0"/>
|
||||
<Component id="progressBar" pref="355" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="23" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="24" max="-2" attributes="0"/>
|
||||
<Component id="progressMessage" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="progressBar" min="-2" pref="32" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="33" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="progressMessage">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/framework/Bundle.properties" key="ProgressPanel.progressMessage.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JProgressBar" name="progressBar">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
90
Core/src/org/sleuthkit/autopsy/framework/ProgressPanel.java
Normal file
90
Core/src/org/sleuthkit/autopsy/framework/ProgressPanel.java
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 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.framework;
|
||||
|
||||
/**
|
||||
* A progress panel consisting of a message label and a progress bar.
|
||||
*/
|
||||
class ProgressPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
ProgressPanel() {
|
||||
initComponents();
|
||||
this.progressBar.setMinimum(0);
|
||||
}
|
||||
|
||||
void setMessage(String message) {
|
||||
this.progressMessage.setText(message);
|
||||
}
|
||||
|
||||
void setInderminate(boolean indeterminate) {
|
||||
this.progressBar.setIndeterminate(indeterminate);
|
||||
}
|
||||
|
||||
void setMaximum(int max) {
|
||||
this.progressBar.setMaximum(max);
|
||||
}
|
||||
|
||||
void setCurrent(int current) {
|
||||
this.progressBar.setValue(current);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
progressMessage = new javax.swing.JLabel();
|
||||
progressBar = new javax.swing.JProgressBar();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(progressMessage, org.openide.util.NbBundle.getMessage(ProgressPanel.class, "ProgressPanel.progressMessage.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(22, 22, 22)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(progressMessage, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, 355, Short.MAX_VALUE))
|
||||
.addContainerGap(23, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(24, 24, 24)
|
||||
.addComponent(progressMessage)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(33, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JProgressBar progressBar;
|
||||
private javax.swing.JLabel progressMessage;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 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.framework;
|
||||
|
||||
import org.sleuthkit.autopsy.framework.ProgressIndicator;
|
||||
|
||||
/**
|
||||
* A "silent" or "null" progress indicator.
|
||||
*/
|
||||
public class SilentProgressIndicator implements ProgressIndicator {
|
||||
|
||||
@Override
|
||||
public void start(String message, int totalWorkUnits) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(String message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void switchToIndeterminate(String message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void switchToDeterminate(String message, int workUnitsCompleted, int totalWorkUnits) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void progress(String message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void progress(int workUnitsCompleted) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void progress(String message, int workUnitsCompleted) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(String message) {
|
||||
}
|
||||
|
||||
}
|
BIN
Core/src/org/sleuthkit/autopsy/images/export16.png
Normal file
BIN
Core/src/org/sleuthkit/autopsy/images/export16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
Core/src/org/sleuthkit/autopsy/images/import16.png
Normal file
BIN
Core/src/org/sleuthkit/autopsy/images/import16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
Core/src/org/sleuthkit/autopsy/images/new16.png
Normal file
BIN
Core/src/org/sleuthkit/autopsy/images/new16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
@ -23,7 +23,6 @@ IngestJob.progress.fileIngest.displayName=Analyzing files from {0}
|
||||
IngestJob.progress.fileIngest.cancelMessage=Waiting for {0} on {1}
|
||||
IngestJob.progress.cancelling={0} (Cancelling...)
|
||||
IngestJob.cancellationDialog.title=Cancel Ingest
|
||||
IngestDialog.title.text=Run Ingest Modules
|
||||
IngestDialog.startButton.title=Start
|
||||
IngestDialog.closeButton.title=Close
|
||||
IngestManager.moduleErr=Module Error
|
||||
@ -114,3 +113,13 @@ IngestJobSettingsPanel.globalSettingsButton.actionCommand=Advanced
|
||||
IngestJobSettingsPanel.globalSettingsButton.text=Global Settings
|
||||
IngestJobSettingsPanel.pastJobsButton.text=History
|
||||
IngestJobSettingsPanel.fileIngestFilterLabel.text=Run ingest modules on:
|
||||
OptionsCategory_Name_IngestOptions=Ingest
|
||||
OptionsCategory_Keywords_IngestOptions=Ingest
|
||||
IngestSettingsPanel.jLabelProcessTimeOutUnits.text=hour(s)
|
||||
IngestSettingsPanel.jFormattedTextFieldProcTimeOutHrs.text=60
|
||||
IngestSettingsPanel.jCheckBoxEnableProcTimeout.text=
|
||||
IngestSettingsPanel.jLabelSetProcessTimeOut.text=Enable timeout to allow modules to automatically terminate after a set amount of time:
|
||||
IngestSettingsPanel.restartRequiredLabel.text=For this computer, a maximum of {0} file ingest threads should be used. Application restart required to take effect.
|
||||
IngestSettingsPanel.jLabelNumThreads.text=Number of threads to use for file ingest:
|
||||
IngestSettingsPanel.ingestWarningLabel.text=Ingest is ongoing, some settings will be unavailable until it finishes.
|
||||
ProfileSettingsPanel.ingestWarningLabel.text=Ingest is ongoing, some settings will be unavailable until it finishes.
|
||||
|
@ -2,7 +2,6 @@ CTL_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8
|
||||
HINT_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8\u30a6\u30a3\u30f3\u30c9\u30a6
|
||||
IngestDialog.closeButton.title=\u9589\u3058\u308b
|
||||
IngestDialog.startButton.title=\u958b\u59cb
|
||||
IngestDialog.title.text=\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8
|
||||
IngestJob.progress.cancelling={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09
|
||||
IngestJob.progress.dataSourceIngest.displayName={1}\u306e{0}
|
||||
IngestJob.progress.fileIngest.displayName={0}\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u4e2d
|
||||
@ -111,3 +110,9 @@ IngestJob.cancelReason.outOfDiskSpace.text=\u30c7\u30a3\u30b9\u30af\u30b9\u30da\
|
||||
IngestJob.cancelReason.caseClosed.text=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u307e\u3057\u305f
|
||||
IngestJobSettingsPanel.globalSettingsButton.actionCommand=\u30a2\u30c9\u30d0\u30f3\u30b9
|
||||
IngestJobSettingsPanel.globalSettingsButton.text=\u30a2\u30c9\u30d0\u30f3\u30b9
|
||||
IngestSettingsPanel.jLabelNumThreads.text=\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306b\u4f7f\u7528\u3059\u308b\u30b9\u30ec\u30c3\u30c9\u6570\uff1a
|
||||
IngestSettingsPanel.jLabelProcessTimeOutUnits.text=\u6642\u9593
|
||||
IngestSettingsPanel.jLabelSetProcessTimeOut.text=\u4e00\u5b9a\u306e\u6642\u9593\u304c\u904e\u304e\u305f\u5f8c\u306b\u81ea\u52d5\u7684\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u505c\u6b62\u3067\u304d\u308b\u3088\u3046\u306b\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u3092\u6709\u52b9\u5316\uff1a
|
||||
IngestSettingsPanel.restartRequiredLabel.text=\u3053\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u30fc\u3067\u306f\u6700\u5927{0}\u306e\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b9\u30ec\u30c3\u30c9\u3092\u4f7f\u7528\u3059\u3079\u304d\u3067\u3059\u3002\u6709\u52b9\u306b\u3059\u308b\u306b\u306f\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u3067\u3059\u3002
|
||||
IngestSettingsPanel.ingestWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u3067\u3059\u3002\u5b8c\u4e86\u3059\u308b\u307e\u3067\u4e00\u90e8\u306e\u8a2d\u5b9a\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002
|
||||
ProfileSettingsPanel.ingestWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u3067\u3059\u3002\u5b8c\u4e86\u3059\u308b\u307e\u3067\u4e00\u90e8\u306e\u8a2d\u5b9a\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -52,13 +52,13 @@ public class IngestJobSettings {
|
||||
|
||||
private static final String ENABLED_MODULES_KEY = "Enabled_Ingest_Modules"; //NON-NLS
|
||||
private static final String DISABLED_MODULES_KEY = "Disabled_Ingest_Modules"; //NON-NLS
|
||||
private static final String LAST_FILE_INGEST_FILTER_KEY = "Last_File_Ingest_Filter";
|
||||
private static final String LAST_FILE_INGEST_FILTER_KEY = "Last_File_Ingest_Filter"; //NON-NLS
|
||||
private static final String MODULE_SETTINGS_FOLDER = "IngestModuleSettings"; //NON-NLS
|
||||
private static final String MODULE_SETTINGS_FOLDER_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), IngestJobSettings.MODULE_SETTINGS_FOLDER).toAbsolutePath().toString();
|
||||
private static final String MODULE_SETTINGS_FILE_EXT = ".settings"; //NON-NLS
|
||||
private static final Logger LOGGER = Logger.getLogger(IngestJobSettings.class.getName());
|
||||
private FilesSet fileIngestFilter;
|
||||
private final String executionContext;
|
||||
private String executionContext;
|
||||
private final IngestType ingestType;
|
||||
private String moduleSettingsFolderPath;
|
||||
private static final CharSequence pythonModuleSettingsPrefixCS = "org.python.proxies.".subSequence(0, "org.python.proxies.".length() - 1); //NON-NLS
|
||||
@ -66,9 +66,9 @@ public class IngestJobSettings {
|
||||
private final List<String> warnings;
|
||||
|
||||
/**
|
||||
* Gets the last selected FileIngestFilter saved in settings which is represented
|
||||
* by a FilesSet, if the last selected filter is null
|
||||
* the default filter will be returned.
|
||||
* Gets the last selected FileIngestFilter saved in settings which is
|
||||
* represented by a FilesSet, if the last selected filter is null the
|
||||
* default filter will be returned.
|
||||
*
|
||||
* @return FilesSet which represents the FileIngestFilter
|
||||
*/
|
||||
@ -111,7 +111,7 @@ public class IngestJobSettings {
|
||||
/**
|
||||
* Constructs an ingest job settings object for a given execution context.
|
||||
* Examples of execution contexts include the add data source wizard and the
|
||||
* run ingest modules dialog. Different execution conterxts may have
|
||||
* run ingest modules dialog. Different execution contexts may have
|
||||
* different ingest job settings.
|
||||
*
|
||||
* @param executionContext The ingest execution context identifier.
|
||||
@ -128,7 +128,7 @@ public class IngestJobSettings {
|
||||
/**
|
||||
* Constructs an ingest job settings object for a given context. Examples of
|
||||
* execution contexts include the add data source wizard and the run ingest
|
||||
* modules dialog. Different execution conterxts may have different ingest
|
||||
* modules dialog. Different execution contexts may have different ingest
|
||||
* job settings.
|
||||
*
|
||||
* @param context The context identifier string.
|
||||
@ -157,10 +157,23 @@ public class IngestJobSettings {
|
||||
this.store();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the settings with a new context name removing the old profile
|
||||
* folder
|
||||
*
|
||||
* @param executionContext will be used to name the new folder for storing
|
||||
* the settings
|
||||
*/
|
||||
void saveAs(String executionContext) {
|
||||
this.executionContext = executionContext;
|
||||
this.createSavedModuleSettingsFolder();
|
||||
this.store();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ingest execution context identifier. Examples of execution
|
||||
* contexts include the add data source wizard and the run ingest modules
|
||||
* dialog. Different execution conterxts may have different ingest job
|
||||
* dialog. Different execution contexts may have different ingest job
|
||||
* settings.
|
||||
*
|
||||
* @return The execution context identifier.
|
||||
@ -246,6 +259,18 @@ public class IngestJobSettings {
|
||||
return Paths.get(IngestJobSettings.MODULE_SETTINGS_FOLDER_PATH, executionContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the ingest module settings folder from a static
|
||||
* manner.
|
||||
*
|
||||
* @param context specify the context of the folder you wish to get
|
||||
*
|
||||
* @return path to the module settings folder
|
||||
*/
|
||||
static Path getSavedModuleSettingsFolder(String context) {
|
||||
return Paths.get(IngestJobSettings.MODULE_SETTINGS_FOLDER_PATH, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the folder for saving the individual ingest module settings part
|
||||
* of these ingest job settings.
|
||||
@ -292,8 +317,8 @@ public class IngestJobSettings {
|
||||
* Get the enabled/disabled ingest modules settings for this context. By
|
||||
* default, all loaded modules are enabled.
|
||||
*/
|
||||
HashSet<String> enabledModuleNames = getModulesNamesFromSetting(IngestJobSettings.ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(loadedModuleNames));
|
||||
HashSet<String> disabledModuleNames = getModulesNamesFromSetting(IngestJobSettings.DISABLED_MODULES_KEY, ""); //NON-NLS
|
||||
HashSet<String> enabledModuleNames = getModulesNamesFromSetting(executionContext, IngestJobSettings.ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(loadedModuleNames));
|
||||
HashSet<String> disabledModuleNames = getModulesNamesFromSetting(executionContext, IngestJobSettings.DISABLED_MODULES_KEY, ""); //NON-NLS
|
||||
|
||||
/**
|
||||
* Check for missing modules and create warnings if any are found.
|
||||
@ -373,12 +398,12 @@ public class IngestJobSettings {
|
||||
*
|
||||
* @return The list of module names associated with the key.
|
||||
*/
|
||||
private HashSet<String> getModulesNamesFromSetting(String key, String defaultSetting) {
|
||||
if (ModuleSettings.settingExists(this.executionContext, key) == false) {
|
||||
ModuleSettings.setConfigSetting(this.executionContext, key, defaultSetting);
|
||||
private static HashSet<String> getModulesNamesFromSetting(String context, String key, String defaultSetting) {
|
||||
if (ModuleSettings.settingExists(context, key) == false) {
|
||||
ModuleSettings.setConfigSetting(context, key, defaultSetting);
|
||||
}
|
||||
HashSet<String> moduleNames = new HashSet<>();
|
||||
String modulesSetting = ModuleSettings.getConfigSetting(this.executionContext, key);
|
||||
String modulesSetting = ModuleSettings.getConfigSetting(context, key);
|
||||
if (!modulesSetting.isEmpty()) {
|
||||
String[] settingNames = modulesSetting.split(", ");
|
||||
for (String name : settingNames) {
|
||||
@ -406,6 +431,18 @@ public class IngestJobSettings {
|
||||
return moduleNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set which contains all the names of enabled modules for the
|
||||
* specified context.
|
||||
*
|
||||
* @param context -the execution context (profile name) to check
|
||||
*
|
||||
* @return the names of the enabled modules
|
||||
*/
|
||||
static List<String> getEnabledModules(String context) {
|
||||
return new ArrayList<>(getModulesNamesFromSetting(context, ENABLED_MODULES_KEY, ""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the moduleSettingsFilePath is that of a serialized jython
|
||||
* instance. Serialized Jython instances (settings saved on the disk)
|
||||
@ -489,8 +526,8 @@ public class IngestJobSettings {
|
||||
disabledModuleNames.add(moduleName);
|
||||
}
|
||||
}
|
||||
ModuleSettings.setConfigSetting(this.executionContext, ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(enabledModuleNames));
|
||||
ModuleSettings.setConfigSetting(this.executionContext, DISABLED_MODULES_KEY, makeCommaSeparatedValuesList(disabledModuleNames));
|
||||
ModuleSettings.setConfigSetting(this.executionContext, IngestJobSettings.ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(enabledModuleNames));
|
||||
ModuleSettings.setConfigSetting(this.executionContext, IngestJobSettings.DISABLED_MODULES_KEY, makeCommaSeparatedValuesList(disabledModuleNames));
|
||||
|
||||
/**
|
||||
* Save the last used File Ingest Filter setting for this context.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -185,6 +185,10 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
|
||||
pastJobsButton.setEnabled(!dataSources.isEmpty() && !ingestJobs.isEmpty());
|
||||
}
|
||||
|
||||
void setPastJobsButtonVisible(boolean isVisible) {
|
||||
pastJobsButton.setVisible(isVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -330,11 +330,11 @@ public class IngestManager {
|
||||
|
||||
// check whether a multi-user case is currently being processed
|
||||
try {
|
||||
if (!Case.isCaseOpen() || Case.getCurrentCase().getCaseType() != Case.CaseType.MULTI_USER_CASE) {
|
||||
if (Case.getCurrentCase().getCaseType() != Case.CaseType.MULTI_USER_CASE) {
|
||||
return;
|
||||
}
|
||||
} catch (IllegalStateException ignore) {
|
||||
// thorown by Case.getCurrentCase() when no case is open
|
||||
// Thrown by Case.getCurrentCase() when no case is open
|
||||
return;
|
||||
}
|
||||
|
||||
@ -343,7 +343,7 @@ public class IngestManager {
|
||||
logger.log(Level.SEVERE, "Service {0} is down! Cancelling all running ingest jobs", serviceDisplayName); //NON-NLS
|
||||
|
||||
// display notification if running interactively
|
||||
if (isIngestRunning() && RuntimeProperties.coreComponentsAreActive()) {
|
||||
if (isIngestRunning() && RuntimeProperties.runningWithGUI()) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -379,7 +379,7 @@ public class IngestManager {
|
||||
* Case.getTextIndexName() API.
|
||||
*/
|
||||
Case openedCase = Case.getCurrentCase();
|
||||
String channelPrefix = openedCase.getTextIndexName();
|
||||
String channelPrefix = openedCase.getName();
|
||||
if (Case.CaseType.MULTI_USER_CASE == openedCase.getCaseType()) {
|
||||
jobEventPublisher.openRemoteEventChannel(String.format(JOB_EVENT_CHANNEL_NAME, channelPrefix));
|
||||
moduleEventPublisher.openRemoteEventChannel(String.format(MODULE_EVENT_CHANNEL_NAME, channelPrefix));
|
||||
@ -392,24 +392,17 @@ public class IngestManager {
|
||||
}
|
||||
|
||||
synchronized void handleCaseClosed() {
|
||||
/*
|
||||
* TODO (JIRA-2227): IngestManager should wait for cancelled ingest jobs
|
||||
* to complete when a case is closed.
|
||||
*/
|
||||
this.cancelAllIngestJobs(IngestJob.CancellationReason.CASE_CLOSED);
|
||||
jobEventPublisher.closeRemoteEventChannel();
|
||||
moduleEventPublisher.closeRemoteEventChannel();
|
||||
this.jobCreationIsEnabled = false;
|
||||
clearIngestMessageBox();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated, use RuntimeProperties.setCoreComponentsActive instead.
|
||||
*
|
||||
* @param runInteractively True or false
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public synchronized void setRunInteractively(boolean runInteractively) {
|
||||
RuntimeProperties.setCoreComponentsActive(runInteractively);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the custom installer for this package once the window system is
|
||||
* initialized, allowing the ingest manager to get the top component used to
|
||||
@ -428,7 +421,7 @@ public class IngestManager {
|
||||
*/
|
||||
void postIngestMessage(IngestMessage message) {
|
||||
synchronized (this.ingestMessageBoxLock) {
|
||||
if (ingestMessageBox != null && RuntimeProperties.coreComponentsAreActive()) {
|
||||
if (ingestMessageBox != null && RuntimeProperties.runningWithGUI()) {
|
||||
if (message.getMessageType() != IngestMessage.MessageType.ERROR && message.getMessageType() != IngestMessage.MessageType.WARNING) {
|
||||
ingestMessageBox.displayMessage(message);
|
||||
} else {
|
||||
@ -475,7 +468,7 @@ public class IngestManager {
|
||||
*/
|
||||
public void queueIngestJob(Collection<Content> dataSources, IngestJobSettings settings) {
|
||||
if (jobCreationIsEnabled) {
|
||||
IngestJob job = new IngestJob(dataSources, settings, RuntimeProperties.coreComponentsAreActive());
|
||||
IngestJob job = new IngestJob(dataSources, settings, RuntimeProperties.runningWithGUI());
|
||||
if (job.hasIngestPipeline()) {
|
||||
long taskId = nextThreadId.incrementAndGet();
|
||||
Future<Void> task = startIngestJobsThreadPool.submit(new StartIngestJobTask(taskId, job));
|
||||
@ -485,9 +478,9 @@ public class IngestManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an ingest job that will process a collection of data sources.
|
||||
* This is intended to be used in an auto-ingest context and will fail
|
||||
* if no ingest modules are enabled.
|
||||
* Starts an ingest job that will process a collection of data sources. This
|
||||
* is intended to be used in an auto-ingest context and will fail if no
|
||||
* ingest modules are enabled.
|
||||
*
|
||||
* @param dataSources The data sources to process.
|
||||
* @param settings The settings for the ingest job.
|
||||
@ -497,7 +490,7 @@ public class IngestManager {
|
||||
*/
|
||||
public synchronized IngestJobStartResult beginIngestJob(Collection<Content> dataSources, IngestJobSettings settings) {
|
||||
if (this.jobCreationIsEnabled) {
|
||||
IngestJob job = new IngestJob(dataSources, settings, RuntimeProperties.coreComponentsAreActive());
|
||||
IngestJob job = new IngestJob(dataSources, settings, RuntimeProperties.runningWithGUI());
|
||||
if (job.hasIngestPipeline()) {
|
||||
return this.startIngestJob(job); // Start job
|
||||
}
|
||||
@ -543,7 +536,7 @@ public class IngestManager {
|
||||
try {
|
||||
if (!servicesMonitor.getServiceStatus(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString()).equals(ServicesMonitor.ServiceStatus.UP.toString())) {
|
||||
// display notification if running interactively
|
||||
if (RuntimeProperties.coreComponentsAreActive()) {
|
||||
if (RuntimeProperties.runningWithGUI()) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -582,7 +575,7 @@ public class IngestManager {
|
||||
logger.log(Level.SEVERE, String.format("Error starting %s ingest module for job %d", error.getModuleDisplayName(), job.getId()), error.getThrowable()); //NON-NLS
|
||||
}
|
||||
IngestManager.logger.log(Level.SEVERE, "Ingest job {0} could not be started", job.getId()); //NON-NLS
|
||||
if (RuntimeProperties.coreComponentsAreActive()) {
|
||||
if (RuntimeProperties.runningWithGUI()) {
|
||||
final StringBuilder message = new StringBuilder();
|
||||
message.append(Bundle.IngestManager_startupErr_dlgMsg()).append("\n");
|
||||
message.append(Bundle.IngestManager_startupErr_dlgSolution()).append("\n\n");
|
||||
@ -966,7 +959,7 @@ public class IngestManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (RuntimeProperties.coreComponentsAreActive()) {
|
||||
if (RuntimeProperties.runningWithGUI()) {
|
||||
final String displayName = NbBundle.getMessage(this.getClass(), "IngestManager.StartIngestJobsTask.run.displayName");
|
||||
this.progress = ProgressHandle.createHandle(displayName, new Cancellable() {
|
||||
@Override
|
||||
|
@ -130,7 +130,7 @@ class IngestMessagesToolbar extends javax.swing.JPanel {
|
||||
|
||||
Case.addPropertyChangeListener((PropertyChangeEvent evt) -> {
|
||||
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
setEnabled(evt.getNewValue() != null && RuntimeProperties.coreComponentsAreActive());
|
||||
setEnabled(evt.getNewValue() != null && RuntimeProperties.runningWithGUI());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="tabbedPane" pref="824" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="tabbedPane" pref="543" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JTabbedPane" name="tabbedPane">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
225
Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java
Normal file
225
Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 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.ingest;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
|
||||
import org.sleuthkit.autopsy.modules.interestingitems.FilesSetDefsPanel;
|
||||
import org.sleuthkit.autopsy.modules.interestingitems.FilesSetDefsPanel.PANEL_TYPE;
|
||||
|
||||
/**
|
||||
* Global options panel for keyword searching.
|
||||
*/
|
||||
public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel {
|
||||
|
||||
@NbBundle.Messages({"IngestOptionsPanel.settingsTab.text=Settings",
|
||||
"IngestOptionsPanel.settingsTab.toolTipText=Settings regarding resources available to ingest.",
|
||||
"IngestOptionsPanel.fileFiltersTab.text=File Filters",
|
||||
"IngestOptionsPanel.fileFiltersTab.toolTipText=Settings for creating and editing ingest file filters.",
|
||||
"IngestOptionsPanel.profilesTab.text=Profiles",
|
||||
"IngestOptionsPanel.profilesTab.toolTipText=Settings for creating and editing profiles."})
|
||||
|
||||
private FilesSetDefsPanel filterPanel;
|
||||
private final static int INDEX_OF_FILTER_PANEL = 0;
|
||||
private IngestSettingsPanel settingsPanel;
|
||||
private final static int INDEX_OF_SETTINGS_PANEL = 2;
|
||||
private ProfileSettingsPanel profilePanel;
|
||||
private final static int INDEX_OF_PROFILE_PANEL = 1;
|
||||
/**
|
||||
* This panel implements a property change listener that listens to ingest
|
||||
* job events so it can disable the buttons on the panel if ingest is
|
||||
* running. This is done to prevent changes to user-defined types while the
|
||||
* type definitions are in use.
|
||||
*/
|
||||
IngestJobEventPropertyChangeListener ingestJobEventsListener;
|
||||
|
||||
public IngestOptionsPanel() {
|
||||
initComponents();
|
||||
customizeComponents();
|
||||
}
|
||||
|
||||
private void customizeComponents() {
|
||||
filterPanel = new FilesSetDefsPanel(PANEL_TYPE.FILE_INGEST_FILTERS);
|
||||
settingsPanel = new IngestSettingsPanel();
|
||||
profilePanel = new ProfileSettingsPanel();
|
||||
|
||||
tabbedPane.insertTab(NbBundle.getMessage(IngestOptionsPanel.class, "IngestOptionsPanel.fileFiltersTab.text"), null,
|
||||
filterPanel, NbBundle.getMessage(IngestOptionsPanel.class, "IngestOptionsPanel.fileFiltersTab.toolTipText"), INDEX_OF_FILTER_PANEL);
|
||||
tabbedPane.insertTab(NbBundle.getMessage(IngestOptionsPanel.class, "IngestOptionsPanel.profilesTab.text"), null,
|
||||
profilePanel, NbBundle.getMessage(IngestOptionsPanel.class, "IngestOptionsPanel.profilesTab.toolTipText"), INDEX_OF_PROFILE_PANEL);
|
||||
tabbedPane.insertTab(NbBundle.getMessage(IngestOptionsPanel.class, "IngestOptionsPanel.settingsTab.text"), null,
|
||||
settingsPanel, NbBundle.getMessage(IngestOptionsPanel.class, "IngestOptionsPanel.settingsTab.toolTipText"), INDEX_OF_SETTINGS_PANEL);
|
||||
//Listener for when tabbed panes are switched, because we can have two file filter definitions panels open at the same time
|
||||
//we may wind up in a situation where the user has created and saved one in the profiles panel
|
||||
//so we need to refresh the filterPanel in those cases before proceeding.
|
||||
tabbedPane.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
if (e.getSource() instanceof JTabbedPane) {
|
||||
//because we can have two filterPanels open at the same time
|
||||
//we need to save the settings when we change tabs otherwise
|
||||
//they could be overwritten with out of date
|
||||
if (tabbedPane.getSelectedIndex() == INDEX_OF_FILTER_PANEL) {
|
||||
filterPanel.load();
|
||||
}
|
||||
else {
|
||||
filterPanel.saveSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addIngestJobEventsListener();
|
||||
enableTabs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a property change listener that listens to ingest job events to
|
||||
* disable the buttons on the panel if ingest is running. This is done to
|
||||
* prevent changes to user-defined types while the type definitions are in
|
||||
* use.
|
||||
*/
|
||||
private void addIngestJobEventsListener() {
|
||||
ingestJobEventsListener = new IngestJobEventPropertyChangeListener();
|
||||
IngestManager.getInstance().addIngestJobEventListener(ingestJobEventsListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* A property change listener that listens to ingest job events.
|
||||
*/
|
||||
private class IngestJobEventPropertyChangeListener implements PropertyChangeListener {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
enableTabs();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables tabs and options inside of tabs during Ingest, and re-enables
|
||||
* them after Ingest is complete or cancelled.
|
||||
*/
|
||||
private void enableTabs() {
|
||||
boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning();
|
||||
tabbedPane.setEnabled(!ingestIsRunning);
|
||||
settingsPanel.enableButtons(!ingestIsRunning);
|
||||
profilePanel.enableButtons(!ingestIsRunning);
|
||||
filterPanel.enableButtons(!ingestIsRunning);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void addPropertyChangeListener(PropertyChangeListener l) {
|
||||
filterPanel.addPropertyChangeListener(l);
|
||||
settingsPanel.addPropertyChangeListener(l);
|
||||
profilePanel.addPropertyChangeListener(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void removePropertyChangeListener(PropertyChangeListener l) {
|
||||
filterPanel.removePropertyChangeListener(l);
|
||||
settingsPanel.removePropertyChangeListener(l);
|
||||
profilePanel.removePropertyChangeListener(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void saveSettings() {
|
||||
filterPanel.store();
|
||||
settingsPanel.store();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void store() {
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void load() {
|
||||
filterPanel.load();
|
||||
settingsPanel.load();
|
||||
profilePanel.load();
|
||||
}
|
||||
|
||||
boolean valid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called when the cancel button is clicked.
|
||||
*/
|
||||
void cancel() {
|
||||
//doesn't need to do anything
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
tabbedPane = new javax.swing.JTabbedPane();
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(tabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 824, Short.MAX_VALUE)
|
||||
.addGap(0, 0, 0))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(tabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 543, Short.MAX_VALUE)
|
||||
.addGap(0, 0, 0))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JTabbedPane tabbedPane;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.modules.interestingitems;
|
||||
package org.sleuthkit.autopsy.ingest;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
@ -26,29 +26,22 @@ import javax.swing.SwingUtilities;
|
||||
import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
@OptionsPanelController.TopLevelRegistration(
|
||||
categoryName = "#OptionsCategory_Name_FileIngestFilterDefinitions",
|
||||
categoryName = "#OptionsCategory_Name_IngestOptions",
|
||||
iconBase = "org/sleuthkit/autopsy/images/file_ingest_filter32x32.png",
|
||||
keywords = "#OptionsCategory_Keywords_FileIngestFilterDefinitions",
|
||||
keywordsCategory = "FileIngestFilterDefinitions",
|
||||
position = 7
|
||||
)
|
||||
position = 2,
|
||||
keywords = "#OptionsCategory_Keywords_IngestOptions",
|
||||
keywordsCategory = "IngestOptions")
|
||||
|
||||
/**
|
||||
* Class for creating an FilesSetDefsPanel which will be used for configuring
|
||||
* the FileIngestFilter.
|
||||
*/
|
||||
public final class FileIngestFilterDefsOptionsPanelController extends OptionsPanelController {
|
||||
public class IngestOptionsPanelController extends OptionsPanelController {
|
||||
|
||||
private FilesSetDefsPanel panel;
|
||||
private IngestOptionsPanel panel;
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
private boolean changed;
|
||||
private static final Logger LOGGER = Logger.getLogger(FileIngestFilterDefsOptionsPanelController.class.getName());
|
||||
|
||||
/**
|
||||
* Component should load its data here.
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void update() {
|
||||
@ -56,11 +49,28 @@ public final class FileIngestFilterDefsOptionsPanelController extends OptionsPan
|
||||
changed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IngestOptionsPanel which is contained inside this controller.
|
||||
*
|
||||
* @return panel
|
||||
*/
|
||||
private IngestOptionsPanel getPanel() {
|
||||
if (panel == null) {
|
||||
panel = new IngestOptionsPanel();
|
||||
panel.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getPropertyName().equals(OptionsPanelController.PROP_CHANGED)) {
|
||||
changed();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when both the Ok and Apply buttons are pressed. It
|
||||
* applies to any of the panels that have been opened in the process of
|
||||
* using the options pane.
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void applyChanges() {
|
||||
@ -76,71 +86,59 @@ public final class FileIngestFilterDefsOptionsPanelController extends OptionsPan
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when the Cancel button is pressed. It applies to
|
||||
* any of the panels that have been opened in the process of using the
|
||||
* options pane.
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void cancel() {
|
||||
// need not do anything special, if no changes have been persisted yet
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
getPanel().cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine whether any changes have been made to this controller's
|
||||
* panel.
|
||||
*
|
||||
* @return Whether or not a change has been made.
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return getPanel().valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isChanged() {
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public JComponent getComponent(Lookup lkp) {
|
||||
return getPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public HelpCtx getHelpCtx() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public JComponent getComponent(Lookup masterLookup) {
|
||||
return getPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPropertyChangeListener(PropertyChangeListener l) {
|
||||
pcs.addPropertyChangeListener(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePropertyChangeListener(PropertyChangeListener l) {
|
||||
pcs.removePropertyChangeListener(l);
|
||||
public void addPropertyChangeListener(PropertyChangeListener pl) {
|
||||
pcs.addPropertyChangeListener(pl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an interestingItemsDefPanel that will be labeled to indicate it
|
||||
* is for File Ingest Filter settings
|
||||
*
|
||||
* @return an FilesSetDefsPanel which has text and fields modified to
|
||||
* indicate it is for File Ingest Filtering.
|
||||
* @inheritDoc
|
||||
*/
|
||||
private FilesSetDefsPanel getPanel() {
|
||||
if (panel == null) {
|
||||
panel = new FilesSetDefsPanel(FilesSetDefsPanel.PANEL_TYPE.FILE_INGEST_FILTERS);
|
||||
panel.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getPropertyName().equals(OptionsPanelController.PROP_CHANGED)) {
|
||||
changed();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return panel;
|
||||
public void removePropertyChangeListener(PropertyChangeListener pl) {
|
||||
pcs.removePropertyChangeListener(pl);
|
||||
}
|
||||
|
||||
void changed() {
|
||||
@ -150,5 +148,4 @@ public final class FileIngestFilterDefsOptionsPanelController extends OptionsPan
|
||||
}
|
||||
pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user