diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java
index 227bfd0650..e4f03757fb 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java
@@ -41,6 +41,7 @@ class AddImageTask implements Runnable {
private final String deviceId;
private final String imagePath;
private final String timeZone;
+ private final String imageWriterPath;
private final boolean ignoreFatOrphanFiles;
private final DataSourceProcessorProgressMonitor progressMonitor;
private final DataSourceProcessorCallback callback;
@@ -74,15 +75,19 @@ class AddImageTask implements Runnable {
* java.util.TimeZone.getID.
* @param ignoreFatOrphanFiles Whether to parse orphans if the image has a
* FAT filesystem.
+ * @param imageWriterPath Path that a copy of the image should be written to.
+ * Use empty string to disable image writing
* @param progressMonitor Progress monitor to report progress during
* processing.
* @param callback Callback to call when processing is done.
*/
- AddImageTask(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
+ AddImageTask(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, String imageWriterPath,
+ DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
this.deviceId = deviceId;
this.imagePath = imagePath;
this.timeZone = timeZone;
this.ignoreFatOrphanFiles = ignoreFatOrphanFiles;
+ this.imageWriterPath = imageWriterPath;
this.callback = callback;
this.progressMonitor = progressMonitor;
tskAddImageProcessLock = new Object();
@@ -101,7 +106,7 @@ class AddImageTask implements Runnable {
try {
currentCase.getSleuthkitCase().acquireExclusiveLock();
synchronized (tskAddImageProcessLock) {
- tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles);
+ tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles, imageWriterPath);
}
Thread progressUpdateThread = new Thread(new ProgressUpdater(progressMonitor, tskAddImageProcess));
progressUpdateThread.start();
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
index 12184925e9..18c8263b72 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
@@ -241,3 +241,7 @@ LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default
IngestJobInfoPanel.jLabel1.text=Ingest Modules
IngestJobInfoPanel.jLabel2.text=Ingest Jobs
CaseInformationPanel.closeButton.text=Close
+LocalDiskPanel.copyImageCheckbox.text=Make a copy of the disk
+LocalDiskPanel.imageWriterPathLabel.text=jLabel1
+LocalDiskPanel.imageWriterPathDescLabel.text=Will be saved in the case directory as :
+LocalDiskPanel.imageWriterErrorLabel.text=Error Label
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
index 1cceb7ab12..8837c496d0 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
@@ -185,7 +185,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
* @param callback Callback to call when processing is done.
*/
public void run(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
- addImageTask = new AddImageTask(deviceId, imagePath, timeZone, ignoreFatOrphanFiles, progressMonitor, callback);
+ addImageTask = new AddImageTask(deviceId, imagePath, timeZone, ignoreFatOrphanFiles, "", progressMonitor, callback);
new Thread(addImageTask).start();
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java
index 015f7751ea..80d1306598 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java
@@ -54,6 +54,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData
private String deviceId;
private String drivePath;
private String timeZone;
+ private String imageWriterPath = "";
private boolean ignoreFatOrphanFiles;
private boolean setDataSourceOptionsCalled;
@@ -137,8 +138,11 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData
drivePath = configPanel.getContentPaths();
timeZone = configPanel.getTimeZone();
ignoreFatOrphanFiles = configPanel.getNoFatOrphans();
+ if(configPanel.getImageWriterEnabled()){
+ imageWriterPath = configPanel.getImageWriterPath();
+ }
}
- addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, progressMonitor, callback);
+ addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, imageWriterPath, progressMonitor, callback);
new Thread(addDiskTask).start();
}
@@ -164,7 +168,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData
* @param callback Callback to call when processing is done.
*/
public void run(String deviceId, String drivePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
- addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, progressMonitor, callback);
+ addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, imageWriterPath, progressMonitor, callback);
new Thread(addDiskTask).start();
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form
index b1409546e6..4c711c0187 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form
@@ -35,12 +35,21 @@
+
-
+
+
+
+
+
+
+
+
+
-
+
@@ -61,7 +70,16 @@
-
+
+
+
+
+
+
+
+
+
+
@@ -165,5 +183,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java
index 0d485b3392..88a276494d 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java
@@ -22,6 +22,7 @@ import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
+import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
@@ -56,6 +57,7 @@ final class LocalDiskPanel extends JPanel {
private static final long serialVersionUID = 1L;
private List disks;
private LocalDiskModel model;
+ private String fullImageWriterPath = "";
private boolean enableNext = false;
/**
@@ -106,6 +108,10 @@ final class LocalDiskPanel extends JPanel {
timeZoneComboBox = new javax.swing.JComboBox<>();
noFatOrphansCheckbox = new javax.swing.JCheckBox();
descLabel = new javax.swing.JLabel();
+ copyImageCheckbox = new javax.swing.JCheckBox();
+ imageWriterPathLabel = new javax.swing.JLabel();
+ imageWriterPathDescLabel = new javax.swing.JLabel();
+ imageWriterErrorLabel = new javax.swing.JLabel();
setMinimumSize(new java.awt.Dimension(0, 65));
setPreferredSize(new java.awt.Dimension(485, 65));
@@ -132,6 +138,16 @@ final class LocalDiskPanel extends JPanel {
descLabel.setFont(descLabel.getFont().deriveFont(descLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(descLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.descLabel.text")); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(copyImageCheckbox, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.copyImageCheckbox.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(imageWriterPathLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.imageWriterPathLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(imageWriterPathDescLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.imageWriterPathDescLabel.text")); // NOI18N
+
+ imageWriterErrorLabel.setFont(imageWriterErrorLabel.getFont().deriveFont(imageWriterErrorLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
+ imageWriterErrorLabel.setForeground(new java.awt.Color(255, 0, 0));
+ org.openide.awt.Mnemonics.setLocalizedText(imageWriterErrorLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.imageWriterErrorLabel.text")); // NOI18N
+
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@@ -146,10 +162,17 @@ final class LocalDiskPanel extends JPanel {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(noFatOrphansCheckbox)
+ .addComponent(copyImageCheckbox)
.addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21)
- .addComponent(descLabel)))
- .addGap(0, 102, Short.MAX_VALUE))
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(descLabel)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(imageWriterPathDescLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(imageWriterPathLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(imageWriterErrorLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 444, javax.swing.GroupLayout.PREFERRED_SIZE))))
+ .addGap(0, 12, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -167,14 +190,26 @@ final class LocalDiskPanel extends JPanel {
.addComponent(noFatOrphansCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(descLabel)
- .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(copyImageCheckbox)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(imageWriterPathDescLabel)
+ .addComponent(imageWriterPathLabel))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(imageWriterErrorLabel)
+ .addContainerGap(58, Short.MAX_VALUE))
);
}// //GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JCheckBox copyImageCheckbox;
private javax.swing.JLabel descLabel;
private javax.swing.JComboBox diskComboBox;
private javax.swing.JLabel diskLabel;
private javax.swing.JLabel errorLabel;
+ private javax.swing.JLabel imageWriterErrorLabel;
+ private javax.swing.JLabel imageWriterPathDescLabel;
+ private javax.swing.JLabel imageWriterPathLabel;
private javax.swing.JCheckBox noFatOrphansCheckbox;
private javax.swing.JComboBox timeZoneComboBox;
private javax.swing.JLabel timeZoneLabel;
@@ -214,6 +249,36 @@ final class LocalDiskPanel extends JPanel {
boolean getNoFatOrphans() {
return noFatOrphansCheckbox.isSelected();
}
+
+ private void setPotentialImageWriterPath(LocalDisk disk){
+ System.out.println("\n\nsetPotentialImageWriterPath");
+ System.out.println(" name: " + disk.getName());
+ System.out.println(" path: " + disk.getPath());
+ String path = disk.getName().replaceAll("[:]", "");
+ path += ".vhd";
+ System.out.println(" Output file: " + path);
+ imageWriterPathLabel.setText(path);
+ fullImageWriterPath = Case.getCurrentCase().getCaseDirectory() + "\\" + path;
+ }
+
+ private boolean imageWriterPathIsValid(){
+
+ File f = new File(fullImageWriterPath);
+ if(f.exists()) {
+ this.imageWriterErrorLabel.setText("Error - file already exists"); // Put in bundle!!!!
+ return false;
+ }
+ imageWriterErrorLabel.setText("");
+ return true;
+ }
+
+ boolean getImageWriterEnabled(){
+ return copyImageCheckbox.isSelected();
+ }
+
+ String getImageWriterPath(){
+ return fullImageWriterPath;
+ }
/**
* Should we enable the wizard's next button? Always return true because we
@@ -222,6 +287,11 @@ final class LocalDiskPanel extends JPanel {
* @return true
*/
public boolean validatePanel() {
+ if(copyImageCheckbox.isSelected() &&
+ ! imageWriterPathIsValid()){
+ return false;
+ }
+
return enableNext;
}
@@ -318,6 +388,7 @@ final class LocalDiskPanel extends JPanel {
if (ready) {
selected = (LocalDisk) anItem;
enableNext = true;
+ setPotentialImageWriterPath((LocalDisk) selected);
try {
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);