Merge commit 'refs/pull/7927/head' of https://github.com/sleuthkit/autopsy into develop

This commit is contained in:
mmckinnon_admin 2025-01-03 16:32:21 -05:00
commit 777bea09d3
14 changed files with 676 additions and 255 deletions

View File

@ -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() {

View File

@ -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();
}
}
}
}

View File

@ -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...

View File

@ -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...

View File

@ -82,6 +82,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 +163,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();
}
/**
@ -206,7 +209,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
this.host = host;
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,7 +218,7 @@ 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);
}
/**
@ -270,7 +273,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
// 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);
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<>();
@ -290,7 +293,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
ingestStream = new DefaultIngestStream();
}
doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, progress, callBack);
doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, this.password, progress, callBack);
}
/**
@ -315,6 +318,10 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
if (sha256.isEmpty()) {
sha256 = null;
}
password = configPanel.getPassword();
if (password.isEmpty()) {
password = null;
}
}
/**
@ -352,7 +359,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, this.password, 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,7 +368,7 @@ 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);
}
/**
@ -389,11 +396,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 +421,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 +457,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
timeZone = null;
ignoreFatOrphanFiles = false;
host = null;
password = null;
configPanel.reset();
}
@ -470,10 +479,20 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
}
try {
// 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;
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);
@ -501,7 +520,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
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,7 +529,7 @@ 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, null, progressMonitor, callBack);
}
@Override
@ -531,7 +550,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
// 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, 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<>();
@ -551,7 +570,7 @@ 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, null, progressMonitor, callBack);
return ingestStream;
}

View File

@ -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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</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="&lt;String&gt;"/>
</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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</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="&lt;String&gt;"/>
</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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</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>

View File

@ -18,9 +18,14 @@
*/
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.logging.Level;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
@ -32,11 +37,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 +52,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 +64,13 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
private final String contextName;
private final List<FileFilter> fileChooserFilters;
private static int VALIDATE_TIMEOUT_MILLIS = 1200;
static ScheduledThreadPoolExecutor delayedValidationService = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("ImageFilePanel delayed validation").build());
private final Object validateActionLock = new Object();
private Runnable validateAction = null;
private Future<?> validateFuture = null;
/**
* Creates new form ImageFilePanel
*
@ -76,6 +93,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
sectorSizeComboBox.setSelectedIndex(0);
errorLabel.setVisible(false);
loadingLabel.setVisible(false);
this.fileChooserFilters = fileChooserFilters;
}
@ -105,11 +123,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 +153,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 +179,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 +198,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 +224,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 +494,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 +585,17 @@ 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);
}
/**
@ -454,41 +607,75 @@ 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);
String path = getContentPaths();
if (!isImagePathValid()) {
showError(null);
return false;
}
if (!StringUtils.isBlank(getMd5()) && !HashUtility.isValidMd5Hash(getMd5())) {
errorLabel.setVisible(true);
errorLabel.setText(Bundle.ImageFilePanel_validatePanel_invalidMD5());
showError(Bundle.ImageFilePanel_validatePanel_invalidMD5());
return false;
}
if (!StringUtils.isBlank(getSha1()) && !HashUtility.isValidSha1Hash(getSha1())) {
errorLabel.setVisible(true);
errorLabel.setText(Bundle.ImageFilePanel_validatePanel_invalidSHA1());
showError(Bundle.ImageFilePanel_validatePanel_invalidSHA1());
return false;
}
if (!StringUtils.isBlank(getSha256()) && !HashUtility.isValidSha256Hash(getSha256())) {
errorLabel.setVisible(true);
errorLabel.setText(Bundle.ImageFilePanel_validatePanel_invalidSHA256());
showError(Bundle.ImageFilePanel_validatePanel_invalidSHA256());
return false;
}
try {
String password = this.getPassword();
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;
}
/**
* 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("");
}
}
private boolean isImagePathValid() {
String path = getContentPaths();
@ -499,6 +686,16 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
return true;
}
/**
* @return True if the panel is on a delay for validating (i.e. typing a
* password for bitlocker).
*/
public boolean isValidationLoading() {
synchronized (this.validateActionLock) {
return this.validateAction != null;
}
}
public void storeSettings() {
String imagePathName = getContentPaths();
if (null != imagePathName) {
@ -514,21 +711,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
@ -554,4 +736,86 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
public void select() {
pathTextField.requestFocusInWindow();
}
/**
* 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 = false;
synchronized (ImageFilePanel.this.validateActionLock) {
if (ImageFilePanel.this.validateFuture != null &&
!ImageFilePanel.this.validateFuture.isCancelled() &&
!ImageFilePanel.this.validateFuture.isDone()) {
ImageFilePanel.this.validateFuture.cancel(true);
triggerUpdate = true;
}
ImageFilePanel.this.validateAction = new ValidationRunnable();
ImageFilePanel.this.validateFuture = ImageFilePanel.this.delayedValidationService.schedule(
ImageFilePanel.this.validateAction,
VALIDATE_TIMEOUT_MILLIS,
TimeUnit.MILLISECONDS);
}
// trigger invalidation after setting up new runnable if not already triggered
if (triggerUpdate) {
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
}
errorLabel.setVisible(false);
if (!ImageFilePanel.this.loadingLabel.isVisible()) {
ImageFilePanel.this.loadingLabel.setVisible(true);
}
}
/**
* Runnable to run the updateHelper if the validation action remains
* this runnable.
*/
private class ValidationRunnable implements Runnable {
@Override
public void run() {
if (Thread.interrupted()) {
return;
}
synchronized (ImageFilePanel.this.validateActionLock) {
if (ImageFilePanel.this.validateAction != this) {
return;
}
// set the validation action to null to indicate that this is done running and can be validated.
ImageFilePanel.this.validateAction = null;
ImageFilePanel.this.validateFuture = null;
}
ImageFilePanel.this.updateHelper();
}
}
}
}

