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

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();
}
/**
@ -191,11 +160,7 @@ class AddImageWizardIngestConfigPanel extends ShortcutWizardDescriptorPanel {
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();
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;
}
if (result.isEmpty()) {
throw new IllegalCaseNameException(String.format("Failed to sanitize case name '%s'", 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;
}
return result;
/*
* 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 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" />

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();
@ -225,36 +227,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
* text box.

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

View File

View File

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