Bug fixes for Case actions

This commit is contained in:
Richard Cordovano 2017-01-24 00:36:36 -05:00
parent 938edeb0ab
commit e7ecd2e756
13 changed files with 260 additions and 292 deletions

View File

@ -30,7 +30,8 @@ import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* An action wired in to the Case/Exit menu item.
* 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)

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014-2017 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,32 +35,37 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Action to open the log subdirectory for the currently open case, or the log
* subdirectory of the user directory if there is no current case.
* The action associated with the Help/Open Log Folder menu item. It opens a
* file explorer window for the log subdirectory for the currently open case, or
* the log subdirectory of the user directory if there is no current case.
*/
@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 {
private static final Logger LOGGER = Logger.getLogger(OpenLogFolderAction.class.getName());
private static final Logger logger = Logger.getLogger(OpenLogFolderAction.class.getName());
@Override
public void actionPerformed(ActionEvent e) {
File logDir;
try {
Case currentCase = Case.getCurrentCase();
logDir = new File(currentCase.getLogDirectoryPath());
} catch (IllegalStateException ex) {
/*
* No open case.
*/
if (Case.isCaseOpen()) {
try {
Case currentCase = Case.getCurrentCase();
logDir = new File(currentCase.getLogDirectoryPath());
} catch (IllegalStateException ex) {
/*
* The case
*/
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");
}
try {
if (logDir.exists() == false) {
LOGGER.log(Level.SEVERE, String.format("The log subdirectory %s does not exist", logDir));
logger.log(Level.SEVERE, String.format("The log subdirectory %s does not exist", logDir));
NotifyDescriptor notifyDescriptor = new NotifyDescriptor.Message(
NbBundle.getMessage(this.getClass(), "OpenLogFolder.error1", logDir.getAbsolutePath()),
NotifyDescriptor.ERROR_MESSAGE);
@ -69,12 +74,12 @@ public final class OpenLogFolderAction implements ActionListener {
Desktop.getDesktop().open(logDir);
}
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, String.format("Could not open log directory %s", logDir), ex);
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

@ -35,16 +35,19 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Action to open the subdirectory of the current case that contains 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.
*/
@ActionRegistration(displayName = "#CTL_OpenOutputFolder", iconInMenu = true, lazy = true)
@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 Logger LOGGER = Logger.getLogger(OpenOutputFolderAction.class.getName());
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(OpenOutputFolderAction.class.getName());
@Override
public void performAction() {
@ -56,7 +59,7 @@ public final class OpenOutputFolderAction extends CallableSystemAction {
try {
Desktop.getDesktop().open(outputDir);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, String.format("Failed to open output folder %s", outputDir), ex); //NON-NLS
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);
@ -67,19 +70,14 @@ public final class OpenOutputFolderAction extends CallableSystemAction {
DialogDisplayer.getDefault().notify(descriptor);
}
} catch (IllegalStateException ex) {
LOGGER.log(Level.SEVERE, "OpenOutputFolderAction enabled with no current case", ex); //NON-NLS
logger.log(Level.SEVERE, "OpenOutputFolderAction enabled with no current case", ex); //NON-NLS
JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "OpenOutputFolder.noCaseOpen"));
}
}
@Override
public boolean isEnabled() {
try {
Case.getCurrentCase();
return true;
} catch (IllegalStateException ex) {
return false;
}
return Case.isCaseOpen();
}
@Override

View File

@ -1,15 +1,15 @@
/*
* 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");
* 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.
@ -29,19 +29,18 @@ 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.
*/
@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() {
@ -60,16 +59,11 @@ public final class ShowIngestProgressSnapshotAction extends CallableSystemAction
@Override
public boolean isEnabled() {
try {
Case.getCurrentCase();
return true;
} catch (IllegalStateException ex) {
return false;
}
return Case.isCaseOpen();
}
@Override
public boolean asynchronous() {
return false; // run on edt
return false;
}
}

View File

@ -128,9 +128,10 @@ public class Case {
/*
* The application name, used to make the title of the main application
* window [application] name when there is no open case and [application
* name]-[curent case display name] when there is an open case. Initialized
* by getting the main window title before a case has been opened.
* window [application name] when there is no open case and [curent case
* display name] - [application name] when there is an open case.
* Initialized by getting the main window title before a case has been
* opened.
*
* TODO (JIRA-2231): Make the application name a RuntimeProperties item set
* by Installers.
@ -749,9 +750,9 @@ public class Case {
if (RuntimeProperties.runningWithGUI()) {
progressIndicator = new ModalDialogProgressIndicator(
Bundle.Case_progressIndicatorTitle_closingCase(),
new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
Bundle.Case_progressIndicatorCancelButton_label(),
null,
new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
Bundle.Case_progressIndicatorCancelButton_label(),
null,
listener);
} else {
progressIndicator = new LoggingProgressIndicator();
@ -873,10 +874,10 @@ public class Case {
ProgressIndicator progressIndicator;
if (RuntimeProperties.runningWithGUI()) {
progressIndicator = new ModalDialogProgressIndicator(
Bundle.Case_progressIndicatorTitle_deletingCase(),
new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
Bundle.Case_progressIndicatorCancelButton_label(),
null,
Bundle.Case_progressIndicatorTitle_deletingCase(),
new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
Bundle.Case_progressIndicatorCancelButton_label(),
null,
listener);
} else {
progressIndicator = new LoggingProgressIndicator();
@ -891,7 +892,7 @@ public class Case {
* cannot be deleted if another node has it open.
*/
progressIndicator.start(Bundle.Case_progressMessage_acquiringLocks());
try (CoordinationService.Lock dirLock = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot()).tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, metadata.getCaseDatabasePath())) {
try (CoordinationService.Lock dirLock = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot()).tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, metadata.getCaseDirectory())) {
assert (null != dirLock);
/*
@ -1277,7 +1278,7 @@ public class Case {
CallableSystemAction.get(AddImageAction.class).setEnabled(true);
CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true);
CallableSystemAction.get(DeleteCurrentCaseAction.class).setEnabled(true);
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true);
CallableSystemAction.get(OpenTimelineAction.class).setEnabled(true);
/*
@ -1296,8 +1297,8 @@ public class Case {
}
/*
* Reset the main window title to be [application name] - [case
* name], instead of just the application name.
* Reset the main window title to be [curent case display name]
* - [application name], instead of just the application name.
*/
addCaseNameToMainWindowTitle(currentCase.getDisplayName());
});
@ -1323,7 +1324,7 @@ public class Case {
CallableSystemAction.get(AddImageAction.class).setEnabled(false);
CallableSystemAction.get(CaseCloseAction.class).setEnabled(false);
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false);
CallableSystemAction.get(DeleteCurrentCaseAction.class).setEnabled(false);
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false);
CallableSystemAction.get(OpenTimelineAction.class).setEnabled(false);
/*
@ -1334,7 +1335,7 @@ public class Case {
/*
* Reset the main window title to be just the application name,
* instead of [application name] - [case name].
* instead of [curent case display name] - [application name].
*/
Frame mainWindow = WindowManager.getDefault().getMainWindow();
mainWindow.setTitle(appName);
@ -1786,7 +1787,7 @@ public class Case {
/**
* Updates the case display name name.
*
*
* @param oldCaseName The old case name.
* @param oldPath The old path name.
* @param newCaseName The new case name.
@ -1873,10 +1874,21 @@ public class Case {
progressIndicator.progress(Bundle.Case_progressMessage_creatingCaseDatabase());
String dbName = null;
try {
if (caseType == CaseType.SINGLE_USER_CASE) {
dbName = Paths.get(caseDir, SINGLE_USER_CASE_DB_NAME).toString();
this.caseDb = SleuthkitCase.newCase(dbName);
} else if (caseType == CaseType.MULTI_USER_CASE) {
if (CaseType.SINGLE_USER_CASE == caseType) {
/*
* For single-user cases, the case database is a SQLite database
* with a fixed name and is physically located in the root of
* the case directory.
*/
dbName = SINGLE_USER_CASE_DB_NAME;
this.caseDb = SleuthkitCase.newCase(Paths.get(caseDir, SINGLE_USER_CASE_DB_NAME).toString());
} else if (CaseType.MULTI_USER_CASE == caseType) {
/*
* For multi-user cases, the case database is a PostgreSQL
* database with a name consiting of the case name with a time
* stamp suffix and is physically located on the database
* server.
*/
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
Date date = new Date();
dbName = caseName + "_" + dateFormat.format(date);
@ -1924,7 +1936,7 @@ public class Case {
try {
progressIndicator.progress(Bundle.Case_progressMessage_openingCaseDatabase());
if (CaseType.SINGLE_USER_CASE == metadata.getCaseType()) {
this.caseDb = SleuthkitCase.openCase(metadata.getCaseDatabasePath());
this.caseDb = SleuthkitCase.openCase(Paths.get(metadata.getCaseDirectory(), metadata.getCaseDatabaseName()).toString());
} else if (UserPreferences.getIsMultiUserModeEnabled()) {
try {
this.caseDb = SleuthkitCase.openCase(metadata.getCaseDatabaseName(), UserPreferences.getDatabaseConnectionInfo(), metadata.getCaseDirectory());

View File

@ -43,14 +43,13 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
/**
* An action to close the current case and pop up the start up window that
* allows a user to open another case.
* 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.
*/
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.casemodule.CaseCloseAction")
@ActionRegistration(displayName = "#CTL_CaseCloseAct", lazy = false)
@ActionReferences(value = {
@ActionReference(path = "Toolbars/Case", position = 104)
})
@ActionReferences(value = {@ActionReference(path = "Toolbars/Case", position = 104)})
public final class CaseCloseAction extends CallableSystemAction implements Presenter.Toolbar {
private static final long serialVersionUID = 1L;
@ -58,19 +57,20 @@ public final class CaseCloseAction extends CallableSystemAction implements Prese
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
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) {
@ -117,17 +117,17 @@ public final class CaseCloseAction extends CallableSystemAction implements Prese
}
/**
* This method does nothing. Use the "actionPerformed(ActionEvent e)"
* instead of this method.
* Closes the current case.
*/
@Override
public void performAction() {
actionPerformed(null);
}
/**
* Gets the name of this action. This may be presented as an item in a menu.
* Gets the action name.
*
* @return actionName
* @return The action name.
*/
@Override
public String getName() {
@ -135,9 +135,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() {
@ -145,9 +145,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

@ -19,9 +19,11 @@
package org.sleuthkit.autopsy.casemodule;
import java.awt.event.ActionEvent;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
@ -32,15 +34,16 @@ import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* An action to delete the current case.
* The action associated with the Delete button of the Case Properties panel. It
* deletes the current case.
*/
final class DeleteCurrentCaseAction extends CallableSystemAction {
final class CaseDeleteAction extends CallableSystemAction {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(DeleteCurrentCaseAction.class.getName());
private static final Logger logger = Logger.getLogger(CaseDeleteAction.class.getName());
DeleteCurrentCaseAction() { // Should pass in caller
putValue(Action.NAME, NbBundle.getMessage(DeleteCurrentCaseAction.class, "CTL_CaseDeleteAction"));
CaseDeleteAction() {
putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction"));
this.setEnabled(false);
}
@ -68,18 +71,34 @@ final class DeleteCurrentCaseAction extends CallableSystemAction {
null,
NotifyDescriptor.NO_OPTION));
if (null != response && DialogDescriptor.YES_OPTION == response) {
try {
Case.deleteCurrentCase();
} catch (CaseActionException 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);
}
// because the "Delete Case" button is in the "CaseProperties" window, we have to close that window when we delete the case.
CasePropertiesAction.closeCasePropertiesWindow();
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);
@ -92,7 +111,7 @@ final class DeleteCurrentCaseAction extends CallableSystemAction {
@Override
public String getName() {
return NbBundle.getMessage(DeleteCurrentCaseAction.class, "CTL_CaseDeleteAction");
return NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction");
}
@Override

View File

@ -54,11 +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 static final String SCHEMA_VERSION_TWO = "2";
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
@ -67,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
@ -78,7 +79,7 @@ public final class CaseMetadata {
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,16 +97,16 @@ public final class CaseMetadata {
* Constructs an object that provides access to the case metadata stored in
* a new case metadata file that is created using the supplied metadata.
*
* @param caseDirectory The case directory.
* @param caseType The type of 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 caseDirectory The case directory.
* @param caseType The type of 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.
*
* @throws CaseMetadataException If the new case metadata file cannot be
* created.
@ -117,7 +118,7 @@ public final class CaseMetadata {
this.caseDisplayName = caseDisplayName;
this.caseNumber = caseNumber;
this.examiner = examiner;
this.caseDatabase = caseDatabase;
this.caseDatabaseName = caseDatabase;
createdByVersion = Version.getVersion();
createdDate = CaseMetadata.DATE_FORMAT.format(new Date());
writeToFile();
@ -172,7 +173,7 @@ public final class CaseMetadata {
public String getCaseName() {
return caseName;
}
/**
* Gets the case display name.
*
@ -181,7 +182,7 @@ public final class CaseMetadata {
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.
@ -198,7 +199,7 @@ public final class CaseMetadata {
throw ex;
}
}
/**
* Gets the case number.
*
@ -218,32 +219,12 @@ 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();
}
}
/**
* 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.
*/
public String getCaseDatabasePath() throws UnsupportedOperationException {
if (caseType == Case.CaseType.SINGLE_USER_CASE) {
return caseDatabase;
} else {
throw new UnsupportedOperationException();
}
return caseDatabaseName;
}
/**
@ -260,8 +241,8 @@ public final class CaseMetadata {
this.textIndexName = oldIndexName;
throw ex;
}
}
}
/**
* Gets the text index name.
*
@ -383,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);
}
@ -444,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));
@ -451,10 +438,10 @@ 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.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_ELEMENT_NAME, true);
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, true);
}
@ -511,4 +498,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

@ -26,9 +26,9 @@ 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.
*
* IMPORTANT: Must be called in the Swing Event Dispatch Thread (EDT).
* 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.
*/
@ServiceProvider(service = CaseNewActionInterface.class)
public final class CaseNewAction extends CallableSystemAction implements CaseNewActionInterface {
@ -42,6 +42,7 @@ public final class CaseNewAction extends CallableSystemAction implements CaseNew
@Override
public void performAction() {
actionPerformed(null);
}
@Override

View File

@ -43,21 +43,25 @@ import org.sleuthkit.autopsy.coreutils.Version;
import org.sleuthkit.autopsy.ingest.IngestManager;
/**
* An action that opens an existing case. It is associated with the Case/Open
* menu item via the layer.xml file, with a toolbar button, and with a button on
* the startup window.
* 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.
*/
@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));
@ -127,7 +131,7 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
try {
get();
} catch (InterruptedException | ExecutionException ex) {
LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(),
@ -144,6 +148,7 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
@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
String title = NbBundle.getMessage(this.getClass(), "CasePropertiesAction.window.title");
popUpWindow = new JDialog((JFrame) WindowManager.getDefault().getMainWindow(), title, false);
try {
SwingUtilities.invokeLater(() -> {
if (null == casePropertiesDialog) {
String title = NbBundle.getMessage(this.getClass(), "CasePropertiesAction.window.title");
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

@ -200,9 +200,6 @@
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.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>

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,44 +32,15 @@ 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 {
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 {
initComponents();
caseNameTextField.setText(currentCase.getDisplayName());
@ -93,10 +59,10 @@ class CasePropertiesForm extends javax.swing.JPanel {
crDateField.setText(crDate);
caseDirField.setText(caseDir);
current = currentCase;
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());
}
@ -162,11 +128,6 @@ class CasePropertiesForm extends javax.swing.JPanel {
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);
}
});
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
@ -318,34 +279,36 @@ 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("|")) {
String errorMsg = NbBundle
.getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.msg");
JOptionPane.showMessageDialog(caller, errorMsg,
NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.title"),
JOptionPane.ERROR_MESSAGE);
} else {
// ask for the confirmation first
String confMsg = NbBundle
.getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.confMsg.msg", oldCaseName,
newCaseName);
NotifyDescriptor d = new NotifyDescriptor.Confirmation(confMsg,
NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.confMsg.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) {
// if user select "Yes"
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
{
if (newCaseName.contains("\\") || newCaseName.contains("/") || newCaseName.contains(":")
|| newCaseName.contains("*") || newCaseName.contains("?") || newCaseName.contains("\"")
|| newCaseName.contains("<") || newCaseName.contains(">") || newCaseName.contains("|")) {
String errorMsg = NbBundle
.getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.msg");
JOptionPane.showMessageDialog(caller, errorMsg,
NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.title"),
JOptionPane.ERROR_MESSAGE);
} else {
// ask for the confirmation first
String confMsg = NbBundle
.getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.confMsg.msg", oldCaseName,
newCaseName);
NotifyDescriptor d = new NotifyDescriptor.Confirmation(confMsg,
NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.confMsg.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) {
// if user select "Yes"
String oldPath = current.getCaseMetadata().getFilePath().toString();
try {
current.updateCaseName(oldCaseName, oldPath, newCaseName, oldPath);
} catch (CaseActionException ex) {
Logger.getLogger(CasePropertiesForm.class.getName()).log(Level.WARNING, "Error: problem updating case name.", ex); //NON-NLS
}
}
}
}
@ -353,13 +316,9 @@ class CasePropertiesForm extends javax.swing.JPanel {
}//GEN-LAST:event_updateCaseNameButtonActionPerformed
private void deleteCaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteCaseButtonActionPerformed
CallableSystemAction.get(DeleteCurrentCaseAction.class).actionPerformed(evt);
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;