2031: add raw data source processor

This commit is contained in:
U-BASIS\zhaohui 2016-10-25 16:56:40 -04:00
parent c558a42ee1
commit d9606a97f4
6 changed files with 940 additions and 1 deletions

View File

@ -39,6 +39,7 @@ import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datasourceprocessors.RawDSProcessor;
/**
* visual component for the first panel of add image wizard. Allows the user to
@ -92,7 +93,8 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
datasourceProcessorsMap.remove(LocalDiskDSProcessor.getType());
}
coreDSPTypes.add(LocalFilesDSProcessor.getType());
coreDSPTypes.add(RawDSProcessor.getType());
for (String dspType : coreDSPTypes) {
typeComboBox.addItem(dspType);
}

View File

@ -0,0 +1,192 @@
package org.sleuthkit.autopsy.datasourceprocessors;
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 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.
*/
import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskFileRange;
/*
* A runnable that adds a raw data source to a case database.
*/
class AddRawImageTask implements Runnable {
private static final Logger logger = Logger.getLogger(AddRawImageTask.class.getName());
private static final String MODULE_NAME = "Raw Data Source Processor";
private final String deviceId;
private final String imageFilePath;
private final String timeZone;
private final long chunkSize;
private final DataSourceProcessorProgressMonitor progressMonitor;
private final DataSourceProcessorCallback callback;
private boolean criticalErrorOccurred;
private volatile boolean cancelled = false; //ZL: where do this use
/**
* Constructs a runnable that adds a raw data source to a case database.
*
* @param deviceId An ASCII-printable identifier for the
* device associated with the data source
* that is intended to be unique across
* multiple cases (e.g., a UUID).
* @param imageFilePath Path to a Raw data source file.
* @param timeZone The time zone to use when processing dates
* and times for the image, obtained from
* java.util.TimeZone.getID.
* @param breakupChunks 2GB or not breakup.
* @param progressMonitor Progress monitor for reporting
* progressMonitor during processing.
* @param callback Callback to call when processing is done.
*/
AddRawImageTask(String deviceId, String imageFilePath, String timeZone, long chunkSize, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
this.deviceId = deviceId;
this.imageFilePath = imageFilePath;
this.timeZone = timeZone;
this.chunkSize = chunkSize;
this.callback = callback;
this.progressMonitor = progressMonitor;
}
/**
* Adds a raw data source to a case database.
*/
@Override
public void run() {
/*
* Process the input image file.
*/
progressMonitor.setIndeterminate(true);
List<Content> newDataSources = new ArrayList<>();
List<String> errorMessages = new ArrayList<>();
addImageToCase(newDataSources, errorMessages);
/*
* This appears to be the best that can be done to indicate completion
* with the DataSourceProcessorProgressMonitor in its current form.
*/
progressMonitor.setProgress(0); //ZL TODO???
progressMonitor.setProgress(100);
/**
* Return the results via the callback passed to the constructor.
*/
DataSourceProcessorCallback.DataSourceProcessorResult result;
if (criticalErrorOccurred) {
result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
} else if (!errorMessages.isEmpty()) {
result = DataSourceProcessorCallback.DataSourceProcessorResult.NONCRITICAL_ERRORS;
} else {
result = DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS;
}
callback.done(result, errorMessages, newDataSources);
criticalErrorOccurred = false;
}
/**
* Attempts to add the input image to the case.
*
* @param newDataSources If the image is added, a data source is added to
* this list for eventual return to the caller via the
* callback.
* @param errorMessages If there are any error messages, the error messages
* are added to this list for eventual return to the
* caller via the callback.
*/
private void addImageToCase(List<Content> dataSources, List<String> errorMessages) {
progressMonitor.setProgressText(String.format("Adding raw image: %s", imageFilePath));
List<String> imageFilePaths = new ArrayList<>();
SleuthkitCase caseDatabase = Case.getCurrentCase().getSleuthkitCase();
caseDatabase.acquireExclusiveLock();
File imageFile = Paths.get(imageFilePath).toFile();
if (!imageFile.exists()) {
errorMessages.add(String.format("Critical error adding %s for device %s is not existing.", imageFilePath, deviceId));
criticalErrorOccurred = true;
return;
}
imageFilePaths.add(imageFilePath);
try {
/*
* Get Image that will be added to case
*/
Image dataSource = caseDatabase.addImageInfo(0, imageFilePaths, timeZone); //TODO: change hard coded deviceId.
dataSources.add(dataSource);
List<TskFileRange> fileRanges = new ArrayList<>();
/*
* Verify the size of the new image. Note that it may not be what is
* expected, but at least part of it was added to the case.
*/
String verificationError = dataSource.verifyImageSize();
if (!verificationError.isEmpty()) {
errorMessages.add(String.format("Non-critical error adding %s for device %s: %s", imageFilePaths, deviceId, verificationError));
}
long imageSize = dataSource.getSize();
int sequence = 0;
//start byte and end byte
long start = 0;
if (chunkSize > 0 && imageSize >= RawDSInputPanel.TWO_GB) {
for (double size = RawDSInputPanel.TWO_GB; size < dataSource.getSize(); size += RawDSInputPanel.TWO_GB) {
fileRanges.add(new TskFileRange(start, RawDSInputPanel.TWO_GB, sequence));
start += RawDSInputPanel.TWO_GB;
//TODO: remember the last piece
sequence++;
}
}
double leftoverSize = imageSize - sequence * RawDSInputPanel.TWO_GB;
fileRanges.add(new TskFileRange(start, (long)leftoverSize, sequence));
caseDatabase.addLayoutFiles(dataSource, fileRanges);
} catch (TskCoreException ex) {
errorMessages.add(String.format("Critical error adding %s for device %s: %s", imageFilePaths, deviceId, ex.getLocalizedMessage()));
criticalErrorOccurred = true;
} finally {
caseDatabase.releaseExclusiveLock();
}
}
/**
* Attempts to cancel the processing of the input image file. May result in
* partial processing of the input.
*/
public void cancelTask() {
logger.log(Level.WARNING, "AddMPFImageTask cancelled, processing may be incomplete");
cancelled = true;
}
}

