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 synchronized String getConfigSetting(String moduleName, String settingName)
 
static boolean isPhysicalDrive(String path)
 
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
 
static boolean isValidForCaseType(String path, Case.CaseType caseType)
 
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()
 
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)