Merge branch 'develop' of https://github.com/sleuthkit/autopsy into 2094-ExportImportFilesSets

This commit is contained in:
William Schaefer 2017-03-02 15:07:46 -05:00
commit f0ea129bde
852 changed files with 148620 additions and 6217 deletions

View File

@ -258,6 +258,7 @@
<package>org.sleuthkit.autopsy.events</package> <package>org.sleuthkit.autopsy.events</package>
<package>org.sleuthkit.autopsy.externalresults</package> <package>org.sleuthkit.autopsy.externalresults</package>
<package>org.sleuthkit.autopsy.filesearch</package> <package>org.sleuthkit.autopsy.filesearch</package>
<package>org.sleuthkit.autopsy.framework</package>
<package>org.sleuthkit.autopsy.ingest</package> <package>org.sleuthkit.autopsy.ingest</package>
<package>org.sleuthkit.autopsy.keywordsearchservice</package> <package>org.sleuthkit.autopsy.keywordsearchservice</package>
<package>org.sleuthkit.autopsy.menuactions</package> <package>org.sleuthkit.autopsy.menuactions</package>

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -25,27 +25,37 @@ import org.openide.LifecycleManager;
import org.openide.awt.ActionID; import org.openide.awt.ActionID;
import org.openide.awt.ActionReference; import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration; import org.openide.awt.ActionRegistration;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.coreutils.Logger; 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) @ActionRegistration(displayName = "Exit", iconInMenu = true)
@ActionReference(path = "Menu/Case", position = 1000, separatorBefore = 999) @ActionReference(path = "Menu/Case", position = 1000, separatorBefore = 999)
@ActionID(id = "org.sleuthkit.autopsy.casemodule.ExitAction", category = "Case") @ActionID(id = "org.sleuthkit.autopsy.casemodule.ExitAction", category = "Case")
final public class ExitAction implements ActionListener { 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 @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (IngestRunningCheck.checkAndConfirmProceed(Bundle.ExitAction_confirmationDialog_title(), Bundle.ExitAction_confirmationDialog_message())) {
new Thread(() -> {
try { try {
Case currentCase = Case.getCurrentCase(); Case.closeCurrentCase();
if (currentCase != null) { } catch (CaseActionException ex) {
currentCase.closeCase(); Logger.getLogger(ExitAction.class.getName()).log(Level.SEVERE, "Error closing the current case on exit", ex); //NON-NLS
}
} catch (Exception ex) {
Logger.getLogger(ExitAction.class.getName()).log(Level.SEVERE, "Had a problem closing the case.", ex); //NON-NLS
} finally { } finally {
LifecycleManager.getDefault().exit(); LifecycleManager.getDefault().exit();
} }
}).start();
}
} }
} }

View File

