Merge pull request #2568 from APriestman/imageWriterListener

Refactor image writer
This commit is contained in:
Richard Cordovano 2017-03-08 11:34:59 -05:00 committed by GitHub
commit cbb7ee515b
947 changed files with 154990 additions and 9358 deletions

View File

@ -31,6 +31,14 @@
<specification-version>1.46.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.api.templates</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.6.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.core</code-name-base>
<build-prerequisite/>
@ -155,6 +163,14 @@
<specification-version>9.7.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.loaders</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.63.2</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.modules</code-name-base>
<build-prerequisite/>
@ -242,6 +258,7 @@
<package>org.sleuthkit.autopsy.events</package>
<package>org.sleuthkit.autopsy.externalresults</package>
<package>org.sleuthkit.autopsy.filesearch</package>
<package>org.sleuthkit.autopsy.framework</package>
<package>org.sleuthkit.autopsy.ingest</package>
<package>org.sleuthkit.autopsy.keywordsearchservice</package>
<package>org.sleuthkit.autopsy.menuactions</package>

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -25,27 +25,37 @@ import org.openide.LifecycleManager;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* The action associated with the Case/Exit menu item. It closes the current
* case, if any, and shuts down the application.
*/
@ActionRegistration(displayName = "Exit", iconInMenu = true)
@ActionReference(path = "Menu/Case", position = 1000, separatorBefore = 999)
@ActionID(id = "org.sleuthkit.autopsy.casemodule.ExitAction", category = "Case")
final public class ExitAction implements ActionListener {
@NbBundle.Messages({
"ExitAction.confirmationDialog.title=Ingest is Running",
"ExitAction.confirmationDialog.message=Ingest is running, are you sure you want to exit?"
})
@Override
public void actionPerformed(ActionEvent e) {
if (IngestRunningCheck.checkAndConfirmProceed(Bundle.ExitAction_confirmationDialog_title(), Bundle.ExitAction_confirmationDialog_message())) {
new Thread(() -> {
try {
Case currentCase = Case.getCurrentCase();
if (currentCase != null) {
currentCase.closeCase();
}
} catch (Exception ex) {
Logger.getLogger(ExitAction.class.getName()).log(Level.SEVERE, "Had a problem closing the case.", ex); //NON-NLS
Case.closeCurrentCase();
} catch (CaseActionException ex) {
Logger.getLogger(ExitAction.class.getName()).log(Level.SEVERE, "Error closing the current case on exit", ex); //NON-NLS
} finally {
LifecycleManager.getDefault().exit();
}
}).start();
}
}
}

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
*
* Copyright 2014-2015 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,9 +18,9 @@
*/
package org.sleuthkit.autopsy.actions;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
@ -35,10 +35,14 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Action in menu to open the folder containing the log files
* The action associated with the Help/Open Log Folder menu item. It opens a
* file explorer window for either the log subdirectory for the currently open
* case, or the log subdirectory of the user directory, if there is no current
* case.
*
* This action should only be invoked in the event dispatch thread (EDT).
*/
@ActionRegistration(
displayName = "#CTL_OpenLogFolder", iconInMenu = true)
@ActionRegistration(displayName = "#CTL_OpenLogFolder", iconInMenu = true)
@ActionReference(path = "Menu/Help", position = 1750)
@ActionID(id = "org.sleuthkit.autopsy.actions.OpenLogFolderAction", category = "Help")
public final class OpenLogFolderAction implements ActionListener {
@ -47,25 +51,42 @@ public final class OpenLogFolderAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
try {
File logDir;
if (Case.isCaseOpen()) {
logDir = new File(Case.getCurrentCase().getLogDirectoryPath());
try {
/*
* Open the log directory for the case.
*/
Case currentCase = Case.getCurrentCase();
logDir = new File(currentCase.getLogDirectoryPath());
} catch (IllegalStateException ex) {
/*
* There is no open case, open the application level log
* directory.
*/
logDir = new File(Places.getUserDirectory().getAbsolutePath() + File.separator + "var" + File.separator + "log");
}
} else {
logDir = new File(Places.getUserDirectory().getAbsolutePath() + File.separator + "var" + File.separator + "log");
}
if (logDir.exists() == false) {
NotifyDescriptor d
= new NotifyDescriptor.Message(
try {
if (logDir.exists()) {
Desktop.getDesktop().open(logDir);
} else {
logger.log(Level.SEVERE, String.format("The log directory %s does not exist", logDir));
NotifyDescriptor notifyDescriptor = new NotifyDescriptor.Message(
NbBundle.getMessage(this.getClass(), "OpenLogFolder.error1", logDir.getAbsolutePath()),
NotifyDescriptor.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(d);
} else {
Desktop.getDesktop().open(logDir);
DialogDisplayer.getDefault().notify(notifyDescriptor);
}
} catch (IOException ex) {
logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "OpenLogFolder.CouldNotOpenLogFolder"), ex); //NON-NLS
logger.log(Level.SEVERE, String.format("Could not open log directory %s", logDir), ex);
NotifyDescriptor notifyDescriptor = new NotifyDescriptor.Message(
NbBundle.getMessage(this.getClass(), "OpenLogFolder.CouldNotOpenLogFolder", logDir.getAbsolutePath()),
NotifyDescriptor.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(notifyDescriptor);
}
}
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -35,37 +35,45 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Action in menu to open the folder containing the output files
* The action associated with the Tools/Open Output Folder menu item. It opens a
* file explorer window for the root output directory for the currently open
* case. If the case is a single-user case, this is the case directory. If the
* case is a multi-user case, this is a subdirectory of the case directory
* specific to the host machine.
*
* This action should only be invoked in the event dispatch thread (EDT).
*/
@ActionRegistration(
displayName = "#CTL_OpenOutputFolder", iconInMenu = true, lazy=true)
@ActionRegistration(displayName = "#CTL_OpenOutputFolder", iconInMenu = true, lazy = false)
@ActionReference(path = "Menu/Tools", position = 1850, separatorBefore = 1849)
@ActionID(id = "org.sleuthkit.autopsy.actions.OpenOutputFolderAction", category = "Help")
public final class OpenOutputFolderAction extends CallableSystemAction {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(OpenOutputFolderAction.class.getName());
@Override
public void performAction() {
try {
File outputDir;
if (Case.isCaseOpen()) {
outputDir = new File(Case.getCurrentCase().getOutputDirectory());
if (outputDir.exists() == false) {
NotifyDescriptor d
= new NotifyDescriptor.Message(NbBundle.getMessage(this.getClass(),
"OpenOutputFolder.error1", outputDir.getAbsolutePath()),
NotifyDescriptor.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(d);
} else {
try {
Case currentCase = Case.getCurrentCase();
outputDir = new File(currentCase.getOutputDirectory());
if (outputDir.exists()) {
try {
Desktop.getDesktop().open(outputDir);
} catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Failed to open output folder %s", outputDir), ex); //NON-NLS
NotifyDescriptor descriptor = new NotifyDescriptor.Message(
NbBundle.getMessage(this.getClass(), "OpenOutputFolder.CouldNotOpenOutputFolder", outputDir.getAbsolutePath()), NotifyDescriptor.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(descriptor);
}
} else {
JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "OpenOutputFolder.noCaseOpen"));
NotifyDescriptor descriptor = new NotifyDescriptor.Message(
NbBundle.getMessage(this.getClass(), "OpenOutputFolder.error1", outputDir.getAbsolutePath()), NotifyDescriptor.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(descriptor);
}
} catch (IOException ex) {
logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "OpenOutputFolder.CouldNotOpenOutputFolder"), ex); //NON-NLS
} catch (IllegalStateException ex) {
logger.log(Level.SEVERE, "OpenOutputFolderAction enabled with no current case", ex); //NON-NLS
JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "OpenOutputFolder.noCaseOpen"));
}
}
@ -81,8 +89,9 @@ public final class OpenOutputFolderAction extends CallableSystemAction {
@Override
public boolean asynchronous() {
return false; // run on edt
return false;
}
@Override
public String getName() {
return NbBundle.getMessage(OpenOutputFolderAction.class, "CTL_OpenOutputFolder");

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2014 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.casemodule;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
@ -28,7 +29,6 @@ import java.util.logging.Level;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@ -44,26 +44,26 @@ import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter;
import org.openide.util.lookup.ServiceProvider;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.Image;
/**
* The action to add an image to the current Case. This action should be
* disabled on creation and it will be enabled on new case creation or case
* opened.
* An action that invokes the Add Data Source wizard.
*
* @author jantonius
* This action should only be invoked in the event dispatch thread (EDT).
*/
// TODO: need annotation because there's a "Lookup.getDefault().lookup(AddImageAction.class)"
// used in AddImageWizardPanel1 (among other places). It really shouldn't be done like that.
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.casemodule.AddImageAction")
@ActionRegistration(displayName = "#CTL_AddImage", lazy = false)
@ActionReferences(value = {
@ActionReference(path = "Toolbars/Case", position = 100)})
@ActionReferences(value = {@ActionReference(path = "Toolbars/Case", position = 100)})
@ServiceProvider(service = AddImageAction.class)
public final class AddImageAction extends CallableSystemAction implements Presenter.Toolbar {
private static final long serialVersionUID = 1L;
private static final Dimension SIZE = new Dimension(875, 550);
private final ChangeSupport cleanupSupport = new ChangeSupport(this);
// Keys into the WizardDescriptor properties that pass information between stages of the wizard
// <TYPE>: <DESCRIPTION>
// String: time zone that the image is from
@ -84,15 +84,13 @@ public final class AddImageAction extends CallableSystemAction implements Presen
static final String NOFATORPHANS_PROP = "nofatorphans"; //NON-NLS
static final Logger logger = Logger.getLogger(AddImageAction.class.getName());
static final Dimension SIZE = new Dimension(875, 550);
private WizardDescriptor wizardDescriptor;
private WizardDescriptor.Iterator<WizardDescriptor> iterator;
private Dialog dialog;
private JButton toolbarButton = new JButton();
private final JButton toolbarButton = new JButton();
/**
* The constructor for AddImageAction class
* Constructs an action that invokes the Add Data Source wizard.
*/
public AddImageAction() {
putValue(Action.NAME, NbBundle.getMessage(AddImageAction.class, "CTL_AddImage")); // set the action Name
@ -106,26 +104,19 @@ public final class AddImageAction extends CallableSystemAction implements Presen
}
});
this.setEnabled(false); // disable this action class
/*
* Disable this action until a case is opened. Currently, the Case class
* enables the action.
*/
this.setEnabled(false);
}
/**
* Pop-up the "Add Image" wizard panel.
*
* @param e
*/
@Override
public void actionPerformed(ActionEvent e) {
if (IngestManager.getInstance().isIngestRunning()) {
final String msg = NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.msg");
if (JOptionPane.showConfirmDialog(null, msg,
NbBundle.getMessage(this.getClass(),
"AddImageAction.ingestConfig.ongoingIngest.title"),
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.NO_OPTION) {
return;
}
}
String optionsDlgTitle = NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.title");
String optionsDlgMessage = NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.msg");
if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
iterator = new AddImageWizardIterator(this);
wizardDescriptor = new WizardDescriptor(iterator);
wizardDescriptor.setTitle(NbBundle.getMessage(this.getClass(), "AddImageAction.wizard.title"));
@ -138,6 +129,7 @@ public final class AddImageAction extends CallableSystemAction implements Presen
dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
Dimension d = dialog.getSize();
dialog.setSize(SIZE);
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
dialog.setVisible(true);
dialog.toFront();
@ -145,6 +137,7 @@ public final class AddImageAction extends CallableSystemAction implements Presen
//add-image process, reverting an image)
runCleanupTasks();
}
}
/**
* Closes the current dialog and wizard, and opens a new one. Used in the
@ -172,12 +165,9 @@ public final class AddImageAction extends CallableSystemAction implements Presen
void runTask(Image newImage);
}
/**
* This method does nothing. Use the "actionPerformed(ActionEvent e)"
* instead of this method.
*/
@Override
public void performAction() {
actionPerformed(null);
}
/**
@ -191,9 +181,9 @@ public final class AddImageAction extends CallableSystemAction implements Presen
}
/**
* Gets the HelpCtx associated with implementing object
* Gets the help context for this action.
*
* @return HelpCtx or HelpCtx.DEFAULT_HELP
* @return The help context.
*/
@Override
public HelpCtx getHelpCtx() {
@ -201,9 +191,9 @@ public final class AddImageAction extends CallableSystemAction implements Presen
}
/**
* Returns the toolbar component of this action
* Gets the toolbar component for this action.
*
* @return component the toolbar button
* @return The toolbar button
*/
@Override
public Component getToolbarPresenter() {
@ -214,7 +204,7 @@ public final class AddImageAction extends CallableSystemAction implements Presen
}
/**
* Set this action to be enabled/disabled
* Enables and disables this action.
*
* @param value whether to enable this action or not
*/
@ -236,8 +226,8 @@ public final class AddImageAction extends CallableSystemAction implements Presen
public void requestFocusButton(String buttonText) {
// get all buttons on this wizard panel
Object[] wizardButtons = wizardDescriptor.getOptions();
for (int i = 0; i < wizardButtons.length; i++) {
JButton tempButton = (JButton) wizardButtons[i];
for (Object wizardButton : wizardButtons) {
JButton tempButton = (JButton) wizardButton;
if (tempButton.getText().equals(buttonText)) {
tempButton.setDefaultCapable(true);
tempButton.requestFocus();
@ -254,8 +244,6 @@ public final class AddImageAction extends CallableSystemAction implements Presen
cleanupSupport.fireChange();
}
ChangeSupport cleanupSupport = new ChangeSupport(this);
/**
* Instances of this class implement the cleanup() method to run cleanup
* code when the wizard exits.

View File

@ -26,6 +26,8 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datasourceprocessors.ImageWriter;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.SleuthkitJNI;
@ -207,7 +209,8 @@ class AddImageTask implements Runnable {
errorMessages.add(verificationError);
}
if(! imageWriterPath.isEmpty()){
Case.getCurrentCase().scheduleImageWriterFinish(imageId);
ImageWriter writer = new ImageWriter(imageId);
writer.subscribeToEvents();
}
newDataSources.add(newImage);
} else {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2014 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -30,6 +30,7 @@ import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescriptorPanel;
/**
* The final panel of the add image wizard. It displays a progress bar and
@ -39,7 +40,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgress
* {@link AddImageWizardIngestConfigPanel} (which is a bit weird if you ask m
* -jm)
*/
class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePanel<WizardDescriptor> {
class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
/**
* flag to indicate that the image adding process is finished and this panel
@ -53,7 +54,7 @@ class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePa
private AddImageWizardAddingProgressVisual component;
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
private DSPProgressMonitorImpl dspProgressMonitorImpl = new DSPProgressMonitorImpl();
private final DSPProgressMonitorImpl dspProgressMonitorImpl = new DSPProgressMonitorImpl();
public DSPProgressMonitorImpl getDSPProgressMonitorImpl() {
return dspProgressMonitorImpl;
@ -192,7 +193,7 @@ class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePa
protected final void fireChangeEvent() {
Iterator<ChangeListener> it;
synchronized (listeners) {
it = new HashSet<ChangeListener>(listeners).iterator();
it = new HashSet<>(listeners).iterator();
}
ChangeEvent ev = new ChangeEvent(this);
while (it.hasNext()) {
@ -239,8 +240,4 @@ class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePa
getComponent().showErrors(errorString, critical);
}
@Override
public boolean isFinishPanel() {
return true;
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -33,18 +33,19 @@ import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.openide.windows.WindowManager;
import java.awt.Cursor;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescriptorPanel;
/**
* The "Add Image" wizard panel1 handling the logic of selecting image file(s)
* to add to Case, and pick the time zone.
*/
class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<WizardDescriptor>, PropertyChangeListener {
class AddImageWizardChooseDataSourcePanel extends ShortcutWizardDescriptorPanel implements PropertyChangeListener {
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private AddImageWizardAddingProgressPanel progressPanel;
private final AddImageWizardAddingProgressPanel progressPanel;
private AddImageWizardChooseDataSourceVisual component;
private boolean isNextEnable = false;
private static final String PROP_LASTDATASOURCE_PATH = "LBL_LastDataSource_PATH"; //NON-NLS
@ -122,7 +123,7 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
isNextEnable = isEnabled;
fireChangeEvent();
}
private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
/**
* Adds a listener to changes of the panel's validity.
@ -155,7 +156,7 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
protected final void fireChangeEvent() {
Iterator<ChangeListener> it;
synchronized (listeners) {
it = new HashSet<ChangeListener>(listeners).iterator();
it = new HashSet<>(listeners).iterator();
}
ChangeEvent ev = new ChangeEvent(this);
while (it.hasNext()) {
@ -218,8 +219,6 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
*/
@Override
public void storeSettings(WizardDescriptor settings) {
return;
}
/**

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2015 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -32,13 +32,17 @@ import javax.swing.SwingUtilities;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.IngestProfileSelectionWizardPanel;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescriptorPanel;
/**
* second panel of add image wizard, allows user to configure ingest modules.
@ -46,20 +50,19 @@ import org.sleuthkit.autopsy.ingest.IngestManager;
* TODO: review this for dead code. think about moving logic of adding image to
* 3rd panel( {@link AddImageWizardAddingProgressPanel}) separate class -jm
*/
class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDescriptor> {
private final IngestJobSettingsPanel ingestJobSettingsPanel;
class AddImageWizardIngestConfigPanel extends ShortcutWizardDescriptorPanel {
@Messages("AddImageWizardIngestConfigPanel.name.text=Configure Ingest Modules")
private IngestJobSettingsPanel ingestJobSettingsPanel;
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private Component component = null;
private String lastProfileUsed = AddImageWizardIngestConfigPanel.class.getCanonicalName();
private final List<Content> newContents = Collections.synchronizedList(new ArrayList<Content>());
private boolean ingested = false;
private boolean readyToIngest = false;
// task that will clean up the created database file if the wizard is cancelled before it finishes
private AddImageAction.CleanupTask cleanupTask;
@ -75,10 +78,12 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
this.addImageAction = action;
this.progressPanel = proPanel;
this.dataSourcePanel = dsPanel;
IngestJobSettings ingestJobSettings = new IngestJobSettings(AddImageWizardIngestConfigPanel.class.getCanonicalName());
showWarnings(ingestJobSettings);
//When this panel is viewed by the user it will always be displaying the
//IngestJobSettingsPanel with the AddImageWizardIngestConfigPanel.class.getCanonicalName();
this.ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings);
}
/**
@ -93,6 +98,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
public Component getComponent() {
if (component == null) {
component = new AddImageWizardIngestConfigVisual(this.ingestJobSettingsPanel);
component.setName(Bundle.AddImageWizardIngestConfigPanel_name_text());
}
return component;
}
@ -166,12 +172,10 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
settings.setOptions(new Object[]{WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, WizardDescriptor.FINISH_OPTION, cancel});
cleanupTask = null;
readyToIngest = false;
newContents.clear();
// Start processing the data source by handing it off to the selected DSP,
// so it gets going in the background while the user is still picking the Ingest modules
startDataSourceProcessing(settings);
startDataSourceProcessing();
}
/**
@ -185,7 +189,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
*/
@Override
public void storeSettings(WizardDescriptor settings) {
IngestJobSettings ingestJobSettings = this.ingestJobSettingsPanel.getSettings();
IngestJobSettings ingestJobSettings = ingestJobSettingsPanel.getSettings();
ingestJobSettings.save();
showWarnings(ingestJobSettings);
@ -205,6 +209,28 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
}
}
/**
* Loads the proper settings for this panel to use the previously selected
* Ingest profile when this panel would be skipped due to a profile being
* chosen.
*/
@Override
public void processThisPanelBeforeSkipped() {
if (!(ModuleSettings.getConfigSetting(IngestProfileSelectionWizardPanel.getLastProfilePropertiesFile(), AddImageWizardIterator.getPropLastprofileName()) == null)
&& !ModuleSettings.getConfigSetting(IngestProfileSelectionWizardPanel.getLastProfilePropertiesFile(), AddImageWizardIterator.getPropLastprofileName()).isEmpty()) {
lastProfileUsed = ModuleSettings.getConfigSetting(IngestProfileSelectionWizardPanel.getLastProfilePropertiesFile(), AddImageWizardIterator.getPropLastprofileName());
}
//Because this panel kicks off ingest during the wizard we need to
//swap out the ingestJobSettings for the ones of the chosen profile before
//we start processing
IngestJobSettings ingestJobSettings = new IngestJobSettings(lastProfileUsed);
ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings);
showWarnings(ingestJobSettings);
component = new AddImageWizardIngestConfigVisual(this.ingestJobSettingsPanel);
readyToIngest = true;
startDataSourceProcessing();
}
/**
* Start ingest after verifying we have a new image, we are ready to ingest,
* and we haven't already ingested.
@ -221,7 +247,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
* Starts the Data source processing by kicking off the selected
* DataSourceProcessor
*/
private void startDataSourceProcessing(WizardDescriptor settings) {
private void startDataSourceProcessing() {
final UUID dataSourceId = UUID.randomUUID();
// Add a cleanup task to interrupt the background process if the

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,6 +26,9 @@ import javax.swing.JComponent;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.ingest.IngestProfiles;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.IngestProfileSelectionWizardPanel;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescriptorPanel;
/**
* The iterator class for the "Add Image" wizard panel. This class is used to
@ -34,8 +37,10 @@ import org.openide.util.NbBundle;
class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescriptor> {
private int index = 0;
private List<WizardDescriptor.Panel<WizardDescriptor>> panels;
private AddImageAction action;
private List<ShortcutWizardDescriptorPanel> panels;
private final AddImageAction action;
private int progressPanelIndex;
private final static String PROP_LASTPROFILE_NAME = "AIW_LASTPROFILE_NAME"; //NON-NLS
AddImageWizardIterator(AddImageAction action) {
this.action = action;
@ -45,19 +50,22 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
* Initialize panels representing individual wizard's steps and sets various
* properties for them influencing wizard appearance.
*/
private List<WizardDescriptor.Panel<WizardDescriptor>> getPanels() {
private List<ShortcutWizardDescriptorPanel> getPanels() {
if (panels == null) {
panels = new ArrayList<WizardDescriptor.Panel<WizardDescriptor>>();
panels = new ArrayList<>();
AddImageWizardAddingProgressPanel progressPanel = new AddImageWizardAddingProgressPanel();
AddImageWizardChooseDataSourcePanel dsPanel = new AddImageWizardChooseDataSourcePanel(progressPanel);
AddImageWizardIngestConfigPanel ingestConfigPanel = new AddImageWizardIngestConfigPanel(dsPanel, action, progressPanel);
panels.add(dsPanel);
List<IngestProfiles.IngestProfile> profiles = IngestProfiles.getIngestProfiles();
if (!profiles.isEmpty()) {
panels.add(new IngestProfileSelectionWizardPanel(AddImageWizardIngestConfigPanel.class.getCanonicalName(), getPropLastprofileName()));
}
panels.add(ingestConfigPanel);
panels.add(progressPanel);
progressPanelIndex = panels.indexOf(progressPanel); //Doing programatically because number of panels is variable
String[] steps = new String[panels.size()];
for (int i = 0; i < panels.size(); i++) {
Component c = panels.get(i).getComponent();
@ -66,7 +74,7 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
if (c instanceof JComponent) { // assume Swing components
JComponent jc = (JComponent) c;
// Sets step number of a component
jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i));
jc.putClientProperty("WizardPanel_contentSelectedIndex", i);
// Sets steps names for a panel
jc.putClientProperty("WizardPanel_contentData", steps);
// Turn on subtitle creation on each step
@ -91,13 +99,30 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
return index;
}
/**
* Gets the name of the property which stores the name of the last profile
* used by the Add Image Wizard.
*
* @return the PROP_LASTPROFILE_NAME
*/
static String getPropLastprofileName() {
return PROP_LASTPROFILE_NAME;
}
/**
* @return the PROP_LASTPROFILE_NAME
*/
static String getPROP_LASTPROFILE_NAME() {
return PROP_LASTPROFILE_NAME;
}
/**
* Gets the current panel.
*
* @return panel the current panel
*/
@Override
public WizardDescriptor.Panel<WizardDescriptor> current() {
public ShortcutWizardDescriptorPanel current() {
if (panels != null) {
return panels.get(index);
} else {
@ -146,7 +171,14 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
if (!hasNext()) {
throw new NoSuchElementException();
}
boolean panelEnablesSkipping = current().panelEnablesSkipping();
boolean skipNextPanel = current().skipNextPanel();
index++;
if (panelEnablesSkipping && skipNextPanel) {
current().processThisPanelBeforeSkipped();
nextPanel();
}
}
/**
@ -158,7 +190,7 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
if (!hasPrevious()) {
throw new NoSuchElementException();
}
if (index == 2) {
if (index == progressPanelIndex) {
index--;
}
index--;

View File

@ -15,12 +15,6 @@ NewCaseVisualPanel1.caseNameTextField.text_1=
NewCaseVisualPanel1.jLabel2.text_1=Case data will be stored in the following directory:
NewCaseVisualPanel1.caseParentDirTextField.text=
NewCaseVisualPanel1.caseDirTextField.text_1=
CasePropertiesForm.caseDirLabel.text=Case Directory:
CasePropertiesForm.crDateLabel.text=Created Date:
CasePropertiesForm.caseNameLabel.text=Case Name:
CasePropertiesForm.caseNameTextField.text=
CasePropertiesForm.updateCaseNameButton.text=Update Name
CasePropertiesForm.deleteCaseButton.text=Delete Case
CueBannerPanel.autopsyLogo.text=
CueBannerPanel.createNewLabel.text=Create New Case
CueBannerPanel.openLabel.text=Open Existing Case
@ -31,8 +25,6 @@ CueBannerPanel.openCaseButton.text=
CueBannerPanel.openRecentButton.text=
OpenRecentCasePanel.cancelButton.text=Cancel
OpenRecentCasePanel.jLabel1.text=Recent Cases
CasePropertiesForm.caseNumberLabel.text=Case Number:
CasePropertiesForm.examinerLabel.text=Examiner:
NewCaseVisualPanel2.caseNumberTextField.text=
NewCaseVisualPanel2.examinerLabel.text=Examiner:
NewCaseVisualPanel2.caseNumberLabel.text=Case Number:
@ -102,12 +94,9 @@ AddImageWizardIngestConfigVisual.getName.text=Configure Ingest Modules
AddImageWizardIterator.stepXofN=Step {0} of {1}
AddLocalFilesTask.localFileAdd.progress.text=Adding\: {0}/{1}
Case.getCurCase.exception.noneOpen=Cannot get the current case; there is no case open\!
Case.create.exception.msg=Error creating a case\: {0} in dir {1}
Case.databaseConnectionInfo.error.msg=Error accessing database server connection info. See Tools, Options, Multi-user.
Case.open.exception.blankCase.msg=Case name is blank.
Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the database with the following path has been made\:\n {0}
Case.open.msgDlg.updated.title=Case Database Schema Update
Case.open.exception.checkFile.msg=Case file must have {0} extension.
Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-user.
Case.checkImgExist.confDlg.doesntExist.msg={0} has detected that one of the images associated with \n\
this case are missing. Would you like to search for them now?\n\
@ -117,9 +106,6 @@ Please note that you will still be able to browse directories and generate repor
if you choose No, but you will not be able to view file content or run the ingest process.
Case.checkImgExist.confDlg.doesntExist.title=Missing Image
Case.addImg.exception.msg=Error adding image to the case
Case.closeCase.exception.msg=Error while trying to close the current case.
Case.deleteCase.exception.msg=Error deleting the case dir\: {0}
Case.deleteCase.exception.msg2=Error deleting the case dir\: {0}
Case.updateCaseName.exception.msg=Error while trying to update the case name.
Case.updateExaminer.exception.msg=Error while trying to update the examiner.
Case.updateCaseNum.exception.msg=Error while trying to update the case number.
@ -137,7 +123,6 @@ Case.GetCaseTypeGivenPath.Failure=Unable to get case type
Case.metaDataFileCorrupt.exception.msg=The case metadata file (.aut) is corrupted.
Case.deleteReports.deleteFromDiskException.log.msg=Unable to delete the report from the disk.
Case.deleteReports.deleteFromDiskException.msg=Unable to delete the report {0} from the disk.\nYou may manually delete it from {1}
Case.exception.errorLocking=Unable to open case being updated by another user.
CaseDeleteAction.closeConfMsg.text=Are you sure want to close and delete this case? \n\
Case Name\: {0}\n\
Case Directory\: {1}
@ -229,8 +214,6 @@ NewCaseVisualPanel1.caseParentDirWarningLabel.text=
NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-user
NewCaseVisualPanel1.singleUserCaseRadioButton.text=Single-user
NewCaseVisualPanel1.caseTypeLabel.text=Case Type:
CasePropertiesForm.lbDbType.text=Case Type:
CasePropertiesForm.lbDbName.text=Database Name:
SingleUserCaseConverter.BadDatabaseFileName=Database file does not exist!
SingleUserCaseConverter.AlreadyMultiUser=Case is already multi-user!
SingleUserCaseConverter.NonUniqueDatabaseName=Database name not unique.
@ -250,3 +233,13 @@ LocalDiskPanel.imageWriterErrorLabel.text=Error Label
LocalDiskPanel.jLabel1.text=Note that at least one ingest module must be run to create a complete copy
LocalDiskPanel.pathTextField.text=
LocalDiskPanel.browseButton.text=Browse
CasePropertiesPanel.updateCaseNameButton.text=Update Name
CasePropertiesPanel.caseNameTextField.text=
CasePropertiesPanel.caseDirLabel.text=Case Directory:
CasePropertiesPanel.crDateLabel.text=Created Date:
CasePropertiesPanel.caseNameLabel.text=Case Name:
CasePropertiesPanel.lbDbName.text=Database Name:
CasePropertiesPanel.lbDbType.text=Case Type:
CasePropertiesPanel.examinerLabel.text=Examiner:
CasePropertiesPanel.caseNumberLabel.text=Case Number:
CasePropertiesPanel.deleteCaseButton.text=Delete Case

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_CaseCloseAct=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b
CTL_CaseNewAction=\u65b0\u898f\u30b1\u30fc\u30b9...
@ -12,19 +11,12 @@ NewCaseVisualPanel1.caseNameLabel.text_1=\u30b1\u30fc\u30b9\u540d\uff1a
NewCaseVisualPanel1.caseDirLabel.text=\u30d9\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\uff1a
NewCaseVisualPanel1.caseDirBrowseButton.text=\u95b2\u89a7
NewCaseVisualPanel1.jLabel2.text_1=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u306f\u6b21\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306b\u4fdd\u5b58\u3055\u308c\u307e\u3059\uff1a
CasePropertiesForm.caseDirLabel.text=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\uff1a
CasePropertiesForm.crDateLabel.text=\u4f5c\u6210\u65e5\uff1a
CasePropertiesForm.caseNameLabel.text=\u30b1\u30fc\u30b9\u540d\uff1a
CasePropertiesForm.updateCaseNameButton.text=\u66f4\u65b0
CasePropertiesForm.deleteCaseButton.text=\u30b1\u30fc\u30b9\u3092\u524a\u9664
CueBannerPanel.createNewLabel.text=\u65b0\u898f\u30b1\u30fc\u30b9\u3092\u4f5c\u6210
CueBannerPanel.openLabel.text=\u65e2\u5b58\u30b1\u30fc\u30b9\u3092\u958b\u304f
CueBannerPanel.closeButton.text=\u9589\u3058\u308b
CueBannerPanel.openRecentLabel.text=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f
OpenRecentCasePanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb
OpenRecentCasePanel.jLabel1.text=\u6700\u8fd1\u958b\u3044\u305f\u30d5\u30a1\u30a4\u30eb
CasePropertiesForm.caseNumberLabel.text=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a
CasePropertiesForm.examinerLabel.text=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a
NewCaseVisualPanel2.examinerLabel.text=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a
NewCaseVisualPanel2.caseNumberLabel.text=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a
NewCaseVisualPanel2.optionalLabel.text=\u30aa\u30d7\u30b7\u30e7\u30ca\u30eb\uff1a\u30b1\u30fc\u30b9\u756a\u53f7\u304a\u3088\u3073\u8abf\u67fb\u62c5\u5f53\u8005\u3092\u8a2d\u5b9a
@ -80,21 +72,15 @@ AddImageWizardIngestConfigVisual.getName.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30
AddImageWizardIterator.stepXofN=\u30b9\u30c6\u30c3\u30d7{0}\uff0f{1}
AddLocalFilesTask.localFileAdd.progress.text=\u8ffd\u52a0\u4e2d\uff1a{0}/{1}
Case.getCurCase.exception.noneOpen=\u4f5c\u696d\u4e2d\u306e\u30b1\u30fc\u30b9\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\uff1b\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\uff01
Case.create.exception.msg=\u30b1\u30fc\u30b9\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{1}\u306e{0}
Case.open.exception.blankCase.msg=\u30b1\u30fc\u30b9\u540d\u304c\u7a7a\u767d\u3067\u3059\u3002
Case.open.msgDlg.updated.msg=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002\n\u6b21\u306e\u30d1\u30b9\u3092\u6301\u3064\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30b3\u30d4\u30fc\u304c\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\uff1a\n\
{0}
Case.open.msgDlg.updated.title=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0
Case.open.exception.checkFile.msg=\u30b1\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u306f{0}\u62e1\u5f35\u5b50\u304c\u5fc5\u8981\u3067\u3059\u3002
Case.checkImgExist.confDlg.doesntExist.msg={0} \u304c\u3053\u306e\u30b1\u30fc\u30b9\u306b\u95a2\u9023\u3059\u308b\u30a4\u30e1\u30fc\u30b8\u306e\u3046\u3061\uff11\u3064\u304c\u6b20\u843d\u3057\u3066\u3044\u308b\u306e\u3092\u691c\u51fa\u3057\u307e\u3057\u305f\u3002\u305d\u308c\u3092\u4eca\u304b\u3089\u691c\u7d22\u3057\u307e\u3059\u304b\uff1f\n\n\
\u4ee5\u524d\u3001\u30a4\u30e1\u30fc\u30b8\u306f\u6b21\u306b\u3042\u308a\u307e\u3057\u305f\uff1a\n\
{1}\n\
\u3044\u3044\u3048\u3092\u9078\u629e\u3057\u3066\u3082\u3001\u4eca\u5f8c\u3082\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u95b2\u89a7\u3057\u3001\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u304c\u3067\u304d\u307e\u3059\u304c\u3001\n\u30d5\u30a1\u30a4\u30eb\u30b3\u30f3\u30c6\u30f3\u30c4\u306e\u8868\u793a\u307e\u305f\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30d7\u30ed\u30bb\u30b9\u306e\u5b9f\u884c\u304c\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002
Case.checkImgExist.confDlg.doesntExist.title=\u6b20\u843d\u3057\u3066\u3044\u308b\u30a4\u30e1\u30fc\u30b8
Case.addImg.exception.msg=\u30b1\u30fc\u30b9\u306b\u30a4\u30e1\u30fc\u30b8\u3092\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
Case.closeCase.exception.msg=\u4f5c\u696d\u4e2d\u306e\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b\u6700\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
Case.deleteCase.exception.msg=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}
Case.deleteCase.exception.msg2=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}
Case.updateCaseName.exception.msg=\u30b1\u30fc\u30b9\u540d\u3092\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
Case.updateExaminer.exception.msg=\u8abf\u67fb\u62c5\u5f53\u8005\u3092\u66f4\u65b0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
Case.updateCaseNum.exception.msg=\u30b1\u30fc\u30b9\u756a\u53f7\u3092\u66f4\u65b0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
@ -203,8 +189,6 @@ CollaborationMonitor.addingDataSourceStatus.msg={0}\u304c\u30c7\u30fc\u30bf\u30d
CollaborationMonitor.analyzingDataSourceStatus.msg={0}\u304c{1}\u3092\u89e3\u6790\u4e2d
NewCaseVisualPanel1.multiUserCaseRadioButton.text=\u8907\u6570\u30e6\u30fc\u30b6\u30fc
NewCaseVisualPanel1.singleUserCaseRadioButton.text=\u5358\u6570\u30e6\u30fc\u30b6\u30fc
CasePropertiesForm.lbDbType.text=\u30b1\u30fc\u30b9\u30bf\u30a4\u30d7\uff1a
CasePropertiesForm.lbDbName.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\uff1a
SingleUserCaseConverter.BadDatabaseFileName=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u307e\u305b\u3093\uff01
SingleUserCaseConverter.AlreadyMultiUser=\u30b1\u30fc\u30b9\u306f\u65e2\u306b\u8907\u6570\u30e6\u30fc\u30b6\u30fc\u3067\u3059\uff01
SingleUserCaseConverter.NonUniqueDatabaseName=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\u304c\u30e6\u30cb\u30fc\u30af\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
@ -216,3 +200,12 @@ Case_caseType_multiUser=\u8907\u6570\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9
Case_caseType_singleUser=\u5358\u6570\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9
CasePropertiesForm.imagesTable.columnModel.title0=\u30d1\u30b9
CasePropertiesForm.imagesTable.columnModel.title1=\u524a\u9664
CasePropertiesPanel.updateCaseNameButton.text=\u66f4\u65b0
CasePropertiesPanel.caseDirLabel.text=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\uff1a
CasePropertiesPanel.crDateLabel.text=\u4f5c\u6210\u65e5\uff1a
CasePropertiesPanel.caseNameLabel.text=\u30b1\u30fc\u30b9\u540d\uff1a
CasePropertiesPanel.lbDbName.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\uff1a
CasePropertiesPanel.lbDbType.text=\u30b1\u30fc\u30b9\u30bf\u30a4\u30d7\uff1a
CasePropertiesPanel.examinerLabel.text=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a
CasePropertiesPanel.caseNumberLabel.text=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a
CasePropertiesPanel.deleteCaseButton.text=\u30b1\u30fc\u30b9\u3092\u524a\u9664

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2015 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,31 +19,33 @@
package org.sleuthkit.autopsy.casemodule;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.SwingWorker;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
import java.util.logging.Level;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.windows.WindowManager;
import java.awt.Cursor;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
/**
* The action to close the current Case. This class should be disabled on
* creation and it will be enabled on new case creation or case opened.
* The action associated with the Case/Close Case menu item and the Close Case
* toolbar button. It closes the current case and pops up the start up window
* that allows a user to open another case.
*
* This action should only be invoked in the event dispatch thread (EDT).
*/
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.casemodule.CaseCloseAction")
@ActionRegistration(displayName = "#CTL_CaseCloseAct", lazy = false)
@ -51,87 +53,69 @@ import org.openide.awt.ActionRegistration;
@ActionReference(path = "Toolbars/Case", position = 104)})
public final class CaseCloseAction extends CallableSystemAction implements Presenter.Toolbar {
JButton toolbarButton = new JButton();
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(CaseCloseAction.class.getName());
private final JButton toolbarButton = new JButton();
/**
* The constructor for this class
* Constructs the action associated with the Case/Close Case menu item and
* the Close Case toolbar button.
*/
public CaseCloseAction() {
putValue("iconBase", "org/sleuthkit/autopsy/images/close-icon.png"); // put the icon NON-NLS
putValue(Action.NAME, NbBundle.getMessage(CaseCloseAction.class, "CTL_CaseCloseAct")); // put the action Name
// set action of the toolbar button
putValue("iconBase", "org/sleuthkit/autopsy/images/close-icon.png"); //NON-NLS
putValue(Action.NAME, NbBundle.getMessage(CaseCloseAction.class, "CTL_CaseCloseAct")); //NON-NLS
toolbarButton.addActionListener(CaseCloseAction.this::actionPerformed);
this.setEnabled(false);
}
/**
* Closes the current opened case.
* Closes the current case.
*
* @param e the action event for this method
* @param e The action event.
*/
@Override
public void actionPerformed(ActionEvent e) {
// if ingest is ongoing, warn and get confirmaion before opening a different case
if (IngestManager.getInstance().isIngestRunning()) {
// show the confirmation first to close the current case and open the "New Case" wizard panel
String closeCurrentCase = NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning");
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(closeCurrentCase,
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning.title"),
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
descriptor.setValue(NotifyDescriptor.NO_OPTION);
Object res = DialogDisplayer.getDefault().notify(descriptor);
if (res != null && res == DialogDescriptor.YES_OPTION) {
try {
Case.getCurrentCase().closeCase(); // close the current case
} catch (Exception ex) {
Logger.getLogger(NewCaseWizardAction.class.getName()).log(Level.WARNING, "Error closing case.", ex); //NON-NLS
}
} else {
return;
}
}
if (Case.isCaseOpen() == false) {
return;
}
String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
try {
Case result = Case.getCurrentCase();
result.closeCase();
} catch (CaseActionException | IllegalStateException unused) {
// Already logged.
}
Case.closeCurrentCase();
return null;
}
@Override
protected void done() {
try {
get();
} catch (InterruptedException ex) {
logger.log(Level.SEVERE, "Unexpected interrupt closing the current case", ex);
} catch (ExecutionException ex) {
logger.log(Level.SEVERE, "Error closing the current case", ex);
MessageNotifyUtil.Message.error(Bundle.Case_closeException_couldNotCloseCase(ex.getMessage()));
}
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
StartupWindowProvider.getInstance().open();
}
}.execute();
}
/**
* This method does nothing. Use the "actionPerformed(ActionEvent e)"
* instead of this method.
*/
@Override
public void performAction() {
}
/**
* Gets the name of this action. This may be presented as an item in a menu.
* Closes the current case.
*/
@Override
public void performAction() {
actionPerformed(null);
}
/**
* Gets the action name.
*
* @return actionName
* @return The action name.
*/
@Override
public String getName() {
@ -139,9 +123,9 @@ public final class CaseCloseAction extends CallableSystemAction implements Prese
}
/**
* Gets the HelpCtx associated with implementing object
* Gets the help context.
*
* @return HelpCtx or HelpCtx.DEFAULT_HELP
* @return The help context.
*/
@Override
public HelpCtx getHelpCtx() {
@ -149,9 +133,9 @@ public final class CaseCloseAction extends CallableSystemAction implements Prese
}
/**
* Returns the toolbar component of this action
* Returns the toolbar component of this action.
*
* @return component the toolbar button
* @return The toolbar button
*/
@Override
public Component getToolbarPresenter() {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2014 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,138 +19,106 @@
package org.sleuthkit.autopsy.casemodule;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
/**
* The action to delete the current Case. This class should be disabled on
* creation and it will be enabled on new case creation or case opened.
* The action associated with the Delete button of the Case Properties panel. It
* deletes the current case.
*
* This action should only be invoked in the event dispatch thread (EDT).
*/
final class CaseDeleteAction extends CallableSystemAction {
private JPanel caller; // for error handling
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(CaseDeleteAction.class.getName());
/**
* The constructor for this class
*/
public CaseDeleteAction() {
putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction")); // put the action Name
CaseDeleteAction() {
putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction"));
this.setEnabled(false);
}
/**
* Deletes the current opened case.
*
* @param e
*/
@Override
@Messages({
"Case.deleteCaseConfirmationDialog.title=Delete Current Case?",
"Case.deleteCaseConfirmationDialog.message=Are you sure you want to close and delete the current case?",
"Case.deleteCaseFailureMessageBox.title=Failed to Delete Case",
"# {0} - exception message", "Case.deleteCaseFailureMessageBox.message=Error deleting case: {0}",})
public void actionPerformed(ActionEvent e) {
Case currentCase = Case.getCurrentCase();
File caseFolder = new File(currentCase.getCaseDirectory());
String caseName = currentCase.getName();
if (!caseFolder.exists()) {
// throw an error
logger.log(Level.WARNING, "Couldn't delete case.", new Exception("The case directory doesn't exist.")); //NON-NLS
} else {
// show the confirmation first to close the current case and open the "New Case" wizard panel
String closeCurrentCase = NbBundle.getMessage(this.getClass(), "CaseDeleteAction.closeConfMsg.text", caseName, caseFolder.getPath());
NotifyDescriptor d = new NotifyDescriptor.Confirmation(closeCurrentCase,
NbBundle.getMessage(this.getClass(),
"CaseDeleteAction.closeConfMsg.title"),
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
d.setValue(NotifyDescriptor.NO_OPTION);
Object res = DialogDisplayer.getDefault().notify(d);
if (res != null && res == DialogDescriptor.YES_OPTION) {
boolean success = false;
try {
Case.getCurrentCase().deleteCase(caseFolder); // delete the current case
success = true;
} catch (CaseActionException ex) {
logger.log(Level.WARNING, "Could not delete the case folder: " + caseFolder); //NON-NLS
}
Case currentCase = Case.getCurrentCase();
String caseName = currentCase.getName();
String caseDirectory = currentCase.getCaseDirectory();
// show notification whether the case has been deleted or it failed to delete...
if (!success) {
JOptionPane.showMessageDialog(caller,
NbBundle.getMessage(this.getClass(),
"CaseDeleteAction.msgDlg.fileInUse.msg"),
NbBundle.getMessage(this.getClass(),
"CaseDeleteAction.msgDlg.fileInUse.title"),
JOptionPane.ERROR_MESSAGE); // throw an error
} else {
CasePropertiesAction.closeCasePropertiesWindow(); // because the "Delete Case" button is in the "CaseProperties" window, we have to close that window when we delete the case.
JOptionPane.showMessageDialog(caller, NbBundle.getMessage(this.getClass(),
"CaseDeleteAction.msgDlg.caseDelete.msg",
caseName));
}
}
}
}
/**
* This method does nothing. Use the "actionPerformed(ActionEvent e)"
* instead of this method.
/*
* Do a confirmation dialog and close the current case if the user
* confirms he/she wants to proceed.
*/
Object response = DialogDisplayer.getDefault().notify(new NotifyDescriptor(
Bundle.Case_deleteCaseConfirmationDialog_message(),
Bundle.Case_deleteCaseConfirmationDialog_title(),
NotifyDescriptor.YES_NO_OPTION,
NotifyDescriptor.WARNING_MESSAGE,
null,
NotifyDescriptor.NO_OPTION));
if (null != response && DialogDescriptor.YES_OPTION == response) {
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
Case.deleteCurrentCase();
return null;
}
@Override
protected void done() {
try {
get();
} catch (InterruptedException | ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Failed to delete case %s at %s", caseName, caseDirectory), ex);
JOptionPane.showMessageDialog(
null,
Bundle.Case_deleteCaseFailureMessageBox_message(ex.getMessage()),
Bundle.Case_deleteCaseFailureMessageBox_title(),
JOptionPane.ERROR_MESSAGE);
}
/*
* Close the Case Properties dialog that is the parent
* of the Delete button that invokes this action.
*/
CasePropertiesAction.closeCasePropertiesWindow();
}
}.execute();
}
} catch (IllegalStateException ex) {
logger.log(Level.SEVERE, "Case delete action called with no current case", ex);
}
}
@Override
public void performAction() {
// Note: I use the actionPerformed above instead of this method
}
/**
* Gets the name of this action. This may be presented as an item in a menu.
*
* @return actionName
*/
@Override
public String getName() {
return NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction");
}
/**
* Gets the HelpCtx associated with implementing object
*
* @return HelpCtx or HelpCtx.DEFAULT_HELP
*/
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
}

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -54,10 +54,11 @@ public final class CaseMetadata {
private static final String FILE_EXTENSION = ".aut";
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)");
private static final String SCHEMA_VERSION_ONE = "1.0";
private final static String AUTOPSY_CREATED_VERSION_ELEMENT_NAME = "AutopsyCreatedVersion"; //NON-NLS
private static final String SCHEMA_VERSION_TWO = "2.0";
private final static String AUTOPSY_VERSION_ELEMENT_NAME = "AutopsyCreatedVersion"; //NON-NLS
private final static String CASE_DATABASE_NAME_ELEMENT_NAME = "DatabaseName"; //NON-NLS
private final static String TEXT_INDEX_NAME_ELEMENT = "TextIndexName"; //NON-NLS
private static final String CURRENT_SCHEMA_VERSION = "2.0";
private static final String CURRENT_SCHEMA_VERSION = "3.0";
private final static String ROOT_ELEMENT_NAME = "AutopsyCase"; //NON-NLS
private final static String SCHEMA_VERSION_ELEMENT_NAME = "SchemaVersion"; //NON-NLS
private final static String CREATED_DATE_ELEMENT_NAME = "CreatedDate"; //NON-NLS
@ -66,6 +67,7 @@ public final class CaseMetadata {
private final static String AUTOPSY_SAVED_BY_ELEMENT_NAME = "SavedByAutopsyVersion"; //NON-NLS
private final static String CASE_ELEMENT_NAME = "Case"; //NON-NLS
private final static String CASE_NAME_ELEMENT_NAME = "Name"; //NON-NLS
private final static String CASE_DISPLAY_NAME_ELEMENT_NAME = "DisplayName"; //NON-NLS
private final static String CASE_NUMBER_ELEMENT_NAME = "Number"; //NON-NLS
private final static String EXAMINER_ELEMENT_NAME = "Examiner"; //NON-NLS
private final static String CASE_TYPE_ELEMENT_NAME = "CaseType"; //NON-NLS
@ -74,9 +76,10 @@ public final class CaseMetadata {
private final Path metadataFilePath;
private Case.CaseType caseType;
private String caseName;
private String caseDisplayName;
private String caseNumber;
private String examiner;
private String caseDatabase;
private String caseDatabaseName;
private String textIndexName;
private String createdDate;
private String createdByVersion;
@ -96,25 +99,26 @@ public final class CaseMetadata {
*
* @param caseDirectory The case directory.
* @param caseType The type of case.
* @param caseName The name of the case.
* @param caseName The immutable name of the case.
* @param caseDisplayName The display name of the case, can be changed by a
* user.
* @param caseNumber The case number.
* @param examiner The name of the case examiner.
* @param caseDatabase For a single-user case, the full path to the
* case database file. For a multi-user case, the
* case database name.
* @param caseTextIndexName The text index name.
* @param caseDatabase For a single-user case, the full path to the case
* database file. For a multi-user case, the case
* database name.
*
* @throws CaseMetadataException If the new case metadata file cannot be
* created.
*/
CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseNumber, String examiner, String caseDatabase, String caseTextIndexName) throws CaseMetadataException {
CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseDisplayName, String caseNumber, String examiner, String caseDatabase) throws CaseMetadataException {
metadataFilePath = Paths.get(caseDirectory, caseName + FILE_EXTENSION);
this.caseType = caseType;
this.caseName = caseName;
this.caseDisplayName = caseDisplayName;
this.caseNumber = caseNumber;
this.examiner = examiner;
this.caseDatabase = caseDatabase;
this.textIndexName = caseTextIndexName;
this.caseDatabaseName = caseDatabase;
createdByVersion = Version.getVersion();
createdDate = CaseMetadata.DATE_FORMAT.format(new Date());
writeToFile();
@ -162,7 +166,7 @@ public final class CaseMetadata {
}
/**
* Gets the case display name.
* Gets the immutable case name, set at case creation.
*
* @return The case display name.
*/
@ -170,19 +174,28 @@ public final class CaseMetadata {
return caseName;
}
/**
* Gets the case display name.
*
* @return The case display name.
*/
public String getCaseDisplayName() {
return this.caseDisplayName;
}
/**
* Sets the case display name. This does not change the name of the case
* directory, the case database, or the text index name.
*
* @param caseName A case display name.
*/
void setCaseName(String caseName) throws CaseMetadataException {
void setCaseDisplayName(String caseName) throws CaseMetadataException {
String oldCaseName = caseName;
this.caseName = caseName;
this.caseDisplayName = caseName;
try {
writeToFile();
} catch (CaseMetadataException ex) {
this.caseName = oldCaseName;
this.caseDisplayName = oldCaseName;
throw ex;
}
}
@ -206,31 +219,27 @@ public final class CaseMetadata {
}
/**
* Gets the name of the case case database.
* Gets the name of the case database.
*
* @return The case database name.
*/
public String getCaseDatabaseName() {
if (caseType == Case.CaseType.MULTI_USER_CASE) {
return caseDatabase;
} else {
return Paths.get(caseDatabase).getFileName().toString();
}
return caseDatabaseName;
}
/**
* Gets the full path to the case database file if the case is a single-user
* case.
* Sets the text index name.
*
* @return The full path to the case database file for a single-user case.
*
* @throws UnsupportedOperationException If called for a multi-user case.
* @param caseTextIndexName The text index name.
*/
public String getCaseDatabasePath() throws UnsupportedOperationException {
if (caseType == Case.CaseType.SINGLE_USER_CASE) {
return caseDatabase;
} else {
throw new UnsupportedOperationException();
void setTextIndexName(String caseTextIndexName) throws CaseMetadataException {
String oldIndexName = caseTextIndexName;
this.textIndexName = caseTextIndexName;
try {
writeToFile();
} catch (CaseMetadataException ex) {
this.textIndexName = oldIndexName;
throw ex;
}
}
@ -355,10 +364,11 @@ public final class CaseMetadata {
* Create the children of the case element.
*/
createChildElement(doc, caseElement, CASE_NAME_ELEMENT_NAME, caseName);
createChildElement(doc, caseElement, CASE_DISPLAY_NAME_ELEMENT_NAME, caseDisplayName);
createChildElement(doc, caseElement, CASE_NUMBER_ELEMENT_NAME, caseNumber);
createChildElement(doc, caseElement, EXAMINER_ELEMENT_NAME, examiner);
createChildElement(doc, caseElement, CASE_TYPE_ELEMENT_NAME, caseType.toString());
createChildElement(doc, caseElement, CASE_DATABASE_ELEMENT_NAME, caseDatabase);
createChildElement(doc, caseElement, CASE_DATABASE_ELEMENT_NAME, caseDatabaseName);
createChildElement(doc, caseElement, TEXT_INDEX_ELEMENT, textIndexName);
}
@ -402,7 +412,7 @@ public final class CaseMetadata {
String schemaVersion = getElementTextContent(rootElement, SCHEMA_VERSION_ELEMENT_NAME, true);
this.createdDate = getElementTextContent(rootElement, CREATED_DATE_ELEMENT_NAME, true);
if (schemaVersion.equals(SCHEMA_VERSION_ONE)) {
this.createdByVersion = getElementTextContent(rootElement, AUTOPSY_CREATED_VERSION_ELEMENT_NAME, true);
this.createdByVersion = getElementTextContent(rootElement, AUTOPSY_VERSION_ELEMENT_NAME, true);
} else {
this.createdByVersion = getElementTextContent(rootElement, AUTOPSY_CREATED_BY_ELEMENT_NAME, true);
}
@ -416,6 +426,11 @@ public final class CaseMetadata {
}
Element caseElement = (Element) caseElements.item(0);
this.caseName = getElementTextContent(caseElement, CASE_NAME_ELEMENT_NAME, true);
if (schemaVersion.equals(SCHEMA_VERSION_ONE) || schemaVersion.equals(SCHEMA_VERSION_TWO)) {
this.caseDisplayName = caseName;
} else {
this.caseDisplayName = getElementTextContent(caseElement, CASE_DISPLAY_NAME_ELEMENT_NAME, true);
}
this.caseNumber = getElementTextContent(caseElement, CASE_NUMBER_ELEMENT_NAME, false);
this.examiner = getElementTextContent(caseElement, EXAMINER_ELEMENT_NAME, false);
this.caseType = Case.CaseType.fromString(getElementTextContent(caseElement, CASE_TYPE_ELEMENT_NAME, true));
@ -423,18 +438,21 @@ public final class CaseMetadata {
throw new CaseMetadataException("Case metadata file corrupted");
}
if (schemaVersion.equals(SCHEMA_VERSION_ONE)) {
this.caseDatabase = getElementTextContent(caseElement, CASE_DATABASE_NAME_ELEMENT_NAME, true);
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_NAME_ELEMENT_NAME, true);
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_NAME_ELEMENT, true);
} else {
this.caseDatabase = getElementTextContent(caseElement, CASE_DATABASE_ELEMENT_NAME, true);
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, true);
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_ELEMENT_NAME, true);
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false);
}
/*
* Update the file to the current schema, if necessary.
* Fix up the case database name due to a bug that for a time caused
* the absolute paths of single-user case databases to be stored.
*/
if (!schemaVersion.equals(CURRENT_SCHEMA_VERSION)) {
writeToFile();
Path possibleAbsoluteCaseDbPath = Paths.get(this.caseDatabaseName);
if (possibleAbsoluteCaseDbPath.getNameCount() > 1) {
Path caseDirectoryPath = Paths.get(getCaseDirectory());
this.caseDatabaseName = caseDirectoryPath.relativize(possibleAbsoluteCaseDbPath).toString();
}
} catch (ParserConfigurationException | SAXException | IOException ex) {
@ -483,4 +501,22 @@ public final class CaseMetadata {
}
}
/**
* Gets the full path to the case database file if the case is a single-user
* case.
*
* @return The full path to the case database file for a single-user case.
*
* @throws UnsupportedOperationException If called for a multi-user case.
* @deprecated
*/
@Deprecated
public String getCaseDatabasePath() throws UnsupportedOperationException {
if (Case.CaseType.SINGLE_USER_CASE == caseType) {
return Paths.get(getCaseDirectory(), caseDatabaseName).toString();
} else {
throw new UnsupportedOperationException();
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2014 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,27 +26,25 @@ import org.openide.util.actions.SystemAction;
import org.openide.util.lookup.ServiceProvider;
/**
* The action to create a new case. This action class is always enabled.
* The action associated with the Case/New Case menu item and the Create New
* Case button of the start up window that allows a user to open a case. It
* invokes the New Case wizard.
*
* @author jantonius
* This action should only be invoked in the event dispatch thread (EDT).
*/
@ServiceProvider(service = CaseNewActionInterface.class)
public final class CaseNewAction extends CallableSystemAction implements CaseNewActionInterface {
private NewCaseWizardAction wizard = SystemAction.get(NewCaseWizardAction.class);
private static final long serialVersionUID = 1L;
/**
* Calls the "New Case" wizard panel action.
*
* @param e
*/
@Override
public void actionPerformed(ActionEvent e) {
wizard.performAction();
SystemAction.get(NewCaseWizardAction.class).performAction();
}
@Override
public void performAction() {
actionPerformed(null);
}
@Override

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -22,39 +22,45 @@ import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.lookup.ServiceProvider;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.Version;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.sleuthkit.autopsy.coreutils.Logger;
import java.util.logging.Level;
import org.openide.util.HelpCtx;
import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.ingest.IngestManager;
/**
* An action that opens an existing case.
* The action associated with the Case/Open Case menu item via the layer.xml
* file, a toolbar button, and the Create New Case button of the start up window
* that allows a user to open a case. It opens an existing case.
*
* This action should only be invoked in the event dispatch thread (EDT).
*/
@ServiceProvider(service = CaseOpenAction.class)
public final class CaseOpenAction extends CallableSystemAction implements ActionListener {
private static final Logger logger = Logger.getLogger(CaseOpenAction.class.getName());
private static final String PROP_BASECASE = "LBL_BaseCase_PATH"; //NON-NLS
private static final long serialVersionUID = 1L;
private static final String PROP_BASECASE = "LBL_BaseCase_PATH"; //NON-NLS
private static final Logger logger = Logger.getLogger(CaseOpenAction.class.getName());
private final JFileChooser fileChooser = new JFileChooser();
private final FileFilter caseMetadataFileFilter;
/**
* Constructs an action that opens an existing case.
* Constructs the action associated with the Case/Open Case menu item via
* the layer.xml file, a toolbar button, and the Create New Case button of
* the start up window that allows a user to open a case. It opens an
* existing case.
*
*/
public CaseOpenAction() {
caseMetadataFileFilter = new FileNameExtensionFilter(NbBundle.getMessage(CaseOpenAction.class, "CaseOpenAction.autFilter.title", Version.getName(), CaseMetadata.getFileExtension()), CaseMetadata.getFileExtension().substring(1));
@ -75,37 +81,11 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
*/
@Override
public void actionPerformed(ActionEvent e) {
/*
* If ingest is running, do a dialog to warn the user and confirm the
* intent to close the current case and leave the ingest process
* incomplete.
*/
if (IngestManager.getInstance().isIngestRunning()) {
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning"),
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning.title"),
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
descriptor.setValue(NotifyDescriptor.NO_OPTION);
Object res = DialogDisplayer.getDefault().notify(descriptor);
if (res != null && res == DialogDescriptor.YES_OPTION) {
Case currentCase = null;
try {
currentCase = Case.getCurrentCase();
currentCase.closeCase();
} catch (IllegalStateException ignored) {
/*
* No current case.
*/
} catch (CaseActionException ex) {
logger.log(Level.SEVERE, String.format("Error closing case at %s while ingest was running", (null != currentCase ? currentCase.getCaseDirectory() : "?")), ex); //NON-NLS
}
} else {
return;
}
}
String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
/**
* Pop up a file chooser to allow the user to select a case meta data
* Pop up a file chooser to allow the user to select a case metadata
* file (.aut file).
*/
int retval = fileChooser.showOpenDialog(WindowManager.getDefault().getMainWindow());
@ -116,36 +96,54 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
StartupWindowProvider.getInstance().close();
/*
* Try to open the case associated with the case metadata file the
* user selected.
* Try to open the case associated with the case metadata file
* the user selected.
*/
final String path = fileChooser.getSelectedFile().getPath();
String dirPath = fileChooser.getSelectedFile().getParent();
ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE, dirPath.substring(0, dirPath.lastIndexOf(File.separator)));
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
new Thread(() -> {
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
Case.openAsCurrentCase(path);
return null;
}
@Override
protected void done() {
try {
Case.open(path);
} catch (CaseActionException ex) {
get();
} catch (InterruptedException ex) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
SwingUtilities.invokeLater(() -> {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(),
ex.getMessage(), // Should be user-friendly
ex.getMessage(),
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE);
StartupWindowProvider.getInstance().open();
} catch (ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(),
ex.getCause().getMessage(), //get the message of the wrapped exception
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE);
if (!Case.isCaseOpen()) {
StartupWindowProvider.getInstance().open();
}
});
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}.execute();
}
}).start();
}
}
@Override
public void performAction() {
actionPerformed(null);
}
@Override

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2015 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,34 +18,41 @@
*/
package org.sleuthkit.autopsy.casemodule;
import java.awt.*;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
/**
*
/*
* The panel in the default Autopsy startup window.
*/
public class CueBannerPanel extends javax.swing.JPanel {
final private static String title = NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.title.text");
final private static JFrame frame = new JFrame(title);
final static JDialog recentCasesWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
private static final long serialVersionUID = 1L;
/*
* This is field is static for the sake of the closeOpenRecentCasesWindow
* method.
*/
private static JDialog recentCasesWindow;
// for error handling
private static JPanel caller = new JPanel();
public static void closeOpenRecentCasesWindow() {
if (null != recentCasesWindow) {
recentCasesWindow.setVisible(false);
}
}
public CueBannerPanel() {
initComponents();
refresh();
customizeComponents();
enableComponents();
}
public CueBannerPanel(String welcomeLogo) {
@ -55,7 +62,53 @@ public class CueBannerPanel extends javax.swing.JPanel {
ImageIcon icon = new ImageIcon(cl.getResource(welcomeLogo));
autopsyLogo.setIcon(icon);
}
refresh();
customizeComponents();
enableComponents();
}
public void setCloseButtonActionListener(ActionListener e) {
closeButton.addActionListener(e);
}
public void setCloseButtonText(String text) {
closeButton.setText(text);
}
public void refresh() {
enableComponents();
}
private void customizeComponents() {
recentCasesWindow = new JDialog(
WindowManager.getDefault().getMainWindow(),
NbBundle.getMessage(CueBannerPanel.class, "CueBannerPanel.title.text"),
Dialog.ModalityType.APPLICATION_MODAL);
recentCasesWindow.setSize(new Dimension(750, 400));
recentCasesWindow.getRootPane().registerKeyboardAction(
e -> {
recentCasesWindow.setVisible(false);
},
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
OpenRecentCasePanel recentCasesPanel = OpenRecentCasePanel.getInstance();
recentCasesPanel.setCloseButtonActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
recentCasesWindow.setVisible(false);
}
});
recentCasesWindow.add(recentCasesPanel);
recentCasesWindow.pack();
recentCasesWindow.setResizable(false);
}
private void enableComponents() {
if (RecentCases.getInstance().getTotalRecentCases() == 0) {
openRecentButton.setEnabled(false);
openRecentLabel.setEnabled(false);
} else {
openRecentButton.setEnabled(true);
openRecentLabel.setEnabled(true);
}
}
/**
@ -180,15 +233,6 @@ public class CueBannerPanel extends javax.swing.JPanel {
);
}// </editor-fold>//GEN-END:initComponents
public void refresh() {
if (RecentCases.getInstance().getTotalRecentCases() == 0) {
openRecentButton.setEnabled(false);
openRecentLabel.setEnabled(false);
} else {
openRecentButton.setEnabled(true);
openRecentLabel.setEnabled(true);
}
}
private void newCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newCaseButtonActionPerformed
Lookup.getDefault().lookup(CaseNewActionInterface.class).actionPerformed(evt);
}//GEN-LAST:event_newCaseButtonActionPerformed
@ -198,37 +242,8 @@ public class CueBannerPanel extends javax.swing.JPanel {
}//GEN-LAST:event_openCaseButtonActionPerformed
private void openRecentButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openRecentButtonActionPerformed
// open the recent cases dialog
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
// set the popUp window / JFrame
recentCasesWindow.setSize(750, 400);
int w = recentCasesWindow.getSize().width;
int h = recentCasesWindow.getSize().height;
// set the location of the popUp Window on the center of the screen
recentCasesWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
recentCasesWindow.setLocationRelativeTo(this);
recentCasesWindow.getRootPane().registerKeyboardAction(e -> {
recentCasesWindow.dispose();
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
OpenRecentCasePanel welcomeWindow = OpenRecentCasePanel.getInstance();
// add the command to close the window to the button on the Volume Detail Panel
welcomeWindow.setCloseButtonActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
recentCasesWindow.dispose();
}
});
recentCasesWindow.add(welcomeWindow);
recentCasesWindow.pack();
recentCasesWindow.setResizable(false);
recentCasesWindow.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
recentCasesWindow.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
OpenRecentCasePanel.getInstance(); //refreshes the recent cases table
recentCasesWindow.setVisible(true);
}//GEN-LAST:event_openRecentButtonActionPerformed
@ -244,29 +259,4 @@ public class CueBannerPanel extends javax.swing.JPanel {
private javax.swing.JLabel openRecentLabel;
// End of variables declaration//GEN-END:variables
/**
* Sets the Close button action listener.
*
* @param e the action listener
*/
public void setCloseButtonActionListener(ActionListener e) {
closeButton.addActionListener(e);
}
/**
* Sets the Close button label (default is "Close").
*
* @param text The new label for the button.
*/
public void setCloseButtonText(String text) {
closeButton.setText(text);
}
/**
* Close the open recent cases window.
*/
public static void closeOpenRecentCasesWindow() {
//startupWindow.setVisible(false);
recentCasesWindow.dispose();
}
}

View File

@ -33,7 +33,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgress
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.DataSourceUtils;
import org.sleuthkit.autopsy.corecomponentinterfaces.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
/**
* A image file data source processor that implements the DataSourceProcessor

View File

@ -30,7 +30,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.DriveUtils;
import org.sleuthkit.autopsy.corecomponentinterfaces.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
/**
* A local drive data source processor that implements the DataSourceProcessor

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,31 +19,33 @@
package org.sleuthkit.autopsy.casemodule;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dialog;
import java.io.File;
import java.text.MessageFormat;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import javax.swing.SwingUtilities;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.SystemAction;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JOptionPane;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.openide.windows.WindowManager;
import java.awt.Cursor;
import java.util.concurrent.ExecutionException;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* An action that creates and runs the new case wizard.
* The action associated with the Case/New Case menu item, t toolbar button, and
* the button in the start up window that allows users to open cases action. It
* runs first the New Case wizard, then the Add Data Source wizard.
*
* This action should only be invoked in the event dispatch thread (EDT).
*/
final class NewCaseWizardAction extends CallableSystemAction {
@ -53,39 +55,15 @@ final class NewCaseWizardAction extends CallableSystemAction {
@Override
public void performAction() {
/*
* If ingest is running, do a dialog to warn the user and confirm the
* intent to close the current case and leave the ingest process
* incomplete.
*/
if (IngestManager.getInstance().isIngestRunning()) {
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning"),
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning.title"),
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
descriptor.setValue(NotifyDescriptor.NO_OPTION);
Object res = DialogDisplayer.getDefault().notify(descriptor);
if (res != null && res == DialogDescriptor.YES_OPTION) {
Case currentCase = null;
try {
currentCase = Case.getCurrentCase();
currentCase.closeCase();
} catch (IllegalStateException ignored) {
/*
* No current case.
*/
} catch (CaseActionException ex) {
logger.log(Level.SEVERE, String.format("Error closing case at %s while ingest was running", (null != currentCase ? currentCase.getCaseDirectory() : "?")), ex); //NON-NLS
}
} else {
return;
}
}
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
runNewCaseWizard();
}
}
private void runNewCaseWizard() {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
final WizardDescriptor wizardDescriptor = new WizardDescriptor(getNewCaseWizardPanels());
wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
wizardDescriptor.setTitle(NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.newCase.windowTitle.text"));
@ -101,7 +79,7 @@ final class NewCaseWizardAction extends CallableSystemAction {
final String caseName = (String) wizardDescriptor.getProperty("caseName"); //NON-NLS
String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS
CaseType caseType = CaseType.values()[(int) wizardDescriptor.getProperty("caseType")]; //NON-NLS
Case.create(createdDirectory, caseName, caseNumber, examiner, caseType);
Case.createAsCurrentCase(createdDirectory, caseName, caseNumber, examiner, caseType);
return null;
}
@ -109,26 +87,29 @@ final class NewCaseWizardAction extends CallableSystemAction {
protected void done() {
try {
get();
/*
* Run the Add Data Source wizard by invoking the Add
* Data Source wizard.
*/
AddImageAction addImageAction = SystemAction.get(AddImageAction.class);
addImageAction.actionPerformed(null);
} catch (Exception ex) {
} catch (InterruptedException | ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Error creating case %s", wizardDescriptor.getProperty("caseName")), ex); //NON-NLS
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(),
(ex instanceof ExecutionException ? ex.getCause().getMessage() : ex.getMessage()),
NbBundle.getMessage(this.getClass(), "CaseCreateAction.msgDlg.cantCreateCase.msg"), //NON-NLS
JOptionPane.ERROR_MESSAGE);
StartupWindowProvider.getInstance().close(); // RC: Why close and open?
if (!Case.isCaseOpen()) {
StartupWindowProvider.getInstance().close();
StartupWindowProvider.getInstance().open();
}
});
doFailedCaseCleanup(wizardDescriptor);
} finally {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}.execute();
} else {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
new Thread(() -> {
doFailedCaseCleanup(wizardDescriptor);
}).start();
@ -138,11 +119,8 @@ final class NewCaseWizardAction extends CallableSystemAction {
private void doFailedCaseCleanup(WizardDescriptor wizardDescriptor) {
String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS
if (createdDirectory != null) {
Case.deleteCaseDirectory(new File(createdDirectory));
FileUtil.deleteDir(new File(createdDirectory));
}
SwingUtilities.invokeLater(() -> {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
});
}
/**

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,111 +18,61 @@
*/
package org.sleuthkit.autopsy.casemodule;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import java.awt.Cursor;
import java.util.logging.Level;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
/**
* An action listener that opens a recent case.
* An action listener for a specific case, associated with a Recent Cases menu
* item for the case by a DynamicMenuContent content JMenuItem.
*
* This action should only be invoked in the event dispatch thread (EDT).
*/
class RecentItems implements ActionListener {
private static final Logger logger = Logger.getLogger(RecentItems.class.getName());
private final String caseName;
private final String caseMetaDataFilePath;
/**
* Constructs an action listener that opens a recent case.
* Constructs an action listener for a specific case, associated with a
* Recent Cases menu item for the case by a DynamicMenuContent content
* JMenuItem.
*
* @param caseName The name of the case.
* @param caseMetaDataFilePath The path to the case metadata file.
*/
public RecentItems(String caseName, String caseMetaDataFilePath) {
this.caseName = caseName;
RecentItems(String caseName, String caseMetaDataFilePath) {
this.caseMetaDataFilePath = caseMetaDataFilePath;
}
/**
* Opens the recent case.
* Opens the case associated with the action.
*
* @param e the action event
*/
@Override
public void actionPerformed(ActionEvent e) {
/*
* If ingest is running, do a dialog to warn the user and confirm the
* intent to close the current case and leave the ingest process
* incomplete.
*/
if (IngestManager.getInstance().isIngestRunning()) {
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning"),
NbBundle.getMessage(this.getClass(), "CloseCaseWhileIngesting.Warning.title"),
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
descriptor.setValue(NotifyDescriptor.NO_OPTION);
Object res = DialogDisplayer.getDefault().notify(descriptor);
if (res != null && res == DialogDescriptor.YES_OPTION) {
Case currentCase = null;
try {
currentCase = Case.getCurrentCase();
currentCase.closeCase();
} catch (IllegalStateException ignored) {
/*
* No current case.
*/
} catch (CaseActionException ex) {
logger.log(Level.SEVERE, String.format("Error closing case at %s while ingest was running", (null!= currentCase ? currentCase.getCaseDirectory() : "?")),ex); //NON-NLS
}
} else {
return;
}
}
/*
* Open the case.
*/
if (caseName.equals("") || caseMetaDataFilePath.equals("") || (!new File(caseMetaDataFilePath).exists())) {
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
NbBundle.getMessage(this.getClass(), "RecentItems.openRecentCase.msgDlg.text", caseName),
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"),
JOptionPane.ERROR_MESSAGE);
RecentCases.getInstance().removeRecentCase(caseName, caseMetaDataFilePath);
if (Case.isCaseOpen() == false) {
EventQueue.invokeLater(() -> {
StartupWindowProvider.getInstance().open();
});
}
} else {
SwingUtilities.invokeLater(() -> {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
});
String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
new Thread(() -> {
try {
Case.open(caseMetaDataFilePath);
Case.openAsCurrentCase(caseMetaDataFilePath);
} catch (CaseActionException ex) {
SwingUtilities.invokeLater(() -> {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetaDataFilePath), ex); //NON-NLS
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(),
ex.getMessage(), // Should be user-friendly
ex.getMessage(),
NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE);
if (!Case.isCaseOpen()) {
StartupWindowProvider.getInstance().open();
}
});
}
}).start();

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,25 +19,22 @@
package org.sleuthkit.autopsy.casemodule;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JDialog;
import javax.swing.JFrame;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.openide.windows.WindowManager;
/**
* The default implementation of the Autopsy startup window
* The default implementation of the Autopsy startup window.
*/
@ServiceProvider(service = StartupWindowInterface.class)
public final class StartupWindow extends JDialog implements StartupWindowInterface {
private static StartupWindow instance;
private static final long serialVersionUID = 1L;
private static final String TITLE = NbBundle.getMessage(StartupWindow.class, "StartupWindow.title.text");
private static Dimension DIMENSIONS = new Dimension(750, 400);
private static final Dimension DIMENSIONS = new Dimension(750, 400);
private static CueBannerPanel welcomeWindow;
public StartupWindow() {
@ -45,37 +42,18 @@ public final class StartupWindow extends JDialog implements StartupWindowInterfa
init();
}
/**
* Shows the startup window.
*/
private void init() {
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
// set the popUp window / JFrame
setSize(DIMENSIONS);
int w = this.getSize().width;
int h = this.getSize().height;
// set the location of the popUp Window on the center of the screen
setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
welcomeWindow = new CueBannerPanel();
// add the command to close the window to the button on the Volume Detail Panel
welcomeWindow.setCloseButtonActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
close();
}
});
add(welcomeWindow);
pack();
setResizable(false);
}
@Override
@ -85,9 +63,6 @@ public final class StartupWindow extends JDialog implements StartupWindowInterfa
setVisible(true);
}
/**
* Closes the startup window.
*/
@Override
public void close() {
this.setVisible(false);

View File

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

View File

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

View File

@ -1,21 +1,21 @@
/*
* 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.
*/
* 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.casemodule.services;
import java.beans.PropertyChangeEvent;
@ -31,7 +31,7 @@ import org.openide.util.Lookup;
iconBase = "org/sleuthkit/autopsy/casemodule/services/tag-options-panel-icon.png",
keywords = "#OptionsCategory_TagNames",
keywordsCategory = "CustomTagNames",
position = 8
position = 10
)
public final class TagsOptionsPanelController extends OptionsPanelController {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,129 +18,89 @@
*/
package org.sleuthkit.autopsy.coordinationservice;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.curator.RetryPolicy;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.sleuthkit.autopsy.core.UserPreferences;
import java.io.IOException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.sleuthkit.autopsy.core.UserPreferences;
/**
* A centralized service for maintaining configuration information and providing
* distributed synchronization using a shared hierarchical namespace of nodes.
* A coordination service for maintaining configuration information and
* providing distributed synchronization using a shared hierarchical namespace
* of nodes.
*
* TODO (JIRA 2205): Simple refactoring for general use.
*/
public final class CoordinationService {
/**
* Category nodes are the immediate children of the root node of a shared
* hierarchical namespace managed by the coordination service.
*/
public enum CategoryNode { // RJCTODO: Move this to CoordinationServiceNamespace
CASES("cases"),
MANIFESTS("manifests"),
CONFIG("config"),
RESOURCE("resource");
private final String displayName;
private CategoryNode(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
}
/**
* Exception type thrown by the coordination service.
*/
public final static class CoordinationServiceException extends Exception {
private static final long serialVersionUID = 1L;
private CoordinationServiceException(String message) {
super(message);
}
private CoordinationServiceException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* An opaque encapsulation of a lock for use in distributed synchronization.
* Instances are obtained by calling a get lock method and must be passed to
* a release lock method.
*/
public static class Lock implements AutoCloseable {
/**
* This implementation uses the Curator read/write lock. see
* http://curator.apache.org/curator-recipes/shared-reentrant-read-write-lock.html
*/
private final InterProcessMutex interProcessLock;
private final String nodePath;
private Lock(String nodePath, InterProcessMutex lock) {
this.nodePath = nodePath;
this.interProcessLock = lock;
}
public String getNodePath() {
return nodePath;
}
public void release() throws CoordinationServiceException {
try {
this.interProcessLock.release();
} catch (Exception ex) {
throw new CoordinationServiceException(String.format("Failed to release the lock on %s", nodePath), ex);
}
}
@Override
public void close() throws CoordinationServiceException {
release();
}
}
private static CuratorFramework curator = null;
private static final Map<String, CoordinationService> rootNodesToServices = new HashMap<>();
private final Map<String, String> categoryNodeToPath = new HashMap<>();
private static final int SESSION_TIMEOUT_MILLISECONDS = 300000;
private static final int CONNECTION_TIMEOUT_MILLISECONDS = 300000;
private static final int ZOOKEEPER_SESSION_TIMEOUT_MILLIS = 3000;
private static final int ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS = 15000;
private static final int PORT_OFFSET = 1000;
private static final int PORT_OFFSET = 1000; // When run in Solr, ZooKeeper defaults to Solr port + 1000
private final Map<String, String> categoryNodeToPath = new HashMap<>();
/**
* Gets an instance of the centralized coordination service for a specific
* namespace.
* Determines if ZooKeeper is accessible with the current settings. Closes
* the connection prior to returning.
*
* @return true if a connection was achieved, false otherwise
*
* @throws InterruptedException
* @throws IOException
*/
private static boolean isZooKeeperAccessible() throws InterruptedException, IOException {
boolean result = false;
Object workerThreadWaitNotifyLock = new Object();
int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET;
String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort;
ZooKeeper zooKeeper = new ZooKeeper(connectString, ZOOKEEPER_SESSION_TIMEOUT_MILLIS,
(WatchedEvent event) -> {
synchronized (workerThreadWaitNotifyLock) {
workerThreadWaitNotifyLock.notify();
}
});
synchronized (workerThreadWaitNotifyLock) {
workerThreadWaitNotifyLock.wait(ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS);
}
ZooKeeper.States state = zooKeeper.getState();
if (state == ZooKeeper.States.CONNECTED || state == ZooKeeper.States.CONNECTEDREADONLY) {
result = true;
}
zooKeeper.close();
return result;
}
/**
* Gets a coordination service for a specific namespace.
*
* @param rootNode The name of the root node that defines the namespace.
*
* @return The service for the namespace defined by the root node name.
* @return The coordination service.
*
* @throws CoordinationServiceException If an instaNce of the coordination
* @throws CoordinationServiceException If an instance of the coordination
* service cannot be created.
*/
public static synchronized CoordinationService getInstance(String rootNode) throws CoordinationServiceException {
public static synchronized CoordinationService getServiceForNamespace(String rootNode) throws CoordinationServiceException {
/*
* Connect to ZooKeeper via Curator.
*/
if (null == curator) {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
// When run in Solr, ZooKeeper defaults to Solr port + 1000
int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET;
String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort;
curator = CuratorFrameworkFactory.newClient(connectString, SESSION_TIMEOUT_MILLISECONDS, CONNECTION_TIMEOUT_MILLISECONDS, retryPolicy);
@ -157,7 +117,7 @@ public final class CoordinationService {
CoordinationService service;
try {
service = new CoordinationService(rootNode);
} catch (Exception ex) {
} catch (IOException | InterruptedException | KeeperException | CoordinationServiceException ex) {
curator = null;
throw new CoordinationServiceException("Failed to create coordination service", ex);
}
@ -167,15 +127,18 @@ public final class CoordinationService {
}
/**
* Constructs an instance of the centralized coordination service for a
* specific namespace.
* Constructs an instance of the coordination service for a specific
* namespace.
*
* @param rootNodeName The name of the root node that defines the namespace.
*
* @throws Exception (calls Curator methods that throw Exception instead of
* more specific exceptions)
*/
private CoordinationService(String rootNodeName) throws Exception {
private CoordinationService(String rootNodeName) throws InterruptedException, IOException, KeeperException, CoordinationServiceException {
if (false == isZooKeeperAccessible()) {
throw new Exception("Unable to access ZooKeeper");
throw new CoordinationServiceException("Unable to access ZooKeeper");
}
String rootNode = rootNodeName;
@ -191,6 +154,8 @@ public final class CoordinationService {
if (ex.code() != KeeperException.Code.NODEEXISTS) {
throw ex;
}
} catch (Exception ex) {
throw new CoordinationServiceException("Curator experienced an error", ex);
}
categoryNodeToPath.put(node.getDisplayName(), nodePath);
}
@ -201,6 +166,9 @@ public final class CoordinationService {
* in the namespace managed by this coordination service. Blocks until the
* lock is obtained or the time out expires.
*
* IMPORTANT: The lock needs to be released in the same thread in which it
* is acquired.
*
* @param category The desired category in the namespace.
* @param nodePath The node path to use as the basis for the lock.
* @param timeOut Length of the time out.
@ -236,6 +204,9 @@ public final class CoordinationService {
* in the namespace managed by this coordination service. Returns
* immediately if the lock can not be acquired.
*
* IMPORTANT: The lock needs to be released in the same thread in which it
* is acquired.
*
* @param category The desired category in the namespace.
* @param nodePath The node path to use as the basis for the lock.
*
@ -262,6 +233,9 @@ public final class CoordinationService {
* the namespace managed by this coordination service. Blocks until the lock
* is obtained or the time out expires.
*
* IMPORTANT: The lock needs to be released in the same thread in which it
* is acquired.
*
* @param category The desired category in the namespace.
* @param nodePath The node path to use as the basis for the lock.
* @param timeOut Length of the time out.
@ -297,6 +271,9 @@ public final class CoordinationService {
* the namespace managed by this coordination service. Returns immediately
* if the lock can not be acquired.
*
* IMPORTANT: The lock needs to be released in the same thread in which it
* is acquired.
*
* @param category The desired category in the namespace.
* @param nodePath The node path to use as the basis for the lock.
*
@ -385,35 +362,77 @@ public final class CoordinationService {
}
/**
* Determines if ZooKeeper is accessible with the current settings. Closes
* the connection prior to returning.
*
* @return true if a connection was achieved, false otherwise
* Exception type thrown by the coordination service.
*/
private static boolean isZooKeeperAccessible() {
boolean result = false;
Object workerThreadWaitNotifyLock = new Object();
int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET;
String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort;
public final static class CoordinationServiceException extends Exception {
private static final long serialVersionUID = 1L;
private CoordinationServiceException(String message) {
super(message);
}
private CoordinationServiceException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* An opaque encapsulation of a lock for use in distributed synchronization.
* Instances are obtained by calling a get lock method and must be passed to
* a release lock method.
*/
public static class Lock implements AutoCloseable {
/**
* This implementation uses the Curator read/write lock. see
* http://curator.apache.org/curator-recipes/shared-reentrant-read-write-lock.html
*/
private final InterProcessMutex interProcessLock;
private final String nodePath;
private Lock(String nodePath, InterProcessMutex lock) {
this.nodePath = nodePath;
this.interProcessLock = lock;
}
public String getNodePath() {
return nodePath;
}
public void release() throws CoordinationServiceException {
try {
ZooKeeper zooKeeper = new ZooKeeper(connectString, ZOOKEEPER_SESSION_TIMEOUT_MILLIS,
(WatchedEvent event) -> {
this.interProcessLock.release();
} catch (Exception ex) {
throw new CoordinationServiceException(String.format("Failed to release the lock on %s", nodePath), ex);
}
}
synchronized (workerThreadWaitNotifyLock) {
workerThreadWaitNotifyLock.notify();
@Override
public void close() throws CoordinationServiceException {
release();
}
});
synchronized (workerThreadWaitNotifyLock) {
workerThreadWaitNotifyLock.wait(ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS);
}
ZooKeeper.States state = zooKeeper.getState();
if (state == ZooKeeper.States.CONNECTED || state == ZooKeeper.States.CONNECTEDREADONLY) {
result = true;
/**
* Category nodes are the immediate children of the root node of a shared
* hierarchical namespace managed by a coordination service.
*/
public enum CategoryNode {
CASES("cases"),
MANIFESTS("manifests"),
CONFIG("config"),
RESOURCE("resource");
private final String displayName;
private CategoryNode(String displayName) {
this.displayName = displayName;
}
zooKeeper.close();
} catch (InterruptedException | IOException ignored) {
public String getDisplayName() {
return displayName;
}
return result;
}
}

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2015 Basis Technology Corp.
* Copyright 2013-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -24,46 +24,70 @@ package org.sleuthkit.autopsy.core;
*/
public class RuntimeProperties {
private static boolean coreComponentsActive = true;
private static boolean coreComponentsActiveSet = false;
private static boolean runningWithGUI = true;
private static boolean runningWithGUIFlagHasBeenSet = false;
/**
* Sets or unsets a flag indicating whether or not the core Autopsy UI
* components and user interactions with those components via menus, message
* boxes, NetBeans progress handles, etc., are enabled.
* <p>
* This flag exists as a mechanism to allow use of Autopsy as a platform
* with the core Autopsy user interface disabled, until such time as the
* user interface is made separable and optional.
* Sets or unsets a flag indicating whether or not the application is
* running with a GUI. The flag can only be set once per application
* innvocation.
*
* @param coreComponentsActive True or false.
* @param runningWithGUI True or false.
*
* @throws RuntimePropertiesException if the flag has already been set.
*/
public synchronized static void setCoreComponentsActive(boolean coreComponentsActive) {
if (!coreComponentsActiveSet) {
RuntimeProperties.coreComponentsActive = coreComponentsActive;
coreComponentsActiveSet = true;
public synchronized static void setRunningWithGUI(boolean runningWithGUI) throws RuntimePropertiesException {
if (!runningWithGUIFlagHasBeenSet) {
RuntimeProperties.runningWithGUI = runningWithGUI;
runningWithGUIFlagHasBeenSet = true;
} else {
throw new RuntimePropertiesException("The runningWithGUI flag has already been set and cannot be changed");
}
}
/**
* Gets a flag indicating whether or not the core Autopsy UI components and
* user interactions with those components via menus, message boxes,
* NetBeans progress handles, etc., are enabled.
* <p>
* This flag exists as a mechanism to allow use of Autopsy as a platform
* with the core Autopsy user interface disabled, until such time as the
* user interface is made separable and optional.
* Gets a flag indicating whether or not the application is running with a
* GUI.
*
* @return True or false.
*/
public synchronized static boolean coreComponentsAreActive() {
return coreComponentsActive;
public synchronized static boolean runningWithGUI() {
return runningWithGUI;
}
/**
* Private constructor to prevent creation of instances of this class.
*/
private RuntimeProperties() {
}
/**
* Exception to throw if there is an error setting a runtime property.
*/
public final static class RuntimePropertiesException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructor for an exception to throw if there is an error setting
* a runtime property.
*
* @param message The exception message.
*/
public RuntimePropertiesException(String message) {
super(message);
}
/**
* Constructor for an exception to throw if there is an error setting
* a runtime property.
*
* @param message The exception message.
* @param cause The cause of the error.
*/
public RuntimePropertiesException(String message, Throwable cause) {
super(message, cause);
}
}
}

View File

@ -49,55 +49,6 @@
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Component id="numberOfFileIngestThreadsComboBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="restartRequiredLabel" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabelTimeDisplay" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabelNumThreads" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabelSetProcessTimeOut" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="useLocalTimeRB" min="-2" max="-2" attributes="0"/>
<Component id="useGMTTimeRB" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="jCheckBoxEnableProcTimeout" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jFormattedTextFieldProcTimeOutHrs" min="-2" pref="27" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabelProcessTimeOutUnits" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
<EmptySpace min="-2" pref="213" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabelHideKnownFiles" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabelSelectFile" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="keepCurrentViewerRB" min="-2" max="-2" attributes="0"/>
<Component id="useBestViewerRB" min="-2" max="-2" attributes="0"/>
<Component id="dataSourcesHideKnownCB" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="viewsHideKnownCB" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace min="395" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabelHideSlackFiles" alignment="0" min="-2" max="-2" attributes="0"/>
@ -111,6 +62,30 @@
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabelTimeDisplay" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="useLocalTimeRB" min="-2" max="-2" attributes="0"/>
<Component id="useGMTTimeRB" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Component id="jLabelHideKnownFiles" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabelSelectFile" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="keepCurrentViewerRB" min="-2" max="-2" attributes="0"/>
<Component id="useBestViewerRB" min="-2" max="-2" attributes="0"/>
<Component id="dataSourcesHideKnownCB" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="viewsHideKnownCB" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
@ -142,24 +117,7 @@
<Component id="useLocalTimeRB" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="useGMTTimeRB" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jLabelNumThreads" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="numberOfFileIngestThreadsComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="restartRequiredLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jLabelSetProcessTimeOut" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jCheckBoxEnableProcTimeout" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="jFormattedTextFieldProcTimeOutHrs" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabelProcessTimeOutUnits" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace pref="49" max="32767" attributes="0"/>
<EmptySpace pref="148" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -264,73 +222,6 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="viewsHideKnownCBActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabelNumThreads">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jLabelNumThreads.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="numberOfFileIngestThreadsComboBox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="numberOfFileIngestThreadsComboBoxActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;Integer&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="restartRequiredLabel">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/warning16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.restartRequiredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabelSetProcessTimeOut">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jLabelSetProcessTimeOut.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckBoxEnableProcTimeout">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jCheckBoxEnableProcTimeoutActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabelProcessTimeOutUnits">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JFormattedTextField" name="jFormattedTextFieldProcTimeOutHrs">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jFormattedTextFieldProcTimeOutHrs.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jFormattedTextFieldProcTimeOutHrsActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new JFormattedTextField(NumberFormat.getIntegerInstance());"/>
</AuxValues>
</Component>
<Component class="javax.swing.JCheckBox" name="dataSourcesHideSlackCB">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">

View File

@ -18,13 +18,7 @@
*/
package org.sleuthkit.autopsy.corecomponents;
import java.text.NumberFormat;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFormattedTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.core.UserPreferences;
/**
@ -36,55 +30,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
AutopsyOptionsPanel() {
initComponents();
/*
* Profiling has shown that contention for I/O resources and for the
* case database limits the number of threads that can do meaningful
* work during ingest. If Autopsy was compute-bound, adding more threads
* on machines with enough processors might help, but currently, after
* four threads, performance actually stays flat and then starts to
* degrade.
*/
int availableProcessors = Runtime.getRuntime().availableProcessors();
Integer fileIngestThreadCountChoices[];
int recommendedFileIngestThreadCount;
if (availableProcessors >= 6) {
fileIngestThreadCountChoices = new Integer[]{1, 2, 4};
recommendedFileIngestThreadCount = 4;
} else if (availableProcessors >= 4 && availableProcessors < 6) {
fileIngestThreadCountChoices = new Integer[]{1, 2, 4};
recommendedFileIngestThreadCount = 2;
} else if (availableProcessors >= 2 && availableProcessors < 4) {
fileIngestThreadCountChoices = new Integer[]{1, 2};
recommendedFileIngestThreadCount = 1;
} else {
fileIngestThreadCountChoices = new Integer[]{1};
recommendedFileIngestThreadCount = 1;
}
numberOfFileIngestThreadsComboBox.setModel(new DefaultComboBoxModel<>(fileIngestThreadCountChoices));
restartRequiredLabel.setText(NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.restartRequiredLabel.text", recommendedFileIngestThreadCount));
// TODO listen to changes in form fields and call controller.changed()
DocumentListener docListener = new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}
@Override
public void removeUpdate(DocumentEvent e) {
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}
@Override
public void changedUpdate(DocumentEvent e) {
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}
};
this.jFormattedTextFieldProcTimeOutHrs.getDocument().addDocumentListener(docListener);
}
void load() {
@ -98,20 +43,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
boolean useLocalTime = UserPreferences.displayTimesInLocalTime();
useLocalTimeRB.setSelected(useLocalTime);
useGMTTimeRB.setSelected(!useLocalTime);
numberOfFileIngestThreadsComboBox.setSelectedItem(UserPreferences.numberOfFileIngestThreads());
if (UserPreferences.getIsTimeOutEnabled()) {
// user specified time out
jCheckBoxEnableProcTimeout.setSelected(true);
jFormattedTextFieldProcTimeOutHrs.setEditable(true);
int timeOutHrs = UserPreferences.getProcessTimeOutHrs();
jFormattedTextFieldProcTimeOutHrs.setValue((long) timeOutHrs);
} else {
// never time out
jCheckBoxEnableProcTimeout.setSelected(false);
jFormattedTextFieldProcTimeOutHrs.setEditable(false);
int timeOutHrs = UserPreferences.getProcessTimeOutHrs();
jFormattedTextFieldProcTimeOutHrs.setValue((long) timeOutHrs);
}
}
void store() {
@ -121,14 +52,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
UserPreferences.setHideSlackFilesInDataSourcesTree(dataSourcesHideSlackCB.isSelected());
UserPreferences.setHideSlackFilesInViewsTree(viewsHideSlackCB.isSelected());
UserPreferences.setDisplayTimesInLocalTime(useLocalTimeRB.isSelected());
UserPreferences.setNumberOfFileIngestThreads((Integer) numberOfFileIngestThreadsComboBox.getSelectedItem());
UserPreferences.setIsTimeOutEnabled(jCheckBoxEnableProcTimeout.isSelected());
if (jCheckBoxEnableProcTimeout.isSelected()) {
// only store time out if it is enabled
long timeOutHrs = (long) jFormattedTextFieldProcTimeOutHrs.getValue();
UserPreferences.setProcessTimeOutHrs((int) timeOutHrs);
}
}
boolean valid() {
@ -156,13 +79,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
jLabelHideKnownFiles = new javax.swing.JLabel();
dataSourcesHideKnownCB = new javax.swing.JCheckBox();
viewsHideKnownCB = new javax.swing.JCheckBox();
jLabelNumThreads = new javax.swing.JLabel();
numberOfFileIngestThreadsComboBox = new javax.swing.JComboBox<>();
restartRequiredLabel = new javax.swing.JLabel();
jLabelSetProcessTimeOut = new javax.swing.JLabel();
jCheckBoxEnableProcTimeout = new javax.swing.JCheckBox();
jLabelProcessTimeOutUnits = new javax.swing.JLabel();
jFormattedTextFieldProcTimeOutHrs = new JFormattedTextField(NumberFormat.getIntegerInstance());
dataSourcesHideSlackCB = new javax.swing.JCheckBox();
viewsHideSlackCB = new javax.swing.JCheckBox();
jLabelHideSlackFiles = new javax.swing.JLabel();
@ -223,35 +139,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
}
});
org.openide.awt.Mnemonics.setLocalizedText(jLabelNumThreads, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelNumThreads.text")); // NOI18N
numberOfFileIngestThreadsComboBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
numberOfFileIngestThreadsComboBoxActionPerformed(evt);
}
});
restartRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/warning16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(restartRequiredLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.restartRequiredLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabelSetProcessTimeOut, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelSetProcessTimeOut.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jCheckBoxEnableProcTimeout, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text")); // NOI18N
jCheckBoxEnableProcTimeout.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jCheckBoxEnableProcTimeoutActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(jLabelProcessTimeOutUnits, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text")); // NOI18N
jFormattedTextFieldProcTimeOutHrs.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jFormattedTextFieldProcTimeOutHrs.text")); // NOI18N
jFormattedTextFieldProcTimeOutHrs.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jFormattedTextFieldProcTimeOutHrsActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(dataSourcesHideSlackCB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.dataSourcesHideSlackCB.text")); // NOI18N
dataSourcesHideSlackCB.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -276,30 +163,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(10, 10, 10)
.addComponent(numberOfFileIngestThreadsComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(restartRequiredLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabelTimeDisplay)
.addComponent(jLabelNumThreads)
.addComponent(jLabelSetProcessTimeOut)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(10, 10, 10)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(useLocalTimeRB)
.addComponent(useGMTTimeRB)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jCheckBoxEnableProcTimeout)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jFormattedTextFieldProcTimeOutHrs, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabelProcessTimeOutUnits)))))
.addGap(213, 213, 213)))
.addContainerGap())
.addComponent(useGMTTimeRB))))
.addContainerGap(512, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabelHideKnownFiles)
@ -349,21 +220,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
.addComponent(useLocalTimeRB)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(useGMTTimeRB)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabelNumThreads)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(numberOfFileIngestThreadsComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(restartRequiredLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabelSetProcessTimeOut)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jCheckBoxEnableProcTimeout)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jFormattedTextFieldProcTimeOutHrs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabelProcessTimeOutUnits)))
.addContainerGap(49, Short.MAX_VALUE))
.addContainerGap(148, Short.MAX_VALUE))
);
jScrollPane1.setViewportView(jPanel1);
@ -380,11 +237,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
);
}// </editor-fold>//GEN-END:initComponents
private void jCheckBoxEnableProcTimeoutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBoxEnableProcTimeoutActionPerformed
jFormattedTextFieldProcTimeOutHrs.setEditable(jCheckBoxEnableProcTimeout.isSelected());
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_jCheckBoxEnableProcTimeoutActionPerformed
private void useBestViewerRBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useBestViewerRBActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_useBestViewerRBActionPerformed
@ -409,14 +261,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_useGMTTimeRBActionPerformed
private void numberOfFileIngestThreadsComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_numberOfFileIngestThreadsComboBoxActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_numberOfFileIngestThreadsComboBoxActionPerformed
private void jFormattedTextFieldProcTimeOutHrsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jFormattedTextFieldProcTimeOutHrsActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_jFormattedTextFieldProcTimeOutHrsActionPerformed
private void dataSourcesHideSlackCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataSourcesHideSlackCBActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_dataSourcesHideSlackCBActionPerformed
@ -430,20 +274,13 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
private javax.swing.ButtonGroup buttonGroup3;
private javax.swing.JCheckBox dataSourcesHideKnownCB;
private javax.swing.JCheckBox dataSourcesHideSlackCB;
private javax.swing.JCheckBox jCheckBoxEnableProcTimeout;
private javax.swing.JFormattedTextField jFormattedTextFieldProcTimeOutHrs;
private javax.swing.JLabel jLabelHideKnownFiles;
private javax.swing.JLabel jLabelHideSlackFiles;
private javax.swing.JLabel jLabelNumThreads;
private javax.swing.JLabel jLabelProcessTimeOutUnits;
private javax.swing.JLabel jLabelSelectFile;
private javax.swing.JLabel jLabelSetProcessTimeOut;
private javax.swing.JLabel jLabelTimeDisplay;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JRadioButton keepCurrentViewerRB;
private javax.swing.JComboBox<Integer> numberOfFileIngestThreadsComboBox;
private javax.swing.JLabel restartRequiredLabel;
private javax.swing.JRadioButton useBestViewerRB;
private javax.swing.JRadioButton useGMTTimeRB;
private javax.swing.JRadioButton useLocalTimeRB;

View File

@ -1,7 +1,7 @@
CTL_DataContentAction=DataContent
CTL_DataContentTopComponent=Data Content
CTL_CustomAboutAction=About
OptionsCategory_Name_General=Autopsy
OptionsCategory_Name_General=View
OptionsCategory_Keywords_General=Autopsy Options
HINT_DataContentTopComponent=This is a DataContent window
HINT_NodeTableTopComponent=This is a DataResult window
@ -139,11 +139,9 @@ AutopsyOptionsPanel.useGMTTimeRB.text=Use GMT
AutopsyOptionsPanel.useLocalTimeRB.text=Use local time zone
AutopsyOptionsPanel.keepCurrentViewerRB.toolTipText=For example, stay in Hex view when a JPEG is selected.
AutopsyOptionsPanel.keepCurrentViewerRB.text=Stay on the same file viewer
AutopsyOptionsPanel.restartRequiredLabel.text=For this computer, a maximum of {0} file ingest threads should be used. Application restart required to take effect.
AutopsyOptionsPanel.jLabelSelectFile.text=When selecting a file:
AutopsyOptionsPanel.jLabelHideKnownFiles.text=Hide known files (i.e. those in the NIST NSRL) in the:
AutopsyOptionsPanel.jLabelTimeDisplay.text=When displaying times:
AutopsyOptionsPanel.jLabelNumThreads.text=Number of threads to use for file ingest:
FXVideoPanel.progress.bufferingCancelled=media buffering was canceled
FXVideoPanel.progress.bufferingInterrupted=media buffering was interrupted
FXVideoPanel.progress.errorWritingVideoToDisk=Error writing video to disk
@ -158,10 +156,6 @@ MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database por
MultiUserSettingsPanel.validationErrMsg.invalidMessageServicePort=Invalid message service port number
MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort=Invalid Solr server port number
MultiUserSettingsPanel.validationErrMsg.invalidMessgeServiceURI=Message service host and/or port not valid
AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text=
AutopsyOptionsPanel.jFormattedTextFieldProcTimeOutHrs.text=60
AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text=hour(s)
AutopsyOptionsPanel.jLabelSetProcessTimeOut.text=Enable timeout to allow modules to automatically terminate after a set amount of time\:
DataContentViewerHex.goToOffsetLabel.text=Jump to Offset
DataContentViewerHex.goToOffsetTextField.text=
DataContentViewerHex.goToOffsetTextField.msgDlg=Invalid Offset\: {0}

View File

@ -1,5 +1,4 @@
CTL_DataContentAction=\u30c7\u30fc\u30bf\u30b3\u30f3\u30c6\u30f3\u30c4
OptionsCategory_Name_General=Autopsy
OptionsCategory_Keywords_General=Autopsy\u30aa\u30d7\u30b7\u30e7\u30f3
CTL_CustomAboutAction=Autopsy\u306b\u3064\u3044\u3066
CTL_DataContentTopComponent=\u30c7\u30fc\u30bf\u30b3\u30f3\u30c6\u30f3\u30c4
@ -116,11 +115,9 @@ AutopsyOptionsPanel.useGMTTimeRB.text=GMT\u3092\u4f7f\u7528
AutopsyOptionsPanel.useLocalTimeRB.text=\u30ed\u30fc\u30ab\u30eb\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\u3092\u4f7f\u7528
AutopsyOptionsPanel.keepCurrentViewerRB.toolTipText=\u4f8b\u3048\u3070\u3001JPEG\u304c\u9078\u629e\u3055\u308c\u305f\u5834\u5408\u306b\u305d\u306e\u307e\u307eHEX\u30d3\u30e5\u30fc\u3092\u4f7f\u7528\u3002
AutopsyOptionsPanel.keepCurrentViewerRB.text=\u305d\u306e\u307e\u307e\u540c\u3058\u30d5\u30a1\u30a4\u30eb\u30d3\u30e5\u30fc\u30a2\u3092\u4f7f\u7528
AutopsyOptionsPanel.restartRequiredLabel.text=\u3053\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u30fc\u3067\u306f\u6700\u5927{0}\u306e\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b9\u30ec\u30c3\u30c9\u3092\u4f7f\u7528\u3059\u3079\u304d\u3067\u3059\u3002\u6709\u52b9\u306b\u3059\u308b\u306b\u306f\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u3067\u3059\u3002
AutopsyOptionsPanel.jLabelSelectFile.text=\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3059\u308b\u5834\u5408\uff1a
AutopsyOptionsPanel.jLabelHideKnownFiles.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb\uff08NIST NSRL\u5185\u306e\uff09\u3092\u6b21\u306b\u96a0\u3059\uff1a
AutopsyOptionsPanel.jLabelTimeDisplay.text=\u6642\u9593\u3092\u8868\u793a\u3059\u308b\u5834\u5408\uff1a
AutopsyOptionsPanel.jLabelNumThreads.text=\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306b\u4f7f\u7528\u3059\u308b\u30b9\u30ec\u30c3\u30c9\u6570\uff1a
FXVideoPanel.progress.bufferingCancelled=\u30e1\u30c7\u30a3\u30a2\u306e\u30d0\u30c3\u30d5\u30a1\u30ea\u30f3\u30b0\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f
FXVideoPanel.progress.bufferingInterrupted=\u30e1\u30c7\u30a3\u30a2\u306e\u30d0\u30c3\u30d5\u30a1\u30ea\u30f3\u30b0\u304c\u4e2d\u65ad\u3055\u308c\u307e\u3057\u305f
FXVideoPanel.progress.errorWritingVideoToDisk=\u30d3\u30c7\u30aa\u3092\u30c7\u30a3\u30b9\u30af\u3078\u66f8\u304d\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
@ -135,8 +132,6 @@ MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort=\u7121\u52b9\u306a\u
MultiUserSettingsPanel.validationErrMsg.invalidMessageServicePort=\u7121\u52b9\u306a\u30e1\u30c3\u30bb\u30fc\u30b8\u30b5\u30fc\u30d3\u30b9\u30dd\u30fc\u30c8\u756a\u53f7
MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort=\u7121\u52b9\u306aSolr\u30b5\u30fc\u30d0\u30fc\u30dd\u30fc\u30c8\u756a\u53f7
MultiUserSettingsPanel.validationErrMsg.invalidMessgeServiceURI=\u7121\u52b9\u306a\u30e1\u30c3\u30bb\u30fc\u30b8\u30b5\u30fc\u30d3\u30b9\u30db\u30b9\u30c8\u3084\u30dd\u30fc\u30c8\u756a\u53f7
AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text=\u6642\u9593
AutopsyOptionsPanel.jLabelSetProcessTimeOut.text=\u4e00\u5b9a\u306e\u6642\u9593\u304c\u904e\u304e\u305f\u5f8c\u306b\u81ea\u52d5\u7684\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u505c\u6b62\u3067\u304d\u308b\u3088\u3046\u306b\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u3092\u6709\u52b9\u5316\uff1a
DataContentViewerHex.goToOffsetLabel.text=\u30aa\u30d5\u30bb\u30c3\u30c8\u306b\u30b8\u30e3\u30f3\u30d7
DataContentViewerHex.goToOffsetTextField.msgDlg=\u7121\u52b9\u306a\u30aa\u30d5\u30bb\u30c3\u30c8\uff1a{0}
DataContentViewerHex.setDataView.invalidOffset.negativeOffsetValue=\u8a08\u7b97\u3055\u308c\u305f\u30aa\u30d5\u30bb\u30c3\u30c8\u306b\u30b8\u30e3\u30f3\u30d7\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -22,7 +22,6 @@ import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JTabbedPane;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
@ -30,6 +29,7 @@ import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Top component that organizes all of the data content viewers. Doing a lookup
@ -42,17 +42,18 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent;
//@TopComponent.OpenActionRegistration(displayName = "#CTL_DataContentAction", preferredID = "DataContentTopComponent")
public final class DataContentTopComponent extends TopComponent implements DataContent {
private static Logger logger = Logger.getLogger(DataContentTopComponent.class.getName());
private static final Logger logger = Logger.getLogger(DataContentTopComponent.class.getName());
// reference to the "default" TC that always stays open
private static DataContentTopComponent defaultInstance;
private static final long serialVersionUID = 1L;
// set to true if this is the TC that always stays open and is the default place to display content
private boolean isDefault;
private final boolean isDefault;
// the content panel holding tabs with content viewers
private final DataContentPanel dataContentPanel;
// contains a list of the undocked TCs
private static ArrayList<DataContentTopComponent> newWindowList = new ArrayList<DataContentTopComponent>();
private static final ArrayList<DataContentTopComponent> newWindowList = new ArrayList<>();
private static final String PREFERRED_ID = "DataContentTopComponent"; //NON-NLS
private static final String DEFAULT_NAME = NbBundle.getMessage(DataContentTopComponent.class, "CTL_DataContentTopComponent");
private static final String TOOLTIP_TEXT = NbBundle.getMessage(DataContentTopComponent.class, "HINT_DataContentTopComponent");
@ -67,8 +68,8 @@ public final class DataContentTopComponent extends TopComponent implements DataC
dataContentPanel = new DataContentPanel(isDefault);
add(dataContentPanel);
putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.valueOf(isDefault)); // prevent option to close compoment in GUI
logger.log(Level.INFO, "Created DataContentTopComponent instance: " + this); //NON-NLS
putClientProperty(TopComponent.PROP_CLOSING_DISABLED, isDefault); // prevent option to close compoment in GUI
logger.log(Level.INFO, "Created DataContentTopComponent instance: {0}", this); //NON-NLS
}
/**
@ -91,24 +92,13 @@ public final class DataContentTopComponent extends TopComponent implements DataC
return dctc;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.Y_AXIS));
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
/**
* Gets default instance. Do not use directly: reserved for *.settings files
* only, i.e. deserialization routines; otherwise you could get a
* non-deserialized defaultInstance. To obtain the singleton instance, use
* {@link #findInstance}.
* findInstance.
*
* @return
*/
public static synchronized DataContentTopComponent getDefault() {
if (defaultInstance == null) {
@ -118,8 +108,10 @@ public final class DataContentTopComponent extends TopComponent implements DataC
}
/**
* Obtain the default DataContentTopComponent defaultInstance. Never call
* {@link #getDefault} directly!
* Obtain the default DataContentTopComponent default instance. Never call
* getDefault directly!
*
* @return The default DataContentTopComponent.
*/
public static synchronized DataContentTopComponent findInstance() {
TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
@ -171,7 +163,12 @@ public final class DataContentTopComponent extends TopComponent implements DataC
@Override
public boolean canClose() {
return (!this.isDefault) || !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image in this case
/*
* If this is the main content viewers top component in the bottom of
* the main window, only it to be closed when there's no case opened or
* no data sources in the open case.
*/
return (!this.isDefault) || !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false;
}
@Override
@ -195,4 +192,18 @@ public final class DataContentTopComponent extends TopComponent implements DataC
public static List<DataContentTopComponent> getNewWindowList() {
return newWindowList;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.Y_AXIS));
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -276,7 +276,9 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (!Case.isCaseOpen()) {
try {
Case.getCurrentCase();
} catch (IllegalStateException ex) {
// Handle the in-between condition when case is being closed
// and legacy selection events are pumped.
return;
@ -443,7 +445,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
@Override
public List<DataResultViewer> getViewers() {
List<DataResultViewer> ret = new ArrayList<DataResultViewer>();
List<DataResultViewer> ret = new ArrayList<>();
for (UpdateWrapper w : viewers) {
ret.add(w.getViewer());
}
@ -452,7 +454,12 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
}
public boolean canClose() {
return (!this.isMain) || !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image in this case
/*
* If this is the main results panel in the main top component in the
* upper right of the main window, only allow it to be closed when
* there's no case opened or no data sources in the open case.
*/
return (!this.isMain) || !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false;
}
@Override

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -314,7 +314,12 @@ public class DataResultTopComponent extends TopComponent implements DataResult,
@Override
public boolean canClose() {
return (!this.isMain) || !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image in this case
/*
* If this is the results top component in the upper right of the main
* window, only allow it to be closed when there's no case opened or no
* data sources in the open case.
*/
return (!this.isMain) || !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false;
}
/**

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2014 Basis Technology Corp.
* Copyright 2013-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -31,7 +31,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_Multi_User_Settings",
iconBase = "org/sleuthkit/autopsy/images/User-Group-icon-green32.png",
position = 2,
position = 3,
keywords = "#OptionsCategory_Keywords_Multi_User_Options",
keywordsCategory = "Multi-user")
public final class MultiUserSettingsPanelController extends OptionsPanelController {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.corecomponents;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
/**
* A filter node that creates at most one layer of child nodes for the node it
@ -44,7 +45,7 @@ public class TableFilterNode extends FilterNode {
* The constructor should include column order key. (See getColumnOrderKey)
*/
public TableFilterNode(Node wrappedNode, boolean createChildren) {
super(wrappedNode, TableFilterChildren.createInstance(wrappedNode, createChildren));
super(wrappedNode, TableFilterChildren.createInstance(wrappedNode, createChildren) , Lookups.proxy(wrappedNode));
this.createChildren = createChildren;
}

View File

@ -163,12 +163,22 @@ public final class ExecUtil {
process.waitFor(timeOut, units);
if (process.isAlive() && terminator.shouldTerminateProcess()) {
killProcess(process);
try {
process.waitFor(); //waiting to help ensure process is shutdown before calling interrupt() or returning
} catch (InterruptedException exx) {
Logger.getLogger(ExecUtil.class.getName()).log(Level.INFO, String.format("Wait for process termination following killProcess was interrupted for command %s", processBuilder.command().get(0)));
}
}
} while (process.isAlive());
} catch (InterruptedException ex) {
if (process.isAlive()) {
killProcess(process);
}
try {
process.waitFor(); //waiting to help ensure process is shutdown before calling interrupt() or returning
} catch (InterruptedException exx) {
Logger.getLogger(ExecUtil.class.getName()).log(Level.INFO, String.format("Wait for process termination following killProcess was interrupted for command %s", processBuilder.command().get(0)));
}
Logger.getLogger(ExecUtil.class.getName()).log(Level.INFO, "Thread interrupted while running {0}", processBuilder.command().get(0)); // NON-NLS
Thread.currentThread().interrupt();
}

View File

@ -315,4 +315,29 @@ public class UNCPathUtilities {
}
return driveMap;
}
/**
* Converts a path to UNC, if possible. This is accomplished by checking the
* mapped drives list the operating system maintains and substituting where
* required. If the drive of the path passed in does not exist in the cached
* mapped drives list, a rescan of the mapped drives list is forced, and
* mapping is attempted one more time.
*
* @param indexDir the String of the absolute path to be converted to UNC,
* if possible
*
* @return UNC path if able to convert to UNC, original input path otherwise
*/
synchronized public String convertPathToUNC(String indexDir) {
// if we can check for UNC paths, do so, otherwise just return the indexDir
String result = mappedDriveToUNC(indexDir);
if (result == null) {
rescanDrives();
result = mappedDriveToUNC(indexDir);
}
if (result == null) {
return indexDir;
}
return result;
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,62 +19,105 @@
package org.sleuthkit.autopsy.datamodel;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.util.Arrays;
import java.util.logging.Level;
import org.apache.commons.lang.StringUtils;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskException;
/**
* StringContent object for a blackboard artifact, that can be looked up and
* used to display text for the DataContent viewers. Displays values in artifact
* in HTML. Note that it has no style associated with it and assumes that the
* pane showing the HTML has styles set (such as with HTMLEditorKit).
* An HTML representation of an artifact. The representation is plain vanilla
* HTML, so any styling needs to be supplied by the display mechansim. For
* example, GUI components such as content viewers might use HTMLEditorKit to
* add styling.
*/
public class ArtifactStringContent implements StringContent {
BlackboardArtifact artifact;
private final static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private final static Logger logger = Logger.getLogger(ArtifactStringContent.class.getName());
private final BlackboardArtifact artifact;
private String stringContent = "";
static final Logger logger = Logger.getLogger(ArtifactStringContent.class.getName());
private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public ArtifactStringContent(BlackboardArtifact art) {
artifact = art;
/**
* Constructs an HTML representation of an artifact. The representation is
* plain vanilla HTML, so any styling needs to be supplied by the display
* mechansim. For example, GUI components such as content viewers might use
* HTMLEditorKit to add styling.
*
* @param artifact The artifact to be represented as HTML.
*/
public ArtifactStringContent(BlackboardArtifact artifact) {
this.artifact = artifact;
}
/**
* Gets the HTML representation of the artifact.
*
* @return The HTML representation of the artifact as a string.
*/
@Messages({
"ArtifactStringContent.attrsTableHeader.attribute=Attribute",
"ArtifactStringContent.attrsTableHeader.value=Value",
"ArtifactStringContent.attrsTableHeader.sources=Source(s)",
"ArtifactStringContent.failedToGetSourcePath.message=Failed to get source file path from case database",
"ArtifactStringContent.failedToGetAttributes.message=Failed to get some or all attributes from case database"
})
@Override
@SuppressWarnings("deprecation")
public String getString() {
if (stringContent.isEmpty()) {
try {
StringBuilder buffer = new StringBuilder();
/*
* Start the document.
*/
StringBuilder buffer = new StringBuilder(1024);
buffer.append("<html>\n"); //NON-NLS
buffer.append("<body>\n"); //NON-NLS
// artifact name header
buffer.append("<h4>"); //NON-NLS
/*
* Use the artifact display name as a header.
*/
buffer.append("<h3>"); //NON-NLS
buffer.append(artifact.getDisplayName());
buffer.append("</h4>\n"); //NON-NLS
buffer.append("</h3>\n"); //NON-NLS
// start table for attributes
buffer.append("<table border='0'>"); //NON-NLS
/*
* Put the attributes, source content path and artifact id in a
* table.
*/
buffer.append("<table border='1'>"); //NON-NLS
buffer.append("<tr>"); //NON-NLS
buffer.append("<td>"); //NON-NLS
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_attribute());
buffer.append("</td>"); //NON-NLS
buffer.append("<td>"); //NON-NLS
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_value());
buffer.append("</td>"); //NON-NLS
buffer.append("<td>"); //NON-NLS
buffer.append(Bundle.ArtifactStringContent_attrsTableHeader_sources());
buffer.append("</td>"); //NON-NLS
buffer.append("</tr>\n"); //NON-NLS
try {
Content content = artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
// cycle through each attribute and display in a row in the table.
/*
* Add rows for each attribute.
*/
for (BlackboardAttribute attr : artifact.getAttributes()) {
// name column
/*
* Attribute display name column.
*/
buffer.append("<tr><td>"); //NON-NLS
buffer.append(attr.getAttributeType().getDisplayName());
buffer.append("</td>"); //NON-NLS
// value column
/*
* Attribute value column.
*/
buffer.append("<td>"); //NON-NLS
switch (attr.getAttributeType().getValueType()) {
case STRING:
@ -88,48 +131,57 @@ public class ArtifactStringContent implements StringContent {
case INTEGER:
case LONG:
case DOUBLE:
case BYTE:
buffer.append(attr.getDisplayString());
break;
case BYTE:
buffer.append(Arrays.toString(attr.getValueBytes()));
break;
case DATETIME:
long epoch = attr.getValueLong();
String time = "0000-00-00 00:00:00";
if (epoch != 0) {
dateFormatter.setTimeZone(getTimeZone(artifact));
if (null != content && 0 != epoch) {
dateFormatter.setTimeZone(ContentUtils.getTimeZone(content));
time = dateFormatter.format(new java.util.Date(epoch * 1000));
}
buffer.append(time);
break;
}
if (!"".equals(attr.getContext())) {
buffer.append(" (");
buffer.append(attr.getContext());
buffer.append(")");
}
buffer.append("</td>"); //NON-NLS
/*
* Attribute sources column.
*/
buffer.append("<td>"); //NON-NLS
buffer.append(StringUtils.join(attr.getSources(), ", "));
buffer.append("</td>"); //NON-NLS
buffer.append("</tr>\n"); //NON-NLS
}
final Content content = getAssociatedContent(artifact);
String path = "";
try {
path = content.getUniquePath();
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Exception while calling Content.getUniquePath() on {0} : {1}", new Object[]{content, ex.getLocalizedMessage()}); //NON-NLS
}
//add file path
/*
* Add a row for the source content path.
*/
buffer.append("<tr>"); //NON-NLS
buffer.append("<td>"); //NON-NLS
buffer.append(NbBundle.getMessage(this.getClass(), "ArtifactStringContent.getStr.srcFilePath.text"));
buffer.append("</td>"); //NON-NLS
buffer.append("<td>"); //NON-NLS
String path = "";
try {
if (null != content) {
path = content.getUniquePath();
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Error getting source content path for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
path = Bundle.ArtifactStringContent_failedToGetSourcePath_message();
}
buffer.append(path);
buffer.append("</td>"); //NON-NLS
buffer.append("</tr>\n"); //NON-NLS
// add artifact ID (useful for debugging)
/*
* Add a row for the artifact id.
*/
buffer.append("<tr><td>"); //NON-NLS
buffer.append(NbBundle.getMessage(this.getClass(), "ArtifactStringContent.getStr.artifactId.text"));
buffer.append("</td><td>"); //NON-NLS
@ -137,29 +189,26 @@ public class ArtifactStringContent implements StringContent {
buffer.append("</td>"); //NON-NLS
buffer.append("</tr>\n"); //NON-NLS
/*
* Finish the document
*/
buffer.append("</table>"); //NON-NLS
buffer.append("</html>\n"); //NON-NLS
stringContent = buffer.toString();
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Error getting data for artifact (artifact_id=%d)", artifact.getArtifactID()), ex);
buffer.append("<tr><td>"); //NON-NLS
buffer.append(Bundle.ArtifactStringContent_failedToGetAttributes_message());
buffer.append("</td>"); //NON-NLS
buffer.append("</tr>\n"); //NON-NLS
buffer.append("</table>"); //NON-NLS
buffer.append("</html>\n"); //NON-NLS
stringContent = buffer.toString();
} catch (TskException ex) {
stringContent = NbBundle.getMessage(this.getClass(), "ArtifactStringContent.getStr.err");
}
}
return stringContent;
}
private static Content getAssociatedContent(BlackboardArtifact artifact) {
try {
return artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
} catch (TskException ex) {
logger.log(Level.WARNING, "Getting file failed", ex); //NON-NLS
}
throw new IllegalArgumentException(NbBundle.getMessage(ArtifactStringContent.class, "ArtifactStringContent.exception.msg"));
}
private static TimeZone getTimeZone(BlackboardArtifact artifact) {
return ContentUtils.getTimeZone(getAssociatedContent(artifact));
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -404,7 +404,8 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE.getTypeID()) {
} else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
} else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID()
@ -452,13 +453,6 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
forLookup.add(content);
}
// if there is a text highlighted version, of the content, add it too
// currently happens from keyword search module
TextMarkupLookup highlight = getHighlightLookup(artifact, content);
if (highlight != null) {
forLookup.add(highlight);
}
return Lookups.fixed(forLookup.toArray(new Object[forLookup.size()]));
}
@ -472,39 +466,6 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.getAssocCont.exception.msg"));
}
private static TextMarkupLookup getHighlightLookup(BlackboardArtifact artifact, Content content) {
if (artifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
return null;
}
long objectId = content.getId();
Lookup lookup = Lookup.getDefault();
TextMarkupLookup highlightFactory = lookup.lookup(TextMarkupLookup.class);
try {
List<BlackboardAttribute> attributes = artifact.getAttributes();
String keyword = null;
String regexp = null;
for (BlackboardAttribute att : attributes) {
final int attributeTypeID = att.getAttributeType().getTypeID();
if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
keyword = att.getValueString();
} else if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()) {
regexp = att.getValueString();
} else if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
objectId = att.getValueLong();
}
}
if (keyword != null) {
boolean isRegexp = StringUtils.isNotBlank(regexp);
String origQuery = isRegexp ? regexp : keyword;
return highlightFactory.createInstance(objectId, keyword, isRegexp, origQuery);
}
} catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, "Failed to retrieve Blackboard Attributes", ex); //NON-NLS
}
return null;
}
@Override
public boolean isLeafTypeNode() {

View File

@ -12,7 +12,7 @@ AbstractAbstractFileNode.modeColLbl=Mode
AbstractAbstractFileNode.useridColLbl=UserID
AbstractAbstractFileNode.groupidColLbl=GroupID
AbstractAbstractFileNode.metaAddrColLbl=Meta Addr.
AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.
AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.ArtifactStringContent.getStr.err
AbstractAbstractFileNode.typeDirColLbl=Type(Dir)
AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)
AbstractAbstractFileNode.knownColLbl=Known
@ -25,7 +25,6 @@ AbstractContentNode.exception.cannotChangeSysName.msg=Cannot change the system n
AbstractFsContentNode.noDesc.text=no description
ArtifactStringContent.getStr.srcFilePath.text=Source File Path
ArtifactStringContent.getStr.err=Error getting content
ArtifactStringContent.exception.msg=Could not get file from database
ArtifactTypeNode.createSheet.artType.name=Artifact Type
ArtifactTypeNode.createSheet.artType.displayName=Artifact Type
ArtifactTypeNode.createSheet.artType.desc=no description
@ -172,8 +171,6 @@ KeywordHits.createNodeForKey.chgTime.desc=Change Time
KeywordHits.createNodeForKey.chgTime.name=ChangeTime
KeywordHits.createNodeForKey.accessTime.name=AccessTime
KeywordHits.createNodeForKey.modTime.name=ModifiedTime
KnownFileFilterNode.selectionContext.dataSources=Data Sources
KnownFileFilterNode.selectionContext.views=Views
LayoutFileNode.propertyType.parts=Parts
LayoutFileNode.createSheet.name.name=Name
LayoutFileNode.createSheet.name.displayName=Name
@ -222,8 +219,6 @@ ReportNode.reportNameProperty.name=Report Name
ReportNode.reportNameProperty.displayName=Report Name
ReportNode.reportNameProperty.desc=Name of the report
ReportsListNode.displayName=Reports
SlackFileFilterNode.selectionContext.dataSources=Data Sources
SlackFileFilterNode.selectionContext.views=Views
SlackFileNode.getActions.viewInNewWin.text=View in New Window
SlackFileNode.getActions.viewFileInDir.text=View File in Directory
TagNameNode.namePlusTags.text={0} Tags

View File

@ -18,7 +18,6 @@ AbstractContentNode.exception.cannotChangeSysName.msg=\u30b7\u30b9\u30c6\u30e0\u
AbstractFsContentNode.noDesc.text=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
ArtifactStringContent.getStr.srcFilePath.text=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9
ArtifactStringContent.getStr.err=\u30b3\u30f3\u30c6\u30f3\u30c4\u53d6\u5f97\u30a8\u30e9\u30fc
ArtifactStringContent.exception.msg=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f
ArtifactTypeNode.createSheet.artType.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
ArtifactTypeNode.createSheet.childCnt.name=\u30c1\u30e3\u30a4\u30eb\u30c9\u6570
ArtifactTypeNode.createSheet.childCnt.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093

View File

@ -147,7 +147,9 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
final String mime_type = resultSet.getString("mime_type"); //NON-NLS
if (!mime_type.isEmpty()) {
String mimeType[] = mime_type.split("/");
if (!mimeType[0].isEmpty() && !mimeType[1].isEmpty()) {
//Note: Users are able to define custom mime types in Autopsy that do not
//contain a "/" or possibly have multiple slashes
if (mimeType.length > 1 && !mimeType[0].isEmpty() && !mimeType[1].isEmpty()) {
if (!existingMimeTypes.containsKey(mimeType[0])) {
existingMimeTypes.put(mimeType[0], new ArrayList<>());
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2014 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,7 +18,6 @@
*/
package org.sleuthkit.autopsy.datamodel;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.sql.ResultSet;
@ -27,7 +26,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.openide.nodes.Children;
import org.openide.nodes.Sheet;
@ -40,7 +38,7 @@ import org.sleuthkit.autopsy.directorytree.FileSearchAction;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
import org.sleuthkit.autopsy.ingest.RunIngestModulesDialog;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
@ -101,22 +99,14 @@ public class ImageNode extends AbstractContentNode<Image> {
"ImageNode.getActions.openFileSearchByAttr.text=Open File Search by Attributes",})
public Action[] getActions(boolean context) {
List<Action> actionsList = new ArrayList<Action>();
List<Action> actionsList = new ArrayList<>();
for (Action a : super.getActions(true)) {
actionsList.add(a);
}
actionsList.addAll(ExplorerNodeActionVisitor.getActions(content));
actionsList.add(new FileSearchAction(
Bundle.ImageNode_getActions_openFileSearchByAttr_text()));
actionsList.add(new AbstractAction(
Bundle.ImageNode_action_runIngestMods_text()) {
@Override
public void actionPerformed(ActionEvent e) {
final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog(Collections.<Content>singletonList(content));
ingestDialog.display();
}
});
actionsList.add(new RunIngestModulesAction(Collections.<Content>singletonList(content)));
actionsList.add(new NewWindowViewAction(
NbBundle.getMessage(this.getClass(), "ImageNode.getActions.viewInNewWin.text"), this));
return actionsList.toArray(new Action[0]);

View File

@ -1,181 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2014 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datamodel;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskData;
/**
* A Filter Node responsible for conditionally filtering out Nodes that
* represent known files.
*
* Filters known files IF the option to Filter Known files for the given
* SelectionContext is set. Otherwise, does nothing.
*
* @author jwallace
*/
public class KnownFileFilterNode extends FilterNode {
private static boolean filterFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
private static boolean filterFromViews = UserPreferences.hideKnownFilesInViewsTree();
static {
UserPreferences.addChangeListener(new PreferenceChangeListener() {
@Override
public void preferenceChange(PreferenceChangeEvent evt) {
switch (evt.getKey()) {
case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE:
filterFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
break;
case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE:
filterFromViews = UserPreferences.hideKnownFilesInViewsTree();
break;
}
}
});
}
public enum SelectionContext {
DATA_SOURCES(NbBundle.getMessage(KnownFileFilterNode.class, "KnownFileFilterNode.selectionContext.dataSources")),
VIEWS(NbBundle.getMessage(KnownFileFilterNode.class, "KnownFileFilterNode.selectionContext.views")),
OTHER(""); // Subnode of another node.
private final String displayName;
SelectionContext(String displayName) {
this.displayName = displayName;
}
public static SelectionContext getContextFromName(String name) {
if (name.equals(DATA_SOURCES.getName())) {
return DATA_SOURCES;
} else if (name.equals(VIEWS.getName())) {
return VIEWS;
} else {
return OTHER;
}
}
private String getName() {
return displayName;
}
}
/**
* Create a KnownFileFilterNode from the given Node. Note that the Node
* should be from the directory tree.
*
* @param arg
* @param context
*/
public KnownFileFilterNode(Node arg, SelectionContext context) {
super(arg, new KnownFileFilterChildren(arg, context));
}
private KnownFileFilterNode(Node arg, boolean filter) {
super(arg, new KnownFileFilterChildren(arg, filter));
}
/**
* Get the selection context of a Node in the DirectoryTree.
*
* @param n
*
* @return
*/
public static SelectionContext getSelectionContext(Node n) {
if (n == null || n.getParentNode() == null) {
// Parent of root node or root node. Occurs during case open / close.
return SelectionContext.OTHER;
} else if (n.getParentNode().getParentNode() == null) {
// One level below root node. Should be one of DataSources, Views, or Results
return SelectionContext.getContextFromName(n.getDisplayName());
} else {
return getSelectionContext(n.getParentNode());
}
}
/**
* Complementary class to KnownFileFilterNode.
*
* Filters out children Nodes that represent known files. Otherwise, returns
* the original node wrapped in another instance of the KnownFileFilterNode.
*
* @author jwallace
*/
private static class KnownFileFilterChildren extends FilterNode.Children {
/**
* True if this KnownFileFilterChildren should filter out known files.
*/
private boolean filter;
/**
* Constructor used when the context has already been determined.
*
* @param arg
* @param filter
*/
private KnownFileFilterChildren(Node arg, boolean filter) {
super(arg);
this.filter = filter;
}
/**
* Constructor used when the context has not been determined.
*
* @param arg
* @param context
*/
private KnownFileFilterChildren(Node arg, KnownFileFilterNode.SelectionContext context) {
super(arg);
switch (context) {
case DATA_SOURCES:
filter = filterFromDataSources;
break;
case VIEWS:
filter = filterFromViews;
break;
default:
filter = false;
break;
}
}
@Override
protected Node[] createNodes(Node arg) {
if (filter) {
// Filter out child nodes that represent known files
AbstractFile file = arg.getLookup().lookup(AbstractFile.class);
if (file != null && (file.getKnown() == TskData.FileKnown.KNOWN)) {
return new Node[]{};
}
}
return new Node[]{new KnownFileFilterNode(arg, filter)};
}
}
}

View File

@ -1,180 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2014 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datamodel;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskData;
/**
* A Filter Node responsible for conditionally filtering out Nodes that
* represent slack files.
*
* Filters known files IF the option to Filter Slack files for the given
* SelectionContext is set. Otherwise, does nothing.
*
*/
public class SlackFileFilterNode extends FilterNode {
private static boolean filterFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree();
private static boolean filterFromViews = UserPreferences.hideSlackFilesInViewsTree();
static {
UserPreferences.addChangeListener(new PreferenceChangeListener() {
@Override
public void preferenceChange(PreferenceChangeEvent evt) {
switch (evt.getKey()) {
case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SRCS_TREE:
filterFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree();
break;
case UserPreferences.HIDE_SLACK_FILES_IN_VIEWS_TREE:
filterFromViews = UserPreferences.hideSlackFilesInViewsTree();
break;
}
}
});
}
public enum SelectionContext {
DATA_SOURCES(NbBundle.getMessage(SlackFileFilterNode.class, "SlackFileFilterNode.selectionContext.dataSources")),
VIEWS(NbBundle.getMessage(SlackFileFilterNode.class, "SlackFileFilterNode.selectionContext.views")),
OTHER(""); // Subnode of another node.
private final String displayName;
SelectionContext(String displayName) {
this.displayName = displayName;
}
public static SelectionContext getContextFromName(String name) {
if (name.equals(DATA_SOURCES.getName())) {
return DATA_SOURCES;
} else if (name.equals(VIEWS.getName())) {
return VIEWS;
} else {
return OTHER;
}
}
private String getName() {
return displayName;
}
}
/**
* Create a SlackFileFilterNode from the given Node. Note that the Node
* should be from the directory tree.
*
* @param arg
* @param context
*/
public SlackFileFilterNode(Node arg, SelectionContext context) {
super(arg, new SlackFileFilterChildren(arg, context));
}
private SlackFileFilterNode(Node arg, boolean filter) {
super(arg, new SlackFileFilterChildren(arg, filter));
}
/**
* Get the selection context of a Node in the DirectoryTree.
*
* @param n
*
* @return
*/
public static SelectionContext getSelectionContext(Node n) {
if (n == null || n.getParentNode() == null) {
// Parent of root node or root node. Occurs during case open / close.
return SelectionContext.OTHER;
} else if (n.getParentNode().getParentNode() == null) {
// One level below root node. Should be one of DataSources, Views, or Results
return SelectionContext.getContextFromName(n.getDisplayName());
} else {
return getSelectionContext(n.getParentNode());
}
}
/**
* Complementary class to SlackFileFilterNode.
*
* Filters out children Nodes that represent slack files. Otherwise, returns
* the original node wrapped in another instance of the SlackFileFilterNode.
*
* @author jwallace
*/
private static class SlackFileFilterChildren extends FilterNode.Children {
/**
* True if this SlackFileFilterChildren should filter out slack files.
*/
private boolean filter;
/**
* Constructor used when the context has already been determined.
*
* @param arg
* @param filter
*/
private SlackFileFilterChildren(Node arg, boolean filter) {
super(arg);
this.filter = filter;
}
/**
* Constructor used when the context has not been determined.
*
* @param arg
* @param context
*/
private SlackFileFilterChildren(Node arg, SlackFileFilterNode.SelectionContext context) {
super(arg);
switch (context) {
case DATA_SOURCES:
filter = filterFromDataSources;
break;
case VIEWS:
filter = filterFromViews;
break;
default:
filter = false;
break;
}
}
@Override
protected Node[] createNodes(Node arg) {
if (filter) {
// Filter out child nodes that represent slack files
AbstractFile file = arg.getLookup().lookup(AbstractFile.class);
if ((file != null) && file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
return new Node[]{};
}
}
return new Node[]{new SlackFileFilterNode(arg, filter)};
}
}
}

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
*
* Copyright 2011-2014 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,7 +18,6 @@
*/
package org.sleuthkit.autopsy.datamodel;
import java.awt.event.ActionEvent;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
@ -27,7 +26,6 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
@ -38,7 +36,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.directorytree.ExtractAction;
import org.sleuthkit.autopsy.directorytree.FileSearchAction;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.ingest.RunIngestModulesDialog;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
@ -50,7 +48,7 @@ import org.sleuthkit.datamodel.VirtualDirectory;
*/
public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirectory> {
private static Logger logger = Logger.getLogger(VirtualDirectoryNode.class.getName());
private static final Logger logger = Logger.getLogger(VirtualDirectoryNode.class.getName());
//prefix for special VirtualDirectory root nodes grouping local files
public final static String LOGICAL_FILE_SET_PREFIX = "LogicalFileSet"; //NON-NLS
@ -100,14 +98,7 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirect
actions.add(null); // creates a menu separator
actions.add(new FileSearchAction(
Bundle.ImageNode_getActions_openFileSearchByAttr_text()));
actions.add(new AbstractAction(
Bundle.VirtualDirectoryNode_action_runIngestMods_text()) {
@Override
public void actionPerformed(ActionEvent e) {
final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog(Collections.<Content>singletonList(content));
ingestDialog.display();
}
});
actions.add(new RunIngestModulesAction(Collections.<Content>singletonList(content)));
actions.addAll(ContextMenuExtensionPoint.getActions());
return actions.toArray(new Action[0]);
}

View File

@ -21,7 +21,7 @@ package org.sleuthkit.autopsy.datasourceprocessors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
@ -41,111 +41,140 @@ import org.sleuthkit.datamodel.TskCoreException;
/**
* The ImageWriter class is used to complete VHD copies created from local disks
* after the ingest process completes.
* after the ingest process completes. The AddImageTask for this data source must have included
* a non-empty imageWriterPath parameter to enable Image Writer.
*/
public class ImageWriter {
public class ImageWriter implements PropertyChangeListener{
private final Logger logger = Logger.getLogger(ImageWriter.class.getName());
private final HashSet<Long> dataSourceIds = new HashSet<>();
private final Object dataSourceIdsLock; // Get this lock before accessing dataSourceIds
private final Long dataSourceId;
private final HashSet<ScheduledFuture<?>> progressUpdaters = new HashSet<>();
private final HashSet<Long> imagesBeingFinished = new HashSet<>();
private final HashSet<ProgressHandle> progressBars = new HashSet<>();
private final HashSet<Future<?>> finishTasksInProgress = new HashSet<>();
private boolean isCancelled;
private final Object currentTasksLock; // Get this lock before accessing imagesBeingFinished, progressBars, progressUpdaters, finishTasksInProgress or isCancelled
private Long imageHandle = null;
private Future<?> finishTask = null;
private ProgressHandle progressHandle = null;
private ScheduledFuture<?> progressUpdateTask = null;
private boolean isCancelled = false;
private boolean isStarted = false;
private boolean isFinished = false;
private final Object currentTasksLock = new Object(); // Get this lock before accessing imageHandle, finishTask, progressHandle, progressUpdateTask,
// isCancelled, isStarted, or isFinished
private boolean listenerStarted;
private ScheduledThreadPoolExecutor periodicTasksExecutor = null;
private final boolean doUI;
public ImageWriter(){
dataSourceIdsLock = new Object();
currentTasksLock = new Object();
listenerStarted = false;
isCancelled = false;
private static final AtomicInteger numFinishJobsInProgress = new AtomicInteger(0);
doUI = RuntimeProperties.coreComponentsAreActive();
if(doUI){
periodicTasksExecutor = new ScheduledThreadPoolExecutor(5, new ThreadFactoryBuilder().setNameFormat("image-writer-progress-update-%d").build()); //NON-NLS
}
/**
* Create the Image Writer object.
* After creation, startListeners() should be called.
* @param dataSourceId
*/
public ImageWriter(Long dataSourceId){
this.dataSourceId = dataSourceId;
doUI = RuntimeProperties.runningWithGUI();
}
/**
* Creates a listener on IngestJobEvents if it hasn't already been started.
* When a DataSourceAnalysisCompletedEvent arrives, if it matches
* the data source ID of an image that is using Image Writer, then finish the image
* (fill in any gaps). The AddImageTask for this data source must have included
* a non-empty imageWriterPath parameter to enable Image Writer.
* Add this ImageWriter object as a listener to the necessary events
*/
public void subscribeToEvents(){
IngestManager.getInstance().addIngestJobEventListener(this);
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), this);
}
/**
* Deregister this object from the events. This is ok to call multiple times.
*/
public void unsubscribeFromEvents(){
IngestManager.getInstance().removeIngestJobEventListener(this);
Case.removeEventSubscriber(Case.Events.CURRENT_CASE.toString(), this);
}
/**
* Handle the events:
* DATA_SOURCE_ANALYSIS_COMPLETED - start the finish image process and clean up after it is complete
* CURRENT_CASE (case closing) - cancel the finish image process (if necessary)
*/
private synchronized void startListener(){
if(! listenerStarted){
IngestManager.getInstance().addIngestJobEventListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED.toString())){
if(evt instanceof DataSourceAnalysisCompletedEvent){
DataSourceAnalysisCompletedEvent event = (DataSourceAnalysisCompletedEvent)evt;
if(event.getDataSource() != null){
long imageId = event.getDataSource().getId();
String name = event.getDataSource().getName();
// Check whether we need to run finishImage for this data source
synchronized(dataSourceIdsLock){
if( ! ImageWriter.this.dataSourceIds.contains(imageId)){
// Image writer was not used on this data source or we've already finished it
// Check that the event corresponds to this datasource
if(imageId != dataSourceId){
return;
} else {
// Remove the imageId from the list here so we can't get past this point twice
// for the same image. Multiple DataSourceAnalysisCompletedEvent events can come from
// the same image if more ingest modules are run later, but the imageId is only added
// to the list during the intial task to add the image to the database.
ImageWriter.this.dataSourceIds.remove(imageId);
}
}
logger.log(Level.INFO, String.format("Finishing VHD image for %s",
event.getDataSource().getName())); //NON-NLS
new Thread(() -> {
try{
Image image = Case.getCurrentCase().getSleuthkitCase().getImageById(imageId);
ProgressHandle progressHandle = null;
ScheduledFuture<?> progressUpdateTask = null;
startFinishImage(name);
}).start();
if(doUI){
progressHandle = ProgressHandle.createHandle("Image writer - " + name);
progressHandle.start(100);
progressUpdateTask = periodicTasksExecutor.scheduleAtFixedRate(
new ProgressUpdateTask(progressHandle, image.getImageHandle()), 0, 250, TimeUnit.MILLISECONDS);
} else {
logger.log(Level.SEVERE, "DataSourceAnalysisCompletedEvent did not contain a dataSource object"); //NON-NLS
}
}
else if(evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())){
// Technically this could be a case open event (and not the expected case close event) but
// that would probably mean something bad is going on, and we'd still want to cancel
// Image Writer.
close();
}
}
private void startFinishImage(String dataSourceName){
synchronized(currentTasksLock){
ImageWriter.this.imagesBeingFinished.add(image.getImageHandle());
if(doUI){
if(isCancelled){
progressUpdateTask.cancel(true);
return;
}
ImageWriter.this.progressUpdaters.add(progressUpdateTask);
ImageWriter.this.progressBars.add(progressHandle);
// If we've already started the finish process for this datasource, return.
// Multiple DataSourceAnalysisCompletedEvent events can come from
// the same image if more ingest modules are run later
if(isStarted){
return;
} else {
isStarted = true;
}
Image image;
try{
image = Case.getCurrentCase().getSleuthkitCase().getImageById(dataSourceId);
imageHandle = image.getImageHandle();
} catch (TskCoreException ex){
logger.log(Level.SEVERE, "Error loading image", ex);
// Stay subscribed to the events for now. Case close will clean everything up.
return;
}
logger.log(Level.INFO, String.format("Finishing VHD image for %s",
dataSourceName)); //NON-NLS
if(doUI){
periodicTasksExecutor = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("image-writer-progress-update-%d").build()); //NON-NLS
progressHandle = ProgressHandle.createHandle("Image writer - " + dataSourceName);
progressHandle.start(100);
progressUpdateTask = periodicTasksExecutor.scheduleAtFixedRate(
new ProgressUpdateTask(progressHandle, imageHandle), 0, 250, TimeUnit.MILLISECONDS);
}
// The added complexity here with the Future is because we absolutely need to make sure
// the call to finishImageWriter returns before allowing the TSK data structures to be freed
// during case close.
Future<?> finishTask = Executors.newSingleThreadExecutor().submit(() -> {
numFinishJobsInProgress.incrementAndGet();
finishTask = Executors.newSingleThreadExecutor().submit(() -> {
try{
SleuthkitJNI.finishImageWriter(image.getImageHandle());
SleuthkitJNI.finishImageWriter(imageHandle);
} catch (TskCoreException ex){
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
}
});
synchronized(currentTasksLock){
ImageWriter.this.finishTasksInProgress.add(finishTask);
}
// Wait for finishImageWriter to complete
@ -155,84 +184,75 @@ public class ImageWriter {
} catch (InterruptedException | ExecutionException ex){
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
}
numFinishJobsInProgress.decrementAndGet();
synchronized(currentTasksLock){
ImageWriter.this.finishTasksInProgress.remove(finishTask);
ImageWriter.this.imagesBeingFinished.remove(image.getImageHandle());
unsubscribeFromEvents();
if(doUI){
// Some of these may be called twice if the user closes the case
progressUpdateTask.cancel(true);
ImageWriter.this.progressUpdaters.remove(progressUpdateTask);
progressHandle.finish();
ImageWriter.this.progressBars.remove(progressHandle);
periodicTasksExecutor.shutdown();
}
isFinished = true;
}
logger.log(Level.INFO, String.format("Finished writing VHD image for %s", event.getDataSource().getName())); //NON-NLS
} catch (TskCoreException ex){
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
}
}).start();
} else {
logger.log(Level.SEVERE, "DataSourceAnalysisCompletedEvent did not contain a dataSource object"); //NON-NLS
}
}
}
});
}
listenerStarted = true;
logger.log(Level.INFO, String.format("Finished writing VHD image for %s", dataSourceName)); //NON-NLS
}
/**
* Add a data source ID to the list of images to run finishImage on.
* Also starts the listener if needed.
* @param id The dataSource/Image ID
* Tell the finishImage process to stop and wait for it to do so.
*/
public void addDataSourceId(Long id){
startListener();
synchronized(dataSourceIdsLock){
dataSourceIds.add(id);
}
}
/**
* Stop any open progress update task, finish the progress bars, and tell
* the finishImage process to stop
*/
public void close(){
private void close(){
synchronized(currentTasksLock){
isCancelled = true;
for(ScheduledFuture<?> task:ImageWriter.this.progressUpdaters){
task.cancel(true);
unsubscribeFromEvents();
// The case either got closed during ingest (before the startFinishImage got called)
// or an error occurred. If imageHandle is not null, we know that the first block of
// startFinishImage() completed so all the tasks have also been initialized.
if(imageHandle == null){
return;
}
for(Long handle:imagesBeingFinished){
SleuthkitJNI.cancelFinishImage(handle);
if(!isFinished){
SleuthkitJNI.cancelFinishImage(imageHandle);
logger.log(Level.SEVERE, "Case closed before VHD image could be finished"); //NON-NLS
}
// Wait for all the finish tasks to end
for(Future<?> task:ImageWriter.this.finishTasksInProgress){
// Wait for the finish task to end
try{
task.get();
finishTask.get();
} catch (InterruptedException | ExecutionException ex){
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
}
}
for(ProgressHandle progressHandle:ImageWriter.this.progressBars){
// Stop the progress bar update task.
// The thread from startFinishImage will also stop it
// once the task completes, but we have to make absolutely sure
// this gets done before the Sleuthkit data structures are freed.
// Since we've stopped the update task, we'll stop the associated progress
// bar now, too.
progressUpdateTask.cancel(true);
progressHandle.finish();
}
}
}
/**
* Get the number of images currently being finished.
* @return number of images in progress
*/
public static int numberOfJobsInProgress(){
return numFinishJobsInProgress.get();
}
/**
* Task to query the Sleuthkit processing to get the percentage done.
*/
private final class ProgressUpdateTask implements Runnable {
long imageHandle;
ProgressHandle progressHandle;
final long imageHandle;
final ProgressHandle progressHandle;
ProgressUpdateTask(ProgressHandle progressHandle, long imageHandle){
this.imageHandle = imageHandle;

View File

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

View File

@ -1,46 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.directorytree;
import org.openide.explorer.ExplorerManager;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
/**
* This class is used for the creation of all the children for the
* DataResultFilterNode that created in the DataResultFilterNode.java.
*
*/
class DataResultFilterChildren extends FilterNode.Children {
ExplorerManager sourceEm;
/**
* the constructor
*/
public DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
super(arg);
this.sourceEm = sourceEm;
}
@Override
protected Node copyNode(Node arg0) {
return new DataResultFilterNode(arg0, sourceEm);
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -23,6 +23,8 @@ import java.beans.PropertyVetoException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.openide.explorer.ExplorerManager;
@ -33,6 +35,7 @@ import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction;
import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType;
@ -58,6 +61,7 @@ import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.VirtualDirectory;
@ -67,11 +71,37 @@ import org.sleuthkit.datamodel.VirtualDirectory;
*/
public class DataResultFilterNode extends FilterNode {
private ExplorerManager sourceEm;
private static boolean filterKnownFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
private static boolean filterKnownFromViews = UserPreferences.hideKnownFilesInViewsTree();
private static boolean filterSlackFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree();
private static boolean filterSlackFromViews = UserPreferences.hideSlackFilesInViewsTree();
private final DisplayableItemNodeVisitor<List<Action>> getActionsDIV;
static {
UserPreferences.addChangeListener(new PreferenceChangeListener() {
@Override
public void preferenceChange(PreferenceChangeEvent evt) {
switch (evt.getKey()) {
case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE:
filterKnownFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
break;
case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE:
filterKnownFromViews = UserPreferences.hideKnownFilesInViewsTree();
break;
case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SRCS_TREE:
filterSlackFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree();
break;
case UserPreferences.HIDE_SLACK_FILES_IN_VIEWS_TREE:
filterSlackFromViews = UserPreferences.hideSlackFilesInViewsTree();
break;
}
}
});
}
private final DisplayableItemNodeVisitor<AbstractAction> getPreferredActionsDIV;
static private final DisplayableItemNodeVisitor<List<Action>> getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor();
private final DisplayableItemNodeVisitor<AbstractAction> getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor();
private final ExplorerManager sourceEm;
/**
*
@ -81,8 +111,17 @@ public class DataResultFilterNode extends FilterNode {
public DataResultFilterNode(Node node, ExplorerManager em) {
super(node, new DataResultFilterChildren(node, em));
this.sourceEm = em;
getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor();
getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor();
}
/**
*
* @param node Root node to be passed to DataResult viewers
* @param em ExplorerManager for component that is creating the node
*/
private DataResultFilterNode(Node node, ExplorerManager em, boolean filterKnown, boolean filterSlack) {
super(node, new DataResultFilterChildren(node, em, filterKnown, filterSlack));
this.sourceEm = em;
}
/**
@ -150,6 +189,64 @@ public class DataResultFilterNode extends FilterNode {
return propertySets;
}
/**
* This class is used for the creation of all the children for the
* DataResultFilterNode that created in the DataResultFilterNode.java.
*
*/
private static class DataResultFilterChildren extends FilterNode.Children {
private final ExplorerManager sourceEm;
private boolean filterKnown;
private boolean filterSlack;
/**
* the constructor
*/
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
super(arg);
switch (SelectionContext.getSelectionContext(arg)) {
case DATA_SOURCES:
filterSlack = filterSlackFromDataSources;
filterKnown = filterKnownFromDataSources;
break;
case VIEWS:
filterSlack = filterSlackFromViews;
filterKnown = filterKnownFromViews;
break;
default:
filterSlack = false;
filterKnown = false;
break;
}
this.sourceEm = sourceEm;
}
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm, boolean filterKnown, boolean filterSlack) {
super(arg);
this.filterKnown = filterKnown;
this.filterSlack = filterSlack;
this.sourceEm = sourceEm;
}
@Override
protected Node[] createNodes(Node key) {
AbstractFile file = key.getLookup().lookup(AbstractFile.class);
if (file != null) {
if (filterKnown && (file.getKnown() == TskData.FileKnown.KNOWN)) {
// Filter out child nodes that represent known files
return new Node[]{};
}
if (filterSlack && file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
// Filter out child nodes that represent slack files
return new Node[]{};
}
}
return new Node[]{new DataResultFilterNode(key, sourceEm, filterKnown, filterSlack)};
}
}
/**
* Uses the default nodes actions per node, adds some custom ones and
* returns them per visited node type

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2014 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,12 +18,10 @@
*/
package org.sleuthkit.autopsy.directorytree;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
@ -32,8 +30,7 @@ import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.AbstractContentNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
import org.sleuthkit.autopsy.ingest.RunIngestModulesDialog;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Directory;
@ -42,86 +39,83 @@ import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.VirtualDirectory;
/**
* This class sets the actions for the nodes in the directory tree and creates
* the children filter so that files and such are hidden from the tree.
*
* A node filter (decorator) that sets the actions for the nodes in the
* directory tree and wraps the node children with a
* DirectoryTreeFilterChildren.
*/
class DirectoryTreeFilterNode extends FilterNode {
private static final Action collapseAll = new CollapseAction(
NbBundle.getMessage(DirectoryTreeFilterNode.class, "DirectoryTreeFilterNode.action.collapseAll.text"));
private static final Logger logger = Logger.getLogger(DirectoryTreeFilterNode.class.getName());
private static final Action collapseAllAction = new CollapseAction(NbBundle.getMessage(DirectoryTreeFilterNode.class, "DirectoryTreeFilterNode.action.collapseAll.text"));
/**
* the constructor
* A node filter (decorator) that sets the actions for the nodes in the
* directory tree and wraps the node children with a
* DirectoryTreeFilterChildren.
*
* @param nodeToWrap The node to wrap.
* @param createChildren Whether to create the children of the wrapped node
* or treat it a a leaf node.
*/
DirectoryTreeFilterNode(Node arg, boolean createChildren) {
super(arg, DirectoryTreeFilterChildren.createInstance(arg, createChildren),
new ProxyLookup(Lookups.singleton(new OriginalNode(arg)),
arg.getLookup()));
DirectoryTreeFilterNode(Node nodeToWrap, boolean createChildren) {
super(nodeToWrap,
DirectoryTreeFilterChildren.createInstance(nodeToWrap, createChildren),
new ProxyLookup(Lookups.singleton(new OriginalNode(nodeToWrap)), nodeToWrap.getLookup()));
}
/**
* Gets the display name for the node, possibly including a child count in
* parentheses.
*
* @return The display name for the node.
*/
@Override
public String getDisplayName() {
final Node orig = getOriginal();
String name = orig.getDisplayName();
//do not show children counts for non content nodes
if (orig instanceof AbstractContentNode) {
//show only for file content nodes
AbstractFile file = getLookup().lookup(AbstractFile.class);
if (file != null) {
try {
final int numChildren = file.getChildrenCount();
/*
* Left-to-right marks here are necessary to keep the count
* and parens together for mixed right-to-left and
* left-to-right names.
*/
name = name + " \u200E(\u200E" + numChildren + ")\u200E"; //NON-NLS
// left-to-right marks here are necessary to keep the count and parens together
// for mixed right-to-left and left-to-right names
name = name + " \u200E(\u200E" + numChildren + ")\u200E";
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting children count to display for file: " + file, ex); //NON-NLS
}
}
}
return name;
}
/**
* Right click action for the nodes in the directory tree.
* Gets the context mneu (right click menu) actions for the node.
*
* @param popup
* @param context Whether to find actions for context meaning or for the
* node itself.
*
* @return
*/
@Override
public Action[] getActions(boolean popup) {
public Action[] getActions(boolean context) {
List<Action> actions = new ArrayList<>();
final Content content = this.getLookup().lookup(Content.class);
if (content != null) {
actions.addAll(DirectoryTreeFilterNode.getDetailActions(content));
actions.addAll(ExplorerNodeActionVisitor.getActions(content));
//extract dir action
Directory dir = this.getLookup().lookup(Directory.class);
if (dir != null) {
actions.add(ExtractAction.getInstance());
actions.add(new AbstractAction(
NbBundle.getMessage(this.getClass(), "DirectoryTreeFilterNode.action.runIngestMods.text")) {
@Override
public void actionPerformed(ActionEvent e) {
final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog(dir);
ingestDialog.display();
}
});
actions.add(new RunIngestModulesAction(dir));
}
final Image img = this.getLookup().lookup(Image.class);
VirtualDirectory virtualDirectory = this.getLookup().lookup(VirtualDirectory.class);
// determine if the virtualDireory is at root-level (Logical File Set).
final VirtualDirectory virtualDirectory = this.getLookup().lookup(VirtualDirectory.class);
boolean isRootVD = false;
if (virtualDirectory != null) {
try {
@ -132,48 +126,15 @@ class DirectoryTreeFilterNode extends FilterNode {
logger.log(Level.WARNING, "Error determining the parent of the virtual directory", ex); // NON-NLS
}
}
// 'run ingest' action and 'file search' action are added only if the
// selected node is img node or a root level virtual directory.
if (img != null || isRootVD) {
actions.add(new FileSearchAction(
NbBundle.getMessage(this.getClass(), "DirectoryTreeFilterNode.action.openFileSrcByAttr.text")));
actions.add(new AbstractAction(
NbBundle.getMessage(this.getClass(), "DirectoryTreeFilterNode.action.runIngestMods.text")) {
@Override
public void actionPerformed(ActionEvent e) {
final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog(Collections.<Content>singletonList(content));
ingestDialog.display();
}
});
actions.add(new FileSearchAction(NbBundle.getMessage(this.getClass(), "DirectoryTreeFilterNode.action.openFileSrcByAttr.text")));
actions.add(new RunIngestModulesAction(Collections.<Content>singletonList(content)));
}
}
//check if delete actions should be added
final Node orig = getOriginal();
//TODO add a mechanism to determine if DisplayableItemNode
if (orig instanceof DisplayableItemNode) {
actions.addAll(getDeleteActions((DisplayableItemNode) orig));
}
actions.add(collapseAll);
actions.add(collapseAllAction);
return actions.toArray(new Action[actions.size()]);
}
private static List<Action> getDeleteActions(DisplayableItemNode original) {
List<Action> actions = new ArrayList<>();
//actions.addAll(original.accept(getDeleteActionVisitor));
return actions;
}
private static List<Action> getDetailActions(Content c) {
List<Action> actions = new ArrayList<>();
actions.addAll(ExplorerNodeActionVisitor.getActions(c));
return actions;
}
//FIXME: this seems like a big hack -jm
public static class OriginalNode {

View File

@ -37,9 +37,9 @@
<Component id="backButton" min="-2" pref="26" max="-2" attributes="1"/>
<Component id="showRejectedCheckBox" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" min="-2" pref="838" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="854" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,7 +18,6 @@
*/
package org.sleuthkit.autopsy.directorytree;
import org.sleuthkit.autopsy.datamodel.EmptyNode;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
@ -62,15 +61,14 @@ import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.datamodel.DataSources;
import org.sleuthkit.autopsy.datamodel.DataSourcesNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
import org.sleuthkit.autopsy.datamodel.EmptyNode;
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType;
import org.sleuthkit.autopsy.datamodel.KeywordHits;
import org.sleuthkit.autopsy.datamodel.KnownFileFilterNode;
import org.sleuthkit.autopsy.datamodel.Reports;
import org.sleuthkit.autopsy.datamodel.Results;
import org.sleuthkit.autopsy.datamodel.ResultsNode;
import org.sleuthkit.autopsy.datamodel.RootContentChildren;
import org.sleuthkit.autopsy.datamodel.SlackFileFilterNode;
import org.sleuthkit.autopsy.datamodel.Tags;
import org.sleuthkit.autopsy.datamodel.Views;
import org.sleuthkit.autopsy.datamodel.ViewsNode;
@ -231,8 +229,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
.addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(showRejectedCheckBox))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 838, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 854, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
}// </editor-fold>//GEN-END:initComponents
@ -297,6 +295,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
* only, i.e. deserialization routines; otherwise you could get a
* non-deserialized instance. To obtain the singleton instance, use
* {@link #findInstance}.
*
* @return instance - the default instance
*/
public static synchronized DirectoryTreeTopComponent getDefault() {
if (instance == null) {
@ -308,6 +308,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
/**
* Obtain the DirectoryTreeTopComponent instance. Never call
* {@link #getDefault} directly!
*
* @return getDefault() - the default instance
*/
public static synchronized DirectoryTreeTopComponent findInstance() {
WindowManager winManager = WindowManager.getDefault();
@ -349,13 +351,18 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
// change the cursor to "waiting cursor" for this operation
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
if (Case.isCaseOpen()) {
Case currentCase = Case.getCurrentCase();
Case currentCase = null;
try {
currentCase = Case.getCurrentCase();
} catch (IllegalStateException ex) {
/*
* No open case.
*/
}
// close the top component if there's no image in this case
if (currentCase.hasData() == false) {
//this.close();
((BeanTreeView) this.jScrollPane1).setRootVisible(false); // hide the root
if (null == currentCase || currentCase.hasData() == false) {
((TreeView) this.jScrollPane1).setRootVisible(false); // hide the root
} else {
// if there's at least one image, load the image and open the top component
List<Object> items = new ArrayList<>();
@ -395,7 +402,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
em.setRootContext(root);
em.getRootContext().setName(currentCase.getName());
em.getRootContext().setDisplayName(currentCase.getName());
((BeanTreeView) this.jScrollPane1).setRootVisible(false); // hide the root
((TreeView) this.jScrollPane1).setRootVisible(false); // hide the root
// Reset the forward and back lists because we're resetting the root context
resetHistory();
@ -434,13 +441,12 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
if (childNodes.getNodesCount() > 0) {
try {
em.setSelectedNodes(new Node[]{childNodes.getNodeAt(0)});
} catch (Exception ex) {
} catch (PropertyVetoException ex) {
LOGGER.log(Level.SEVERE, "Error setting default selected node.", ex); //NON-NLS
}
}
}
}
} finally {
this.setCursor(null);
}
@ -490,7 +496,12 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
@Override
public boolean canClose() {
return !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image in this case
/*
* Only allow the main tree view in the left side of the main window to
* be closed if there is no opne case or the open case has no data
* sources.
*/
return !Case.isCaseOpen() || Case.getCurrentCase().hasData() == false;
}
/**
@ -536,7 +547,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (RuntimeProperties.coreComponentsAreActive()) {
if (RuntimeProperties.runningWithGUI()) {
String changed = evt.getPropertyName();
if (changed.equals(Case.Events.CURRENT_CASE.toString())) { // changed current case
// When a case is closed, the old value of this property is the
@ -643,22 +654,17 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
//set node, wrap in filter node first to filter out children
Node drfn = new DataResultFilterNode(originNode, DirectoryTreeTopComponent.this.em);
Node kffn = new KnownFileFilterNode(drfn, KnownFileFilterNode.getSelectionContext(originNode));
Node sffn = new SlackFileFilterNode(kffn, SlackFileFilterNode.getSelectionContext(originNode));
// Create a TableFilterNode with knowledge of the node's type to allow for column order settings
if (FileTypesByMimeType.isEmptyMimeTypeNode(originNode)) {
//Special case for when File Type Identification has not yet been run and
//there are no mime types to populate Files by Mime Type Tree
if (FileTypesByMimeType.isEmptyMimeTypeNode(originNode)) {
EmptyNode emptyNode = new EmptyNode(Bundle.DirectoryTreeTopComponent_emptyMimeNode_text());
Node emptyDrfn = new DataResultFilterNode(emptyNode, DirectoryTreeTopComponent.this.em);
Node emptyKffn = new KnownFileFilterNode(emptyDrfn, KnownFileFilterNode.getSelectionContext(emptyNode));
Node emptySffn = new SlackFileFilterNode(emptyKffn, SlackFileFilterNode.getSelectionContext(originNode));
dataResult.setNode(new TableFilterNode(emptySffn, true, "This Node Is Empty")); //NON-NLS
dataResult.setNode(new TableFilterNode(emptyNode, true, "This Node Is Empty")); //NON-NLS
} else if (originNode instanceof DisplayableItemNode) {
dataResult.setNode(new TableFilterNode(sffn, true, ((DisplayableItemNode) originNode).getItemType()));
dataResult.setNode(new TableFilterNode(drfn, true, ((DisplayableItemNode) originNode).getItemType()));
} else {
dataResult.setNode(new TableFilterNode(sffn, true));
dataResult.setNode(new TableFilterNode(drfn, true));
}
String displayName = "";
@ -667,7 +673,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
try {
displayName = content.getUniquePath();
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: " + originNode); //NON-NLS
LOGGER.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: {0}", originNode); //NON-NLS
}
} else if (originNode.getLookup().lookup(String.class) != null) {
displayName = originNode.getLookup().lookup(String.class);
@ -799,7 +805,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
* Set the selected node using a path to a previously selected node.
*
* @param previouslySelectedNodePath Path to a previously selected node.
* @param rootNodeName Name of the root node to match, may be null.
* @param rootNodeName Name of the root node to match, may be
* null.
*/
private void setSelectedNode(final String[] previouslySelectedNodePath, final String rootNodeName) {
if (previouslySelectedNodePath == null) {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -34,7 +34,7 @@ import org.openide.util.Lookup;
iconBase = "org/sleuthkit/autopsy/directorytree/external-viewer-rules-32x32.png",
keywords = "#OptionsCategory_Keywords_ExternalViewer",
keywordsCategory = "ExternalViewer",
position = 9
position = 11
)
public final class ExternalViewerOptionsPanelController extends OptionsPanelController {

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.directorytree;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import static org.sleuthkit.autopsy.directorytree.Bundle.*;
@NbBundle.Messages({"SelectionContext.dataSources=Data Sources",
"SelectionContext.views=Views"})
enum SelectionContext {
DATA_SOURCES(SelectionContext_dataSources()),
VIEWS(SelectionContext_views()),
OTHER(""); // Subnode of another node.
private final String displayName;
private SelectionContext(String displayName) {
this.displayName = displayName;
}
public static SelectionContext getContextFromName(String name) {
if (name.equals(DATA_SOURCES.getName())) {
return DATA_SOURCES;
} else if (name.equals(VIEWS.getName())) {
return VIEWS;
} else {
return OTHER;
}
}
private String getName() {
return displayName;
}
/**
* Get the selection context of a Node in the DirectoryTree.
*
* @param n
*
* @return
*/
public static SelectionContext getSelectionContext(Node n) {
if (n == null || n.getParentNode() == null) {
// Parent of root node or root node. Occurs during case open / close.
return SelectionContext.OTHER;
} else if (n.getParentNode().getParentNode() == null) {
// One level below root node. Should be one of DataSources, Views, or Results
return SelectionContext.getContextFromName(n.getDisplayName());
} else {
return getSelectionContext(n.getParentNode());
}
}
}

View File

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

View File

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

View File

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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -23,7 +23,6 @@ IngestJob.progress.fileIngest.displayName=Analyzing files from {0}
IngestJob.progress.fileIngest.cancelMessage=Waiting for {0} on {1}
IngestJob.progress.cancelling={0} (Cancelling...)
IngestJob.cancellationDialog.title=Cancel Ingest
IngestDialog.title.text=Run Ingest Modules
IngestDialog.startButton.title=Start
IngestDialog.closeButton.title=Close
IngestManager.moduleErr=Module Error
@ -114,3 +113,13 @@ IngestJobSettingsPanel.globalSettingsButton.actionCommand=Advanced
IngestJobSettingsPanel.globalSettingsButton.text=Global Settings
IngestJobSettingsPanel.pastJobsButton.text=History
IngestJobSettingsPanel.fileIngestFilterLabel.text=Run ingest modules on:
OptionsCategory_Name_IngestOptions=Ingest
OptionsCategory_Keywords_IngestOptions=Ingest
IngestSettingsPanel.jLabelProcessTimeOutUnits.text=hour(s)
IngestSettingsPanel.jFormattedTextFieldProcTimeOutHrs.text=60
IngestSettingsPanel.jCheckBoxEnableProcTimeout.text=
IngestSettingsPanel.jLabelSetProcessTimeOut.text=Enable timeout to allow modules to automatically terminate after a set amount of time:
IngestSettingsPanel.restartRequiredLabel.text=For this computer, a maximum of {0} file ingest threads should be used. Application restart required to take effect.
IngestSettingsPanel.jLabelNumThreads.text=Number of threads to use for file ingest:
IngestSettingsPanel.ingestWarningLabel.text=Ingest is ongoing, some settings will be unavailable until it finishes.
ProfileSettingsPanel.ingestWarningLabel.text=Ingest is ongoing, some settings will be unavailable until it finishes.

View File

@ -2,7 +2,6 @@ CTL_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8
HINT_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8\u30a6\u30a3\u30f3\u30c9\u30a6
IngestDialog.closeButton.title=\u9589\u3058\u308b
IngestDialog.startButton.title=\u958b\u59cb
IngestDialog.title.text=\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8
IngestJob.progress.cancelling={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09
IngestJob.progress.dataSourceIngest.displayName={1}\u306e{0}
IngestJob.progress.fileIngest.displayName={0}\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u4e2d
@ -111,3 +110,9 @@ IngestJob.cancelReason.outOfDiskSpace.text=\u30c7\u30a3\u30b9\u30af\u30b9\u30da\
IngestJob.cancelReason.caseClosed.text=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u307e\u3057\u305f
IngestJobSettingsPanel.globalSettingsButton.actionCommand=\u30a2\u30c9\u30d0\u30f3\u30b9
IngestJobSettingsPanel.globalSettingsButton.text=\u30a2\u30c9\u30d0\u30f3\u30b9
IngestSettingsPanel.jLabelNumThreads.text=\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306b\u4f7f\u7528\u3059\u308b\u30b9\u30ec\u30c3\u30c9\u6570\uff1a
IngestSettingsPanel.jLabelProcessTimeOutUnits.text=\u6642\u9593
IngestSettingsPanel.jLabelSetProcessTimeOut.text=\u4e00\u5b9a\u306e\u6642\u9593\u304c\u904e\u304e\u305f\u5f8c\u306b\u81ea\u52d5\u7684\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u505c\u6b62\u3067\u304d\u308b\u3088\u3046\u306b\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u3092\u6709\u52b9\u5316\uff1a
IngestSettingsPanel.restartRequiredLabel.text=\u3053\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u30fc\u3067\u306f\u6700\u5927{0}\u306e\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b9\u30ec\u30c3\u30c9\u3092\u4f7f\u7528\u3059\u3079\u304d\u3067\u3059\u3002\u6709\u52b9\u306b\u3059\u308b\u306b\u306f\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u3067\u3059\u3002
IngestSettingsPanel.ingestWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u3067\u3059\u3002\u5b8c\u4e86\u3059\u308b\u307e\u3067\u4e00\u90e8\u306e\u8a2d\u5b9a\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002
ProfileSettingsPanel.ingestWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u3067\u3059\u3002\u5b8c\u4e86\u3059\u308b\u307e\u3067\u4e00\u90e8\u306e\u8a2d\u5b9a\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -52,13 +52,13 @@ public class IngestJobSettings {
private static final String ENABLED_MODULES_KEY = "Enabled_Ingest_Modules"; //NON-NLS
private static final String DISABLED_MODULES_KEY = "Disabled_Ingest_Modules"; //NON-NLS
private static final String LAST_FILE_INGEST_FILTER_KEY = "Last_File_Ingest_Filter";
private static final String LAST_FILE_INGEST_FILTER_KEY = "Last_File_Ingest_Filter"; //NON-NLS
private static final String MODULE_SETTINGS_FOLDER = "IngestModuleSettings"; //NON-NLS
private static final String MODULE_SETTINGS_FOLDER_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), IngestJobSettings.MODULE_SETTINGS_FOLDER).toAbsolutePath().toString();
private static final String MODULE_SETTINGS_FILE_EXT = ".settings"; //NON-NLS
private static final Logger LOGGER = Logger.getLogger(IngestJobSettings.class.getName());
private FilesSet fileIngestFilter;
private final String executionContext;
private String executionContext;
private final IngestType ingestType;
private String moduleSettingsFolderPath;
private static final CharSequence pythonModuleSettingsPrefixCS = "org.python.proxies.".subSequence(0, "org.python.proxies.".length() - 1); //NON-NLS
@ -66,15 +66,15 @@ public class IngestJobSettings {
private final List<String> warnings;
/**
* Gets the last selected FileIngestFilter saved in settings which is represented
* by a FilesSet, if the last selected filter is null
* the default filter will be returned.
* Gets the last selected FileIngestFilter saved in settings which is
* represented by a FilesSet, if the last selected filter is null the
* default filter will be returned.
*
* @return FilesSet which represents the FileIngestFilter
*/
FilesSet getFileIngestFilter() {
if (fileIngestFilter==null){
fileIngestFilter=FilesSetsManager.getDefaultFilter();
if (fileIngestFilter == null) {
fileIngestFilter = FilesSetsManager.getDefaultFilter();
}
return fileIngestFilter;
}
@ -111,7 +111,7 @@ public class IngestJobSettings {
/**
* Constructs an ingest job settings object for a given execution context.
* Examples of execution contexts include the add data source wizard and the
* run ingest modules dialog. Different execution conterxts may have
* run ingest modules dialog. Different execution contexts may have
* different ingest job settings.
*
* @param executionContext The ingest execution context identifier.
@ -128,7 +128,7 @@ public class IngestJobSettings {
/**
* Constructs an ingest job settings object for a given context. Examples of
* execution contexts include the add data source wizard and the run ingest
* modules dialog. Different execution conterxts may have different ingest
* modules dialog. Different execution contexts may have different ingest
* job settings.
*
* @param context The context identifier string.
@ -157,10 +157,23 @@ public class IngestJobSettings {
this.store();
}
/**
* Saves the settings with a new context name removing the old profile
* folder
*
* @param executionContext will be used to name the new folder for storing
* the settings
*/
void saveAs(String executionContext) {
this.executionContext = executionContext;
this.createSavedModuleSettingsFolder();
this.store();
}
/**
* Gets the ingest execution context identifier. Examples of execution
* contexts include the add data source wizard and the run ingest modules
* dialog. Different execution conterxts may have different ingest job
* dialog. Different execution contexts may have different ingest job
* settings.
*
* @return The execution context identifier.
@ -246,6 +259,18 @@ public class IngestJobSettings {
return Paths.get(IngestJobSettings.MODULE_SETTINGS_FOLDER_PATH, executionContext);
}
/**
* Returns the path to the ingest module settings folder from a static
* manner.
*
* @param context specify the context of the folder you wish to get
*
* @return path to the module settings folder
*/
static Path getSavedModuleSettingsFolder(String context) {
return Paths.get(IngestJobSettings.MODULE_SETTINGS_FOLDER_PATH, context);
}
/**
* Creates the folder for saving the individual ingest module settings part
* of these ingest job settings.
@ -292,8 +317,8 @@ public class IngestJobSettings {
* Get the enabled/disabled ingest modules settings for this context. By
* default, all loaded modules are enabled.
*/
HashSet<String> enabledModuleNames = getModulesNamesFromSetting(IngestJobSettings.ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(loadedModuleNames));
HashSet<String> disabledModuleNames = getModulesNamesFromSetting(IngestJobSettings.DISABLED_MODULES_KEY, ""); //NON-NLS
HashSet<String> enabledModuleNames = getModulesNamesFromSetting(executionContext, IngestJobSettings.ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(loadedModuleNames));
HashSet<String> disabledModuleNames = getModulesNamesFromSetting(executionContext, IngestJobSettings.DISABLED_MODULES_KEY, ""); //NON-NLS
/**
* Check for missing modules and create warnings if any are found.
@ -352,9 +377,9 @@ public class IngestJobSettings {
ModuleSettings.setConfigSetting(this.executionContext, IngestJobSettings.LAST_FILE_INGEST_FILTER_KEY, FilesSetsManager.getDefaultFilter().getName());
}
try {
Map<String,FilesSet> fileIngestFilters = FilesSetsManager.getInstance()
Map<String, FilesSet> fileIngestFilters = FilesSetsManager.getInstance()
.getCustomFileIngestFilters();
for (FilesSet fSet : FilesSetsManager.getStandardFileIngestFilters()){
for (FilesSet fSet : FilesSetsManager.getStandardFileIngestFilters()) {
fileIngestFilters.put(fSet.getName(), fSet);
}
this.fileIngestFilter = fileIngestFilters.get(ModuleSettings.getConfigSetting(
@ -373,12 +398,12 @@ public class IngestJobSettings {
*
* @return The list of module names associated with the key.
*/
private HashSet<String> getModulesNamesFromSetting(String key, String defaultSetting) {
if (ModuleSettings.settingExists(this.executionContext, key) == false) {
ModuleSettings.setConfigSetting(this.executionContext, key, defaultSetting);
private static HashSet<String> getModulesNamesFromSetting(String context, String key, String defaultSetting) {
if (ModuleSettings.settingExists(context, key) == false) {
ModuleSettings.setConfigSetting(context, key, defaultSetting);
}
HashSet<String> moduleNames = new HashSet<>();
String modulesSetting = ModuleSettings.getConfigSetting(this.executionContext, key);
String modulesSetting = ModuleSettings.getConfigSetting(context, key);
if (!modulesSetting.isEmpty()) {
String[] settingNames = modulesSetting.split(", ");
for (String name : settingNames) {
@ -406,6 +431,18 @@ public class IngestJobSettings {
return moduleNames;
}
/**
* Get a set which contains all the names of enabled modules for the
* specified context.
*
* @param context -the execution context (profile name) to check
*
* @return the names of the enabled modules
*/
static List<String> getEnabledModules(String context) {
return new ArrayList<>(getModulesNamesFromSetting(context, ENABLED_MODULES_KEY, ""));
}
/**
* Determines if the moduleSettingsFilePath is that of a serialized jython
* instance. Serialized Jython instances (settings saved on the disk)
@ -489,8 +526,8 @@ public class IngestJobSettings {
disabledModuleNames.add(moduleName);
}
}
ModuleSettings.setConfigSetting(this.executionContext, ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(enabledModuleNames));
ModuleSettings.setConfigSetting(this.executionContext, DISABLED_MODULES_KEY, makeCommaSeparatedValuesList(disabledModuleNames));
ModuleSettings.setConfigSetting(this.executionContext, IngestJobSettings.ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(enabledModuleNames));
ModuleSettings.setConfigSetting(this.executionContext, IngestJobSettings.DISABLED_MODULES_KEY, makeCommaSeparatedValuesList(disabledModuleNames));
/**
* Save the last used File Ingest Filter setting for this context.

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -185,6 +185,10 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
pastJobsButton.setEnabled(!dataSources.isEmpty() && !ingestJobs.isEmpty());
}
void setPastJobsButtonVisible(boolean isVisible) {
pastJobsButton.setVisible(isVisible);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always

View File

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

View File

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

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="tabbedPane" pref="824" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="tabbedPane" pref="543" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JTabbedPane" name="tabbedPane">
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,225 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.ingest;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSetDefsPanel;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSetDefsPanel.PANEL_TYPE;
/**
* Global options panel for keyword searching.
*/
public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel {
@NbBundle.Messages({"IngestOptionsPanel.settingsTab.text=Settings",
"IngestOptionsPanel.settingsTab.toolTipText=Settings regarding resources available to ingest.",
"IngestOptionsPanel.fileFiltersTab.text=File Filters",
"IngestOptionsPanel.fileFiltersTab.toolTipText=Settings for creating and editing ingest file filters.",
"IngestOptionsPanel.profilesTab.text=Profiles",
"IngestOptionsPanel.profilesTab.toolTipText=Settings for creating and editing profiles."})
private FilesSetDefsPanel filterPanel;
private final static int INDEX_OF_FILTER_PANEL = 0;
private IngestSettingsPanel settingsPanel;
private final static int INDEX_OF_SETTINGS_PANEL = 2;
private ProfileSettingsPanel profilePanel;
private final static int INDEX_OF_PROFILE_PANEL = 1;
/**
* This panel implements a property change listener that listens to ingest
* job events so it can disable the buttons on the panel if ingest is
* running. This is done to prevent changes to user-defined types while the
* type definitions are in use.
*/
IngestJobEventPropertyChangeListener ingestJobEventsListener;
public IngestOptionsPanel() {
initComponents();
customizeComponents();
}
private void customizeComponents() {
filterPanel = new FilesSetDefsPanel(PANEL_TYPE.FILE_INGEST_FILTERS);
settingsPanel = new IngestSettingsPanel();
profilePanel = new ProfileSettingsPanel();
tabbedPane.insertTab(NbBundle.getMessage(IngestOptionsPanel.class, "IngestOptionsPanel.fileFiltersTab.text"), null,
filterPanel, NbBundle.getMessage(IngestOptionsPanel.class, "IngestOptionsPanel.fileFiltersTab.toolTipText"), INDEX_OF_FILTER_PANEL);
tabbedPane.insertTab(NbBundle.getMessage(IngestOptionsPanel.class, "IngestOptionsPanel.profilesTab.text"), null,
profilePanel, NbBundle.getMessage(IngestOptionsPanel.class, "IngestOptionsPanel.profilesTab.toolTipText"), INDEX_OF_PROFILE_PANEL);
tabbedPane.insertTab(NbBundle.getMessage(IngestOptionsPanel.class, "IngestOptionsPanel.settingsTab.text"), null,
settingsPanel, NbBundle.getMessage(IngestOptionsPanel.class, "IngestOptionsPanel.settingsTab.toolTipText"), INDEX_OF_SETTINGS_PANEL);
//Listener for when tabbed panes are switched, because we can have two file filter definitions panels open at the same time
//we may wind up in a situation where the user has created and saved one in the profiles panel
//so we need to refresh the filterPanel in those cases before proceeding.
tabbedPane.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (e.getSource() instanceof JTabbedPane) {
//because we can have two filterPanels open at the same time
//we need to save the settings when we change tabs otherwise
//they could be overwritten with out of date
if (tabbedPane.getSelectedIndex() == INDEX_OF_FILTER_PANEL) {
filterPanel.load();
}
else {
filterPanel.saveSettings();
}
}
}
});
addIngestJobEventsListener();
enableTabs();
}
/**
* Add a property change listener that listens to ingest job events to
* disable the buttons on the panel if ingest is running. This is done to
* prevent changes to user-defined types while the type definitions are in
* use.
*/
private void addIngestJobEventsListener() {
ingestJobEventsListener = new IngestJobEventPropertyChangeListener();
IngestManager.getInstance().addIngestJobEventListener(ingestJobEventsListener);
}
/**
* A property change listener that listens to ingest job events.
*/
private class IngestJobEventPropertyChangeListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
enableTabs();
}
});
}
}
/**
* Disables tabs and options inside of tabs during Ingest, and re-enables
* them after Ingest is complete or cancelled.
*/
private void enableTabs() {
boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning();
tabbedPane.setEnabled(!ingestIsRunning);
settingsPanel.enableButtons(!ingestIsRunning);
profilePanel.enableButtons(!ingestIsRunning);
filterPanel.enableButtons(!ingestIsRunning);
}
/**
* @inheritDoc
*/
@Override
public void addPropertyChangeListener(PropertyChangeListener l) {
filterPanel.addPropertyChangeListener(l);
settingsPanel.addPropertyChangeListener(l);
profilePanel.addPropertyChangeListener(l);
}
/**
* @inheritDoc
*/
@Override
public void removePropertyChangeListener(PropertyChangeListener l) {
filterPanel.removePropertyChangeListener(l);
settingsPanel.removePropertyChangeListener(l);
profilePanel.removePropertyChangeListener(l);
}
/**
* @inheritDoc
*/
@Override
public void saveSettings() {
filterPanel.store();
settingsPanel.store();
}
/**
* @inheritDoc
*/
@Override
public void store() {
saveSettings();
}
/**
* @inheritDoc
*/
@Override
public void load() {
filterPanel.load();
settingsPanel.load();
profilePanel.load();
}
boolean valid() {
return true;
}
/**
* Method called when the cancel button is clicked.
*/
void cancel() {
//doesn't need to do anything
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
tabbedPane = new javax.swing.JTabbedPane();
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(tabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 824, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(tabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 543, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JTabbedPane tabbedPane;
// End of variables declaration//GEN-END:variables
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2016 Basis Technology Corp.
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.modules.interestingitems;
package org.sleuthkit.autopsy.ingest;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
@ -26,29 +26,22 @@ import javax.swing.SwingUtilities;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.coreutils.Logger;
@OptionsPanelController.TopLevelRegistration(
categoryName = "#OptionsCategory_Name_FileIngestFilterDefinitions",
categoryName = "#OptionsCategory_Name_IngestOptions",
iconBase = "org/sleuthkit/autopsy/images/file_ingest_filter32x32.png",
keywords = "#OptionsCategory_Keywords_FileIngestFilterDefinitions",
keywordsCategory = "FileIngestFilterDefinitions",
position = 7
)
position = 2,
keywords = "#OptionsCategory_Keywords_IngestOptions",
keywordsCategory = "IngestOptions")
/**
* Class for creating an FilesSetDefsPanel which will be used for configuring
* the FileIngestFilter.
*/
public final class FileIngestFilterDefsOptionsPanelController extends OptionsPanelController {
public class IngestOptionsPanelController extends OptionsPanelController {
private FilesSetDefsPanel panel;
private IngestOptionsPanel panel;
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private boolean changed;
private static final Logger LOGGER = Logger.getLogger(FileIngestFilterDefsOptionsPanelController.class.getName());
/**
* Component should load its data here.
* @inheritDoc
*/
@Override
public void update() {
@ -56,11 +49,28 @@ public final class FileIngestFilterDefsOptionsPanelController extends OptionsPan
changed = false;
}
/**
* Get the IngestOptionsPanel which is contained inside this controller.
*
* @return panel
*/
private IngestOptionsPanel getPanel() {
if (panel == null) {
panel = new IngestOptionsPanel();
panel.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(OptionsPanelController.PROP_CHANGED)) {
changed();
}
}
});
}
return panel;
}
/**
* This method is called when both the Ok and Apply buttons are pressed. It
* applies to any of the panels that have been opened in the process of
* using the options pane.
* @inheritDoc
*/
@Override
public void applyChanges() {
@ -76,71 +86,59 @@ public final class FileIngestFilterDefsOptionsPanelController extends OptionsPan
}
/**
* This method is called when the Cancel button is pressed. It applies to
* any of the panels that have been opened in the process of using the
* options pane.
* @inheritDoc
*/
@Override
public void cancel() {
// need not do anything special, if no changes have been persisted yet
}
@Override
public boolean isValid() {
return true;
getPanel().cancel();
}
/**
* Used to determine whether any changes have been made to this controller's
* panel.
*
* @return Whether or not a change has been made.
* @inheritDoc
*/
@Override
public boolean isValid() {
return getPanel().valid();
}
/**
* @inheritDoc
*/
@Override
public boolean isChanged() {
return changed;
}
/**
* @inheritDoc
*/
@Override
public JComponent getComponent(Lookup lkp) {
return getPanel();
}
/**
* @inheritDoc
*/
@Override
public HelpCtx getHelpCtx() {
return null;
}
/**
* @inheritDoc
*/
@Override
public JComponent getComponent(Lookup masterLookup) {
return getPanel();
}
@Override
public void addPropertyChangeListener(PropertyChangeListener l) {
pcs.addPropertyChangeListener(l);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener l) {
pcs.removePropertyChangeListener(l);
public void addPropertyChangeListener(PropertyChangeListener pl) {
pcs.addPropertyChangeListener(pl);
}
/**
* Creates an interestingItemsDefPanel that will be labeled to indicate it
* is for File Ingest Filter settings
*
* @return an FilesSetDefsPanel which has text and fields modified to
* indicate it is for File Ingest Filtering.
* @inheritDoc
*/
private FilesSetDefsPanel getPanel() {
if (panel == null) {
panel = new FilesSetDefsPanel(FilesSetDefsPanel.PANEL_TYPE.FILE_INGEST_FILTERS);
panel.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(OptionsPanelController.PROP_CHANGED)) {
changed();
}
}
});
}
return panel;
public void removePropertyChangeListener(PropertyChangeListener pl) {
pcs.removePropertyChangeListener(pl);
}
void changed() {
@ -150,5 +148,4 @@ public final class FileIngestFilterDefsOptionsPanelController extends OptionsPan
}
pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
}
}

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