19 package org.sleuthkit.autopsy.casemodule;
 
   22 import java.util.Calendar;
 
   23 import java.util.List;
 
   24 import javax.swing.JFileChooser;
 
   25 import javax.swing.JOptionPane;
 
   26 import javax.swing.JPanel;
 
   27 import javax.swing.JTextField;
 
   28 import javax.swing.event.DocumentEvent;
 
   29 import javax.swing.event.DocumentListener;
 
   30 import javax.swing.filechooser.FileFilter;
 
   31 import org.apache.commons.lang3.StringUtils;
 
   32 import org.openide.util.NbBundle;
 
   45 @SuppressWarnings(
"PMD.SingularField") 
 
   48     private static final long serialVersionUID = 1L;
 
   49     private static final String PROP_LASTIMAGE_PATH = 
"LBL_LastImage_PATH"; 
 
   50     private static final String[] SECTOR_SIZE_CHOICES = {
"Auto Detect", 
"512", 
"1024", 
"2048", 
"4096"};
 
   51     private final JFileChooser fileChooser = 
new JFileChooser();
 
   62     private ImageFilePanel(String context, List<FileFilter> fileChooserFilters) {
 
   63         this.contextName = context;
 
   70         for (String choice : SECTOR_SIZE_CHOICES) {
 
   71             sectorSizeComboBox.addItem(choice);
 
   73         sectorSizeComboBox.setSelectedIndex(0);
 
   75         errorLabel.setVisible(
false);
 
   77         fileChooser.setDragEnabled(
false);
 
   78         fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
 
   79         fileChooser.setMultiSelectionEnabled(
false);
 
   80         fileChooserFilters.forEach(fileChooser::addChoosableFileFilter);
 
   81         if (fileChooserFilters.isEmpty() == 
false) {
 
   82             fileChooser.setFileFilter(fileChooserFilters.get(0));
 
   92         for (String timeZone : timeZoneList) {
 
   93             timeZoneComboBox.addItem(timeZone);
 
  121         return pathTextField;
 
  125         return md5HashTextField;
 
  129         return sha1HashTextField;
 
  133         return sha256HashTextField;
 
  144         pathLabel = 
new javax.swing.JLabel();
 
  145         browseButton = 
new javax.swing.JButton();
 
  146         pathTextField = 
new javax.swing.JTextField();
 
  147         timeZoneLabel = 
new javax.swing.JLabel();
 
  148         timeZoneComboBox = 
new javax.swing.JComboBox<>();
 
  149         noFatOrphansCheckbox = 
new javax.swing.JCheckBox();
 
  150         errorLabel = 
new javax.swing.JLabel();
 
  151         sectorSizeLabel = 
new javax.swing.JLabel();
 
  152         sectorSizeComboBox = 
new javax.swing.JComboBox<>();
 
  153         sha256HashLabel = 
new javax.swing.JLabel();
 
  154         sha256HashTextField = 
new javax.swing.JTextField();
 
  155         sha1HashTextField = 
new javax.swing.JTextField();
 
  156         md5HashTextField = 
new javax.swing.JTextField();
 
  157         sha1HashLabel = 
new javax.swing.JLabel();
 
  158         md5HashLabel = 
new javax.swing.JLabel();
 
  159         hashValuesLabel = 
new javax.swing.JLabel();
 
  160         hashValuesNoteLabel = 
new javax.swing.JLabel();
 
  162         setMinimumSize(
new java.awt.Dimension(0, 65));
 
  163         setPreferredSize(
new java.awt.Dimension(403, 65));
 
  165         org.openide.awt.Mnemonics.setLocalizedText(pathLabel, 
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.pathLabel.text")); 
 
  167         org.openide.awt.Mnemonics.setLocalizedText(browseButton, 
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.browseButton.text")); 
 
  168         browseButton.addActionListener(
new java.awt.event.ActionListener() {
 
  169             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  170                 browseButtonActionPerformed(evt);
 
  174         pathTextField.setText(
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.pathTextField.text")); 
 
  176         org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, 
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.timeZoneLabel.text")); 
 
  178         timeZoneComboBox.setMaximumRowCount(30);
 
  180         org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, 
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.noFatOrphansCheckbox.text")); 
 
  181         noFatOrphansCheckbox.setToolTipText(
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.noFatOrphansCheckbox.toolTipText")); 
 
  183         errorLabel.setForeground(
new java.awt.Color(255, 0, 0));
 
  184         org.openide.awt.Mnemonics.setLocalizedText(errorLabel, 
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.errorLabel.text")); 
 
  186         org.openide.awt.Mnemonics.setLocalizedText(sectorSizeLabel, 
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.sectorSizeLabel.text")); 
 
  188         org.openide.awt.Mnemonics.setLocalizedText(sha256HashLabel, 
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.sha256HashLabel.text")); 
 
  189         sha256HashLabel.setEnabled(
false);
 
  191         sha256HashTextField.setText(
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.sha256HashTextField.text")); 
 
  192         sha256HashTextField.setEnabled(
false);
 
  194         sha1HashTextField.setText(
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.sha1HashTextField.text")); 
 
  195         sha1HashTextField.setEnabled(
false);
 
  197         md5HashTextField.setText(
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.md5HashTextField.text")); 
 
  198         md5HashTextField.setEnabled(
false);
 
  200         org.openide.awt.Mnemonics.setLocalizedText(sha1HashLabel, 
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.sha1HashLabel.text")); 
 
  201         sha1HashLabel.setEnabled(
false);
 
  203         org.openide.awt.Mnemonics.setLocalizedText(md5HashLabel, 
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.md5HashLabel.text")); 
 
  204         md5HashLabel.setEnabled(
false);
 
  206         org.openide.awt.Mnemonics.setLocalizedText(hashValuesLabel, 
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.hashValuesLabel.text")); 
 
  207         hashValuesLabel.setEnabled(
false);
 
  209         org.openide.awt.Mnemonics.setLocalizedText(hashValuesNoteLabel, 
org.openide.util.NbBundle.getMessage(
ImageFilePanel.class, 
"ImageFilePanel.hashValuesNoteLabel.text")); 
 
  210         hashValuesNoteLabel.setEnabled(
false);
 
  212         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  213         this.setLayout(layout);
 
  214         layout.setHorizontalGroup(
 
  215             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  216             .addGroup(layout.createSequentialGroup()
 
  217                 .addComponent(pathTextField)
 
  218                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  219                 .addComponent(browseButton)
 
  221             .addGroup(layout.createSequentialGroup()
 
  222                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  223                     .addComponent(pathLabel)
 
  224                     .addComponent(noFatOrphansCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 262, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  225                 .addGap(0, 368, Short.MAX_VALUE))
 
  226             .addGroup(layout.createSequentialGroup()
 
  227                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  228                     .addComponent(errorLabel)
 
  229                     .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, 
false)
 
  230                         .addGroup(layout.createSequentialGroup()
 
  231                             .addComponent(timeZoneLabel)
 
  232                             .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  233                             .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  234                         .addGroup(layout.createSequentialGroup()
 
  235                             .addComponent(sectorSizeLabel)
 
  236                             .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  237                             .addComponent(sectorSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  238                         .addGroup(layout.createSequentialGroup()
 
  239                             .addComponent(md5HashLabel)
 
  240                             .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  241                             .addComponent(md5HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  242                         .addGroup(layout.createSequentialGroup()
 
  243                             .addComponent(sha1HashLabel)
 
  244                             .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  245                             .addComponent(sha1HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  246                         .addGroup(layout.createSequentialGroup()
 
  247                             .addComponent(sha256HashLabel)
 
  248                             .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  249                             .addComponent(sha256HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 455, javax.swing.GroupLayout.PREFERRED_SIZE)))
 
  250                     .addComponent(hashValuesNoteLabel)
 
  251                     .addComponent(hashValuesLabel))
 
  252                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  254         layout.setVerticalGroup(
 
  255             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  256             .addGroup(layout.createSequentialGroup()
 
  257                 .addComponent(pathLabel)
 
  258                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  259                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  260                     .addComponent(browseButton)
 
  261                     .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  262                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  263                 .addComponent(noFatOrphansCheckbox)
 
  264                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  265                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  266                     .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  267                     .addComponent(timeZoneLabel))
 
  268                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  269                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  270                     .addComponent(sectorSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  271                     .addComponent(sectorSizeLabel))
 
  273                 .addComponent(hashValuesLabel)
 
  274                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  275                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  276                     .addComponent(md5HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  277                     .addComponent(md5HashLabel))
 
  278                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  279                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  280                     .addComponent(sha1HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  281                     .addComponent(sha1HashLabel))
 
  282                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  283                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  284                     .addComponent(sha256HashTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  285                     .addComponent(sha256HashLabel))
 
  287                 .addComponent(hashValuesNoteLabel)
 
  289                 .addComponent(errorLabel)
 
  290                 .addContainerGap(51, Short.MAX_VALUE))
 
  294     @NbBundle.Messages({
"ImageFilePanel.000.confirmationMessage=The selected file" 
  295         + 
" has extenson .001 but there is a .000 file in the sequence of raw images." 
  296         + 
"\nShould the .000 file be used as the start, instead of the selected .001 file?\n"})
 
  298         String oldText = getContentPaths();
 
  300         File currentDir = 
new File(oldText);
 
  301         if (currentDir.exists()) {
 
  302             fileChooser.setCurrentDirectory(currentDir);
 
  305         if (fileChooser.showOpenDialog(
this) == JFileChooser.APPROVE_OPTION) {
 
  306             String path = fileChooser.getSelectedFile().getPath();
 
  307             if (path.endsWith(
".001")) {
 
  308                 String zeroX3_path = StringUtils.removeEnd(path, 
".001") + 
".000";
 
  309                 if (
new File(zeroX3_path).exists()) {
 
  310                     int showConfirmDialog = JOptionPane.showConfirmDialog(
this,
 
  311                             Bundle.ImageFilePanel_000_confirmationMessage(),
 
  312                             "Choose .001 file?", JOptionPane.YES_NO_OPTION);
 
  313                     if (showConfirmDialog == JOptionPane.YES_OPTION) {
 
  319             setContentPath(path);
 
  325             if (!oldText.equals(getContentPaths())) {
 
  326                 md5HashTextField.setText(null);
 
  327                 sha1HashTextField.setText(null);
 
  328                 sha256HashTextField.setText(null);
 
  361         hashValuesLabel.setEnabled(enabled);
 
  362         hashValuesNoteLabel.setEnabled(enabled);
 
  364         md5HashLabel.setEnabled(enabled);
 
  365         md5HashTextField.setEnabled(enabled);
 
  367         sha1HashLabel.setEnabled(enabled);
 
  368         sha1HashTextField.setEnabled(enabled);
 
  370         sha256HashLabel.setEnabled(enabled);
 
  371         sha256HashTextField.setEnabled(enabled);
 
  380         return pathTextField.getText();
 
  389         pathTextField.setText(s);
 
  398         int sectorSizeSelectionIndex = sectorSizeComboBox.getSelectedIndex();
 
  400         if (sectorSizeSelectionIndex == 0) {
 
  404         return Integer.valueOf((String) sectorSizeComboBox.getSelectedItem());
 
  408         String tz = timeZoneComboBox.getSelectedItem().toString();
 
  409         return tz.substring(tz.indexOf(
')') + 2).trim();
 
  413         return noFatOrphansCheckbox.isSelected();
 
  417         return this.md5HashTextField.getText();
 
  421         return this.sha1HashTextField.getText();
 
  425         return this.sha256HashTextField.getText();
 
  430         pathTextField.setText(null);
 
  431         this.md5HashTextField.setText(null);
 
  432         this.sha1HashTextField.setText(null);
 
  433         this.sha256HashTextField.setText(null);
 
  442         "ImageFilePanel.validatePanel.dataSourceOnCDriveError=Warning: Path to multi-user data source is on \"C:\" drive",
 
  443         "ImageFilePanel.validatePanel.invalidMD5=Invalid MD5 hash",
 
  444         "ImageFilePanel.validatePanel.invalidSHA1=Invalid SHA1 hash",
 
  445         "ImageFilePanel.validatePanel.invalidSHA256=Invalid SHA256 hash",})
 
  447         errorLabel.setVisible(
false);
 
  449         String path = getContentPaths();
 
  450         if (!isImagePathValid()) {
 
  454         if (!StringUtils.isBlank(getMd5()) && !HashUtility.isValidMd5Hash(getMd5())) {
 
  455             errorLabel.setVisible(
true);
 
  456             errorLabel.setText(Bundle.ImageFilePanel_validatePanel_invalidMD5());
 
  460         if (!StringUtils.isBlank(getSha1()) && !HashUtility.isValidSha1Hash(getSha1())) {
 
  461             errorLabel.setVisible(
true);
 
  462             errorLabel.setText(Bundle.ImageFilePanel_validatePanel_invalidSHA1());
 
  466         if (!StringUtils.isBlank(getSha256()) && !HashUtility.isValidSha256Hash(getSha256())) {
 
  467             errorLabel.setVisible(
true);
 
  468             errorLabel.setText(Bundle.ImageFilePanel_validatePanel_invalidSHA256());
 
  473             errorLabel.setVisible(
true);
 
  474             errorLabel.setText(Bundle.ImageFilePanel_validatePanel_dataSourceOnCDriveError());
 
  481         String path = getContentPaths();
 
  491         String imagePathName = getContentPaths();
 
  492         if (null != imagePathName) {
 
  493             String imagePath = imagePathName.substring(0, imagePathName.lastIndexOf(File.separator) + 1);
 
  500         if (StringUtils.isNotBlank(lastImagePath)) {
 
  501             setContentPath(lastImagePath);
 
  526     @NbBundle.Messages({
"ImageFilePanel.moduleErr=Module Error",
 
  527         "ImageFilePanel.moduleErr.msg=A module caused an error listening to ImageFilePanel updates." 
  528         + 
" See log to determine which module. Some data could be incomplete.\n"})
 
  530         if (isImagePathValid() && !getContentPaths().toLowerCase().endsWith(
".e01")) {
 
  531             setHashValuesComponentsEnabled(
true);
 
  533             setHashValuesComponentsEnabled(
false);
 
  543         pathTextField.requestFocusInWindow();
 
static boolean isPhysicalDrive(String path)
static boolean isValidForMultiUserCase(String path, Case.CaseType caseType)
javax.swing.JLabel hashValuesNoteLabel
boolean getNoFatOrphans()
JTextField getSha256TextField()
javax.swing.JLabel timeZoneLabel
static List< String > createTimeZoneList()
javax.swing.JLabel pathLabel
boolean isImagePathValid()
JTextField getSha1TextField()
javax.swing.JTextField sha256HashTextField
javax.swing.JComboBox< String > sectorSizeComboBox
static synchronized ImageFilePanel createInstance(String context, List< FileFilter > fileChooserFilters)
javax.swing.JLabel sha1HashLabel
javax.swing.JTextField sha1HashTextField
javax.swing.JLabel sha256HashLabel
JTextField getMd5TextFieldField()
void createTimeZoneList()
static String createTimeZoneString(TimeZone timeZone)
void setContentPath(String s)
void browseButtonActionPerformed(java.awt.event.ActionEvent evt)
javax.swing.JLabel sectorSizeLabel
static synchronized void setConfigSetting(String moduleName, String settingName, String settingVal)
javax.swing.JLabel hashValuesLabel
javax.swing.JTextField md5HashTextField
javax.swing.JLabel md5HashLabel
ImageFilePanel(String context, List< FileFilter > fileChooserFilters)
javax.swing.JComboBox< String > timeZoneComboBox
void changedUpdate(DocumentEvent e)
void setHashValuesComponentsEnabled(boolean enabled)
JTextField getPathTextField()
static String getConfigSetting(String moduleName, String settingName)
javax.swing.JButton browseButton
static boolean isPartition(String path)
javax.swing.JTextField pathTextField
static Case getCurrentCase()
javax.swing.JLabel errorLabel
javax.swing.JCheckBox noFatOrphansCheckbox
void removeUpdate(DocumentEvent e)
void insertUpdate(DocumentEvent e)