View File

@ -0,0 +1,12 @@
# To change this license header, choose License Headers in Project Properties.
# To change this template file, choose Tools | Templates
# and open the template in the editor.
RawDSInputPanel.pathLabel.text=Browse for a raw image file:
RawDSInputPanel.errorLabel.text=Error Label
RawDSInputPanel.browseButton.text=Browse
RawDSInputPanel.pathTextField.text=
RawDSInputPanel.jBreakFileUpLabel.text=Break image up into:
RawDSInputPanel.jNoBreakupRadioButton.text=Do not break up
RawDSInputPanel.j2GBBreakupRadioButton.text=2GB chunks
RawDSInputPanel.timeZoneLabel.text=Please select the input timezone:

View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Component class="javax.swing.ButtonGroup" name="infileTypeButtonGroup">
</Component>
</NonVisualComponents>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="timeZoneLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="timeZoneComboBox" min="-2" pref="215" max="-2" attributes="0"/>
<EmptySpace min="0" pref="9" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="pathTextField" max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="browseButton" min="-2" pref="67" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="pathLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="16" max="-2" attributes="0"/>
<Component id="j2GBBreakupRadioButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jNoBreakupRadioButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jBreakFileUpLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="errorLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="pathLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="pathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace 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 max="-2" attributes="0"/>
<Component id="errorLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jBreakFileUpLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jNoBreakupRadioButton" min="-2" max="-2" attributes="0"/>
<Component id="j2GBBreakupRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="pathLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.pathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="pathTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.pathTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</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/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.browseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="j2GBBreakupRadioButton">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="infileTypeButtonGroup"/>
</Property>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.j2GBBreakupRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="j2GBBreakupRadioButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jBreakFileUpLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.jBreakFileUpLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JRadioButton" name="jNoBreakupRadioButton">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="infileTypeButtonGroup"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.jNoBreakupRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jNoBreakupRadioButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="errorLabel">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.errorLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</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/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</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="&lt;String&gt;"/>
</AuxValues>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,400 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 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.datasourceprocessors;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.util.Calendar;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PathValidator;
public class RawDSInputPanel extends JPanel implements DocumentListener {
public static final long TWO_GB = 2000000000L;
private static final long serialVersionUID = 1L; //default
private final String PROP_LASTINPUT_PATH = "LBL_LastInputFile_PATH";
private PropertyChangeSupport pcs = null;
private final JFileChooser fc = new JFileChooser();
// Externally supplied name is used to store settings
private final String contextName;
private double chunkSize;
/**
* Creates new form RawDSInputPanel
*/
private RawDSInputPanel(String context) {
initComponents();
errorLabel.setVisible(false);
fc.setDragEnabled(false);
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setMultiSelectionEnabled(false);
/*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);
}
}*/
//fc.setFileFilter(null);
this.contextName = context;
pcs = new PropertyChangeSupport(this);
createTimeZoneList();
}
/**
* Creates and returns an instance of a RawDSInputPanel.
*/
public static synchronized RawDSInputPanel createInstance(String context) {
RawDSInputPanel instance = new RawDSInputPanel(context);
instance.postInit();
return instance;
}
//post-constructor initialization to properly initialize listener support
//without leaking references of uninitialized objects
private void postInit() {
pathTextField.getDocument().addDocumentListener(this);
}
/**
* 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);
}
/**
* 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() {
infileTypeButtonGroup = new javax.swing.ButtonGroup();
pathLabel = new javax.swing.JLabel();
pathTextField = new javax.swing.JTextField();
browseButton = new javax.swing.JButton();
j2GBBreakupRadioButton = new javax.swing.JRadioButton();
jBreakFileUpLabel = new javax.swing.JLabel();
jNoBreakupRadioButton = new javax.swing.JRadioButton();
errorLabel = new javax.swing.JLabel();
timeZoneLabel = new javax.swing.JLabel();
timeZoneComboBox = new javax.swing.JComboBox<>();
org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.pathLabel.text")); // NOI18N
pathTextField.setText(org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.pathTextField.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.browseButton.text")); // NOI18N
browseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
browseButtonActionPerformed(evt);
}
});
infileTypeButtonGroup.add(j2GBBreakupRadioButton);
j2GBBreakupRadioButton.setSelected(true);
org.openide.awt.Mnemonics.setLocalizedText(j2GBBreakupRadioButton, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.j2GBBreakupRadioButton.text")); // NOI18N
j2GBBreakupRadioButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
j2GBBreakupRadioButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(jBreakFileUpLabel, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.jBreakFileUpLabel.text")); // NOI18N
infileTypeButtonGroup.add(jNoBreakupRadioButton);
org.openide.awt.Mnemonics.setLocalizedText(jNoBreakupRadioButton, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.jNoBreakupRadioButton.text")); // NOI18N
jNoBreakupRadioButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jNoBreakupRadioButtonActionPerformed(evt);
}
});
errorLabel.setForeground(new java.awt.Color(255, 0, 0));
org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.errorLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.timeZoneLabel.text")); // NOI18N
timeZoneComboBox.setMaximumRowCount(30);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(timeZoneLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 9, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(pathTextField)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(browseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pathLabel)
.addGroup(layout.createSequentialGroup()
.addGap(16, 16, 16)
.addComponent(j2GBBreakupRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jNoBreakupRadioButton))
.addComponent(jBreakFileUpLabel)
.addComponent(errorLabel))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(pathLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(browseButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.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.RELATED)
.addComponent(errorLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jBreakFileUpLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jNoBreakupRadioButton)
.addComponent(j2GBBreakupRadioButton))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
@SuppressWarnings("deprecation")
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
String oldText = pathTextField.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();
pathTextField.setText(path);
}
pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString(), false, true);
}//GEN-LAST:event_browseButtonActionPerformed
private void j2GBBreakupRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_j2GBBreakupRadioButtonActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_j2GBBreakupRadioButtonActionPerformed
private void jNoBreakupRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jNoBreakupRadioButtonActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_jNoBreakupRadioButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton browseButton;
private javax.swing.JLabel errorLabel;
private javax.swing.ButtonGroup infileTypeButtonGroup;
private javax.swing.JRadioButton j2GBBreakupRadioButton;
private javax.swing.JLabel jBreakFileUpLabel;
private javax.swing.JRadioButton jNoBreakupRadioButton;
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
*/
public String getImageFilePath() {
return pathTextField.getText();
}
public void reset() {
//reset the UI elements to default
pathTextField.setText(null);
j2GBBreakupRadioButton.setSelected(true);
}
public long getChunkSize() {
if (jNoBreakupRadioButton.isSelected()) {
return -1;
} else { //if have more choices here, the selection of each radiobutton should be checked
return TWO_GB;
}
}
public String getTimeZone() {
String tz = timeZoneComboBox.getSelectedItem().toString();
return tz.substring(tz.indexOf(")") + 2).trim();
}
/**
* Should we enable the next button of the wizard?
*
* @return true if a proper image has been selected, false otherwise
*/
public boolean validatePanel() {
errorLabel.setVisible(false);
String path = getImageFilePath();
if (path == null || path.isEmpty()) {
return false;
}
// display warning if there is one (but don't disable "next" button)
warnIfPathIsInvalid(path);
boolean isExist = new File(path).exists();
return (isExist);
}
/**
* Validates path to selected data source and displays warning if it is
* invalid.
*
* @param path Absolute path to the selected data source
*/
private void warnIfPathIsInvalid(String path) {
if (!PathValidator.isValid(path, Case.getCurrentCase().getCaseType())) {
errorLabel.setVisible(true);
errorLabel.setText("Path to multi-user data source is on \"C:\" drive");
}
}
public void storeSettings() {
String inFilePath = getImageFilePath();
if (null != inFilePath) {
String imagePath = inFilePath.substring(0, inFilePath.lastIndexOf(File.separator) + 1);
ModuleSettings.setConfigSetting(contextName, PROP_LASTINPUT_PATH, imagePath);
}
}
public void readSettings() {
String inFilePath = ModuleSettings.getConfigSetting(contextName, PROP_LASTINPUT_PATH);
if (null != inFilePath) {
if (!inFilePath.isEmpty()) {
pathTextField.setText(inFilePath);
}
}
}
/**
* Update functions are called by the pathTextField which has this set as
* it's DocumentEventListener. Each update function fires a property change
* to be caught by the parent panel.
*
* @param e the event, which is ignored
*/
@Override
public void insertUpdate(DocumentEvent e) {
pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
}
@Override
public void removeUpdate(DocumentEvent e) {
pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
}
@Override
public void changedUpdate(DocumentEvent e) {
pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
}
/**
* Set the focus to the pathTextField.
*/
public void select() {
pathTextField.requestFocusInWindow();
}
@Override
public synchronized void addPropertyChangeListener(PropertyChangeListener pcl) {
super.addPropertyChangeListener(pcl);
if (pcs == null) {
pcs = new PropertyChangeSupport(this);
}
pcs.addPropertyChangeListener(pcl);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener pcl) {
super.removePropertyChangeListener(pcl);
pcs.removePropertyChangeListener(pcl);
}
}

