This commit is contained in:
Tim McIver 2013-02-12 13:59:24 -05:00
commit ef14c0fa22

View File

@ -51,9 +51,9 @@ import org.sleuthkit.datamodel.*;
import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess; import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess;
/** /**
* Stores all information for a given case. Only a single case can * Stores all information for a given case. Only a single case can currently be
* currently be open at a time. Use getCurrentCase() to retrieve the * open at a time. Use getCurrentCase() to retrieve the object for the current
* object for the current case. * case.
*/ */
public class Case { public class Case {
@ -62,22 +62,21 @@ public class Case {
/** /**
* Property name that indicates the name of the current case has changed. * Property name that indicates the name of the current case has changed.
* Fired with the case is renamed, and when the current case is * Fired with the case is renamed, and when the current case is
* opened/closed/changed. The value is a String: the name of the case. * opened/closed/changed. The value is a String: the name of the case. The
* The empty string ("") is used for no open case. * empty string ("") is used for no open case.
*/ */
public static final String CASE_NAME = "caseName"; public static final String CASE_NAME = "caseName";
/** /**
* Property name that indicates the number of the current case has changed. * Property name that indicates the number of the current case has changed.
* Fired with the case number is changed. * Fired with the case number is changed. The value is an int: the number of
* The value is an int: the number of the case. * the case. -1 is used for no case number set.
* -1 is used for no case number set.
*/ */
public static final String CASE_NUMBER = "caseNumber"; public static final String CASE_NUMBER = "caseNumber";
/** /**
* Property name that indicates the examiner of the current case has changed. * Property name that indicates the examiner of the current case has
* Fired with the case examiner is changed. * changed. Fired with the case examiner is changed. The value is a String:
* The value is a String: the name of the examiner. * the name of the examiner. The empty string ("") is used for no examiner
* The empty string ("") is used for no examiner set. * set.
*/ */
public static final String CASE_EXAMINER = "caseExaminer"; public static final String CASE_EXAMINER = "caseExaminer";
/** /**
@ -93,11 +92,10 @@ public class Case {
*/ */
public static final String CASE_DEL_IMAGE = "removeImages"; public static final String CASE_DEL_IMAGE = "removeImages";
/** /**
* Property name that indicates the currently open case has changed. * Property name that indicates the currently open case has changed. The new
* The new value is the instance of the opened Case, or null if there is no * value is the instance of the opened Case, or null if there is no open
* open case. * case. The old value is the instance of the closed Case, or null if there
* The old value is the instance of the closed Case, or null if there was no * was no open case.
* open case.
*/ */
public static final String CASE_CURRENT_CASE = "currentCase"; public static final String CASE_CURRENT_CASE = "currentCase";
/** /**
@ -116,7 +114,6 @@ public class Case {
// Track the current case (only set with changeCase() method) // Track the current case (only set with changeCase() method)
private static Case currentCase = null; private static Case currentCase = null;
private Services services; private Services services;
private static final Logger logger = Logger.getLogger(Case.class.getName()); private static final Logger logger = Logger.getLogger(Case.class.getName());
/** /**
@ -148,6 +145,7 @@ public class Case {
/** /**
* Check if case is currently open * Check if case is currently open
*
* @return true if case is open * @return true if case is open
*/ */
public static boolean isCaseOpen() { public static boolean isCaseOpen() {
@ -155,8 +153,9 @@ public class Case {
} }
/** /**
* Updates the current case to the given case and fires off * Updates the current case to the given case and fires off the appropriate
* the appropriate property-change * property-change
*
* @param newCase the new current case * @param newCase the new current case
*/ */
private static void changeCase(Case newCase) { private static void changeCase(Case newCase) {
@ -174,8 +173,6 @@ public class Case {
pcs.firePropertyChange(CASE_NAME, oldCaseName, ""); pcs.firePropertyChange(CASE_NAME, oldCaseName, "");
if (newCase != null) { if (newCase != null) {
currentCase = newCase; currentCase = newCase;
@ -289,8 +286,8 @@ public class Case {
for (Map.Entry<Long, String> entry : imgPaths.entrySet()) { for (Map.Entry<Long, String> entry : imgPaths.entrySet()) {
long obj_id = entry.getKey(); long obj_id = entry.getKey();
String path = entry.getValue(); String path = entry.getValue();
boolean fileExists = (pathExists(path) || boolean fileExists = (pathExists(path)
driveExists(path)); || driveExists(path));
if (!fileExists) { if (!fileExists) {
int ret = JOptionPane.showConfirmDialog(null, appName + " has detected that one of the images associated with \n" int ret = JOptionPane.showConfirmDialog(null, appName + " has detected that one of the images associated with \n"
+ "this case are missing. Would you like to search for them now?\n" + "this case are missing. Would you like to search for them now?\n"
@ -337,6 +334,7 @@ public class Case {
/** /**
* Get the underlying SleuthkitCase instance from the Sleuth Kit bindings * Get the underlying SleuthkitCase instance from the Sleuth Kit bindings
* library. * library.
*
* @return * @return
*/ */
public SleuthkitCase getSleuthkitCase() { public SleuthkitCase getSleuthkitCase() {
@ -360,6 +358,7 @@ public class Case {
/** /**
* Delete this case. This methods delete all folders and files of this case. * Delete this case. This methods delete all folders and files of this case.
*
* @param caseDir case dir to delete * @param caseDir case dir to delete
* @throws CaseActionException exception throw if case could not be deleted * @throws CaseActionException exception throw if case could not be deleted
*/ */
@ -467,6 +466,7 @@ public class Case {
/** /**
* Returns the current version of Autopsy * Returns the current version of Autopsy
*
* @return autopsyVer * @return autopsyVer
*/ */
public static String getAutopsyVersion() { public static String getAutopsyVersion() {
@ -475,6 +475,7 @@ public class Case {
/** /**
* Gets the application name * Gets the application name
*
* @return appName * @return appName
*/ */
public static String getAppName() { public static String getAppName() {
@ -483,6 +484,7 @@ public class Case {
/** /**
* Gets the case name * Gets the case name
*
* @return name * @return name
*/ */
public String getName() { public String getName() {
@ -491,6 +493,7 @@ public class Case {
/** /**
* Gets the case number * Gets the case number
*
* @return number * @return number
*/ */
public String getNumber() { public String getNumber() {
@ -499,6 +502,7 @@ public class Case {
/** /**
* Gets the Examiner name * Gets the Examiner name
*
* @return examiner * @return examiner
*/ */
public String getExaminer() { public String getExaminer() {
@ -507,6 +511,7 @@ public class Case {
/** /**
* Gets the case directory path * Gets the case directory path
*
* @return caseDirectoryPath * @return caseDirectoryPath
*/ */
public String getCaseDirectory() { public String getCaseDirectory() {
@ -519,6 +524,7 @@ public class Case {
/** /**
* Gets the full path to the temp directory of this case * Gets the full path to the temp directory of this case
*
* @return tempDirectoryPath * @return tempDirectoryPath
*/ */
public String getTempDirectory() { public String getTempDirectory() {
@ -531,6 +537,7 @@ public class Case {
/** /**
* Gets the full path to the cache directory of this case * Gets the full path to the cache directory of this case
*
* @return cacheDirectoryPath * @return cacheDirectoryPath
*/ */
public String getCacheDirectory() { public String getCacheDirectory() {
@ -543,6 +550,7 @@ public class Case {
/** /**
* get the created date of this case * get the created date of this case
*
* @return case creation date * @return case creation date
*/ */
public String getCreatedDate() { public String getCreatedDate() {
@ -554,27 +562,29 @@ public class Case {
} }
/** /**
* Get absolute module output directory path where modules should save their permanent data * Get absolute module output directory path where modules should save their
* The directory is a subdirectory of this case dir. * permanent data The directory is a subdirectory of this case dir.
*
* @return absolute path to the module output dir * @return absolute path to the module output dir
*/ */
public String getModulesOutputDirectoryPath() { public String getModulesOutputDirAbsPath() {
return this.getCaseDirectory() + File.separator + getModulesOutputDirectory(); return this.getCaseDirectory() + File.separator + getModulesOutputDirRelPath();
} }
/** /**
* Get relative (with respect to case dir) * Get relative (with respect to case dir) module output directory path
* module output directory path where modules should save their permanent data * where modules should save their permanent data The directory is a
* The directory is a subdirectory of this case dir. * subdirectory of this case dir.
*
* @return relative path to the module output dir * @return relative path to the module output dir
*/ */
public String getModulesOutputDirectory() { public static String getModulesOutputDirRelPath() {
return "ModuleOutput"; return "ModuleOutput";
} }
/** /**
* get the PropertyChangeSupport of this class * get the PropertyChangeSupport of this class
*
* @return PropertyChangeSupport * @return PropertyChangeSupport
*/ */
public static PropertyChangeSupport getPropertyChangeSupport() { public static PropertyChangeSupport getPropertyChangeSupport() {
@ -587,6 +597,7 @@ public class Case {
/** /**
* get all the image id in this case * get all the image id in this case
*
* @return imageIDs * @return imageIDs
*/ */
public Long[] getImageIDs() { public Long[] getImageIDs() {
@ -600,6 +611,7 @@ public class Case {
/** /**
* Count the root objects. * Count the root objects.
*
* @return The number of total root objects in this case. * @return The number of total root objects in this case.
*/ */
public int getRootObjectsCount() { public int getRootObjectsCount() {
@ -608,6 +620,7 @@ public class Case {
/** /**
* Get the data model Content objects in the root of this case's hierarchy. * Get the data model Content objects in the root of this case's hierarchy.
*
* @return a list of the root objects * @return a list of the root objects
*/ */
public List<Content> getRootObjects() { public List<Content> getRootObjects() {
@ -645,29 +658,30 @@ public class Case {
/** /**
* Check if image from the given image path exists. * Check if image from the given image path exists.
*
* @param imgPath the image path * @param imgPath the image path
* @return isExist whether the path exists * @return isExist whether the path exists
*/ */
public static boolean pathExists(String imgPath) { public static boolean pathExists(String imgPath) {
return new File(imgPath).isFile(); return new File(imgPath).isFile();
} }
/** /**
* Does the given string refer to a physical drive? * Does the given string refer to a physical drive?
*/ */
private static final String pdisk = "\\\\.\\physicaldrive"; private static final String pdisk = "\\\\.\\physicaldrive";
private static final String dev = "/dev/"; private static final String dev = "/dev/";
static boolean isPhysicalDrive(String path) { static boolean isPhysicalDrive(String path) {
return path.toLowerCase().startsWith(pdisk) || return path.toLowerCase().startsWith(pdisk)
path.toLowerCase().startsWith(dev); || path.toLowerCase().startsWith(dev);
} }
/** /**
* Does the given string refer to a local drive / partition? * Does the given string refer to a local drive / partition?
*/ */
static boolean isPartition(String path) { static boolean isPartition(String path) {
return path.toLowerCase().startsWith("\\\\.\\") && return path.toLowerCase().startsWith("\\\\.\\")
path.toLowerCase().endsWith(":"); && path.toLowerCase().endsWith(":");
} }
/** /**
@ -701,8 +715,8 @@ public class Case {
/** /**
* Convert the Java timezone ID to the "formatted" string that can be * Convert the Java timezone ID to the "formatted" string that can be
* accepted by the C/C++ code. * accepted by the C/C++ code. Example: "America/New_York" converted to
* Example: "America/New_York" converted to "EST5EDT", etc * "EST5EDT", etc
* *
* @param timezoneID * @param timezoneID
* @return * @return
@ -735,6 +749,7 @@ public class Case {
/* The methods below are used to manage the case directories (creating, checking, deleting, etc) */ /* The methods below are used to manage the case directories (creating, checking, deleting, etc) */
/** /**
* to create the case directory * to create the case directory
*
* @param caseDir the case directory path * @param caseDir the case directory path
* @param caseName the case name * @param caseName the case name
* @throws CaseActionException throw if could not create the case dir * @throws CaseActionException throw if could not create the case dir
@ -746,8 +761,7 @@ public class Case {
if (caseDirF.exists()) { if (caseDirF.exists()) {
if (caseDirF.isFile()) { if (caseDirF.isFile()) {
throw new CaseActionException("Cannot create case dir, already exists and is not a directory: " + caseDir); throw new CaseActionException("Cannot create case dir, already exists and is not a directory: " + caseDir);
} } else if (!caseDirF.canRead() || !caseDirF.canWrite()) {
else if (! caseDirF.canRead() || ! caseDirF.canWrite()) {
throw new CaseActionException("Cannot create case dir, already exists and cannot read/write: " + caseDir); throw new CaseActionException("Cannot create case dir, already exists and cannot read/write: " + caseDir);
} }
} }
@ -767,6 +781,13 @@ public class Case {
if (result == false) { if (result == false) {
throw new CaseActionException("Could not create case directory: " + caseDir + " for case: " + caseName); throw new CaseActionException("Could not create case directory: " + caseDir + " for case: " + caseName);
} }
final String modulesOutDir = caseDir + File.separator + getModulesOutputDirRelPath();
result = new File(modulesOutDir).mkdir();
if (result == false) {
throw new CaseActionException("Could not create modules output directory: " + modulesOutDir + " for case: " + caseName);
}
} catch (Exception e) { } catch (Exception e) {
throw new CaseActionException("Could not create case directory: " + caseDir + " for case: " + caseName, e); throw new CaseActionException("Could not create case directory: " + caseDir + " for case: " + caseName, e);
} }
@ -774,6 +795,7 @@ public class Case {
/** /**
* delete the given case directory * delete the given case directory
*
* @param casePath the case path * @param casePath the case path
* @return boolean whether the case directory is successfully deleted or not * @return boolean whether the case directory is successfully deleted or not
*/ */
@ -790,12 +812,11 @@ public class Case {
} }
/** /**
* Call if there are no images in the case. Displays * Call if there are no images in the case. Displays a dialog offering to
* a dialog offering to add one. * add one.
*/ */
private static void runAddImageAction() { private static void runAddImageAction() {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
final AddImageAction action = Lookup.getDefault().lookup(AddImageAction.class); final AddImageAction action = Lookup.getDefault().lookup(AddImageAction.class);
@ -806,6 +827,7 @@ public class Case {
/** /**
* Checks if a String is a valid case name * Checks if a String is a valid case name
*
* @param caseName the candidate String * @param caseName the candidate String
* @return true if the candidate String is a valid case name * @return true if the candidate String is a valid case name
*/ */
@ -831,12 +853,32 @@ public class Case {
} }
} }
/**
* Check for existence of certain case sub dirs and create them if needed.
* @param openedCase
*/
private static void checkSubFolders(Case openedCase) {
String modulesOutputDir = openedCase.getModulesOutputDirAbsPath();
File modulesOutputDirF = new File(modulesOutputDir);
if (!modulesOutputDirF.exists()) {
logger.log(Level.INFO, "Creating modules output dir for the case.");
}
try {
if (! modulesOutputDirF.mkdir() ) {
logger.log(Level.SEVERE, "Error creating modules output dir for the case, dir: " + modulesOutputDir);
}
} catch (SecurityException e) {
logger.log(Level.SEVERE, "Error creating modules output dir for the case, dir: " + modulesOutputDir, e);
}
}
//case change helper //case change helper
private static void doCaseChange(Case toChangeTo) { private static void doCaseChange(Case toChangeTo) {
if (toChangeTo != null) { // new case is open if (toChangeTo != null) { // new case is open
// clear the temp folder when the case is created / opened // clear the temp folder when the case is created / opened
Case.clearTempFolder(); Case.clearTempFolder();
checkSubFolders(toChangeTo);
// enable these menus // enable these menus
CallableSystemAction.get(AddImageAction.class).setEnabled(true); CallableSystemAction.get(AddImageAction.class).setEnabled(true);
@ -898,4 +940,3 @@ public class Case {
} }
} }
} }