Merge branch 'rc-280' of https://github.com/sleuthkit/autopsy into keyword_class_2495

This commit is contained in:
Eugene Livis 2017-04-12 13:53:56 -04:00
commit 8252e81b1f
374 changed files with 555 additions and 491 deletions

30
.gitignore vendored
View File

@ -3,20 +3,23 @@
/*/build/
*/nbproject/private/*
/nbproject/private/*
/Core/release/
/Core/src/org/sleuthkit/autopsy/coreutils/Version.properties
/Core/src/org/sleuthkit/autopsy/casemodule/docs/QuickStart.html
/Core/src/org/sleuthkit/autopsy/casemodule/docs/screenshot.png
/Core/src/org/sleuthkit/autopsy/datamodel/ranges.csv
/Core/build/
/Core/dist/
/Core/nbproject/*
!/Core/nbproject/project.xml
!/Core/nbproject/project.properties
/CoreLibs/release/
/CoreLibs/build/
/CoreLibs/dist/
/CoreLibs/nbproject/*
!/CoreLibs/nbproject/project.xml
!/CoreLibs/nbproject/project.properties
KeywordSearch/release/
/KeywordSearch/build/
/KeywordSearch/dist/
/KeywordSearch/nbproject/*
@ -46,6 +49,8 @@ genfiles.properties
/test/script/DBDump.txt
/test/script/SortedData-Diff.txt
/test/script/SortedData.txt
/test/script/myconfig.xml
/test/script/*/*.xml
/test/build/
/test/dist/
/test/nbproject/*
@ -59,19 +64,12 @@ genfiles.properties
/jdiff-logs/*
/gen_version.txt
hs_err_pid*.log
Core/src/org/sleuthkit/autopsy/casemodule/docs/QuickStart.html
Core/src/org/sleuthkit/autopsy/casemodule/docs/screenshot.png
Core/src/org/sleuthkit/autopsy/datamodel/ranges.csv
/test/script/myconfig.xml
/test/script/*/*.xml
.DS_Store
.*.swp
Core/release/
CoreLibs/release/
Experimental/release/
ImageGallery/release/
KeywordSearch/release/
thunderbirdparser/release/
/ImageGallery/release/
/RecentActivity/release/
/Experimental/release/
/thunderbirdparser/release/

View File

