mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-14 17:06:16 +00:00
commit
9f50dd1860
356
Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java
Normal file
356
Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java
Normal file
@ -0,0 +1,356 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.SleuthkitJNI;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
|
||||
/*
|
||||
* A background task (swingworker) that adds the given image to
|
||||
* database using the Sleuthkit JNI interface.
|
||||
*
|
||||
* It updates the given ProgressMonitor as it works through adding the image,
|
||||
* and et the end, calls the specified Callback.
|
||||
*/
|
||||
public class AddImageTask implements Runnable {
|
||||
|
||||
private Logger logger = Logger.getLogger(AddImageTask.class.getName());
|
||||
|
||||
private Case currentCase;
|
||||
// true if the process was requested to stop
|
||||
private volatile boolean cancelled = false;
|
||||
//true if revert has been invoked.
|
||||
private boolean reverted = false;
|
||||
private boolean hasCritError = false;
|
||||
|
||||
private volatile boolean addImageDone = false;
|
||||
|
||||
private List<String> errorList = new ArrayList<String>();
|
||||
|
||||
private DSPProgressMonitor progressMonitor;
|
||||
private DSPCallback callbackObj;
|
||||
|
||||
private final List<Content> newContents = Collections.synchronizedList(new ArrayList<Content>());
|
||||
|
||||
private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess;
|
||||
private Thread dirFetcher;
|
||||
|
||||
private String imagePath;
|
||||
private String dataSourcetype;
|
||||
String timeZone;
|
||||
boolean noFatOrphans;
|
||||
|
||||
|
||||
/*
|
||||
* A Swingworker that updates the progressMonitor with the name of the
|
||||
* directory currently being processed by the AddImageTask
|
||||
*/
|
||||
private class CurrentDirectoryFetcher implements Runnable {
|
||||
|
||||
DSPProgressMonitor progressMonitor;
|
||||
SleuthkitJNI.CaseDbHandle.AddImageProcess process;
|
||||
|
||||
CurrentDirectoryFetcher(DSPProgressMonitor aProgressMonitor, SleuthkitJNI.CaseDbHandle.AddImageProcess proc) {
|
||||
this.progressMonitor = aProgressMonitor;
|
||||
this.process = proc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the currently processing directory
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
String currDir = process.currentDirectory();
|
||||
if (currDir != null) {
|
||||
if (!currDir.isEmpty() ) {
|
||||
progressMonitor.setProgressText("Adding: " + currDir);
|
||||
}
|
||||
}
|
||||
Thread.sleep(2 * 1000);
|
||||
}
|
||||
return;
|
||||
} catch (InterruptedException ie) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected AddImageTask(String imgPath, String tz, boolean noOrphans, DSPProgressMonitor aProgressMonitor, DSPCallback cbObj ) {
|
||||
|
||||
currentCase = Case.getCurrentCase();
|
||||
|
||||
|
||||
this.imagePath = imgPath;
|
||||
this.timeZone = tz;
|
||||
this.noFatOrphans = noOrphans;
|
||||
|
||||
this.callbackObj = cbObj;
|
||||
this.progressMonitor = aProgressMonitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the addImage process, but does not commit the results.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
|
||||
errorList.clear();
|
||||
|
||||
//lock DB for writes in this thread
|
||||
SleuthkitCase.dbWriteLock();
|
||||
|
||||
addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans);
|
||||
dirFetcher = new Thread( new CurrentDirectoryFetcher(progressMonitor, addImageProcess));
|
||||
|
||||
try {
|
||||
progressMonitor.setIndeterminate(true);
|
||||
progressMonitor.setProgress(0);
|
||||
|
||||
dirFetcher.start();
|
||||
|
||||
addImageProcess.run(new String[]{this.imagePath});
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Core errors occurred while running add image. ", ex);
|
||||
//critical core/system error and process needs to be interrupted
|
||||
hasCritError = true;
|
||||
errorList.add(ex.getMessage());
|
||||
} catch (TskDataException ex) {
|
||||
logger.log(Level.WARNING, "Data errors occurred while running add image. ", ex);
|
||||
errorList.add(ex.getMessage());
|
||||
}
|
||||
finally {
|
||||
|
||||
}
|
||||
|
||||
// handle addImage done
|
||||
postProcess();
|
||||
|
||||
// unclock the DB
|
||||
SleuthkitCase.dbWriteUnlock();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the newly added image to DB
|
||||
*
|
||||
*
|
||||
* @throws Exception if commit or adding the image to the case failed
|
||||
*/
|
||||
private void commitImage() throws Exception {
|
||||
|
||||
long imageId = 0;
|
||||
try {
|
||||
imageId = addImageProcess.commit();
|
||||
} catch (TskException e) {
|
||||
logger.log(Level.WARNING, "Errors occured while committing the image", e);
|
||||
errorList.add(e.getMessage());
|
||||
} finally {
|
||||
|
||||
if (imageId != 0) {
|
||||
// get the newly added Image so we can return to caller
|
||||
Image newImage = currentCase.getSleuthkitCase().getImageById(imageId);
|
||||
|
||||
//while we have the image, verify the size of its contents
|
||||
String verificationErrors = newImage.verifyImageSize();
|
||||
if (verificationErrors.equals("") == false) {
|
||||
//data error (non-critical)
|
||||
errorList.add(verificationErrors);
|
||||
}
|
||||
|
||||
// Add the image to the list of new content
|
||||
newContents.add(newImage);
|
||||
}
|
||||
|
||||
logger.log(Level.INFO, "Image committed, imageId: " + imageId);
|
||||
logger.log(Level.INFO, PlatformUtil.getAllMemUsageInfo());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Post processing after the addImageProcess is done.
|
||||
*
|
||||
*/
|
||||
private void postProcess() {
|
||||
|
||||
|
||||
// cancel the directory fetcher
|
||||
dirFetcher.interrupt();
|
||||
|
||||
addImageDone = true;
|
||||
// attempt actions that might fail and force the process to stop
|
||||
|
||||
if (cancelled || hasCritError) {
|
||||
logger.log(Level.INFO, "Handling errors or interruption that occured in add image process");
|
||||
revert();
|
||||
}
|
||||
if (!errorList.isEmpty()) {
|
||||
logger.log(Level.INFO, "Handling non-critical errors that occured in add image process");
|
||||
}
|
||||
|
||||
// When everything happens without an error:
|
||||
if (!(cancelled || hasCritError)) {
|
||||
|
||||
try {
|
||||
// Tell the progress monitor we're done
|
||||
progressMonitor.setProgress(100);
|
||||
|
||||
if (newContents.isEmpty()) {
|
||||
if (addImageProcess != null) { // and if we're done configuring ingest
|
||||
// commit anything
|
||||
try {
|
||||
commitImage();
|
||||
} catch (Exception ex) {
|
||||
errorList.add(ex.getMessage());
|
||||
// Log error/display warning
|
||||
logger.log(Level.SEVERE, "Error adding image to case.", ex);
|
||||
}
|
||||
} else {
|
||||
logger.log(Level.SEVERE, "Missing image process object");
|
||||
}
|
||||
}
|
||||
|
||||
else { //already commited?
|
||||
logger.log(Level.INFO, "Assuming image already committed, will not commit.");
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
//handle unchecked exceptions post image add
|
||||
errorList.add(ex.getMessage());
|
||||
|
||||
logger.log(Level.WARNING, "Unexpected errors occurred while running post add image cleanup. ", ex);
|
||||
logger.log(Level.SEVERE, "Error adding image to case", ex);
|
||||
} finally {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// invoke the callBack, unless the caller cancelled
|
||||
if (!cancelled) {
|
||||
doCallBack();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Call the callback with results, new content, and errors, if any
|
||||
*/
|
||||
private void doCallBack()
|
||||
{
|
||||
DSPCallback.DSP_Result result;
|
||||
|
||||
if (hasCritError) {
|
||||
result = DSPCallback.DSP_Result.CRITICAL_ERRORS;
|
||||
}
|
||||
else if (!errorList.isEmpty()) {
|
||||
result = DSPCallback.DSP_Result.NONCRITICAL_ERRORS;
|
||||
}
|
||||
else {
|
||||
result = DSPCallback.DSP_Result.NO_ERRORS;
|
||||
}
|
||||
|
||||
// invoke the callcak, passing it the result, list of new contents, and list of errors
|
||||
callbackObj.done(result, errorList, newContents);
|
||||
}
|
||||
|
||||
/*
|
||||
* cancel the image addition, if possible
|
||||
*/
|
||||
public void cancelTask() {
|
||||
|
||||
cancelled = true;
|
||||
|
||||
if (!addImageDone) {
|
||||
try {
|
||||
interrupt();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Failed to interrup the add image task...");
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
revert();
|
||||
}
|
||||
catch(Exception ex) {
|
||||
logger.log(Level.SEVERE, "Failed to revert the add image task...");
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Interrurp the add image process if it is still running
|
||||
*/
|
||||
private void interrupt() throws Exception {
|
||||
|
||||
try {
|
||||
logger.log(Level.INFO, "interrupt() add image process");
|
||||
addImageProcess.stop(); //it might take time to truly stop processing and writing to db
|
||||
} catch (TskException ex) {
|
||||
throw new Exception("Error stopping add-image process.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Revert - if image has already been added but not committed yet
|
||||
*/
|
||||
void revert() {
|
||||
|
||||
if (!reverted) {
|
||||
try {
|
||||
logger.log(Level.INFO, "Revert after add image process");
|
||||
try {
|
||||
addImageProcess.revert();
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error reverting add image process", ex);
|
||||
}
|
||||
} finally {
|
||||
|
||||
}
|
||||
reverted = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -18,7 +18,9 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.EventQueue;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
@ -27,6 +29,7 @@ import javax.swing.event.ChangeListener;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor;
|
||||
|
||||
/**
|
||||
* The final panel of the add image wizard. It displays a progress bar and
|
||||
@ -50,6 +53,49 @@ class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePa
|
||||
private AddImageWizardAddingProgressVisual component;
|
||||
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
|
||||
|
||||
private DSPProgressMonitorImpl dspProgressMonitorImpl = new DSPProgressMonitorImpl();
|
||||
|
||||
public DSPProgressMonitorImpl getDSPProgressMonitorImpl() {
|
||||
return dspProgressMonitorImpl;
|
||||
}
|
||||
|
||||
private class DSPProgressMonitorImpl implements DSPProgressMonitor {
|
||||
@Override
|
||||
public void setIndeterminate(final boolean indeterminate) {
|
||||
// update the progress bar asynchronously
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getComponent().getProgressBar().setIndeterminate(indeterminate);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgress(final int progress) {
|
||||
// update the progress bar asynchronously
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getComponent().getProgressBar().setValue(progress);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgressText(final String text) {
|
||||
// update the progress UI asynchronously
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getComponent().setProgressMsgText(text);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* Get the visual component for the panel. In this template, the component
|
||||
* is kept separate. This can be more efficient: if the wizard is created
|
||||
|
@ -142,7 +142,7 @@
|
||||
<Component id="subTitle2Label" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="progressLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="subTitle1Label" alignment="0" max="32767" attributes="1"/>
|
||||
<Component id="TextArea_CurrentDirectory" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="progressTextArea" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="progressBar" alignment="0" max="32767" attributes="1"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="8" max="32767" attributes="0"/>
|
||||
@ -158,7 +158,7 @@
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="progressBar" min="-2" pref="23" max="-2" attributes="1"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="TextArea_CurrentDirectory" min="-2" pref="91" max="-2" attributes="0"/>
|
||||
<Component id="progressTextArea" min="-2" pref="91" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="progressLabel" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@ -185,7 +185,7 @@
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="4"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextArea" name="TextArea_CurrentDirectory">
|
||||
<Component class="javax.swing.JTextArea" name="progressTextArea">
|
||||
<Properties>
|
||||
<Property name="editable" type="boolean" value="false"/>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
@ -196,11 +196,11 @@
|
||||
<Property name="wrapStyleWord" type="boolean" value="true"/>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Currently Adding:">
|
||||
<TitledBorder title="Status">
|
||||
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageWizardAddingProgressVisual.TextArea_CurrentDirectory.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageWizardAddingProgressVisual.progressTextArea.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
|
@ -71,7 +71,7 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel {
|
||||
donePanel.setVisible(false);
|
||||
viewLogButton.setVisible(false);
|
||||
//match visual background of panel
|
||||
this.TextArea_CurrentDirectory.setBackground(this.getBackground());
|
||||
this.progressTextArea.setBackground(this.getBackground());
|
||||
|
||||
}
|
||||
|
||||
@ -95,10 +95,10 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel {
|
||||
/**
|
||||
* Updates the currently processing directory
|
||||
*
|
||||
* @param dir the text to update with
|
||||
* @param msg the text to update with
|
||||
*/
|
||||
public void setCurrentDirText(String dir) {
|
||||
this.TextArea_CurrentDirectory.setText(dir);
|
||||
public void setProgressMsgText(String msg) {
|
||||
this.progressTextArea.setText(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,7 +140,7 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel {
|
||||
inProgressPanel = new javax.swing.JPanel();
|
||||
progressBar = new javax.swing.JProgressBar();
|
||||
progressLabel = new javax.swing.JLabel();
|
||||
TextArea_CurrentDirectory = new javax.swing.JTextArea();
|
||||
progressTextArea = new javax.swing.JTextArea();
|
||||
subTitle2Label = new javax.swing.JLabel();
|
||||
subTitle1Label = new javax.swing.JLabel();
|
||||
|
||||
@ -193,14 +193,14 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel {
|
||||
org.openide.awt.Mnemonics.setLocalizedText(progressLabel, org.openide.util.NbBundle.getMessage(AddImageWizardAddingProgressVisual.class, "AddImageWizardAddingProgressVisual.progressLabel.text")); // NOI18N
|
||||
progressLabel.setPreferredSize(null);
|
||||
|
||||
TextArea_CurrentDirectory.setEditable(false);
|
||||
TextArea_CurrentDirectory.setBackground(new java.awt.Color(240, 240, 240));
|
||||
TextArea_CurrentDirectory.setLineWrap(true);
|
||||
TextArea_CurrentDirectory.setRows(5);
|
||||
TextArea_CurrentDirectory.setWrapStyleWord(true);
|
||||
TextArea_CurrentDirectory.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(AddImageWizardAddingProgressVisual.class, "AddImageWizardAddingProgressVisual.TextArea_CurrentDirectory.border.title"))); // NOI18N
|
||||
TextArea_CurrentDirectory.setCursor(new java.awt.Cursor(java.awt.Cursor.TEXT_CURSOR));
|
||||
TextArea_CurrentDirectory.setFocusable(false);
|
||||
progressTextArea.setEditable(false);
|
||||
progressTextArea.setBackground(new java.awt.Color(240, 240, 240));
|
||||
progressTextArea.setLineWrap(true);
|
||||
progressTextArea.setRows(5);
|
||||
progressTextArea.setWrapStyleWord(true);
|
||||
progressTextArea.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(AddImageWizardAddingProgressVisual.class, "AddImageWizardAddingProgressVisual.progressTextArea.border.title"))); // NOI18N
|
||||
progressTextArea.setCursor(new java.awt.Cursor(java.awt.Cursor.TEXT_CURSOR));
|
||||
progressTextArea.setFocusable(false);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(subTitle2Label, org.openide.util.NbBundle.getMessage(AddImageWizardAddingProgressVisual.class, "AddImageWizardAddingProgressVisual.subTitle2Label.text")); // NOI18N
|
||||
|
||||
@ -216,7 +216,7 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel {
|
||||
.addComponent(subTitle2Label)
|
||||
.addComponent(progressLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(subTitle1Label, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(TextArea_CurrentDirectory)
|
||||
.addComponent(progressTextArea)
|
||||
.addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGap(0, 8, Short.MAX_VALUE))
|
||||
);
|
||||
@ -229,7 +229,7 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel {
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(TextArea_CurrentDirectory, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(progressTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(progressLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
@ -268,12 +268,12 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel {
|
||||
dialog.setVisible(true);
|
||||
}//GEN-LAST:event_viewLogButtonActionPerformed
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
protected javax.swing.JTextArea TextArea_CurrentDirectory;
|
||||
protected javax.swing.JPanel donePanel;
|
||||
protected javax.swing.JPanel inProgressPanel;
|
||||
private javax.swing.JPanel loadingPanel;
|
||||
private javax.swing.JProgressBar progressBar;
|
||||
protected javax.swing.JLabel progressLabel;
|
||||
protected javax.swing.JTextArea progressTextArea;
|
||||
protected javax.swing.JLabel statusLabel;
|
||||
protected javax.swing.JLabel subTitle1Label;
|
||||
protected javax.swing.JLabel subTitle2Label;
|
||||
|
@ -43,6 +43,7 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
|
||||
* The visual component that displays this panel. If you need to access the
|
||||
* component from this class, just use getComponent().
|
||||
*/
|
||||
private AddImageWizardAddingProgressPanel progressPanel;
|
||||
private AddImageWizardChooseDataSourceVisual component;
|
||||
private boolean isNextEnable = false;
|
||||
private static final String PROP_LASTDATASOURCE_PATH = "LBL_LastDataSource_PATH";
|
||||
@ -50,6 +51,12 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
|
||||
// paths to any set hash lookup databases (can be null)
|
||||
private String NSRLPath, knownBadPath;
|
||||
|
||||
|
||||
AddImageWizardChooseDataSourcePanel(AddImageWizardAddingProgressPanel proPanel) {
|
||||
|
||||
this.progressPanel = proPanel;
|
||||
|
||||
}
|
||||
/**
|
||||
* Get the visual component for the panel. In this template, the component
|
||||
* is kept separate. This can be more efficient: if the wizard is created
|
||||
@ -173,13 +180,6 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
|
||||
|
||||
// Prepopulate the image directory from the properties file
|
||||
try {
|
||||
String lastDataSourceDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_LASTDATASOURCE_PATH);
|
||||
String lastDataSourceType = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_LASTDATASOURCE_TYPE);
|
||||
|
||||
//set the last path for the content panel for which it was saved
|
||||
if (component.getContentType().toString().equals(lastDataSourceType)) {
|
||||
component.setContentPath(lastDataSourceDirectory);
|
||||
}
|
||||
|
||||
// Load hash database settings, enable or disable the checkbox
|
||||
this.NSRLPath = null;
|
||||
@ -216,19 +216,8 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
|
||||
*/
|
||||
@Override
|
||||
public void storeSettings(WizardDescriptor settings) {
|
||||
settings.putProperty(AddImageAction.DATASOURCEPATH_PROP, getComponent().getContentPaths());
|
||||
settings.putProperty(AddImageAction.DATASOURCETYPE_PROP, getComponent().getContentType());
|
||||
settings.putProperty(AddImageAction.TIMEZONE_PROP, getComponent().getSelectedTimezone()); // store the timezone
|
||||
settings.putProperty(AddImageAction.NOFATORPHANS_PROP, Boolean.valueOf(getComponent().getNoFatOrphans()));
|
||||
//settings.putProperty(AddImageAction.LOOKUPFILES_PROP, getComponent().getLookupFilesCheckboxChecked());
|
||||
//settings.putProperty(AddImageAction.SOLR_PROP, getComponent().getIndexImageCheckboxChecked());
|
||||
|
||||
// Store the path to the first image selected into the properties file
|
||||
String firstImage = getComponent().getContentPaths();
|
||||
String firstImagePath = firstImage.substring(0, firstImage.lastIndexOf(File.separator) + 1);
|
||||
ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_LASTDATASOURCE_PATH, firstImagePath);
|
||||
ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_LASTDATASOURCE_TYPE, getComponent().getContentType().toString());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,16 +39,6 @@
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="nextLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="timeZoneLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="timeZoneComboBox" min="-2" pref="252" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
|
||||
<Component id="descLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="imgInfoLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="54" max="32767" attributes="0"/>
|
||||
@ -65,16 +55,7 @@
|
||||
<Component id="imgInfoLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="inputPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="timeZoneLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="timeZoneComboBox" 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 max="-2" attributes="0"/>
|
||||
<Component id="descLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="64" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="45" max="32767" attributes="0"/>
|
||||
<Component id="nextLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
@ -89,41 +70,6 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="timeZoneLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageWizardChooseDataSourceVisual.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="timeZoneComboBox">
|
||||
<Properties>
|
||||
<Property name="maximumRowCount" type="int" value="30"/>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="noFatOrphansCheckbox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageWizardChooseDataSourceVisual.noFatOrphansCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageWizardChooseDataSourceVisual.noFatOrphansCheckbox.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="descLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="AddImageWizardChooseDataSourceVisual.descLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="inputPanel">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
@ -160,7 +106,7 @@
|
||||
<Component id="typeComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="typePanel" pref="77" max="32767" attributes="0"/>
|
||||
<Component id="typePanel" pref="173" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -192,7 +138,7 @@
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="77" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="173" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
@ -204,7 +150,7 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<ContentTypePanel>"/>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
|
@ -18,49 +18,44 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.Component;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
import org.sleuthkit.autopsy.casemodule.ContentTypePanel.ContentType;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
|
||||
/**
|
||||
* visual component for the first panel of add image wizard. Allows user to pick
|
||||
* data source and timezone.
|
||||
* visual component for the first panel of add image wizard.
|
||||
* Allows the user to choose the data source type and then select the data source
|
||||
*
|
||||
*/
|
||||
final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
|
||||
enum EVENT {
|
||||
static final Logger logger = Logger.getLogger(AddImageWizardChooseDataSourceVisual.class.getName());
|
||||
|
||||
UPDATE_UI, FOCUS_NEXT
|
||||
};
|
||||
static final List<String> rawExt = Arrays.asList(new String[]{".img", ".dd", ".001", ".aa", ".raw"});
|
||||
static final String rawDesc = "Raw Images (*.img, *.dd, *.001, *.aa, *.raw)";
|
||||
static GeneralFilter rawFilter = new GeneralFilter(rawExt, rawDesc);
|
||||
static final List<String> encaseExt = Arrays.asList(new String[]{".e01"});
|
||||
static final String encaseDesc = "Encase Images (*.e01)";
|
||||
static GeneralFilter encaseFilter = new GeneralFilter(encaseExt, encaseDesc);
|
||||
static final List<String> allExt = new ArrayList<String>();
|
||||
|
||||
static {
|
||||
allExt.addAll(rawExt);
|
||||
allExt.addAll(encaseExt);
|
||||
}
|
||||
static final String allDesc = "All Supported Types";
|
||||
static GeneralFilter allFilter = new GeneralFilter(allExt, allDesc);
|
||||
private AddImageWizardChooseDataSourcePanel wizPanel;
|
||||
private ContentTypeModel model;
|
||||
private ContentTypePanel currentPanel;
|
||||
|
||||
private JPanel currentPanel;
|
||||
private Map<String, DataSourceProcessor> datasourceProcessorsMap = new HashMap<String, DataSourceProcessor>();
|
||||
|
||||
|
||||
List<String> coreDSPTypes = new ArrayList<String>();
|
||||
|
||||
/**
|
||||
* Creates new form AddImageVisualPanel1
|
||||
@ -70,16 +65,75 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
AddImageWizardChooseDataSourceVisual(AddImageWizardChooseDataSourcePanel wizPanel) {
|
||||
initComponents();
|
||||
this.wizPanel = wizPanel;
|
||||
createTimeZoneList();
|
||||
|
||||
customInit();
|
||||
}
|
||||
|
||||
private void customInit() {
|
||||
model = new ContentTypeModel();
|
||||
typeComboBox.setModel(model);
|
||||
typeComboBox.setSelectedIndex(0);
|
||||
|
||||
typePanel.setLayout(new BorderLayout());
|
||||
updateCurrentPanel(ImageFilePanel.getDefault());
|
||||
|
||||
discoverDataSourceProcessors();
|
||||
|
||||
// set up the DSP type combobox
|
||||
typeComboBox.removeAllItems();
|
||||
|
||||
Set<String> dspTypes = datasourceProcessorsMap.keySet();
|
||||
|
||||
// make a list of core DSPs
|
||||
// ensure that the core DSPs are at the top and in a fixed order
|
||||
coreDSPTypes.add(ImageDSProcessor.dsType);
|
||||
coreDSPTypes.add(LocalDiskDSProcessor.dsType);
|
||||
coreDSPTypes.add(LocalFilesDSProcessor.dsType);
|
||||
|
||||
for(String dspType:coreDSPTypes){
|
||||
typeComboBox.addItem(dspType);
|
||||
}
|
||||
|
||||
// now add any addtional DSPs that haven't already been added
|
||||
for(String dspType:dspTypes){
|
||||
if (!coreDSPTypes.contains(dspType)) {
|
||||
typeComboBox.addItem(dspType);
|
||||
}
|
||||
}
|
||||
|
||||
// set a custom renderer that draws a separator at the end of the core DSPs in the combobox
|
||||
typeComboBox.setRenderer(new ComboboxSeparatorRenderer(typeComboBox.getRenderer()){
|
||||
@Override
|
||||
protected boolean addSeparatorAfter(JList list, Object value, int index){
|
||||
return (index == coreDSPTypes.size() - 1);
|
||||
}
|
||||
});
|
||||
|
||||
//add actionlistner to listen for change
|
||||
ActionListener cbActionListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
dspSelectionChanged();
|
||||
}
|
||||
};
|
||||
typeComboBox.addActionListener(cbActionListener);
|
||||
typeComboBox.setSelectedIndex(0);
|
||||
}
|
||||
|
||||
private void discoverDataSourceProcessors() {
|
||||
|
||||
for (DataSourceProcessor dsProcessor: Lookup.getDefault().lookupAll(DataSourceProcessor.class)) {
|
||||
|
||||
if (!datasourceProcessorsMap.containsKey(dsProcessor.getType()) ) {
|
||||
dsProcessor.reset();
|
||||
datasourceProcessorsMap.put(dsProcessor.getType(), dsProcessor);
|
||||
}
|
||||
else {
|
||||
logger.log(Level.SEVERE, "discoverDataSourceProcessors(): A DataSourceProcessor already exists for type = " + dsProcessor.getType() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dspSelectionChanged() {
|
||||
// update the current panel to selection
|
||||
currentPanel = getCurrentDSProcessor().getPanel();
|
||||
updateCurrentPanel(currentPanel);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,7 +141,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
*
|
||||
* @param panel instance of ImageTypePanel to change to
|
||||
*/
|
||||
private void updateCurrentPanel(ContentTypePanel panel) {
|
||||
private void updateCurrentPanel(JPanel panel) {
|
||||
currentPanel = panel;
|
||||
typePanel.removeAll();
|
||||
typePanel.add((JPanel) currentPanel, BorderLayout.CENTER);
|
||||
@ -96,28 +150,32 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
currentPanel.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getPropertyName().equals(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString())) {
|
||||
if (evt.getPropertyName().equals(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString())) {
|
||||
updateUI(null);
|
||||
}
|
||||
if (evt.getPropertyName().equals(AddImageWizardChooseDataSourceVisual.EVENT.FOCUS_NEXT.toString())) {
|
||||
if (evt.getPropertyName().equals(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString())) {
|
||||
wizPanel.moveFocusToNext();
|
||||
}
|
||||
}
|
||||
});
|
||||
currentPanel.select();
|
||||
if (currentPanel.getContentType().equals(ContentType.LOCAL)) {
|
||||
//disable image specific options
|
||||
noFatOrphansCheckbox.setEnabled(false);
|
||||
descLabel.setEnabled(false);
|
||||
timeZoneComboBox.setEnabled(false);
|
||||
} else {
|
||||
noFatOrphansCheckbox.setEnabled(true);
|
||||
descLabel.setEnabled(true);
|
||||
timeZoneComboBox.setEnabled(true);
|
||||
}
|
||||
|
||||
updateUI(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently selected DS Processor
|
||||
* @return DataSourceProcessor the DataSourceProcessor corresponding to the data source type selected in the combobox
|
||||
*/
|
||||
public DataSourceProcessor getCurrentDSProcessor() {
|
||||
// get the type of the currently selected panel and then look up
|
||||
// the correspodning DS Handler in the map
|
||||
String dsType = (String) typeComboBox.getSelectedItem();
|
||||
DataSourceProcessor dsProcessor = datasourceProcessorsMap.get(dsType);
|
||||
|
||||
return dsProcessor;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the this panel. This name will be shown on the left
|
||||
* panel of the "Add Image" wizard panel.
|
||||
@ -129,94 +187,6 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
return "Enter Data Source Information";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data sources path from the Image Path Text Field.
|
||||
*
|
||||
* @return data source path, can be comma separated for multiples
|
||||
*/
|
||||
public String getContentPaths() {
|
||||
return currentPanel.getContentPaths();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data sources type selected
|
||||
*
|
||||
* @return data source selected
|
||||
*/
|
||||
public ContentType getContentType() {
|
||||
return currentPanel.getContentType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the data sources panel selected
|
||||
*/
|
||||
public void reset() {
|
||||
currentPanel.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the image path of the current panel.
|
||||
*
|
||||
* @param s the image path to set
|
||||
*/
|
||||
public void setContentPath(String s) {
|
||||
currentPanel.setContentPath(s);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if no fat orphans processing is selected
|
||||
*/
|
||||
boolean getNoFatOrphans() {
|
||||
return noFatOrphansCheckbox.isSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time zone that selected on the drop down list.
|
||||
*
|
||||
* @return timeZone the time zone that selected
|
||||
*/
|
||||
public String getSelectedTimezone() {
|
||||
String tz = timeZoneComboBox.getSelectedItem().toString();
|
||||
return tz.substring(tz.indexOf(")") + 2).trim();
|
||||
}
|
||||
|
||||
// add the timeZone list to the timeZoneComboBox
|
||||
/**
|
||||
* Creates the drop down list for the time zones and then makes the local
|
||||
* machine time zones to be selected.
|
||||
*/
|
||||
public void createTimeZoneList() {
|
||||
// load and add all timezone
|
||||
String[] ids = SimpleTimeZone.getAvailableIDs();
|
||||
for (String id : ids) {
|
||||
TimeZone zone = TimeZone.getTimeZone(id);
|
||||
int offset = zone.getRawOffset() / 1000;
|
||||
int hour = offset / 3600;
|
||||
int minutes = (offset % 3600) / 60;
|
||||
String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id);
|
||||
|
||||
/*
|
||||
* DateFormat dfm = new SimpleDateFormat("z");
|
||||
* dfm.setTimeZone(zone); boolean hasDaylight =
|
||||
* zone.useDaylightTime(); String first = dfm.format(new Date(2010,
|
||||
* 1, 1)); String second = dfm.format(new Date(2011, 6, 6)); int mid
|
||||
* = hour * -1; String result = first + Integer.toString(mid);
|
||||
* if(hasDaylight){ result = result + second; }
|
||||
* timeZoneComboBox.addItem(item + " (" + result + ")");
|
||||
*/
|
||||
timeZoneComboBox.addItem(item);
|
||||
}
|
||||
// get the current timezone
|
||||
TimeZone thisTimeZone = Calendar.getInstance().getTimeZone();
|
||||
int thisOffset = thisTimeZone.getRawOffset() / 1000;
|
||||
int thisHour = thisOffset / 3600;
|
||||
int thisMinutes = (thisOffset % 3600) / 60;
|
||||
String formatted = String.format("(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID());
|
||||
|
||||
// set the selected timezone
|
||||
timeZoneComboBox.setSelectedItem(formatted);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
@ -229,14 +199,10 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
buttonGroup1 = new javax.swing.ButtonGroup();
|
||||
jLabel2 = new javax.swing.JLabel();
|
||||
nextLabel = new javax.swing.JLabel();
|
||||
timeZoneLabel = new javax.swing.JLabel();
|
||||
timeZoneComboBox = new javax.swing.JComboBox<String>();
|
||||
noFatOrphansCheckbox = new javax.swing.JCheckBox();
|
||||
descLabel = new javax.swing.JLabel();
|
||||
inputPanel = new javax.swing.JPanel();
|
||||
typeTabel = new javax.swing.JLabel();
|
||||
typePanel = new javax.swing.JPanel();
|
||||
typeComboBox = new javax.swing.JComboBox<ContentTypePanel>();
|
||||
typeComboBox = new javax.swing.JComboBox<String>();
|
||||
imgInfoLabel = new javax.swing.JLabel();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.jLabel2.text")); // NOI18N
|
||||
@ -245,15 +211,6 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(nextLabel, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.nextLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.timeZoneLabel.text")); // NOI18N
|
||||
|
||||
timeZoneComboBox.setMaximumRowCount(30);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.noFatOrphansCheckbox.text")); // NOI18N
|
||||
noFatOrphansCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.noFatOrphansCheckbox.toolTipText")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(descLabel, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.descLabel.text")); // NOI18N
|
||||
|
||||
inputPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(typeTabel, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.typeTabel.text")); // NOI18N
|
||||
@ -269,7 +226,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
);
|
||||
typePanelLayout.setVerticalGroup(
|
||||
typePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 77, Short.MAX_VALUE)
|
||||
.addGap(0, 173, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
javax.swing.GroupLayout inputPanelLayout = new javax.swing.GroupLayout(inputPanel);
|
||||
@ -295,7 +252,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
.addComponent(typeTabel)
|
||||
.addComponent(typeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(typePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 77, Short.MAX_VALUE)
|
||||
.addComponent(typePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 173, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
@ -313,14 +270,6 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(nextLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(timeZoneLabel)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 252, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(noFatOrphansCheckbox)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(21, 21, 21)
|
||||
.addComponent(descLabel))
|
||||
.addComponent(imgInfoLabel))
|
||||
.addGap(0, 54, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
@ -332,30 +281,18 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
.addComponent(imgInfoLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(inputPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(timeZoneLabel)
|
||||
.addComponent(timeZoneComboBox, 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.RELATED)
|
||||
.addComponent(descLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 64, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 45, Short.MAX_VALUE)
|
||||
.addComponent(nextLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, 0))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.ButtonGroup buttonGroup1;
|
||||
private javax.swing.JLabel descLabel;
|
||||
private javax.swing.JLabel imgInfoLabel;
|
||||
private javax.swing.JPanel inputPanel;
|
||||
private javax.swing.JLabel jLabel2;
|
||||
private javax.swing.JLabel nextLabel;
|
||||
private javax.swing.JCheckBox noFatOrphansCheckbox;
|
||||
private javax.swing.JComboBox<String> timeZoneComboBox;
|
||||
private javax.swing.JLabel timeZoneLabel;
|
||||
private javax.swing.JComboBox<ContentTypePanel> typeComboBox;
|
||||
private javax.swing.JComboBox<String> typeComboBox;
|
||||
private javax.swing.JPanel typePanel;
|
||||
private javax.swing.JLabel typeTabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
@ -369,44 +306,31 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
* @param e the document event
|
||||
*/
|
||||
public void updateUI(DocumentEvent e) {
|
||||
this.wizPanel.enableNextButton(currentPanel.enableNext());
|
||||
// Enable the Next button if the current DSP panel is valid
|
||||
this.wizPanel.enableNextButton(getCurrentDSProcessor().validatePanel());
|
||||
}
|
||||
|
||||
/**
|
||||
* ComboBoxModel to control typeComboBox and supply ImageTypePanels.
|
||||
*/
|
||||
private class ContentTypeModel implements ComboBoxModel<ContentTypePanel> {
|
||||
|
||||
private ContentTypePanel selected;
|
||||
private ContentTypePanel[] types = ContentTypePanel.getPanels();
|
||||
public abstract class ComboboxSeparatorRenderer implements ListCellRenderer{
|
||||
private ListCellRenderer delegate;
|
||||
private JPanel separatorPanel = new JPanel(new BorderLayout());
|
||||
private JSeparator separator = new JSeparator();
|
||||
|
||||
@Override
|
||||
public void setSelectedItem(Object anItem) {
|
||||
selected = (ContentTypePanel) anItem;
|
||||
updateCurrentPanel(selected);
|
||||
public ComboboxSeparatorRenderer(ListCellRenderer delegate){
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSelectedItem() {
|
||||
return selected;
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus){
|
||||
Component comp = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if(index!=-1 && addSeparatorAfter(list, value, index)){
|
||||
separatorPanel.removeAll();
|
||||
separatorPanel.add(comp, BorderLayout.CENTER);
|
||||
separatorPanel.add(separator, BorderLayout.SOUTH);
|
||||
return separatorPanel;
|
||||
}else
|
||||
return comp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return types.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentTypePanel getElementAt(int index) {
|
||||
return types[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
}
|
||||
protected abstract boolean addSeparatorAfter(JList list, Object value, int index);
|
||||
}
|
||||
}
|
||||
|
@ -18,41 +18,25 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
|
||||
import org.sleuthkit.autopsy.ingest.IngestConfigurator;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Window;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.casemodule.ContentTypePanel.ContentType;
|
||||
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.FileSystem;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
import org.sleuthkit.datamodel.Volume;
|
||||
import org.sleuthkit.datamodel.VolumeSystem;
|
||||
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
/**
|
||||
* second panel of add image wizard, allows user to configure ingest modules.
|
||||
*
|
||||
@ -68,28 +52,27 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
* component from this class, just use getComponent().
|
||||
*/
|
||||
private Component component = null;
|
||||
|
||||
private final List<Content> newContents = Collections.synchronizedList(new ArrayList<Content>());
|
||||
private boolean ingested = false;
|
||||
private boolean readyToIngest = false;
|
||||
// the paths of the image files to be added
|
||||
private String dataSourcePath;
|
||||
private ContentType dataSourceType;
|
||||
// the time zone where the image is added
|
||||
private String timeZone;
|
||||
//whether to not process FAT filesystem orphans
|
||||
private boolean noFatOrphans;
|
||||
// task that will clean up the created database file if the wizard is cancelled before it finishes
|
||||
private AddImageAction.CleanupTask cleanupImage; // initialized to null in readSettings()
|
||||
private CurrentDirectoryFetcher fetcher;
|
||||
private AddImageProcess process;
|
||||
private AddImageAction action;
|
||||
private AddImageTask addImageTask;
|
||||
private AddLocalFilesTask addLocalFilesTask;
|
||||
private AddImageWizardAddingProgressPanel progressPanel;
|
||||
|
||||
AddImageWizardIngestConfigPanel(AddImageAction action, AddImageWizardAddingProgressPanel proPanel) {
|
||||
this.action = action;
|
||||
// task that will clean up the created database file if the wizard is cancelled before it finishes
|
||||
private AddImageAction.CleanupTask cleanupTask;
|
||||
|
||||
private AddImageAction addImageAction;
|
||||
|
||||
private AddImageWizardAddingProgressPanel progressPanel;
|
||||
private AddImageWizardChooseDataSourcePanel dataSourcePanel;
|
||||
|
||||
private DataSourceProcessor dsProcessor;
|
||||
|
||||
|
||||
AddImageWizardIngestConfigPanel(AddImageWizardChooseDataSourcePanel dsPanel, AddImageAction action, AddImageWizardAddingProgressPanel proPanel) {
|
||||
this.addImageAction = action;
|
||||
this.progressPanel = proPanel;
|
||||
this.dataSourcePanel = dsPanel;
|
||||
|
||||
ingestConfig = Lookup.getDefault().lookup(IngestConfigurator.class);
|
||||
List<String> messages = ingestConfig.setContext(AddImageWizardIngestConfigPanel.class.getCanonicalName());
|
||||
if (messages.isEmpty() == false) {
|
||||
@ -183,24 +166,14 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
JButton cancel = new JButton("Cancel");
|
||||
cancel.setEnabled(false);
|
||||
settings.setOptions(new Object[]{WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, WizardDescriptor.FINISH_OPTION, cancel});
|
||||
cleanupImage = null;
|
||||
cleanupTask = null;
|
||||
readyToIngest = false;
|
||||
|
||||
newContents.clear();
|
||||
dataSourcePath = (String) settings.getProperty(AddImageAction.DATASOURCEPATH_PROP);
|
||||
dataSourceType = (ContentType) settings.getProperty(AddImageAction.DATASOURCETYPE_PROP);
|
||||
timeZone = settings.getProperty(AddImageAction.TIMEZONE_PROP).toString();
|
||||
noFatOrphans = ((Boolean) settings.getProperty(AddImageAction.NOFATORPHANS_PROP)).booleanValue();
|
||||
|
||||
//start the process of adding the content
|
||||
if (dataSourceType.equals(ContentType.LOCAL)) {
|
||||
addLocalFilesTask = new AddLocalFilesTask(settings);
|
||||
addLocalFilesTask.execute();
|
||||
} else {
|
||||
//disk or image
|
||||
addImageTask = new AddImageTask(settings);
|
||||
addImageTask.execute();
|
||||
}
|
||||
// Start processing the data source by handing it off to the selected DSP,
|
||||
// so it gets going in the background while the user is still picking the Ingest modules
|
||||
startDataSourceProcessing(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -235,469 +208,97 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for getting the currently processing directory.
|
||||
*
|
||||
/**
|
||||
* Starts the Data source processing by kicking off the selected DataSourceProcessor
|
||||
*/
|
||||
private static class CurrentDirectoryFetcher extends SwingWorker<Integer, Integer> {
|
||||
private void startDataSourceProcessing(WizardDescriptor settings) {
|
||||
|
||||
AddImageTask task;
|
||||
JProgressBar prog;
|
||||
AddImageWizardAddingProgressVisual wiz;
|
||||
AddImageProcess proc;
|
||||
|
||||
CurrentDirectoryFetcher(JProgressBar prog, AddImageWizardAddingProgressVisual wiz, AddImageProcess proc) {
|
||||
this.wiz = wiz;
|
||||
this.proc = proc;
|
||||
this.prog = prog;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the currently processing directory
|
||||
*/
|
||||
@Override
|
||||
protected Integer doInBackground() {
|
||||
try {
|
||||
while (prog.getValue() < 100 || prog.isIndeterminate()) { //TODO Rely on state variable in AddImgTask class
|
||||
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
wiz.setCurrentDirText(proc.currentDirectory());
|
||||
}
|
||||
});
|
||||
|
||||
Thread.sleep(2 * 1000);
|
||||
}
|
||||
return 1;
|
||||
} catch (InterruptedException ie) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread that will add logical files to database, and then kick-off ingest
|
||||
* modules. Note: the add logical files task cannot currently be reverted as
|
||||
* the add image task can. This is a separate task from AddImgTask because
|
||||
* it is much simpler and does not require locks, since the underlying file
|
||||
* manager methods acquire the locks for each transaction when adding
|
||||
* logical files.
|
||||
*/
|
||||
private class AddLocalFilesTask extends SwingWorker<Integer, Integer> {
|
||||
|
||||
private JProgressBar progressBar;
|
||||
private Case currentCase;
|
||||
// true if the process was requested to stop
|
||||
private boolean interrupted = false;
|
||||
private boolean hasCritError = false;
|
||||
private String errorString = null;
|
||||
private WizardDescriptor settings;
|
||||
private Logger logger = Logger.getLogger(AddLocalFilesTask.class.getName());
|
||||
|
||||
protected AddLocalFilesTask(WizardDescriptor settings) {
|
||||
this.progressBar = progressPanel.getComponent().getProgressBar();
|
||||
currentCase = Case.getCurrentCase();
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the addImage process, but does not commit the results.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
protected Integer doInBackground() {
|
||||
this.setProgress(0);
|
||||
// Add a cleanup task to interupt the backgroud process if the
|
||||
// wizard exits while the background process is running.
|
||||
AddImageAction.CleanupTask cancelledWhileRunning = action.new CleanupTask() {
|
||||
@Override
|
||||
void cleanup() throws Exception {
|
||||
logger.log(Level.INFO, "Add logical files process interrupted.");
|
||||
//nothing to be cleanedup
|
||||
}
|
||||
};
|
||||
|
||||
cancelledWhileRunning.enable();
|
||||
final LocalFilesAddProgressUpdater progUpdater = new LocalFilesAddProgressUpdater(this.progressBar, progressPanel.getComponent());
|
||||
try {
|
||||
final FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
progressPanel.setStateStarted();
|
||||
String[] paths = dataSourcePath.split(LocalFilesPanel.FILES_SEP);
|
||||
List<String> absLocalPaths = new ArrayList<String>();
|
||||
for (String path : paths) {
|
||||
absLocalPaths.add(path);
|
||||
}
|
||||
newContents.add(fileManager.addLocalFilesDirs(absLocalPaths, progUpdater));
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Errors occurred while running add logical files. ", ex);
|
||||
hasCritError = true;
|
||||
errorString = ex.getMessage();
|
||||
} finally {
|
||||
// process is over, doesn't need to be dealt with if cancel happens
|
||||
cancelledWhileRunning.disable();
|
||||
//enqueue what would be in done() to EDT thread
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
postProcess();
|
||||
}
|
||||
});
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* (called by EventDispatch Thread after doInBackground finishes)
|
||||
*/
|
||||
protected void postProcess() {
|
||||
progressBar.setIndeterminate(false);
|
||||
setProgress(100);
|
||||
|
||||
//clear updates
|
||||
// progressPanel.getComponent().setProcessInvis();
|
||||
|
||||
if (interrupted || hasCritError) {
|
||||
logger.log(Level.INFO, "Handling errors or interruption that occured in logical files process");
|
||||
if (hasCritError) {
|
||||
//core error
|
||||
progressPanel.getComponent().showErrors(errorString, true);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (errorString != null) {
|
||||
//data error (non-critical)
|
||||
logger.log(Level.INFO, "Handling non-critical errors that occured in logical files process");
|
||||
progressPanel.getComponent().showErrors(errorString, false);
|
||||
}
|
||||
}
|
||||
try {
|
||||
// When everything happens without an error:
|
||||
if (errorString == null) { // complete progress bar
|
||||
progressPanel.getComponent().setProgressBarTextAndColor("*Logical Files added.", 100, Color.black);
|
||||
}
|
||||
|
||||
// Get attention for the process finish
|
||||
java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
|
||||
AddImageWizardAddingProgressVisual panel = progressPanel.getComponent();
|
||||
if (panel != null) {
|
||||
Window w = SwingUtilities.getWindowAncestor(panel);
|
||||
if (w != null) {
|
||||
w.toFront();
|
||||
}
|
||||
}
|
||||
|
||||
progressPanel.setStateFinished();
|
||||
|
||||
//notify the case
|
||||
if (!newContents.isEmpty()) {
|
||||
Case.getCurrentCase().addLocalDataSource(newContents.get(0));
|
||||
}
|
||||
|
||||
// Start ingest if we can
|
||||
startIngest();
|
||||
|
||||
} catch (Exception ex) {
|
||||
//handle unchecked exceptions
|
||||
logger.log(Level.WARNING, "Unexpected errors occurred while running post add image cleanup. ", ex);
|
||||
progressPanel.getComponent().setProgressBarTextAndColor("*Failed to add image.", 0, Color.black); // set error message
|
||||
logger.log(Level.SEVERE, "Error adding image to case", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the wizard status with logical file/folder
|
||||
*/
|
||||
private class LocalFilesAddProgressUpdater implements FileManager.FileAddProgressUpdater {
|
||||
|
||||
private int count = 0;
|
||||
private JProgressBar prog;
|
||||
private AddImageWizardAddingProgressVisual wiz;
|
||||
|
||||
LocalFilesAddProgressUpdater(JProgressBar prog, AddImageWizardAddingProgressVisual wiz) {
|
||||
this.wiz = wiz;
|
||||
this.prog = prog;
|
||||
}
|
||||
|
||||
// Add a cleanup task to interrupt the background process if the
|
||||
// wizard exits while the background process is running.
|
||||
cleanupTask = addImageAction.new CleanupTask() {
|
||||
@Override
|
||||
public void fileAdded(final AbstractFile newFile) {
|
||||
if (count++ % 10 == 0 && (prog.getValue() < 100 || prog.isIndeterminate())) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
wiz.setCurrentDirText(newFile.getParentPath() + "/" + newFile.getName());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
void cleanup() throws Exception {
|
||||
cancelDataSourceProcessing();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cleanupTask.enable();
|
||||
|
||||
// get the selected DSProcessor
|
||||
dsProcessor = dataSourcePanel.getComponent().getCurrentDSProcessor();
|
||||
|
||||
DSPCallback cbObj = new DSPCallback () {
|
||||
@Override
|
||||
public void doneEDT(DSPCallback.DSP_Result result, List<String> errList, List<Content> contents) {
|
||||
dataSourceProcessorDone(result, errList, contents );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
progressPanel.setStateStarted();
|
||||
|
||||
// Kick off the DSProcessor
|
||||
dsProcessor.run(progressPanel.getDSPProgressMonitorImpl(), cbObj);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread that will make the JNI call to add image to database, and then
|
||||
* kick-off ingest modules.
|
||||
/*
|
||||
* Cancels the data source processing - in case the users presses 'Cancel'
|
||||
*/
|
||||
private class AddImageTask extends SwingWorker<Integer, Integer> {
|
||||
private void cancelDataSourceProcessing() {
|
||||
dsProcessor.cancel();
|
||||
}
|
||||
|
||||
private JProgressBar progressBar;
|
||||
private Case currentCase;
|
||||
// true if the process was requested to stop
|
||||
private boolean interrupted = false;
|
||||
private boolean hasCritError = false;
|
||||
private String errorString = null;
|
||||
private WizardDescriptor wizDescriptor;
|
||||
private Logger logger = Logger.getLogger(AddImageTask.class.getName());
|
||||
/*
|
||||
* Callback for the data source processor.
|
||||
* Invoked by the DSP on the EDT thread, when it finishes processing the data source.
|
||||
*/
|
||||
private void dataSourceProcessorDone(DSPCallback.DSP_Result result, List<String> errList, List<Content> contents) {
|
||||
|
||||
protected AddImageTask(WizardDescriptor settings) {
|
||||
this.progressBar = progressPanel.getComponent().getProgressBar();
|
||||
currentCase = Case.getCurrentCase();
|
||||
this.wizDescriptor = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the addImage process, but does not commit the results.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
protected Integer doInBackground() {
|
||||
|
||||
this.setProgress(0);
|
||||
|
||||
|
||||
// Add a cleanup task to interupt the backgroud process if the
|
||||
// wizard exits while the background process is running.
|
||||
AddImageAction.CleanupTask cancelledWhileRunning = action.new CleanupTask() {
|
||||
@Override
|
||||
void cleanup() throws Exception {
|
||||
logger.log(Level.INFO, "Add image process interrupted.");
|
||||
addImageTask.interrupt(); //it might take time to truly interrupt
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
try {
|
||||
//lock DB for writes in EWT thread
|
||||
//wait until lock acquired in EWT
|
||||
EventQueue.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
SleuthkitCase.dbWriteLock();
|
||||
}
|
||||
});
|
||||
} catch (InterruptedException ex) {
|
||||
logger.log(Level.WARNING, "Errors occurred while running add image, could not acquire lock. ", ex);
|
||||
return 0;
|
||||
|
||||
} catch (InvocationTargetException ex) {
|
||||
logger.log(Level.WARNING, "Errors occurred while running add image, could not acquire lock. ", ex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
process = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans);
|
||||
fetcher = new CurrentDirectoryFetcher(this.progressBar, progressPanel.getComponent(), process);
|
||||
cancelledWhileRunning.enable();
|
||||
try {
|
||||
progressPanel.setStateStarted();
|
||||
fetcher.execute();
|
||||
process.run(new String[]{dataSourcePath});
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Core errors occurred while running add image. ", ex);
|
||||
//critical core/system error and process needs to be interrupted
|
||||
hasCritError = true;
|
||||
errorString = ex.getMessage();
|
||||
} catch (TskDataException ex) {
|
||||
logger.log(Level.WARNING, "Data errors occurred while running add image. ", ex);
|
||||
errorString = ex.getMessage();
|
||||
} finally {
|
||||
// process is over, doesn't need to be dealt with if cancel happens
|
||||
cancelledWhileRunning.disable();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the finished AddImageProcess, and cancel the CleanupTask that
|
||||
* would have reverted it.
|
||||
*
|
||||
* @param settings property set to get AddImageProcess and CleanupTask
|
||||
* from
|
||||
*
|
||||
* @throws Exception if commit or adding the image to the case failed
|
||||
*/
|
||||
private void commitImage(WizardDescriptor settings) throws Exception {
|
||||
|
||||
String contentPath = (String) settings.getProperty(AddImageAction.DATASOURCEPATH_PROP);
|
||||
|
||||
String timezone = settings.getProperty(AddImageAction.TIMEZONE_PROP).toString();
|
||||
settings.putProperty(AddImageAction.IMAGEID_PROP, "");
|
||||
|
||||
long imageId = 0;
|
||||
try {
|
||||
imageId = process.commit();
|
||||
} catch (TskException e) {
|
||||
logger.log(Level.WARNING, "Errors occured while committing the image", e);
|
||||
} finally {
|
||||
//commit done, unlock db write in EWT thread
|
||||
//before doing anything else
|
||||
SleuthkitCase.dbWriteUnlock();
|
||||
|
||||
if (imageId != 0) {
|
||||
Image newImage = Case.getCurrentCase().addImage(contentPath, imageId, timezone);
|
||||
|
||||
//while we have the image, verify the size of its contents
|
||||
String verificationErrors = newImage.verifyImageSize();
|
||||
if (verificationErrors.equals("") == false) {
|
||||
//data error (non-critical)
|
||||
progressPanel.addErrors(verificationErrors, false);
|
||||
}
|
||||
|
||||
|
||||
newContents.add(newImage);
|
||||
settings.putProperty(AddImageAction.IMAGEID_PROP, imageId);
|
||||
}
|
||||
|
||||
// Can't bail and revert image add after commit, so disable image cleanup
|
||||
// task
|
||||
cleanupImage.disable();
|
||||
settings.putProperty(AddImageAction.IMAGECLEANUPTASK_PROP, null);
|
||||
|
||||
logger.log(Level.INFO, "Image committed, imageId: " + imageId);
|
||||
logger.log(Level.INFO, PlatformUtil.getAllMemUsageInfo());
|
||||
// disable the cleanup task
|
||||
cleanupTask.disable();
|
||||
|
||||
// Get attention for the process finish
|
||||
java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
|
||||
AddImageWizardAddingProgressVisual panel = progressPanel.getComponent();
|
||||
if (panel != null) {
|
||||
Window w = SwingUtilities.getWindowAncestor(panel);
|
||||
if (w != null) {
|
||||
w.toFront();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* (called by EventDispatch Thread after doInBackground finishes)
|
||||
*/
|
||||
@Override
|
||||
protected void done() {
|
||||
//these are required to stop the CurrentDirectoryFetcher
|
||||
progressBar.setIndeterminate(false);
|
||||
setProgress(100);
|
||||
|
||||
// attempt actions that might fail and force the process to stop
|
||||
|
||||
if (interrupted || hasCritError) {
|
||||
logger.log(Level.INFO, "Handling errors or interruption that occured in add image process");
|
||||
revert();
|
||||
if (hasCritError) {
|
||||
//core error
|
||||
progressPanel.addErrors(errorString, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (errorString != null) {
|
||||
//data error (non-critical)
|
||||
logger.log(Level.INFO, "Handling non-critical errors that occured in add image process");
|
||||
progressPanel.addErrors(errorString, false);
|
||||
}
|
||||
// Tell the panel we're done
|
||||
progressPanel.setStateFinished();
|
||||
|
||||
|
||||
try {
|
||||
// When everything happens without an error:
|
||||
|
||||
// the add-image process needs to be reverted if the wizard doesn't finish
|
||||
cleanupImage = action.new CleanupTask() {
|
||||
//note, CleanupTask runs inside EWT thread
|
||||
@Override
|
||||
void cleanup() throws Exception {
|
||||
logger.log(Level.INFO, "Running cleanup task after add image process");
|
||||
revert();
|
||||
}
|
||||
};
|
||||
cleanupImage.enable();
|
||||
|
||||
if (errorString == null) { // complete progress bar
|
||||
progressPanel.getComponent().setProgressBarTextAndColor("*Data Source added.", 100, Color.black);
|
||||
}
|
||||
|
||||
// Get attention for the process finish
|
||||
java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
|
||||
AddImageWizardAddingProgressVisual panel = progressPanel.getComponent();
|
||||
if (panel != null) {
|
||||
Window w = SwingUtilities.getWindowAncestor(panel);
|
||||
if (w != null) {
|
||||
w.toFront();
|
||||
}
|
||||
}
|
||||
|
||||
// Tell the panel we're done
|
||||
progressPanel.setStateFinished();
|
||||
|
||||
// Commit the image
|
||||
if (!newContents.isEmpty()) //already commited
|
||||
{
|
||||
logger.log(Level.INFO, "Assuming image already committed, will not commit.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (process != null) { // and if we're done configuring ingest
|
||||
// commit anything
|
||||
try {
|
||||
commitImage(wizDescriptor);
|
||||
} catch (Exception ex) {
|
||||
// Log error/display warning
|
||||
logger.log(Level.SEVERE, "Error adding image to case.", ex);
|
||||
}
|
||||
} else {
|
||||
logger.log(Level.SEVERE, "Missing image process object");
|
||||
}
|
||||
//check the result and display to user
|
||||
if (result == DSPCallback.DSP_Result.NO_ERRORS)
|
||||
progressPanel.getComponent().setProgressBarTextAndColor("*Data Source added.", 100, Color.black);
|
||||
else
|
||||
progressPanel.getComponent().setProgressBarTextAndColor("*Errors encountered in adding Data Source.", 100, Color.red);
|
||||
|
||||
|
||||
|
||||
|
||||
// Start ingest if we can
|
||||
startIngest();
|
||||
|
||||
} catch (Exception ex) {
|
||||
//handle unchecked exceptions post image add
|
||||
|
||||
logger.log(Level.WARNING, "Unexpected errors occurred while running post add image cleanup. ", ex);
|
||||
|
||||
progressPanel.getComponent().setProgressBarTextAndColor("*Failed to add image.", 0, Color.black); // set error message
|
||||
|
||||
// Log error/display warning
|
||||
|
||||
logger.log(Level.SEVERE, "Error adding image to case", ex);
|
||||
} finally {
|
||||
}
|
||||
//if errors, display them on the progress panel
|
||||
for ( String err: errList ) {
|
||||
// TBD: there probably should be an error level for each error
|
||||
progressPanel.addErrors(err, false);
|
||||
}
|
||||
|
||||
void interrupt() throws Exception {
|
||||
interrupted = true;
|
||||
try {
|
||||
logger.log(Level.INFO, "interrupt() add image process");
|
||||
process.stop(); //it might take time to truly stop processing and writing to db
|
||||
} catch (TskException ex) {
|
||||
throw new Exception("Error stopping add-image process.", ex);
|
||||
}
|
||||
newContents.clear();
|
||||
newContents.addAll(contents);
|
||||
|
||||
//notify the UI of the new content added to the case
|
||||
if (!newContents.isEmpty()) {
|
||||
|
||||
Case.getCurrentCase().notifyNewDataSource(newContents.get(0));
|
||||
}
|
||||
|
||||
//runs in EWT
|
||||
void revert() {
|
||||
try {
|
||||
logger.log(Level.INFO, "Revert after add image process");
|
||||
try {
|
||||
process.revert();
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error reverting add image process", ex);
|
||||
}
|
||||
} finally {
|
||||
//unlock db write within EWT thread
|
||||
SleuthkitCase.dbWriteUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Start ingest if we can
|
||||
progressPanel.setStateStarted();
|
||||
startIngest();
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -47,11 +47,16 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
|
||||
*/
|
||||
private List<WizardDescriptor.Panel<WizardDescriptor>> getPanels() {
|
||||
if (panels == null) {
|
||||
AddImageWizardAddingProgressPanel wizPanel = new AddImageWizardAddingProgressPanel();
|
||||
panels = new ArrayList<WizardDescriptor.Panel<WizardDescriptor>>();
|
||||
panels.add(new AddImageWizardChooseDataSourcePanel());
|
||||
panels.add(new AddImageWizardIngestConfigPanel(action, wizPanel));
|
||||
panels.add(wizPanel);
|
||||
|
||||
AddImageWizardAddingProgressPanel progressPanel = new AddImageWizardAddingProgressPanel();
|
||||
|
||||
AddImageWizardChooseDataSourcePanel dsPanel = new AddImageWizardChooseDataSourcePanel(progressPanel);
|
||||
AddImageWizardIngestConfigPanel ingestConfigPanel = new AddImageWizardIngestConfigPanel(dsPanel, action, progressPanel);
|
||||
|
||||
panels.add(dsPanel);
|
||||
panels.add(ingestConfigPanel);
|
||||
panels.add(progressPanel);
|
||||
|
||||
String[] steps = new String[panels.size()];
|
||||
for (int i = 0; i < panels.size(); i++) {
|
||||
|
185
Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java
Normal file
185
Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
|
||||
/**
|
||||
* Thread that will add logical files to database, and then kick-off ingest
|
||||
* modules. Note: the add logical files task cannot currently be reverted as
|
||||
* the add image task can. This is a separate task from AddImgTask because
|
||||
* it is much simpler and does not require locks, since the underlying file
|
||||
* manager methods acquire the locks for each transaction when adding
|
||||
* logical files.
|
||||
*/
|
||||
public class AddLocalFilesTask implements Runnable {
|
||||
|
||||
private Logger logger = Logger.getLogger(AddLocalFilesTask.class.getName());
|
||||
|
||||
private String dataSourcePath;
|
||||
private DSPProgressMonitor progressMonitor;
|
||||
private DSPCallback callbackObj;
|
||||
|
||||
private Case currentCase;
|
||||
// true if the process was requested to stop
|
||||
private volatile boolean cancelled = false;
|
||||
private boolean hasCritError = false;
|
||||
|
||||
private List<String> errorList = new ArrayList<String>();
|
||||
private final List<Content> newContents = Collections.synchronizedList(new ArrayList<Content>());
|
||||
|
||||
|
||||
protected AddLocalFilesTask(String dataSourcePath, DSPProgressMonitor aProgressMonitor, DSPCallback cbObj) {
|
||||
|
||||
currentCase = Case.getCurrentCase();
|
||||
|
||||
this.dataSourcePath = dataSourcePath;
|
||||
this.callbackObj = cbObj;
|
||||
this.progressMonitor = aProgressMonitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the addImage process, but does not commit the results.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
errorList.clear();
|
||||
|
||||
final LocalFilesAddProgressUpdater progUpdater = new LocalFilesAddProgressUpdater(progressMonitor);
|
||||
try {
|
||||
|
||||
progressMonitor.setIndeterminate(true);
|
||||
progressMonitor.setProgress(0);
|
||||
|
||||
final FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
String[] paths = dataSourcePath.split(LocalFilesPanel.FILES_SEP);
|
||||
List<String> absLocalPaths = new ArrayList<String>();
|
||||
for (String path : paths) {
|
||||
absLocalPaths.add(path);
|
||||
}
|
||||
newContents.add(fileManager.addLocalFilesDirs(absLocalPaths, progUpdater));
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Errors occurred while running add logical files. ", ex);
|
||||
hasCritError = true;
|
||||
errorList.add(ex.getMessage());
|
||||
} finally {
|
||||
|
||||
}
|
||||
|
||||
// handle done
|
||||
postProcess();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* (called by EventDispatch Thread after doInBackground finishes)
|
||||
*/
|
||||
protected void postProcess() {
|
||||
|
||||
if (cancelled || hasCritError) {
|
||||
logger.log(Level.WARNING, "Handling errors or interruption that occured in logical files process");
|
||||
|
||||
}
|
||||
if (!errorList.isEmpty()) {
|
||||
//data error (non-critical)
|
||||
logger.log(Level.WARNING, "Handling non-critical errors that occured in logical files process");
|
||||
}
|
||||
|
||||
if (!(cancelled || hasCritError)) {
|
||||
progressMonitor.setProgress(100);
|
||||
progressMonitor.setIndeterminate(false);
|
||||
}
|
||||
|
||||
// invoke the callBack, unless the caller cancelled
|
||||
if (!cancelled) {
|
||||
doCallBack();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the callback with results, new content, and errors, if any
|
||||
*/
|
||||
private void doCallBack()
|
||||
{
|
||||
DSPCallback.DSP_Result result;
|
||||
|
||||
if (hasCritError) {
|
||||
result = DSPCallback.DSP_Result.CRITICAL_ERRORS;
|
||||
}
|
||||
else if (!errorList.isEmpty()) {
|
||||
result = DSPCallback.DSP_Result.NONCRITICAL_ERRORS;
|
||||
}
|
||||
else {
|
||||
result = DSPCallback.DSP_Result.NO_ERRORS;
|
||||
}
|
||||
|
||||
// invoke the callback, passing it the result, list of new contents, and list of errors
|
||||
callbackObj.done(result, errorList, newContents);
|
||||
}
|
||||
|
||||
/*
|
||||
* cancel the files addition, if possible
|
||||
*/
|
||||
public void cancelTask() {
|
||||
cancelled = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the wizard status with logical file/folder
|
||||
*/
|
||||
private class LocalFilesAddProgressUpdater implements FileManager.FileAddProgressUpdater {
|
||||
|
||||
private int count = 0;
|
||||
private DSPProgressMonitor progressMonitor;
|
||||
|
||||
|
||||
LocalFilesAddProgressUpdater(DSPProgressMonitor progressMonitor) {
|
||||
|
||||
this.progressMonitor = progressMonitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileAdded(final AbstractFile newFile) {
|
||||
if (count++ % 10 == 0) {
|
||||
progressMonitor.setProgressText("Adding: " + newFile.getParentPath() + "/" + newFile.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -115,7 +115,6 @@ ImageFilePanel.browseButton.text=Browse
|
||||
ImageFilePanel.pathTextField.text=
|
||||
LocalDiskPanel.diskLabel.text=Select a local disk:
|
||||
MissingImageDialog.selectButton.text=Select Image
|
||||
MissingImageDialog.typeTabel.text=Select input type to add:
|
||||
MissingImageDialog.titleLabel.text=Search for missing image
|
||||
MissingImageDialog.cancelButton.text=Cancel
|
||||
LocalDiskPanel.errorLabel.text=Error Label
|
||||
@ -134,17 +133,23 @@ LocalFilesPanel.selectButton.actionCommand=Add
|
||||
AddImageWizardIngestConfigVisual.subtitleLabel.text=Configure the ingest modules you would like to run on this data source.
|
||||
AddImageWizardIngestConfigVisual.titleLabel.text=Configure Ingest Modules
|
||||
AddImageWizardAddingProgressVisual.statusLabel.text=File system has been added to the local database. Files are being analyzed.
|
||||
AddImageWizardChooseDataSourceVisual.noFatOrphansCheckbox.toolTipText=
|
||||
AddImageWizardChooseDataSourceVisual.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems
|
||||
AddImageWizardChooseDataSourceVisual.descLabel.text=(faster results, although some data will not be searched)
|
||||
AddImageWizardChooseDataSourceVisual.typeTabel.text=Select source type to add:
|
||||
AddImageWizardChooseDataSourceVisual.jLabel2.text=jLabel2
|
||||
AddImageWizardChooseDataSourceVisual.timeZoneLabel.text=Please select the input timezone:
|
||||
AddImageWizardChooseDataSourceVisual.nextLabel.text=<html> Press 'Next' to analyze the input data, extract volume and file system data, and populate a local database.</html>
|
||||
AddImageWizardChooseDataSourceVisual.imgInfoLabel.text=Enter Data Source Information:
|
||||
AddImageWizardAddingProgressVisual.progressLabel.text=<progress>
|
||||
AddImageWizardAddingProgressVisual.TextArea_CurrentDirectory.border.title=Currently Adding:
|
||||
AddImageWizardAddingProgressVisual.viewLogButton.text=View Log
|
||||
AddImageWizardAddingProgressVisual.titleLabel.text=Adding Data Source
|
||||
AddImageWizardAddingProgressVisual.subTitle1Label.text=File system information is being added to a local database. File analysis will start when this finishes.
|
||||
AddImageWizardAddingProgressVisual.subTitle2Label.text=Processing Data Source and Adding to Database
|
||||
ImageFilePanel.timeZoneLabel.text=Please select the input timezone:
|
||||
ImageFilePanel.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems
|
||||
ImageFilePanel.noFatOrphansCheckbox.toolTipText=
|
||||
ImageFilePanel.descLabel.text=(faster results, although some data will not be searched)
|
||||
LocalDiskPanel.timeZoneLabel.text=Please select the input timezone:
|
||||
LocalDiskPanel.noFatOrphansCheckbox.toolTipText=
|
||||
LocalDiskPanel.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems
|
||||
LocalDiskPanel.descLabel.text=(faster results, although some data will not be searched)
|
||||
MissingImageDialog.browseButton.text=Browse
|
||||
MissingImageDialog.pathNameTextField.text=
|
||||
AddImageWizardAddingProgressVisual.progressTextArea.border.title=Status
|
||||
|
@ -384,7 +384,9 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
+ "\nPlease note that you will still be able to browse directories and generate reports\n"
|
||||
+ "if you choose No, but you will not be able to view file content or run the ingest process.", "Missing Image", JOptionPane.YES_NO_OPTION);
|
||||
if (ret == JOptionPane.YES_OPTION) {
|
||||
|
||||
MissingImageDialog.makeDialog(obj_id, db);
|
||||
|
||||
} else {
|
||||
logger.log(Level.WARNING, "Selected image files don't match old files!");
|
||||
}
|
||||
@ -401,6 +403,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
* @param imgId the ID of the image that being added
|
||||
* @param timeZone the timeZone of the image where it's added
|
||||
*/
|
||||
@Deprecated
|
||||
public Image addImage(String imgPath, long imgId, String timeZone) throws CaseActionException {
|
||||
logger.log(Level.INFO, "Adding image to Case. imgPath: {0} ID: {1} TimeZone: {2}", new Object[]{imgPath, imgId, timeZone});
|
||||
|
||||
@ -420,11 +423,23 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
*
|
||||
* @param newDataSource new data source added
|
||||
*/
|
||||
@Deprecated
|
||||
void addLocalDataSource(Content newDataSource) {
|
||||
pcs.firePropertyChange(CASE_ADD_DATA_SOURCE, null, newDataSource);
|
||||
CoreComponentControl.openCoreWindows();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the UI that a new data source has been added.
|
||||
*
|
||||
*
|
||||
* @param newDataSource new data source added
|
||||
*/
|
||||
void notifyNewDataSource(Content newDataSource) {
|
||||
pcs.firePropertyChange(CASE_ADD_DATA_SOURCE, null, newDataSource);
|
||||
CoreComponentControl.openCoreWindows();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Services object for this case.
|
||||
*/
|
||||
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
abstract class ContentTypePanel extends JPanel {
|
||||
|
||||
public enum ContentType{IMAGE, DISK, LOCAL};
|
||||
|
||||
/**
|
||||
* Returns a list off all the panels extending ImageTypePanel.
|
||||
* @return list of all ImageTypePanels
|
||||
*/
|
||||
public static ContentTypePanel[] getPanels() {
|
||||
return new ContentTypePanel[] {ImageFilePanel.getDefault(), LocalDiskPanel.getDefault(), LocalFilesPanel.getDefault() };
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path of the selected content in this panel.
|
||||
* @return paths to selected content (one or more if multiselect supported)
|
||||
*/
|
||||
abstract public String getContentPaths();
|
||||
|
||||
/**
|
||||
* Set the selected content in this panel to the provided path.
|
||||
* This function is optional.
|
||||
* @param s path to selected content
|
||||
*/
|
||||
abstract public void setContentPath(String s);
|
||||
|
||||
/**
|
||||
* Get content type (image, disk, local file) of the source this wizard panel is for
|
||||
* @return ContentType of the source panel
|
||||
*/
|
||||
abstract public ContentType getContentType();
|
||||
|
||||
/**
|
||||
* Returns if the next button should be enabled in the current wizard.
|
||||
* @return true if the next button should be enabled, false otherwise
|
||||
*/
|
||||
abstract public boolean enableNext();
|
||||
|
||||
/**
|
||||
* Tells this panel to reset itself
|
||||
*/
|
||||
abstract public void reset();
|
||||
|
||||
/**
|
||||
* Tells this panel it has been selected.
|
||||
*/
|
||||
abstract public void select();
|
||||
|
||||
|
||||
}
|
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
/**
|
||||
@ -28,6 +29,16 @@ import javax.swing.filechooser.FileFilter;
|
||||
*/
|
||||
public class GeneralFilter extends FileFilter{
|
||||
|
||||
|
||||
// Extensions & Descriptions for commonly used filters
|
||||
public static final List<String> RAW_IMAGE_EXTS = Arrays.asList(new String[]{".img", ".dd", ".001", ".aa", ".raw", ".bin"});
|
||||
public static final String RAW_IMAGE_DESC = "Raw Images (*.img, *.dd, *.001, *.aa, *.raw, *.bin)";
|
||||
|
||||
public static final List<String> ENCASE_IMAGE_EXTS = Arrays.asList(new String[]{".e01"});
|
||||
public static final String ENCASE_IMAGE_DESC = "Encase Images (*.e01)";
|
||||
|
||||
|
||||
|
||||
private List<String> extensions;
|
||||
private String desc;
|
||||
|
||||
|
218
Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
Normal file
218
Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JPanel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
|
||||
/**
|
||||
* Image data source processor.
|
||||
* Handles the addition of "disk images" to Autopsy.
|
||||
*
|
||||
* An instance of this class is created via the Netbeans Lookup() method.
|
||||
*
|
||||
*/
|
||||
@ServiceProvider(service = DataSourceProcessor.class)
|
||||
public class ImageDSProcessor implements DataSourceProcessor {
|
||||
|
||||
|
||||
|
||||
static final Logger logger = Logger.getLogger(ImageDSProcessor.class.getName());
|
||||
|
||||
// Data source type handled by this processor
|
||||
protected final static String dsType = "Image File";
|
||||
|
||||
// The Config UI panel that plugins into the Choose Data Source Wizard
|
||||
private ImageFilePanel imageFilePanel;
|
||||
|
||||
// The Background task that does the actual work of adding the image
|
||||
private AddImageTask addImageTask;
|
||||
|
||||
// true of cancelled by the caller
|
||||
private boolean cancelled = false;
|
||||
|
||||
DSPCallback callbackObj = null;
|
||||
|
||||
// set to TRUE if the image options have been set via API and config Jpanel should be ignored
|
||||
private boolean imageOptionsSet = false;
|
||||
|
||||
// image options
|
||||
private String imagePath;
|
||||
private String timeZone;
|
||||
private boolean noFatOrphans;
|
||||
|
||||
|
||||
|
||||
|
||||
static final GeneralFilter rawFilter = new GeneralFilter(GeneralFilter.RAW_IMAGE_EXTS, GeneralFilter.RAW_IMAGE_DESC);
|
||||
static final GeneralFilter encaseFilter = new GeneralFilter(GeneralFilter.ENCASE_IMAGE_EXTS, GeneralFilter.ENCASE_IMAGE_DESC);
|
||||
|
||||
static final List<String> allExt = new ArrayList<String>();
|
||||
static {
|
||||
allExt.addAll(GeneralFilter.RAW_IMAGE_EXTS);
|
||||
allExt.addAll(GeneralFilter.ENCASE_IMAGE_EXTS);
|
||||
}
|
||||
static final String allDesc = "All Supported Types";
|
||||
static final GeneralFilter allFilter = new GeneralFilter(allExt, allDesc);
|
||||
|
||||
static final List<FileFilter> filtersList = new ArrayList<FileFilter>();
|
||||
|
||||
static {
|
||||
filtersList.add(allFilter);
|
||||
filtersList.add(rawFilter);
|
||||
filtersList.add(encaseFilter);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A no argument constructor is required for the NM lookup() method to create an object
|
||||
*/
|
||||
public ImageDSProcessor() {
|
||||
|
||||
// Create the config panel
|
||||
imageFilePanel = ImageFilePanel.createInstance(ImageDSProcessor.class.getName(), filtersList);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Data source type (string) handled by this DSP
|
||||
*
|
||||
* @return String the data source type
|
||||
**/
|
||||
@Override
|
||||
public String getType() {
|
||||
return dsType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JPanel for collecting the Data source information
|
||||
*
|
||||
* @return JPanel the config panel
|
||||
**/
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
|
||||
|
||||
imageFilePanel.readSettings();
|
||||
imageFilePanel.select();
|
||||
|
||||
return imageFilePanel;
|
||||
}
|
||||
/**
|
||||
* Validates the data collected by the JPanel
|
||||
*
|
||||
* @return String returns NULL if success, error string if there is any errors
|
||||
**/
|
||||
@Override
|
||||
public boolean validatePanel() {
|
||||
|
||||
return imageFilePanel.validatePanel();
|
||||
}
|
||||
/**
|
||||
* Runs the data source processor.
|
||||
* This must kick off processing the data source in background
|
||||
*
|
||||
* @param progressMonitor Progress monitor to report progress during processing
|
||||
* @param cbObj callback to call when processing is done.
|
||||
**/
|
||||
@Override
|
||||
public void run(DSPProgressMonitor progressMonitor, DSPCallback cbObj) {
|
||||
|
||||
callbackObj = cbObj;
|
||||
cancelled = false;
|
||||
|
||||
if (!imageOptionsSet)
|
||||
{
|
||||
//tell the panel to save the current settings
|
||||
imageFilePanel.storeSettings();
|
||||
|
||||
// get the image options from the panel
|
||||
imagePath = imageFilePanel.getContentPaths();
|
||||
timeZone = imageFilePanel.getTimeZone();
|
||||
noFatOrphans = imageFilePanel.getNoFatOrphans();
|
||||
}
|
||||
|
||||
addImageTask = new AddImageTask(imagePath, timeZone, noFatOrphans, progressMonitor, cbObj);
|
||||
new Thread(addImageTask).start();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the data source processing
|
||||
**/
|
||||
@Override
|
||||
public void cancel() {
|
||||
|
||||
cancelled = true;
|
||||
|
||||
addImageTask.cancelTask();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the data source processor
|
||||
**/
|
||||
@Override
|
||||
public void reset() {
|
||||
|
||||
// reset the config panel
|
||||
imageFilePanel.reset();
|
||||
|
||||
// reset state
|
||||
imageOptionsSet = false;
|
||||
imagePath = null;
|
||||
timeZone = null;
|
||||
noFatOrphans = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data source options externally.
|
||||
* To be used by a client that does not have a UI and does not use the JPanel to
|
||||
* collect this information from a user.
|
||||
*
|
||||
* @param imgPath path to thew image or first image
|
||||
* @param String timeZone
|
||||
* @param noFat whether to parse FAT orphans
|
||||
**/
|
||||
public void setDataSourceOptions(String imgPath, String tz, boolean noFat) {
|
||||
|
||||
this.imagePath = imgPath;
|
||||
this.timeZone = tz;
|
||||
this.noFatOrphans = noFat;
|
||||
|
||||
imageOptionsSet = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -31,8 +31,20 @@
|
||||
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="pathLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="284" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="timeZoneLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="timeZoneComboBox" min="-2" pref="215" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="pathLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="noFatOrphansCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
|
||||
<Component id="descLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="20" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -45,6 +57,16 @@
|
||||
<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="separate" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="timeZoneLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="timeZoneComboBox" 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 max="-2" attributes="0"/>
|
||||
<Component id="descLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -74,5 +96,40 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="timeZoneLabel">
|
||||
<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.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="timeZoneComboBox">
|
||||
<Properties>
|
||||
<Property name="maximumRowCount" type="int" value="30"/>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="noFatOrphansCheckbox">
|
||||
<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.noFatOrphansCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="ImageFilePanel.noFatOrphansCheckbox.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="descLabel">
|
||||
<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.descLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -22,41 +22,71 @@ import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
|
||||
|
||||
/**
|
||||
* ImageTypePanel for adding an image file such as .img, .E0x, .00x, etc.
|
||||
*/
|
||||
public class ImageFilePanel extends ContentTypePanel implements DocumentListener {
|
||||
private static ImageFilePanel instance = null;
|
||||
public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
|
||||
private final String PROP_LASTIMAGE_PATH = "LBL_LastImage_PATH";
|
||||
|
||||
private PropertyChangeSupport pcs = null;
|
||||
private JFileChooser fc = new JFileChooser();
|
||||
|
||||
// Externally supplied name is used to store settings
|
||||
private String contextName;
|
||||
|
||||
/**
|
||||
* Creates new form ImageFilePanel
|
||||
* @param context a string context name used to read/store last used settings
|
||||
* @param fileChooserFilters a list of filters to be used with the FileChooser
|
||||
*/
|
||||
public ImageFilePanel() {
|
||||
private ImageFilePanel(String context, List<FileFilter> fileChooserFilters) {
|
||||
initComponents();
|
||||
fc.setDragEnabled(false);
|
||||
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
fc.setMultiSelectionEnabled(false);
|
||||
fc.addChoosableFileFilter(AddImageWizardChooseDataSourceVisual.rawFilter);
|
||||
fc.addChoosableFileFilter(AddImageWizardChooseDataSourceVisual.encaseFilter);
|
||||
fc.setFileFilter(AddImageWizardChooseDataSourceVisual.allFilter);
|
||||
|
||||
boolean firstFilter = true;
|
||||
for (FileFilter filter: fileChooserFilters ) {
|
||||
if (firstFilter) { // set the first on the list as the default selection
|
||||
fc.setFileFilter(filter);
|
||||
firstFilter = false;
|
||||
}
|
||||
else {
|
||||
fc.addChoosableFileFilter(filter);
|
||||
}
|
||||
}
|
||||
|
||||
this.contextName = context;
|
||||
pcs = new PropertyChangeSupport(this);
|
||||
|
||||
createTimeZoneList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default instance of a ImageFilePanel.
|
||||
* Creates and returns an instance of a ImageFilePanel.
|
||||
*/
|
||||
public static synchronized ImageFilePanel getDefault() {
|
||||
if (instance == null) {
|
||||
instance = new ImageFilePanel();
|
||||
instance.postInit();
|
||||
}
|
||||
return instance;
|
||||
public static synchronized ImageFilePanel createInstance(String context, List<FileFilter> fileChooserFilters) {
|
||||
|
||||
ImageFilePanel instance = new ImageFilePanel(context, fileChooserFilters );
|
||||
|
||||
instance.postInit();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
//post-constructor initialization to properly initialize listener support
|
||||
@ -79,6 +109,10 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener
|
||||
pathLabel = new javax.swing.JLabel();
|
||||
browseButton = new javax.swing.JButton();
|
||||
pathTextField = new javax.swing.JTextField();
|
||||
timeZoneLabel = new javax.swing.JLabel();
|
||||
timeZoneComboBox = new javax.swing.JComboBox<String>();
|
||||
noFatOrphansCheckbox = new javax.swing.JCheckBox();
|
||||
descLabel = new javax.swing.JLabel();
|
||||
|
||||
setMinimumSize(new java.awt.Dimension(0, 65));
|
||||
setPreferredSize(new java.awt.Dimension(403, 65));
|
||||
@ -94,6 +128,15 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener
|
||||
|
||||
pathTextField.setText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.pathTextField.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.timeZoneLabel.text")); // NOI18N
|
||||
|
||||
timeZoneComboBox.setMaximumRowCount(30);
|
||||
|
||||
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
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(descLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.descLabel.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
@ -104,8 +147,17 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener
|
||||
.addComponent(browseButton)
|
||||
.addGap(2, 2, 2))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(pathLabel)
|
||||
.addGap(0, 284, Short.MAX_VALUE))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(timeZoneLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(pathLabel)
|
||||
.addComponent(noFatOrphansCheckbox)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(21, 21, 21)
|
||||
.addComponent(descLabel)))
|
||||
.addGap(0, 20, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -114,7 +166,16 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener
|
||||
.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)))
|
||||
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(timeZoneLabel)
|
||||
.addComponent(timeZoneComboBox, 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.RELATED)
|
||||
.addComponent(descLabel)
|
||||
.addContainerGap(33, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -131,20 +192,23 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener
|
||||
String path = fc.getSelectedFile().getPath();
|
||||
pathTextField.setText(path);
|
||||
}
|
||||
pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.FOCUS_NEXT.toString(), false, true);
|
||||
pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString(), false, true);
|
||||
}//GEN-LAST:event_browseButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton browseButton;
|
||||
private javax.swing.JLabel descLabel;
|
||||
private javax.swing.JCheckBox noFatOrphansCheckbox;
|
||||
private javax.swing.JLabel pathLabel;
|
||||
private javax.swing.JTextField pathTextField;
|
||||
private javax.swing.JComboBox<String> timeZoneComboBox;
|
||||
private javax.swing.JLabel timeZoneLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
* Get the path of the user selected image.
|
||||
* @return the image path
|
||||
*/
|
||||
@Override
|
||||
public String getContentPaths() {
|
||||
return pathTextField.getText();
|
||||
}
|
||||
@ -152,33 +216,37 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener
|
||||
/**
|
||||
* Set the path of the image file.
|
||||
*/
|
||||
@Override
|
||||
public void setContentPath(String s) {
|
||||
pathTextField.setText(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType getContentType() {
|
||||
return ContentType.IMAGE;
|
||||
public String getTimeZone() {
|
||||
String tz = timeZoneComboBox.getSelectedItem().toString();
|
||||
return tz.substring(tz.indexOf(")") + 2).trim();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getNoFatOrphans() {
|
||||
return noFatOrphansCheckbox.isSelected();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void reset() {
|
||||
//nothing to reset
|
||||
//reset the UI elements to default
|
||||
pathTextField.setText(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Should we enable the next button of the wizard?
|
||||
* @return true if a proper image has been selected, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean enableNext() {
|
||||
public boolean validatePanel() {
|
||||
String path = getContentPaths();
|
||||
if (path == null || path.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isExist = Case.pathExists(path);
|
||||
boolean isPhysicalDrive = Case.isPhysicalDrive(path);
|
||||
boolean isPartition = Case.isPartition(path);
|
||||
@ -186,6 +254,57 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener
|
||||
return (isExist || isPhysicalDrive || isPartition);
|
||||
}
|
||||
|
||||
|
||||
public void storeSettings() {
|
||||
String imagePathName = getContentPaths();
|
||||
if (null != imagePathName ) {
|
||||
String imagePath = imagePathName.substring(0, imagePathName.lastIndexOf(File.separator) + 1);
|
||||
ModuleSettings.setConfigSetting(contextName, PROP_LASTIMAGE_PATH, imagePath);
|
||||
}
|
||||
}
|
||||
|
||||
public void readSettings() {
|
||||
String lastImagePath = ModuleSettings.getConfigSetting(contextName, PROP_LASTIMAGE_PATH);
|
||||
if (null != lastImagePath) {
|
||||
if (!lastImagePath.isEmpty())
|
||||
pathTextField.setText(lastImagePath);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates the drop down list for the time zones and then makes the local
|
||||
* machine time zone to be selected.
|
||||
*/
|
||||
public void createTimeZoneList() {
|
||||
// load and add all timezone
|
||||
String[] ids = SimpleTimeZone.getAvailableIDs();
|
||||
for (String id : ids) {
|
||||
TimeZone zone = TimeZone.getTimeZone(id);
|
||||
int offset = zone.getRawOffset() / 1000;
|
||||
int hour = offset / 3600;
|
||||
int minutes = (offset % 3600) / 60;
|
||||
String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id);
|
||||
|
||||
/*
|
||||
* DateFormat dfm = new SimpleDateFormat("z");
|
||||
* dfm.setTimeZone(zone); boolean hasDaylight =
|
||||
* zone.useDaylightTime(); String first = dfm.format(new Date(2010,
|
||||
* 1, 1)); String second = dfm.format(new Date(2011, 6, 6)); int mid
|
||||
* = hour * -1; String result = first + Integer.toString(mid);
|
||||
* if(hasDaylight){ result = result + second; }
|
||||
* timeZoneComboBox.addItem(item + " (" + result + ")");
|
||||
*/
|
||||
timeZoneComboBox.addItem(item);
|
||||
}
|
||||
// get the current timezone
|
||||
TimeZone thisTimeZone = Calendar.getInstance().getTimeZone();
|
||||
int thisOffset = thisTimeZone.getRawOffset() / 1000;
|
||||
int thisHour = thisOffset / 3600;
|
||||
int thisMinutes = (thisOffset % 3600) / 60;
|
||||
String formatted = String.format("(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID());
|
||||
|
||||
// set the selected timezone
|
||||
timeZoneComboBox.setSelectedItem(formatted);
|
||||
}
|
||||
/**
|
||||
* Update functions are called by the pathTextField which has this set
|
||||
* as it's DocumentEventListener. Each update function fires a property change
|
||||
@ -194,34 +313,26 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener
|
||||
*/
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true);
|
||||
pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true);
|
||||
pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true);
|
||||
pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the focus to the pathTextField.
|
||||
*/
|
||||
@Override
|
||||
public void select() {
|
||||
pathTextField.requestFocusInWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the string form of this panel
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Image File";
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void addPropertyChangeListener(PropertyChangeListener pcl) {
|
||||
|
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
|
||||
@ServiceProvider(service = DataSourceProcessor.class)
|
||||
public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
|
||||
static final Logger logger = Logger.getLogger(ImageDSProcessor.class.getName());
|
||||
|
||||
// Data source type handled by this processor
|
||||
static protected final String dsType = "Local Disk";
|
||||
|
||||
// The Config UI panel that plugins into the Choose Data Source Wizard
|
||||
private LocalDiskPanel localDiskPanel;
|
||||
|
||||
// The Background task that does the actual work of adding the local Disk
|
||||
// Adding a local disk is exactly same as adding an Image.
|
||||
private AddImageTask addDiskTask;
|
||||
|
||||
// true if cancelled by the caller
|
||||
private boolean cancelled = false;
|
||||
|
||||
DSPCallback callbackObj = null;
|
||||
|
||||
// set to TRUE if the image options have been set via API and config Jpanel should be ignored
|
||||
private boolean localDiskOptionsSet = false;
|
||||
|
||||
// data source options
|
||||
private String localDiskPath;
|
||||
private String timeZone;
|
||||
private boolean noFatOrphans;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* A no argument constructor is required for the NM lookup() method to create an object
|
||||
*/
|
||||
public LocalDiskDSProcessor() {
|
||||
|
||||
// Create the config panel
|
||||
localDiskPanel = LocalDiskPanel.getDefault();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Data source type (string) handled by this DSP
|
||||
*
|
||||
* @return String the data source type
|
||||
**/
|
||||
@Override
|
||||
public String getType() {
|
||||
return dsType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JPanel for collecting the Data source information
|
||||
*
|
||||
* @return JPanel the config panel
|
||||
**/
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
|
||||
localDiskPanel.select();
|
||||
return localDiskPanel;
|
||||
}
|
||||
/**
|
||||
* Validates the data collected by the JPanel
|
||||
*
|
||||
* @return String returns NULL if success, error string if there is any errors
|
||||
**/
|
||||
@Override
|
||||
public boolean validatePanel() {
|
||||
return localDiskPanel.validatePanel();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Runs the data source processor.
|
||||
* This must kick off processing the data source in background
|
||||
*
|
||||
* @param progressMonitor Progress monitor to report progress during processing
|
||||
* @param cbObj callback to call when processing is done.
|
||||
**/
|
||||
@Override
|
||||
public void run(DSPProgressMonitor progressMonitor, DSPCallback cbObj) {
|
||||
|
||||
callbackObj = cbObj;
|
||||
cancelled = false;
|
||||
|
||||
if (!localDiskOptionsSet) {
|
||||
// get the image options from the panel
|
||||
localDiskPath = localDiskPanel.getContentPaths();
|
||||
timeZone = localDiskPanel.getTimeZone();
|
||||
noFatOrphans = localDiskPanel.getNoFatOrphans();
|
||||
}
|
||||
|
||||
addDiskTask = new AddImageTask(localDiskPath, timeZone, noFatOrphans, progressMonitor, cbObj);
|
||||
new Thread(addDiskTask).start();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Cancel the data source processing
|
||||
**/
|
||||
@Override
|
||||
public void cancel() {
|
||||
|
||||
cancelled = true;
|
||||
|
||||
addDiskTask.cancelTask();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the data source processor
|
||||
**/
|
||||
@Override
|
||||
public void reset() {
|
||||
|
||||
// reset the config panel
|
||||
localDiskPanel.reset();
|
||||
|
||||
// reset state
|
||||
localDiskOptionsSet = false;
|
||||
localDiskPath = null;
|
||||
timeZone = null;
|
||||
noFatOrphans = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data source options externally.
|
||||
* To be used by a client that does not have a UI and does not use the JPanel to
|
||||
* collect this information from a user.
|
||||
*
|
||||
* @param diskPath path to the local disk
|
||||
* @param String timeZone
|
||||
* @param noFat whether to parse FAT orphans
|
||||
**/
|
||||
public void setDataSourceOptions(String diskPath, String tz, boolean noFat) {
|
||||
|
||||
this.localDiskPath = diskPath;
|
||||
this.timeZone = tz;
|
||||
this.noFatOrphans = noFat;
|
||||
|
||||
localDiskOptionsSet = true;
|
||||
|
||||
}
|
||||
}
|
@ -29,8 +29,18 @@
|
||||
<Component id="diskLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="diskComboBox" min="-2" pref="345" max="-2" attributes="0"/>
|
||||
<Component id="errorLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="timeZoneLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="timeZoneComboBox" min="-2" pref="215" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
|
||||
<Component id="descLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="140" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="102" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -40,8 +50,18 @@
|
||||
<Component id="diskLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="diskComboBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="13" max="-2" attributes="0"/>
|
||||
<Component id="errorLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="timeZoneLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="timeZoneComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="descLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -71,5 +91,40 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="timeZoneLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalDiskPanel.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="timeZoneComboBox">
|
||||
<Properties>
|
||||
<Property name="maximumRowCount" type="int" value="30"/>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="noFatOrphansCheckbox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalDiskPanel.noFatOrphansCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalDiskPanel.noFatOrphansCheckbox.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="descLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalDiskPanel.descLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -25,7 +25,10 @@ import java.awt.Font;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.ComboBoxModel;
|
||||
@ -37,13 +40,16 @@ import javax.swing.ListCellRenderer;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.ListDataListener;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
|
||||
/**
|
||||
* ImageTypePanel for adding a local disk or partition such as PhysicalDrive0 or C:.
|
||||
*/
|
||||
public class LocalDiskPanel extends ContentTypePanel {
|
||||
public class LocalDiskPanel extends JPanel {
|
||||
private static final Logger logger = Logger.getLogger(LocalDiskPanel.class.getName());
|
||||
|
||||
private static LocalDiskPanel instance;
|
||||
private PropertyChangeSupport pcs = null;
|
||||
private List<LocalDisk> disks = new ArrayList<LocalDisk>();
|
||||
@ -56,6 +62,9 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
public LocalDiskPanel() {
|
||||
initComponents();
|
||||
customInit();
|
||||
|
||||
createTimeZoneList();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,8 +82,10 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
model = new LocalDiskModel();
|
||||
diskComboBox.setModel(model);
|
||||
diskComboBox.setRenderer(model);
|
||||
|
||||
errorLabel.setText("");
|
||||
diskComboBox.setEnabled(false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,6 +100,10 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
diskLabel = new javax.swing.JLabel();
|
||||
diskComboBox = new javax.swing.JComboBox();
|
||||
errorLabel = new javax.swing.JLabel();
|
||||
timeZoneLabel = new javax.swing.JLabel();
|
||||
timeZoneComboBox = new javax.swing.JComboBox<String>();
|
||||
noFatOrphansCheckbox = new javax.swing.JCheckBox();
|
||||
descLabel = new javax.swing.JLabel();
|
||||
|
||||
setMinimumSize(new java.awt.Dimension(0, 65));
|
||||
setPreferredSize(new java.awt.Dimension(485, 65));
|
||||
@ -98,6 +113,15 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
errorLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.errorLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.timeZoneLabel.text")); // NOI18N
|
||||
|
||||
timeZoneComboBox.setMaximumRowCount(30);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.noFatOrphansCheckbox.text")); // NOI18N
|
||||
noFatOrphansCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.noFatOrphansCheckbox.toolTipText")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(descLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.descLabel.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
@ -106,8 +130,16 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(diskLabel)
|
||||
.addComponent(diskComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(errorLabel))
|
||||
.addGap(0, 140, Short.MAX_VALUE))
|
||||
.addComponent(errorLabel)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(timeZoneLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(noFatOrphansCheckbox)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(21, 21, 21)
|
||||
.addComponent(descLabel)))
|
||||
.addGap(0, 102, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -115,21 +147,34 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
.addComponent(diskLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(diskComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(13, 13, 13)
|
||||
.addComponent(errorLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(timeZoneLabel)
|
||||
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(noFatOrphansCheckbox)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(errorLabel))
|
||||
.addComponent(descLabel)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JLabel descLabel;
|
||||
private javax.swing.JComboBox diskComboBox;
|
||||
private javax.swing.JLabel diskLabel;
|
||||
private javax.swing.JLabel errorLabel;
|
||||
private javax.swing.JCheckBox noFatOrphansCheckbox;
|
||||
private javax.swing.JComboBox<String> timeZoneComboBox;
|
||||
private javax.swing.JLabel timeZoneLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
* Return the currently selected disk path.
|
||||
* @return String selected disk path
|
||||
*/
|
||||
@Override
|
||||
//@Override
|
||||
public String getContentPaths() {
|
||||
if(disks.size() > 0) {
|
||||
LocalDisk selected = (LocalDisk) diskComboBox.getSelectedItem();
|
||||
@ -143,7 +188,7 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
/**
|
||||
* Set the selected disk.
|
||||
*/
|
||||
@Override
|
||||
// @Override
|
||||
public void setContentPath(String s) {
|
||||
for(int i=0; i<disks.size(); i++) {
|
||||
if(disks.get(i).getPath().equals(s)) {
|
||||
@ -152,9 +197,14 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType getContentType() {
|
||||
return ContentType.DISK;
|
||||
public String getTimeZone() {
|
||||
String tz = timeZoneComboBox.getSelectedItem().toString();
|
||||
return tz.substring(tz.indexOf(")") + 2).trim();
|
||||
|
||||
}
|
||||
|
||||
boolean getNoFatOrphans() {
|
||||
return noFatOrphansCheckbox.isSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -162,31 +212,27 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
* Always return true because we control the possible selections.
|
||||
* @return true
|
||||
*/
|
||||
@Override
|
||||
public boolean enableNext() {
|
||||
//@Override
|
||||
public boolean validatePanel() {
|
||||
return enableNext;
|
||||
}
|
||||
|
||||
@Override
|
||||
//@Override
|
||||
public void reset() {
|
||||
//nothing to reset
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the representation of this panel as a String.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Local Disk";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the focus to the diskComboBox and refreshes the list of disks.
|
||||
*/
|
||||
@Override
|
||||
// @Override
|
||||
public void select() {
|
||||
diskComboBox.requestFocusInWindow();
|
||||
model.loadDisks();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -207,16 +253,61 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
pcs.removePropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the drop down list for the time zones and then makes the local
|
||||
* machine time zone to be selected.
|
||||
*/
|
||||
public void createTimeZoneList() {
|
||||
// load and add all timezone
|
||||
String[] ids = SimpleTimeZone.getAvailableIDs();
|
||||
for (String id : ids) {
|
||||
TimeZone zone = TimeZone.getTimeZone(id);
|
||||
int offset = zone.getRawOffset() / 1000;
|
||||
int hour = offset / 3600;
|
||||
int minutes = (offset % 3600) / 60;
|
||||
String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id);
|
||||
|
||||
/*
|
||||
* DateFormat dfm = new SimpleDateFormat("z");
|
||||
* dfm.setTimeZone(zone); boolean hasDaylight =
|
||||
* zone.useDaylightTime(); String first = dfm.format(new Date(2010,
|
||||
* 1, 1)); String second = dfm.format(new Date(2011, 6, 6)); int mid
|
||||
* = hour * -1; String result = first + Integer.toString(mid);
|
||||
* if(hasDaylight){ result = result + second; }
|
||||
* timeZoneComboBox.addItem(item + " (" + result + ")");
|
||||
*/
|
||||
timeZoneComboBox.addItem(item);
|
||||
}
|
||||
// get the current timezone
|
||||
TimeZone thisTimeZone = Calendar.getInstance().getTimeZone();
|
||||
int thisOffset = thisTimeZone.getRawOffset() / 1000;
|
||||
int thisHour = thisOffset / 3600;
|
||||
int thisMinutes = (thisOffset % 3600) / 60;
|
||||
String formatted = String.format("(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID());
|
||||
|
||||
// set the selected timezone
|
||||
timeZoneComboBox.setSelectedItem(formatted);
|
||||
}
|
||||
|
||||
private class LocalDiskModel implements ComboBoxModel, ListCellRenderer {
|
||||
private Object selected;
|
||||
private boolean ready = false;
|
||||
private volatile boolean loadingDisks = false;
|
||||
List<LocalDisk> physical = new ArrayList<LocalDisk>();
|
||||
List<LocalDisk> partitions = new ArrayList<LocalDisk>();
|
||||
|
||||
//private String SELECT = "Select a local disk:";
|
||||
private String LOADING = "Loading local disks...";
|
||||
LocalDiskThread worker = null;
|
||||
|
||||
|
||||
private void loadDisks() {
|
||||
|
||||
// if there is a worker already building the lists, then cancel it first.
|
||||
if (loadingDisks && worker != null) {
|
||||
worker.cancel(false);
|
||||
}
|
||||
|
||||
// Clear the lists
|
||||
errorLabel.setText("");
|
||||
disks = new ArrayList<LocalDisk>();
|
||||
@ -224,9 +315,13 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
partitions = new ArrayList<LocalDisk>();
|
||||
diskComboBox.setEnabled(false);
|
||||
ready = false;
|
||||
enableNext = false;
|
||||
loadingDisks = true;
|
||||
|
||||
LocalDiskThread worker = new LocalDiskThread();
|
||||
worker = new LocalDiskThread();
|
||||
worker.execute();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -234,7 +329,7 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
if(ready) {
|
||||
selected = anItem;
|
||||
enableNext = true;
|
||||
pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true);
|
||||
pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,8 +395,6 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
// Populate the lists
|
||||
physical = PlatformUtil.getPhysicalDrives();
|
||||
partitions = PlatformUtil.getPartitions();
|
||||
disks.addAll(physical);
|
||||
disks.addAll(partitions);
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -337,6 +430,11 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
enableNext = false;
|
||||
displayErrors();
|
||||
ready = true;
|
||||
worker = null;
|
||||
loadingDisks = false;
|
||||
|
||||
disks.addAll(physical);
|
||||
disks.addAll(partitions);
|
||||
|
||||
if(disks.size() > 0) {
|
||||
diskComboBox.setEnabled(true);
|
||||
|
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
@ServiceProvider(service = DataSourceProcessor.class)
|
||||
public class LocalFilesDSProcessor implements DataSourceProcessor {
|
||||
|
||||
static final Logger logger = Logger.getLogger(LocalFilesDSProcessor.class.getName());
|
||||
|
||||
// Data source type handled by this processor
|
||||
protected static final String dsType = "Logical Files";
|
||||
|
||||
// The Config UI panel that plugins into the Choose Data Source Wizard
|
||||
private LocalFilesPanel localFilesPanel;
|
||||
|
||||
// The Background task that does the actual work of adding the files
|
||||
private AddLocalFilesTask addFilesTask;
|
||||
|
||||
// true if cancelled by the caller
|
||||
private boolean cancelled = false;
|
||||
|
||||
DSPCallback callbackObj = null;
|
||||
|
||||
// set to TRUE if the image options have been set via API and config Jpanel should be ignored
|
||||
private boolean localFilesOptionsSet = false;
|
||||
|
||||
// data source options
|
||||
private String localFilesPath;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* A no argument constructor is required for the NM lookup() method to create an object
|
||||
*/
|
||||
public LocalFilesDSProcessor() {
|
||||
|
||||
// Create the config panel
|
||||
localFilesPanel = LocalFilesPanel.getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Data source type (string) handled by this DSP
|
||||
*
|
||||
* @return String the data source type
|
||||
**/
|
||||
@Override
|
||||
public String getType() {
|
||||
return dsType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JPanel for collecting the Data source information
|
||||
*
|
||||
* @return JPanel the config panel
|
||||
**/
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
localFilesPanel.select();
|
||||
return localFilesPanel;
|
||||
}
|
||||
/**
|
||||
* Validates the data collected by the JPanel
|
||||
*
|
||||
* @return String returns NULL if success, error string if there is any errors
|
||||
**/
|
||||
@Override
|
||||
public boolean validatePanel() {
|
||||
return localFilesPanel.validatePanel();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Runs the data source processor.
|
||||
* This must kick off processing the data source in background
|
||||
*
|
||||
* @param progressMonitor Progress monitor to report progress during processing
|
||||
* @param cbObj callback to call when processing is done.
|
||||
**/
|
||||
@Override
|
||||
public void run(DSPProgressMonitor progressMonitor, DSPCallback cbObj) {
|
||||
|
||||
callbackObj = cbObj;
|
||||
cancelled = false;
|
||||
|
||||
if (!localFilesOptionsSet) {
|
||||
// get the selected file paths from the panel
|
||||
localFilesPath = localFilesPanel.getContentPaths();
|
||||
}
|
||||
|
||||
addFilesTask = new AddLocalFilesTask(localFilesPath, progressMonitor, cbObj);
|
||||
new Thread(addFilesTask).start();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the data source processing
|
||||
**/
|
||||
@Override
|
||||
public void cancel() {
|
||||
|
||||
cancelled = true;
|
||||
addFilesTask.cancelTask();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the data source processor
|
||||
**/
|
||||
@Override
|
||||
public void reset() {
|
||||
|
||||
// reset the config panel
|
||||
localFilesPanel.reset();
|
||||
|
||||
// reset state
|
||||
localFilesOptionsSet = false;
|
||||
localFilesPath = null;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data source options externally.
|
||||
* To be used by a client that does not have a UI and does not use the JPanel to
|
||||
* collect this information from a user.
|
||||
*
|
||||
* @param filesPath PATH_SEP list of paths to local files
|
||||
*
|
||||
**/
|
||||
public void setDataSourceOptions(String filesPath) {
|
||||
|
||||
this.localFilesPath = filesPath;
|
||||
|
||||
localFilesOptionsSet = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -24,11 +24,13 @@ import java.io.File;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JPanel;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
|
||||
/**
|
||||
* Add input wizard subpanel for adding local files / dirs to the case
|
||||
*/
|
||||
public class LocalFilesPanel extends ContentTypePanel {
|
||||
public class LocalFilesPanel extends JPanel {
|
||||
|
||||
private PropertyChangeSupport pcs = null;
|
||||
private Set<File> currentFiles = new TreeSet<File>(); //keep currents in a set to disallow duplicates per add
|
||||
@ -57,7 +59,7 @@ public class LocalFilesPanel extends ContentTypePanel {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
//@Override
|
||||
public String getContentPaths() {
|
||||
//TODO consider interface change to return list of paths instead
|
||||
|
||||
@ -72,36 +74,37 @@ public class LocalFilesPanel extends ContentTypePanel {
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
//@Override
|
||||
public void setContentPath(String s) {
|
||||
//for the local file panel we don't need to restore the last paths used
|
||||
//when the wizard restarts
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType getContentType() {
|
||||
return ContentType.LOCAL;
|
||||
//@Override
|
||||
public String getContentType() {
|
||||
return "LOCAL";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enableNext() {
|
||||
//@Override
|
||||
public boolean validatePanel() {
|
||||
return enableNext;
|
||||
}
|
||||
|
||||
@Override
|
||||
//@Override
|
||||
public void select() {
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
//@Override
|
||||
public void reset() {
|
||||
currentFiles.clear();
|
||||
selectedPaths.setText("");
|
||||
enableNext = false;
|
||||
pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true);
|
||||
|
||||
//pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public synchronized void addPropertyChangeListener(PropertyChangeListener pcl) {
|
||||
super.addPropertyChangeListener(pcl);
|
||||
|
||||
@ -231,7 +234,7 @@ public class LocalFilesPanel extends ContentTypePanel {
|
||||
else {
|
||||
enableNext = false;
|
||||
}
|
||||
pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true);
|
||||
pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
|
||||
}//GEN-LAST:event_selectButtonActionPerformed
|
||||
|
||||
private void clearButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clearButtonActionPerformed
|
||||
|
@ -110,65 +110,49 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="typePanel" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="typeTabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="typeComboBox" pref="298" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="pathNameTextField" min="-2" pref="285" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="83" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="typeTabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="typeComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pathNameTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="typePanel" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace pref="62" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JComboBox" name="typeComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="typeTabel">
|
||||
<Component class="javax.swing.JTextField" name="pathNameTextField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MissingImageDialog.typeTabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MissingImageDialog.pathNameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="pathNameTextFieldActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="browseButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MissingImageDialog.browseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="typePanel">
|
||||
|
||||
<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="57" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="titleLabel">
|
||||
|
@ -18,49 +18,71 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.JDialog;
|
||||
import java.io.File;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.event.ListDataListener;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.sleuthkit.autopsy.casemodule.GeneralFilter;
|
||||
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
|
||||
|
||||
public class MissingImageDialog extends javax.swing.JDialog {
|
||||
private static final Logger logger = Logger.getLogger(MissingImageDialog.class.getName());
|
||||
long obj_id;
|
||||
SleuthkitCase db;
|
||||
ContentTypePanel currentPanel;
|
||||
ImageTypeModel model;
|
||||
|
||||
|
||||
|
||||
static final GeneralFilter rawFilter = new GeneralFilter(GeneralFilter.RAW_IMAGE_EXTS, GeneralFilter.RAW_IMAGE_DESC);
|
||||
static final GeneralFilter encaseFilter = new GeneralFilter(GeneralFilter.ENCASE_IMAGE_EXTS, GeneralFilter.ENCASE_IMAGE_DESC);
|
||||
|
||||
static final List<String> allExt = new ArrayList<String>();
|
||||
static {
|
||||
allExt.addAll(GeneralFilter.RAW_IMAGE_EXTS);
|
||||
allExt.addAll(GeneralFilter.ENCASE_IMAGE_EXTS);
|
||||
}
|
||||
static final String allDesc = "All Supported Types";
|
||||
static final GeneralFilter allFilter = new GeneralFilter(allExt, allDesc);
|
||||
|
||||
private JFileChooser fc = new JFileChooser();
|
||||
|
||||
private MissingImageDialog(long obj_id, SleuthkitCase db) {
|
||||
super(new JFrame(), true);
|
||||
this.obj_id = obj_id;
|
||||
this.db = db;
|
||||
initComponents();
|
||||
|
||||
fc.setDragEnabled(false);
|
||||
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
fc.setMultiSelectionEnabled(false);
|
||||
|
||||
fc.addChoosableFileFilter(rawFilter);
|
||||
fc.addChoosableFileFilter(encaseFilter);
|
||||
fc.setFileFilter(allFilter);
|
||||
|
||||
|
||||
customInit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Client call to create a MissingImageDialog.
|
||||
*
|
||||
* @param obj_id obj_id of the missing image
|
||||
* @param db the current SleuthkitCase connected to a db
|
||||
*/
|
||||
//
|
||||
// * Client call to create a MissingImageDialog.
|
||||
// *
|
||||
// * @param obj_id obj_id of the missing image
|
||||
// * @param db the current SleuthkitCase connected to a db
|
||||
//
|
||||
static void makeDialog(long obj_id, SleuthkitCase db) {
|
||||
final MissingImageDialog dialog = new MissingImageDialog(obj_id, db);
|
||||
dialog.addWindowListener(new WindowAdapter() {
|
||||
@ -73,11 +95,8 @@ public class MissingImageDialog extends javax.swing.JDialog {
|
||||
}
|
||||
|
||||
private void customInit() {
|
||||
model = new ImageTypeModel();
|
||||
typeComboBox.setModel(model);
|
||||
typeComboBox.setSelectedIndex(0);
|
||||
typePanel.setLayout(new BorderLayout());
|
||||
updateCurrentPanel(ImageFilePanel.getDefault());
|
||||
|
||||
selectButton.setEnabled(false);
|
||||
}
|
||||
|
||||
private void display() {
|
||||
@ -92,54 +111,31 @@ public class MissingImageDialog extends javax.swing.JDialog {
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh this panel.
|
||||
* @param panel current typepanel
|
||||
*/
|
||||
private void updateCurrentPanel(ContentTypePanel panel) {
|
||||
currentPanel = panel;
|
||||
typePanel.removeAll();
|
||||
typePanel.add((JPanel) currentPanel, BorderLayout.CENTER);
|
||||
typePanel.validate();
|
||||
typePanel.repaint();
|
||||
this.validate();
|
||||
this.repaint();
|
||||
currentPanel.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if(evt.getPropertyName().equals(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString())) {
|
||||
updateSelectButton();
|
||||
}
|
||||
if(evt.getPropertyName().equals(AddImageWizardChooseDataSourceVisual.EVENT.FOCUS_NEXT.toString())) {
|
||||
moveFocusToSelect();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
currentPanel.select();
|
||||
updateSelectButton();
|
||||
}
|
||||
|
||||
/**
|
||||
* Focuses the select button for easy enter-pressing access.
|
||||
*/
|
||||
//
|
||||
// * Focuses the select button for easy enter-pressing access.
|
||||
//
|
||||
private void moveFocusToSelect() {
|
||||
this.selectButton.requestFocusInWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables/disables the select button based off the current panel.
|
||||
*/
|
||||
//
|
||||
// * Enables/disables the select button based off the current panel.
|
||||
//
|
||||
private void updateSelectButton() {
|
||||
this.selectButton.setEnabled(currentPanel.enableNext());
|
||||
|
||||
// Enable this based on whether there is a valid path
|
||||
if (!pathNameTextField.getText().isEmpty()) {
|
||||
String filePath = pathNameTextField.getText();
|
||||
boolean isExist = Case.pathExists(filePath) || Case.driveExists(filePath);
|
||||
selectButton.setEnabled(isExist);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
//
|
||||
// * This method is called from within the constructor to initialize the form.
|
||||
// * WARNING: Do NOT modify this code. The content of this method is always
|
||||
// * regenerated by the Form Editor.
|
||||
//
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
@ -148,9 +144,8 @@ public class MissingImageDialog extends javax.swing.JDialog {
|
||||
selectButton = new javax.swing.JButton();
|
||||
cancelButton = new javax.swing.JButton();
|
||||
containerPanel = new javax.swing.JPanel();
|
||||
typeComboBox = new javax.swing.JComboBox();
|
||||
typeTabel = new javax.swing.JLabel();
|
||||
typePanel = new javax.swing.JPanel();
|
||||
pathNameTextField = new javax.swing.JTextField();
|
||||
browseButton = new javax.swing.JButton();
|
||||
titleLabel = new javax.swing.JLabel();
|
||||
titleSeparator = new javax.swing.JSeparator();
|
||||
|
||||
@ -191,43 +186,39 @@ public class MissingImageDialog extends javax.swing.JDialog {
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(typeTabel, org.openide.util.NbBundle.getMessage(MissingImageDialog.class, "MissingImageDialog.typeTabel.text")); // NOI18N
|
||||
pathNameTextField.setText(org.openide.util.NbBundle.getMessage(MissingImageDialog.class, "MissingImageDialog.pathNameTextField.text")); // NOI18N
|
||||
pathNameTextField.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
pathNameTextFieldActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout typePanelLayout = new javax.swing.GroupLayout(typePanel);
|
||||
typePanel.setLayout(typePanelLayout);
|
||||
typePanelLayout.setHorizontalGroup(
|
||||
typePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
);
|
||||
typePanelLayout.setVerticalGroup(
|
||||
typePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 57, Short.MAX_VALUE)
|
||||
);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(MissingImageDialog.class, "MissingImageDialog.browseButton.text")); // NOI18N
|
||||
browseButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
browseButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout containerPanelLayout = new javax.swing.GroupLayout(containerPanel);
|
||||
containerPanel.setLayout(containerPanelLayout);
|
||||
containerPanelLayout.setHorizontalGroup(
|
||||
containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(containerPanelLayout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(typePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(containerPanelLayout.createSequentialGroup()
|
||||
.addComponent(typeTabel)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(typeComboBox, 0, 298, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
.addContainerGap()
|
||||
.addComponent(pathNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 285, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(browseButton)
|
||||
.addContainerGap(83, Short.MAX_VALUE))
|
||||
);
|
||||
containerPanelLayout.setVerticalGroup(
|
||||
containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(containerPanelLayout.createSequentialGroup()
|
||||
.addGap(0, 0, 0)
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(typeTabel)
|
||||
.addComponent(typeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(typePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
.addComponent(pathNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(browseButton))
|
||||
.addContainerGap(62, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
titleLabel.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
|
||||
@ -268,7 +259,7 @@ public class MissingImageDialog extends javax.swing.JDialog {
|
||||
|
||||
private void selectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectButtonActionPerformed
|
||||
try {
|
||||
String newPath = currentPanel.getContentPaths();
|
||||
String newPath = pathNameTextField.getText();
|
||||
//TODO handle local files
|
||||
db.setImagePaths(obj_id, Arrays.asList(new String[]{newPath}));
|
||||
} catch (TskCoreException ex) {
|
||||
@ -281,21 +272,48 @@ public class MissingImageDialog extends javax.swing.JDialog {
|
||||
cancel();
|
||||
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||
|
||||
private void pathNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pathNameTextFieldActionPerformed
|
||||
// TODO add your handling code here:
|
||||
|
||||
updateSelectButton();
|
||||
}//GEN-LAST:event_pathNameTextFieldActionPerformed
|
||||
|
||||
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
|
||||
|
||||
|
||||
|
||||
String oldText = pathNameTextField.getText();
|
||||
|
||||
// set the current directory of the FileChooser if the ImagePath Field is valid
|
||||
File currentDir = new File(oldText);
|
||||
if (currentDir.exists()) {
|
||||
fc.setCurrentDirectory(currentDir);
|
||||
}
|
||||
|
||||
int retval = fc.showOpenDialog(this);
|
||||
if (retval == JFileChooser.APPROVE_OPTION) {
|
||||
String path = fc.getSelectedFile().getPath();
|
||||
pathNameTextField.setText(path);
|
||||
}
|
||||
//pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString(), false, true);
|
||||
|
||||
updateSelectButton();
|
||||
}//GEN-LAST:event_browseButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton browseButton;
|
||||
private javax.swing.JPanel buttonPanel;
|
||||
private javax.swing.JButton cancelButton;
|
||||
private javax.swing.JPanel containerPanel;
|
||||
private javax.swing.JTextField pathNameTextField;
|
||||
private javax.swing.JButton selectButton;
|
||||
private javax.swing.JLabel titleLabel;
|
||||
private javax.swing.JSeparator titleSeparator;
|
||||
private javax.swing.JComboBox typeComboBox;
|
||||
private javax.swing.JPanel typePanel;
|
||||
private javax.swing.JLabel typeTabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
* Verify the user wants to cancel searching for the image.
|
||||
*/
|
||||
//
|
||||
// * Verify the user wants to cancel searching for the image.
|
||||
//
|
||||
void cancel() {
|
||||
int ret = JOptionPane.showConfirmDialog(null,
|
||||
"No image file has been selected, are you sure you\n" +
|
||||
@ -306,40 +324,5 @@ public class MissingImageDialog extends javax.swing.JDialog {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ComboBoxModel to control typeComboBox and supply ImageTypePanels.
|
||||
*/
|
||||
private class ImageTypeModel implements ComboBoxModel {
|
||||
ContentTypePanel selected;
|
||||
ContentTypePanel[] types = ContentTypePanel.getPanels();
|
||||
|
||||
@Override
|
||||
public void setSelectedItem(Object anItem) {
|
||||
selected = (ContentTypePanel) anItem;
|
||||
updateCurrentPanel(selected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSelectedItem() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return types.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
return types[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sleuthkit.autopsy.corecomponentinterfaces;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.util.List;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
|
||||
/**
|
||||
* Abstract class for a callback for a DataSourceProcessor.
|
||||
*
|
||||
* Ensures that DSP invokes the caller overridden method, doneEDT(),
|
||||
* in the EDT thread.
|
||||
*
|
||||
*/
|
||||
public abstract class DSPCallback {
|
||||
|
||||
public enum DSP_Result
|
||||
{
|
||||
NO_ERRORS,
|
||||
CRITICAL_ERRORS,
|
||||
NONCRITICAL_ERRORS,
|
||||
};
|
||||
|
||||
/*
|
||||
* Invoke the caller supplied callback function on the EDT thread
|
||||
*/
|
||||
public void done(DSP_Result result, List<String> errList, List<Content> newContents)
|
||||
{
|
||||
|
||||
final DSP_Result resultf = result;
|
||||
final List<String> errListf = errList;
|
||||
final List<Content> newContentsf = newContents;
|
||||
|
||||
// Invoke doneEDT() that runs on the EDT .
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doneEDT(resultf, errListf, newContentsf );
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* calling code overrides to provide its own calllback
|
||||
*/
|
||||
public abstract void doneEDT(DSP_Result result, List<String> errList, List<Content> newContents);
|
||||
};
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.corecomponentinterfaces;
|
||||
|
||||
/*
|
||||
* An GUI agnostic DSPProgressMonitor interface for DataSourceProcesssors to
|
||||
* indicate progress.
|
||||
* It models after a JProgressbar though it could use any underlying implementation
|
||||
*/
|
||||
public interface DSPProgressMonitor {
|
||||
|
||||
void setIndeterminate(boolean indeterminate);
|
||||
|
||||
void setProgress(int progress);
|
||||
|
||||
void setProgressText(String text);
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2013 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.corecomponentinterfaces;
|
||||
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
/*
|
||||
* Defines an interface used by the Add DataSource wizard to discover different
|
||||
* Data SourceProcessors.
|
||||
*
|
||||
* Each data source may have its unique attributes and may need to be processed
|
||||
* differently.
|
||||
*
|
||||
* The DataSourceProcessor interface defines a uniform mechanism for the Autopsy UI
|
||||
* to:
|
||||
* - collect details for the data source to be processed.
|
||||
* - Process the data source in the background
|
||||
* - Be notified when the processing is complete
|
||||
*/
|
||||
public interface DataSourceProcessor {
|
||||
|
||||
/*
|
||||
* The DSP Panel may fire Property change events
|
||||
* The caller must enure to add itself as a listener and
|
||||
* then react appropriately to the events
|
||||
*/
|
||||
enum DSP_PANEL_EVENT {
|
||||
|
||||
UPDATE_UI, // the content of JPanel has changed that MAY warrant updates to the caller UI
|
||||
FOCUS_NEXT // the caller UI may move focus the the next UI element, floowing the panel.
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the type of Data Source it handles.
|
||||
* This name gets displayed in the drop-down listbox
|
||||
**/
|
||||
String getType();
|
||||
|
||||
/**
|
||||
* Returns the picker panel to be displayed along with any other
|
||||
* runtime options supported by the data source handler.
|
||||
**/
|
||||
JPanel getPanel();
|
||||
|
||||
/**
|
||||
* Called to validate the input data in the panel.
|
||||
* Returns true if no errors, or
|
||||
* Returns false if there is an error.
|
||||
**/
|
||||
boolean validatePanel();
|
||||
|
||||
/**
|
||||
* Called to invoke the handling of Data source in the background.
|
||||
* Returns after starting the background thread
|
||||
* @param settings wizard settings to read/store properties
|
||||
* @param progressPanel progress panel to be updated while processing
|
||||
*
|
||||
**/
|
||||
void run(DSPProgressMonitor progressPanel, DSPCallback dspCallback);
|
||||
|
||||
|
||||
/**
|
||||
* Called to cancel the background processing.
|
||||
**/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* Called to reset/reinitialize the DSP.
|
||||
*
|
||||
**/
|
||||
void reset();
|
||||
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user