diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index cdf46e4d8c..85dd7443ae 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -138,15 +138,8 @@ IntervalErrorReport.TotalIssues=total issue(s) IntervalErrorReport.ErrorText=Database Connection Error CasePropertiesAction.window.title=Case Properties CueBannerPanel.title.text=Open Recent Case -GeneralFilter.rawImageDesc.text=Raw Images (*.img, *.dd, *.001, *.aa, *.raw, *.bin) -GeneralFilter.encaseImageDesc.text=Encase Images (*.e01) -GeneralFilter.virtualMachineImageDesc.text=Virtual Machines (*.vmdk, *.vhd) -GeneralFilter.executableDesc.text=Executables (*.exe) ImageDSProcessor.dsType.text=Disk Image or VM File -GeneralFilter.graphicImageDesc.text=Images (*.png, *.jpg, *.jpeg, *.gif, *.bmp) ImageDSProcessor.allDesc.text=All Supported Types -ImageFilePanel.moduleErr=Module Error -ImageFilePanel.moduleErr.msg=A module caused an error listening to ImageFilePanel updates. See log to determine which module. Some data could be incomplete. LocalDiskDSProcessor.dsType.text=Local Disk LocalDiskPanel.localDiskModel.loading.msg=Loading local disks... LocalDiskPanel.localDiskModel.nodrives.msg=No Accessible Drives @@ -197,7 +190,6 @@ UpdateRecentCases.menuItem.clearRecentCases.text=Clear Recent Cases UpdateRecentCases.menuItem.empty=-Empty- AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=Cancel ImageFilePanel.errorLabel.text=Error Label -DataSourceOnCDriveError.text=Warning\: Path to multi-user data source is on "C\:" drive NewCaseVisualPanel1.CaseFolderOnCDriveError.text=Warning: Path to multi-user case folder is on \"C:\" drive LocalFilesPanel.errorLabel.text=Error Label CollaborationMonitor.addingDataSourceStatus.msg={0} adding data source diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java b/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java index f848722953..7d06ae23c3 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,12 +18,11 @@ */ package org.sleuthkit.autopsy.casemodule; -import org.openide.util.NbBundle; - import java.io.File; -import java.util.List; import java.util.Arrays; +import java.util.List; import javax.swing.filechooser.FileFilter; +import org.openide.util.NbBundle; /** * FileFilter helper class. Matches files based on extension @@ -31,25 +30,28 @@ import javax.swing.filechooser.FileFilter; public class GeneralFilter extends FileFilter { // Extensions & Descriptions for commonly used filters - public static final List RAW_IMAGE_EXTS = Arrays.asList(new String[]{".img", ".dd", ".001", ".aa", ".raw", ".bin"}); //NON-NLS - public static final String RAW_IMAGE_DESC = NbBundle.getMessage(GeneralFilter.class, "GeneralFilter.rawImageDesc.text"); + public static final List RAW_IMAGE_EXTS = Arrays.asList(".img", ".dd", ".001", ".aa", ".raw", ".bin"); //NON-NLS + @NbBundle.Messages("GeneralFilter.rawImageDesc.text=Raw Images (*.img, *.dd, *.001, *.aa, *.raw, *.bin)") + public static final String RAW_IMAGE_DESC = Bundle.GeneralFilter_rawImageDesc_text(); - public static final List ENCASE_IMAGE_EXTS = Arrays.asList(new String[]{".e01"}); //NON-NLS - public static final String ENCASE_IMAGE_DESC = NbBundle.getMessage(GeneralFilter.class, - "GeneralFilter.encaseImageDesc.text"); + public static final List ENCASE_IMAGE_EXTS = Arrays.asList(".e01"); //NON-NLS + @NbBundle.Messages("GeneralFilter.encaseImageDesc.text=Encase Images (*.e01)") + public static final String ENCASE_IMAGE_DESC = Bundle.GeneralFilter_encaseImageDesc_text(); - public static final List VIRTUAL_MACHINE_EXTS = Arrays.asList(new String[]{".vmdk", ".vhd"}); //NON-NLS - public static final String VIRTUAL_MACHINE_DESC = NbBundle.getMessage(GeneralFilter.class, - "GeneralFilter.virtualMachineImageDesc.text"); + public static final List VIRTUAL_MACHINE_EXTS = Arrays.asList(".vmdk", ".vhd"); //NON-NLS + @NbBundle.Messages("GeneralFilter.virtualMachineImageDesc.text=Virtual Machines (*.vmdk, *.vhd)") + public static final String VIRTUAL_MACHINE_DESC = Bundle.GeneralFilter_virtualMachineImageDesc_text(); - public static final List EXECUTABLE_EXTS = Arrays.asList(new String[]{".exe"}); //NON-NLS - public static final String EXECUTABLE_DESC = NbBundle.getMessage(GeneralFilter.class, "GeneralFilter.executableDesc.text"); + public static final List EXECUTABLE_EXTS = Arrays.asList(".exe"); //NON-NLS + @NbBundle.Messages("GeneralFilter.executableDesc.text=Executables (*.exe)") + public static final String EXECUTABLE_DESC = Bundle.GeneralFilter_executableDesc_text(); - public static final List GRAPHIC_IMAGE_EXTS = Arrays.asList(new String[]{".png", ".jpeg", ".jpg", ".gif", ".bmp"}); //NON-NLS - public static final String GRAPHIC_IMG_DECR = NbBundle.getMessage(GeneralFilter.class, "GeneralFilter.graphicImageDesc.text"); + public static final List GRAPHIC_IMAGE_EXTS = Arrays.asList(".png", ".jpeg", ".jpg", ".gif", ".bmp"); //NON-NLS + @NbBundle.Messages("GeneralFilter.graphicImageDesc.text=Images (*.png, *.jpg, *.jpeg, *.gif, *.bmp)") + public static final String GRAPHIC_IMG_DECR = Bundle.GeneralFilter_graphicImageDesc_text(); - private List extensions; - private String desc; + private final List extensions; + private final String desc; public GeneralFilter(List ext, String desc) { super(); @@ -69,15 +71,8 @@ public class GeneralFilter extends FileFilter { if (f.isDirectory()) { return true; } else { - Boolean result = false; String name = f.getName().toLowerCase(); - - for (String ext : extensions) { - if (name.endsWith(ext)) { - result = result || true; - } - } - return result; + return extensions.stream().anyMatch(name::endsWith); } } @@ -90,5 +85,4 @@ public class GeneralFilter extends FileFilter { public String getDescription() { return desc; } - } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index 4373959707..0fe51144eb 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2016 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,88 +23,91 @@ import java.util.Calendar; import java.util.List; import java.util.SimpleTimeZone; import java.util.TimeZone; +import java.util.logging.Level; import javax.swing.JFileChooser; +import javax.swing.JPanel; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -import javax.swing.JPanel; import javax.swing.filechooser.FileFilter; - +import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle; +import static org.sleuthkit.autopsy.casemodule.Bundle.*; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; -import org.sleuthkit.autopsy.coreutils.ModuleSettings; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.DriveUtils; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.PathValidator; /** - * ImageTypePanel for adding an image file such as .img, .E0x, .00x, etc. + * Panel for adding an image file such as .img, .E0x, .00x, etc. Allows the user + * to select a file as well as choose the timezone and whether to ignore orphan + * files in FAT32. */ public class ImageFilePanel extends JPanel implements DocumentListener { - private final String PROP_LASTIMAGE_PATH = "LBL_LastImage_PATH"; //NON-NLS private static final Logger logger = Logger.getLogger(ImageFilePanel.class.getName()); - private final JFileChooser fc = new JFileChooser(); + private static final String PROP_LASTIMAGE_PATH = "LBL_LastImage_PATH"; //NON-NLS - // Externally supplied name is used to store settings + private final JFileChooser fileChooser = new JFileChooser(); + + /** + * Externally supplied name is used to store settings + */ private final 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 + * @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. */ private ImageFilePanel(String context, List fileChooserFilters) { + this.contextName = context; initComponents(); - fc.setDragEnabled(false); - fc.setFileSelectionMode(JFileChooser.FILES_ONLY); - fc.setMultiSelectionEnabled(false); + + // Populate the drop down list of time zones + for (String id : SimpleTimeZone.getAvailableIDs()) { + timeZoneComboBox.addItem(timeZoneToString(TimeZone.getTimeZone(id))); + } + // set the selected timezone to the current timezone + timeZoneComboBox.setSelectedItem(timeZoneToString(Calendar.getInstance().getTimeZone())); errorLabel.setVisible(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); - } + fileChooser.setDragEnabled(false); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooser.setMultiSelectionEnabled(false); + fileChooserFilters.forEach(fileChooser::addChoosableFileFilter); + if (fileChooserFilters.isEmpty() == false) { + fileChooser.setFileFilter(fileChooserFilters.get(0)); } - - this.contextName = context; - } /** * Creates and returns an instance of a 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. + * * @return instance of the ImageFilePanel */ public static synchronized ImageFilePanel createInstance(String context, List fileChooserFilters) { - ImageFilePanel instance = new ImageFilePanel(context, fileChooserFilters); - instance.postInit(); - instance.createTimeZoneList(); - + // post-constructor initialization of listener support without leaking references of uninitialized objects + instance.pathTextField.getDocument().addDocumentListener(instance); return instance; } - //post-constructor initialization to properly initialize listener support - //without leaking references of uninitialized objects - private void postInit() { - pathTextField.getDocument().addDocumentListener(this); - } - /** * 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() { @@ -187,29 +190,20 @@ public class ImageFilePanel extends JPanel implements DocumentListener { .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// //GEN-END:initComponents - @SuppressWarnings("deprecation") + private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed - String oldText = pathTextField.getText(); + String oldText = getContentPaths(); // set the current directory of the FileChooser if the ImagePath Field is valid File currentDir = new File(oldText); if (currentDir.exists()) { - fc.setCurrentDirectory(currentDir); + fileChooser.setCurrentDirectory(currentDir); } - int retval = fc.showOpenDialog(this); - if (retval == JFileChooser.APPROVE_OPTION) { - String path = fc.getSelectedFile().getPath(); - pathTextField.setText(path); + if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + setContentPath(fileChooser.getSelectedFile().getPath()); } - try { - firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString(), false, true); - } catch (Exception e) { - logger.log(Level.SEVERE, "ImageFilePanel listener threw exception", e); //NON-NLS - MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "ImageFilePanel.moduleErr"), - NbBundle.getMessage(this.getClass(), "ImageFilePanel.moduleErr.msg"), - MessageNotifyUtil.MessageType.ERROR); - } + updateHelper(); }//GEN-LAST:event_browseButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables @@ -234,6 +228,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { /** * Set the path of the image file. + * * @param s path of the image file */ public void setContentPath(String s) { @@ -242,7 +237,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { public String getTimeZone() { String tz = timeZoneComboBox.getSelectedItem().toString(); - return tz.substring(tz.indexOf(")") + 2).trim(); + return tz.substring(tz.indexOf(')') + 2).trim(); } public boolean getNoFatOrphans() { @@ -259,34 +254,23 @@ public class ImageFilePanel extends JPanel implements DocumentListener { * * @return true if a proper image has been selected, false otherwise */ + @NbBundle.Messages("DataSourceOnCDriveError.text=Warning: Path to multi-user data source is on \"C:\" drive") public boolean validatePanel() { errorLabel.setVisible(false); String path = getContentPaths(); - if (path == null || path.isEmpty()) { + if (StringUtils.isBlank(path)) { return false; } // display warning if there is one (but don't disable "next" button) - warnIfPathIsInvalid(path); - - boolean isExist = new File(path).isFile(); - boolean isPhysicalDrive = DriveUtils.isPhysicalDrive(path); - boolean isPartition = DriveUtils.isPartition(path); - - return (isExist || isPhysicalDrive || isPartition); - } - - /** - * 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())) { + if (false == PathValidator.isValid(path, Case.getCurrentCase().getCaseType())) { errorLabel.setVisible(true); - errorLabel.setText(NbBundle.getMessage(this.getClass(), "DataSourceOnCDriveError.text")); + errorLabel.setText(Bundle.DataSourceOnCDriveError_text()); } + + return new File(path).isFile() + || DriveUtils.isPhysicalDrive(path) + || DriveUtils.isPartition(path); } public void storeSettings() { @@ -299,47 +283,39 @@ public class ImageFilePanel extends JPanel implements DocumentListener { public void readSettings() { String lastImagePath = ModuleSettings.getConfigSetting(contextName, PROP_LASTIMAGE_PATH); - if (null != lastImagePath) { - if (!lastImagePath.isEmpty()) { - pathTextField.setText(lastImagePath); - } + if (StringUtils.isNotBlank(lastImagePath)) { + setContentPath(lastImagePath); } } /** - * Creates the drop down list for the time zones and then makes the local - * machine time zone to be selected. + * Get a string representation of a TimeZone for use in the drop down list. + * + * @param zone The TimeZone to make a string for + * + * @return A string representation of a TimeZone for use in the drop down + * list. */ - 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); //NON-NLS + static private String timeZoneToString(TimeZone zone) { + int offset = zone.getRawOffset() / 1000; + int hour = offset / 3600; + int minutes = (offset % 3600) / 60; + return String.format("(GMT%+d:%02d) %s", hour, minutes, zone.getID()); //NON-NLS + } - /* - * 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()); //NON-NLS + @Override + public void insertUpdate(DocumentEvent e) { + updateHelper(); + } - // set the selected timezone - timeZoneComboBox.setSelectedItem(formatted); + @Override + public void removeUpdate(DocumentEvent e) { + updateHelper(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + updateHelper(); } /** @@ -347,43 +323,16 @@ public class ImageFilePanel extends JPanel implements DocumentListener { * 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) { - + @NbBundle.Messages({"ImageFilePanel.moduleErr=Module Error", + "ImageFilePanel.moduleErr.msg=A module caused an error listening to ImageFilePanel updates." + + " See log to determine which module. Some data could be incomplete.\n"}) + private void updateHelper() { try { firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); - } catch (Exception ee) { - logger.log(Level.SEVERE, "ImageFilePanel listener threw exception", ee); //NON-NLS - MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "ImageFilePanel.moduleErr"), - NbBundle.getMessage(this.getClass(), "ImageFilePanel.moduleErr.msg"), - MessageNotifyUtil.MessageType.ERROR); - } - } - - @Override - public void removeUpdate(DocumentEvent e) { - try { - firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); - } catch (Exception ee) { - logger.log(Level.SEVERE, "ImageFilePanel listener threw exception", ee); //NON-NLS - MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "ImageFilePanel.moduleErr"), - NbBundle.getMessage(this.getClass(), "ImageFilePanel.moduleErr.msg"), - MessageNotifyUtil.MessageType.ERROR); - } - } - - @Override - public void changedUpdate(DocumentEvent e) { - - try { - firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); - } catch (Exception ee) { - logger.log(Level.SEVERE, "ImageFilePanel listener threw exception", ee); //NON-NLS - MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "ImageFilePanel.moduleErr"), - NbBundle.getMessage(this.getClass(), "ImageFilePanel.moduleErr.msg"), - MessageNotifyUtil.MessageType.ERROR); + } catch (Exception e) { + logger.log(Level.SEVERE, "ImageFilePanel listener threw exception", e); //NON-NLS + MessageNotifyUtil.Notify.error(ImageFilePanel_moduleErr(), ImageFilePanel_moduleErr_msg()); } }