View File

@ -0,0 +1,156 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 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.datasourceprocessors;
import javax.swing.JPanel;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
/**
* A Raw data source processor that implements the DataSourceProcessor service
* provider interface to allow integration with the add data source wizard.
* It also provides a run method overload to allow it to be used independently
* of the wizard.
*/
@ServiceProvider(service = DataSourceProcessor.class)
public class RawDSProcessor implements DataSourceProcessor {
private static final String DATA_SOURCE_TYPE = "Raw Data Source";
private final RawDSInputPanel configPanel;
private AddRawImageTask addImageTask;
/*
* Constructs a Raw data source processor that implements the
* DataSourceProcessor service provider interface to allow integration
* with the add data source wizard. It also provides a run method
* overload to allow it to be used independently of the wizard.
*/
public RawDSProcessor() {
configPanel = RawDSInputPanel.createInstance(RawDSProcessor.class.getName());
}
/**
* Gets a string that describes the type of data sources this processor is
* able to add to the case database. The string is suitable for display in a
* type selection UI component (e.g., a combo box).
*
* @return A data source type display string for this data source processor.
*/
public static String getType() {
return DATA_SOURCE_TYPE;
}
/**
* Gets a string that describes the type of data sources this processor is
* able to add to the case database. The string is suitable for display in a
* type selection UI component (e.g., a combo box).
*
* @return A data source type display string for this data source processor.
*/
@Override
public String getDataSourceType() {
return DATA_SOURCE_TYPE;
}
/**
* Gets the panel that allows a user to select a data source and do any
* configuration required by the data source. The panel is less than 544
* pixels wide and less than 173 pixels high.
*
* @return A selection and configuration panel for this data source
* processor.
*/
@Override
public JPanel getPanel() {
configPanel.readSettings();
configPanel.select();
return configPanel;
}
/**
* Indicates whether the settings in the selection and configuration panel
* are valid and complete.
*
* @return True if the settings are valid and complete and the processor is
* ready to have its run method called, false otherwise.
*/
@Override
public boolean isPanelValid() {
return configPanel.validatePanel();
}
/**
* Adds a data source to the case database using a background task in a
* separate thread and the settings provided by the selection and
* configuration panel. Returns as soon as the background task is started.
* The background task uses a callback object to signal task completion and
* return results.
*
* This method should not be called unless isPanelValid returns true.
*
* @param progressMonitor Progress monitor that will be used by the
* background task to report progress.
* @param callback Callback that will be used by the background task
* to return results.
*/
@Override
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
configPanel.storeSettings();
run("0", configPanel.getImageFilePath(), configPanel.getTimeZone(), configPanel.getChunkSize(), progressMonitor, callback); //TODO: change hard coded deviceId
}
/**
* Adds a data source to the case database using a background task in a
* separate thread and the given settings instead of those provided by the
* selection and configuration panel. Returns as soon as the background task
* is started and uses the callback object to signal task completion and
* return results.
*
* @param deviceId An ASCII-printable identifier for the
* device associated with the data source
* that is intended to be unique across
* multiple cases (e.g., a UUID).
* @param rawDSInputFilePath Path to a Raw data source file.
* @param isHandsetFile Indicates whether the XML file is for a
* handset or a SIM.
* @param progressMonitor Progress monitor for reporting progress
* during processing.
*/
public void run(String deviceId, String imageFilePath, String timeZone, long chunkSize, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
addImageTask = new AddRawImageTask(deviceId, imageFilePath, timeZone, chunkSize, progressMonitor, callback);
new Thread(addImageTask).start();
}
@Override
public void cancel() {
}
/**
* Resets the selection and configuration panel for this data source
* processor.
*/
@Override
public void reset() {
configPanel.reset();
}
}