diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/AddCellebritePhysicalReportTask.java b/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/AddCellebritePhysicalReportTask.java deleted file mode 100644 index d624853fec..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/AddCellebritePhysicalReportTask.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015 Basis Technology Corp. - * Contact: carrier sleuthkit 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.experimental.cellex.datasourceprocessors; - -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.casemodule.services.FileManager; -import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; -import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult; -import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.Image; -import org.sleuthkit.datamodel.LocalFilesDataSource; -import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.SleuthkitJNI; -import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskDataException; - -/* - * A runnable that adds the image files from a Cellebrite UFED output folder to - * a case database. If SleuthKit fails to find a filesystem in any of input - * image files, the file is added to the case as a local/logical file instead. - */ -class AddCellebritePhysicalReportTask implements Runnable { - - private static final Logger logger = Logger.getLogger(AddCellebritePhysicalReportTask.class.getName()); - public static final String MODULE_NAME = "Cellebrite UFED Output Data Source Processor"; - public static final String TSK_FS_TYPE_UNKNOWN_ERR_MSG = "Cannot determine file system type"; - private final String deviceId; - private final List imageFilePaths; - private final String timeZone; - private final DataSourceProcessorProgressMonitor progressMonitor; - private final DataSourceProcessorCallback callback; - private final Case currentCase; - private boolean criticalErrorOccurred; - private volatile boolean cancelled; - - /** - * Constructs a runnable that adds the image files from a Cellebrite UFED - * output folder to a case database. If SleuthKit fails to find a filesystem - * in any of input image files, the file is added to the case as a - * local/logical file instead. - * - * @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 imageFilePaths The paths of the Cellebrite output files. - * @param timeZone The time zone to use when processing dates and - * times for the image, obtained from - * java.util.TimeZone.getID. - * @param progressMonitor Progress monitor for reporting progress during - * processing. - * @param callback Callback to call when processing is done. - */ - AddCellebritePhysicalReportTask(String deviceId, List imageFilePaths, String timeZone, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { - this.deviceId = deviceId; - this.imageFilePaths = imageFilePaths; - this.timeZone = timeZone; - this.callback = callback; - this.progressMonitor = progressMonitor; - currentCase = Case.getCurrentCase(); - } - - @Override - public void run() { - /* - * Try to add the input image files as images. - */ - List newDataSources = new ArrayList<>(); - List localFileDataSourcePaths = new ArrayList<>(); - List errorMessages = new ArrayList<>(); - currentCase.getSleuthkitCase().acquireExclusiveLock(); - try { - progressMonitor.setIndeterminate(true); - for (String imageFilePath : imageFilePaths) { - if (!cancelled) { - addImageToCase(imageFilePath, newDataSources, localFileDataSourcePaths, errorMessages); - } - } - } finally { - currentCase.getSleuthkitCase().releaseExclusiveLock(); - } - - /* - * Try to add any input image files that did not have file systems as a - * single local/logical files set with the device id as the root virtual - * directory name. - */ - if (!cancelled && localFileDataSourcePaths.size() > 0) { - FileManager fileManager = currentCase.getServices().getFileManager(); - FileManager.FileAddProgressUpdater progressUpdater = (final AbstractFile newFile) -> { - progressMonitor.setProgressText(String.format("Adding: %s as logical file", Paths.get(newFile.getParentPath(), newFile.getName()))); - }; - try { - LocalFilesDataSource localFilesDataSource = fileManager.addLocalFilesDataSource(deviceId, deviceId, timeZone, localFileDataSourcePaths, progressUpdater); - newDataSources.add(localFilesDataSource.getRootDirectory()); - } catch (TskCoreException | TskDataException ex) { - errorMessages.add(String.format("Error adding images without file systems for device %s: %s", deviceId, ex.getLocalizedMessage())); - criticalErrorOccurred = true; - } - } - - /* - * This appears to be the best that can be done to indicate completion - * with the DataSourceProcessorProgressMonitor in its current form. - */ - progressMonitor.setProgress(0); - progressMonitor.setProgress(100); - - /* - * Pass the results back via the callback. - */ - DataSourceProcessorResult result; - if (criticalErrorOccurred) { - result = DataSourceProcessorResult.CRITICAL_ERRORS; - } else if (!errorMessages.isEmpty()) { - result = DataSourceProcessorResult.NONCRITICAL_ERRORS; - } else { - result = DataSourceProcessorResult.NO_ERRORS; - } - callback.done(result, errorMessages, newDataSources); - criticalErrorOccurred = false; - } - - /** - * Attempts to cancel the processing of the input image files. May result in - * partial processing of the input. - */ - public void cancelTask() { - logger.log(Level.WARNING, "AddCellebriteAndroidImageTask cancelled, processing may be incomplete"); - cancelled = true; - } - - /** - * Attempts to add an input image to the case. - * - * @param imageFilePath The image file path. - * @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 localFileDataSourcePaths If the image cannot be added because - * SleuthKit cannot detect a filesystem, the - * image file path is added to this list for - * later addition as a part of a - * local/logical files data source. - * @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(String imageFilePath, List newDataSources, List localFileDataSourcePaths, List errorMessages) { - /* - * Try to add the image to the case database as a data source. - */ - progressMonitor.setProgressText(String.format("Adding: %s", imageFilePath)); - SleuthkitCase caseDatabase = currentCase.getSleuthkitCase(); - SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess = caseDatabase.makeAddImageProcess(timeZone, false, false); - Thread progressReporterThread = new Thread(new AddImageProgressReportingTask(progressMonitor, addImageProcess)); - try { - progressReporterThread.start(); - addImageProcess.run(deviceId, new String[]{imageFilePath}); - } catch (TskCoreException ex) { - if (ex.getMessage().contains(TSK_FS_TYPE_UNKNOWN_ERR_MSG)) { - /* - * If SleuthKit failed to add the image because it did not find - * a file system, save the image path so it can be added to the - * case as part of a local/logical files data source. All other - * errors are critical. - */ - localFileDataSourcePaths.add(imageFilePath); - } else { - errorMessages.add(String.format("Critical error adding %s for %s:", imageFilePath, deviceId, ex.getLocalizedMessage())); - criticalErrorOccurred = true; - } - /* - * Either way, the add image process needs to be reverted. - */ - try { - addImageProcess.revert(); - } catch (TskCoreException e) { - errorMessages.add(String.format("Critical error reverting add image process for %s for %s: %s", imageFilePath, deviceId, e.getLocalizedMessage())); - criticalErrorOccurred = true; - } - return; - } catch (TskDataException ex) { - errorMessages.add(String.format("Non-critical error adding %s for %s: %s", imageFilePath, deviceId, ex.getLocalizedMessage())); - } finally { - progressReporterThread.interrupt(); - } - - /* - * Try to commit the results of the add image process, retrieve the new - * image from the case database, and add it to the list of new data - * sources to be returned via the callback. - */ - try { - long imageId = addImageProcess.commit(); - Image dataSource = caseDatabase.getImageById(imageId); - newDataSources.add(dataSource); - - /* - * 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", imageFilePath, deviceId, verificationError)); - } - } catch (TskCoreException ex) { - /* - * The add image process commit failed or querying the case database - * for the newly added image failed. Either way, this is a critical - * error. - */ - errorMessages.add(String.format("Critical error adding %s for device %s: %s", imageFilePath, deviceId, ex.getLocalizedMessage())); - criticalErrorOccurred = true; - } - } - -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/AddImageProgressReportingTask.java b/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/AddImageProgressReportingTask.java deleted file mode 100644 index 78de63b6d0..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/AddImageProgressReportingTask.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015 Basis Technology Corp. - * Contact: carrier sleuthkit 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.experimental.cellex.datasourceprocessors; - -import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; -import org.sleuthkit.datamodel.SleuthkitJNI; - -/* - * A Runnable that updates a data source processor progress monitor with the - * name of the directory currently being processed by a SleuthKit add image - * process. - * - * TODO (JIRA-1578): The sleep code in the run method should be removed. Clients - * should use a java.util.concurrent.ScheduledThreadPoolExecutor instead to be - * able to control update frequency and cancellation. - */ -class AddImageProgressReportingTask implements Runnable { - - DataSourceProcessorProgressMonitor progressMonitor; - SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess; - - /** - * Constructs a Runnable that updates a data source processor progress - * monitor with the name of the directory currently being processed by a - * SleuthKit add image process. - * - * @param progressMonitor The progress monitor. - * @param addImageProcess An Sleuth add image process. - */ - AddImageProgressReportingTask(DataSourceProcessorProgressMonitor progressMonitor, SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess) { - this.progressMonitor = progressMonitor; - this.addImageProcess = addImageProcess; - } - - /** - * Every two seconds, updates the progress monitor with the name of the - * directory currently being processed by the add image process. - */ - @Override - public void run() { - try { - while (!Thread.currentThread().isInterrupted()) { - String currDir = addImageProcess.currentDirectory(); - if (null != currDir && !currDir.isEmpty()) { - progressMonitor.setProgressText("Adding: " + currDir); - } - /* - * TODO (JIRA-1578): The sleep should be removed here. Clients - * should use a java.util.concurrent.ScheduledThreadPoolExecutor - * instead to be able to control update frequency and - * cancellation, - */ - Thread.sleep(2 * 1000); - } - } catch (InterruptedException expected) { - } - } -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/Bundle.properties deleted file mode 100644 index 195ddf9ec6..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/Bundle.properties +++ /dev/null @@ -1,28 +0,0 @@ -OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=\ - Extracts application information, lists potentially suspicious databases and SD card folders, and parses known SQLite databases. -OpenIDE-Module-Name=Android Triage -MPFModuleSimplePanel.jSizeLabel.text=Min Size (MB): -MPFModuleSimplePanel.jImgExtCheckBox.text=.img -MPFModuleSimplePanel.jNoExtCheckBox.text=\ No extension -MPFModuleSimplePanel.jBinExtCheckBox.text=.bin -MPFModuleSimplePanel.jMinSizeSpinner.toolTipText=Minimum size of file to be processed by MPF. -MPFModuleSimplePanel.jAllFilesRadioButton.text=Yes (will take longer) -MPFModuleSimplePanel.jFilterFilesRadioButton.text=No -MPFModuleSimplePanel.jLabel2.text=File Extensions: -MPFModuleSimplePanel.jLabel3.text=Process files that meet the following criteria: -MPFModuleSimplePanel.jLabel4.text=Run on all files in set of logical files? -OpenIDE-Module-Short-Description=Does triage of Android data. -CellebritePhysicalReportInputPanel.errorLabel.text=Error Label -CellebritePhysicalReportInputPanel.timeZoneLabel.text=Please select the input timezone: -CellebritePhysicalReportInputPanel.browseButton.text=Browse -CellebritePhysicalReportInputPanel.pathTextField.text= -CellebritePhysicalReportInputPanel.pathLabel.text=Browse for a Android phone image folder: -CellebriteLogicalReportPanel.pathLabel.text=Browse for a Cellebrite XML file: -CellebriteLogicalReportPanel.errorLabel.text=Error Label -CellebriteLogicalReportPanel.jSIMRadioButton.text=SIM -CellebriteLogicalReportPanel.jLabel1.text=Input type: -CellebriteLogicalReportPanel.jHandsetRadioButton.text=Handset -CellebriteLogicalReportPanel.browseButton.text=Browse -CellebriteLogicalReportPanel.pathTextField.text= -CellebritePhysicalReportProcessor.process.exception.text=Exception while trying to extract archive diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/CellebritePhysicalReportInputPanel.form b/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/CellebritePhysicalReportInputPanel.form deleted file mode 100644 index e2836d7a67..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/CellebritePhysicalReportInputPanel.form +++ /dev/null @@ -1,115 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/CellebritePhysicalReportInputPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/CellebritePhysicalReportInputPanel.java deleted file mode 100644 index a664135dca..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/CellebritePhysicalReportInputPanel.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015 Basis Technology Corp. - * Contact: carrier sleuthkit 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.experimental.cellex.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 CellebritePhysicalReportInputPanel extends JPanel implements DocumentListener { - - private static final long serialVersionUID = 1L; - - 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 CellebriteAndroidInputPanel - */ - public CellebritePhysicalReportInputPanel(String context) { - initComponents(); - - errorLabel.setVisible(false); - - fc.setDragEnabled(false); - fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - fc.setMultiSelectionEnabled(false); - - this.contextName = context; - pcs = new PropertyChangeSupport(this); - - createTimeZoneList(); - } - - /** - * Creates and returns an instance of a ImageFilePanel. - */ - public static synchronized CellebritePhysicalReportInputPanel createInstance(String context) { - CellebritePhysicalReportInputPanel instance = new CellebritePhysicalReportInputPanel(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); - } - - /** - * Get the path of the user selected folder. - * - * @return the image path - */ - public String getContentPaths() { - return pathTextField.getText(); - } - - /** - * Set the path of the images folder. - */ - public void setContentPath(String s) { - pathTextField.setText(s); - } - - public String getTimeZone() { - String tz = timeZoneComboBox.getSelectedItem().toString(); - return tz.substring(tz.indexOf(")") + 2).trim(); - } - - /** - * 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") - // //GEN-BEGIN:initComponents - private void initComponents() { - - pathLabel = new javax.swing.JLabel(); - pathTextField = new javax.swing.JTextField(); - browseButton = new javax.swing.JButton(); - timeZoneLabel = new javax.swing.JLabel(); - timeZoneComboBox = new javax.swing.JComboBox<>(); - errorLabel = new javax.swing.JLabel(); - - org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(CellebritePhysicalReportInputPanel.class, "CellebritePhysicalReportInputPanel.pathLabel.text")); // NOI18N - - pathTextField.setText(org.openide.util.NbBundle.getMessage(CellebritePhysicalReportInputPanel.class, "CellebritePhysicalReportInputPanel.pathTextField.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(CellebritePhysicalReportInputPanel.class, "CellebritePhysicalReportInputPanel.browseButton.text")); // NOI18N - browseButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - browseButtonActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(CellebritePhysicalReportInputPanel.class, "CellebritePhysicalReportInputPanel.timeZoneLabel.text")); // NOI18N - - timeZoneComboBox.setMaximumRowCount(30); - - errorLabel.setForeground(new java.awt.Color(255, 0, 0)); - org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(CellebritePhysicalReportInputPanel.class, "CellebritePhysicalReportInputPanel.errorLabel.text")); // NOI18N - - 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) - .addComponent(pathLabel) - .addGroup(layout.createSequentialGroup() - .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 286, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(browseButton)) - .addGroup(layout.createSequentialGroup() - .addComponent(timeZoneLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(errorLabel)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - 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)) - .addGap(8, 8, 8) - .addComponent(errorLabel) - .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)) - .addContainerGap(198, Short.MAX_VALUE)) - ); - }// //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 - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton browseButton; - private javax.swing.JLabel errorLabel; - private javax.swing.JLabel pathLabel; - private javax.swing.JTextField pathTextField; - private javax.swing.JComboBox timeZoneComboBox; - private javax.swing.JLabel timeZoneLabel; - // End of variables declaration//GEN-END:variables - - /** - * 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); - } - - /** - * 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 = getContentPaths(); - if (path == null || path.isEmpty()) { - return false; - } - - // display warning if there is one (but don't disable "next" button) - warnIfPathIsInvalid(path); - - // check if a folder exists by this name. - File f = new File(path); - boolean isValid = (f.exists() && f.isDirectory()); - - return isValid; - } - - /** - * 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 reset() { - //reset the UI elements to default - pathTextField.setText(null); - } - - /* - * Store the last used settings - */ - 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); - } - } - - /* - * Read and load the last used settings - */ - public void readSettings() { - String lastImagePath = ModuleSettings.getConfigSetting(contextName, PROP_LASTIMAGE_PATH); - if (null != lastImagePath) { - if (!lastImagePath.isEmpty()) { - pathTextField.setText(lastImagePath); - } - } - } - -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/CellebritePhysicalReportProcessor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/CellebritePhysicalReportProcessor.java deleted file mode 100644 index eb0c297fc8..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/CellebritePhysicalReportProcessor.java +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015 Basis Technology Corp. - * Contact: carrier sleuthkit 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.experimental.cellex.datasourceprocessors; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import org.sleuthkit.autopsy.corecomponentinterfaces.AutomatedIngestDataSourceProcessor; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; -import java.util.UUID; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import javax.swing.JPanel; -import javax.swing.filechooser.FileFilter; -import org.apache.commons.io.FilenameUtils; -import org.openide.util.NbBundle; -import org.openide.util.lookup.ServiceProvider; -import org.openide.util.lookup.ServiceProviders; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.GeneralFilter; -import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; -import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; -import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; -import org.sleuthkit.autopsy.coreutils.TimeStampUtils; - -/** - * An Cellebrite UFED output folder 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. - */ -@ServiceProviders(value={ - @ServiceProvider(service=DataSourceProcessor.class), - @ServiceProvider(service=AutomatedIngestDataSourceProcessor.class)} -) -public class CellebritePhysicalReportProcessor implements AutomatedIngestDataSourceProcessor { - - private static final String DATA_SOURCE_TYPE = "Cellebrite Physical Report"; - private final CellebritePhysicalReportInputPanel configPanel; - private AddCellebritePhysicalReportTask addImagesTask; - - private static final List CELLEBRITE_EXTS = Arrays.asList(new String[]{".bin"}); - private static final String CELLEBRITE_DESC = "Cellebrite Physical Files (*.bin)"; - private static final GeneralFilter binFileFilter = new GeneralFilter(CELLEBRITE_EXTS, CELLEBRITE_DESC); - private static final List filtersList = new ArrayList<>(); - static { - filtersList.add(binFileFilter); - } - - private static final GeneralFilter zipFilter = new GeneralFilter(Arrays.asList(new String[]{".zip"}), ""); - private static final List archiveFilters = new ArrayList<>(); - static { - archiveFilters.add(zipFilter); - } - - private static final String AUTO_INGEST_MODULE_OUTPUT_DIR = "AutoIngest"; - - /** - * Constructs a Cellebrite UFED output folder 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 CellebritePhysicalReportProcessor() { - configPanel = CellebritePhysicalReportInputPanel.createInstance(CellebritePhysicalReportProcessor.class.getName()); - } - -/** - * Gets the file extensions supported by this data source processor as a - * list of file filters. - * - * @return List List of FileFilter objects - */ - public static final List getFileFilterList() { - return filtersList; - } - - /** - * 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(UUID.randomUUID().toString(), configPanel.getContentPaths(), configPanel.getTimeZone(), progressMonitor, callback); - } - - /** - * 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. - * - * 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. - */ - public void run(String deviceId, String imageFolderPath, String timeZone, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { - List imageFilePaths = getImageFilePaths(imageFolderPath); - addImagesTask = new AddCellebritePhysicalReportTask(deviceId, imageFilePaths, timeZone, progressMonitor, callback); - new Thread(addImagesTask).start(); - } - - /** - * Requests cancellation of the background task that adds a data source to - * the case database, after the task is started using the run method. This - * is a "best effort" cancellation, with no guarantees that the case - * database will be unchanged. If cancellation succeeded, the list of new - * data sources returned by the background task will be empty. - */ - @Override - public void cancel() { - if (null != addImagesTask) { - addImagesTask.cancelTask(); - } - } - - /** - * Resets the selection and configuration panel for this data source - * processor. - */ - @Override - public void reset() { - configPanel.reset(); - } - - /** - * Gets the paths of the image files in a Cellebrite UFED output folder. - * - * @param folderPath The path to a Cellebrite UFED output folder - * - * @return A list of image file paths. - */ - private static List getImageFilePaths(String folderPath) { - List imageFilePaths = new ArrayList<>(); - File folder = new File(folderPath); - File[] listOfFiles = folder.listFiles(); - for (File file : listOfFiles) { - if (file.isFile() && isValidDataSource(file.toPath())){ - Path filePathName = Paths.get(folderPath, file.getName()); - imageFilePaths.add(filePathName.toString()); - } - } - return imageFilePaths; - } - - /** - * Extracts the contents of a ZIP archive submitted as a data source to a - * subdirectory of the auto ingest module output directory. - * - * @throws IOException if there is a problem extracting the data source from - * the archive. - */ - private static Path extractDataSource(Path outputDirectoryPath, Path dataSourcePath) throws IOException { - String dataSourceFileNameNoExt = FilenameUtils.removeExtension(dataSourcePath.getFileName().toString()); - Path destinationFolder = Paths.get(outputDirectoryPath.toString(), - AUTO_INGEST_MODULE_OUTPUT_DIR, - dataSourceFileNameNoExt + "_" + TimeStampUtils.createTimeStamp()); - Files.createDirectories(destinationFolder); - - int BUFFER_SIZE = 524288; // Read/write 500KB at a time - File sourceZipFile = dataSourcePath.toFile(); - ZipFile zipFile; - zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ); - Enumeration zipFileEntries = zipFile.entries(); - try { - while (zipFileEntries.hasMoreElements()) { - ZipEntry entry = zipFileEntries.nextElement(); - String currentEntry = entry.getName(); - File destFile = new File(destinationFolder.toString(), currentEntry); - destFile = new File(destinationFolder.toString(), destFile.getName()); - File destinationParent = destFile.getParentFile(); - destinationParent.mkdirs(); - if (!entry.isDirectory()) { - BufferedInputStream is = new BufferedInputStream(zipFile.getInputStream(entry)); - int currentByte; - byte data[] = new byte[BUFFER_SIZE]; - try (FileOutputStream fos = new FileOutputStream(destFile); BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) { - currentByte = is.read(data, 0, BUFFER_SIZE); - while (currentByte != -1) { - dest.write(data, 0, currentByte); - currentByte = is.read(data, 0, BUFFER_SIZE); - } - } - } - } - } finally { - zipFile.close(); - } - return destinationFolder; - } - - private static boolean isValidDataSource(Path dataSourcePath) { - - String fileName = dataSourcePath.getFileName().toString(); - // is it a ".bin" image - if (!isAcceptedByFiler(new File(fileName), filtersList)) { - return false; - } - - // this needs to identify and handle different Cellebrite scenarios: - // i single image in a single file - // ii. Single image split over multiple files - just need to pass the first to TSK and it will combine the split image files. - // Note there may be more than than one split images in a single dir, - // e.g. blk0_mmcblk0.bin, blk0_mmcblk0(1).bin......, and blk24_mmcblk1.bin, blk24_mmcblk1(1).bin...... - //iii. Multiple image files - one per volume - need to handle each one separately - // e.g. blk0_mmcblk0.bin, mtd0_system.bin, mtd1_cache.bin, mtd2_userdata.bin - String fNameNoExt = FilenameUtils.removeExtension(fileName); - return (! fNameNoExt.toLowerCase().matches("\\w+\\(\\d+\\)")); - } - - private static boolean isAcceptedByFiler(File file, List filters) { - for (FileFilter filter : filters) { - if (filter.accept(file)) { - return true; - } - } - return false; - } - - private static boolean isArchive(Path dataSourcePath) throws AutomatedIngestDataSourceProcessorException { - String fileName = dataSourcePath.getFileName().toString(); - // check whether it's a zip archive file that can be extracted - if (isAcceptedByFiler(new File(fileName), archiveFilters)) { - return true; - } - return false; - } - - @Override - public int canProcess(Path dataSourcePath) throws AutomatedIngestDataSourceProcessorException { - // check whether this is an archive or a ".bin" file - if (isArchive(dataSourcePath) || isValidDataSource(dataSourcePath)) { - // return "high confidence" value - return 90; - } - return 0; - } - - @Override - public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) throws AutomatedIngestDataSourceProcessorException { - - List dataSourcePathList = Collections.emptyList(); - if (isArchive(dataSourcePath)) { - // extract the archive and pass the extracted folder as input - Path extractedDataSourcePath = Paths.get(""); - try { - Case currentCase = Case.getCurrentCase(); - extractedDataSourcePath = extractDataSource(Paths.get(currentCase.getModuleDirectory()), dataSourcePath); - } catch (Exception ex) { - throw new AutomatedIngestDataSourceProcessorException(NbBundle.getMessage(CellebritePhysicalReportProcessor.class, "CellebritePhysicalReportProcessor.process.exception.text"), ex); - } - run(deviceId, extractedDataSourcePath.toString(), "", progressMonitor, callBack); - } else if (isValidDataSource(dataSourcePath)) { - // pass the single ".bin" file as input - dataSourcePathList = Arrays.asList(new String[]{dataSourcePath.toString()}); - // in this particular case we don't want to call run() method as it will try to identify and process all ".bin" files in data source folder - addImagesTask = new AddCellebritePhysicalReportTask(deviceId, dataSourcePathList, "", progressMonitor, callBack); - new Thread(addImagesTask).start(); - } - } -} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/Util.java b/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/Util.java deleted file mode 100644 index fe550b291a..0000000000 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/cellex/datasourceprocessors/Util.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015 Basis Technology Corp. - * Contact: carrier sleuthkit 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.experimental.cellex.datasourceprocessors; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import static java.lang.Math.min; -import java.util.Collection; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * - * @author flynn - */ -public class Util { - - public interface Mapper { - - public T2 apply(T1 x); - } - - public static void copyToFile(AbstractFile inputFile, String destPath) - throws IOException, TskCoreException { - long inputSize = inputFile.getSize(); - long bufSize = min(inputSize, 65536L); - - byte[] buffer = new byte[(int) bufSize]; - - FileOutputStream output = new FileOutputStream(destPath); - - long offset = 0; - long bytesLeft = inputSize; - - try { - while (bytesLeft > 0) { - int bytesRead = inputFile.read(buffer, offset, bufSize); - - if (bytesRead < 0) { - throw new IOException("I/O error (rc " + bytesRead + ")"); - } - - output.write(buffer); - - bytesLeft -= bytesRead; - offset += bytesRead; - } - } finally { - // Always always always close output, no matter what. - output.close(); - } - } - - public static String getBasename(String path) { - String baseName = path; - int lastSlash = baseName.lastIndexOf(File.separator); - - if (lastSlash >= 0) { - baseName = baseName.substring(lastSlash + 1); - } - - return baseName; - } - - public static String stripExtension(String path) { - String noExt = path; - - int lastPeriod = path.lastIndexOf('.'); - - if (lastPeriod > 0) { // Not >=, >. A single "." should be preserved. - noExt = path.substring(0, lastPeriod); - } - - return noExt; - } - - public static String joinPath(String... elements) { - return join(File.separator, elements); - } - - public static String join(String delim, Mapper mapFunc, - String... elements) { - String joined = ""; - - for (String element : elements) { - if (mapFunc != null) { - element = mapFunc.apply(element); - } - - if ((element != null) && (element.length() > 0)) { - if (joined.length() > 0) { - joined += delim; - } - - joined += element; - } - } - - return joined; - } - - public static String join(String delim, Mapper mapFunc, - Collection elements) { - return join(delim, mapFunc, - elements.toArray(new String[elements.size()])); - } - - public static String join(String delim, String... elements) { - return join(delim, null, elements); - } - - public static String join(String delim, Collection elements) { - return join(delim, null, elements); - } -}