/* * Autopsy Forensic Browser * * Copyright 2011 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.casemodule; import java.io.File; import java.util.Calendar; import java.util.SimpleTimeZone; import java.util.TimeZone; import javax.swing.JCheckBox; import javax.swing.event.DocumentEvent; import javax.swing.filechooser.FileFilter; import javax.swing.JFileChooser; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.event.DocumentListener; import org.openide.DialogDescriptor; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; /** * The "Add Image" wizard panel 1. This class is used to design the "form" of * the panel 1 for "Add Image" wizard panel. * * @author jantonius */ final class AddImageVisualPanel1 extends JPanel implements DocumentListener { private JFileChooser fc = new JFileChooser(); private FileFilter filter; static final String[] imgExt = {".img", ".dd"}; static final String imgDesc = "Raw Images (*.img, *.dd)"; static GeneralFilter imgFilter = new GeneralFilter(imgExt, imgDesc, false); static final String[] splitExt = {".*\\.[0-9][0-9][0-9]", ".*\\.[a-z][a-z]"}; static final String splitDesc = "Split Part (*.001, *.002, etc)"; static GeneralFilter splitFilter = new GeneralFilter(splitExt, splitDesc, true); static final String[] encasExt = {".*\\.e[0-9][0-9]", ".*\\.e[a-z][a-z]"}; static final String encaseDesc = "Encase Images (*.e01, *.eAA)"; static GeneralFilter encaseFilter = new GeneralFilter(encasExt, encaseDesc, true); private boolean multi = false; private AddImageWizardPanel1 wizPanel; /** * Creates new form AddImageVisualPanel1 * @param wizPanel corresponding WizardPanel to handle logic of wizard step */ AddImageVisualPanel1(AddImageWizardPanel1 wizPanel) { initComponents(); this.wizPanel = wizPanel; fc.setDragEnabled(multi); fc.setFileSelectionMode(JFileChooser.FILES_ONLY); fc.setMultiSelectionEnabled(multi); fc.addChoosableFileFilter(imgFilter); filter = imgFilter; buttonGroup1.add(encase); buttonGroup1.add(rawSingle); buttonGroup1.add(rawSplit); imgPathTextField.getDocument().addDocumentListener(this); imgPathTextField.setText(""); jLabel1.setText(""); rawSingle.setSelected(true); rawSplit.setSelected(false); encase.setSelected(false); createTimeZoneList(); } /** * Returns the name of the this panel. This name will be shown on the left * panel of the "Add Image" wizard panel. * * @return name the name of this panel */ @Override public String getName() { return "Enter Image Information"; } /** * Gets the array of image paths from the Image Path Text Field. * * @return imagePaths the array of image paths */ public String[] getImagePaths() { String[] imgPath = Case.convertImgPath(imgPathTextField.getText()); if (Case.checkMultiplePathExist(imgPath)) { return imgPath; } else { return new String[0]; } } public JTextField getImagePathTextField() { return this.imgPathTextField; } /** * * @return true if no fat orphans processing is selected */ boolean getNoFatOrphans() { return noFatOrphansCheckbox.isSelected(); } /** * Gets the type of the image that's selected. * * @return imgType the type of the image that selected */ public String getImgType() { if (rawSingle.isSelected()) { return "Raw Single"; } if (rawSplit.isSelected()) { return "Raw Split"; } if (encase.isSelected()) { return "EnCase"; } else { return "Nothing Selected"; } } /** * Gets the time zone that selected on the drop down list. * * @return timeZone the time zone that selected */ public String getSelectedTimezone() { String tz = timeZoneComboBox.getSelectedItem().toString(); return tz.substring(tz.indexOf(")") + 2).trim(); } // add the timeZone list to the timeZoneComboBox /** * Creates the drop down list for the time zones and then makes the local * machine time zones to be selected. */ public void createTimeZoneList() { // load and add all timezone String[] ids = SimpleTimeZone.getAvailableIDs(); for (String id : ids) { TimeZone zone = TimeZone.getTimeZone(id); int offset = zone.getRawOffset() / 1000; int hour = offset / 3600; int minutes = (offset % 3600) / 60; String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id); /* DateFormat dfm = new SimpleDateFormat("z"); dfm.setTimeZone(zone); boolean hasDaylight = zone.useDaylightTime(); String first = dfm.format(new Date(2010, 1, 1)); String second = dfm.format(new Date(2011, 6, 6)); int mid = hour * -1; String result = first + Integer.toString(mid); if(hasDaylight){ result = result + second; } timeZoneComboBox.addItem(item + " (" + result + ")"); */ timeZoneComboBox.addItem(item); } // get the current timezone TimeZone thisTimeZone = Calendar.getInstance().getTimeZone(); int thisOffset = thisTimeZone.getRawOffset() / 1000; int thisHour = thisOffset / 3600; int thisMinutes = (thisOffset % 3600) / 60; String formatted = String.format("(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID()); // set the selected timezone timeZoneComboBox.setSelectedItem(formatted); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ // //GEN-BEGIN:initComponents private void initComponents() { buttonGroup1 = new javax.swing.ButtonGroup(); rawSingle = new javax.swing.JRadioButton(); rawSplit = new javax.swing.JRadioButton(); imgTypeLabel = new javax.swing.JLabel(); encase = new javax.swing.JRadioButton(); imgPathLabel = new javax.swing.JLabel(); multipleSelectLabel = new javax.swing.JLabel(); imgPathTextField = new javax.swing.JTextField(); imgPathBrowserButton = new javax.swing.JButton(); this.imgPathBrowserButton.setDefaultCapable(true); this.imgPathBrowserButton.requestFocus(); imgInfoLabel = new javax.swing.JLabel(); jLabel1 = new javax.swing.JLabel(); timeZoneComboBox = new javax.swing.JComboBox(); timeZoneLabel = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); noFatOrphansCheckbox = new javax.swing.JCheckBox(); optionsLabel1 = new javax.swing.JLabel(); setMinimumSize(new java.awt.Dimension(559, 328)); setPreferredSize(new java.awt.Dimension(588, 328)); org.openide.awt.Mnemonics.setLocalizedText(rawSingle, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.rawSingle.text")); // NOI18N rawSingle.setRequestFocusEnabled(false); rawSingle.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { rawSingleActionPerformed(evt); } }); org.openide.awt.Mnemonics.setLocalizedText(rawSplit, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.rawSplit.text")); // NOI18N rawSplit.setRequestFocusEnabled(false); rawSplit.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { rawSplitActionPerformed(evt); } }); org.openide.awt.Mnemonics.setLocalizedText(imgTypeLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgTypeLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(encase, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.encase.text")); // NOI18N encase.setRequestFocusEnabled(false); encase.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { encaseActionPerformed(evt); } }); org.openide.awt.Mnemonics.setLocalizedText(imgPathLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgPathLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(multipleSelectLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.multipleSelectLabel.text")); // NOI18N imgPathTextField.setText(org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgPathTextField.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(imgPathBrowserButton, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgPathBrowserButton.text")); // NOI18N imgPathBrowserButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { imgPathBrowserButtonActionPerformed(evt); } }); imgInfoLabel.setFont(new java.awt.Font("Tahoma", 1, 14)); org.openide.awt.Mnemonics.setLocalizedText(imgInfoLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.imgInfoLabel.text")); // NOI18N jLabel1.setForeground(new java.awt.Color(255, 0, 51)); org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.jLabel1.text")); // NOI18N timeZoneComboBox.setMaximumRowCount(30); org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.timeZoneLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.jLabel2.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.noFatOrphansCheckbox.text")); // NOI18N noFatOrphansCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.noFatOrphansCheckbox.toolTipText")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(optionsLabel1, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.optionsLabel1.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) .addGroup(layout.createSequentialGroup() .addGap(10, 10, 10) .addComponent(noFatOrphansCheckbox)) .addComponent(imgTypeLabel) .addGroup(layout.createSequentialGroup() .addGap(10, 10, 10) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(rawSplit) .addComponent(rawSingle) .addComponent(encase))) .addComponent(multipleSelectLabel) .addComponent(imgInfoLabel) .addComponent(jLabel1) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() .addComponent(timeZoneLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 253, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() .addComponent(imgPathLabel) .addGap(18, 18, 18) .addComponent(imgPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 389, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(imgPathBrowserButton))) .addComponent(optionsLabel1) .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap(39, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(imgInfoLabel) .addGap(19, 19, 19) .addComponent(imgTypeLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(rawSingle) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(rawSplit) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(encase) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(imgPathLabel) .addComponent(imgPathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(imgPathBrowserButton)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(multipleSelectLabel) .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)) .addGap(18, 18, 18) .addComponent(optionsLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(noFatOrphansCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jLabel1) .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(25, 25, 25)) ); }// //GEN-END:initComponents /** * When the "rawSingle" radio button is selected. * * @param evt the action event */ private void rawSingleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rawSingleActionPerformed rawSingle.setSelected(true); rawSplit.setSelected(false); encase.setSelected(false); multipleSelectLabel.setText("Single Image: Multiple Select Disabled"); filter = imgFilter; multi = false; this.updateUI(null); }//GEN-LAST:event_rawSingleActionPerformed /** * When the "rawSplit" radio button is selected. * * @param evt the action event */ private void rawSplitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rawSplitActionPerformed rawSingle.setSelected(false); rawSplit.setSelected(true); encase.setSelected(false); multipleSelectLabel.setText("Split Image: Multiple Select Enabled. Use Ctrl, Shift, " + "or Drag to select multiple image parts"); filter = splitFilter; multi = true; updateUI(null); }//GEN-LAST:event_rawSplitActionPerformed /** * When the "encase" radio button is selected. * * @param evt the action event */ private void encaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_encaseActionPerformed rawSingle.setSelected(false); rawSplit.setSelected(false); encase.setSelected(true); multipleSelectLabel.setText("EnCase Image: Multiple Select Enabled. Use Ctrl, Shift, " + "or Drag to select multiple image parts"); filter = encaseFilter; multi = true; updateUI(null); }//GEN-LAST:event_encaseActionPerformed /** * When the "Browse" button is pressed, open the file chooser window to * select the images. * * @param evt the action event */ private void imgPathBrowserButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_imgPathBrowserButtonActionPerformed fc.resetChoosableFileFilters(); fc.addChoosableFileFilter(filter); fc.setFileFilter(filter); fc.setMultiSelectionEnabled(multi); fc.setDragEnabled(multi); String oldText = imgPathTextField.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) { File[] files = fc.getSelectedFiles(); String path = ""; if (multi) { for (File file : files) { path = path + "\"" + file.getPath() + "\" "; } imgPathTextField.setText(path); } else { path = fc.getSelectedFile().getPath(); imgPathTextField.setText(path); } //if split image, and 1 chunk given, verify it's the first chunk boolean invalidChunk = false; String[] imgPath = Case.convertImgPath(imgPathTextField.getText()); if (imgPath.length == 1 && multi == true) { if (!imgPath[0].matches(".*\\.0.*1$") //001 && !imgPath[0].matches(".*\\.[aA]{1,}$") //aaa && !imgPath[0].matches(".*\\.[eE]{1}0.*1$") //E01 ) { NotifyDescriptor nd = new NotifyDescriptor.Confirmation("You need to select either all chunks or only the first chunk of a split image to add the entire image correctly. Are you sure you want to use this selection?", "Warning: First image chunk not selected", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE); nd.setValue(NotifyDescriptor.NO_OPTION); Object res = DialogDisplayer.getDefault().notify(nd); if (res != null && res == DialogDescriptor.NO_OPTION) { invalidChunk = true; } } } if (invalidChunk) { imgPathTextField.setText(oldText); return; } } this.wizPanel.moveFocusToNext(); }//GEN-LAST:event_imgPathBrowserButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.ButtonGroup buttonGroup1; private javax.swing.JRadioButton encase; private javax.swing.JLabel imgInfoLabel; private javax.swing.JButton imgPathBrowserButton; private javax.swing.JLabel imgPathLabel; private static javax.swing.JTextField imgPathTextField; private javax.swing.JLabel imgTypeLabel; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel multipleSelectLabel; private javax.swing.JCheckBox noFatOrphansCheckbox; private javax.swing.JLabel optionsLabel1; private static javax.swing.JRadioButton rawSingle; private javax.swing.JRadioButton rawSplit; private javax.swing.JComboBox timeZoneComboBox; private javax.swing.JLabel timeZoneLabel; // End of variables declaration//GEN-END:variables /** * Gives notification that there was an insert into the document. The * range given by the DocumentEvent bounds the freshly inserted region. * * @param e the document event */ @Override public void insertUpdate(DocumentEvent e) { updateUI(e); } /** * Gives notification that a portion of the document has been * removed. The range is given in terms of what the view last * saw (that is, before updating sticky positions). * * @param e the document event */ @Override public void removeUpdate(DocumentEvent e) { updateUI(e); } /** * Gives notification that an attribute or set of attributes changed. * * @param e the document event */ @Override public void changedUpdate(DocumentEvent e) { updateUI(e); } /** * The "listener" that updates the UI of this panel based on the changes of * fields on this panel. This is also the method to check whether all the * fields on this panel are correctly filled and decides whether to enable * the "Next" button or not. * * @param e the document event */ public void updateUI(DocumentEvent e) { String[] imgPath = Case.convertImgPath(imgPathTextField.getText()); boolean isExist = Case.checkMultiplePathExist(imgPath); File imgFile = new File(imgPath[0]); // check if the given paths exist and those are paths to image files boolean isImagePath = true; for (int i = 0; i < imgPath.length; i++) { File tempImgFile = new File(imgPath[i]); isImagePath = isImagePath && (Case.isPhysicalDrive(imgPath[i]) || (tempImgFile.exists() && !tempImgFile.isDirectory() && (imgFilter.accept(tempImgFile) || splitFilter.accept(tempImgFile) || encaseFilter.accept(tempImgFile)))); } if (isImagePath) { Case currentCase = Case.getCurrentCase(); File dbFile = new File(currentCase.getCaseDirectory() + File.separator + imgFile.getName() + ".db"); if (dbFile.exists()) { String dbExist = "This database already exists. Do you want to overwrite the database?"; NotifyDescriptor d = new NotifyDescriptor.Confirmation(dbExist, "Warning: Overwrite Database", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE); d.setValue(NotifyDescriptor.NO_OPTION); isExist = false; Object res = DialogDisplayer.getDefault().notify(d); if (res != null && res == DialogDescriptor.YES_OPTION) { isExist = dbFile.delete(); if (!isExist) { jLabel1.setText("*Database for this image is already created and it can't be deleted because it's being used."); } } if (res != null && res == DialogDescriptor.NO_OPTION) { jLabel1.setText("*Database for this image exist. Either delete it or select another image."); } } } else { isExist = false; } if (isExist) { jLabel1.setText(""); } this.wizPanel.enableNextButton(isExist); } }