View File

@ -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
@ -182,7 +183,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, password),
progressMonitor,
new StreamingAddDataSourceCallbacks(new DefaultIngestStream()),
new StreamingAddImageTaskCallback(new DefaultIngestStream(), callback));
@ -250,7 +251,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, password),
progressMonitor,
new StreamingAddDataSourceCallbacks(new DefaultIngestStream()),
new StreamingAddImageTaskCallback(new DefaultIngestStream(), callback));

View File

@ -21,6 +21,8 @@ package org.sleuthkit.autopsy.coreutils;
import org.sleuthkit.datamodel.SleuthkitJNI;
import java.io.IOException;
import java.nio.file.Path;
import java.text.MessageFormat;
import org.apache.commons.lang3.StringUtils;
/**
* Utility methods for working with data sources.
@ -41,4 +43,25 @@ public class DataSourceUtils {
public static boolean imageHasFileSystem(Path dataSourcePath) throws IOException {
return SleuthkitJNI.isImageSupported(dataSourcePath.toString());
}
public static boolean imageHasFileSystem(Path dataSourcePath, String password) throws IOException {
try {
// LOGGER.info("Testing if disk image {} can be opened", hostPath);
SleuthkitJNI.TestOpenImageResult openImageResult = SleuthkitJNI.testOpenImage(dataSourcePath.toString(), password);
if (!openImageResult.wasSuccessful()) {
String message = MessageFormat.format("An error occurred while opening {0}: {1}",
dataSourcePath.toString(),
openImageResult == null || StringUtils.isBlank(openImageResult.getMessage())
? "<unknown>"
: openImageResult.getMessage());
return false;
}
} catch (Throwable ex) {
String message = "An error occurred while opening " + dataSourcePath.toString();
return false;
}
return SleuthkitJNI.isImageSupported(dataSourcePath.toString());
}
}

View File

@ -62,7 +62,7 @@
<!-- for viewers -->
<dependency conf="autopsy_core->default" org="org.freedesktop.gstreamer" name="gst1-java-core" rev="1.4.0"/>
<dependency conf="autopsy_core->default" org="net.java.dev.jna" name="jna-platform" rev="5.15.0"/>
<dependency conf="autopsy_core->default" org="net.java.dev.jna" name="jna-platform" rev="5.16.0"/>
<!-- for file search -->
<dependency conf="autopsy_core->default" org="com.github.lgooddatepicker" name="LGoodDatePicker" rev="11.2.1"/>

View File

@ -118,8 +118,8 @@ file.reference.jericho-html-3.4.jar=release/modules/ext/jericho-html-3.4.jar
file.reference.jfxtras-common-17-r1.jar=release/modules/ext/jfxtras-common-17-r1.jar
file.reference.jfxtras-controls-17-r1.jar=release/modules/ext/jfxtras-controls-17-r1.jar
file.reference.jfxtras-fxml-17-r1.jar=release/modules/ext/jfxtras-fxml-17-r1.jar
file.reference.jna-5.15.0.jar=release/modules/ext/jna-5.15.0.jar
file.reference.jna-platform-5.15.0.jar=release/modules/ext/jna-platform-5.15.0.jar
file.reference.jna-5.16.0.jar=release/modules/ext/jna-5.16.0.jar
file.reference.jna-platform-5.16.0.jar=release/modules/ext/jna-platform-5.16.0.jar
file.reference.joda-time-2.10.14.jar=release/modules/ext/joda-time-2.10.14.jar
file.reference.jsr305-3.0.2.jar=release/modules/ext/jsr305-3.0.2.jar
file.reference.LGoodDatePicker-11.2.1.jar=release/modules/ext/LGoodDatePicker-11.2.1.jar

View File

@ -1041,12 +1041,12 @@
<binary-origin>release/modules/ext/jfxtras-fxml-17-r1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jna-5.15.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jna-5.15.0.jar</binary-origin>
<runtime-relative-path>ext/jna-5.16.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jna-5.16.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jna-platform-5.15.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jna-platform-5.15.0.jar</binary-origin>
<runtime-relative-path>ext/jna-platform-5.16.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jna-platform-5.16.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/joda-time-2.10.14.jar</runtime-relative-path>

View File

@ -64,7 +64,7 @@ file.reference.jdom2-2.0.6.1.jar=release/modules/ext/jdom2-2.0.6.1.jar
file.reference.jempbox-1.8.16.jar=release/modules/ext/jempbox-1.8.16.jar
file.reference.jhighlight-1.0.3.jar=release/modules/ext/jhighlight-1.0.3.jar
file.reference.jmatio-1.5.jar=release/modules/ext/jmatio-1.5.jar
file.reference.jna-5.15.0.jar=release/modules/ext/jna-5.15.0.jar
file.reference.jna-5.16.0.jar=release/modules/ext/jna-5.16.0.jar
file.reference.joda-time-2.2.jar=release/modules/ext/joda-time-2.2.jar
file.reference.json-simple-1.1.1.jar=release/modules/ext/json-simple-1.1.1.jar
file.reference.jsr305-3.0.2.jar=release/modules/ext/jsr305-3.0.2.jar

View File

@ -620,8 +620,8 @@
<binary-origin>release/modules/ext/jmatio-1.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jna-5.15.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jna-5.15.0.jar</binary-origin>
<runtime-relative-path>ext/jna-5.16.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jna-5.16.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/joda-time-2.2.jar</runtime-relative-path>