@ -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() {
}
}

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014-2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -18,9 +18,9 @@
*/ */
package org.sleuthkit.autopsy.actions; package org.sleuthkit.autopsy.actions;
import java.awt.Desktop;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.Desktop;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
@ -35,10 +35,14 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger; 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( @ActionRegistration(displayName = "#CTL_OpenLogFolder", iconInMenu = true)
displayName = "#CTL_OpenLogFolder", iconInMenu = true)
@ActionReference(path = "Menu/Help", position = 1750) @ActionReference(path = "Menu/Help", position = 1750)
@ActionID(id = "org.sleuthkit.autopsy.actions.OpenLogFolderAction", category = "Help") @ActionID(id = "org.sleuthkit.autopsy.actions.OpenLogFolderAction", category = "Help")
public final class OpenLogFolderAction implements ActionListener { public final class OpenLogFolderAction implements ActionListener {
@ -47,25 +51,42 @@ public final class OpenLogFolderAction implements ActionListener {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
try {
File logDir; File logDir;
if (Case.isCaseOpen()) { 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 { } else {
logDir = new File(Places.getUserDirectory().getAbsolutePath() + File.separator + "var" + File.separator + "log"); logDir = new File(Places.getUserDirectory().getAbsolutePath() + File.separator + "var" + File.separator + "log");
} }
if (logDir.exists() == false) {
NotifyDescriptor d try {
= new NotifyDescriptor.Message( 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()), NbBundle.getMessage(this.getClass(), "OpenLogFolder.error1", logDir.getAbsolutePath()),
NotifyDescriptor.ERROR_MESSAGE); NotifyDescriptor.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(d); DialogDisplayer.getDefault().notify(notifyDescriptor);
} else {
Desktop.getDesktop().open(logDir);
} }
} catch (IOException ex) { } 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);
}
}
} }
}
}

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -35,37 +35,45 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger; 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( @ActionRegistration(displayName = "#CTL_OpenOutputFolder", iconInMenu = true, lazy = false)
displayName = "#CTL_OpenOutputFolder", iconInMenu = true, lazy=true)
@ActionReference(path = "Menu/Tools", position = 1850, separatorBefore = 1849) @ActionReference(path = "Menu/Tools", position = 1850, separatorBefore = 1849)
@ActionID(id = "org.sleuthkit.autopsy.actions.OpenOutputFolderAction", category = "Help") @ActionID(id = "org.sleuthkit.autopsy.actions.OpenOutputFolderAction", category = "Help")
public final class OpenOutputFolderAction extends CallableSystemAction { public final class OpenOutputFolderAction extends CallableSystemAction {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(OpenOutputFolderAction.class.getName()); private static final Logger logger = Logger.getLogger(OpenOutputFolderAction.class.getName());
@Override @Override
public void performAction() { public void performAction() {
try {
File outputDir; File outputDir;
if (Case.isCaseOpen()) { try {
outputDir = new File(Case.getCurrentCase().getOutputDirectory()); Case currentCase = Case.getCurrentCase();
if (outputDir.exists() == false) { outputDir = new File(currentCase.getOutputDirectory());
NotifyDescriptor d if (outputDir.exists()) {
= new NotifyDescriptor.Message(NbBundle.getMessage(this.getClass(), try {
"OpenOutputFolder.error1", outputDir.getAbsolutePath()),
NotifyDescriptor.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(d);
} else {
Desktop.getDesktop().open(outputDir); 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 { } 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) { } catch (IllegalStateException ex) {
logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "OpenOutputFolder.CouldNotOpenOutputFolder"), ex); //NON-NLS 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 @Override
public boolean asynchronous() { public boolean asynchronous() {
return false; // run on edt return false;
} }
@Override @Override
public String getName() { public String getName() {
return NbBundle.getMessage(OpenOutputFolderAction.class, "CTL_OpenOutputFolder"); return NbBundle.getMessage(OpenOutputFolderAction.class, "CTL_OpenOutputFolder");

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -29,23 +29,24 @@ import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog; import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
@ActionID( /**
category = "Help", * The action associated with the Help/Get Ingest Progress Snapshot menu item.
id = "org.sleuthkit.autopsy.actions.ShowIngestProgressSnapshotAction" * It opens a the Ingest Progress Snapshot dialog.
) *
@ActionRegistration( * This action should only be invoked in the event dispatch thread (EDT).
displayName = "#CTL_ShowIngestProgressSnapshotAction", */
lazy = false @ActionID(category = "Help", id = "org.sleuthkit.autopsy.actions.ShowIngestProgressSnapshotAction")
) @ActionRegistration(displayName = "#CTL_ShowIngestProgressSnapshotAction", lazy = false)
@ActionReference(path = "Menu/Help", position = 1125) @ActionReference(path = "Menu/Help", position = 1125)
@Messages("CTL_ShowIngestProgressSnapshotAction=Ingest Status Details") @Messages("CTL_ShowIngestProgressSnapshotAction=Ingest Status Details")
public final class ShowIngestProgressSnapshotAction extends CallableSystemAction implements ActionListener { public final class ShowIngestProgressSnapshotAction extends CallableSystemAction implements ActionListener {
private static final String ACTION_NAME = NbBundle.getMessage(ShowIngestProgressSnapshotAction.class, "ShowIngestProgressSnapshotAction.actionName.text"); private static final String ACTION_NAME = NbBundle.getMessage(ShowIngestProgressSnapshotAction.class, "ShowIngestProgressSnapshotAction.actionName.text");
private static final long serialVersionUID = 1L;
@Override @Override
public void performAction() { public void performAction() {
IngestProgressSnapshotDialog dialog = new IngestProgressSnapshotDialog(); new IngestProgressSnapshotDialog();
} }
@Override @Override
@ -65,6 +66,6 @@ public final class ShowIngestProgressSnapshotAction extends CallableSystemAction
@Override @Override
public boolean asynchronous() { public boolean asynchronous() {
return false; // run on edt return false;
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2014 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.awt.Component; import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dialog; import java.awt.Dialog;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
@ -28,7 +29,6 @@ import java.util.logging.Level;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; 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.CallableSystemAction;
import org.openide.util.actions.Presenter; import org.openide.util.actions.Presenter;
import org.openide.util.lookup.ServiceProvider; 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.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.Image;
/** /**
* The action to add an image to the current Case. This action should be * An action that invokes the Add Data Source wizard.
* disabled on creation and it will be enabled on new case creation or case
* opened.
* *
* @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") @ActionID(category = "Tools", id = "org.sleuthkit.autopsy.casemodule.AddImageAction")
@ActionRegistration(displayName = "#CTL_AddImage", lazy = false) @ActionRegistration(displayName = "#CTL_AddImage", lazy = false)
@ActionReferences(value = { @ActionReferences(value = {@ActionReference(path = "Toolbars/Case", position = 100)})
@ActionReference(path = "Toolbars/Case", position = 100)})
@ServiceProvider(service = AddImageAction.class) @ServiceProvider(service = AddImageAction.class)
public final class AddImageAction extends CallableSystemAction implements Presenter.Toolbar { 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 // Keys into the WizardDescriptor properties that pass information between stages of the wizard
// <TYPE>: <DESCRIPTION> // <TYPE>: <DESCRIPTION>
// String: time zone that the image is from // 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 String NOFATORPHANS_PROP = "nofatorphans"; //NON-NLS
static final Logger logger = Logger.getLogger(AddImageAction.class.getName()); static final Logger logger = Logger.getLogger(AddImageAction.class.getName());
static final Dimension SIZE = new Dimension(875, 550);
private WizardDescriptor wizardDescriptor; private WizardDescriptor wizardDescriptor;
private WizardDescriptor.Iterator<WizardDescriptor> iterator; private WizardDescriptor.Iterator<WizardDescriptor> iterator;
private Dialog dialog; 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() { public AddImageAction() {
putValue(Action.NAME, NbBundle.getMessage(AddImageAction.class, "CTL_AddImage")); // set the action Name 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 @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (IngestManager.getInstance().isIngestRunning()) { String optionsDlgTitle = NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.title");
final String msg = NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.msg"); String optionsDlgMessage = NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.msg");
if (JOptionPane.showConfirmDialog(null, msg, if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
NbBundle.getMessage(this.getClass(), WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
"AddImageAction.ingestConfig.ongoingIngest.title"),
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.NO_OPTION) {
return;
}
}
iterator = new AddImageWizardIterator(this); iterator = new AddImageWizardIterator(this);
wizardDescriptor = new WizardDescriptor(iterator); wizardDescriptor = new WizardDescriptor(iterator);
wizardDescriptor.setTitle(NbBundle.getMessage(this.getClass(), "AddImageAction.wizard.title")); 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); dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
Dimension d = dialog.getSize(); Dimension d = dialog.getSize();
dialog.setSize(SIZE); dialog.setSize(SIZE);
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
dialog.setVisible(true); dialog.setVisible(true);
dialog.toFront(); dialog.toFront();
@ -145,6 +137,7 @@ public final class AddImageAction extends CallableSystemAction implements Presen
//add-image process, reverting an image) //add-image process, reverting an image)
runCleanupTasks(); runCleanupTasks();
} }
}
/** /**
* Closes the current dialog and wizard, and opens a new one. Used in the * 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); void runTask(Image newImage);
} }
/**
* This method does nothing. Use the "actionPerformed(ActionEvent e)"
* instead of this method.
*/
@Override @Override
public void performAction() { 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 @Override
public HelpCtx getHelpCtx() { 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 @Override
public Component getToolbarPresenter() { 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 * @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) { public void requestFocusButton(String buttonText) {
// get all buttons on this wizard panel // get all buttons on this wizard panel
Object[] wizardButtons = wizardDescriptor.getOptions(); Object[] wizardButtons = wizardDescriptor.getOptions();
for (int i = 0; i < wizardButtons.length; i++) { for (Object wizardButton : wizardButtons) {
JButton tempButton = (JButton) wizardButtons[i]; JButton tempButton = (JButton) wizardButton;
if (tempButton.getText().equals(buttonText)) { if (tempButton.getText().equals(buttonText)) {
tempButton.setDefaultCapable(true); tempButton.setDefaultCapable(true);
tempButton.requestFocus(); tempButton.requestFocus();
@ -254,8 +244,6 @@ public final class AddImageAction extends CallableSystemAction implements Presen
cleanupSupport.fireChange(); cleanupSupport.fireChange();
} }
ChangeSupport cleanupSupport = new ChangeSupport(this);
/** /**
* Instances of this class implement the cleanup() method to run cleanup * Instances of this class implement the cleanup() method to run cleanup
* code when the wizard exits. * code when the wizard exits.

View File

@ -15,12 +15,6 @@ NewCaseVisualPanel1.caseNameTextField.text_1=
NewCaseVisualPanel1.jLabel2.text_1=Case data will be stored in the following directory: NewCaseVisualPanel1.jLabel2.text_1=Case data will be stored in the following directory:
NewCaseVisualPanel1.caseParentDirTextField.text= NewCaseVisualPanel1.caseParentDirTextField.text=
NewCaseVisualPanel1.caseDirTextField.text_1= 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.autopsyLogo.text=
CueBannerPanel.createNewLabel.text=Create New Case CueBannerPanel.createNewLabel.text=Create New Case
CueBannerPanel.openLabel.text=Open Existing Case CueBannerPanel.openLabel.text=Open Existing Case
@ -31,8 +25,6 @@ CueBannerPanel.openCaseButton.text=
CueBannerPanel.openRecentButton.text= CueBannerPanel.openRecentButton.text=
OpenRecentCasePanel.cancelButton.text=Cancel OpenRecentCasePanel.cancelButton.text=Cancel
OpenRecentCasePanel.jLabel1.text=Recent Cases OpenRecentCasePanel.jLabel1.text=Recent Cases
CasePropertiesForm.caseNumberLabel.text=Case Number:
CasePropertiesForm.examinerLabel.text=Examiner:
NewCaseVisualPanel2.caseNumberTextField.text= NewCaseVisualPanel2.caseNumberTextField.text=
NewCaseVisualPanel2.examinerLabel.text=Examiner: NewCaseVisualPanel2.examinerLabel.text=Examiner:
NewCaseVisualPanel2.caseNumberLabel.text=Case Number: NewCaseVisualPanel2.caseNumberLabel.text=Case Number:
@ -98,12 +90,9 @@ AddImageWizardIngestConfigVisual.getName.text=Configure Ingest Modules
AddImageWizardIterator.stepXofN=Step {0} of {1} AddImageWizardIterator.stepXofN=Step {0} of {1}
AddLocalFilesTask.localFileAdd.progress.text=Adding\: {0}/{1} AddLocalFilesTask.localFileAdd.progress.text=Adding\: {0}/{1}
Case.getCurCase.exception.noneOpen=Cannot get the current case; there is no case open\! 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.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.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.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.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\ 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\ this case are missing. Would you like to search for them now?\n\
@ -113,9 +102,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. 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.checkImgExist.confDlg.doesntExist.title=Missing Image
Case.addImg.exception.msg=Error adding image to the case 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.updateCaseName.exception.msg=Error while trying to update the case name.
Case.updateExaminer.exception.msg=Error while trying to update the examiner. Case.updateExaminer.exception.msg=Error while trying to update the examiner.
Case.updateCaseNum.exception.msg=Error while trying to update the case number. Case.updateCaseNum.exception.msg=Error while trying to update the case number.
@ -133,7 +119,6 @@ Case.GetCaseTypeGivenPath.Failure=Unable to get case type
Case.metaDataFileCorrupt.exception.msg=The case metadata file (.aut) is corrupted. 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.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.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\ CaseDeleteAction.closeConfMsg.text=Are you sure want to close and delete this case? \n\
Case Name\: {0}\n\ Case Name\: {0}\n\
Case Directory\: {1} Case Directory\: {1}
@ -225,8 +210,6 @@ NewCaseVisualPanel1.caseParentDirWarningLabel.text=
NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-user NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-user
NewCaseVisualPanel1.singleUserCaseRadioButton.text=Single-user NewCaseVisualPanel1.singleUserCaseRadioButton.text=Single-user
NewCaseVisualPanel1.caseTypeLabel.text=Case Type: NewCaseVisualPanel1.caseTypeLabel.text=Case Type:
CasePropertiesForm.lbDbType.text=Case Type:
CasePropertiesForm.lbDbName.text=Database Name:
SingleUserCaseConverter.BadDatabaseFileName=Database file does not exist! SingleUserCaseConverter.BadDatabaseFileName=Database file does not exist!
SingleUserCaseConverter.AlreadyMultiUser=Case is already multi-user! SingleUserCaseConverter.AlreadyMultiUser=Case is already multi-user!
SingleUserCaseConverter.NonUniqueDatabaseName=Database name not unique. SingleUserCaseConverter.NonUniqueDatabaseName=Database name not unique.
@ -241,3 +224,13 @@ LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default
IngestJobInfoPanel.jLabel1.text=Ingest Modules IngestJobInfoPanel.jLabel1.text=Ingest Modules
IngestJobInfoPanel.jLabel2.text=Ingest Jobs IngestJobInfoPanel.jLabel2.text=Ingest Jobs
CaseInformationPanel.closeButton.text=Close CaseInformationPanel.closeButton.text=Close
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

View File

@ -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_AddImageButton=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0
CTL_CaseCloseAct=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b CTL_CaseCloseAct=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b
CTL_CaseNewAction=\u65b0\u898f\u30b1\u30fc\u30b9... 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.caseDirLabel.text=\u30d9\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\uff1a
NewCaseVisualPanel1.caseDirBrowseButton.text=\u95b2\u89a7 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 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.createNewLabel.text=\u65b0\u898f\u30b1\u30fc\u30b9\u3092\u4f5c\u6210
CueBannerPanel.openLabel.text=\u65e2\u5b58\u30b1\u30fc\u30b9\u3092\u958b\u304f CueBannerPanel.openLabel.text=\u65e2\u5b58\u30b1\u30fc\u30b9\u3092\u958b\u304f
CueBannerPanel.closeButton.text=\u9589\u3058\u308b CueBannerPanel.closeButton.text=\u9589\u3058\u308b
CueBannerPanel.openRecentLabel.text=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f CueBannerPanel.openRecentLabel.text=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f
OpenRecentCasePanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb OpenRecentCasePanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb
OpenRecentCasePanel.jLabel1.text=\u6700\u8fd1\u958b\u3044\u305f\u30d5\u30a1\u30a4\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.examinerLabel.text=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a
NewCaseVisualPanel2.caseNumberLabel.text=\u30b1\u30fc\u30b9\u756a\u53f7\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 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} AddImageWizardIterator.stepXofN=\u30b9\u30c6\u30c3\u30d7{0}\uff0f{1}
AddLocalFilesTask.localFileAdd.progress.text=\u8ffd\u52a0\u4e2d\uff1a{0}/{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.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\ 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} {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.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\ 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\ \u4ee5\u524d\u3001\u30a4\u30e1\u30fc\u30b8\u306f\u6b21\u306b\u3042\u308a\u307e\u3057\u305f\uff1a\n\
{1}\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 \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.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.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.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.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 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 CollaborationMonitor.analyzingDataSourceStatus.msg={0}\u304c{1}\u3092\u89e3\u6790\u4e2d
NewCaseVisualPanel1.multiUserCaseRadioButton.text=\u8907\u6570\u30e6\u30fc\u30b6\u30fc NewCaseVisualPanel1.multiUserCaseRadioButton.text=\u8907\u6570\u30e6\u30fc\u30b6\u30fc
NewCaseVisualPanel1.singleUserCaseRadioButton.text=\u5358\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.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.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 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 Case_caseType_singleUser=\u5358\u6570\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9
CasePropertiesForm.imagesTable.columnModel.title0=\u30d1\u30b9 CasePropertiesForm.imagesTable.columnModel.title0=\u30d1\u30b9
CasePropertiesForm.imagesTable.columnModel.title1=\u524a\u9664 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

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,31 +19,33 @@
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.awt.Component; import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.SwingWorker; 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.ActionID;
import org.openide.awt.ActionReference; import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences; import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration; 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 * The action associated with the Case/Close Case menu item and the Close Case
* creation and it will be enabled on new case creation or case opened. * 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") @ActionID(category = "Tools", id = "org.sleuthkit.autopsy.casemodule.CaseCloseAction")
@ActionRegistration(displayName = "#CTL_CaseCloseAct", lazy = false) @ActionRegistration(displayName = "#CTL_CaseCloseAct", lazy = false)
@ -51,87 +53,69 @@ import org.openide.awt.ActionRegistration;
@ActionReference(path = "Toolbars/Case", position = 104)}) @ActionReference(path = "Toolbars/Case", position = 104)})
public final class CaseCloseAction extends CallableSystemAction implements Presenter.Toolbar { 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() { public CaseCloseAction() {
putValue("iconBase", "org/sleuthkit/autopsy/images/close-icon.png"); // put the icon NON-NLS putValue("iconBase", "org/sleuthkit/autopsy/images/close-icon.png"); //NON-NLS
putValue(Action.NAME, NbBundle.getMessage(CaseCloseAction.class, "CTL_CaseCloseAct")); // put the action Name putValue(Action.NAME, NbBundle.getMessage(CaseCloseAction.class, "CTL_CaseCloseAct")); //NON-NLS
// set action of the toolbar button
toolbarButton.addActionListener(CaseCloseAction.this::actionPerformed); toolbarButton.addActionListener(CaseCloseAction.this::actionPerformed);
this.setEnabled(false); 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 @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
// if ingest is ongoing, warn and get confirmaion before opening a different case String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
if (IngestManager.getInstance().isIngestRunning()) { if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
// 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;
}
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
new SwingWorker<Void, Void>() { new SwingWorker<Void, Void>() {
@Override @Override
protected Void doInBackground() throws Exception { protected Void doInBackground() throws Exception {
try { Case.closeCurrentCase();
Case result = Case.getCurrentCase();
result.closeCase();
} catch (CaseActionException | IllegalStateException unused) {
// Already logged.
}
return null; return null;
} }
@Override @Override
protected void done() { 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)); WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
} }
}.execute(); }.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 @Override
public String getName() { 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 @Override
public HelpCtx getHelpCtx() { 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 @Override
public Component getToolbarPresenter() { public Component getToolbarPresenter() {

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2014 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,138 +19,106 @@
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.io.File; import java.util.concurrent.ExecutionException;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JOptionPane; 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.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.DialogDescriptor;
import org.openide.DialogDisplayer; import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor; import org.openide.NotifyDescriptor;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.coreutils.Logger; 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 * The action associated with the Delete button of the Case Properties panel. It
* creation and it will be enabled on new case creation or case opened. * deletes the current case.
*
* This action should only be invoked in the event dispatch thread (EDT).
*/ */
final class CaseDeleteAction extends CallableSystemAction { 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()); private static final Logger logger = Logger.getLogger(CaseDeleteAction.class.getName());
/** CaseDeleteAction() {
* The constructor for this class putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction"));
*/
public CaseDeleteAction() {
putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction")); // put the action Name
this.setEnabled(false); this.setEnabled(false);
} }
/**
* Deletes the current opened case.
*
* @param e
*/
@Override @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) { 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 { try {
Case.getCurrentCase().deleteCase(caseFolder); // delete the current case Case currentCase = Case.getCurrentCase();
success = true; String caseName = currentCase.getName();
} catch (CaseActionException ex) { String caseDirectory = currentCase.getCaseDirectory();
logger.log(Level.WARNING, "Could not delete the case folder: " + caseFolder); //NON-NLS
}
// show notification whether the case has been deleted or it failed to delete... /*
if (!success) { * Do a confirmation dialog and close the current case if the user
JOptionPane.showMessageDialog(caller, * confirms he/she wants to proceed.
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.
*/ */
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 @Override
public void performAction() { 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 @Override
public String getName() { public String getName() {
return NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction"); return NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction");
} }
/**
* Gets the HelpCtx associated with implementing object
*
* @return HelpCtx or HelpCtx.DEFAULT_HELP
*/
@Override @Override
public HelpCtx getHelpCtx() { public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP; return HelpCtx.DEFAULT_HELP;
} }
} }

View File

@ -54,7 +54,7 @@ class CaseInformationPanel extends javax.swing.JPanel {
// put the image paths information into hashmap // put the image paths information into hashmap
Map<Long, String> imgPaths = Case.getImagePaths(currentCase.getSleuthkitCase()); 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()); cpf.setSize(cpf.getPreferredSize());
this.tabbedPane.addTab(Bundle.CaseInformationPanel_caseDetails_header(), cpf); this.tabbedPane.addTab(Bundle.CaseInformationPanel_caseDetails_header(), cpf);
this.tabbedPane.addTab(Bundle.CaseInformationPanel_ingestJobInfo_header(), new IngestJobInfoPanel()); this.tabbedPane.addTab(Bundle.CaseInformationPanel_ingestJobInfo_header(), new IngestJobInfoPanel());

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -54,10 +54,11 @@ public final class CaseMetadata {
private static final String FILE_EXTENSION = ".aut"; 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 DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)");
private static final String SCHEMA_VERSION_ONE = "1.0"; 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 CASE_DATABASE_NAME_ELEMENT_NAME = "DatabaseName"; //NON-NLS
private final static String TEXT_INDEX_NAME_ELEMENT = "TextIndexName"; //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 ROOT_ELEMENT_NAME = "AutopsyCase"; //NON-NLS
private final static String SCHEMA_VERSION_ELEMENT_NAME = "SchemaVersion"; //NON-NLS private final static String SCHEMA_VERSION_ELEMENT_NAME = "SchemaVersion"; //NON-NLS
private final static String CREATED_DATE_ELEMENT_NAME = "CreatedDate"; //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 AUTOPSY_SAVED_BY_ELEMENT_NAME = "SavedByAutopsyVersion"; //NON-NLS
private final static String CASE_ELEMENT_NAME = "Case"; //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_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 CASE_NUMBER_ELEMENT_NAME = "Number"; //NON-NLS
private final static String EXAMINER_ELEMENT_NAME = "Examiner"; //NON-NLS private final static String EXAMINER_ELEMENT_NAME = "Examiner"; //NON-NLS
private final static String CASE_TYPE_ELEMENT_NAME = "CaseType"; //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 final Path metadataFilePath;
private Case.CaseType caseType; private Case.CaseType caseType;
private String caseName; private String caseName;
private String caseDisplayName;
private String caseNumber; private String caseNumber;
private String examiner; private String examiner;
private String caseDatabase; private String caseDatabaseName;
private String textIndexName; private String textIndexName;
private String createdDate; private String createdDate;
private String createdByVersion; private String createdByVersion;
@ -96,25 +99,26 @@ public final class CaseMetadata {
* *
* @param caseDirectory The case directory. * @param caseDirectory The case directory.
* @param caseType The type of case. * @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 caseNumber The case number.
* @param examiner The name of the case examiner. * @param examiner The name of the case examiner.
* @param caseDatabase For a single-user case, the full path to the * @param caseDatabase For a single-user case, the full path to the case
* case database file. For a multi-user case, the * database file. For a multi-user case, the case
* case database name. * database name.
* @param caseTextIndexName The text index name.
* *
* @throws CaseMetadataException If the new case metadata file cannot be * @throws CaseMetadataException If the new case metadata file cannot be
* created. * 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); metadataFilePath = Paths.get(caseDirectory, caseName + FILE_EXTENSION);
this.caseType = caseType; this.caseType = caseType;
this.caseName = caseName; this.caseName = caseName;
this.caseDisplayName = caseDisplayName;
this.caseNumber = caseNumber; this.caseNumber = caseNumber;
this.examiner = examiner; this.examiner = examiner;
this.caseDatabase = caseDatabase; this.caseDatabaseName = caseDatabase;
this.textIndexName = caseTextIndexName;
createdByVersion = Version.getVersion(); createdByVersion = Version.getVersion();
createdDate = CaseMetadata.DATE_FORMAT.format(new Date()); createdDate = CaseMetadata.DATE_FORMAT.format(new Date());
writeToFile(); 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. * @return The case display name.
*/ */
@ -170,19 +174,28 @@ public final class CaseMetadata {
return caseName; 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 * Sets the case display name. This does not change the name of the case
* directory, the case database, or the text index name. * directory, the case database, or the text index name.
* *
* @param caseName A case display name. * @param caseName A case display name.
*/ */
void setCaseName(String caseName) throws CaseMetadataException { void setCaseDisplayName(String caseName) throws CaseMetadataException {
String oldCaseName = caseName; String oldCaseName = caseName;
this.caseName = caseName; this.caseDisplayName = caseName;
try { try {
writeToFile(); writeToFile();
} catch (CaseMetadataException ex) { } catch (CaseMetadataException ex) {
this.caseName = oldCaseName; this.caseDisplayName = oldCaseName;
throw ex; 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. * @return The case database name.
*/ */
public String getCaseDatabaseName() { public String getCaseDatabaseName() {
if (caseType == Case.CaseType.MULTI_USER_CASE) { return caseDatabaseName;
return caseDatabase;
} else {
return Paths.get(caseDatabase).getFileName().toString();
}
} }
/** /**
* Gets the full path to the case database file if the case is a single-user * Sets the text index name.
* case.
* *
* @return The full path to the case database file for a single-user case. * @param caseTextIndexName The text index name.
*
* @throws UnsupportedOperationException If called for a multi-user case.
*/ */
public String getCaseDatabasePath() throws UnsupportedOperationException { void setTextIndexName(String caseTextIndexName) throws CaseMetadataException {
if (caseType == Case.CaseType.SINGLE_USER_CASE) { String oldIndexName = caseTextIndexName;
return caseDatabase; this.textIndexName = caseTextIndexName;
} else { try {
throw new UnsupportedOperationException(); writeToFile();
} catch (CaseMetadataException ex) {
this.textIndexName = oldIndexName;
throw ex;
} }
} }
@ -355,10 +364,11 @@ public final class CaseMetadata {
* Create the children of the case element. * Create the children of the case element.
*/ */
createChildElement(doc, caseElement, CASE_NAME_ELEMENT_NAME, caseName); 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, CASE_NUMBER_ELEMENT_NAME, caseNumber);
createChildElement(doc, caseElement, EXAMINER_ELEMENT_NAME, examiner); createChildElement(doc, caseElement, EXAMINER_ELEMENT_NAME, examiner);
createChildElement(doc, caseElement, CASE_TYPE_ELEMENT_NAME, caseType.toString()); 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); createChildElement(doc, caseElement, TEXT_INDEX_ELEMENT, textIndexName);
} }
@ -402,7 +412,7 @@ public final class CaseMetadata {
String schemaVersion = getElementTextContent(rootElement, SCHEMA_VERSION_ELEMENT_NAME, true); String schemaVersion = getElementTextContent(rootElement, SCHEMA_VERSION_ELEMENT_NAME, true);
this.createdDate = getElementTextContent(rootElement, CREATED_DATE_ELEMENT_NAME, true); this.createdDate = getElementTextContent(rootElement, CREATED_DATE_ELEMENT_NAME, true);
if (schemaVersion.equals(SCHEMA_VERSION_ONE)) { 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 { } else {
this.createdByVersion = getElementTextContent(rootElement, AUTOPSY_CREATED_BY_ELEMENT_NAME, true); this.createdByVersion = getElementTextContent(rootElement, AUTOPSY_CREATED_BY_ELEMENT_NAME, true);
} }
@ -416,6 +426,11 @@ public final class CaseMetadata {
} }
Element caseElement = (Element) caseElements.item(0); Element caseElement = (Element) caseElements.item(0);
this.caseName = getElementTextContent(caseElement, CASE_NAME_ELEMENT_NAME, true); 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.caseNumber = getElementTextContent(caseElement, CASE_NUMBER_ELEMENT_NAME, false);
this.examiner = getElementTextContent(caseElement, EXAMINER_ELEMENT_NAME, false); this.examiner = getElementTextContent(caseElement, EXAMINER_ELEMENT_NAME, false);
this.caseType = Case.CaseType.fromString(getElementTextContent(caseElement, CASE_TYPE_ELEMENT_NAME, true)); this.caseType = Case.CaseType.fromString(getElementTextContent(caseElement, CASE_TYPE_ELEMENT_NAME, true));
@ -423,11 +438,21 @@ public final class CaseMetadata {
throw new CaseMetadataException("Case metadata file corrupted"); throw new CaseMetadataException("Case metadata file corrupted");
} }
if (schemaVersion.equals(SCHEMA_VERSION_ONE)) { 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); this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_NAME_ELEMENT, true);
} else { } else {
this.caseDatabase = getElementTextContent(caseElement, CASE_DATABASE_ELEMENT_NAME, true); this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_ELEMENT_NAME, true);
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, true); this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false);
}
/*
* 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.
*/
Path possibleAbsoluteCaseDbPath = Paths.get(this.caseDatabaseName);
if (possibleAbsoluteCaseDbPath.getNameCount() > 1) {
Path caseDirectoryPath = Paths.get(getCaseDirectory());
this.caseDatabaseName = caseDirectoryPath.relativize(possibleAbsoluteCaseDbPath).toString();
} }
/* /*
@ -483,4 +508,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();
}
}
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2014 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -26,27 +26,25 @@ import org.openide.util.actions.SystemAction;
import org.openide.util.lookup.ServiceProvider; 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) @ServiceProvider(service = CaseNewActionInterface.class)
public final class CaseNewAction extends CallableSystemAction implements CaseNewActionInterface { 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 @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
wizard.performAction(); SystemAction.get(NewCaseWizardAction.class).performAction();
} }
@Override @Override
public void performAction() { public void performAction() {
actionPerformed(null);
} }
@Override @Override

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -22,39 +22,45 @@ import java.awt.Cursor;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.io.File; import java.io.File;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.JFileChooser; import javax.swing.JFileChooser;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingUtilities; import javax.swing.SwingWorker;
import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.filechooser.FileNameExtensionFilter;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.openide.windows.WindowManager; 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.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.Version; 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) @ServiceProvider(service = CaseOpenAction.class)
public final class CaseOpenAction extends CallableSystemAction implements ActionListener { 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 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 JFileChooser fileChooser = new JFileChooser();
private final FileFilter caseMetadataFileFilter; 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() { public CaseOpenAction() {
caseMetadataFileFilter = new FileNameExtensionFilter(NbBundle.getMessage(CaseOpenAction.class, "CaseOpenAction.autFilter.title", Version.getName(), CaseMetadata.getFileExtension()), CaseMetadata.getFileExtension().substring(1)); 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 @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
/* String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
* If ingest is running, do a dialog to warn the user and confirm the String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
* intent to close the current case and leave the ingest process if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
* 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;
}
}
/** /**
* Pop up a file chooser to allow the user to select a case metadata * Pop up a file chooser to allow the user to select a case metadata
* file (.aut file). * file (.aut file).
@ -116,36 +96,45 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
StartupWindowProvider.getInstance().close(); StartupWindowProvider.getInstance().close();
/* /*
* Try to open the case associated with the case metadata file the * Try to open the case associated with the case metadata file
* user selected. * the user selected.
*/ */
final String path = fileChooser.getSelectedFile().getPath(); final String path = fileChooser.getSelectedFile().getPath();
String dirPath = fileChooser.getSelectedFile().getParent(); String dirPath = fileChooser.getSelectedFile().getParent();
ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE, dirPath.substring(0, dirPath.lastIndexOf(File.separator))); ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE, dirPath.substring(0, dirPath.lastIndexOf(File.separator)));
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 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 { try {
Case.open(path); get();
} catch (CaseActionException ex) { } catch (InterruptedException | ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS 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)); WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(), WindowManager.getDefault().getMainWindow(),
ex.getMessage(), // Should be user-friendly ex.getMessage(),
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
if (!Case.isCaseOpen()) {
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
} }
}); WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}.execute();
} }
}).start();
} }
} }
@Override @Override
public void performAction() { public void performAction() {
actionPerformed(null);
} }
@Override @Override

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2014 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -23,98 +23,70 @@ import java.awt.Toolkit;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.logging.Level;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.JFrame; import javax.swing.SwingUtilities;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.openide.windows.WindowManager; 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, * The action associated with the Case/Case Properties menu item. It invokes the
* user can update the case properties (for example: updates the case name and * Case Properties dialog.
* removes the image from the current case)
*
* @author jantonius
*/ */
final class CasePropertiesAction extends CallableSystemAction { final class CasePropertiesAction extends CallableSystemAction {
private static JDialog popUpWindow; private static final long serialVersionUID = 1L;
private static JDialog casePropertiesDialog;
/**
* The CasePropertiesAction constructor
*/
CasePropertiesAction() { 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); this.setEnabled(false);
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), new PropertyChangeListener() { Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), new PropertyChangeListener() {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { 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 @Override
public void performAction() { public void performAction() {
if (popUpWindow == null) { SwingUtilities.invokeLater(() -> {
// create the popUp window for it if (null == casePropertiesDialog) {
String title = NbBundle.getMessage(this.getClass(), "CasePropertiesAction.window.title"); String title = NbBundle.getMessage(this.getClass(), "CasePropertiesAction.window.title");
popUpWindow = new JDialog((JFrame) WindowManager.getDefault().getMainWindow(), title, false); casePropertiesDialog = new JDialog(WindowManager.getDefault().getMainWindow(), title, false);
try {
CaseInformationPanel caseInformationPanel = new CaseInformationPanel(); CaseInformationPanel caseInformationPanel = new CaseInformationPanel();
caseInformationPanel.addCloseButtonAction((ActionEvent e) -> { 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(); Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
double w = popUpWindow.getSize().getWidth(); double w = casePropertiesDialog.getSize().getWidth();
double h = popUpWindow.getSize().getHeight(); double h = casePropertiesDialog.getSize().getHeight();
popUpWindow.setLocation((int) ((screenDimension.getWidth() - w) / 2), (int) ((screenDimension.getHeight() - h) / 2)); casePropertiesDialog.setLocation((int) ((screenDimension.getWidth() - w) / 2), (int) ((screenDimension.getHeight() - h) / 2));
casePropertiesDialog.setVisible(true);
popUpWindow.setVisible(true);
} catch (Exception ex) {
Logger.getLogger(CasePropertiesAction.class.getName()).log(Level.WARNING, "Error displaying Case Properties window.", ex); //NON-NLS
} }
} casePropertiesDialog.setVisible(true);
popUpWindow.setVisible(true); casePropertiesDialog.toFront();
popUpWindow.toFront(); });
} }
/**
* Gets the name of this action. This may be presented as an item in a menu.
*
* @return actionName
*/
@Override @Override
public String getName() { public String getName() {
return NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction"); return NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction");
} }
/**
* Gets the HelpCtx associated with implementing object
*
* @return HelpCtx or HelpCtx.DEFAULT_HELP
*/
@Override @Override
public HelpCtx getHelpCtx() { public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP; return HelpCtx.DEFAULT_HELP;
} }
static void closeCasePropertiesWindow() { static void closeCasePropertiesWindow() {
popUpWindow.dispose(); casePropertiesDialog.setVisible(false);
} }
} }

View File

@ -161,7 +161,7 @@
</FontInfo> </FontInfo>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.caseNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
@ -173,7 +173,7 @@
</FontInfo> </FontInfo>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.crDateLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
@ -185,7 +185,7 @@
</FontInfo> </FontInfo>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.caseDirLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
@ -197,12 +197,9 @@
</FontInfo> </FontInfo>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.caseNameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="caseNameTextFieldActionPerformed"/>
</Events>
</Component> </Component>
<Component class="javax.swing.JButton" name="updateCaseNameButton"> <Component class="javax.swing.JButton" name="updateCaseNameButton">
<Properties> <Properties>
@ -212,7 +209,7 @@
</FontInfo> </FontInfo>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.updateCaseNameButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -227,7 +224,7 @@
</FontInfo> </FontInfo>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.deleteCaseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -242,7 +239,7 @@
</FontInfo> </FontInfo>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.caseNumberLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
@ -254,7 +251,7 @@
</FontInfo> </FontInfo>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.examinerLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
@ -266,7 +263,7 @@
</FontInfo> </FontInfo>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.lbDbType.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
@ -278,7 +275,7 @@
</FontInfo> </FontInfo>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesPanel.lbDbName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -17,14 +17,9 @@
* limitations under the License. * limitations under the License.
*/ */
/*
* CasePropertiesForm.java
*
* Created on Mar 14, 2011, 1:48:20 PM
*/
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.io.File; import java.nio.file.Paths;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
@ -37,55 +32,26 @@ import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
/** /**
* The form where user can change / update the properties of the current case * A panel that allows the user to view various properties of the current case
* metadata. * 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 static final long serialVersionUID = 1L;
private Case current = null; private Case current = null;
private static JPanel caller; // panel for error private static JPanel caller; // panel for error
// Shrink a path to fit in targetLength (if necessary), by replaceing part CasePropertiesPanel(Case currentCase, String crDate, String caseDir, Map<Long, String> imgPaths) throws CaseMetadata.CaseMetadataException {
// 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 {
initComponents(); initComponents();
caseNameTextField.setText(currentCase.getName()); caseNameTextField.setText(currentCase.getDisplayName());
String caseNumber = currentCase.getNumber(); String caseNumber = currentCase.getNumber();
if (!caseNumber.equals("")) { if (!caseNumber.isEmpty()) {
caseNumberField.setText(caseNumber); caseNumberField.setText(caseNumber);
} else { } else {
caseNumberField.setText("N/A"); caseNumberField.setText("N/A");
} }
String examiner = currentCase.getExaminer(); String examiner = currentCase.getExaminer();
if (!examiner.equals("")) { if (!examiner.isEmpty()) {
examinerField.setText(examiner); examinerField.setText(examiner);
} else { } else {
examinerField.setText("N/A"); examinerField.setText("N/A");
@ -96,7 +62,7 @@ class CasePropertiesForm extends javax.swing.JPanel {
CaseMetadata caseMetadata = currentCase.getCaseMetadata(); CaseMetadata caseMetadata = currentCase.getCaseMetadata();
if (caseMetadata.getCaseType() == Case.CaseType.SINGLE_USER_CASE) { if (caseMetadata.getCaseType() == Case.CaseType.SINGLE_USER_CASE) {
dbNameField.setText(caseMetadata.getCaseDatabasePath()); dbNameField.setText(Paths.get(caseMetadata.getCaseDirectory(), caseMetadata.getCaseDatabaseName()).toString());
} else { } else {
dbNameField.setText(caseMetadata.getCaseDatabaseName()); dbNameField.setText(caseMetadata.getCaseDatabaseName());
} }
@ -152,24 +118,19 @@ class CasePropertiesForm extends javax.swing.JPanel {
jScrollPane1.setViewportView(jTextArea1); jScrollPane1.setViewportView(jTextArea1);
caseNameLabel.setFont(caseNameLabel.getFont().deriveFont(caseNameLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); 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.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.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.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.setText(org.openide.util.NbBundle.getMessage(CasePropertiesPanel.class, "CasePropertiesPanel.caseNameTextField.text")); // NOI18N
caseNameTextField.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
caseNameTextFieldActionPerformed(evt);
}
});
updateCaseNameButton.setFont(updateCaseNameButton.getFont().deriveFont(updateCaseNameButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); 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() { updateCaseNameButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
updateCaseNameButtonActionPerformed(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.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() { deleteCaseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteCaseButtonActionPerformed(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.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.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.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.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)); caseDirField.setMinimumSize(new java.awt.Dimension(25, 14));
@ -303,13 +264,13 @@ class CasePropertiesForm extends javax.swing.JPanel {
* @param evt The action event * @param evt The action event
*/ */
private void updateCaseNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateCaseNameButtonActionPerformed 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(); String newCaseName = caseNameTextField.getText();
// check if the old and new case name is not equal // check if the old and new case name is not equal
if (!oldCaseName.equals(newCaseName)) { if (!oldCaseName.equals(newCaseName)) {
// check if the case name is empty // check if the case name is empty
if (newCaseName.trim().equals("")) { if (newCaseName.trim().isEmpty()) {
JOptionPane.showMessageDialog(caller, JOptionPane.showMessageDialog(caller,
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.msgDlg.empty.msg"), "CasePropertiesForm.updateCaseName.msgDlg.empty.msg"),
@ -318,6 +279,7 @@ class CasePropertiesForm extends javax.swing.JPanel {
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
} else // check if case Name contain one of this following symbol: } else // check if case Name contain one of this following symbol:
// \ / : * ? " < > | // \ / : * ? " < > |
{
if (newCaseName.contains("\\") || newCaseName.contains("/") || newCaseName.contains(":") if (newCaseName.contains("\\") || newCaseName.contains("/") || newCaseName.contains(":")
|| newCaseName.contains("*") || newCaseName.contains("?") || newCaseName.contains("\"") || 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(); String oldPath = current.getCaseMetadata().getFilePath().toString();
try { try {
current.updateCaseName(oldCaseName, oldPath, newCaseName, oldPath); current.updateCaseName(oldCaseName, oldPath, newCaseName, oldPath);
} catch (Exception ex) { } catch (CaseActionException ex) {
Logger.getLogger(CasePropertiesForm.class.getName()).log(Level.WARNING, "Error: problem updating case name.", ex); //NON-NLS 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); CallableSystemAction.get(CaseDeleteAction.class).actionPerformed(evt);
}//GEN-LAST:event_deleteCaseButtonActionPerformed }//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 // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel caseDirField; private javax.swing.JLabel caseDirField;

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -77,8 +77,13 @@ final class CollaborationMonitor {
* collaborating nodes, informs the user of collaboration tasks on other * collaborating nodes, informs the user of collaboration tasks on other
* nodes using progress bars, and monitors the health of key collaboration * nodes using progress bars, and monitors the health of key collaboration
* services. * 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 * Get the local host name so it can be used to identify the source of
* collaboration tasks broadcast by this node. * collaboration tasks broadcast by this node.
@ -91,9 +96,7 @@ final class CollaborationMonitor {
*/ */
eventPublisher = new AutopsyEventPublisher(); eventPublisher = new AutopsyEventPublisher();
try { try {
Case openedCase = Case.getCurrentCase(); eventPublisher.openRemoteEventChannel(String.format(EVENT_CHANNEL_NAME, eventChannelPrefix));
String channelPrefix = openedCase.getTextIndexName();
eventPublisher.openRemoteEventChannel(String.format(EVENT_CHANNEL_NAME, channelPrefix));
} catch (AutopsyEventException ex) { } catch (AutopsyEventException ex) {
throw new CollaborationMonitorException("Failed to initialize", ex); throw new CollaborationMonitorException("Failed to initialize", ex);
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -18,34 +18,41 @@
*/ */
package org.sleuthkit.autopsy.casemodule; 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.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke; import javax.swing.KeyStroke;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.openide.util.NbBundle; 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 { public class CueBannerPanel extends javax.swing.JPanel {
final private static String title = NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.title.text"); private static final long serialVersionUID = 1L;
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 * This is field is static for the sake of the closeOpenRecentCasesWindow
* method.
*/
private static JDialog recentCasesWindow;
// for error handling public static void closeOpenRecentCasesWindow() {
private static JPanel caller = new JPanel(); if (null != recentCasesWindow) {
recentCasesWindow.setVisible(false);
}
}
public CueBannerPanel() { public CueBannerPanel() {
initComponents(); initComponents();
refresh(); customizeComponents();
enableComponents();
} }
public CueBannerPanel(String welcomeLogo) { public CueBannerPanel(String welcomeLogo) {
@ -55,7 +62,53 @@ public class CueBannerPanel extends javax.swing.JPanel {
ImageIcon icon = new ImageIcon(cl.getResource(welcomeLogo)); ImageIcon icon = new ImageIcon(cl.getResource(welcomeLogo));
autopsyLogo.setIcon(icon); 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 }// </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 private void newCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newCaseButtonActionPerformed
Lookup.getDefault().lookup(CaseNewActionInterface.class).actionPerformed(evt); Lookup.getDefault().lookup(CaseNewActionInterface.class).actionPerformed(evt);
}//GEN-LAST:event_newCaseButtonActionPerformed }//GEN-LAST:event_newCaseButtonActionPerformed
@ -198,37 +242,8 @@ public class CueBannerPanel extends javax.swing.JPanel {
}//GEN-LAST:event_openCaseButtonActionPerformed }//GEN-LAST:event_openCaseButtonActionPerformed
private void openRecentButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openRecentButtonActionPerformed private void openRecentButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openRecentButtonActionPerformed
recentCasesWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
// open the recent cases dialog OpenRecentCasePanel.getInstance(); //refreshes the recent cases table
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.setVisible(true); recentCasesWindow.setVisible(true);
}//GEN-LAST:event_openRecentButtonActionPerformed }//GEN-LAST:event_openRecentButtonActionPerformed
@ -244,29 +259,4 @@ public class CueBannerPanel extends javax.swing.JPanel {
private javax.swing.JLabel openRecentLabel; private javax.swing.JLabel openRecentLabel;
// End of variables declaration//GEN-END:variables // 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();
}
} }

View File

@ -33,7 +33,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgress
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.DataSourceUtils; 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 * A image file data source processor that implements the DataSourceProcessor

View File

@ -30,7 +30,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.DriveUtils; 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 * A local drive data source processor that implements the DataSourceProcessor

View File

@ -29,7 +29,7 @@ import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; 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 * A local/logical files and/or directories data source processor that

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,31 +19,33 @@
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.awt.Component; import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dialog; import java.awt.Dialog;
import java.io.File; import java.io.File;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import javax.swing.SwingUtilities;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer; import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.WizardDescriptor; import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.SystemAction; 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 org.openide.windows.WindowManager;
import java.awt.Cursor; import org.sleuthkit.autopsy.actions.IngestRunningCheck;
import java.util.concurrent.ExecutionException; import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.ingest.IngestManager; 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 { final class NewCaseWizardAction extends CallableSystemAction {
@ -53,39 +55,15 @@ final class NewCaseWizardAction extends CallableSystemAction {
@Override @Override
public void performAction() { public void performAction() {
/* String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
* If ingest is running, do a dialog to warn the user and confirm the String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
* intent to close the current case and leave the ingest process if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
* 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));
runNewCaseWizard(); runNewCaseWizard();
} }
}
private void runNewCaseWizard() { private void runNewCaseWizard() {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
final WizardDescriptor wizardDescriptor = new WizardDescriptor(getNewCaseWizardPanels()); final WizardDescriptor wizardDescriptor = new WizardDescriptor(getNewCaseWizardPanels());
wizardDescriptor.setTitleFormat(new MessageFormat("{0}")); wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
wizardDescriptor.setTitle(NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.newCase.windowTitle.text")); 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 final String caseName = (String) wizardDescriptor.getProperty("caseName"); //NON-NLS
String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS
CaseType caseType = CaseType.values()[(int) wizardDescriptor.getProperty("caseType")]; //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; return null;
} }
@ -109,26 +87,29 @@ final class NewCaseWizardAction extends CallableSystemAction {
protected void done() { protected void done() {
try { try {
get(); get();
/*
* Run the Add Data Source wizard by invoking the Add
* Data Source wizard.
*/
AddImageAction addImageAction = SystemAction.get(AddImageAction.class); AddImageAction addImageAction = SystemAction.get(AddImageAction.class);
addImageAction.actionPerformed(null); 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 logger.log(Level.SEVERE, String.format("Error creating case %s", wizardDescriptor.getProperty("caseName")), ex); //NON-NLS
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(), WindowManager.getDefault().getMainWindow(),
(ex instanceof ExecutionException ? ex.getCause().getMessage() : ex.getMessage()), (ex instanceof ExecutionException ? ex.getCause().getMessage() : ex.getMessage()),
NbBundle.getMessage(this.getClass(), "CaseCreateAction.msgDlg.cantCreateCase.msg"), //NON-NLS NbBundle.getMessage(this.getClass(), "CaseCreateAction.msgDlg.cantCreateCase.msg"), //NON-NLS
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
StartupWindowProvider.getInstance().close(); // RC: Why close and open? StartupWindowProvider.getInstance().close();
if (!Case.isCaseOpen()) {
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
}
});
doFailedCaseCleanup(wizardDescriptor); doFailedCaseCleanup(wizardDescriptor);
} finally {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} }
} }
}.execute(); }.execute();
} else { } else {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
new Thread(() -> { new Thread(() -> {
doFailedCaseCleanup(wizardDescriptor); doFailedCaseCleanup(wizardDescriptor);
}).start(); }).start();
@ -138,11 +119,8 @@ final class NewCaseWizardAction extends CallableSystemAction {
private void doFailedCaseCleanup(WizardDescriptor wizardDescriptor) { private void doFailedCaseCleanup(WizardDescriptor wizardDescriptor) {
String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS
if (createdDirectory != null) { if (createdDirectory != null) {
Case.deleteCaseDirectory(new File(createdDirectory)); FileUtil.deleteDir(new File(createdDirectory));
} }
SwingUtilities.invokeLater(() -> {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
});
} }
/** /**

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -23,9 +23,6 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; 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.ChangeEvent;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import org.openide.DialogDescriptor; import org.openide.DialogDescriptor;
@ -34,7 +31,10 @@ import org.openide.NotifyDescriptor;
import org.openide.WizardDescriptor; import org.openide.WizardDescriptor;
import org.openide.WizardValidationException; import org.openide.WizardValidationException;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case.CaseType; 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; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
/** /**
@ -101,7 +101,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
// fireChangeEvent(); // fireChangeEvent();
// and uncomment the complicated stuff below. // 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. * Adds a listener to changes of the panel's validity.
@ -134,7 +134,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
protected final void fireChangeEvent() { protected final void fireChangeEvent() {
Iterator<ChangeListener> it; Iterator<ChangeListener> it;
synchronized (listeners) { synchronized (listeners) {
it = new HashSet<ChangeListener>(listeners).iterator(); it = new HashSet<>(listeners).iterator();
} }
ChangeEvent ev = new ChangeEvent(this); ChangeEvent ev = new ChangeEvent(this);
while (it.hasNext()) { while (it.hasNext()) {
@ -167,15 +167,15 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
*/ */
@Override @Override
public void readSettings(WizardDescriptor settings) { public void readSettings(WizardDescriptor settings) {
NewCaseVisualPanel1 component = getComponent(); NewCaseVisualPanel1 panel = getComponent();
try { try {
String lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE); String lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE);
component.setCaseParentDir(lastBaseDirectory); panel.setCaseParentDir(lastBaseDirectory);
component.readSettings(); panel.readSettings();
createdDirectory = (String) settings.getProperty("createdDirectory"); //NON-NLS createdDirectory = (String) settings.getProperty("createdDirectory"); //NON-NLS
if (createdDirectory != null && !createdDirectory.equals("")) { if (createdDirectory != null && !createdDirectory.isEmpty()) {
logger.log(Level.INFO, "Deleting a case dir in readSettings(): " + createdDirectory); //NON-NLS logger.log(Level.INFO, "Deleting a case dir in readSettings(): {0}", createdDirectory); //NON-NLS
Case.deleteCaseDirectory(new File(createdDirectory)); FileUtil.deleteDir(new File(createdDirectory));
} }
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.WARNING, "Could not read wizard settings in NewCaseWizardPanel1, ", e); //NON-NLS 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 // if user says yes
try { try {
createDirectory(caseDirPath, getComponent().getCaseType()); createDirectory(caseDirPath, getComponent().getCaseType());
} catch (Exception ex) { } catch (WizardValidationException ex) {
String errorMsg = NbBundle.getMessage(this.getClass(), String errorMsg = NbBundle.getMessage(this.getClass(),
"NewCaseWizardPanel1.validate.errMsg.cantCreateParDir.msg", "NewCaseWizardPanel1.validate.errMsg.cantCreateParDir.msg",
caseParentDir); caseParentDir);
@ -259,7 +259,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
} else { } else {
try { try {
createDirectory(caseDirPath, getComponent().getCaseType()); createDirectory(caseDirPath, getComponent().getCaseType());
} catch (Exception ex) { } catch (WizardValidationException ex) {
String errorMsg = NbBundle String errorMsg = NbBundle
.getMessage(this.getClass(), "NewCaseWizardPanel1.validate.errMsg.cantCreateDir"); .getMessage(this.getClass(), "NewCaseWizardPanel1.validate.errMsg.cantCreateDir");
logger.log(Level.WARNING, errorMsg, ex); 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 // delete the folder if we already created the folder and the error shows up
if (new File(caseDirPath).exists()) { if (new File(caseDirPath).exists()) {
Case.deleteCaseDirectory(new File(caseDirPath)); FileUtil.deleteDir(new File(caseDirPath));
} }
String errorMsg = NbBundle.getMessage(this.getClass(), 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 logger.log(Level.WARNING, "Startup window didn't close as expected.", ex); //NON-NLS
} }
} }
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -27,9 +27,8 @@ import javax.swing.JTable;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.openide.windows.WindowManager; 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. * 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 casePath = casePaths[imagesTable.getSelectedRow()];
final String caseName = caseNames[imagesTable.getSelectedRow()]; final String caseName = caseNames[imagesTable.getSelectedRow()];
if (!casePath.equals("")) { if (!casePath.isEmpty()) {
try { try {
StartupWindowProvider.getInstance().close(); StartupWindowProvider.getInstance().close();
CueBannerPanel.closeOpenRecentCasesWindow(); CueBannerPanel.closeOpenRecentCasesWindow();
@ -114,34 +113,26 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
/* /*
* Open the case. * 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(), JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
NbBundle.getMessage(this.getClass(), "RecentItems.openRecentCase.msgDlg.text", caseName), NbBundle.getMessage(this.getClass(), "RecentItems.openRecentCase.msgDlg.text", caseName),
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
RecentCases.getInstance().removeRecentCase(caseName, casePath); // remove the recent case if it doesn't exist anymore RecentCases.getInstance().removeRecentCase(caseName, casePath); // remove the recent case if it doesn't exist anymore
if (Case.isCaseOpen() == false) {
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
}
} else { } else {
SwingUtilities.invokeLater(() -> {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
});
new Thread(() -> { new Thread(() -> {
try { try {
Case.open(casePath); Case.openAsCurrentCase(casePath);
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
SwingUtilities.invokeLater(() -> {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", casePath), ex); //NON-NLS 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( JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(), WindowManager.getDefault().getMainWindow(),
ex.getMessage(), // Should be user-friendly ex.getMessage(), // Should be user-friendly
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
if (!Case.isCaseOpen()) {
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
}
}); });
} }
}).start(); }).start();
@ -160,7 +151,7 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
public int getRowCount() { public int getRowCount() {
int count = 0; int count = 0;
for (String s : caseNames) { for (String s : caseNames) {
if (!s.equals("")) { if (!s.isEmpty()) {
count++; count++;
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2014 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -30,13 +30,13 @@ import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import org.openide.filesystems.FileUtil;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter; 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.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
/** /**
* The action in this class is to clear the list of "Recent Cases". The * 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 { final class RecentCases extends CallableSystemAction implements Presenter.Menu {
static final int LENGTH = 6; private static final long serialVersionUID = 1L;
static final String NAME_PROP_KEY = "LBL_RecentCase_Name"; //NON-NLS private static final int LENGTH = 6;
static final String PATH_PROP_KEY = "LBL_RecentCase_Path"; //NON-NLS private static final String NAME_PROP_KEY = "LBL_RecentCase_Name"; //NON-NLS
static final RecentCase BLANK_RECENTCASE = new RecentCase("", ""); 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 static RecentCases instance = new RecentCases();
private final Deque<RecentCase> recentCases; // newest case is last case
private Deque<RecentCase> recentCases; // newest case is last case
/** /**
* Gets the instance of the RecentCases singleton. * Gets the instance of the RecentCases singleton.
@ -61,8 +60,8 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
* @return INSTANCE the RecentCases singleton * @return INSTANCE the RecentCases singleton
*/ */
static public RecentCases getInstance() { static public RecentCases getInstance() {
INSTANCE.refreshRecentCases(); instance.refreshRecentCases();
return INSTANCE; return instance;
} }
/** /**
@ -84,7 +83,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
} }
// Load recentCases from properties // Load recentCases from properties
recentCases = new LinkedList<RecentCase>(); recentCases = new LinkedList<>();
for (int i = 0; i < LENGTH; i++) { for (int i = 0; i < LENGTH; i++) {
final RecentCase rc = new RecentCase(getName(i), getPath(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 * @return true if the case exists, false otherwise
*/ */
boolean exists() { boolean exists() {
return !(name.equals("") || path.equals("") || !new File(path).exists()); return !(name.isEmpty() || path.isEmpty() || !new File(path).exists());
} }
// netbeans autogenerated hashCode // netbeans autogenerated hashCode
@ -211,7 +210,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
* exist. * exist.
*/ */
private void refreshRecentCases() { private void refreshRecentCases() {
List<RecentCase> toDelete = new ArrayList<RecentCase>(); List<RecentCase> toDelete = new ArrayList<>();
for (RecentCase rc : recentCases) { for (RecentCase rc : recentCases) {
if (!rc.exists()) { if (!rc.exists()) {
toDelete.add(rc); toDelete.add(rc);
@ -256,14 +255,14 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
*/ */
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
UpdateRecentCases.hasRecentCase = false; UpdateRecentCases.setHasRecentCase(false);
recentCases.clear(); recentCases.clear();
try { try {
// clear the properties file // clear the properties file
storeRecentCases(); 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 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 { try {
storeRecentCases(); 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 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 { try {
storeRecentCases(); 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 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 // write the properties file
try { try {
storeRecentCases(); 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 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; int i = 0;
String currentCaseName = null; String currentCaseName = null;
try { try {
currentCaseName = Case.getCurrentCase().getName(); currentCaseName = Case.getCurrentCase().getDisplayName();
} catch (IllegalStateException ex) { } catch (IllegalStateException ex) {
// in case there is no current case. // in case there is no current case.
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -18,111 +18,61 @@
*/ */
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.awt.EventQueue;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.io.File; import java.util.logging.Level;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import java.awt.Cursor; import org.sleuthkit.autopsy.actions.IngestRunningCheck;
import java.util.logging.Level;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.sleuthkit.autopsy.coreutils.Logger; 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 { class RecentItems implements ActionListener {
private static final Logger logger = Logger.getLogger(RecentItems.class.getName()); private static final Logger logger = Logger.getLogger(RecentItems.class.getName());
private final String caseName;
private final String caseMetaDataFilePath; 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 caseName The name of the case.
* @param caseMetaDataFilePath The path to the case metadata file. * @param caseMetaDataFilePath The path to the case metadata file.
*/ */
public RecentItems(String caseName, String caseMetaDataFilePath) { RecentItems(String caseName, String caseMetaDataFilePath) {
this.caseName = caseName;
this.caseMetaDataFilePath = caseMetaDataFilePath; this.caseMetaDataFilePath = caseMetaDataFilePath;
} }
/** /**
* Opens the recent case. * Opens the case associated with the action.
* *
* @param e the action event * @param e the action event
*/ */
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
/* String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
* If ingest is running, do a dialog to warn the user and confirm the String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
* intent to close the current case and leave the ingest process if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
* 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));
});
new Thread(() -> { new Thread(() -> {
try { try {
Case.open(caseMetaDataFilePath); Case.openAsCurrentCase(caseMetaDataFilePath);
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
SwingUtilities.invokeLater(() -> {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetaDataFilePath), ex); //NON-NLS 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( JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(), WindowManager.getDefault().getMainWindow(),
ex.getMessage(), // Should be user-friendly ex.getMessage(),
NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
if (!Case.isCaseOpen()) {
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
}
}); });
} }
}).start(); }).start();

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -34,19 +34,21 @@ import java.util.Date;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case.CaseType; 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.UserPreferences;
import org.sleuthkit.autopsy.core.UserPreferencesException; import org.sleuthkit.autopsy.core.UserPreferencesException;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.datamodel.CaseDbConnectionInfo; import org.sleuthkit.datamodel.CaseDbConnectionInfo;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
/** /**
* Import a case from single-user to multi-user. * Import a case from single-user to multi-user.
*
* DO NOT USE, NEEDS TO BE UPDATED
*/ */
public class SingleUserCaseConverter { 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 AUTOPSY_DB_FILE = "autopsy.db"; //NON-NLS
private static final String DOTAUT = CaseMetadata.getFileExtension(); //NON-NLS private static final String DOTAUT = CaseMetadata.getFileExtension(); //NON-NLS
private static final String TIMELINE_FOLDER = "Timeline"; //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 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); //NON-NLS
Date date = new Date(); Date date = new Date();
String dbName = Case.sanitizeCaseName(icd.getNewCaseName()) + "_" + dateFormat.format(date); //NON-NLS String dbName = Case.sanitizeCaseName(icd.getNewCaseName()) + "_" + dateFormat.format(date); //NON-NLS
String solrName = dbName;
icd.setPostgreSQLDbName(dbName); icd.setPostgreSQLDbName(dbName);
// Copy items to new hostname folder structure // Copy items to new hostname folder structure
@ -195,9 +196,10 @@ public class SingleUserCaseConverter {
CaseMetadata newCaseMetadata = new CaseMetadata(icd.getCaseOutputFolder().toString(), CaseMetadata newCaseMetadata = new CaseMetadata(icd.getCaseOutputFolder().toString(),
CaseType.MULTI_USER_CASE, CaseType.MULTI_USER_CASE,
icd.getNewCaseName(), icd.getNewCaseName(),
icd.getNewCaseName(),
oldCaseMetadata.getCaseNumber(), oldCaseMetadata.getCaseNumber(),
oldCaseMetadata.getExaminer(), oldCaseMetadata.getExaminer(),
dbName, solrName); dbName);
// Set created date. This calls writefile, no need to call it again // Set created date. This calls writefile, no need to call it again
newCaseMetadata.setCreatedDate(oldCaseMetadata.getCreatedDate()); newCaseMetadata.setCreatedDate(oldCaseMetadata.getCreatedDate());
newCaseMetadata.setCreatedByVersion(oldCaseMetadata.getCreatedByVersion()); newCaseMetadata.setCreatedByVersion(oldCaseMetadata.getCreatedByVersion());

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -18,51 +18,43 @@
*/ */
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.datamodel.SleuthkitCase;
/** /**
* This class enables capturing errors and batching them for reporting on a * Acts as a bridge between the Sleuthkit Java bindings classes and Autopsy by
* no-more-than-x number of seconds basis. When created, you specify the minimum * implementing the SleuthkitCase$ErrorObserver interface. All errors are
* time between user notifications. When the time between notifications has * written to the Autopsy logs. If a GUI is running, errors are also batched up
* expired, the next error encountered will cause a report to be shown to the * and reported periodically to the user via the notification area in the lower
* user. * 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 newProblems;
private long totalProblems; private long totalProblems;
private long lastReportedDate; private long lastReportedDate;
private final int milliSecondsBetweenReports;
private final String message;
/** /**
* Create a new IntervalErrorReprotData instance and subscribe for TSK error * Create a new IntervalErrorReprotData instance and subscribe for TSK error
* notifications for the current case. * 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. * @param secondsBetweenReports Minimum number of seconds between reports.
* It will not warn more frequently than this. * It will not warn more frequently than this.
* @param message The message that will be shown when warning * @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.newProblems = 0;
this.totalProblems = 0; this.totalProblems = 0;
this.lastReportedDate = 0; // arm the first warning by choosing zero this.lastReportedDate = 0; // arm the first warning by choosing zero
this.milliSecondsBetweenReports = secondsBetweenReports * 1000; // convert to milliseconds this.milliSecondsBetweenReports = secondsBetweenReports * 1000; // convert to milliseconds
this.message = message; 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 context The context in which the error occurred.
* @param errorMessage A description of the error that 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.newProblems += 1;
this.totalProblems += newProblems; this.totalProblems += newProblems;
long currentTimeStamp = System.currentTimeMillis(); long currentTimeStamp = System.currentTimeMillis();
if ((currentTimeStamp - lastReportedDate) > milliSecondsBetweenReports) { if ((currentTimeStamp - lastReportedDate) > milliSecondsBetweenReports) {
this.lastReportedDate = currentTimeStamp; this.lastReportedDate = currentTimeStamp;
MessageNotifyUtil.Notify.error(message, context + ", " + errorMessage + " " MessageNotifyUtil.Notify.error(message, context + ", " + errorMessage + " "
+ this.newProblems + " " + this.newProblems + " "
+ NbBundle.getMessage(IntervalErrorReportData.class, "IntervalErrorReport.NewIssues") + NbBundle.getMessage(SleuthkitErrorReporter.class, "IntervalErrorReport.NewIssues")
+ " " + this.totalProblems + " " + " " + this.totalProblems + " "
+ NbBundle.getMessage(IntervalErrorReportData.class, "IntervalErrorReport.TotalIssues") + NbBundle.getMessage(SleuthkitErrorReporter.class, "IntervalErrorReport.TotalIssues")
+ "."); + ".");
this.newProblems = 0; this.newProblems = 0;
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,25 +19,22 @@
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.JFrame;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.openide.windows.WindowManager; 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) @ServiceProvider(service = StartupWindowInterface.class)
public final class StartupWindow extends JDialog implements StartupWindowInterface { 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 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; private static CueBannerPanel welcomeWindow;
public StartupWindow() { public StartupWindow() {
@ -45,37 +42,18 @@ public final class StartupWindow extends JDialog implements StartupWindowInterfa
init(); init();
} }
/**
* Shows the startup window.
*/
private void init() { private void init() {
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
// set the popUp window / JFrame
setSize(DIMENSIONS); 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(); welcomeWindow = new CueBannerPanel();
// add the command to close the window to the button on the Volume Detail Panel
welcomeWindow.setCloseButtonActionListener(new ActionListener() { welcomeWindow.setCloseButtonActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
close(); close();
} }
}); });
add(welcomeWindow); add(welcomeWindow);
pack(); pack();
setResizable(false); setResizable(false);
} }
@Override @Override
@ -85,9 +63,6 @@ public final class StartupWindow extends JDialog implements StartupWindowInterfa
setVisible(true); setVisible(true);
} }
/**
* Closes the startup window.
*/
@Override @Override
public void close() { public void close() {
this.setVisible(false); this.setVisible(false);

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -30,15 +30,20 @@ import org.openide.util.actions.SystemAction;
*/ */
class UpdateRecentCases extends JMenuItem implements DynamicMenuContent { class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
int length; private static final long serialVersionUID = 1L;
static boolean hasRecentCase = false; private static int NUM_CASES_TO_DISPLAY;
private static boolean hasRecentCase = false;
/** /**
* the constructor * the constructor
*/ */
UpdateRecentCases() { UpdateRecentCases() {
// display last 5 cases. // 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() { public JComponent[] getMenuPresenters() {
String[] caseName = RecentCases.getInstance().getRecentCaseNames(); String[] caseName = RecentCases.getInstance().getRecentCaseNames();
String[] casePath = RecentCases.getInstance().getRecentCasePaths(); 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 // 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(""))) { if ((!caseName[i].equals(""))) {
JMenuItem menuItem = new JMenuItem(caseName[i]); JMenuItem menuItem = new JMenuItem(caseName[i]);
menuItem.setActionCommand(caseName[i].toUpperCase()); menuItem.setActionCommand(caseName[i].toUpperCase());
@ -68,11 +73,11 @@ class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
// if it has recent case, create clear menu // if it has recent case, create clear menu
if (hasRecentCase) { if (hasRecentCase) {
comps[length] = new JSeparator(); comps[NUM_CASES_TO_DISPLAY] = new JSeparator();
JMenuItem clearMenu = new JMenuItem( JMenuItem clearMenu = new JMenuItem(
NbBundle.getMessage(UpdateRecentCases.class, "UpdateRecentCases.menuItem.clearRecentCases.text")); NbBundle.getMessage(UpdateRecentCases.class, "UpdateRecentCases.menuItem.clearRecentCases.text"));
clearMenu.addActionListener(SystemAction.get(RecentCases.class)); clearMenu.addActionListener(SystemAction.get(RecentCases.class));
comps[length + 1] = clearMenu; comps[NUM_CASES_TO_DISPLAY + 1] = clearMenu;
} // otherwise, just create a disabled empty menu } // otherwise, just create a disabled empty menu
else { else {
comps = new JComponent[1]; 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 * Updates the Recent Cases menu items.
* processing.
* *
* @param jcs the previously used menu items returned by previous call to * @param menuItems A set of Recent Case menu items to be updated.
* getMenuPresenters() or synchMenuPresenters()
* *
* @return menu a new set of items to show in menu. Can be either an updated * @return A updated set of recent case menu items to show in the Recent
* old set of instances or a completely new one. * Cases menu.
*/ */
@Override @Override
public JComponent[] synchMenuPresenters(JComponent[] jcs) { public JComponent[] synchMenuPresenters(JComponent[] menuItems) {
return getMenuPresenters(); return getMenuPresenters();
} }
} }

View File

@ -2,7 +2,7 @@
* *
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* Copyright 2012 42six Solutions. * Copyright 2012 42six Solutions.
* Contact: aebadirad <at> 42six <dot> com * Contact: aebadirad <at> 42six <dot> com

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -18,129 +18,89 @@
*/ */
package org.sleuthkit.autopsy.coordinationservice; package org.sleuthkit.autopsy.coordinationservice;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.curator.RetryPolicy; import org.apache.curator.RetryPolicy;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex; import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock; 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.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.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 * A coordination service for maintaining configuration information and
* distributed synchronization using a shared hierarchical namespace of nodes. * providing distributed synchronization using a shared hierarchical namespace
* of nodes.
*
* TODO (JIRA 2205): Simple refactoring for general use.
*/ */
public final class CoordinationService { 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 CuratorFramework curator = null;
private static final Map<String, CoordinationService> rootNodesToServices = new HashMap<>(); 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 SESSION_TIMEOUT_MILLISECONDS = 300000;
private static final int CONNECTION_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_SESSION_TIMEOUT_MILLIS = 3000;
private static final int ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS = 15000; 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 * Determines if ZooKeeper is accessible with the current settings. Closes
* namespace. * 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. * @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. * 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) { if (null == curator) {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3); RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
// When run in Solr, ZooKeeper defaults to Solr port + 1000
int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET; int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET;
String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort; String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort;
curator = CuratorFrameworkFactory.newClient(connectString, SESSION_TIMEOUT_MILLISECONDS, CONNECTION_TIMEOUT_MILLISECONDS, retryPolicy); curator = CuratorFrameworkFactory.newClient(connectString, SESSION_TIMEOUT_MILLISECONDS, CONNECTION_TIMEOUT_MILLISECONDS, retryPolicy);
@ -157,7 +117,7 @@ public final class CoordinationService {
CoordinationService service; CoordinationService service;
try { try {
service = new CoordinationService(rootNode); service = new CoordinationService(rootNode);
} catch (Exception ex) { } catch (IOException | InterruptedException | KeeperException | CoordinationServiceException ex) {
curator = null; curator = null;
throw new CoordinationServiceException("Failed to create coordination service", ex); 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 * Constructs an instance of the coordination service for a specific
* specific namespace. * namespace.
* *
* @param rootNodeName The name of the root node that defines the 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()) { if (false == isZooKeeperAccessible()) {
throw new Exception("Unable to access ZooKeeper"); throw new CoordinationServiceException("Unable to access ZooKeeper");
} }
String rootNode = rootNodeName; String rootNode = rootNodeName;
@ -191,6 +154,8 @@ public final class CoordinationService {
if (ex.code() != KeeperException.Code.NODEEXISTS) { if (ex.code() != KeeperException.Code.NODEEXISTS) {
throw ex; throw ex;
} }
} catch (Exception ex) {
throw new CoordinationServiceException("Curator experienced an error", ex);
} }
categoryNodeToPath.put(node.getDisplayName(), nodePath); categoryNodeToPath.put(node.getDisplayName(), nodePath);
} }
@ -201,6 +166,9 @@ public final class CoordinationService {
* in the namespace managed by this coordination service. Blocks until the * in the namespace managed by this coordination service. Blocks until the
* lock is obtained or the time out expires. * 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 category The desired category in the namespace.
* @param nodePath The node path to use as the basis for the lock. * @param nodePath The node path to use as the basis for the lock.
* @param timeOut Length of the time out. * @param timeOut Length of the time out.
@ -236,6 +204,9 @@ public final class CoordinationService {
* in the namespace managed by this coordination service. Returns * in the namespace managed by this coordination service. Returns
* immediately if the lock can not be acquired. * 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 category The desired category in the namespace.
* @param nodePath The node path to use as the basis for the lock. * @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 * the namespace managed by this coordination service. Blocks until the lock
* is obtained or the time out expires. * 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 category The desired category in the namespace.
* @param nodePath The node path to use as the basis for the lock. * @param nodePath The node path to use as the basis for the lock.
* @param timeOut Length of the time out. * @param timeOut Length of the time out.
@ -297,6 +271,9 @@ public final class CoordinationService {
* the namespace managed by this coordination service. Returns immediately * the namespace managed by this coordination service. Returns immediately
* if the lock can not be acquired. * 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 category The desired category in the namespace.
* @param nodePath The node path to use as the basis for the lock. * @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 * Exception type thrown by the coordination service.
* the connection prior to returning.
*
* @return true if a connection was achieved, false otherwise
*/ */
private static boolean isZooKeeperAccessible() { public final static class CoordinationServiceException extends Exception {
boolean result = false;
Object workerThreadWaitNotifyLock = new Object();
int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET;
String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort;
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 { try {
ZooKeeper zooKeeper = new ZooKeeper(connectString, ZOOKEEPER_SESSION_TIMEOUT_MILLIS, this.interProcessLock.release();
(WatchedEvent event) -> { } catch (Exception ex) {
throw new CoordinationServiceException(String.format("Failed to release the lock on %s", nodePath), ex);
}
}
synchronized (workerThreadWaitNotifyLock) { @Override
workerThreadWaitNotifyLock.notify(); public void close() throws CoordinationServiceException {
} release();
}); }
synchronized (workerThreadWaitNotifyLock) { }
workerThreadWaitNotifyLock.wait(ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS);
} /**
ZooKeeper.States state = zooKeeper.getState(); * Category nodes are the immediate children of the root node of a shared
if (state == ZooKeeper.States.CONNECTED || state == ZooKeeper.States.CONNECTEDREADONLY) { * hierarchical namespace managed by a coordination service.
result = true; */
} public enum CategoryNode {
zooKeeper.close();
} catch (InterruptedException | IOException ignored) { CASES("cases"),
} MANIFESTS("manifests"),
return result; CONFIG("config"),
RESOURCE("resource");
private final String displayName;
private CategoryNode(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2016-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,7 +19,7 @@
package org.sleuthkit.autopsy.coordinationservice; package org.sleuthkit.autopsy.coordinationservice;
/** /**
* Namespace elements for auto ingest coordination service nodes. * Root node for Autopsy coordination service namespace.
*/ */
public final class CoordinationServiceNamespace { public final class CoordinationServiceNamespace {
private static final String ROOT = "autopsy"; private static final String ROOT = "autopsy";

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013-2015 Basis Technology Corp. * Copyright 2013-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -24,46 +24,70 @@ package org.sleuthkit.autopsy.core;
*/ */
public class RuntimeProperties { public class RuntimeProperties {
private static boolean coreComponentsActive = true; private static boolean runningWithGUI = true;
private static boolean coreComponentsActiveSet = false; private static boolean runningWithGUIFlagHasBeenSet = false;
/** /**
* Sets or unsets a flag indicating whether or not the core Autopsy UI * Sets or unsets a flag indicating whether or not the application is
* components and user interactions with those components via menus, message * running with a GUI. The flag can only be set once per application
* boxes, NetBeans progress handles, etc., are enabled. * innvocation.
* <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.
* *
* @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) { public synchronized static void setRunningWithGUI(boolean runningWithGUI) throws RuntimePropertiesException {
if (!coreComponentsActiveSet) { if (!runningWithGUIFlagHasBeenSet) {
RuntimeProperties.coreComponentsActive = coreComponentsActive; RuntimeProperties.runningWithGUI = runningWithGUI;
coreComponentsActiveSet = true; 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 * Gets a flag indicating whether or not the application is running with a
* user interactions with those components via menus, message boxes, * GUI.
* 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.
* *
* @return True or false. * @return True or false.
*/ */
public synchronized static boolean coreComponentsAreActive() { public synchronized static boolean runningWithGUI() {
return coreComponentsActive; return runningWithGUI;
} }
/** /**
* Private constructor to prevent creation of instances of this class. * Private constructor to prevent creation of instances of this class.
*/ */
private RuntimeProperties() { 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);
}
}
} }
}

View File

@ -1,7 +1,7 @@
CTL_DataContentAction=DataContent CTL_DataContentAction=DataContent
CTL_DataContentTopComponent=Data Content CTL_DataContentTopComponent=Data Content
CTL_CustomAboutAction=About CTL_CustomAboutAction=About
OptionsCategory_Name_General=Autopsy OptionsCategory_Name_General=View
OptionsCategory_Keywords_General=Autopsy Options OptionsCategory_Keywords_General=Autopsy Options
HINT_DataContentTopComponent=This is a DataContent window HINT_DataContentTopComponent=This is a DataContent window
HINT_NodeTableTopComponent=This is a DataResult window HINT_NodeTableTopComponent=This is a DataResult window

View File

@ -1,5 +1,4 @@
CTL_DataContentAction=\u30c7\u30fc\u30bf\u30b3\u30f3\u30c6\u30f3\u30c4 CTL_DataContentAction=\u30c7\u30fc\u30bf\u30b3\u30f3\u30c6\u30f3\u30c4
OptionsCategory_Name_General=Autopsy
OptionsCategory_Keywords_General=Autopsy\u30aa\u30d7\u30b7\u30e7\u30f3 OptionsCategory_Keywords_General=Autopsy\u30aa\u30d7\u30b7\u30e7\u30f3
CTL_CustomAboutAction=Autopsy\u306b\u3064\u3044\u3066 CTL_CustomAboutAction=Autopsy\u306b\u3064\u3044\u3066
CTL_DataContentTopComponent=\u30c7\u30fc\u30bf\u30b3\u30f3\u30c6\u30f3\u30c4 CTL_DataContentTopComponent=\u30c7\u30fc\u30bf\u30b3\u30f3\u30c6\u30f3\u30c4

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -22,7 +22,6 @@ import java.beans.PropertyChangeEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JTabbedPane; import javax.swing.JTabbedPane;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
@ -30,6 +29,7 @@ import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent; 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 * 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") //@TopComponent.OpenActionRegistration(displayName = "#CTL_DataContentAction", preferredID = "DataContentTopComponent")
public final class DataContentTopComponent extends TopComponent implements DataContent { 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 // reference to the "default" TC that always stays open
private static DataContentTopComponent defaultInstance; 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 // 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 // the content panel holding tabs with content viewers
private final DataContentPanel dataContentPanel; private final DataContentPanel dataContentPanel;
// contains a list of the undocked TCs // 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 PREFERRED_ID = "DataContentTopComponent"; //NON-NLS
private static final String DEFAULT_NAME = NbBundle.getMessage(DataContentTopComponent.class, "CTL_DataContentTopComponent"); private static final String DEFAULT_NAME = NbBundle.getMessage(DataContentTopComponent.class, "CTL_DataContentTopComponent");
private static final String TOOLTIP_TEXT = NbBundle.getMessage(DataContentTopComponent.class, "HINT_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); dataContentPanel = new DataContentPanel(isDefault);
add(dataContentPanel); add(dataContentPanel);
putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.valueOf(isDefault)); // prevent option to close compoment in GUI putClientProperty(TopComponent.PROP_CLOSING_DISABLED, isDefault); // prevent option to close compoment in GUI
logger.log(Level.INFO, "Created DataContentTopComponent instance: " + this); //NON-NLS 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; 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 * Gets default instance. Do not use directly: reserved for *.settings files
* only, i.e. deserialization routines; otherwise you could get a * only, i.e. deserialization routines; otherwise you could get a
* non-deserialized defaultInstance. To obtain the singleton instance, use * non-deserialized defaultInstance. To obtain the singleton instance, use
* {@link #findInstance}. * findInstance.
*
* @return
*/ */
public static synchronized DataContentTopComponent getDefault() { public static synchronized DataContentTopComponent getDefault() {
if (defaultInstance == null) { if (defaultInstance == null) {
@ -118,8 +108,10 @@ public final class DataContentTopComponent extends TopComponent implements DataC
} }
/** /**
* Obtain the default DataContentTopComponent defaultInstance. Never call * Obtain the default DataContentTopComponent default instance. Never call
* {@link #getDefault} directly! * getDefault directly!
*
* @return The default DataContentTopComponent.
*/ */
public static synchronized DataContentTopComponent findInstance() { public static synchronized DataContentTopComponent findInstance() {
TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
@ -171,7 +163,12 @@ public final class DataContentTopComponent extends TopComponent implements DataC
@Override @Override
public boolean canClose() { 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 @Override
@ -195,4 +192,18 @@ public final class DataContentTopComponent extends TopComponent implements DataC
public static List<DataContentTopComponent> getNewWindowList() { public static List<DataContentTopComponent> getNewWindowList() {
return newWindowList; 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
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -276,7 +276,9 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
if (!Case.isCaseOpen()) { try {
Case.getCurrentCase();
} catch (IllegalStateException ex) {
// Handle the in-between condition when case is being closed // Handle the in-between condition when case is being closed
// and legacy selection events are pumped. // and legacy selection events are pumped.
return; return;
@ -443,7 +445,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
@Override @Override
public List<DataResultViewer> getViewers() { public List<DataResultViewer> getViewers() {
List<DataResultViewer> ret = new ArrayList<DataResultViewer>(); List<DataResultViewer> ret = new ArrayList<>();
for (UpdateWrapper w : viewers) { for (UpdateWrapper w : viewers) {
ret.add(w.getViewer()); ret.add(w.getViewer());
} }
@ -452,7 +454,12 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
} }
public boolean canClose() { 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 @Override

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -314,7 +314,12 @@ public class DataResultTopComponent extends TopComponent implements DataResult,
@Override @Override
public boolean canClose() { 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;
} }
/** /**

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -25,6 +25,7 @@ import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.SwingUtilities;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo; import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException; import javax.swing.UnsupportedLookAndFeelException;
@ -32,7 +33,9 @@ import org.netbeans.spi.sendopts.OptionProcessor;
import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI; import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI;
import org.openide.modules.ModuleInstall; import org.openide.modules.ModuleInstall;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException; import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.casemodule.CaseMetadata;
@ -50,7 +53,7 @@ public class Installer extends ModuleInstall {
private static Installer instance; private static Installer instance;
public synchronized static Installer getDefault() { public synchronized static Installer getDefault() {
if (instance == null) { if (null == instance) {
instance = new Installer(); instance = new Installer();
} }
return instance; return instance;
@ -80,21 +83,18 @@ public class Installer extends ModuleInstall {
if (processor instanceof OpenFromArguments) { if (processor instanceof OpenFromArguments) {
OpenFromArguments argsProcessor = (OpenFromArguments) processor; OpenFromArguments argsProcessor = (OpenFromArguments) processor;
final String caseFile = argsProcessor.getDefaultArg(); final String caseFile = argsProcessor.getDefaultArg();
if (caseFile != null && !caseFile.equals("") && caseFile.endsWith(CaseMetadata.getFileExtension()) && new File(caseFile).exists()) { //NON-NLS if (caseFile != null && !caseFile.isEmpty() && caseFile.endsWith(CaseMetadata.getFileExtension()) && new File(caseFile).exists()) { //NON-NLS
new Thread(() -> {
try { try {
Case.open(caseFile); Case.openAsCurrentCase(caseFile);
} catch (Exception ex) { } catch (CaseActionException ex) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseFile), ex); //NON-NLS logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseFile), ex); //NON-NLS
} }
}).start();
return; return;
} }
} }
} }
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
}); });
} }
@Override @Override
@ -105,19 +105,10 @@ public class Installer extends ModuleInstall {
@Override @Override
public void close() { public void close() {
new Thread(() -> { new Thread(() -> {
String caseDirName = null;
try { try {
if (Case.isCaseOpen()) { Case.closeCurrentCase();
Case currentCase = Case.getCurrentCase();
caseDirName = currentCase.getCaseDirectory();
currentCase.closeCase();
}
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
logger.log(Level.SEVERE, String.format("Error closing case with case directory %s", (null != caseDirName ? caseDirName : "?")), ex); //NON-NLS logger.log(Level.SEVERE, "Error closing current case", ex); //NON-NLS
} catch (IllegalStateException ignored) {
/*
* No current case. Case.isCaseOpen is not reliable.
*/
} }
}).start(); }).start();
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013-15 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -140,12 +140,12 @@ public class MediaViewImagePanel extends JPanel implements DataContentViewerMedi
private void showErrorNode(String errorMessage, AbstractFile file) { private void showErrorNode(String errorMessage, AbstractFile file) {
final Button externalViewerButton = new Button(Bundle.MediaViewImagePanel_externalViewerButton_text(), new ImageView(EXTERNAL)); 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 * TODO: why is the name passed into the action constructor? it
* means we duplicate this string all over the place -jm * 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 .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 = ImageUtils.newReadImageTask(file);
readImageTask.setOnSucceeded(succeeded -> { readImageTask.setOnSucceeded(succeeded -> {
//Note that all error conditions are allready logged in readImageTask.succeeded()
if (!Case.isCaseOpen()) { if (!Case.isCaseOpen()) {
/* /*
* handle in-between condition when case is being closed and * Handle the in-between condition when case is being closed
* an image was previously selected * and an image was previously selected
* *
* NOTE: I think this is unnecessary -jm * NOTE: I think this is unnecessary -jm
*/ */
@ -200,7 +199,7 @@ public class MediaViewImagePanel extends JPanel implements DataContentViewerMedi
readImageTask.setOnFailed(failed -> { readImageTask.setOnFailed(failed -> {
if (!Case.isCaseOpen()) { 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 * an image was previously selected
* *
* NOTE: I think this is unnecessary -jm * NOTE: I think this is unnecessary -jm

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.corecomponents;
import org.openide.nodes.FilterNode; import org.openide.nodes.FilterNode;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.util.NbBundle; 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 * 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) * The constructor should include column order key. (See getColumnOrderKey)
*/ */
public TableFilterNode(Node wrappedNode, boolean createChildren) { public TableFilterNode(Node wrappedNode, boolean createChildren) {
super(wrappedNode, TableFilterChildren.createInstance(wrappedNode, createChildren)); super(wrappedNode, TableFilterChildren.createInstance(wrappedNode, createChildren) , Lookups.proxy(wrappedNode));
this.createChildren = createChildren; this.createChildren = createChildren;
} }

View File

@ -315,4 +315,29 @@ public class UNCPathUtilities {
} }
return driveMap; 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;
}
} }

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.logging.Level; import java.util.logging.Level;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
@ -130,9 +131,11 @@ public class ArtifactStringContent implements StringContent {
case INTEGER: case INTEGER:
case LONG: case LONG:
case DOUBLE: case DOUBLE:
case BYTE:
buffer.append(attr.getDisplayString()); buffer.append(attr.getDisplayString());
break; break;
case BYTE:
buffer.append(Arrays.toString(attr.getValueBytes()));
break;
case DATETIME: case DATETIME:
long epoch = attr.getValueLong(); long epoch = attr.getValueLong();
String time = "0000-00-00 00:00:00"; String time = "0000-00-00 00:00:00";

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -404,7 +404,8 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID() if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID() || attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_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) { } else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated)); map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
} else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID() } else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID()
@ -452,13 +453,6 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
forLookup.add(content); 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()])); 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")); 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 @Override
public boolean isLeafTypeNode() { public boolean isLeafTypeNode() {

View File

@ -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);
}

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -27,17 +27,13 @@ import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
@ActionID( @ActionID(category = "Help", id = "org.sleuthkit.autopsy.diagnostics.PerformancePanelAction")
category = "Help", @ActionRegistration(displayName = "#CTL_PerformancePanelAction", lazy = true)
id = "org.sleuthkit.autopsy.diagnostics.PerformancePanelAction"
)
@ActionRegistration(
displayName = "#CTL_PerformancePanelAction",
lazy=true
)
@ActionReference(path = "Menu/Help", position = 1437) @ActionReference(path = "Menu/Help", position = 1437)
public final class PerformancePanelAction extends CallableSystemAction { public final class PerformancePanelAction extends CallableSystemAction {
private static final long serialVersionUID = 1L;
@Override @Override
public void performAction() { public void performAction() {
JDialog dialog = new PerformancePanel(); JDialog dialog = new PerformancePanel();
@ -56,8 +52,9 @@ public final class PerformancePanelAction extends CallableSystemAction {
@Override @Override
public boolean asynchronous() { public boolean asynchronous() {
return false; // run on edt return false;
} }
@Override @Override
public String getName() { public String getName() {
return NbBundle.getMessage(PerformancePanelAction.class, "CTL_PerformancePanelAction"); return NbBundle.getMessage(PerformancePanelAction.class, "CTL_PerformancePanelAction");

View File

@ -353,13 +353,18 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
// change the cursor to "waiting cursor" for this operation // change the cursor to "waiting cursor" for this operation
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try { try {
if (Case.isCaseOpen()) { Case currentCase = null;
Case currentCase = Case.getCurrentCase(); try {
currentCase = Case.getCurrentCase();
} catch (IllegalStateException ex) {
/*
* No open case.
*/
}
// close the top component if there's no image in this case // close the top component if there's no image in this case
if (currentCase.hasData() == false) { if (null == currentCase || currentCase.hasData() == false) {
//this.close(); ((TreeView) this.jScrollPane1).setRootVisible(false); // hide the root
((BeanTreeView) this.jScrollPane1).setRootVisible(false); // hide the root
} else { } else {
// if there's at least one image, load the image and open the top component // if there's at least one image, load the image and open the top component
List<Object> items = new ArrayList<>(); List<Object> items = new ArrayList<>();
@ -399,7 +404,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
em.setRootContext(root); em.setRootContext(root);
em.getRootContext().setName(currentCase.getName()); em.getRootContext().setName(currentCase.getName());
em.getRootContext().setDisplayName(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 // Reset the forward and back lists because we're resetting the root context
resetHistory(); resetHistory();
@ -438,13 +443,12 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
if (childNodes.getNodesCount() > 0) { if (childNodes.getNodesCount() > 0) {
try { try {
em.setSelectedNodes(new Node[]{childNodes.getNodeAt(0)}); 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 LOGGER.log(Level.SEVERE, "Error setting default selected node.", ex); //NON-NLS
} }
} }
} }
}
} finally { } finally {
this.setCursor(null); this.setCursor(null);
} }
@ -494,7 +498,12 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
@Override @Override
public boolean canClose() { 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;
} }
/** /**
@ -540,7 +549,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
*/ */
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
if (RuntimeProperties.coreComponentsAreActive()) { if (RuntimeProperties.runningWithGUI()) {
String changed = evt.getPropertyName(); String changed = evt.getPropertyName();
if (changed.equals(Case.Events.CURRENT_CASE.toString())) { // changed current case if (changed.equals(Case.Events.CURRENT_CASE.toString())) { // changed current case
// When a case is closed, the old value of this property is the // When a case is closed, the old value of this property is the

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -94,7 +94,7 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
} catch (ParseException ex) { } catch (ParseException ex) {
// for now, no need to show the error message to the user here // for now, no need to show the error message to the user here
} }
if (!startDateValue.equals("")) { if (!startDateValue.isEmpty()) {
if (startDate != null) { if (startDate != null) {
fromDate = startDate.getTimeInMillis() / 1000; // divided by 1000 because we want to get the seconds, not miliseconds 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) { } catch (ParseException ex) {
// for now, no need to show the error message to the user here // for now, no need to show the error message to the user here
} }
if (!endDateValue.equals("")) { if (!endDateValue.isEmpty()) {
if (endDate != null) { if (endDate != null) {
toDate = endDate.getTimeInMillis() / 1000; // divided by 1000 because we want to get the seconds, not miliseconds 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<>(); List<String> timeZones = new ArrayList<>();
if (Case.isCaseOpen()) { try {
// get the latest case // get the latest case
Case currentCase = Case.getCurrentCase(); // get the most updated 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 String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id); //NON-NLS
timeZones.add(item); timeZones.add(item);
} }
} catch (IllegalStateException ex) {
// No current case.
} }
return timeZones; return timeZones;

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -29,14 +29,13 @@ import org.sleuthkit.autopsy.directorytree.FileSearchProvider;
final class FileSearchAction extends CallableSystemAction implements FileSearchProvider { final class FileSearchAction extends CallableSystemAction implements FileSearchProvider {
private static final long serialVersionUID = 1L;
private static FileSearchAction instance = null; private static FileSearchAction instance = null;
FileSearchAction() { FileSearchAction() {
super(); super();
setEnabled(Case.isCaseOpen()); //no guarantee listener executed, so check here setEnabled(Case.isCaseOpen());
Case.addPropertyChangeListener(new PropertyChangeListener() { Case.addPropertyChangeListener(new PropertyChangeListener() {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) { if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {

View File

@ -16,9 +16,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.corecomponentinterfaces; package org.sleuthkit.autopsy.framework;
import java.nio.file.Path; 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 * Interface implemented by DataSourceProcessors in order to be supported by

View 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);
}
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}
});
}
}

View File

@ -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);
}

View 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, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JProgressBar" name="progressBar">
</Component>
</SubComponents>
</Form>

View 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
}

View File

@ -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) {
}
}

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013-2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -330,11 +330,11 @@ public class IngestManager {
// check whether a multi-user case is currently being processed // check whether a multi-user case is currently being processed
try { try {
if (!Case.isCaseOpen() || Case.getCurrentCase().getCaseType() != Case.CaseType.MULTI_USER_CASE) { if (Case.getCurrentCase().getCaseType() != Case.CaseType.MULTI_USER_CASE) {
return; return;
} }
} catch (IllegalStateException ignore) { } catch (IllegalStateException ignore) {
// thorown by Case.getCurrentCase() when no case is open // Thrown by Case.getCurrentCase() when no case is open
return; return;
} }
@ -343,7 +343,7 @@ public class IngestManager {
logger.log(Level.SEVERE, "Service {0} is down! Cancelling all running ingest jobs", serviceDisplayName); //NON-NLS logger.log(Level.SEVERE, "Service {0} is down! Cancelling all running ingest jobs", serviceDisplayName); //NON-NLS
// display notification if running interactively // display notification if running interactively
if (isIngestRunning() && RuntimeProperties.coreComponentsAreActive()) { if (isIngestRunning() && RuntimeProperties.runningWithGUI()) {
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -379,7 +379,7 @@ public class IngestManager {
* Case.getTextIndexName() API. * Case.getTextIndexName() API.
*/ */
Case openedCase = Case.getCurrentCase(); Case openedCase = Case.getCurrentCase();
String channelPrefix = openedCase.getTextIndexName(); String channelPrefix = openedCase.getName();
if (Case.CaseType.MULTI_USER_CASE == openedCase.getCaseType()) { if (Case.CaseType.MULTI_USER_CASE == openedCase.getCaseType()) {
jobEventPublisher.openRemoteEventChannel(String.format(JOB_EVENT_CHANNEL_NAME, channelPrefix)); jobEventPublisher.openRemoteEventChannel(String.format(JOB_EVENT_CHANNEL_NAME, channelPrefix));
moduleEventPublisher.openRemoteEventChannel(String.format(MODULE_EVENT_CHANNEL_NAME, channelPrefix)); moduleEventPublisher.openRemoteEventChannel(String.format(MODULE_EVENT_CHANNEL_NAME, channelPrefix));
@ -392,24 +392,17 @@ public class IngestManager {
} }
synchronized void handleCaseClosed() { 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(); jobEventPublisher.closeRemoteEventChannel();
moduleEventPublisher.closeRemoteEventChannel(); moduleEventPublisher.closeRemoteEventChannel();
this.jobCreationIsEnabled = false; this.jobCreationIsEnabled = false;
clearIngestMessageBox(); 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 * 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 * initialized, allowing the ingest manager to get the top component used to
@ -428,7 +421,7 @@ public class IngestManager {
*/ */
void postIngestMessage(IngestMessage message) { void postIngestMessage(IngestMessage message) {
synchronized (this.ingestMessageBoxLock) { synchronized (this.ingestMessageBoxLock) {
if (ingestMessageBox != null && RuntimeProperties.coreComponentsAreActive()) { if (ingestMessageBox != null && RuntimeProperties.runningWithGUI()) {
if (message.getMessageType() != IngestMessage.MessageType.ERROR && message.getMessageType() != IngestMessage.MessageType.WARNING) { if (message.getMessageType() != IngestMessage.MessageType.ERROR && message.getMessageType() != IngestMessage.MessageType.WARNING) {
ingestMessageBox.displayMessage(message); ingestMessageBox.displayMessage(message);
} else { } else {
@ -475,7 +468,7 @@ public class IngestManager {
*/ */
public void queueIngestJob(Collection<Content> dataSources, IngestJobSettings settings) { public void queueIngestJob(Collection<Content> dataSources, IngestJobSettings settings) {
if (jobCreationIsEnabled) { if (jobCreationIsEnabled) {
IngestJob job = new IngestJob(dataSources, settings, RuntimeProperties.coreComponentsAreActive()); IngestJob job = new IngestJob(dataSources, settings, RuntimeProperties.runningWithGUI());
if (job.hasIngestPipeline()) { if (job.hasIngestPipeline()) {
long taskId = nextThreadId.incrementAndGet(); long taskId = nextThreadId.incrementAndGet();
Future<Void> task = startIngestJobsThreadPool.submit(new StartIngestJobTask(taskId, job)); 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. * Starts an ingest job that will process a collection of data sources. This
* This is intended to be used in an auto-ingest context and will fail * is intended to be used in an auto-ingest context and will fail if no
* if no ingest modules are enabled. * ingest modules are enabled.
* *
* @param dataSources The data sources to process. * @param dataSources The data sources to process.
* @param settings The settings for the ingest job. * @param settings The settings for the ingest job.
@ -497,7 +490,7 @@ public class IngestManager {
*/ */
public synchronized IngestJobStartResult beginIngestJob(Collection<Content> dataSources, IngestJobSettings settings) { public synchronized IngestJobStartResult beginIngestJob(Collection<Content> dataSources, IngestJobSettings settings) {
if (this.jobCreationIsEnabled) { if (this.jobCreationIsEnabled) {
IngestJob job = new IngestJob(dataSources, settings, RuntimeProperties.coreComponentsAreActive()); IngestJob job = new IngestJob(dataSources, settings, RuntimeProperties.runningWithGUI());
if (job.hasIngestPipeline()) { if (job.hasIngestPipeline()) {
return this.startIngestJob(job); // Start job return this.startIngestJob(job); // Start job
} }
@ -543,7 +536,7 @@ public class IngestManager {
try { try {
if (!servicesMonitor.getServiceStatus(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString()).equals(ServicesMonitor.ServiceStatus.UP.toString())) { if (!servicesMonitor.getServiceStatus(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString()).equals(ServicesMonitor.ServiceStatus.UP.toString())) {
// display notification if running interactively // display notification if running interactively
if (RuntimeProperties.coreComponentsAreActive()) { if (RuntimeProperties.runningWithGUI()) {
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(new Runnable() {
@Override @Override
public void run() { 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 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 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(); final StringBuilder message = new StringBuilder();
message.append(Bundle.IngestManager_startupErr_dlgMsg()).append("\n"); message.append(Bundle.IngestManager_startupErr_dlgMsg()).append("\n");
message.append(Bundle.IngestManager_startupErr_dlgSolution()).append("\n\n"); message.append(Bundle.IngestManager_startupErr_dlgSolution()).append("\n\n");
@ -966,7 +959,7 @@ public class IngestManager {
return null; return null;
} }
if (RuntimeProperties.coreComponentsAreActive()) { if (RuntimeProperties.runningWithGUI()) {
final String displayName = NbBundle.getMessage(this.getClass(), "IngestManager.StartIngestJobsTask.run.displayName"); final String displayName = NbBundle.getMessage(this.getClass(), "IngestManager.StartIngestJobsTask.run.displayName");
this.progress = ProgressHandle.createHandle(displayName, new Cancellable() { this.progress = ProgressHandle.createHandle(displayName, new Cancellable() {
@Override @Override

View File

@ -130,7 +130,7 @@ class IngestMessagesToolbar extends javax.swing.JPanel {
Case.addPropertyChangeListener((PropertyChangeEvent evt) -> { Case.addPropertyChangeListener((PropertyChangeEvent evt) -> {
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) { if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
setEnabled(evt.getNewValue() != null && RuntimeProperties.coreComponentsAreActive()); setEnabled(evt.getNewValue() != null && RuntimeProperties.runningWithGUI());
} }
}); });
} }

View File

@ -27,7 +27,7 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="profileListLabel" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="profileListLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
@ -45,21 +45,16 @@
</Group> </Group>
</Group> </Group>
<Component id="jSeparator2" min="-2" pref="2" max="-2" attributes="0"/> <Component id="jSeparator2" min="-2" pref="2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/> <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" attributes="0">
<Component id="filterNameLabel" min="-2" pref="36" max="-2" attributes="0"/> <Component id="profileDescLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="216" max="32767" attributes="0"/>
<Component id="filterNameText" max="32767" attributes="0"/>
</Group> </Group>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="filterDescLabel" min="-2" max="-2" attributes="0"/>
<Component id="selectedModulesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="profileDescLabel" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/> <EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
@ -67,20 +62,39 @@
<Component id="ingestWarningLabel" min="-2" max="-2" attributes="0"/> <Component id="ingestWarningLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </Group>
<Component id="filterDescPane" alignment="1" pref="413" max="32767" attributes="0"/> <Component id="profileDescPane" alignment="1" max="32767" attributes="0"/>
<Component id="profileDescPane" alignment="1" pref="413" max="32767" attributes="0"/> <Component id="selectedModulesPane" alignment="1" max="32767" attributes="0"/>
<Component id="selectedModulesPane" alignment="1" pref="413" max="32767" attributes="0"/> </Group>
</Group>
<Group type="102" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Component id="filterDescPane" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</Group> </Group>
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="filterNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="filterNameText" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="selectedModulesLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
@ -90,19 +104,17 @@
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0"> <Group type="103" groupAlignment="1" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Component id="profileDescPane" pref="0" max="32767" attributes="0"/> <Component id="profileDescPane" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="filterNameLabel" max="32767" attributes="0"/> <Component id="filterNameLabel" min="-2" max="-2" attributes="0"/>
<Component id="filterNameText" max="32767" attributes="0"/> <Component id="filterNameText" min="-2" pref="14" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="filterDescLabel" min="-2" max="-2" attributes="0"/> <Component id="filterDescPane" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="filterDescPane" pref="0" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="selectedModulesLabel" min="-2" max="-2" attributes="0"/> <Component id="selectedModulesLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="selectedModulesPane" max="32767" attributes="0"/> <Component id="selectedModulesPane" max="32767" attributes="0"/>
</Group> </Group>
<Component id="profileListPane" pref="415" max="32767" attributes="0"/> <Component id="profileListPane" pref="415" max="32767" attributes="0"/>
@ -257,15 +269,18 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="ProfileSettingsPanel.filterNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="ProfileSettingsPanel.filterNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[30, 14]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[30, 14]"/>
</Property>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JLabel" name="filterNameText"> <Component class="javax.swing.JLabel" name="filterNameText">
</Component>
<Component class="javax.swing.JLabel" name="filterDescLabel">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="horizontalAlignment" type="int" value="2"/>
<ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="ProfileSettingsPanel.filterDescLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <Property name="horizontalTextPosition" type="int" value="2"/>
</Property>
</Properties> </Properties>
</Component> </Component>
<Container class="javax.swing.JScrollPane" name="filterDescPane"> <Container class="javax.swing.JScrollPane" name="filterDescPane">

View File

@ -38,7 +38,6 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
"ProfileSettingsPanel.profileListLabel.text=Profiles:", "ProfileSettingsPanel.profileListLabel.text=Profiles:",
"ProfileSettingsPanel.profileDescLabel.text=Profile Description:", "ProfileSettingsPanel.profileDescLabel.text=Profile Description:",
"ProfileSettingsPanel.filterNameLabel.text=Filter:", "ProfileSettingsPanel.filterNameLabel.text=Filter:",
"ProfileSettingsPanel.filterDescLabel.text=Filter Description:",
"ProfileSettingsPanel.selectedModulesLabel.text=Selected Ingest Modules:", "ProfileSettingsPanel.selectedModulesLabel.text=Selected Ingest Modules:",
"ProfileSettingsPanel.newProfileButton.text=New Profile", "ProfileSettingsPanel.newProfileButton.text=New Profile",
"ProfileSettingsPanel.editProfileButton.text=Edit Profile", "ProfileSettingsPanel.editProfileButton.text=Edit Profile",
@ -85,7 +84,6 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
profileDescLabel = new javax.swing.JLabel(); profileDescLabel = new javax.swing.JLabel();
filterNameLabel = new javax.swing.JLabel(); filterNameLabel = new javax.swing.JLabel();
filterNameText = new javax.swing.JLabel(); filterNameText = new javax.swing.JLabel();
filterDescLabel = new javax.swing.JLabel();
filterDescPane = new javax.swing.JScrollPane(); filterDescPane = new javax.swing.JScrollPane();
filterDescArea = new javax.swing.JTextArea(); filterDescArea = new javax.swing.JTextArea();
selectedModulesPane = new javax.swing.JScrollPane(); selectedModulesPane = new javax.swing.JScrollPane();
@ -148,8 +146,11 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
org.openide.awt.Mnemonics.setLocalizedText(profileDescLabel, org.openide.util.NbBundle.getMessage(ProfileSettingsPanel.class, "ProfileSettingsPanel.profileDescLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(profileDescLabel, org.openide.util.NbBundle.getMessage(ProfileSettingsPanel.class, "ProfileSettingsPanel.profileDescLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(filterNameLabel, org.openide.util.NbBundle.getMessage(ProfileSettingsPanel.class, "ProfileSettingsPanel.filterNameLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(filterNameLabel, org.openide.util.NbBundle.getMessage(ProfileSettingsPanel.class, "ProfileSettingsPanel.filterNameLabel.text")); // NOI18N
filterNameLabel.setMinimumSize(new java.awt.Dimension(30, 14));
filterNameLabel.setPreferredSize(new java.awt.Dimension(30, 14));
org.openide.awt.Mnemonics.setLocalizedText(filterDescLabel, org.openide.util.NbBundle.getMessage(ProfileSettingsPanel.class, "ProfileSettingsPanel.filterDescLabel.text")); // NOI18N filterNameText.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
filterNameText.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
filterDescArea.setEditable(false); filterDescArea.setEditable(false);
filterDescArea.setBackground(new java.awt.Color(240, 240, 240)); filterDescArea.setBackground(new java.awt.Color(240, 240, 240));
@ -193,28 +194,37 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
.addComponent(deleteProfileButton, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(deleteProfileButton, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(6, 6, 6))) .addGap(6, 6, 6)))
.addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(6, 6, 6) .addGap(6, 6, 6)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(filterNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(profileDescLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(filterNameText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(filterDescLabel)
.addComponent(selectedModulesLabel)
.addComponent(profileDescLabel))
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGap(8, 8, 8) .addGap(8, 8, 8)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(ingestWarningLabel) .addComponent(ingestWarningLabel)
.addGap(0, 0, Short.MAX_VALUE)) .addGap(0, 0, Short.MAX_VALUE))
.addComponent(filterDescPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 413, Short.MAX_VALUE) .addComponent(profileDescPane, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(profileDescPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 413, Short.MAX_VALUE) .addComponent(selectedModulesPane, javax.swing.GroupLayout.Alignment.TRAILING)))
.addComponent(selectedModulesPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 413, Short.MAX_VALUE)))) .addGroup(layout.createSequentialGroup()
.addGap(12, 12, 12)) .addGap(10, 10, 10)
.addComponent(filterDescPane)))
.addContainerGap())))
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(filterNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0)
.addComponent(filterNameText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(selectedModulesLabel)
.addContainerGap())))
); );
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {deleteProfileButton, editProfileButton, newProfileButton}); layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {deleteProfileButton, editProfileButton, newProfileButton});
@ -231,16 +241,14 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(profileDescPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) .addComponent(profileDescPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(filterNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(filterNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(filterNameText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(filterNameText, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(filterDescLabel) .addComponent(filterDescPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(filterDescPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGap(18, 18, 18)
.addComponent(selectedModulesLabel) .addComponent(selectedModulesLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(selectedModulesPane)) .addComponent(selectedModulesPane))
@ -428,7 +436,6 @@ class ProfileSettingsPanel extends IngestModuleGlobalSettingsPanel implements Op
private javax.swing.JButton deleteProfileButton; private javax.swing.JButton deleteProfileButton;
private javax.swing.JButton editProfileButton; private javax.swing.JButton editProfileButton;
private javax.swing.JTextArea filterDescArea; private javax.swing.JTextArea filterDescArea;
private javax.swing.JLabel filterDescLabel;
private javax.swing.JScrollPane filterDescPane; private javax.swing.JScrollPane filterDescPane;
private javax.swing.JLabel filterNameLabel; private javax.swing.JLabel filterNameLabel;
private javax.swing.JLabel filterNameText; private javax.swing.JLabel filterNameText;

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -30,14 +30,13 @@ import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter; import org.openide.util.actions.Presenter;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
@ActionID( /**
category = "Tools", * The action associated with assorted Run Ingest Modules menu items.
id = "org.sleuthkit.autopsy.ingest.RunIngestAction" *
) * This action should only be invoked in the event dispatch thread (EDT).
@ActionRegistration( */
displayName = "#CTL_RunIngestAction", @ActionID(category = "Tools", id = "org.sleuthkit.autopsy.ingest.RunIngestAction")
lazy = false @ActionRegistration(displayName = "#CTL_RunIngestAction", lazy = false)
)
@Messages("CTL_RunIngestAction=Run Ingest") @Messages("CTL_RunIngestAction=Run Ingest")
public final class RunIngestAction extends CallableSystemAction implements Presenter.Menu, ActionListener { public final class RunIngestAction extends CallableSystemAction implements Presenter.Menu, ActionListener {
@ -51,6 +50,9 @@ public final class RunIngestAction extends CallableSystemAction implements Prese
return action; return action;
} }
private RunIngestAction() {
}
@Override @Override
public void performAction() { public void performAction() {
getMenuPresenter(); getMenuPresenter();
@ -80,6 +82,6 @@ public final class RunIngestAction extends CallableSystemAction implements Prese
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return Case.isCaseOpen();// && Case.getCurrentCase().hasData(); return Case.isCaseOpen() && Case.getCurrentCase().hasData();
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -23,32 +23,39 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
* An implementation of a keyword search service. * An interface for implementations of a keyword search service.
* *
* TODO (AUT-2158: This interface should not extend Closeable. * TODO (AUT-2158: This interface should not extend Closeable.
*/ */
public interface KeywordSearchService extends Closeable { public interface KeywordSearchService extends Closeable {
/** /**
* Takes a Blackboard artifact and adds all of its attributes to the keyword * Tries to connect to the keyword search service server.
* search index.
* *
* @param artifact * @param host The hostname or IP address of the service.
* @param port The port used by the service.
*
* @throws KeywordSearchServiceException if cannot connect.
*/
public void tryConnect(String host, int port) throws KeywordSearchServiceException;
/**
* Adds an artifact to the keyword search text index as a concatenation of
* all of its attributes.
*
* @param artifact The artifact to index.
* *
* @throws org.sleuthkit.datamodel.TskCoreException * @throws org.sleuthkit.datamodel.TskCoreException
*/ */
public void indexArtifact(BlackboardArtifact artifact) throws TskCoreException; public void indexArtifact(BlackboardArtifact artifact) throws TskCoreException;
/** /**
* Checks if we can communicate with the KeywordSearchService using the * Deletes the keyword search text index for a case.
* passed-in host and port. Closes the connection upon exit. Throws if it
* cannot communicate.
* *
* @param host the remote hostname or IP address of the server * @param textIndexName The text index name.
* @param port the remote port of the server
* *
* @throws KeywordSearchServiceException * @throws KeywordSearchServiceException if unable to delete.
*/ */
public void tryConnect(String host, int port) throws KeywordSearchServiceException; public void deleteTextIndex(String textIndexName) throws KeywordSearchServiceException;
} }

View File

@ -50,10 +50,11 @@ class DataContentDynamicMenu extends JMenuItem implements DynamicMenuContent {
defaultItem.addActionListener(new OpenTopComponentAction(contentWin)); defaultItem.addActionListener(new OpenTopComponentAction(contentWin));
if (!Case.isCaseOpen() || Case.getCurrentCase().hasData() == false) { try {
defaultItem.setEnabled(false); // disable the menu items when no case is opened Case currentCase = Case.getCurrentCase();
} else { defaultItem.setEnabled(currentCase.hasData());
defaultItem.setEnabled(true); // enable the menu items when there's a case opened / created } catch (IllegalStateException ex) {
defaultItem.setEnabled(false); // disable the menu when no case is opened
} }
comps[counter++] = defaultItem; comps[counter++] = defaultItem;

View File

@ -53,10 +53,11 @@ class DataExplorerDynamicMenu extends JMenuItem implements DynamicMenuContent {
JMenuItem item = new JMenuItem(explorerWin.getName()); JMenuItem item = new JMenuItem(explorerWin.getName());
item.addActionListener(new OpenTopComponentAction(explorerWin)); item.addActionListener(new OpenTopComponentAction(explorerWin));
if (!Case.isCaseOpen() || Case.getCurrentCase().hasData() == false) { try {
Case currentCase = Case.getCurrentCase();
item.setEnabled(currentCase.hasData());
} catch (IllegalStateException ex) {
item.setEnabled(false); // disable the menu when no case is opened item.setEnabled(false); // disable the menu when no case is opened
} else {
item.setEnabled(true); // enable the menu if the case is opened or created
} }
comps[i++] = item; comps[i++] = item;

View File

@ -492,7 +492,7 @@ public class HashDbManager implements PropertyChangeListener {
the database from HashLookupSettings and the user may not know about this the database from HashLookupSettings and the user may not know about this
because the dialogs are not being displayed. The next time user starts Autopsy, HashDB because the dialogs are not being displayed. The next time user starts Autopsy, HashDB
will load without errors and the user may think that the problem was solved.*/ will load without errors and the user may think that the problem was solved.*/
if (!allDatabasesLoadedCorrectly && RuntimeProperties.coreComponentsAreActive()) { if (!allDatabasesLoadedCorrectly && RuntimeProperties.runningWithGUI()) {
try { try {
HashLookupSettings.writeSettings(new HashLookupSettings(this.knownHashSets, this.knownBadHashSets)); HashLookupSettings.writeSettings(new HashLookupSettings(this.knownHashSets, this.knownBadHashSets));
allDatabasesLoadedCorrectly = true; allDatabasesLoadedCorrectly = true;
@ -512,7 +512,7 @@ public class HashDbManager implements PropertyChangeListener {
// Give the user an opportunity to find the desired file. // Give the user an opportunity to find the desired file.
String newPath = null; String newPath = null;
if (RuntimeProperties.coreComponentsAreActive() && if (RuntimeProperties.runningWithGUI() &&
JOptionPane.showConfirmDialog(null, JOptionPane.showConfirmDialog(null,
NbBundle.getMessage(this.getClass(), "HashDbManager.dlgMsg.dbNotFoundAtLoc", NbBundle.getMessage(this.getClass(), "HashDbManager.dlgMsg.dbNotFoundAtLoc",
hashSetName, configuredPath), hashSetName, configuredPath),

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2014 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -36,13 +36,13 @@ import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationCleanDialog;
*/ */
class HashDbPanelSearchAction extends CallableSystemAction { class HashDbPanelSearchAction extends CallableSystemAction {
private static final long serialVersionUID = 1L;
static final String ACTION_NAME = NbBundle.getMessage(HashDbPanelSearchAction.class, "HashDbPanelSearchAction.actionName"); static final String ACTION_NAME = NbBundle.getMessage(HashDbPanelSearchAction.class, "HashDbPanelSearchAction.actionName");
private static HashDbPanelSearchAction instance = null; private static HashDbPanelSearchAction instance = null;
HashDbPanelSearchAction() { HashDbPanelSearchAction() {
super(); super();
setEnabled(Case.isCaseOpen()); //no guarantee listener executed, so check here setEnabled(Case.isCaseOpen());
Case.addPropertyChangeListener(new PropertyChangeListener() { Case.addPropertyChangeListener(new PropertyChangeListener() {
@Override @Override

View File

@ -203,7 +203,7 @@ final class HashLookupSettings implements Serializable {
newHashSetName = hashSetName + suffix; newHashSetName = hashSetName + suffix;
} while (hashSetNames.contains(newHashSetName)); } while (hashSetNames.contains(newHashSetName));
logger.log(Level.INFO, "Duplicate hash set name " + hashSetName + " found. Replacing with " + newHashSetName + "."); logger.log(Level.INFO, "Duplicate hash set name " + hashSetName + " found. Replacing with " + newHashSetName + ".");
if (RuntimeProperties.coreComponentsAreActive()) { if (RuntimeProperties.runningWithGUI()) {
JOptionPane.showMessageDialog(null, JOptionPane.showMessageDialog(null,
NbBundle.getMessage(HashLookupSettings.class, NbBundle.getMessage(HashLookupSettings.class,
"HashDbManager.replacingDuplicateHashsetNameMsg", "HashDbManager.replacingDuplicateHashsetNameMsg",
@ -269,7 +269,7 @@ final class HashLookupSettings implements Serializable {
try { try {
FileUtils.copyFile(new File(configFilePath), new File(backupFilePath)); FileUtils.copyFile(new File(configFilePath), new File(backupFilePath));
logger.log(Level.INFO, "Updated the schema, backup saved at: " + backupFilePath); logger.log(Level.INFO, "Updated the schema, backup saved at: " + backupFilePath);
if (RuntimeProperties.coreComponentsAreActive()) { if (RuntimeProperties.runningWithGUI()) {
JOptionPane.showMessageDialog(null, JOptionPane.showMessageDialog(null,
NbBundle.getMessage(HashLookupSettings.class, NbBundle.getMessage(HashLookupSettings.class,
"HashDbManager.savedBackupOfOldConfigMsg", "HashDbManager.savedBackupOfOldConfigMsg",

View File

@ -301,7 +301,7 @@ class ReportExcel implements TableReportModule {
row = sheet.createRow(rowIndex); row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle); row.setRowStyle(setStyle);
row.createCell(0).setCellValue(NbBundle.getMessage(this.getClass(), "ReportExcel.cellVal.caseName")); row.createCell(0).setCellValue(NbBundle.getMessage(this.getClass(), "ReportExcel.cellVal.caseName"));
row.createCell(1).setCellValue(currentCase.getName()); row.createCell(1).setCellValue(currentCase.getDisplayName());
++rowIndex; ++rowIndex;
row = sheet.createRow(rowIndex); row = sheet.createRow(rowIndex);

View File

@ -93,7 +93,7 @@ class ReportGenerator {
DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss"); DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss");
Date date = new Date(); Date date = new Date();
String dateNoTime = dateFormat.format(date); String dateNoTime = dateFormat.format(date);
this.reportPath = currentCase.getReportDirectory() + File.separator + currentCase.getName() + " " + dateNoTime + File.separator; this.reportPath = currentCase.getReportDirectory() + File.separator + currentCase.getDisplayName() + " " + dateNoTime + File.separator;
this.errorList = new ArrayList<>(); this.errorList = new ArrayList<>();

View File

@ -857,7 +857,7 @@ class ReportHTML implements TableReportModule {
iconPath = "favicon.ico"; iconPath = "favicon.ico";
} }
index.append("<head>\n<title>").append(reportTitle).append(" ").append( index.append("<head>\n<title>").append(reportTitle).append(" ").append(
NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.title", currentCase.getName())).append( NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.title", currentCase.getDisplayName())).append(
"</title>\n"); //NON-NLS "</title>\n"); //NON-NLS
index.append("<link rel=\"icon\" type=\"image/ico\" href=\"") index.append("<link rel=\"icon\" type=\"image/ico\" href=\"")
.append(iconPath).append("\" />\n"); //NON-NLS .append(iconPath).append("\" />\n"); //NON-NLS
@ -1017,7 +1017,7 @@ class ReportHTML implements TableReportModule {
Date date = new Date(); Date date = new Date();
String datetime = datetimeFormat.format(date); String datetime = datetimeFormat.format(date);
String caseName = currentCase.getName(); String caseName = currentCase.getDisplayName();
String caseNumber = currentCase.getNumber(); String caseNumber = currentCase.getNumber();
String examiner = currentCase.getExaminer(); String examiner = currentCase.getExaminer();
int imagecount; int imagecount;

View File

@ -84,7 +84,7 @@ public final class ReportWizardAction extends CallableSystemAction implements Pr
Case.addPropertyChangeListener((PropertyChangeEvent evt) -> { Case.addPropertyChangeListener((PropertyChangeEvent evt) -> {
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) { if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
Case newCase = (Case) evt.getNewValue(); Case newCase = (Case) evt.getNewValue();
setEnabled(newCase != null && RuntimeProperties.coreComponentsAreActive()); setEnabled(newCase != null && RuntimeProperties.runningWithGUI());
} }
}); });

View File

@ -90,7 +90,7 @@ public class AddTaggedHashesToHashDb implements GeneralReportModule {
if (content instanceof AbstractFile) { if (content instanceof AbstractFile) {
if (null != ((AbstractFile) content).getMd5Hash()) { if (null != ((AbstractFile) content).getMd5Hash()) {
try { try {
hashSet.addHashes(tag.getContent(), Case.getCurrentCase().getName()); hashSet.addHashes(tag.getContent(), Case.getCurrentCase().getDisplayName());
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
Logger.getLogger(AddTaggedHashesToHashDb.class.getName()).log(Level.SEVERE, "Error adding hash for obj_id = " + tag.getContent().getId() + " to hash database " + hashSet.getHashSetName(), ex); Logger.getLogger(AddTaggedHashesToHashDb.class.getName()).log(Level.SEVERE, "Error adding hash for obj_id = " + tag.getContent().getId() + " to hash database " + hashSet.getHashSetName(), ex);
failedExports.add(tag.getContent().getName()); failedExports.add(tag.getContent().getName());

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.report.testfixtures; package org.sleuthkit.autopsy.test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.report.testfixtures; package org.sleuthkit.autopsy.test;
import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.autopsy.coreutils.Version;
import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.FileIngestModule;

View File

@ -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.test;
import java.util.logging.Level;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.framework.AutopsyService;
import org.sleuthkit.autopsy.framework.ProgressIndicator;
/**
* An implementation of the Autopsy service interface used for test purposes.
*/
//@ServiceProvider(service = AutopsyService.class)
public class TestAutopsyService implements AutopsyService {
private static final Logger logger = Logger.getLogger(TestAutopsyService.class.getName());
@Override
public String getServiceName() {
return "Test Autopsy Service";
}
@Override
public void openCaseResources(CaseContext context) throws AutopsyServiceException {
ProgressIndicator progressIndicator = context.getProgressIndicator();
try {
progressIndicator.start("Test Autopsy Service doing first task...");
logger.log(Level.INFO, "Test Autopsy Service simulating work on first task");
Thread.sleep(1000L);
progressIndicator.progress(20);
Thread.sleep(1000L);
progressIndicator.progress(40);
Thread.sleep(1000L);
progressIndicator.progress(60);
Thread.sleep(1000L);
progressIndicator.progress(80);
Thread.sleep(1000L);
progressIndicator.progress(100);
progressIndicator.finish("First task completed by Test Autopsy Service.");
progressIndicator.start("Test Autopsy Service doing second task...");
for (int i = 0; i < 10000; ++i) {
logger.log(Level.INFO, "Test Autopsy Service simulating work on second task");
if (context.cancelRequested()) {
logger.log(Level.INFO, "Test Autopsy Service cancelled while doing second task, cancel requested = {0}", context.cancelRequested());
break;
}
}
progressIndicator.finish("Second task completed by Test Autopsy Service.");
} catch (InterruptedException ex) {
logger.log(Level.INFO, "Test Autopsy Service interrupted (cancelled) while doing first task, cancel requested = {0}", context.cancelRequested());
}
}
}

View File

@ -60,7 +60,6 @@ public final class OpenTimelineAction extends CallableSystemAction implements Pr
private final JButton toolbarButton = new JButton(getName(), private final JButton toolbarButton = new JButton(getName(),
new ImageIcon(getClass().getResource("images/btn_icon_timeline_colorized_26.png"))); //NON-NLS new ImageIcon(getClass().getResource("images/btn_icon_timeline_colorized_26.png"))); //NON-NLS
/** /**
* Invalidate the reference to the controller so that a new one will be * Invalidate the reference to the controller so that a new one will be
* instantiated the next time this action is invoked * instantiated the next time this action is invoked

View File

@ -453,8 +453,8 @@ public class TimeLineController {
TimeLineController.this.showFullRange(); TimeLineController.this.showFullRange();
} else { } else {
//prompt user to pick specific event and time range //prompt user to pick specific event and time range
ShowInTimelineDialog showInTimelineDilaog = ShowInTimelineDialog showInTimelineDilaog
(file == null) = (file == null)
? new ShowInTimelineDialog(TimeLineController.this, artifact) ? new ShowInTimelineDialog(TimeLineController.this, artifact)
: new ShowInTimelineDialog(TimeLineController.this, file); : new ShowInTimelineDialog(TimeLineController.this, file);
Optional<ViewInTimelineRequestedEvent> dialogResult = showInTimelineDilaog.showAndWait(); Optional<ViewInTimelineRequestedEvent> dialogResult = showInTimelineDilaog.showAndWait();
@ -575,7 +575,6 @@ public class TimeLineController {
Case.addPropertyChangeListener(caseListener); Case.addPropertyChangeListener(caseListener);
listeningToAutopsy = true; listeningToAutopsy = true;
} }
Platform.runLater(() -> promptForRebuild(file, artifact)); Platform.runLater(() -> promptForRebuild(file, artifact));
} }

View File

@ -100,7 +100,7 @@ public class SaveSnapshotAsReport extends Action {
setEventHandler(actionEvent -> { setEventHandler(actionEvent -> {
//capture generation date and use to make default report name //capture generation date and use to make default report name
Date generationDate = new Date(); Date generationDate = new Date();
final String defaultReportName = FileUtil.escapeFileName(currentCase.getName() + " " + new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss").format(generationDate)); //NON_NLS final String defaultReportName = FileUtil.escapeFileName(currentCase.getDisplayName() + " " + new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss").format(generationDate)); //NON_NLS
BufferedImage snapshot = SwingFXUtils.fromFXImage(nodeSupplier.get().snapshot(null, null), null); BufferedImage snapshot = SwingFXUtils.fromFXImage(nodeSupplier.get().snapshot(null, null), null);
//prompt user to pick report name //prompt user to pick report name

View File

@ -46,7 +46,6 @@ class AutoIngestCase implements Comparable<AutoIngestCase> {
* *
* @param caseDirectoryPath The case directory path. * @param caseDirectoryPath The case directory path.
*/ */
// RJCTODO: Throw instead of reporting error, let client decide what to do.
AutoIngestCase(Path caseDirectoryPath) { AutoIngestCase(Path caseDirectoryPath) {
this.caseDirectoryPath = caseDirectoryPath; this.caseDirectoryPath = caseDirectoryPath;
caseName = PathUtils.caseNameFromCaseDirectoryPath(caseDirectoryPath); caseName = PathUtils.caseNameFromCaseDirectoryPath(caseDirectoryPath);
@ -100,7 +99,6 @@ class AutoIngestCase implements Comparable<AutoIngestCase> {
* *
* @return The last accessed date. * @return The last accessed date.
*/ */
// RJCTODO: Throw instead of reporting error, let client decide what to do.
Date getLastAccessedDate() { Date getLastAccessedDate() {
try { try {
BasicFileAttributes fileAttrs = Files.readAttributes(metadataFilePath, BasicFileAttributes.class); BasicFileAttributes fileAttrs = Files.readAttributes(metadataFilePath, BasicFileAttributes.class);

View File

@ -45,20 +45,10 @@ final class AutoIngestCaseDeletedEvent extends AutopsyEvent implements Serializa
this.nodeName = nodeName; this.nodeName = nodeName;
} }
/**
* RJCTODO
*
* @return
*/
String getCaseName() { String getCaseName() {
return caseName; return caseName;
} }
/**
* RJCTODO
*
* @return
*/
String getNodeName() { String getNodeName() {
return nodeName; return nodeName;
} }

View File

@ -0,0 +1,123 @@
/*
* 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.experimental.autoingest;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import javax.swing.SwingUtilities;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.casemodule.AddImageAction;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseNewAction;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.experimental.configuration.AutoIngestUserPreferences;
/**
* Handles locating and opening cases created by auto ingest.
*/
final class AutoIngestCaseManager {
private static final Logger LOGGER = Logger.getLogger(AutoIngestCaseManager.class.getName());
private static AutoIngestCaseManager instance;
/**
* Gets the auto ingest case manager.
*
* @return The auto ingest case manager singleton.
*/
synchronized static AutoIngestCaseManager getInstance() {
if (null == instance) {
instance = new AutoIngestCaseManager();
}
return instance;
}
/**
* Constructs an object that handles locating and opening cases created by
* auto ingest.
*/
private AutoIngestCaseManager() {
/*
* Disable the new case action because review mode is only for looking
* at cases created by automated ingest.
*/
CallableSystemAction.get(CaseNewAction.class).setEnabled(false);
/*
* Permanently delete the "Open Recent Cases" item in the "File" menu.
* This is quite drastic, as it also affects Autopsy standalone mode on
* this machine, but review mode is only for looking at cases created by
* automated ingest.
*/
FileObject root = FileUtil.getConfigRoot();
FileObject openRecentCasesMenu = root.getFileObject("Menu/Case/OpenRecentCase");
if (openRecentCasesMenu != null) {
try {
openRecentCasesMenu.delete();
} catch (IOException ex) {
AutoIngestCaseManager.LOGGER.log(Level.WARNING, "Unable to remove Open Recent Cases file menu item", ex);
}
}
}
/*
* Gets a list of the cases in the top level case folder used by auto
* ingest.
*/
List<AutoIngestCase> getCases() {
List<AutoIngestCase> cases = new ArrayList<>();
List<Path> caseFolders = PathUtils.findCaseFolders(Paths.get(AutoIngestUserPreferences.getAutoModeResultsFolder()));
for (Path caseFolderPath : caseFolders) {
cases.add(new AutoIngestCase(caseFolderPath));
}
return cases;
}
/**
* Opens an auto ingest case case.
*
* @param caseMetadataFilePath Path to the case metadata file.
*
* @throws CaseActionException
*/
synchronized void openCase(Path caseMetadataFilePath) throws CaseActionException {
/*
* Open the case.
*/
Case.openAsCurrentCase(caseMetadataFilePath.toString());
/**
* Disable the add data source action in auto ingest examiner mode. This
* has to be done here because Case.open() calls Case.doCaseChange() and
* the latter method enables the action. Since Case.doCaseChange()
* enables the menus on EDT by calling SwingUtilities.invokeLater(), we
* have to do the same thing here to maintain the order of execution.
*/
SwingUtilities.invokeLater(() -> {
CallableSystemAction.get(AddImageAction.class).setEnabled(false);
});
}
}

View File

@ -73,7 +73,7 @@
<Component class="javax.swing.JButton" name="bnOpen"> <Component class="javax.swing.JButton" name="bnOpen">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="ReviewModeCasePanel.bnOpen.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.bnOpen.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="enabled" type="boolean" value="false"/> <Property name="enabled" type="boolean" value="false"/>
</Properties> </Properties>
@ -109,7 +109,7 @@
<Component class="javax.swing.JButton" name="bnRefresh"> <Component class="javax.swing.JButton" name="bnRefresh">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="ReviewModeCasePanel.bnRefresh.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.bnRefresh.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -160,7 +160,7 @@
</Property> </Property>
<Property name="selected" type="boolean" value="true"/> <Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="ReviewModeCasePanel.rbAllCases.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbAllCases.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -173,7 +173,7 @@
<ComponentRef name="rbGroupHistoryLength"/> <ComponentRef name="rbGroupHistoryLength"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="ReviewModeCasePanel.rbMonths.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbMonths.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -186,7 +186,7 @@
<ComponentRef name="rbGroupHistoryLength"/> <ComponentRef name="rbGroupHistoryLength"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="ReviewModeCasePanel.rbWeeks.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbWeeks.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -199,7 +199,7 @@
<ComponentRef name="rbGroupHistoryLength"/> <ComponentRef name="rbGroupHistoryLength"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="ReviewModeCasePanel.rbDays.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbDays.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="name" type="java.lang.String" value="" noResource="true"/> <Property name="name" type="java.lang.String" value="" noResource="true"/>
</Properties> </Properties>
@ -213,7 +213,7 @@
<Font name="Tahoma" size="12" style="0"/> <Font name="Tahoma" size="12" style="0"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="ReviewModeCasePanel.rbGroupLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.rbGroupLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
@ -222,10 +222,10 @@
<Component class="javax.swing.JButton" name="bnShowLog"> <Component class="javax.swing.JButton" name="bnShowLog">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="ReviewModeCasePanel.bnShowLog.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.bnShowLog.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="ReviewModeCasePanel.bnShowLog.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestCasePanel.bnShowLog.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="enabled" type="boolean" value="false"/> <Property name="enabled" type="boolean" value="false"/>
</Properties> </Properties>

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -18,38 +18,38 @@
*/ */
package org.sleuthkit.autopsy.experimental.autoingest; package org.sleuthkit.autopsy.experimental.autoingest;
import java.awt.Cursor;
import java.awt.Desktop; import java.awt.Desktop;
import java.nio.file.Paths;
import java.util.List;
import javax.swing.JPanel;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.event.WindowAdapter; import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JOptionPane;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel; import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import org.sleuthkit.autopsy.casemodule.StartupWindowProvider;
import java.awt.Cursor;
import java.io.IOException;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.experimental.autoingest.ReviewModeCaseManager.ReviewModeCaseManagerException; import org.sleuthkit.autopsy.casemodule.StartupWindowProvider;
import org.sleuthkit.autopsy.coreutils.Logger;
/** /**
* A panel that allows a user to open cases created by automated ingest. * A panel that allows a user to open cases created by auto ingest.
*/ */
public final class ReviewModeCasePanel extends JPanel { public final class AutoIngestCasePanel extends JPanel {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(ReviewModeCasePanel.class.getName()); private static final Logger logger = Logger.getLogger(AutoIngestCasePanel.class.getName());
private static final AutoIngestCase.LastAccessedDateDescendingComparator reverseDateModifiedComparator = new AutoIngestCase.LastAccessedDateDescendingComparator(); private static final AutoIngestCase.LastAccessedDateDescendingComparator reverseDateModifiedComparator = new AutoIngestCase.LastAccessedDateDescendingComparator();
private static final int CASE_COL_MIN_WIDTH = 30; private static final int CASE_COL_MIN_WIDTH = 30;
private static final int CASE_COL_MAX_WIDTH = 2000; private static final int CASE_COL_MAX_WIDTH = 2000;
@ -60,8 +60,8 @@ public final class ReviewModeCasePanel extends JPanel {
private static final int STATUS_COL_MIN_WIDTH = 55; private static final int STATUS_COL_MIN_WIDTH = 55;
private static final int STATUS_COL_MAX_WIDTH = 250; private static final int STATUS_COL_MAX_WIDTH = 250;
private static final int STATUS_COL_PREFERRED_WIDTH = 60; private static final int STATUS_COL_PREFERRED_WIDTH = 60;
private static final int MILLISECONDS_TO_WAIT_BEFORE_STARTING = 500; // RJCTODO: Shorten name private static final int MILLIS_TO_WAIT_BEFORE_STARTING = 500;
private static final int MILLISECONDS_TO_WAIT_BETWEEN_UPDATES = 30000; // RJCTODO: Shorten name private static final int MILLIS_TO_WAIT_BETWEEN_UPDATES = 30000;
private ScheduledThreadPoolExecutor casesTableRefreshExecutor; private ScheduledThreadPoolExecutor casesTableRefreshExecutor;
/* /*
@ -71,11 +71,11 @@ public final class ReviewModeCasePanel extends JPanel {
* TODO (RC): Consider unifying this stuff in an enum as in * TODO (RC): Consider unifying this stuff in an enum as in
* AutoIngestDashboard to make it less error prone. * AutoIngestDashboard to make it less error prone.
*/ */
private static final String CASE_HEADER = org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.CaseHeaderText"); private static final String CASE_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.CaseHeaderText");
private static final String CREATEDTIME_HEADER = org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText"); private static final String CREATEDTIME_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText");
private static final String COMPLETEDTIME_HEADER = org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.LastAccessedTimeHeaderText"); private static final String COMPLETEDTIME_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.LastAccessedTimeHeaderText");
private static final String STATUS_ICON_HEADER = org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.StatusIconHeaderText"); private static final String STATUS_ICON_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.StatusIconHeaderText");
private static final String OUTPUT_FOLDER_HEADER = org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.OutputFolderHeaderText"); private static final String OUTPUT_FOLDER_HEADER = org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.OutputFolderHeaderText");
enum COLUMN_HEADERS { enum COLUMN_HEADERS {
@ -83,7 +83,7 @@ public final class ReviewModeCasePanel extends JPanel {
CREATEDTIME, CREATEDTIME,
COMPLETEDTIME, COMPLETEDTIME,
STATUS_ICON, STATUS_ICON,
OUTPUTFOLDER // RJCTODO: Change name OUTPUTFOLDER
} }
private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, COMPLETEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER}; private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, COMPLETEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER};
private DefaultTableModel caseTableModel; private DefaultTableModel caseTableModel;
@ -92,8 +92,10 @@ public final class ReviewModeCasePanel extends JPanel {
/** /**
* Constructs a panel that allows a user to open cases created by automated * Constructs a panel that allows a user to open cases created by automated
* ingest. * ingest.
*
* @param parent The parent dialog for this panel.
*/ */
public ReviewModeCasePanel(JDialog parent) { public AutoIngestCasePanel(JDialog parent) {
caseTableModel = new DefaultTableModel(columnNames, 0) { caseTableModel = new DefaultTableModel(columnNames, 0) {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -183,7 +185,7 @@ public final class ReviewModeCasePanel extends JPanel {
casesTableRefreshExecutor = new ScheduledThreadPoolExecutor(1); casesTableRefreshExecutor = new ScheduledThreadPoolExecutor(1);
this.casesTableRefreshExecutor.scheduleAtFixedRate(() -> { this.casesTableRefreshExecutor.scheduleAtFixedRate(() -> {
refreshCasesTable(); refreshCasesTable();
}, MILLISECONDS_TO_WAIT_BEFORE_STARTING, MILLISECONDS_TO_WAIT_BETWEEN_UPDATES, TimeUnit.MILLISECONDS); }, MILLIS_TO_WAIT_BEFORE_STARTING, MILLIS_TO_WAIT_BETWEEN_UPDATES, TimeUnit.MILLISECONDS);
} }
} }
@ -214,7 +216,7 @@ public final class ReviewModeCasePanel extends JPanel {
private void refreshCasesTable() { private void refreshCasesTable() {
try { try {
currentlySelectedCase = getSelectedCase(); currentlySelectedCase = getSelectedCase();
List<AutoIngestCase> theModel = ReviewModeCaseManager.getInstance().getCases(); List<AutoIngestCase> theModel = AutoIngestCaseManager.getInstance().getCases();
EventQueue.invokeLater(new CaseTableRefreshTask(theModel)); EventQueue.invokeLater(new CaseTableRefreshTask(theModel));
} catch (Exception ex) { } catch (Exception ex) {
logger.log(Level.SEVERE, "Unexpected exception in refreshCasesTable", ex); //NON-NLS logger.log(Level.SEVERE, "Unexpected exception in refreshCasesTable", ex); //NON-NLS
@ -279,10 +281,10 @@ public final class ReviewModeCasePanel extends JPanel {
private void openCase(Path caseMetadataFilePath) { private void openCase(Path caseMetadataFilePath) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try { try {
ReviewModeCaseManager.getInstance().openCaseInEDT(caseMetadataFilePath); AutoIngestCaseManager.getInstance().openCase(caseMetadataFilePath);
stopCasesTableRefreshes(); stopCasesTableRefreshes();
StartupWindowProvider.getInstance().close(); StartupWindowProvider.getInstance().close();
} catch (ReviewModeCaseManagerException ex) { } catch (CaseActionException ex) {
logger.log(Level.SEVERE, String.format("Error while opening case with case metadata file path %s", caseMetadataFilePath), ex); logger.log(Level.SEVERE, String.format("Error while opening case with case metadata file path %s", caseMetadataFilePath), ex);
/* /*
* ReviewModeCaseManagerExceptions have user-friendly error * ReviewModeCaseManagerExceptions have user-friendly error
@ -290,7 +292,7 @@ public final class ReviewModeCasePanel extends JPanel {
*/ */
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
ex.getMessage(), ex.getMessage(),
org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.cannotOpenCase"), org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.cannotOpenCase"),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
} finally { } finally {
@ -345,19 +347,13 @@ public final class ReviewModeCasePanel extends JPanel {
long multiplier = 1; long multiplier = 1;
if (rbAllCases.isSelected()) { if (rbAllCases.isSelected()) {
return true; return true;
} else { } else if (rbMonths.isSelected()) {
if (rbMonths.isSelected()) {
multiplier = 31; multiplier = 31;
} else { } else if (rbWeeks.isSelected()) {
if (rbWeeks.isSelected()) {
multiplier = 7; multiplier = 7;
} else { } else if (rbDays.isSelected()) {
if (rbDays.isSelected()) {
multiplier = 1; multiplier = 1;
} }
}
}
}
return ((currentTime - inputTime) / (1000 * 60 * 60 * 24)) < (numberOfUnits * multiplier); return ((currentTime - inputTime) / (1000 * 60 * 60 * 24)) < (numberOfUnits * multiplier);
} }
@ -387,7 +383,7 @@ public final class ReviewModeCasePanel extends JPanel {
setName("Completed Cases"); // NOI18N setName("Completed Cases"); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(bnOpen, org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.bnOpen.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnOpen, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnOpen.text")); // NOI18N
bnOpen.setEnabled(false); bnOpen.setEnabled(false);
bnOpen.addActionListener(new java.awt.event.ActionListener() { bnOpen.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -407,7 +403,7 @@ public final class ReviewModeCasePanel extends JPanel {
}); });
scrollPaneTable.setViewportView(casesTable); scrollPaneTable.setViewportView(casesTable);
org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.bnRefresh.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnRefresh.text")); // NOI18N
bnRefresh.addActionListener(new java.awt.event.ActionListener() { bnRefresh.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
bnRefreshActionPerformed(evt); bnRefreshActionPerformed(evt);
@ -416,7 +412,7 @@ public final class ReviewModeCasePanel extends JPanel {
rbGroupHistoryLength.add(rbAllCases); rbGroupHistoryLength.add(rbAllCases);
rbAllCases.setSelected(true); rbAllCases.setSelected(true);
org.openide.awt.Mnemonics.setLocalizedText(rbAllCases, org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.rbAllCases.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(rbAllCases, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbAllCases.text")); // NOI18N
rbAllCases.addItemListener(new java.awt.event.ItemListener() { rbAllCases.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) { public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbAllCasesItemStateChanged(evt); rbAllCasesItemStateChanged(evt);
@ -424,7 +420,7 @@ public final class ReviewModeCasePanel extends JPanel {
}); });
rbGroupHistoryLength.add(rbMonths); rbGroupHistoryLength.add(rbMonths);
org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.rbMonths.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbMonths.text")); // NOI18N
rbMonths.addItemListener(new java.awt.event.ItemListener() { rbMonths.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) { public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbMonthsItemStateChanged(evt); rbMonthsItemStateChanged(evt);
@ -432,7 +428,7 @@ public final class ReviewModeCasePanel extends JPanel {
}); });
rbGroupHistoryLength.add(rbWeeks); rbGroupHistoryLength.add(rbWeeks);
org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.rbWeeks.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbWeeks.text")); // NOI18N
rbWeeks.addItemListener(new java.awt.event.ItemListener() { rbWeeks.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) { public void itemStateChanged(java.awt.event.ItemEvent evt) {
rbWeeksItemStateChanged(evt); rbWeeksItemStateChanged(evt);
@ -440,7 +436,7 @@ public final class ReviewModeCasePanel extends JPanel {
}); });
rbGroupHistoryLength.add(rbDays); rbGroupHistoryLength.add(rbDays);
org.openide.awt.Mnemonics.setLocalizedText(rbDays, org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.rbDays.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(rbDays, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbDays.text")); // NOI18N
rbDays.setName(""); // NOI18N rbDays.setName(""); // NOI18N
rbDays.addItemListener(new java.awt.event.ItemListener() { rbDays.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) { public void itemStateChanged(java.awt.event.ItemEvent evt) {
@ -449,7 +445,7 @@ public final class ReviewModeCasePanel extends JPanel {
}); });
rbGroupLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N rbGroupLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.rbGroupLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.rbGroupLabel.text")); // NOI18N
javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter); javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter);
panelFilter.setLayout(panelFilterLayout); panelFilter.setLayout(panelFilterLayout);
@ -481,8 +477,8 @@ public final class ReviewModeCasePanel extends JPanel {
.addContainerGap()) .addContainerGap())
); );
org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.bnShowLog.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.text")); // NOI18N
bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "ReviewModeCasePanel.bnShowLog.toolTipText")); // NOI18N bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "AutoIngestCasePanel.bnShowLog.toolTipText")); // NOI18N
bnShowLog.setEnabled(false); bnShowLog.setEnabled(false);
bnShowLog.addActionListener(new java.awt.event.ActionListener() { bnShowLog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -586,14 +582,14 @@ public final class ReviewModeCasePanel extends JPanel {
if (pathToLog.toFile().exists()) { if (pathToLog.toFile().exists()) {
Desktop.getDesktop().edit(pathToLog.toFile()); Desktop.getDesktop().edit(pathToLog.toFile());
} else { } else {
JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "DisplayLogDialog.cannotFindLog"), JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.cannotFindLog"),
org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE); org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE);
} }
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error attempting to open case auto ingest log file %s", pathToLog), ex); logger.log(Level.SEVERE, String.format("Error attempting to open case auto ingest log file %s", pathToLog), ex);
JOptionPane.showMessageDialog(this, JOptionPane.showMessageDialog(this,
org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "DisplayLogDialog.cannotOpenLog"), org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.cannotOpenLog"),
org.openide.util.NbBundle.getMessage(ReviewModeCasePanel.class, "DisplayLogDialog.unableToShowLogFile"), org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "DisplayLogDialog.unableToShowLogFile"),
JOptionPane.PLAIN_MESSAGE); JOptionPane.PLAIN_MESSAGE);
} }
} }

View File

@ -25,7 +25,7 @@ import org.sleuthkit.autopsy.events.AutopsyEvent;
* Event published when an automated ingest manager prioritizes all or part of a * Event published when an automated ingest manager prioritizes all or part of a
* case. * case.
*/ */
public final class AutoIngestCasePrioritizedEvent extends AutopsyEvent implements Serializable { // RJCTODO: Rename to AutoIngestPrioritizationEvent public final class AutoIngestCasePrioritizedEvent extends AutopsyEvent implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final String caseName; private final String caseName;

View File

@ -24,6 +24,7 @@ import java.nio.file.Paths;
import java.time.Instant; import java.time.Instant;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.Objects;
import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;
@ -55,9 +56,9 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
@GuardedBy("this") @GuardedBy("this")
transient private IngestJob ingestJob; transient private IngestJob ingestJob;
@GuardedBy("this") @GuardedBy("this")
transient private boolean cancelled; // RJCTODO: Document transient private boolean cancelled;
@GuardedBy("this") @GuardedBy("this")
transient private boolean completed; // RJCTODO: Document transient private boolean completed;
@GuardedBy("this") @GuardedBy("this")
private Date completedDate; private Date completedDate;
@GuardedBy("this") @GuardedBy("this")
@ -81,7 +82,6 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
* indicate the the job is not completed, i.e., new * indicate the the job is not completed, i.e., new
* Date(0L). * Date(0L).
*/ */
// RJCTODO: The null case directory is error-prone and the nodeName is confusing.
AutoIngestJob(Manifest manifest, Path caseDirectoryPath, int priority, String nodeName, Stage stage, Date completedDate, boolean errorsOccurred) { AutoIngestJob(Manifest manifest, Path caseDirectoryPath, int priority, String nodeName, Stage stage, Date completedDate, boolean errorsOccurred) {
this.manifest = manifest; this.manifest = manifest;
if (null != caseDirectoryPath) { if (null != caseDirectoryPath) {
@ -112,7 +112,6 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
* *
* @return True or false * @return True or false
*/ */
// RJCTODO: Use this or lose this
synchronized boolean hasCaseDirectoryPath() { synchronized boolean hasCaseDirectoryPath() {
return (false == this.caseDirectoryPath.isEmpty()); return (false == this.caseDirectoryPath.isEmpty());
} }
@ -161,21 +160,10 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
return this.priority; return this.priority;
} }
/**
* RJCTODO
*
* @param newStage
*/
synchronized void setStage(Stage newStage) { synchronized void setStage(Stage newStage) {
setStage(newStage, Date.from(Instant.now())); setStage(newStage, Date.from(Instant.now()));
} }
/**
* RJCTODO
*
* @param state
* @param stateStartedDate
*/
synchronized void setStage(Stage newState, Date stateStartedDate) { synchronized void setStage(Stage newState, Date stateStartedDate) {
if (Stage.CANCELLING == this.stage && Stage.COMPLETED != newState) { if (Stage.CANCELLING == this.stage && Stage.COMPLETED != newState) {
return; return;
@ -184,29 +172,14 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
this.stageStartDate = stateStartedDate; this.stageStartDate = stateStartedDate;
} }
/**
* RJCTODO:
*
* @return
*/
synchronized Stage getStage() { synchronized Stage getStage() {
return this.stage; return this.stage;
} }
/**
* RJCTODO
*
* @return
*/
synchronized Date getStageStartDate() { synchronized Date getStageStartDate() {
return this.stageStartDate; return this.stageStartDate;
} }
/**
* RJCTODO
*
* @return
*/
synchronized StageDetails getStageDetails() { synchronized StageDetails getStageDetails() {
String description; String description;
Date startDate; Date startDate;
@ -223,7 +196,7 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
if (!ingestModuleHandle.isCancelled()) { if (!ingestModuleHandle.isCancelled()) {
description = ingestModuleHandle.displayName(); description = ingestModuleHandle.displayName();
} else { } else {
description = String.format(Stage.CANCELLING_MODULE.getDisplayText(), ingestModuleHandle.displayName()); // RJCTODO: FIx this description = String.format(Stage.CANCELLING_MODULE.getDisplayText(), ingestModuleHandle.displayName());
} }
} else { } else {
/** /**
@ -248,26 +221,14 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
this.dataSourceProcessor = dataSourceProcessor; this.dataSourceProcessor = dataSourceProcessor;
} }
/**
* RJCTODO
*/
// RJCTODO: Consider moving this class into AIM and making this private
synchronized void setIngestJob(IngestJob ingestJob) { synchronized void setIngestJob(IngestJob ingestJob) {
this.ingestJob = ingestJob; this.ingestJob = ingestJob;
} }
/**
* RJCTODO
*/
// RJCTODO: Consider moving this class into AIM and making this private.
// Or move the AID into a separate package. Or do not worry about it.
synchronized IngestJob getIngestJob() { synchronized IngestJob getIngestJob() {
return this.ingestJob; return this.ingestJob;
} }
/**
* RJCTODO
*/
synchronized void cancel() { synchronized void cancel() {
setStage(Stage.CANCELLING); setStage(Stage.CANCELLING);
cancelled = true; cancelled = true;
@ -280,26 +241,15 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
} }
} }
/**
* RJCTODO
*/
synchronized boolean isCancelled() { synchronized boolean isCancelled() {
return cancelled; return cancelled;
} }
/**
* RJCTODO
*/
synchronized void setCompleted() { synchronized void setCompleted() {
setStage(Stage.COMPLETED); setStage(Stage.COMPLETED);
completed = true; completed = true;
} }
/**
* RJCTODO
*
* @return
*/
synchronized boolean isCompleted() { synchronized boolean isCompleted() {
return completed; return completed;
} }
@ -321,7 +271,7 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
* @return True or false. * @return True or false.
*/ */
synchronized Date getCompletedDate() { synchronized Date getCompletedDate() {
return completedDate; // RJCTODO: Consider returning null if == 0 (epoch) return completedDate;
} }
/** /**
@ -342,23 +292,10 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
return this.errorsOccurred; return this.errorsOccurred;
} }
/**
* RJCTODO Gets name of the node associated with the job, possibly a remote
* hose if the job is in progress.
*
* @return The node name.
*/
String getNodeName() { String getNodeName() {
return nodeName; return nodeName;
} }
/**
* RJCTODO
*
* @param obj
*
* @return
*/
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof AutoIngestJob)) { if (!(obj instanceof AutoIngestJob)) {
@ -370,26 +307,12 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
return this.getManifest().getFilePath().equals(((AutoIngestJob) obj).getManifest().getFilePath()); return this.getManifest().getFilePath().equals(((AutoIngestJob) obj).getManifest().getFilePath());
} }
/**
* RJCTODO
*
* @return
*/
@Override @Override
public int hashCode() { public int hashCode() {
// RJCTODO: Update this int hash = 71 * (Objects.hashCode(this.caseDirectoryPath));
int hash = 7;
// hash = 71 * hash + Objects.hashCode(this.dateCreated);
return hash; return hash;
} }
/**
* RJCTODO Default sorting is by ready file creation date, descending
*
* @param o
*
* @return
*/
@Override @Override
public int compareTo(AutoIngestJob o) { public int compareTo(AutoIngestJob o) {
return -this.getManifest().getDateFileCreated().compareTo(o.getManifest().getDateFileCreated()); return -this.getManifest().getDateFileCreated().compareTo(o.getManifest().getDateFileCreated());
@ -401,14 +324,6 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
*/ */
static class ReverseDateCompletedComparator implements Comparator<AutoIngestJob> { static class ReverseDateCompletedComparator implements Comparator<AutoIngestJob> {
/**
* RJCTODO
*
* @param o1
* @param o2
*
* @return
*/
@Override @Override
public int compare(AutoIngestJob o1, AutoIngestJob o2) { public int compare(AutoIngestJob o1, AutoIngestJob o2) {
return -o1.getStageStartDate().compareTo(o2.getStageStartDate()); return -o1.getStageStartDate().compareTo(o2.getStageStartDate());
@ -420,14 +335,6 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
*/ */
public static class PriorityComparator implements Comparator<AutoIngestJob> { public static class PriorityComparator implements Comparator<AutoIngestJob> {
/**
* RJCTODO
*
* @param job
* @param anotherJob
*
* @return
*/
@Override @Override
public int compare(AutoIngestJob job, AutoIngestJob anotherJob) { public int compare(AutoIngestJob job, AutoIngestJob anotherJob) {
return -(job.getPriority().compareTo(anotherJob.getPriority())); return -(job.getPriority().compareTo(anotherJob.getPriority()));
@ -442,14 +349,6 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
*/ */
static class AlphabeticalComparator implements Comparator<AutoIngestJob> { static class AlphabeticalComparator implements Comparator<AutoIngestJob> {
/**
* RJCTODO
*
* @param o1
* @param o2
*
* @return
*/
@Override @Override
public int compare(AutoIngestJob o1, AutoIngestJob o2) { public int compare(AutoIngestJob o1, AutoIngestJob o2) {
if (o1.getNodeName().equalsIgnoreCase(LOCAL_HOST_NAME)) { if (o1.getNodeName().equalsIgnoreCase(LOCAL_HOST_NAME)) {
@ -462,10 +361,6 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
} }
} }
/**
* RJCTODO
*/
// RJCTODO: Combine this enum with StageDetails to make a single class.
enum Stage { enum Stage {
PENDING("Pending"), PENDING("Pending"),
@ -494,40 +389,21 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
} }
/**
* RJCTODO
*/
@Immutable @Immutable
static final class StageDetails { static final class StageDetails {
private final String description; private final String description;
private final Date startDate; private final Date startDate;
/**
* RJCTODO
*
* @param description
* @param startDate
*/
private StageDetails(String description, Date startDate) { private StageDetails(String description, Date startDate) {
this.description = description; this.description = description;
this.startDate = startDate; this.startDate = startDate;
} }
/**
* RJCTODO
*
* @return
*/
String getDescription() { String getDescription() {
return this.description; return this.description;
} }
/**
* RJCTODO
*
* @return
*/
Date getStartDate() { Date getStartDate() {
return this.startDate; return this.startDate;
} }

View File

@ -22,28 +22,17 @@ import java.io.Serializable;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.events.AutopsyEvent;
/**
* RJCTODO
*/
@Immutable @Immutable
abstract class AutoIngestJobEvent extends AutopsyEvent implements Serializable { abstract class AutoIngestJobEvent extends AutopsyEvent implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final AutoIngestJob job; private final AutoIngestJob job;
/**
* RJCTODO
*
*/
AutoIngestJobEvent(AutoIngestManager.Event eventSubType, AutoIngestJob job) { AutoIngestJobEvent(AutoIngestManager.Event eventSubType, AutoIngestJob job) {
super(eventSubType.toString(), null, null); super(eventSubType.toString(), null, null);
this.job = job; this.job = job;
} }
/**
* RJCTODO
* @return
*/
AutoIngestJob getJob() { AutoIngestJob getJob() {
return this.job; return this.job;
} }

View File

@ -192,7 +192,7 @@ final class AutoIngestJobLogger {
* to acquire an exclusive lock on the * to acquire an exclusive lock on the
* log file. * log file.
*/ */
void logDataSourceProcessorCancelled() throws AutoIngestJobLoggerException, InterruptedException { // RJCTODO: Is this used now? void logDataSourceProcessorCancelled() throws AutoIngestJobLoggerException, InterruptedException {
log(MessageCategory.WARNING, "Cancelled adding data source to case"); log(MessageCategory.WARNING, "Cancelled adding data source to case");
} }
@ -431,7 +431,7 @@ final class AutoIngestJobLogger {
* log file. * log file.
*/ */
private void log(MessageCategory category, String message) throws AutoIngestJobLoggerException, InterruptedException { private void log(MessageCategory category, String message) throws AutoIngestJobLoggerException, InterruptedException {
try (Lock lock = CoordinationService.getInstance(CoordinationServiceNamespace.getRoot()).tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, getLogPath(caseDirectoryPath).toString(), LOCK_TIME_OUT, LOCK_TIME_OUT_UNIT)) { try (Lock lock = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot()).tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, getLogPath(caseDirectoryPath).toString(), LOCK_TIME_OUT, LOCK_TIME_OUT_UNIT)) {
if (null != lock) { if (null != lock) {
File logFile = getLogPath(caseDirectoryPath).toFile(); File logFile = getLogPath(caseDirectoryPath).toFile();
try (PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(logFile, logFile.exists())), true)) { try (PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(logFile, logFile.exists())), true)) {

View File

@ -28,9 +28,6 @@ public final class AutoIngestJobStartedEvent extends AutoIngestJobEvent implemen
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/**
* RJCTODO
*/
public AutoIngestJobStartedEvent(AutoIngestJob job) { public AutoIngestJobStartedEvent(AutoIngestJob job) {
super(AutoIngestManager.Event.JOB_STARTED, job); super(AutoIngestManager.Event.JOB_STARTED, job);
} }

View File

@ -28,9 +28,6 @@ public final class AutoIngestJobStatusEvent extends AutoIngestJobEvent implement
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/**
* RJCTODO
*/
public AutoIngestJobStatusEvent(AutoIngestJob job) { public AutoIngestJobStatusEvent(AutoIngestJob job) {
super(AutoIngestManager.Event.JOB_STATUS_UPDATED, job); super(AutoIngestManager.Event.JOB_STATUS_UPDATED, job);
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -18,11 +18,9 @@
*/ */
package org.sleuthkit.autopsy.experimental.autoingest; package org.sleuthkit.autopsy.experimental.autoingest;
import org.sleuthkit.autopsy.coordinationservice.CoordinationServiceNamespace;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import org.sleuthkit.autopsy.experimental.configuration.AutoIngestUserPreferences;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import static java.nio.file.FileVisitOption.FOLLOW_LINKS; import static java.nio.file.FileVisitOption.FOLLOW_LINKS;
@ -38,9 +36,6 @@ import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.sleuthkit.autopsy.modules.vmextractor.VirtualMachineFinder;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
@ -54,13 +49,13 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.Observable; import java.util.Observable;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -69,65 +64,50 @@ import java.util.stream.Collectors;
import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;
import javax.swing.filechooser.FileFilter; import org.apache.solr.client.solrj.impl.HttpSolrServer;
import javax.xml.parsers.DocumentBuilder; import org.openide.util.Lookup;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.apache.commons.io.FilenameUtils;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.openide.modules.InstalledFileLocator;
import org.sleuthkit.autopsy.casemodule.Case.CaseType; import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.casemodule.GeneralFilter; import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.ImageDSProcessor; import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.core.UserPreferencesException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.ExecUtil;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
import org.sleuthkit.autopsy.ingest.IngestJob;
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration; import org.sleuthkit.autopsy.coordinationservice.CoordinationServiceNamespace;
import org.apache.solr.client.solrj.impl.HttpSolrServer; import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.openide.util.Lookup; import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.casemodule.LocalFilesDSProcessor;
import org.sleuthkit.autopsy.core.ServicesMonitor.ServicesMonitorException; import org.sleuthkit.autopsy.core.ServicesMonitor.ServicesMonitorException;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.core.UserPreferencesException;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult;
import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.autopsy.events.AutopsyEventException; import org.sleuthkit.autopsy.events.AutopsyEventException;
import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason; import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
import org.sleuthkit.autopsy.ingest.IngestJobStartResult; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestAlertFile.AutoIngestAlertFileException;
import org.sleuthkit.autopsy.ingest.IngestModuleError; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobLogger.AutoIngestJobLoggerException;
import org.sleuthkit.autopsy.experimental.autoingest.FileExporter.FileExportException; import org.sleuthkit.autopsy.experimental.autoingest.FileExporter.FileExportException;
import org.sleuthkit.autopsy.experimental.autoingest.ManifestFileParser.ManifestFileParserException; import org.sleuthkit.autopsy.experimental.autoingest.ManifestFileParser.ManifestFileParserException;
import org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus; import org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus;
import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.PENDING;
import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.PROCESSING;
import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.COMPLETED; import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.COMPLETED;
import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.DELETED; import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.DELETED;
import org.sleuthkit.autopsy.corecomponentinterfaces.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException; import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.PENDING;
import org.sleuthkit.autopsy.coreutils.FileUtil; import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.PROCESSING;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestAlertFile.AutoIngestAlertFileException; import org.sleuthkit.autopsy.experimental.configuration.AutoIngestUserPreferences;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobLogger.AutoIngestJobLoggerException; import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration;
import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration.SharedConfigurationException; import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration.SharedConfigurationException;
import org.sleuthkit.autopsy.ingest.IngestJob;
import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason; import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason;
import org.sleuthkit.autopsy.corecomponentinterfaces.AutoIngestDataSourceProcessor; import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestJobStartResult;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestModuleError;
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
import org.sleuthkit.datamodel.Content;
/** /**
* An auto ingest manager is responsible for processing auto ingest jobs defined * An auto ingest manager is responsible for processing auto ingest jobs defined
@ -232,7 +212,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
void startUp() throws AutoIngestManagerStartupException { void startUp() throws AutoIngestManagerStartupException {
SYS_LOGGER.log(Level.INFO, "Auto ingest starting"); SYS_LOGGER.log(Level.INFO, "Auto ingest starting");
try { try {
coordinationService = CoordinationService.getInstance(CoordinationServiceNamespace.getRoot()); coordinationService = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot());
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
throw new AutoIngestManagerStartupException("Failed to get coordination service", ex); throw new AutoIngestManagerStartupException("Failed to get coordination service", ex);
} }
@ -240,7 +220,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
eventPublisher.openRemoteEventChannel(EVENT_CHANNEL_NAME); eventPublisher.openRemoteEventChannel(EVENT_CHANNEL_NAME);
SYS_LOGGER.log(Level.INFO, "Opened auto ingest event channel"); SYS_LOGGER.log(Level.INFO, "Opened auto ingest event channel");
} catch (AutopsyEventException ex) { } catch (AutopsyEventException ex) {
throw new AutoIngestManagerStartupException("Failed to open aut ingest event channel", ex); SYS_LOGGER.log(Level.SEVERE, "Failed to open auto ingest event channel", ex);
throw new AutoIngestManagerStartupException("Failed to open auto ingest event channel", ex);
} }
rootInputDirectory = Paths.get(AutoIngestUserPreferences.getAutoModeImageFolder()); rootInputDirectory = Paths.get(AutoIngestUserPreferences.getAutoModeImageFolder());
rootOutputDirectory = Paths.get(AutoIngestUserPreferences.getAutoModeResultsFolder()); rootOutputDirectory = Paths.get(AutoIngestUserPreferences.getAutoModeResultsFolder());
@ -249,7 +230,13 @@ public final class AutoIngestManager extends Observable implements PropertyChang
jobProcessingTaskFuture = jobProcessingExecutor.submit(jobProcessingTask); jobProcessingTaskFuture = jobProcessingExecutor.submit(jobProcessingTask);
jobStatusPublishingExecutor.scheduleAtFixedRate(new PeriodicJobStatusEventTask(), JOB_STATUS_EVENT_INTERVAL_SECONDS, JOB_STATUS_EVENT_INTERVAL_SECONDS, TimeUnit.SECONDS); jobStatusPublishingExecutor.scheduleAtFixedRate(new PeriodicJobStatusEventTask(), JOB_STATUS_EVENT_INTERVAL_SECONDS, JOB_STATUS_EVENT_INTERVAL_SECONDS, TimeUnit.SECONDS);
eventPublisher.addSubscriber(EVENT_LIST, instance); eventPublisher.addSubscriber(EVENT_LIST, instance);
RuntimeProperties.setCoreComponentsActive(false); try {
RuntimeProperties.setRunningWithGUI(false);
SYS_LOGGER.log(Level.INFO, "Set running with desktop GUI runtime property to false");
} catch (RuntimeProperties.RuntimePropertiesException ex) {
SYS_LOGGER.log(Level.SEVERE, "Failed to set running with desktop GUI runtime property to false", ex);
throw new AutoIngestManagerStartupException("Failed to set running with desktop GUI runtime property to false", ex);
}
state = State.RUNNING; state = State.RUNNING;
errorState = ErrorState.NONE; errorState = ErrorState.NONE;
} }
@ -483,7 +470,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
for (AutoIngestJob job : hostNamesToRunningJobs.values()) { for (AutoIngestJob job : hostNamesToRunningJobs.values()) {
runningJobs.add(job); runningJobs.add(job);
runningJobs.sort(new AutoIngestJob.AlphabeticalComparator()); // RJCTODO: This sort should be done in the AID runningJobs.sort(new AutoIngestJob.AlphabeticalComparator());
} }
} }
if (null != completedJobs) { if (null != completedJobs) {
@ -684,18 +671,22 @@ public final class AutoIngestManager extends Observable implements PropertyChang
return CaseDeletionResult.FAILED; return CaseDeletionResult.FAILED;
} }
/*
* Acquire an exclusive lock on the case so it can be safely deleted.
* This will fail if the case is open for review or a deletion operation
* on this case is already in progress on another node.
*/
CaseDeletionResult result = CaseDeletionResult.FULLY_DELETED; CaseDeletionResult result = CaseDeletionResult.FULLY_DELETED;
List<Lock> manifestFileLocks = new ArrayList<>(); List<Lock> manifestFileLocks = new ArrayList<>();
try (Lock caseLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())) { try {
if (null == caseLock) { synchronized (jobsLock) {
/*
* Get the case metadata.
*/
CaseMetadata metaData;
Path caseMetaDataFilePath = Paths.get(caseDirectoryPath.toString(), caseName + CaseMetadata.getFileExtension());
try {
metaData = new CaseMetadata(caseMetaDataFilePath);
} catch (CaseMetadata.CaseMetadataException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Failed to get case metadata file %s for case %s at %s", caseMetaDataFilePath, caseName, caseDirectoryPath), ex);
return CaseDeletionResult.FAILED; return CaseDeletionResult.FAILED;
} }
synchronized (jobsLock) {
/* /*
* Do a fresh input directory scan. * Do a fresh input directory scan.
*/ */
@ -703,12 +694,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang
scanner.scan(); scanner.scan();
Set<Path> manifestPaths = casesToManifests.get(caseName); Set<Path> manifestPaths = casesToManifests.get(caseName);
if (null == manifestPaths) { if (null == manifestPaths) {
SYS_LOGGER.log(Level.SEVERE, "No manifest paths found for case {0}", caseName); SYS_LOGGER.log(Level.SEVERE, String.format("No manifest paths found for case %s at %s", caseName, caseDirectoryPath));
return CaseDeletionResult.FAILED; return CaseDeletionResult.FAILED;
} }
/* /*
* Get all of the required manifest locks. * Get exclusive locks on all of the manifests for the case.
* This will exclude other auot ingest nodes from doing anything
* with the case.
*/ */
for (Path manifestPath : manifestPaths) { for (Path manifestPath : manifestPaths) {
try { try {
@ -719,20 +712,18 @@ public final class AutoIngestManager extends Observable implements PropertyChang
return CaseDeletionResult.FAILED; return CaseDeletionResult.FAILED;
} }
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to acquire manifest lock for %s for case %s", manifestPath, caseName), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to acquire manifest lock for %s for case %s at %s", manifestPath, caseName, caseDirectoryPath), ex);
return CaseDeletionResult.FAILED; return CaseDeletionResult.FAILED;
} }
} }
/*
* Get the case metadata.
*/
CaseMetadata metaData;
Path caseMetaDataFilePath = Paths.get(caseDirectoryPath.toString(), caseName + CaseMetadata.getFileExtension());
try { try {
metaData = new CaseMetadata(caseMetaDataFilePath); /*
} catch (CaseMetadata.CaseMetadataException ex) { * Physically delete the case.
SYS_LOGGER.log(Level.SEVERE, String.format("Failed to delete case metadata file %s for case %s", caseMetaDataFilePath, caseName)); */
Case.deleteCase(metaData);
} catch (CaseActionException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Failed to physically delete case %s at %s", caseName, caseDirectoryPath), ex);
return CaseDeletionResult.FAILED; return CaseDeletionResult.FAILED;
} }
@ -745,56 +736,11 @@ public final class AutoIngestManager extends Observable implements PropertyChang
nodeData.setStatus(ManifestNodeData.ProcessingStatus.DELETED); nodeData.setStatus(ManifestNodeData.ProcessingStatus.DELETED);
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString(), nodeData.toArray()); coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString(), nodeData.toArray());
} catch (InterruptedException | CoordinationServiceException ex) { } catch (InterruptedException | CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set delete flag on manifest data for %s for case %s", manifestPath, caseName), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set delete flag on manifest data for %s for case %s at %s", manifestPath, caseName, caseDirectoryPath), ex);
return CaseDeletionResult.PARTIALLY_DELETED; return CaseDeletionResult.PARTIALLY_DELETED;
} }
} }
/*
* Try to unload/delete the Solr core from the Solr server. Do
* this before deleting the case directory because the index
* files are in the case directory and the deletion will fail if
* the core is not unloaded first.
*/
String textIndexName = metaData.getTextIndexName();
try {
unloadSolrCore(metaData.getTextIndexName());
} catch (Exception ex) {
/*
* Could be a problem, or it could be that the core was
* already unloaded (e.g., by the server due to resource
* constraints).
*/
SYS_LOGGER.log(Level.WARNING, String.format("Error deleting text index %s for %s", textIndexName, caseName), ex); //NON-NLS
}
/*
* Delete the case database from the database server.
*/
String caseDatabaseName = metaData.getCaseDatabaseName();
try {
deleteCaseDatabase(caseDatabaseName);
} catch (SQLException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Unable to delete case database %s for %s", caseDatabaseName, caseName), ex); //NON-NLS
result = CaseDeletionResult.PARTIALLY_DELETED;
} catch (UserPreferencesException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error accessing case database connection info, unable to delete case database %s for %s", caseDatabaseName, caseName), ex); //NON-NLS
result = CaseDeletionResult.PARTIALLY_DELETED;
} catch (ClassNotFoundException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Cannot load database driver, unable to delete case database %s for %s", caseDatabaseName, caseName), ex); //NON-NLS
result = CaseDeletionResult.PARTIALLY_DELETED;
}
/*
* Delete the case directory.
*/
File caseDirectory = caseDirectoryPath.toFile();
FileUtil.deleteDir(caseDirectory);
if (caseDirectory.exists()) {
SYS_LOGGER.log(Level.SEVERE, String.format("Failed to delete case directory %s for case %s", caseDirectoryPath, caseName));
return CaseDeletionResult.PARTIALLY_DELETED;
}
/* /*
* Remove the jobs for the case from the pending jobs queue and * Remove the jobs for the case from the pending jobs queue and
* completed jobs list. * completed jobs list.
@ -809,16 +755,15 @@ public final class AutoIngestManager extends Observable implements PropertyChang
notifyObservers(Event.CASE_DELETED); notifyObservers(Event.CASE_DELETED);
return result; return result;
} catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Error acquiring coordination service lock on case %s", caseName), ex);
return CaseDeletionResult.FAILED;
} finally { } finally {
/*
* Always release the manifest locks, regardless of the outcome.
*/
for (Lock lock : manifestFileLocks) { for (Lock lock : manifestFileLocks) {
try { try {
lock.release(); lock.release();
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Failed to release manifest file lock when deleting case %s", caseName), ex); SYS_LOGGER.log(Level.SEVERE, String.format("Failed to release manifest file lock when deleting case %s at %s", caseName, caseDirectoryPath), ex);
} }
} }
} }
@ -826,6 +771,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
/** /**
* Get the current snapshot of the job lists. * Get the current snapshot of the job lists.
*
* @return Snapshot of jobs lists * @return Snapshot of jobs lists
*/ */
JobsSnapshot getCurrentJobsSnapshot() { JobsSnapshot getCurrentJobsSnapshot() {
@ -895,9 +841,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* Starts the process of cancelling the current job. * Starts the process of cancelling the current job.
* *
* Note that the current job is included in the running list for a while * Note that the current job is included in the running list for a while
* because it can take some time * because it can take some time for the automated ingest process for the
* for the automated ingest process for the job to be shut down in * job to be shut down in an orderly fashion.
* an orderly fashion.
*/ */
void cancelCurrentJob() { void cancelCurrentJob() {
if (State.RUNNING != state) { if (State.RUNNING != state) {
@ -1655,8 +1600,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @throws CoordinationServiceException if there is an error while * @throws CoordinationServiceException if there is an error while
* acquiring or releasing a * acquiring or releasing a
* manifest file lock. * manifest file lock.
* @throws InterruptedException if the thread is interrupted while * @throws InterruptedException if the thread is interrupted
* reading the lock data * while reading the lock data
*/ */
private Lock dequeueAndLockNextJob() throws CoordinationServiceException, InterruptedException { private Lock dequeueAndLockNextJob() throws CoordinationServiceException, InterruptedException {
SYS_LOGGER.log(Level.INFO, "Checking pending jobs queue for ready job, enforcing max jobs per case"); SYS_LOGGER.log(Level.INFO, "Checking pending jobs queue for ready job, enforcing max jobs per case");
@ -1694,8 +1639,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @throws CoordinationServiceException if there is an error while * @throws CoordinationServiceException if there is an error while
* acquiring or releasing a * acquiring or releasing a
* manifest file lock. * manifest file lock.
* @throws InterruptedException if the thread is interrupted while * @throws InterruptedException if the thread is interrupted
* reading the lock data * while reading the lock data
*/ */
private Lock dequeueAndLockNextJob(boolean enforceMaxJobsPerCase) throws CoordinationServiceException, InterruptedException { private Lock dequeueAndLockNextJob(boolean enforceMaxJobsPerCase) throws CoordinationServiceException, InterruptedException {
Lock manifestLock = null; Lock manifestLock = null;
@ -1718,8 +1663,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
ManifestNodeData nodeData = new ManifestNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString())); ManifestNodeData nodeData = new ManifestNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
if (!nodeData.getStatus().equals(PENDING)) { if (!nodeData.getStatus().equals(PENDING)) {
/* /*
* Due to a timing issue or a missed event, * Due to a timing issue or a missed event, a
* a non-pending job has ended up on the pending queue. * non-pending job has ended up on the pending queue.
* Skip the job and remove it from the queue. * Skip the job and remove it from the queue.
*/ */
iterator.remove(); iterator.remove();
@ -1820,7 +1765,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath, nodeData.toArray()); coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath, nodeData.toArray());
boolean retry = (!currentJob.isCancelled() && !currentJob.isCompleted()); boolean retry = (!currentJob.isCancelled() && !currentJob.isCompleted());
SYS_LOGGER.log(Level.INFO, "Completed processing of {0}, retry = {1}", new Object[]{manifestPath, retry}); SYS_LOGGER.log(Level.INFO, "Completed processing of {0}, retry = {1}", new Object[]{manifestPath, retry});
if (currentJob.isCancelled()) { if (currentJob.isCancelled()) {
@ -1892,7 +1836,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} finally { } finally {
try { try {
caseForJob.closeCase(); Case.closeCurrentCase();
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
Manifest manifest = currentJob.getManifest(); Manifest manifest = currentJob.getManifest();
throw new CaseManagementException(String.format("Error closing case %s for %s", manifest.getCaseName(), manifest.getFilePath()), ex); throw new CaseManagementException(String.format("Error closing case %s for %s", manifest.getCaseName(), manifest.getFilePath()), ex);
@ -1983,20 +1927,17 @@ public final class AutoIngestManager extends Observable implements PropertyChang
String caseName = manifest.getCaseName(); String caseName = manifest.getCaseName();
SYS_LOGGER.log(Level.INFO, "Opening case {0} for {1}", new Object[]{caseName, manifest.getFilePath()}); SYS_LOGGER.log(Level.INFO, "Opening case {0} for {1}", new Object[]{caseName, manifest.getFilePath()});
currentJob.setStage(AutoIngestJob.Stage.OPENING_CASE); currentJob.setStage(AutoIngestJob.Stage.OPENING_CASE);
try (Lock caseLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, caseName, 30, TimeUnit.MINUTES)) {
if (null != caseLock) {
try { try {
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, caseName); Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, caseName);
if (null != caseDirectoryPath) { if (null != caseDirectoryPath) {
Path metadataFilePath = caseDirectoryPath.resolve(manifest.getCaseName() + CaseMetadata.getFileExtension()); Path metadataFilePath = caseDirectoryPath.resolve(manifest.getCaseName() + CaseMetadata.getFileExtension());
Case.open(metadataFilePath.toString()); Case.openAsCurrentCase(metadataFilePath.toString());
} else { } else {
caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName); caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName);
Case.create(caseDirectoryPath.toString(), currentJob.getManifest().getCaseName(), "", "", CaseType.MULTI_USER_CASE); Case.createAsCurrentCase(caseDirectoryPath.toString(), currentJob.getManifest().getCaseName(), "", "", CaseType.MULTI_USER_CASE);
/* /*
* Sleep a bit before releasing the lock to ensure * Sleep a bit before releasing the lock to ensure that the
* that the new case folder is visible on the * new case folder is visible on the network.
* network.
*/ */
Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000); Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000);
} }
@ -2009,16 +1950,11 @@ public final class AutoIngestManager extends Observable implements PropertyChang
throw new CaseManagementException(String.format("Error creating or opening case %s for %s", manifest.getCaseName(), manifest.getFilePath()), ex); throw new CaseManagementException(String.format("Error creating or opening case %s for %s", manifest.getCaseName(), manifest.getFilePath()), ex);
} catch (IllegalStateException ex) { } catch (IllegalStateException ex) {
/* /*
* Deal with the unfortunate fact that * Deal with the unfortunate fact that Case.getCurrentCase
* Case.getCurrentCase throws IllegalStateException. * throws IllegalStateException.
*/ */
throw new CaseManagementException(String.format("Error getting current case %s for %s", manifest.getCaseName(), manifest.getFilePath()), ex); throw new CaseManagementException(String.format("Error getting current case %s for %s", manifest.getCaseName(), manifest.getFilePath()), ex);
} }
} else {
throw new CaseManagementException(String.format("Timed out acquiring case name lock for %s for %s", manifest.getCaseName(), manifest.getFilePath()));
}
}
} }
/** /**
@ -2118,7 +2054,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* Sleep to allow ingest event subscribers to do their event * Sleep to allow ingest event subscribers to do their event
* handling. * handling.
*/ */
Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000); // RJCTODO: Change the setting description to be more generic Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000);
} }
if (currentJob.isCancelled() || jobProcessingTaskFuture.isCancelled()) { if (currentJob.isCancelled() || jobProcessingTaskFuture.isCancelled()) {
@ -2370,7 +2306,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/ */
ingestLock.wait(); ingestLock.wait();
IngestJob.ProgressSnapshot jobSnapshot = ingestJob.getSnapshot(); IngestJob.ProgressSnapshot jobSnapshot = ingestJob.getSnapshot();
for (IngestJob.ProgressSnapshot.DataSourceProcessingSnapshot snapshot : jobSnapshot.getDataSourceSnapshots()) { // RJCTODO: Are "child" jobs IngestJobs or DataSourceIngestJobs? for (IngestJob.ProgressSnapshot.DataSourceProcessingSnapshot snapshot : jobSnapshot.getDataSourceSnapshots()) {
if (!snapshot.isCancelled()) { if (!snapshot.isCancelled()) {
List<String> cancelledModules = snapshot.getCancelledDataSourceIngestModules(); List<String> cancelledModules = snapshot.getCancelledDataSourceIngestModules();
if (!cancelledModules.isEmpty()) { if (!cancelledModules.isEmpty()) {
@ -2421,7 +2357,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
} finally { } finally {
IngestManager.getInstance().removeIngestJobEventListener(ingestJobEventListener); IngestManager.getInstance().removeIngestJobEventListener(ingestJobEventListener);
currentJob.setIngestJob(null); // RJCTODO: Consider moving AutoIngestJob into AutoIngestManager so that this method can be made private currentJob.setIngestJob(null);
} }
} }
@ -2686,7 +2622,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* remote jobs. The auto ingest job status event is sent only if auto ingest * remote jobs. The auto ingest job status event is sent only if auto ingest
* manager has a currently running auto ingest job. * manager has a currently running auto ingest job.
*/ */
private final class PeriodicJobStatusEventTask implements Runnable { // RJCTODO: Rename to StatusPublishingTask, especially when publishing to the system dashboard private final class PeriodicJobStatusEventTask implements Runnable {
private final long MAX_SECONDS_WITHOUT_UPDATE = JOB_STATUS_EVENT_INTERVAL_SECONDS * MAX_MISSED_JOB_STATUS_UPDATES; private final long MAX_SECONDS_WITHOUT_UPDATE = JOB_STATUS_EVENT_INTERVAL_SECONDS * MAX_MISSED_JOB_STATUS_UPDATES;
@ -2710,8 +2646,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
boolean isError = false; boolean isError = false;
if (getErrorState().equals(ErrorState.NONE)) { if (getErrorState().equals(ErrorState.NONE)) {
if (currentJob != null) { if (currentJob != null) {
message = "Processing " + currentJob.getManifest().getDataSourceFileName() + message = "Processing " + currentJob.getManifest().getDataSourceFileName()
" for case " + currentJob.getManifest().getCaseName(); + " for case " + currentJob.getManifest().getCaseName();
} else { } else {
message = "Paused or waiting for next case"; message = "Paused or waiting for next case";
} }
@ -2778,7 +2714,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
/* /*
* Events published by an auto ingest manager. The events are published * Events published by an auto ingest manager. The events are published
* locally to auto ingest manager clients that register as observers and are * locally to auto ingest manager clients that register as observers and are
* broadcast to other auto ingest nodes. // RJCTODO: Is this true? * broadcast to other auto ingest nodes.
*/ */
enum Event { enum Event {
@ -2853,7 +2789,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @return The jobs collection. * @return The jobs collection.
*/ */
List<AutoIngestJob> getPendingJobs() { List<AutoIngestJob> getPendingJobs() {
return this.pendingJobs; return Collections.unmodifiableList(this.pendingJobs);
} }
/** /**
@ -2862,7 +2798,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @return The jobs collection. * @return The jobs collection.
*/ */
List<AutoIngestJob> getRunningJobs() { List<AutoIngestJob> getRunningJobs() {
return this.runningJobs; return Collections.unmodifiableList(this.runningJobs);
} }
/** /**
@ -2871,14 +2807,11 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @return The jobs collection. * @return The jobs collection.
*/ */
List<AutoIngestJob> getCompletedJobs() { List<AutoIngestJob> getCompletedJobs() {
return this.completedJobs; return Collections.unmodifiableList(this.completedJobs);
} }
} }
/**
* RJCTODO
*/
enum CaseDeletionResult { enum CaseDeletionResult {
FAILED, FAILED,
PARTIALLY_DELETED, PARTIALLY_DELETED,

View File

@ -34,9 +34,6 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
/**
* RJCTODO
*/
@Immutable @Immutable
@ServiceProvider(service = ManifestFileParser.class) @ServiceProvider(service = ManifestFileParser.class)
public final class AutopsyManifestFileParser implements ManifestFileParser { public final class AutopsyManifestFileParser implements ManifestFileParser {
@ -47,14 +44,6 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
private static final String DEVICE_ID_XPATH = "/Manifest/Collection/Image/ID/text()"; private static final String DEVICE_ID_XPATH = "/Manifest/Collection/Image/ID/text()";
private static final String DATA_SOURCE_NAME_XPATH = "/Manifest/Collection/Image/Name/text()"; private static final String DATA_SOURCE_NAME_XPATH = "/Manifest/Collection/Image/Name/text()";
/**
* RJCTODO
*
* @param filePath
*
* @return
*/
@Override @Override
public boolean fileIsManifest(Path filePath) { public boolean fileIsManifest(Path filePath) {
boolean fileIsManifest = false; boolean fileIsManifest = false;
@ -71,15 +60,6 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
return fileIsManifest; return fileIsManifest;
} }
/**
* RJCTODO
*
* @param filePath
*
* @return
*
* @throws org.sleuthkit.autopsy.experimental.autoingest.ManifestFileParser.ManifestFileParserException
*/
@Override @Override
public Manifest parse(Path filePath) throws ManifestFileParserException { public Manifest parse(Path filePath) throws ManifestFileParserException {
if (!fileIsManifest(filePath)) { if (!fileIsManifest(filePath)) {
@ -102,17 +82,6 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
} }
} }
/**
* RJCTODO
*
* @param manifestFilePath
*
* @return
*
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
*/
private Document createManifestDOM(Path manifestFilePath) throws ParserConfigurationException, SAXException, IOException { private Document createManifestDOM(Path manifestFilePath) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();

View File

@ -89,13 +89,6 @@ OpenIDE-Module-Long-Description=\
We make no guarantee that the API of this module will not change, so developers should be careful when relying on it. We make no guarantee that the API of this module will not change, so developers should be careful when relying on it.
OpenIDE-Module-Name=Experimental OpenIDE-Module-Name=Experimental
OpenIDE-Module-Short-Description=This module contains features that are being developed by Basis Technology and are not part of the default Autopsy distribution. OpenIDE-Module-Short-Description=This module contains features that are being developed by Basis Technology and are not part of the default Autopsy distribution.
ReviewModeCasePanel.bnRefresh.text=&Refresh
ReviewModeCasePanel.bnOpen.text=&Open
ReviewModeCasePanel.rbGroupLabel.text=Show Last 10:
ReviewModeCasePanel.rbDays.text=Days
ReviewModeCasePanel.rbWeeks.text=Weeks
ReviewModeCasePanel.rbMonths.text=Months
ReviewModeCasePanel.rbAllCases.text=Everything
ReviewModeCasePanel.cannotOpenCase=Cannot Open Case ReviewModeCasePanel.cannotOpenCase=Cannot Open Case
ReviewModeCasePanel.casePathNotFound=Case path not found ReviewModeCasePanel.casePathNotFound=Case path not found
ReviewModeCasePanel.caseIsLocked=Single-user case is locked. ReviewModeCasePanel.caseIsLocked=Single-user case is locked.
@ -170,12 +163,10 @@ CopyFilesPanel.ConfirmCopyAdd=exists. Do you really want to copy more files to t
CopyFilesPanel.ConfirmCopyYes=Copy CopyFilesPanel.ConfirmCopyYes=Copy
CopyFilesPanel.ConfirmCopyNo=Do not copy CopyFilesPanel.ConfirmCopyNo=Do not copy
ConfirmationDialog.ConfirmUnlockHeader=Confirm Case Unlock ConfirmationDialog.ConfirmUnlockHeader=Confirm Case Unlock
ReviewModeCasePanel.bnShowLog.text=&Show Log
AutoIngestDashboard.bnPrioritizeCase.toolTipText=Move all images associated with a case to top of Pending queue. AutoIngestDashboard.bnPrioritizeCase.toolTipText=Move all images associated with a case to top of Pending queue.
AutoIngestDashboard.bnPrioritizeCase.text=Prioriti&ze Case AutoIngestDashboard.bnPrioritizeCase.text=Prioriti&ze Case
AutoIngestDashboard.bnShowCaseLog.toolTipText=Display case log file for selected case AutoIngestDashboard.bnShowCaseLog.toolTipText=Display case log file for selected case
AutoIngestDashboard.bnShowCaseLog.text=Show Case &Log AutoIngestDashboard.bnShowCaseLog.text=Show Case &Log
ReviewModeCasePanel.bnShowLog.toolTipText=Display case log file for selected case
CopyFilesPanel.bnCancelPendingJob.text=Ca&ncel CopyFilesPanel.bnCancelPendingJob.text=Ca&ncel
CopyFilesPanel.tbDestinationCase.text= CopyFilesPanel.tbDestinationCase.text=
CopyFilesPanel.cbThrottleNetwork.text=&Throttle Network CopyFilesPanel.cbThrottleNetwork.text=&Throttle Network
@ -298,3 +289,12 @@ AutoIngestDashboard.bnPrioritizeJob.toolTipText=Move this folder to the top of t
AutoIngestDashboard.bnReprocessJob.text=Reprocess Job AutoIngestDashboard.bnReprocessJob.text=Reprocess Job
AutoIngestDashboard.bnPrioritizeFolder.label=<AutoIngestDashboard.bnPrioritizeJob.text> AutoIngestDashboard.bnPrioritizeFolder.label=<AutoIngestDashboard.bnPrioritizeJob.text>
AutoIngestDashboard.bnPrioritizeJob.actionCommand=<AutoIngestDashboard.bnPrioritizeJob.text> AutoIngestDashboard.bnPrioritizeJob.actionCommand=<AutoIngestDashboard.bnPrioritizeJob.text>
AutoIngestCasePanel.rbDays.text=Days
AutoIngestCasePanel.rbWeeks.text=Weeks
AutoIngestCasePanel.rbMonths.text=Months
AutoIngestCasePanel.rbAllCases.text=Everything
AutoIngestCasePanel.bnRefresh.text=&Refresh
AutoIngestCasePanel.bnOpen.text=&Open
AutoIngestCasePanel.bnShowLog.toolTipText=Display case log file for selected case
AutoIngestCasePanel.bnShowLog.text=&Show Log
AutoIngestCasePanel.rbGroupLabel.text=Show Last 10:

Some files were not shown because too many files have changed in this diff Show More