mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge branch 'AUT-2487_bitlockerInAutopsy' of github.com:gdicristofaro/autopsy into 25_01_17_outstandingPrs
This commit is contained in:
commit
ebce83a512
@ -107,7 +107,7 @@ class AddImageTask implements Runnable {
|
||||
try {
|
||||
synchronized (tskAddImageProcessLock) {
|
||||
if (!tskAddImageProcessStopped) {
|
||||
tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(imageDetails.timeZone, true, imageDetails.ignoreFatOrphanFiles, imageWriterPath);
|
||||
tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(imageDetails.timeZone, true, imageDetails.ignoreFatOrphanFiles, imageWriterPath, imageDetails.password);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
@ -319,8 +319,9 @@ class AddImageTask implements Runnable {
|
||||
String sha1;
|
||||
String sha256;
|
||||
ImageWriterSettings imageWriterSettings;
|
||||
String password;
|
||||
|
||||
ImageDetails(String deviceId, Image image, int sectorSize, String timeZone, boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256, ImageWriterSettings imageWriterSettings) {
|
||||
ImageDetails(String deviceId, Image image, int sectorSize, String timeZone, boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256, ImageWriterSettings imageWriterSettings, String password) {
|
||||
this.deviceId = deviceId;
|
||||
this.image = image;
|
||||
this.sectorSize = sectorSize;
|
||||
@ -330,6 +331,7 @@ class AddImageTask implements Runnable {
|
||||
this.sha1 = sha1;
|
||||
this.sha256 = sha256;
|
||||
this.imageWriterSettings = imageWriterSettings;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
String getImagePath() {
|
||||
|
@ -50,6 +50,8 @@ final class AddImageWizardDataSourceSettingsVisual extends JPanel {
|
||||
|
||||
private final Map<String, DataSourceProcessor> datasourceProcessorsMap = new HashMap<>();
|
||||
|
||||
private final PanelUpdateListener panelUpdateListener;
|
||||
|
||||
private String currentDsp;
|
||||
|
||||
/**
|
||||
@ -60,6 +62,7 @@ final class AddImageWizardDataSourceSettingsVisual extends JPanel {
|
||||
AddImageWizardDataSourceSettingsVisual(AddImageWizardDataSourceSettingsPanel wizPanel) {
|
||||
initComponents();
|
||||
this.wizPanel = wizPanel;
|
||||
this.panelUpdateListener = new PanelUpdateListener();
|
||||
typePanel.setLayout(new BorderLayout());
|
||||
discoverDataSourceProcessors();
|
||||
currentDsp = ImageDSProcessor.getType(); //default value to the ImageDSProcessor
|
||||
@ -107,25 +110,38 @@ final class AddImageWizardDataSourceSettingsVisual extends JPanel {
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void updateCurrentPanel(JPanel panel) {
|
||||
cleanupUpdateListener(currentPanel);
|
||||
currentPanel = panel;
|
||||
typePanel.removeAll();
|
||||
typePanel.add(currentPanel, BorderLayout.CENTER);
|
||||
typePanel.validate();
|
||||
typePanel.repaint();
|
||||
currentPanel.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getPropertyName().equals(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString())) {
|
||||
wizPanel.enableNextButton(getCurrentDSProcessor().isPanelValid());
|
||||
}
|
||||
if (evt.getPropertyName().equals(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString())) {
|
||||
wizPanel.moveFocusToNext();
|
||||
}
|
||||
}
|
||||
});
|
||||
cleanupUpdateListener(currentPanel);
|
||||
currentPanel.addPropertyChangeListener(panelUpdateListener);
|
||||
this.wizPanel.enableNextButton(getCurrentDSProcessor().isPanelValid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes PanelUpdateListener from panel if found.
|
||||
* @param panel The panel from which to remove the listener.
|
||||
*/
|
||||
private void cleanupUpdateListener(JPanel panel) {
|
||||
if (panel == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PropertyChangeListener[] listeners = panel.getPropertyChangeListeners();
|
||||
if (listeners == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (PropertyChangeListener listener: listeners) {
|
||||
if (listener instanceof PanelUpdateListener) {
|
||||
panel.removePropertyChangeListener(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently selected DS Processor
|
||||
*
|
||||
@ -221,4 +237,20 @@ final class AddImageWizardDataSourceSettingsVisual extends JPanel {
|
||||
|
||||
protected abstract boolean addSeparatorAfter(JList list, Object value, int index);
|
||||
}
|
||||
|
||||
/**
|
||||
* A property change listener that responds to update events.
|
||||
*/
|
||||
private class PanelUpdateListener implements PropertyChangeListener {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getPropertyName().equals(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString())) {
|
||||
wizPanel.enableNextButton(getCurrentDSProcessor().isPanelValid());
|
||||
}
|
||||
if (evt.getPropertyName().equals(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString())) {
|
||||
wizPanel.moveFocusToNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -270,3 +270,6 @@ LocalFilesPanel.timestampToIncludeLabel.text=Timestamps To Include:
|
||||
LocalFilesPanel.accessTimeCheckBox.text=Access Time - Can be changed when the file is opened
|
||||
LocalFilesPanel.timeStampToIncludeLabel.text=Timestamps To Include:
|
||||
LocalFilesPanel.timeStampNoteLabel.text=NOTE: Time stamps may have changed when the files were copied to the current location.
|
||||
ImageFilePanel.passwordLabel.text=Bitlocker Password (optional):
|
||||
ImageFilePanel.passwordTextField.text=
|
||||
ImageFilePanel.loadingLabel.text=loading...
|
||||
|
@ -151,7 +151,7 @@ GeneralFilter.encaseImageDesc.text=Encase Images (*.e01)
|
||||
GeneralFilter.executableDesc.text=Executables (*.exe)
|
||||
GeneralFilter.graphicImageDesc.text=Images (*.png, *.jpg, *.jpeg, *.gif, *.bmp)
|
||||
GeneralFilter.rawImageDesc.text=Raw Images (*.img, *.dd, *.001, *.aa, *.raw, *.bin)
|
||||
GeneralFilter.virtualMachineImageDesc.text=Virtual Machines (*.vmdk, *.vhd)
|
||||
GeneralFilter.virtualMachineImageDesc.text=Virtual Machines (*.vmdk, *.vhd, *.vhdx)
|
||||
ImageFilePanel.000.confirmationMessage=The selected file has extenson .001 but there is a .000 file in the sequence of raw images.\nShould the .000 file be used as the start, instead of the selected .001 file?\n
|
||||
ImageFilePanel.moduleErr=Module Error
|
||||
ImageFilePanel.moduleErr.msg=A module caused an error listening to ImageFilePanel updates. See log to determine which module. Some data could be incomplete.\n
|
||||
@ -159,6 +159,10 @@ ImageFilePanel.validatePanel.dataSourceOnCDriveError=Warning: Path to multi-user
|
||||
ImageFilePanel.validatePanel.invalidMD5=Invalid MD5 hash
|
||||
ImageFilePanel.validatePanel.invalidSHA1=Invalid SHA1 hash
|
||||
ImageFilePanel.validatePanel.invalidSHA256=Invalid SHA256 hash
|
||||
# {0} - imageOpenError
|
||||
ImageFilePanel_validatePanel_imageOpenError=<html><body><p>An error occurred while opening the image:{0}</p></body></html>
|
||||
ImageFilePanel_validatePanel_unknownError=<html><body><p>An unknown error occurred while attempting to validate the image</p></body></html>
|
||||
ImageFilePanel_validatePanel_unknownErrorMsg=<unknown>
|
||||
IngestJobInfoPanel.IngestJobTableModel.EndTime.header=End Time
|
||||
IngestJobInfoPanel.IngestJobTableModel.IngestStatus.header=Ingest Status
|
||||
IngestJobInfoPanel.IngestJobTableModel.StartTime.header=Start Time
|
||||
@ -504,3 +508,6 @@ LocalFilesPanel.timestampToIncludeLabel.text=Timestamps To Include:
|
||||
LocalFilesPanel.accessTimeCheckBox.text=Access Time - Can be changed when the file is opened
|
||||
LocalFilesPanel.timeStampToIncludeLabel.text=Timestamps To Include:
|
||||
LocalFilesPanel.timeStampNoteLabel.text=NOTE: Time stamps may have changed when the files were copied to the current location.
|
||||
ImageFilePanel.passwordLabel.text=Bitlocker Password (optional):
|
||||
ImageFilePanel.passwordTextField.text=
|
||||
ImageFilePanel.loadingLabel.text=loading...
|
||||
|
@ -27,6 +27,7 @@ import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.UUID;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.openide.util.lookup.ServiceProviders;
|
||||
@ -82,6 +83,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
private String sha1;
|
||||
private String sha256;
|
||||
private Host host = null;
|
||||
private String password;
|
||||
|
||||
static {
|
||||
filtersList.add(allFilter);
|
||||
@ -162,7 +164,9 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
*/
|
||||
@Override
|
||||
public boolean isPanelValid() {
|
||||
return configPanel.validatePanel();
|
||||
// before attempting to validate the panel (a potentially long running operation),
|
||||
// check if the validation is loading or on delay.
|
||||
return !configPanel.isValidationLoading() && configPanel.validatePanel();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,7 +185,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
*/
|
||||
@Override
|
||||
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
run(null, progressMonitor, callback);
|
||||
run(null, null, progressMonitor, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -201,12 +205,19 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
*/
|
||||
@Override
|
||||
public void run(Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
run(null, host, progressMonitor, callback);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run(String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
ingestStream = new DefaultIngestStream();
|
||||
readConfigSettings();
|
||||
this.host = host;
|
||||
this.password = StringUtils.defaultString(password, this.password);
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, this.host);
|
||||
new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, this.password, this.host);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
@ -215,117 +226,9 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
return;
|
||||
}
|
||||
|
||||
doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, progressMonitor, callback);
|
||||
doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, this.password, progressMonitor, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Files found during ingest will be sent directly to
|
||||
* the IngestStream provided. Returns as soon as the background task is
|
||||
* started. The background task uses a callback object to signal task
|
||||
* completion and return results.
|
||||
*
|
||||
* This method should not be called unless isPanelValid returns true, and
|
||||
* should only be called for DSPs that support ingest streams.
|
||||
*
|
||||
* @param settings The ingest job settings.
|
||||
* @param progress Progress monitor that will be used by the background task
|
||||
* to report progress.
|
||||
* @param callBack Callback that will be used by the background task to
|
||||
* return results.
|
||||
*/
|
||||
@Override
|
||||
public void runWithIngestStream(IngestJobSettings settings, DataSourceProcessorProgressMonitor progress,
|
||||
DataSourceProcessorCallback callBack) {
|
||||
runWithIngestStream(null, settings, progress, callBack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Files found during ingest will be sent directly to
|
||||
* the IngestStream provided. Returns as soon as the background task is
|
||||
* started. The background task uses a callback object to signal task
|
||||
* completion and return results.
|
||||
*
|
||||
* This method should not be called unless isPanelValid returns true, and
|
||||
* should only be called for DSPs that support ingest streams.
|
||||
*
|
||||
* @param host The host for this data source.
|
||||
* @param settings The ingest job settings.
|
||||
* @param progress Progress monitor that will be used by the background task
|
||||
* to report progress.
|
||||
* @param callBack Callback that will be used by the background task to
|
||||
* return results.
|
||||
*/
|
||||
@Override
|
||||
public void runWithIngestStream(Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progress,
|
||||
DataSourceProcessorCallback callBack) {
|
||||
|
||||
// Read the settings from the wizard
|
||||
readConfigSettings();
|
||||
this.host = host;
|
||||
|
||||
// Set up the data source before creating the ingest stream
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, this.host);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
errors.add(ex.getMessage());
|
||||
callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
|
||||
return;
|
||||
}
|
||||
|
||||
// Now initialize the ingest stream
|
||||
try {
|
||||
ingestStream = IngestManager.getInstance().openIngestStream(image, settings);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error starting ingest modules", ex);
|
||||
// There was an error with ingest, but the data source has already been added
|
||||
// so proceed with the defaultIngestStream. Code in openIngestStream
|
||||
// should have caused a dialog to popup with the errors.
|
||||
ingestStream = new DefaultIngestStream();
|
||||
}
|
||||
|
||||
doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, progress, callBack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the options from the config panel.
|
||||
*/
|
||||
private void readConfigSettings() {
|
||||
configPanel.storeSettings();
|
||||
deviceId = UUID.randomUUID().toString();
|
||||
imagePath = configPanel.getContentPaths();
|
||||
sectorSize = configPanel.getSectorSize();
|
||||
timeZone = configPanel.getTimeZone();
|
||||
ignoreFatOrphanFiles = configPanel.getNoFatOrphans();
|
||||
md5 = configPanel.getMd5();
|
||||
if (md5.isEmpty()) {
|
||||
md5 = null;
|
||||
}
|
||||
sha1 = configPanel.getSha1();
|
||||
if (sha1.isEmpty()) {
|
||||
sha1 = null;
|
||||
}
|
||||
sha256 = configPanel.getSha256();
|
||||
if (sha256.isEmpty()) {
|
||||
sha256 = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this DSP supports ingest streams.
|
||||
*
|
||||
* @return True if this DSP supports an ingest stream, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsIngestStream() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
@ -352,7 +255,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
ingestStream = new DefaultIngestStream();
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId);
|
||||
new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId, null, null);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
@ -361,9 +264,134 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
return;
|
||||
}
|
||||
|
||||
doAddImageProcess(deviceId, imagePath, 0, timeZone, ignoreFatOrphanFiles, null, null, null, progressMonitor, callback);
|
||||
doAddImageProcess(deviceId, imagePath, 0, timeZone, ignoreFatOrphanFiles, null, null, null, this.password, progressMonitor, callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Files found during ingest will be sent directly to
|
||||
* the IngestStream provided. Returns as soon as the background task is
|
||||
* started. The background task uses a callback object to signal task
|
||||
* completion and return results.
|
||||
*
|
||||
* This method should not be called unless isPanelValid returns true, and
|
||||
* should only be called for DSPs that support ingest streams.
|
||||
*
|
||||
* @param settings The ingest job settings.
|
||||
* @param progress Progress monitor that will be used by the background task
|
||||
* to report progress.
|
||||
* @param callBack Callback that will be used by the background task to
|
||||
* return results.
|
||||
*/
|
||||
@Override
|
||||
public void runWithIngestStream(IngestJobSettings settings, DataSourceProcessorProgressMonitor progress,
|
||||
DataSourceProcessorCallback callBack) {
|
||||
runWithIngestStream(null, null, settings, progress, callBack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Files found during ingest will be sent directly to
|
||||
* the IngestStream provided. Returns as soon as the background task is
|
||||
* started. The background task uses a callback object to signal task
|
||||
* completion and return results.
|
||||
*
|
||||
* This method should not be called unless isPanelValid returns true, and
|
||||
* should only be called for DSPs that support ingest streams.
|
||||
*
|
||||
* @param host The host for this data source.
|
||||
* @param settings The ingest job settings.
|
||||
* @param progress Progress monitor that will be used by the background task
|
||||
* to report progress.
|
||||
* @param callBack Callback that will be used by the background task to
|
||||
* return results.
|
||||
*/
|
||||
@Override
|
||||
public void runWithIngestStream(Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progress,
|
||||
DataSourceProcessorCallback callBack) {
|
||||
runWithIngestStream(null, host, settings, progress, callBack);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void runWithIngestStream(String password, Host host, IngestJobSettings settings,
|
||||
DataSourceProcessorProgressMonitor progress, DataSourceProcessorCallback callBack) {
|
||||
|
||||
// Read the settings from the wizard
|
||||
readConfigSettings();
|
||||
this.host = host;
|
||||
this.password = StringUtils.defaultString(password, this.password);
|
||||
|
||||
// Set up the data source before creating the ingest stream
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, this.password, this.host);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
errors.add(ex.getMessage());
|
||||
callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
|
||||
return;
|
||||
}
|
||||
|
||||
// Now initialize the ingest stream
|
||||
try {
|
||||
ingestStream = IngestManager.getInstance().openIngestStream(image, settings);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error starting ingest modules", ex);
|
||||
// There was an error with ingest, but the data source has already been added
|
||||
// so proceed with the defaultIngestStream. Code in openIngestStream
|
||||
// should have caused a dialog to popup with the errors.
|
||||
ingestStream = new DefaultIngestStream();
|
||||
}
|
||||
|
||||
doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, this.password, progress, callBack);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store the options from the config panel.
|
||||
*/
|
||||
private void readConfigSettings() {
|
||||
configPanel.storeSettings();
|
||||
deviceId = UUID.randomUUID().toString();
|
||||
imagePath = configPanel.getContentPaths();
|
||||
sectorSize = configPanel.getSectorSize();
|
||||
timeZone = configPanel.getTimeZone();
|
||||
ignoreFatOrphanFiles = configPanel.getNoFatOrphans();
|
||||
md5 = configPanel.getMd5();
|
||||
if (md5.isEmpty()) {
|
||||
md5 = null;
|
||||
}
|
||||
sha1 = configPanel.getSha1();
|
||||
if (sha1.isEmpty()) {
|
||||
sha1 = null;
|
||||
}
|
||||
sha256 = configPanel.getSha256();
|
||||
if (sha256.isEmpty()) {
|
||||
sha256 = null;
|
||||
}
|
||||
this.password = configPanel.getPassword();
|
||||
if (this.password.isEmpty()) {
|
||||
password = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this DSP supports ingest streams.
|
||||
*
|
||||
* @return True if this DSP supports an ingest stream, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsIngestStream() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the given settings instead of those provided by the
|
||||
@ -389,11 +417,12 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
* @param md5 The MD5 hash of the image, may be null.
|
||||
* @param sha1 The SHA-1 hash of the image, may be null.
|
||||
* @param sha256 The SHA-256 hash of the image, may be null.
|
||||
* @param password Password for image decryption. May be null.
|
||||
* @param progressMonitor Progress monitor for reporting progress
|
||||
* during processing.
|
||||
* @param callback Callback to call when processing is done.
|
||||
*/
|
||||
private void doAddImageProcess(String deviceId, String imagePath, int sectorSize, String timeZone, boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
private void doAddImageProcess(String deviceId, String imagePath, int sectorSize, String timeZone, boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256, String password, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
|
||||
// If the data source or ingest stream haven't been initialized, stop processing
|
||||
if (ingestStream == null) {
|
||||
@ -413,7 +442,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
return;
|
||||
}
|
||||
|
||||
AddImageTask.ImageDetails imageDetails = new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, null);
|
||||
AddImageTask.ImageDetails imageDetails = new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, null, password);
|
||||
addImageTask = new AddImageTask(imageDetails,
|
||||
progressMonitor,
|
||||
new StreamingAddDataSourceCallbacks(ingestStream),
|
||||
@ -449,6 +478,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
timeZone = null;
|
||||
ignoreFatOrphanFiles = false;
|
||||
host = null;
|
||||
password = null;
|
||||
configPanel.reset();
|
||||
}
|
||||
|
||||
@ -463,6 +493,13 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
|
||||
@Override
|
||||
public int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
|
||||
return canProcess(dataSourcePath, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int canProcess(Path dataSourcePath, String password) throws AutoIngestDataSourceProcessorException {
|
||||
|
||||
// check file extension for supported types
|
||||
if (!isAcceptedByFiler(dataSourcePath.toFile(), filtersList)) {
|
||||
@ -470,11 +507,21 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
}
|
||||
|
||||
try {
|
||||
if (password == null) {
|
||||
|
||||
// verify that the image has a file system that TSK can process
|
||||
if (!DataSourceUtils.imageHasFileSystem(dataSourcePath)) {
|
||||
// image does not have a file system that TSK can process
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
// verify that the image has a file system that TSK can process
|
||||
if (!DataSourceUtils.imageHasFileSystem(dataSourcePath, password)) {
|
||||
// image does not have a file system that TSK can process
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new AutoIngestDataSourceProcessorException("Exception inside canProcess() method", ex);
|
||||
}
|
||||
@ -485,23 +532,29 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
|
||||
@Override
|
||||
public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
process(deviceId, dataSourcePath, null, progressMonitor, callBack);
|
||||
process(deviceId, dataSourcePath, null, null, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(String deviceId, Path dataSourcePath, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
process(deviceId, dataSourcePath, null, host, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(String deviceId, Path dataSourcePath, String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
// this method does not use the config panel
|
||||
this.deviceId = deviceId;
|
||||
this.imagePath = dataSourcePath.toString();
|
||||
this.sectorSize = 0;
|
||||
this.timeZone = Calendar.getInstance().getTimeZone().getID();
|
||||
this.password = StringUtils.defaultString(password, this.password);
|
||||
this.host = host;
|
||||
this.ignoreFatOrphanFiles = false;
|
||||
|
||||
ingestStream = new DefaultIngestStream();
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId, host);
|
||||
new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId, this.password, host);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
@ -510,28 +563,36 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
return;
|
||||
}
|
||||
|
||||
doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, progressMonitor, callBack);
|
||||
doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, this.password, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
return processWithIngestStream(deviceId, dataSourcePath, null, settings, progressMonitor, callBack);
|
||||
return processWithIngestStream(deviceId, dataSourcePath, null, null, settings, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
return processWithIngestStream(deviceId, dataSourcePath, null, host, settings, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, String password, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
// this method does not use the config panel
|
||||
this.deviceId = deviceId;
|
||||
this.imagePath = dataSourcePath.toString();
|
||||
this.sectorSize = 0;
|
||||
this.timeZone = Calendar.getInstance().getTimeZone().getID();
|
||||
this.host = host;
|
||||
this.password = password;
|
||||
this.ignoreFatOrphanFiles = false;
|
||||
|
||||
// Set up the data source before creating the ingest stream
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, host);
|
||||
new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, password, host);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
@ -551,8 +612,10 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
return null;
|
||||
}
|
||||
|
||||
doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, progressMonitor, callBack);
|
||||
doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, password, progressMonitor, callBack);
|
||||
|
||||
return ingestStream;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -19,108 +19,10 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,-38,0,0,2,46"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="pathTextField" max="32767" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="pathLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="noFatOrphansCheckbox" alignment="0" min="-2" pref="262" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="368" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="errorLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="timeZoneLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="timeZoneComboBox" min="-2" pref="455" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="sectorSizeLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="sectorSizeComboBox" min="-2" pref="455" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="md5HashLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="md5HashTextField" min="-2" pref="455" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="sha1HashLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="sha1HashTextField" min="-2" pref="455" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="sha256HashLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="sha256HashTextField" min="-2" pref="455" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="hashValuesNoteLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="hashValuesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="pathLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="timeZoneComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="timeZoneLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="sectorSizeComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="sectorSizeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="39" max="-2" attributes="0"/>
|
||||
<Component id="hashValuesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="md5HashTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="md5HashLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="sha1HashTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="sha1HashLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="sha256HashTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="sha256HashLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="hashValuesNoteLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="errorLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="pathLabel">
|
||||
<Properties>
|
||||
@ -128,6 +30,11 @@
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="ImageFilePanel.pathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="browseButton">
|
||||
<Properties>
|
||||
@ -138,6 +45,11 @@
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="pathTextField">
|
||||
<Properties>
|
||||
@ -145,6 +57,11 @@
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="ImageFilePanel.pathTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="timeZoneLabel">
|
||||
<Properties>
|
||||
@ -152,6 +69,11 @@
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="ImageFilePanel.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="timeZoneComboBox">
|
||||
<Properties>
|
||||
@ -163,6 +85,11 @@
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="3" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="noFatOrphansCheckbox">
|
||||
<Properties>
|
||||
@ -173,6 +100,11 @@
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="ImageFilePanel.noFatOrphansCheckbox.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="errorLabel">
|
||||
<Properties>
|
||||
@ -182,7 +114,22 @@
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="ImageFilePanel.errorLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="verticalAlignment" type="int" value="1"/>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[500, 60]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[200, 20]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[200, 60]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="11" gridWidth="3" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="sectorSizeLabel">
|
||||
<Properties>
|
||||
@ -190,6 +137,11 @@
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="ImageFilePanel.sectorSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="4" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="sectorSizeComboBox">
|
||||
<Properties>
|
||||
@ -200,6 +152,11 @@
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="4" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="sha256HashLabel">
|
||||
<Properties>
|
||||
@ -208,6 +165,11 @@
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="9" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="sha256HashTextField">
|
||||
<Properties>
|
||||
@ -216,6 +178,11 @@
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="9" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="sha1HashTextField">
|
||||
<Properties>
|
||||
@ -224,6 +191,11 @@
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="8" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="md5HashTextField">
|
||||
<Properties>
|
||||
@ -232,6 +204,11 @@
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="7" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="sha1HashLabel">
|
||||
<Properties>
|
||||
@ -240,6 +217,11 @@
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="8" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="md5HashLabel">
|
||||
<Properties>
|
||||
@ -248,6 +230,11 @@
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="7" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="hashValuesLabel">
|
||||
<Properties>
|
||||
@ -256,6 +243,11 @@
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="6" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="hashValuesNoteLabel">
|
||||
<Properties>
|
||||
@ -264,6 +256,84 @@
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="10" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="passwordLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="ImageFilePanel.passwordLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="5" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="passwordTextField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="ImageFilePanel.passwordTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="5" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="spacer">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="12" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="loadingLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/working_spinner.gif"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="ImageFilePanel.loadingLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="verticalAlignment" type="int" value="1"/>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[500, 60]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[200, 20]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[200, 60]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="11" gridWidth="3" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -18,9 +18,16 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.io.File;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
@ -32,11 +39,14 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.DriveUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
||||
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||
import org.sleuthkit.autopsy.guiutils.JFileChooserFactory;
|
||||
import org.sleuthkit.datamodel.HashUtility;
|
||||
import org.sleuthkit.datamodel.SleuthkitJNI;
|
||||
import org.sleuthkit.datamodel.SleuthkitJNI.TestOpenImageResult;
|
||||
|
||||
/**
|
||||
* Panel for adding an image file such as .img, .E0x, .00x, etc. Allows the user
|
||||
@ -44,7 +54,9 @@ import org.sleuthkit.datamodel.HashUtility;
|
||||
* files in FAT32.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
public class ImageFilePanel extends JPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AddImageTask.class.getName());
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String PROP_LASTIMAGE_PATH = "LBL_LastImage_PATH"; //NON-NLS
|
||||
@ -54,6 +66,15 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
private final String contextName;
|
||||
private final List<FileFilter> fileChooserFilters;
|
||||
|
||||
private static int VALIDATE_TIMEOUT_MILLIS = 1000;
|
||||
static ScheduledThreadPoolExecutor delayedValidationService = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("ImageFilePanel delayed validation").build());
|
||||
|
||||
private final ReentrantLock validationWaitingLock = new ReentrantLock();
|
||||
private final ReentrantLock validationLock = new ReentrantLock();
|
||||
|
||||
private Runnable validateAction = null;
|
||||
private Future<?> validateFuture = null;
|
||||
|
||||
/**
|
||||
* Creates new form ImageFilePanel
|
||||
*
|
||||
@ -76,6 +97,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
sectorSizeComboBox.setSelectedIndex(0);
|
||||
|
||||
errorLabel.setVisible(false);
|
||||
loadingLabel.setVisible(false);
|
||||
this.fileChooserFilters = fileChooserFilters;
|
||||
}
|
||||
|
||||
@ -105,11 +127,17 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
*/
|
||||
public static synchronized ImageFilePanel createInstance(String context, List<FileFilter> fileChooserFilters) {
|
||||
ImageFilePanel instance = new ImageFilePanel(context, fileChooserFilters);
|
||||
DocumentListener delayedValidationListener = instance.new DelayedValidationDocListener();
|
||||
|
||||
// post-constructor initialization of listener support without leaking references of uninitialized objects
|
||||
instance.getPathTextField().getDocument().addDocumentListener(instance);
|
||||
instance.getMd5TextFieldField().getDocument().addDocumentListener(instance);
|
||||
instance.getSha1TextField().getDocument().addDocumentListener(instance);
|
||||
instance.getSha256TextField().getDocument().addDocumentListener(instance);
|
||||
for (JTextField textField: List.of(
|
||||
instance.getPathTextField(),
|
||||
instance.getMd5TextFieldField(),
|
||||
instance.getSha1TextField(),
|
||||
instance.getSha256TextField(),
|
||||
instance.getPasswordTextField())) {
|
||||
textField.getDocument().addDocumentListener(delayedValidationListener);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@ -129,6 +157,10 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
return sha256HashTextField;
|
||||
}
|
||||
|
||||
private JTextField getPasswordTextField() {
|
||||
return passwordTextField;
|
||||
}
|
||||
|
||||
private JFileChooser getChooser() {
|
||||
if(fileChooser == null) {
|
||||
fileChooser = fileChooserHelper.getChooser();
|
||||
@ -151,6 +183,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
pathLabel = new javax.swing.JLabel();
|
||||
browseButton = new javax.swing.JButton();
|
||||
@ -169,11 +202,25 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
md5HashLabel = new javax.swing.JLabel();
|
||||
hashValuesLabel = new javax.swing.JLabel();
|
||||
hashValuesNoteLabel = new javax.swing.JLabel();
|
||||
passwordLabel = new javax.swing.JLabel();
|
||||
passwordTextField = new javax.swing.JTextField();
|
||||
javax.swing.JPanel spacer = new javax.swing.JPanel();
|
||||
loadingLabel = new javax.swing.JLabel();
|
||||
|
||||
setMinimumSize(new java.awt.Dimension(0, 65));
|
||||
setPreferredSize(new java.awt.Dimension(403, 65));
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.pathLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||
add(pathLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.browseButton.text")); // NOI18N
|
||||
browseButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@ -181,125 +228,227 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
browseButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
|
||||
add(browseButton, gridBagConstraints);
|
||||
|
||||
pathTextField.setText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.pathTextField.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
add(pathTextField, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.timeZoneLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
add(timeZoneLabel, gridBagConstraints);
|
||||
|
||||
timeZoneComboBox.setMaximumRowCount(30);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
|
||||
add(timeZoneComboBox, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.noFatOrphansCheckbox.text")); // NOI18N
|
||||
noFatOrphansCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.noFatOrphansCheckbox.toolTipText")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
add(noFatOrphansCheckbox, gridBagConstraints);
|
||||
|
||||
errorLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.errorLabel.text")); // NOI18N
|
||||
errorLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
||||
errorLabel.setMaximumSize(new java.awt.Dimension(500, 60));
|
||||
errorLabel.setMinimumSize(new java.awt.Dimension(200, 20));
|
||||
errorLabel.setPreferredSize(new java.awt.Dimension(200, 60));
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 11;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||
add(errorLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(sectorSizeLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.sectorSizeLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 4;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
add(sectorSizeLabel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 4;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
|
||||
add(sectorSizeComboBox, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(sha256HashLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.sha256HashLabel.text")); // NOI18N
|
||||
sha256HashLabel.setEnabled(false);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 9;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
add(sha256HashLabel, gridBagConstraints);
|
||||
|
||||
sha256HashTextField.setText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.sha256HashTextField.text")); // NOI18N
|
||||
sha256HashTextField.setEnabled(false);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 9;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
|
||||
add(sha256HashTextField, gridBagConstraints);
|
||||
|
||||
sha1HashTextField.setText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.sha1HashTextField.text")); // NOI18N
|
||||
sha1HashTextField.setEnabled(false);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 8;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
|
||||
add(sha1HashTextField, gridBagConstraints);
|
||||
|
||||
md5HashTextField.setText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.md5HashTextField.text")); // NOI18N
|
||||
md5HashTextField.setEnabled(false);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 7;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
|
||||
add(md5HashTextField, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(sha1HashLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.sha1HashLabel.text")); // NOI18N
|
||||
sha1HashLabel.setEnabled(false);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 8;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
add(sha1HashLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(md5HashLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.md5HashLabel.text")); // NOI18N
|
||||
md5HashLabel.setEnabled(false);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 7;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
add(md5HashLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(hashValuesLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.hashValuesLabel.text")); // NOI18N
|
||||
hashValuesLabel.setEnabled(false);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 6;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||
add(hashValuesLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(hashValuesNoteLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.hashValuesNoteLabel.text")); // NOI18N
|
||||
hashValuesNoteLabel.setEnabled(false);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 10;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
add(hashValuesNoteLabel, gridBagConstraints);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(pathTextField)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(browseButton)
|
||||
.addGap(2, 2, 2))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(pathLabel)
|
||||
.addComponent(noFatOrphansCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 262, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(0, 368, Short.MAX_VALUE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(errorLabel)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(timeZoneLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(sectorSizeLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(sectorSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(md5HashLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(md5HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(sha1HashLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(sha1HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(sha256HashLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(sha256HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addComponent(hashValuesNoteLabel)
|
||||
.addComponent(hashValuesLabel))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
org.openide.awt.Mnemonics.setLocalizedText(passwordLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.passwordLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 5;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
|
||||
add(passwordLabel, gridBagConstraints);
|
||||
|
||||
passwordTextField.setText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.passwordTextField.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 5;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
|
||||
add(passwordTextField, gridBagConstraints);
|
||||
|
||||
javax.swing.GroupLayout spacerLayout = new javax.swing.GroupLayout(spacer);
|
||||
spacer.setLayout(spacerLayout);
|
||||
spacerLayout.setHorizontalGroup(
|
||||
spacerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(pathLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(browseButton)
|
||||
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(noFatOrphansCheckbox)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(timeZoneLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(sectorSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(sectorSizeLabel))
|
||||
.addGap(39, 39, 39)
|
||||
.addComponent(hashValuesLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(md5HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(md5HashLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(sha1HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(sha1HashLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(sha256HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(sha256HashLabel))
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(hashValuesNoteLabel)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(errorLabel)
|
||||
.addContainerGap(51, Short.MAX_VALUE))
|
||||
spacerLayout.setVerticalGroup(
|
||||
spacerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 12;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(spacer, gridBagConstraints);
|
||||
|
||||
loadingLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/working_spinner.gif"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(loadingLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.loadingLabel.text")); // NOI18N
|
||||
loadingLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
||||
loadingLabel.setMaximumSize(new java.awt.Dimension(500, 60));
|
||||
loadingLabel.setMinimumSize(new java.awt.Dimension(200, 20));
|
||||
loadingLabel.setPreferredSize(new java.awt.Dimension(200, 60));
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 11;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
|
||||
add(loadingLabel, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@NbBundle.Messages({"ImageFilePanel.000.confirmationMessage=The selected file"
|
||||
@ -349,9 +498,12 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
private javax.swing.JLabel errorLabel;
|
||||
private javax.swing.JLabel hashValuesLabel;
|
||||
private javax.swing.JLabel hashValuesNoteLabel;
|
||||
private javax.swing.JLabel loadingLabel;
|
||||
private javax.swing.JLabel md5HashLabel;
|
||||
private javax.swing.JTextField md5HashTextField;
|
||||
private javax.swing.JCheckBox noFatOrphansCheckbox;
|
||||
private javax.swing.JLabel passwordLabel;
|
||||
private javax.swing.JTextField passwordTextField;
|
||||
private javax.swing.JLabel pathLabel;
|
||||
private javax.swing.JTextField pathTextField;
|
||||
private javax.swing.JComboBox<String> sectorSizeComboBox;
|
||||
@ -437,12 +589,34 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
return this.sha256HashTextField.getText();
|
||||
}
|
||||
|
||||
String getPassword() {
|
||||
return this.passwordTextField.getText();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
//reset the UI elements to default
|
||||
pathTextField.setText(null);
|
||||
this.md5HashTextField.setText(null);
|
||||
this.sha1HashTextField.setText(null);
|
||||
this.sha256HashTextField.setText(null);
|
||||
this.passwordTextField.setText(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets UI enabled state.
|
||||
*
|
||||
* @param enabled True
|
||||
*/
|
||||
private void setUIEnabled(boolean enabled, boolean validNonE01) {
|
||||
this.browseButton.setEnabled(enabled);
|
||||
this.noFatOrphansCheckbox.setEnabled(enabled);
|
||||
this.passwordTextField.setEnabled(enabled);
|
||||
this.pathTextField.setEnabled(enabled);
|
||||
this.sectorSizeComboBox.setEnabled(enabled);
|
||||
this.md5HashTextField.setEnabled(enabled && validNonE01);
|
||||
this.sha1HashTextField.setEnabled(enabled && validNonE01);
|
||||
this.sha256HashTextField.setEnabled(enabled && validNonE01);
|
||||
this.timeZoneComboBox.setEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -454,44 +628,99 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
"ImageFilePanel.validatePanel.dataSourceOnCDriveError=Warning: Path to multi-user data source is on \"C:\" drive",
|
||||
"ImageFilePanel.validatePanel.invalidMD5=Invalid MD5 hash",
|
||||
"ImageFilePanel.validatePanel.invalidSHA1=Invalid SHA1 hash",
|
||||
"ImageFilePanel.validatePanel.invalidSHA256=Invalid SHA256 hash",})
|
||||
"ImageFilePanel.validatePanel.invalidSHA256=Invalid SHA256 hash",
|
||||
"# {0} - imageOpenError",
|
||||
"ImageFilePanel_validatePanel_imageOpenError=<html><body><p>An error occurred while opening the image:{0}</p></body></html>",
|
||||
"ImageFilePanel_validatePanel_unknownErrorMsg=<unknown>",
|
||||
"ImageFilePanel_validatePanel_unknownError=<html><body><p>An unknown error occurred while attempting to validate the image</p></body></html>"
|
||||
})
|
||||
public boolean validatePanel() {
|
||||
errorLabel.setVisible(false);
|
||||
return runWithLock(this.validationLock, () -> {
|
||||
boolean validNonE01 = true;
|
||||
try {
|
||||
|
||||
// acquire field values at the beginning to minimize chance of changing while validating.
|
||||
String path = getContentPaths();
|
||||
if (!isImagePathValid()) {
|
||||
|
||||
validNonE01 = isValidNonE01(path);
|
||||
setUIEnabled(false, validNonE01);
|
||||
|
||||
String md5 = getMd5();
|
||||
String sha1 = getSha1();
|
||||
String sha256 = getSha256();
|
||||
String password = getPassword();
|
||||
|
||||
if (!isImagePathValid(path)) {
|
||||
showError(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(getMd5()) && !HashUtility.isValidMd5Hash(getMd5())) {
|
||||
errorLabel.setVisible(true);
|
||||
errorLabel.setText(Bundle.ImageFilePanel_validatePanel_invalidMD5());
|
||||
if (!StringUtils.isBlank(md5) && !HashUtility.isValidMd5Hash(md5)) {
|
||||
showError(Bundle.ImageFilePanel_validatePanel_invalidMD5());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(getSha1()) && !HashUtility.isValidSha1Hash(getSha1())) {
|
||||
errorLabel.setVisible(true);
|
||||
errorLabel.setText(Bundle.ImageFilePanel_validatePanel_invalidSHA1());
|
||||
if (!StringUtils.isBlank(sha1) && !HashUtility.isValidSha1Hash(sha1)) {
|
||||
showError(Bundle.ImageFilePanel_validatePanel_invalidSHA1());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(getSha256()) && !HashUtility.isValidSha256Hash(getSha256())) {
|
||||
errorLabel.setVisible(true);
|
||||
errorLabel.setText(Bundle.ImageFilePanel_validatePanel_invalidSHA256());
|
||||
if (!StringUtils.isBlank(sha256) && !HashUtility.isValidSha256Hash(sha256)) {
|
||||
showError(Bundle.ImageFilePanel_validatePanel_invalidSHA256());
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
TestOpenImageResult testResult = SleuthkitJNI.testOpenImage(path, password);
|
||||
if (!testResult.wasSuccessful()) {
|
||||
showError(Bundle.ImageFilePanel_validatePanel_imageOpenError(
|
||||
StringUtils.defaultIfBlank(
|
||||
testResult.getMessage(),
|
||||
Bundle.ImageFilePanel_validatePanel_unknownErrorMsg())));
|
||||
return false;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
logger.log(Level.SEVERE, "An unknown error occurred test opening image: " + path, t);
|
||||
showError(Bundle.ImageFilePanel_validatePanel_unknownError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PathValidator.isValidForCaseType(path, Case.getCurrentCase().getCaseType())) {
|
||||
errorLabel.setVisible(true);
|
||||
errorLabel.setText(Bundle.ImageFilePanel_validatePanel_dataSourceOnCDriveError());
|
||||
showError(Bundle.ImageFilePanel_validatePanel_dataSourceOnCDriveError());
|
||||
} else {
|
||||
showError(null);
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
setUIEnabled(true, validNonE01);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isImagePathValid() {
|
||||
String path = getContentPaths();
|
||||
/**
|
||||
* Show an error message if error message is non-empty. Otherwise, hide
|
||||
* error message. Either way, hide loading label.
|
||||
*
|
||||
* @param errorMessage The error message to show or null for no error.
|
||||
*/
|
||||
private void showError(String errorMessage) {
|
||||
loadingLabel.setVisible(false);
|
||||
if (StringUtils.isNotBlank(errorMessage)) {
|
||||
errorLabel.setVisible(true);
|
||||
errorLabel.setText(errorMessage);
|
||||
} else {
|
||||
errorLabel.setVisible(false);
|
||||
errorLabel.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if path is valid for processing.
|
||||
*
|
||||
* @param path The path.
|
||||
* @return True if valid for processing.
|
||||
*/
|
||||
private boolean isImagePathValid(String path) {
|
||||
if (StringUtils.isBlank(path) || (!(new File(path).isFile() || DriveUtils.isPhysicalDrive(path) || DriveUtils.isPartition(path)))) {
|
||||
return false;
|
||||
}
|
||||
@ -499,6 +728,15 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the path is a valid image that is not an E01.
|
||||
* @param path The path.
|
||||
* @return True if valid image and not E01.
|
||||
*/
|
||||
private boolean isValidNonE01(String path) {
|
||||
return StringUtils.isNotBlank(path) && isImagePathValid(path) && !path.toLowerCase().endsWith(".e01");
|
||||
}
|
||||
|
||||
public void storeSettings() {
|
||||
String imagePathName = getContentPaths();
|
||||
if (null != imagePathName) {
|
||||
@ -514,21 +752,6 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
updateHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
updateHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
updateHelper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update functions are called by the pathTextField which has this set as
|
||||
* it's DocumentEventListener. Each update function fires a property change
|
||||
@ -539,7 +762,8 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
"ImageFilePanel.moduleErr.msg=A module caused an error listening to ImageFilePanel updates."
|
||||
+ " See log to determine which module. Some data could be incomplete.\n"})
|
||||
private void updateHelper() {
|
||||
if (isImagePathValid() && !getContentPaths().toLowerCase().endsWith(".e01")) {
|
||||
String path = getContentPaths();
|
||||
if (isValidNonE01(path)) {
|
||||
setHashValuesComponentsEnabled(true);
|
||||
} else {
|
||||
setHashValuesComponentsEnabled(false);
|
||||
@ -554,4 +778,119 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
public void select() {
|
||||
pathTextField.requestFocusInWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the supplier action with the reentrant lock or blocks until
|
||||
* acquired.
|
||||
*
|
||||
* @param <T>
|
||||
* @param lock The reentrant lock.
|
||||
* @param action The action to run.
|
||||
* @return The value of the supplier.
|
||||
*/
|
||||
private <T> T runWithLock(ReentrantLock lock, Supplier<T> action) {
|
||||
try {
|
||||
lock.lock();
|
||||
return action.get();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if the panel is on a delay for validating (i.e. typing a
|
||||
* password for bitlocker).
|
||||
*/
|
||||
public boolean isValidationLoading() {
|
||||
return runWithLock(this.validationWaitingLock, () -> this.validateFuture != null
|
||||
&& !this.validateFuture.isCancelled()
|
||||
&& !this.validateFuture.isDone());
|
||||
}
|
||||
|
||||
/**
|
||||
* This class validates on a delay canceling any tasks previously scheduled
|
||||
* so that password validation doesn't lock up the system.
|
||||
*/
|
||||
private class DelayedValidationDocListener implements DocumentListener {
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
delayValidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
delayValidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
delayValidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run validation on a delay to avoid password checking too many times
|
||||
* while typing.
|
||||
*/
|
||||
private void delayValidate() {
|
||||
|
||||
boolean triggerUpdate = runWithLock(validationWaitingLock, () -> {
|
||||
|
||||
boolean toRetTriggerUpdate = false;
|
||||
if (isValidationLoading()) {
|
||||
validateFuture.cancel(true);
|
||||
toRetTriggerUpdate = true;
|
||||
}
|
||||
|
||||
validateAction = new ValidationRunnable();
|
||||
|
||||
validateFuture = delayedValidationService.schedule(
|
||||
validateAction,
|
||||
VALIDATE_TIMEOUT_MILLIS,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
||||
return toRetTriggerUpdate;
|
||||
});
|
||||
|
||||
errorLabel.setVisible(false);
|
||||
loadingLabel.setVisible(true);
|
||||
|
||||
// trigger invalidation after setting up new runnable if not already triggered
|
||||
if (triggerUpdate) {
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runnable to run the updateHelper if the validation action remains
|
||||
* this runnable.
|
||||
*/
|
||||
private class ValidationRunnable implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
boolean isRunningAction = runWithLock(validationWaitingLock, () -> {
|
||||
if (validateAction != this) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the validation action to null to indicate that this is done running and can be validated.
|
||||
validateAction = null;
|
||||
validateFuture = null;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!isRunningAction) {
|
||||
return;
|
||||
} else if (Thread.interrupted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImageFilePanel.this.updateHelper();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
private Host host;
|
||||
private ImageWriterSettings imageWriterSettings;
|
||||
private boolean ignoreFatOrphanFiles;
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Constructs a local drive data source processor that implements the
|
||||
@ -135,7 +136,12 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
*/
|
||||
@Override
|
||||
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
run(null, progressMonitor, callback);
|
||||
run(null, null, progressMonitor, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
run(null, host, progressMonitor, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,7 +160,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
* to return results.
|
||||
*/
|
||||
@Override
|
||||
public void run(Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
public void run(String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
deviceId = UUID.randomUUID().toString();
|
||||
drivePath = configPanel.getContentPath();
|
||||
sectorSize = configPanel.getSectorSize();
|
||||
@ -167,12 +173,13 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
this.host = host;
|
||||
this.password = password;
|
||||
|
||||
Image image;
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{drivePath}, sectorSize,
|
||||
timeZone, null, null, null, deviceId, this.host);
|
||||
timeZone, null, null, null, deviceId, this.password, this.host);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding local disk with path " + drivePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
@ -182,7 +189,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
addDiskTask = new AddImageTask(
|
||||
new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, imageWriterSettings),
|
||||
new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, imageWriterSettings, this.password),
|
||||
progressMonitor,
|
||||
new StreamingAddDataSourceCallbacks(new DefaultIngestStream()),
|
||||
new StreamingAddImageTaskCallback(new DefaultIngestStream(), callback));
|
||||
@ -241,7 +248,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{drivePath}, sectorSize,
|
||||
timeZone, null, null, null, deviceId);
|
||||
timeZone, null, null, null, deviceId, this.password, null);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding local disk with path " + drivePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
@ -250,7 +257,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
addDiskTask = new AddImageTask(new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, imageWriterSettings),
|
||||
addDiskTask = new AddImageTask(new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, imageWriterSettings, this.password),
|
||||
progressMonitor,
|
||||
new StreamingAddDataSourceCallbacks(new DefaultIngestStream()),
|
||||
new StreamingAddImageTaskCallback(new DefaultIngestStream(), callback));
|
||||
|
@ -49,7 +49,9 @@ class CommandLineCommand {
|
||||
DATA_SOURCE_PATH,
|
||||
DATA_SOURCE_ID,
|
||||
INGEST_PROFILE_NAME,
|
||||
REPORT_PROFILE_NAME;
|
||||
REPORT_PROFILE_NAME,
|
||||
BITLOCKER_KEY,
|
||||
;
|
||||
}
|
||||
|
||||
private final CommandType type;
|
||||
|
@ -198,7 +198,8 @@ public class CommandLineIngestManager extends CommandLineManager {
|
||||
}
|
||||
|
||||
String dataSourcePath = inputs.get(CommandLineCommand.InputType.DATA_SOURCE_PATH.name());
|
||||
dataSource = new AutoIngestDataSource(UUID.randomUUID().toString(), Paths.get(dataSourcePath));
|
||||
String password = inputs.get(CommandLineCommand.InputType.BITLOCKER_KEY.name());
|
||||
dataSource = new AutoIngestDataSource(UUID.randomUUID().toString(), Paths.get(dataSourcePath), password);
|
||||
runDataSourceProcessor(caseForJob, dataSource);
|
||||
|
||||
String outputDirPath = getOutputDirPath(caseForJob);
|
||||
@ -406,7 +407,7 @@ public class CommandLineIngestManager extends CommandLineManager {
|
||||
// Get an ordered list of data source processors to try
|
||||
List<AutoIngestDataSourceProcessor> validDataSourceProcessors;
|
||||
try {
|
||||
validDataSourceProcessors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSource.getPath());
|
||||
validDataSourceProcessors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSource.getPath(), dataSource.getPassword());
|
||||
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Exception while determining best data source processor for {0}", dataSource.getPath());
|
||||
// rethrow the exception.
|
||||
@ -429,7 +430,7 @@ public class CommandLineIngestManager extends CommandLineManager {
|
||||
DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId, ingestLock);
|
||||
caseForJob.notifyAddingDataSource(taskId);
|
||||
LOGGER.log(Level.INFO, "Identified data source type for {0} as {1}", new Object[]{dataSource.getPath(), selectedProcessor.getDataSourceType()});
|
||||
selectedProcessor.process(dataSource.getDeviceId(), dataSource.getPath(), progressMonitor, callBack);
|
||||
selectedProcessor.process(dataSource.getDeviceId(), dataSource.getPath(), dataSource.getPassword(), null, progressMonitor, callBack);
|
||||
ingestLock.wait();
|
||||
|
||||
// at this point we got the content object(s) from the current DSP.
|
||||
|
@ -30,6 +30,7 @@ import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.netbeans.api.sendopts.CommandException;
|
||||
import org.netbeans.spi.sendopts.Env;
|
||||
@ -52,6 +53,7 @@ public class CommandLineOptionProcessor extends OptionProcessor {
|
||||
private final Option dataSourcePathOption = Option.requiredArgument('s', "dataSourcePath");
|
||||
private final Option dataSourceObjectIdOption = Option.requiredArgument('i', "dataSourceObjectId");
|
||||
private final Option addDataSourceCommandOption = Option.withoutArgument('a', "addDataSource");
|
||||
private final Option bitlockerKeyCommandOption = Option.requiredArgument('k', "key");
|
||||
private final Option runIngestCommandOption = Option.optionalArgument('r', "runIngest");
|
||||
private final Option listAllDataSourcesCommandOption = Option.withoutArgument('l', "listAllDataSources");
|
||||
private final Option generateReportsOption = Option.optionalArgument('g', "generateReports");
|
||||
@ -81,20 +83,21 @@ public class CommandLineOptionProcessor extends OptionProcessor {
|
||||
|
||||
@Override
|
||||
protected Set<Option> getOptions() {
|
||||
Set<Option> set = new HashSet<>();
|
||||
set.add(createCaseCommandOption);
|
||||
set.add(caseNameOption);
|
||||
set.add(caseTypeOption);
|
||||
set.add(caseBaseDirOption);
|
||||
set.add(dataSourcePathOption);
|
||||
set.add(addDataSourceCommandOption);
|
||||
set.add(dataSourceObjectIdOption);
|
||||
set.add(runIngestCommandOption);
|
||||
set.add(listAllDataSourcesCommandOption);
|
||||
set.add(generateReportsOption);
|
||||
set.add(listAllIngestProfileOption);
|
||||
set.add(defaultArgument);
|
||||
return set;
|
||||
return Set.of(
|
||||
createCaseCommandOption,
|
||||
caseNameOption,
|
||||
caseTypeOption,
|
||||
caseBaseDirOption,
|
||||
dataSourcePathOption,
|
||||
addDataSourceCommandOption,
|
||||
bitlockerKeyCommandOption,
|
||||
dataSourceObjectIdOption,
|
||||
runIngestCommandOption,
|
||||
listAllDataSourcesCommandOption,
|
||||
generateReportsOption,
|
||||
listAllIngestProfileOption,
|
||||
defaultArgument
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -203,6 +206,9 @@ public class CommandLineOptionProcessor extends OptionProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
String[] keysArgs = values.get(bitlockerKeyCommandOption);
|
||||
String bitlockerKey = ArrayUtils.isNotEmpty(keysArgs) ? keysArgs[0] : null;
|
||||
|
||||
String dataSourceId = "";
|
||||
if (values.containsKey(dataSourceObjectIdOption)) {
|
||||
|
||||
@ -247,6 +253,11 @@ public class CommandLineOptionProcessor extends OptionProcessor {
|
||||
newCommand.addInputValue(CommandLineCommand.InputType.CASE_NAME.name(), inputCaseName);
|
||||
newCommand.addInputValue(CommandLineCommand.InputType.CASES_BASE_DIR_PATH.name(), caseBaseDir);
|
||||
newCommand.addInputValue(CommandLineCommand.InputType.DATA_SOURCE_PATH.name(), dataSourcePath);
|
||||
|
||||
if (bitlockerKey != null) {
|
||||
newCommand.addInputValue(CommandLineCommand.InputType.BITLOCKER_KEY.name(), bitlockerKey);
|
||||
}
|
||||
|
||||
commands.add(newCommand);
|
||||
runFromCommandLine(true);
|
||||
}
|
||||
|
@ -129,6 +129,27 @@ public interface DataSourceProcessor {
|
||||
run(progressMonitor, callback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Returns as soon as the background task is started.
|
||||
* The background task uses a callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* This method should not be called unless isPanelValid returns true.
|
||||
*
|
||||
* @param password The password
|
||||
* @param host Host for the data source.
|
||||
* @param progressMonitor Progress monitor that will be used by the
|
||||
* background task to report progress.
|
||||
* @param callback Callback that will be used by the background task
|
||||
* to return results.
|
||||
*/
|
||||
default void run(String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
run(host, progressMonitor, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
@ -176,6 +197,31 @@ public interface DataSourceProcessor {
|
||||
runWithIngestStream(settings, progress, callBack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Files found during ingest will be sent directly to
|
||||
* the IngestStream provided. Returns as soon as the background task is
|
||||
* started. The background task uses a callback object to signal task
|
||||
* completion and return results.
|
||||
*
|
||||
* This method should not be called unless isPanelValid returns true, and
|
||||
* should only be called for DSPs that support ingest streams. The ingest
|
||||
* settings must be complete before calling this method.
|
||||
*
|
||||
* @param password The password to decrypt the data source.
|
||||
* @param host Host for this data source.
|
||||
* @param settings The ingest job settings.
|
||||
* @param progress Progress monitor that will be used by the background task
|
||||
* to report progress.
|
||||
* @param callBack Callback that will be used by the background task to
|
||||
* return results.
|
||||
*/
|
||||
default void runWithIngestStream(String password, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progress,
|
||||
DataSourceProcessorCallback callBack) {
|
||||
runWithIngestStream(host, settings, progress, callBack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this DSP supports ingest streams.
|
||||
*
|
||||
|
@ -21,11 +21,15 @@ package org.sleuthkit.autopsy.coreutils;
|
||||
import org.sleuthkit.datamodel.SleuthkitJNI;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* Utility methods for working with data sources.
|
||||
*/
|
||||
public class DataSourceUtils {
|
||||
private static final Logger logger = Logger.getLogger(DataSourceUtils.class.getName());
|
||||
|
||||
/**
|
||||
* Calls TSK to determine whether a
|
||||
@ -41,4 +45,38 @@ public class DataSourceUtils {
|
||||
public static boolean imageHasFileSystem(Path dataSourcePath) throws IOException {
|
||||
return SleuthkitJNI.isImageSupported(dataSourcePath.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls TSK to determine whether a
|
||||
* potential data source has a file system.
|
||||
*
|
||||
* @param dataSourcePath The path to the data source.
|
||||
* @param password The password to decrypt the image.
|
||||
*
|
||||
* @return True or false.
|
||||
*
|
||||
* @throws IOException if an error occurs while trying to determine if the
|
||||
* data source has a file system.
|
||||
*/
|
||||
public static boolean imageHasFileSystem(Path dataSourcePath, String password) throws IOException {
|
||||
try {
|
||||
SleuthkitJNI.TestOpenImageResult openImageResult = SleuthkitJNI.testOpenImage(dataSourcePath.toString(), password);
|
||||
if (openImageResult.wasSuccessful()) {
|
||||
return true;
|
||||
} else {
|
||||
String message = MessageFormat.format("An error occurred while opening {0}: {1}",
|
||||
dataSourcePath.toString(),
|
||||
openImageResult == null || StringUtils.isBlank(openImageResult.getMessage())
|
||||
? "<unknown>"
|
||||
: openImageResult.getMessage());
|
||||
logger.log(Level.INFO, message);
|
||||
return false;
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
String message = "An error occurred while opening " + dataSourcePath.toString();
|
||||
logger.log(Level.WARNING, message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,13 +30,20 @@ public class AutoIngestDataSource {
|
||||
|
||||
private final String deviceId;
|
||||
private final Path path;
|
||||
private final String password;
|
||||
private DataSourceProcessorResult resultCode;
|
||||
private List<String> errorMessages;
|
||||
private List<Content> content;
|
||||
|
||||
public AutoIngestDataSource(String deviceId, Path path) {
|
||||
|
||||
public AutoIngestDataSource(String deviceId, Path path, String password) {
|
||||
this.deviceId = deviceId;
|
||||
this.path = path;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public AutoIngestDataSource(String deviceId, Path path) {
|
||||
this(deviceId, path, null);
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
@ -47,6 +54,13 @@ public class AutoIngestDataSource {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The password to decrypt the data source.
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public synchronized void setDataSourceProcessorOutput(DataSourceProcessorResult result, List<String> errorMessages, List<Content> content) {
|
||||
this.resultCode = result;
|
||||
this.errorMessages = new ArrayList<>(errorMessages);
|
||||
|
@ -50,6 +50,25 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
|
||||
*/
|
||||
int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException;
|
||||
|
||||
/**
|
||||
* Indicates whether the DataSourceProcessor is capable of processing the
|
||||
* data source. Returns a confidence value. Method can throw an exception
|
||||
* for a system level problem. The exception should not be thrown for an issue
|
||||
* related to bad input data.
|
||||
*
|
||||
* @param dataSourcePath Path to the data source.
|
||||
* @param password The password to decrypt the data source.
|
||||
* @return Confidence value. Values between 0 and 100 are recommended. Zero
|
||||
* or less means the data source is not supported by the
|
||||
* DataSourceProcessor. Value of 100 indicates high certainty in
|
||||
* being able to process the data source.
|
||||
* @throws org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
default int canProcess(Path dataSourcePath, String password) throws AutoIngestDataSourceProcessorException {
|
||||
return canProcess(dataSourcePath);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread by calling DataSourceProcessor.run() method. Returns as
|
||||
@ -91,6 +110,30 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
|
||||
process(deviceId, dataSourcePath, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread by calling DataSourceProcessor.run() method. Returns as
|
||||
* soon as the background task is started. The background task uses a
|
||||
* callback object to signal task completion and return results. Method can
|
||||
* throw an exception for a system level problem. The exception should not
|
||||
* be thrown for an issue related to bad input data.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the device
|
||||
* associated with the data source that is intended
|
||||
* to be unique across multiple cases (e.g., a UUID).
|
||||
* @param dataSourcePath Path to the data source.
|
||||
* @param password The password to decrypt the datasource.
|
||||
* @param host Host for this data source.
|
||||
* @param progressMonitor Progress monitor that will be used by the
|
||||
* background task to report progress.
|
||||
* @param callBack Callback that will be used by the background task
|
||||
* to return results.
|
||||
*/
|
||||
default void process(String deviceId, Path dataSourcePath, String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
process(deviceId, dataSourcePath, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread by calling DataSourceProcessor.run() method. Returns as
|
||||
@ -140,6 +183,33 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
|
||||
return processWithIngestStream(deviceId, dataSourcePath, settings, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread by calling DataSourceProcessor.run() method. Returns as
|
||||
* soon as the background task is started. The background task uses a
|
||||
* callback object to signal task completion and return results. Method can
|
||||
* throw an exception for a system level problem. The exception should not
|
||||
* be thrown for an issue related to bad input data.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the device
|
||||
* associated with the data source that is intended
|
||||
* to be unique across multiple cases (e.g., a UUID).
|
||||
* @param dataSourcePath Path to the data source.
|
||||
* @param password The password to decrypt the datasource.
|
||||
* @param host The host for this data source.
|
||||
* @param settings The ingest job settings.
|
||||
* @param progressMonitor Progress monitor that will be used by the
|
||||
* background task to report progress.
|
||||
* @param callBack Callback that will be used by the background task
|
||||
* to return results.
|
||||
*
|
||||
* @return The new ingest stream or null if an error occurred. Errors will be handled by the callback.
|
||||
*/
|
||||
default IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, String password, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
return processWithIngestStream(deviceId, dataSourcePath, settings, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A custom exception for the use of AutomatedIngestDataSourceProcessor.
|
||||
*/
|
||||
|
@ -49,9 +49,27 @@ public class DataSourceProcessorUtility {
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
public static Map<AutoIngestDataSourceProcessor, Integer> getDataSourceProcessorForFile(Path dataSourcePath, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
|
||||
return getDataSourceProcessorForFile(dataSourcePath, null, processorCandidates);
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to find all Data Source Processors (DSP) that are able
|
||||
* to process the input data source. Only the DSPs that implement
|
||||
* AutoIngestDataSourceProcessor interface are used.
|
||||
*
|
||||
* @param dataSourcePath Full path to the data source
|
||||
* @param password The password to decrypt the data source.
|
||||
* @param processorCandidates Possible DSPs that can handle the data source
|
||||
*
|
||||
* @return Hash map of all DSPs that can process the data source along with
|
||||
* their confidence score
|
||||
* @throws
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
public static Map<AutoIngestDataSourceProcessor, Integer> getDataSourceProcessorForFile(Path dataSourcePath, String password, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
|
||||
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap = new HashMap<>();
|
||||
for (AutoIngestDataSourceProcessor processor : processorCandidates) {
|
||||
int confidence = processor.canProcess(dataSourcePath);
|
||||
int confidence = processor.canProcess(dataSourcePath, password);
|
||||
if (confidence > 0) {
|
||||
validDataSourceProcessorsMap.put(processor, confidence);
|
||||
}
|
||||
@ -76,9 +94,29 @@ public class DataSourceProcessorUtility {
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
public static List<AutoIngestDataSourceProcessor> getOrderedListOfDataSourceProcessors(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
|
||||
return getOrderedListOfDataSourceProcessors(dataSourcePath, (String) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to find all Data Source Processors (DSP) that are able
|
||||
* to process the input data source. Only the DSPs that implement
|
||||
* AutoIngestDataSourceProcessor interface are used. Returns ordered list of
|
||||
* data source processors. DSPs are ordered in descending order from highest
|
||||
* confidence to lowest.
|
||||
*
|
||||
* @param dataSourcePath Full path to the data source
|
||||
* @param password The password to decrypt the data source.
|
||||
*
|
||||
* @return Ordered list of data source processors. DSPs are ordered in
|
||||
* descending order from highest confidence to lowest.
|
||||
*
|
||||
* @throws
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
public static List<AutoIngestDataSourceProcessor> getOrderedListOfDataSourceProcessors(Path dataSourcePath, String password) throws AutoIngestDataSourceProcessorException {
|
||||
// lookup all AutomatedIngestDataSourceProcessors
|
||||
Collection<? extends AutoIngestDataSourceProcessor> processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class);
|
||||
return getOrderedListOfDataSourceProcessors(dataSourcePath, processorCandidates);
|
||||
return getOrderedListOfDataSourceProcessors(dataSourcePath, password, processorCandidates);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,7 +136,28 @@ public class DataSourceProcessorUtility {
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
public static List<AutoIngestDataSourceProcessor> getOrderedListOfDataSourceProcessors(Path dataSourcePath, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
|
||||
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap = getDataSourceProcessorForFile(dataSourcePath, processorCandidates);
|
||||
return getOrderedListOfDataSourceProcessors(dataSourcePath, null, processorCandidates);
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to find all Data Source Processors (DSP) that are able
|
||||
* to process the input data source. Only the DSPs that implement
|
||||
* AutoIngestDataSourceProcessor interface are used. Returns ordered list of
|
||||
* data source processors. DSPs are ordered in descending order from highest
|
||||
* confidence to lowest.
|
||||
*
|
||||
* @param dataSourcePath Full path to the data source
|
||||
* @param password The password to decrypt the data source.
|
||||
* @param processorCandidates Collection of AutoIngestDataSourceProcessor objects to use
|
||||
*
|
||||
* @return Ordered list of data source processors. DSPs are ordered in
|
||||
* descending order from highest confidence to lowest.
|
||||
*
|
||||
* @throws
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
public static List<AutoIngestDataSourceProcessor> getOrderedListOfDataSourceProcessors(Path dataSourcePath, String password, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
|
||||
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap = getDataSourceProcessorForFile(dataSourcePath, password, processorCandidates);
|
||||
return orderDataSourceProcessorsByConfidence(validDataSourceProcessorsMap);
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,12 @@ final class AutoIngestJob implements Comparable<AutoIngestJob>, IngestProgressSn
|
||||
*/
|
||||
private boolean ocrEnabled;
|
||||
|
||||
/**
|
||||
* Version 5 fields
|
||||
*/
|
||||
@GuardedBy("this")
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Constructs a new automated ingest job. All job state not specified in the
|
||||
* job manifest is set to the default state for a new job.
|
||||
@ -166,7 +172,7 @@ final class AutoIngestJob implements Comparable<AutoIngestJob>, IngestProgressSn
|
||||
/*
|
||||
* Version 0 fields.
|
||||
*/
|
||||
this.manifest = new Manifest(nodeData.getManifestFilePath(), nodeData.getManifestFileDate(), nodeData.getCaseName(), nodeData.getDeviceId(), nodeData.getDataSourcePath(), Collections.emptyMap());
|
||||
this.manifest = new Manifest(nodeData.getManifestFilePath(), nodeData.getManifestFileDate(), nodeData.getCaseName(), nodeData.getDeviceId(), nodeData.getDataSourcePath(), nodeData.getPassword(), Collections.emptyMap());
|
||||
this.nodeName = nodeData.getProcessingHostName();
|
||||
this.caseDirectoryPath = nodeData.getCaseDirectoryPath().toString();
|
||||
this.priority = nodeData.getPriority();
|
||||
@ -204,6 +210,11 @@ final class AutoIngestJob implements Comparable<AutoIngestJob>, IngestProgressSn
|
||||
*/
|
||||
this.ocrEnabled = nodeData.getOcrEnabled();
|
||||
|
||||
/**
|
||||
* Version 5 fields
|
||||
*/
|
||||
this.password = nodeData.getPassword();
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new AutoIngestJobException(String.format("Error creating automated ingest job"), ex);
|
||||
}
|
||||
@ -282,6 +293,21 @@ final class AutoIngestJob implements Comparable<AutoIngestJob>, IngestProgressSn
|
||||
this.ocrEnabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The password to decrypt the image.
|
||||
*/
|
||||
synchronized String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param password The password to decrypt the image.
|
||||
*/
|
||||
synchronized void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the processing stage of the job. The start date/time for the stage
|
||||
* is set when the stage is set.
|
||||
|
@ -24,6 +24,7 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Date;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* An object that converts auto ingest job data for an auto ingest job
|
||||
@ -31,7 +32,7 @@ import javax.lang.model.type.TypeKind;
|
||||
*/
|
||||
final class AutoIngestJobNodeData {
|
||||
|
||||
private static final int CURRENT_VERSION = 3;
|
||||
private static final int CURRENT_VERSION = 4;
|
||||
private static final int DEFAULT_PRIORITY = 0;
|
||||
|
||||
/*
|
||||
@ -84,6 +85,12 @@ final class AutoIngestJobNodeData {
|
||||
*/
|
||||
private boolean ocrEnabled;
|
||||
|
||||
/**
|
||||
* Version 4 fields.
|
||||
*/
|
||||
private String password; // password to decrypt the image
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current version of the auto ingest job coordination service node
|
||||
* data.
|
||||
@ -121,6 +128,7 @@ final class AutoIngestJobNodeData {
|
||||
setProcessingStageDetails(job.getProcessingStageDetails());
|
||||
setDataSourceSize(job.getDataSourceSize());
|
||||
setOcrEnabled(job.getOcrEnabled());
|
||||
setPassword(manifest.getPassword());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -157,6 +165,7 @@ final class AutoIngestJobNodeData {
|
||||
this.processingStageDetailsStartDate = 0L;
|
||||
this.dataSourceSize = 0L;
|
||||
this.ocrEnabled = false;
|
||||
this.password = "";
|
||||
|
||||
/*
|
||||
* Get fields from node data.
|
||||
@ -208,6 +217,13 @@ final class AutoIngestJobNodeData {
|
||||
this.ocrEnabled = (1 == ocrFlag);
|
||||
}
|
||||
|
||||
if (buffer.hasRemaining()) {
|
||||
/*
|
||||
* Get version 4 fields.
|
||||
*/
|
||||
setPassword(getStringFromBuffer(buffer, TypeKind.SHORT));
|
||||
}
|
||||
|
||||
} catch (BufferUnderflowException ex) {
|
||||
throw new InvalidDataException("Node data is incomplete", ex);
|
||||
}
|
||||
@ -471,6 +487,22 @@ final class AutoIngestJobNodeData {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The password to decrypt the image. Empty indicates no password.
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param password The password to decrypt the image.
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = StringUtils.defaultString(password);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the processing stage of the job.
|
||||
*
|
||||
@ -604,6 +636,10 @@ final class AutoIngestJobNodeData {
|
||||
if (this.version >= 3) {
|
||||
buffer.putInt(this.ocrEnabled ? 1 : 0);
|
||||
}
|
||||
|
||||
if (this.version >= 4) {
|
||||
putStringIntoBuffer(this.password, buffer, TypeKind.SHORT);
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the array
|
||||
|
@ -2573,7 +2573,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
return null;
|
||||
}
|
||||
String deviceId = manifest.getDeviceId();
|
||||
return new AutoIngestDataSource(deviceId, dataSourcePath);
|
||||
String password = manifest.getPassword();
|
||||
return new AutoIngestDataSource(deviceId, dataSourcePath, password);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2603,7 +2604,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
// Get an ordered list of data source processors to try
|
||||
List<AutoIngestDataSourceProcessor> validDataSourceProcessors;
|
||||
try {
|
||||
validDataSourceProcessors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSource.getPath());
|
||||
validDataSourceProcessors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSource.getPath(), dataSource.getPassword());
|
||||
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
|
||||
sysLogger.log(Level.SEVERE, "Exception while determining best data source processor for {0}", dataSource.getPath());
|
||||
// rethrow the exception. It will get caught & handled upstream and will result in AIM auto-pause.
|
||||
@ -2641,7 +2642,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
jobLogger.logIngestJobSettingsErrors();
|
||||
throw new AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException("Error(s) in ingest job settings for " + manifestPath);
|
||||
}
|
||||
currentIngestStream = selectedProcessor.processWithIngestStream(dataSource.getDeviceId(), dataSource.getPath(), ingestJobSettings, progressMonitor, callBack);
|
||||
currentIngestStream = selectedProcessor.processWithIngestStream(dataSource.getDeviceId(), dataSource.getPath(), dataSource.getPassword(), null, ingestJobSettings, progressMonitor, callBack);
|
||||
if (currentIngestStream == null) {
|
||||
// Either there was a failure to add the data source object to the database or the ingest settings were bad.
|
||||
// An error in the ingest settings is the more likely scenario.
|
||||
@ -2651,7 +2652,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
throw new AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException("Error initializing processing for " + manifestPath + ", probably due to an ingest settings error");
|
||||
}
|
||||
} else {
|
||||
selectedProcessor.process(dataSource.getDeviceId(), dataSource.getPath(), progressMonitor, callBack);
|
||||
selectedProcessor.process(dataSource.getDeviceId(), dataSource.getPath(), dataSource.getPassword(), null, progressMonitor, callBack);
|
||||
}
|
||||
ingestLock.wait();
|
||||
|
||||
|
@ -45,6 +45,7 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
|
||||
private static final String MANIFEST_FILE_NAME_SIGNATURE = "_MANIFEST.XML";
|
||||
private static final String ROOT_ELEM_TAG_NAME = "AutopsyManifest";
|
||||
private static final String CASE_NAME_XPATH = "/AutopsyManifest/CaseName/text()";
|
||||
private static final String PASSWORD_XPATH = "/AutopsyManifest/Password/text()";
|
||||
private static final String DEVICE_ID_XPATH = "/AutopsyManifest/DeviceId/text()";
|
||||
private static final String DATA_SOURCE_NAME_XPATH = "/AutopsyManifest/DataSource/text()";
|
||||
private static final Logger logger = Logger.getLogger(AutopsyManifestFileParser.class.getName());
|
||||
@ -102,7 +103,10 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
|
||||
}
|
||||
Path dataSourcePath = filePath.getParent().resolve(dataSourceName);
|
||||
|
||||
return new Manifest(filePath, dateFileCreated, caseName, deviceId, dataSourcePath, new HashMap<>());
|
||||
expr = xpath.compile(PASSWORD_XPATH);
|
||||
String password = (String) expr.evaluate(doc, XPathConstants.STRING);
|
||||
|
||||
return new Manifest(filePath, dateFileCreated, caseName, deviceId, dataSourcePath, password, new HashMap<>());
|
||||
} catch (Exception ex) {
|
||||
throw new ManifestFileParserException(String.format("Error parsing manifest %s", filePath), ex);
|
||||
} finally {
|
||||
|
@ -42,9 +42,14 @@ public final class Manifest implements Serializable {
|
||||
private final String caseName;
|
||||
private final String deviceId;
|
||||
private final String dataSourceFileName;
|
||||
private final String password;
|
||||
private final Map<String, String> manifestProperties;
|
||||
|
||||
public Manifest(Path manifestFilePath, Date dateFileCreated, String caseName, String deviceId, Path dataSourcePath, Map<String, String> manifestProperties) {
|
||||
this(manifestFilePath, dateFileCreated, caseName, deviceId, dataSourcePath, null, manifestProperties);
|
||||
}
|
||||
|
||||
public Manifest(Path manifestFilePath, Date dateFileCreated, String caseName, String deviceId, Path dataSourcePath, String password, Map<String, String> manifestProperties) {
|
||||
this.filePathString = manifestFilePath.toString();
|
||||
this.filePath = Paths.get(filePathString);
|
||||
|
||||
@ -60,6 +65,7 @@ public final class Manifest implements Serializable {
|
||||
this.dataSourcePath = Paths.get("");
|
||||
dataSourceFileName = "";
|
||||
}
|
||||
this.password = password;
|
||||
this.manifestProperties = new HashMap<>(manifestProperties);
|
||||
}
|
||||
|
||||
@ -91,6 +97,13 @@ public final class Manifest implements Serializable {
|
||||
return dataSourcePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The password to decrypt the data source (may be null).
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public String getDataSourceFileName() {
|
||||
return dataSourceFileName;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user