@ -20,17 +20,30 @@ package org.sleuthkit.autopsy.casemodule;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Window;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescriptorPanel;
import org.sleuthkit.datamodel.Content;
/**
* The final panel of the add image wizard. It displays a progress bar and
@ -42,21 +55,35 @@ import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescript
*/
class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
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;
private final AddImageAction addImageAction;
private DataSourceProcessor dsProcessor = null;
private boolean cancelled;
/**
* flag to indicate that the image adding process is finished and this panel
* is completed(valid)
*/
private boolean imgAdded = false;
private boolean ingested = false;
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private AddImageWizardAddingProgressVisual component;
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
private final List<Content> newContents = Collections.synchronizedList(new ArrayList<Content>());
private final DSPProgressMonitorImpl dspProgressMonitorImpl = new DSPProgressMonitorImpl();
private IngestJobSettings ingestJobSettings;
public DSPProgressMonitorImpl getDSPProgressMonitorImpl() {
AddImageWizardAddingProgressPanel(AddImageAction action) {
this.addImageAction = action;
}
DSPProgressMonitorImpl getDSPProgressMonitorImpl() {
return dspProgressMonitorImpl;
}
@ -209,12 +236,24 @@ class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
*/
@Override
public void readSettings(WizardDescriptor settings) {
// Start ingest if it hasn't already been started
startIngest();
settings.setOptions(new Object[]{WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, WizardDescriptor.FINISH_OPTION, WizardDescriptor.CANCEL_OPTION});
if (imgAdded) {
getComponent().setStateFinished();
}
}
void resetReadyToIngest() {
this.readyToIngest = false;
}
void setIngestJobSettings(IngestJobSettings ingestSettings) {
showWarnings(ingestSettings);
this.readyToIngest = true;
this.ingestJobSettings = ingestSettings;
}
/**
* this doesn't appear to store anything? plus, there are no settings in
* this panel -jm
@ -240,4 +279,136 @@ class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
getComponent().showErrors(errorString, critical);
}
/**
* Start ingest after verifying we have a new image, we are ready to ingest,
* and we haven't already ingested.
*/
private void startIngest() {
if (!newContents.isEmpty() && readyToIngest && !ingested) {
ingested = true;
IngestManager.getInstance().queueIngestJob(newContents, ingestJobSettings);
setStateFinished();
}
}
private static void showWarnings(IngestJobSettings ingestJobSettings) {
List<String> warnings = ingestJobSettings.getWarnings();
if (warnings.isEmpty() == false) {
StringBuilder warningMessage = new StringBuilder();
for (String warning : warnings) {
warningMessage.append(warning).append("\n");
}
JOptionPane.showMessageDialog(null, warningMessage.toString());
}
}
/**
* Starts the Data source processing by kicking off the selected
* DataSourceProcessor
*/
void startDataSourceProcessing(DataSourceProcessor dsp) {
if (dsProcessor == null) { //this can only be run once
final UUID dataSourceId = UUID.randomUUID();
newContents.clear();
cleanupTask = null;
readyToIngest = false;
dsProcessor = dsp;
// Add a cleanup task to interrupt the background process if the
// wizard exits while the background process is running.
cleanupTask = addImageAction.new CleanupTask() {
@Override
void cleanup() throws Exception {
cancelDataSourceProcessing(dataSourceId);
cancelled = true;
}
};
cleanupTask.enable();
new Thread(() -> {
Case.getCurrentCase().notifyAddingDataSource(dataSourceId);
}).start();
DataSourceProcessorCallback cbObj = new DataSourceProcessorCallback() {
@Override
public void doneEDT(DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
dataSourceProcessorDone(dataSourceId, result, errList, contents);
}
};
setStateStarted();
// Kick off the DSProcessor
dsProcessor.run(getDSPProgressMonitorImpl(), cbObj);
}
}
/*
* Cancels the data source processing - in case the users presses 'Cancel'
*/
private void cancelDataSourceProcessing(UUID dataSourceId) {
dsProcessor.cancel();
}
/*
* Callback for the data source processor. Invoked by the DSP on the EDT
* thread, when it finishes processing the data source.
*/
private void dataSourceProcessorDone(UUID dataSourceId, DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
// disable the cleanup task
cleanupTask.disable();
// Get attention for the process finish
// this caused a crash on OS X
if (PlatformUtil.isWindowsOS() == true) {
java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
}
AddImageWizardAddingProgressVisual panel = getComponent();
if (panel != null) {
Window w = SwingUtilities.getWindowAncestor(panel);
if (w != null) {
w.toFront();
}
}
// Tell the panel we're done
setStateFinished();
//check the result and display to user
if (result == DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS) {
getComponent().setProgressBarTextAndColor(
NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.dsProcDone.noErrs.text"), 100, Color.black);
} else {
getComponent().setProgressBarTextAndColor(
NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.dsProcDone.errs.text"), 100, Color.red);
}
//if errors, display them on the progress panel
boolean critErr = false;
if (result == DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS) {
critErr = true;
}
for (String err : errList) {
// TBD: there probably should be an error level for each error
addErrors(err, critErr);
}
//notify the UI of the new content added to the case
new Thread(() -> {
if (!contents.isEmpty()) {
Case.getCurrentCase().notifyDataSourceAdded(contents.get(0), dataSourceId);
} else {
Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId);
}
}).start();
if (!cancelled) {
newContents.clear();
newContents.addAll(contents);
setStateStarted();
startIngest();
} else {
cancelled = false;
}
}
}

View File

@ -50,7 +50,6 @@ class AddImageWizardDataSourceSettingsPanel extends ShortcutWizardDescriptorPane
// paths to any set hash lookup databases (can be null)
AddImageWizardDataSourceSettingsPanel() {
}
/**
@ -169,7 +168,7 @@ class AddImageWizardDataSourceSettingsPanel extends ShortcutWizardDescriptorPane
public void readSettings(WizardDescriptor settings) {
// Prepopulate the image directory from the properties file
try {
// If there is a process object in the settings, revert it and remove it from the settings
AddImageAction.CleanupTask cleanupTask = (AddImageAction.CleanupTask) settings.getProperty(AddImageAction.IMAGECLEANUPTASK_PROP);
if (cleanupTask != null) {
@ -184,7 +183,7 @@ class AddImageWizardDataSourceSettingsPanel extends ShortcutWizardDescriptorPane
}
} catch (Exception e) {
}
component.setDspSelection((String)settings.getProperty("SelectedDsp")); //NON-NLS magic string used SelectDataSourceProcessorPanel
component.setDspSelection((String) settings.getProperty("SelectedDsp")); //NON-NLS magic string used SelectDataSourceProcessorPanel
}
/**
@ -197,7 +196,7 @@ class AddImageWizardDataSourceSettingsPanel extends ShortcutWizardDescriptorPane
* @param settings the setting to be stored to
*/
@Override
public void storeSettings(WizardDescriptor settings) {
public void storeSettings(WizardDescriptor settings) {
}
/**

View File

@ -19,28 +19,17 @@
package org.sleuthkit.autopsy.casemodule;
import org.openide.util.NbBundle;
import java.awt.Color;
import java.awt.Component;
import java.awt.Window;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import javax.swing.JButton;
import javax.swing.JOptionPane;
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;
@ -60,24 +49,10 @@ class AddImageWizardIngestConfigPanel extends ShortcutWizardDescriptorPanel {
*/
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;
private final AddImageAction addImageAction;
private final AddImageWizardAddingProgressPanel progressPanel;
private final AddImageWizardDataSourceSettingsPanel dataSourcePanel;
private DataSourceProcessor dsProcessor;
private boolean cancelled;
AddImageWizardIngestConfigPanel(AddImageWizardDataSourceSettingsPanel dsPanel, AddImageAction action, AddImageWizardAddingProgressPanel proPanel) {
this.addImageAction = action;
AddImageWizardIngestConfigPanel(AddImageWizardAddingProgressPanel proPanel) {
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
@ -170,12 +145,6 @@ class AddImageWizardIngestConfigPanel extends ShortcutWizardDescriptorPanel {
NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text"));
cancel.setEnabled(false);
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();
}
/**
@ -190,12 +159,8 @@ class AddImageWizardIngestConfigPanel extends ShortcutWizardDescriptorPanel {
@Override
public void storeSettings(WizardDescriptor settings) {
IngestJobSettings ingestJobSettings = ingestJobSettingsPanel.getSettings();
ingestJobSettings.save();
showWarnings(ingestJobSettings);
// Start ingest if it hasn't already been started
readyToIngest = true;
startIngest();
ingestJobSettings.save();
progressPanel.setIngestJobSettings(ingestJobSettings); //prepare ingest for being started
}
private static void showWarnings(IngestJobSettings ingestJobSettings) {
@ -222,132 +187,7 @@ class AddImageWizardIngestConfigPanel extends ShortcutWizardDescriptorPanel {
}
//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.
*/
private void startIngest() {
if (!newContents.isEmpty() && readyToIngest && !ingested) {
ingested = true;
IngestManager.getInstance().queueIngestJob(newContents, ingestJobSettingsPanel.getSettings());
progressPanel.setStateFinished();
}
}
/**
* Starts the Data source processing by kicking off the selected
* DataSourceProcessor
*/
private void startDataSourceProcessing() {
final UUID dataSourceId = UUID.randomUUID();
// Add a cleanup task to interrupt the background process if the
// wizard exits while the background process is running.
cleanupTask = addImageAction.new CleanupTask() {
@Override
void cleanup() throws Exception {
cancelDataSourceProcessing(dataSourceId);
cancelled = true;
}
};
cleanupTask.enable();
// get the selected DSProcessor
dsProcessor = dataSourcePanel.getComponent().getCurrentDSProcessor();
new Thread(() -> {
Case.getCurrentCase().notifyAddingDataSource(dataSourceId);
}).start();
DataSourceProcessorCallback cbObj = new DataSourceProcessorCallback() {
@Override
public void doneEDT(DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
dataSourceProcessorDone(dataSourceId, result, errList, contents);
}
};
progressPanel.setStateStarted();
// Kick off the DSProcessor
dsProcessor.run(progressPanel.getDSPProgressMonitorImpl(), cbObj);
}
/*
* Cancels the data source processing - in case the users presses 'Cancel'
*/
private void cancelDataSourceProcessing(UUID dataSourceId) {
dsProcessor.cancel();
}
/*
* Callback for the data source processor. Invoked by the DSP on the EDT
* thread, when it finishes processing the data source.
*/
private void dataSourceProcessorDone(UUID dataSourceId, DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
// disable the cleanup task
cleanupTask.disable();
// Get attention for the process finish
// this caused a crash on OS X
if (PlatformUtil.isWindowsOS() == true) {
java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
}
AddImageWizardAddingProgressVisual panel = progressPanel.getComponent();
if (panel != null) {
Window w = SwingUtilities.getWindowAncestor(panel);
if (w != null) {
w.toFront();
}
}
// Tell the panel we're done
progressPanel.setStateFinished();
//check the result and display to user
if (result == DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS) {
progressPanel.getComponent().setProgressBarTextAndColor(
NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.dsProcDone.noErrs.text"), 100, Color.black);
} else {
progressPanel.getComponent().setProgressBarTextAndColor(
NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.dsProcDone.errs.text"), 100, Color.red);
}
//if errors, display them on the progress panel
boolean critErr = false;
if (result == DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS) {
critErr = true;
}
for (String err : errList) {
// TBD: there probably should be an error level for each error
progressPanel.addErrors(err, critErr);
}
//notify the UI of the new content added to the case
new Thread(() -> {
if (!contents.isEmpty()) {
Case.getCurrentCase().notifyDataSourceAdded(contents.get(0), dataSourceId);
} else {
Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId);
}
}).start();
if (!cancelled) {
newContents.clear();
newContents.addAll(contents);
progressPanel.setStateStarted();
startIngest();
} else {
cancelled = false;
}
progressPanel.setIngestJobSettings(ingestJobSettings); //prepare ingest for being started
}
}

View File

@ -56,10 +56,10 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
panels = new ArrayList<>();
AddImageWizardSelectDspPanel dspSelection = new AddImageWizardSelectDspPanel();
panels.add(dspSelection);
AddImageWizardAddingProgressPanel progressPanel = new AddImageWizardAddingProgressPanel();
AddImageWizardAddingProgressPanel progressPanel = new AddImageWizardAddingProgressPanel(action);
AddImageWizardDataSourceSettingsPanel dsPanel = new AddImageWizardDataSourceSettingsPanel();
AddImageWizardIngestConfigPanel ingestConfigPanel = new AddImageWizardIngestConfigPanel(dsPanel, action, progressPanel);
AddImageWizardIngestConfigPanel ingestConfigPanel = new AddImageWizardIngestConfigPanel(progressPanel);
panels.add(dsPanel);
List<IngestProfiles.IngestProfile> profiles = IngestProfiles.getIngestProfiles();
if (!profiles.isEmpty()) {
@ -174,7 +174,13 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
if (!hasNext()) {
throw new NoSuchElementException();
}
// 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
// This will occur when the next button is clicked on the panel where you have chosen your data to process
if (index == dsPanelIndex) {
((AddImageWizardAddingProgressPanel) panels.get(progressPanelIndex)).
startDataSourceProcessing(((AddImageWizardDataSourceSettingsPanel) panels.get(dsPanelIndex)).getComponent().getCurrentDSProcessor());
}
boolean panelEnablesSkipping = current().panelEnablesSkipping();
boolean skipNextPanel = current().skipNextPanel();
index++;

View File

@ -180,7 +180,7 @@ NewCaseWizardAction.newCase.windowTitle.text=New Case Information
NewCaseWizardAction.getName.text=New Case Wizard
NewCaseWizardAction.databaseProblem1.text=Cannot open database. Cancelling case creation.
NewCaseWizardAction.databaseProblem2.text=Error
NewCaseWizardPanel1.validate.errMsg.invalidSymbols=The Case Name cannot contain any of the following symbols\: \\ / \: * ? " < > |
NewCaseWizardPanel1.validate.errMsg.invalidSymbols=The Case Name cannot contain any of the following symbols\: \\ / \: * ? " &lt; > |
NewCaseWizardPanel1.validate.errMsg.dirExists=Case directory ''{0}'' already exists.
NewCaseWizardPanel1.validate.confMsg.createDir.msg=The base directory "{0}" does not exist. \n\n\
Do you want to create that directory?

View File

@ -135,7 +135,7 @@ NewCaseVisualPanel1.caseDirBrowse.selectButton.text=\u9078\u629e
NewCaseVisualPanel2.getName.text=\u4ed8\u52a0\u60c5\u5831
NewCaseWizardAction.newCase.windowTitle.text=\u65b0\u898f\u30b1\u30fc\u30b9\u60c5\u5831
NewCaseWizardAction.getName.text=\u65b0\u898f\u30b1\u30fc\u30b9\u30a6\u30a3\u30b6\u30fc\u30c9
NewCaseWizardPanel1.validate.errMsg.invalidSymbols=\u30b1\u30fc\u30b9\u540d\u306b\u306f\u6b21\u306e\u8a18\u53f7\u3092\u542b\u3081\u307e\u305b\u3093\uff1a\\ / \: * ? " < > |
NewCaseWizardPanel1.validate.errMsg.invalidSymbols=\u30b1\u30fc\u30b9\u540d\u306b\u306f\u6b21\u306e\u8a18\u53f7\u3092\u542b\u3081\u307e\u305b\u3093\uff1a\\ / \: * ? " &lt; > |
NewCaseWizardPanel1.validate.errMsg.dirExists=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea''{0}''\u306f\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059\u3002
NewCaseWizardPanel1.validate.confMsg.createDir.msg=\u30d9\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea''{0}''\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002\n\n\
\u3053\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u4f5c\u6210\u3057\u307e\u3059\u304b\uff1f

View File

@ -116,7 +116,7 @@ public class Case {
private static final int NAME_LOCK_TIMOUT_HOURS = 12;
private static final int SHARED_DIR_LOCK_TIMOUT_HOURS = 12;
private static final int RESOURCE_LOCK_TIMOUT_HOURS = 12;
private static final int MAX_SANITIZED_CASE_NAME_LEN = 47;
private static final int MAX_CASEDB_NAME_LEN_MINUS_TIMESTAMP = 47; //Truncate to 63-16=47 chars to accomodate the timestamp
private static final String SINGLE_USER_CASE_DB_NAME = "autopsy.db";
private static final String EVENT_CHANNEL_NAME = "%s-Case-Events"; //NON-NLS
private static final String CACHE_FOLDER = "Cache"; //NON-NLS
@ -725,56 +725,83 @@ public class Case {
}
/**
* Cleans up the display name for a case to make a suitable case name for
* use in case direcotry paths, coordination service locks, PostgreSQL
* database names, Active MQ message message channels, etc.
*
* PostgreSQL:
* http://www.postgresql.org/docs/9.4/static/sql-syntax-lexical.html 63
* chars max, must start with a-z or _ following chars can be letters _ or
* digits
* Transforms the display name for a case to make a suitable case name for
* use in case directory paths, coordination service locks, Active MQ
* message channels, etc.
*
* ActiveMQ:
* http://activemq.2283324.n4.nabble.com/What-are-limitations-restrictions-on-destination-name-td4664141.html
* may not be ?
*
* @param caseName A candidate case name.
* @param caseDisplayName A case display name.
*
* @return The sanitized case name.
* @return The case display name transformed into a corresponding case name.
*
* @throws org.sleuthkit.autopsy.casemodule.Case.IllegalCaseNameException
*/
public static String displayNameToCaseName(String caseName) throws IllegalCaseNameException {
public static String displayNameToCaseName(String caseDisplayName) throws IllegalCaseNameException {
String result;
/*
* Remove all non-ASCII characters.
*/
String caseName = caseDisplayName.replaceAll("[^\\p{ASCII}]", "_"); //NON-NLS
// Remove all non-ASCII characters
result = caseName.replaceAll("[^\\p{ASCII}]", "_"); //NON-NLS
/*
* Remove all control characters.
*/
caseName = caseName.replaceAll("[\\p{Cntrl}]", "_"); //NON-NLS
// Remove all control characters
result = result.replaceAll("[\\p{Cntrl}]", "_"); //NON-NLS
/*
* Remove /, \, :, ?, space, ' ".
*/
caseName = caseName.replaceAll("[ /?:'\"\\\\]", "_"); //NON-NLS
// Remove / \ : ? space ' "
result = result.replaceAll("[ /?:'\"\\\\]", "_"); //NON-NLS
/*
* Make it all lowercase.
*/
caseName = caseName.toLowerCase();
// Make it all lowercase
result = result.toLowerCase();
// Must start with letter or underscore for PostgreSQL. If not, prepend an underscore.
if (result.length() > 0 && !(Character.isLetter(result.codePointAt(0))) && !(result.codePointAt(0) == '_')) {
result = "_" + result;
if (caseName.isEmpty()) {
throw new IllegalCaseNameException(String.format("Failed to convert case name '%s'", caseDisplayName));
}
// Chop to 63-16=47 left (63 max for PostgreSQL, taking 16 for the date _20151225_123456)
if (result.length() > MAX_SANITIZED_CASE_NAME_LEN) {
result = result.substring(0, MAX_SANITIZED_CASE_NAME_LEN);
return caseName;
}
/**
* Transforms a case name into a name for a PostgreSQL database that can be
* safely used in SQL commands as described at
* http://www.postgresql.org/docs/9.4/static/sql-syntax-lexical.html: 63
* chars max, must start with a letter or underscore, following chars can be
* letters, underscores, or digits. A timestamp suffix is added to ensure
* uniqueness.
*
* @param caseName The case name.
*
* @return The case name transformed into a corresponding PostgreSQL
* case database name.
*/
private static String caseNameToCaseDbName(String caseName) throws IllegalCaseNameException {
/*
* Must start with letter or underscore. If not, prepend an underscore.
*/
String dbName = caseName;
if (dbName.length() > 0 && !(Character.isLetter(dbName.codePointAt(0))) && !(dbName.codePointAt(0) == '_')) {
dbName = "_" + dbName;
}
if (result.isEmpty()) {
throw new IllegalCaseNameException(String.format("Failed to sanitize case name '%s'", caseName));
/*
* Truncate to 63-16=47 chars to accomodate the timestamp, then add the
* timestamp.
*/
if (dbName.length() > MAX_CASEDB_NAME_LEN_MINUS_TIMESTAMP) {
dbName = dbName.substring(0, MAX_CASEDB_NAME_LEN_MINUS_TIMESTAMP);
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
Date date = new Date();
dbName = dbName + "_" + dateFormat.format(date);
return result;
return dbName;
}
/**
@ -1740,6 +1767,7 @@ public class Case {
@Messages({
"Case.progressMessage.creatingCaseDirectory=Creating case directory...",
"Case.progressMessage.creatingCaseDatabase=Creating case database...",
"Case.exceptionMessage.couldNotCreateCaseDatabaseName=Failed to create case database name from case name.",
"Case.progressMessage.creatingCaseMetadataFile=Creating case metadata file...",
"Case.exceptionMessage.couldNotCreateMetadataFile=Failed to create case metadata file.",
"Case.exceptionMessage.couldNotCreateCaseDatabase=Failed to create case database."
@ -1775,25 +1803,27 @@ public class Case {
*/
progressIndicator.progress(Bundle.Case_progressMessage_creatingCaseDatabase());
String dbName = null;
try {
if (CaseType.SINGLE_USER_CASE == caseType) {
dbName = SINGLE_USER_CASE_DB_NAME;
} else if (CaseType.MULTI_USER_CASE == caseType) {
dbName = caseNameToCaseDbName(caseName);
}
} catch (IllegalCaseNameException ex) {
throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseDatabaseName(), ex);
}
try {
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.
* 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.
* database physically located on the database server.
*/
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
Date date = new Date();
dbName = caseName + "_" + dateFormat.format(date);
this.caseDb = SleuthkitCase.newCase(dbName, UserPreferences.getDatabaseConnectionInfo(), caseDir);
}
} catch (TskCoreException ex) {

View File

@ -7,11 +7,6 @@
<import file="nbproject/build-impl.xml"/>
<import file="../BootstrapIvy.xml"/>
<property name="thirdparty.dir" value="${basedir}/../thirdparty" />
<property name="lib.dir" value="${basedir}/release/modules/lib" />
<condition property="os.family" value="unix">
<os family="unix"/>
</condition>
@ -23,6 +18,8 @@
</condition>
<import file="build-${os.family}.xml"/>
<property name="thirdparty.dir" value="${basedir}/../thirdparty" />
<property name="lib.dir" value="${basedir}/release/modules/lib" />
<target name="get-deps" description="retrieve dependencies using ivy" depends="init-ivy,build-native-libs">
<ivy:settings file="ivysettings.xml" />
@ -31,7 +28,7 @@
</target>
<target name="init" depends="get-deps,harness.init"/>
<target name="clean" depends="projectized-common.clean">
<!--Override clean to delete jars, etc downloaded with Ivy,
or copied in from thirdparty folder. This way we don't end up with

View File

@ -57,6 +57,7 @@ import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.CaseNewAction;
import org.sleuthkit.autopsy.casemodule.CaseOpenAction;
import org.sleuthkit.autopsy.core.ServicesMonitor;
@ -181,7 +182,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
* controlling automated ingest for a single node within the cluster.
*/
private AutoIngestDashboard() {
disableUiMenuActions();
//Disable the main window so they can only use the dashboard (if we used setVisible the taskBar icon would go away)
WindowManager.getDefault().getMainWindow().setEnabled(false);
manager = AutoIngestManager.getInstance();
@ -224,36 +226,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
*/
UIManager.put("PopupMenu.consumeEventOnClose", false);
}
private void disableUiMenuActions() {
/*
* Disable the new case action in auto ingest mode.
*/
CallableSystemAction.get(CaseNewAction.class).setEnabled(false);
/*
* Disable the new case action in auto ingest mode.
*/
CallableSystemAction.get(CaseOpenAction.class).setEnabled(false);
CallableSystemAction.get(AutoIngestCaseOpenAction.class).setEnabled(false);
/*
* Permanently delete the "Open Recent Cases" item in the "Case" menu.
* This is quite drastic, as it also affects Autopsy standalone mode on
* this machine, but we need to make sure a user can't open case in
* automated ingest mode. "Open Recent Cases" item can't be disabled via
* CallableSystemAction because of how it is defined in layer.xml, i.e.
* it is defined as "folder", not "file".
*/
FileObject root = FileUtil.getConfigRoot();
FileObject openRecentCasesMenu = root.getFileObject("Menu/Case/OpenRecentCase");
if (openRecentCasesMenu != null) {
try {
openRecentCasesMenu.delete();
} catch (IOException ignore) {
}
}
}
/**
* Queries the services monitor and sets the text for the services status

View File

@ -2,7 +2,37 @@
<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
<!-- for some information on what you could do (e.g. targets to override). -->
<!-- If you delete this file and reopen the project it will be recreated. -->
<project name="org.sleuthkit.autopsy.recentactivity" default="netbeans" basedir=".">
<project name="org.sleuthkit.autopsy.recentactivity" default="netbeans" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">
<description>Builds, tests, and runs the project org.sleuthkit.autopsy.recentactivity.</description>
<import file="nbproject/build-impl.xml"/>
<import file="../BootstrapIvy.xml"/>
<property name="thirdparty.dir" value="${basedir}/../thirdparty"/>
<target name="get-thirdparty-tools" >
<copy todir="${basedir}/release/pasco2">
<fileset dir="${thirdparty.dir}/pasco2/lib/" />
</copy>
<copy todir="${basedir}/release/rr">
<fileset dir="${thirdparty.dir}/rr/" />
</copy>
<copy todir="${basedir}/release/rr-full" >
<fileset dir="${thirdparty.dir}/rr-full/" />
</copy>
</target>
<target name="get-deps" depends="init-ivy,get-thirdparty-tools">
<!-- fetch all the dependencies from Ivy and stick them in the right places -->
<ivy:resolve/>
<ivy:retrieve conf="recent-activity" pattern="${basedir}/release/modules/ext/[artifact]-[revision](-[classifier]).[ext]" />
</target>
<target name="init" depends="get-deps,harness.init"/>
<target name="clean" depends="projectized-common.clean">
<!--Override clean to delete jars, etc downloaded with Ivy
or copied in from thirdparty folder. This way we don't end up with
out-of-date/unneeded stuff in the installer-->
<delete dir="${basedir}/release" />
</target>
</project>

12
RecentActivity/ivy.xml Normal file
View File

@ -0,0 +1,12 @@
<ivy-module version="2.0">
<info organisation="org.sleuthkit.autopsy" module="keywordsearch"/>
<configurations >
<!-- module dependencies -->
<conf name="recent-activity"/>
</configurations>
<dependencies>
<dependency conf="recent-activity->default" org="com.google.code.gson" name="gson" rev="2.1"/>
</dependencies>
</ivy-module>

View File

@ -0,0 +1,9 @@
<ivysettings>
<settings defaultResolver="main"/>
<resolvers>
<chain name="main">
<ibiblio name="central" m2compatible="true"/>
<ibiblio name="maven.restlet.org" root="http://maven.restlet.com" m2compatible="true" />
</chain>
</resolvers>
</ivysettings>

View File

View File

View File

View File

@ -1,6 +1,6 @@
# 20120528 *ALL* Plugins that apply on any HIVES, alphabetical order
baseline
findexes
regtime
rlo
# 20120528 *ALL* Plugins that apply on any HIVES, alphabetical order
baseline
findexes
regtime
rlo
del

View File

View File

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