19 package org.sleuthkit.autopsy.datasourceprocessors;
 
   22 import java.util.Calendar;
 
   23 import java.util.SimpleTimeZone;
 
   24 import java.util.TimeZone;
 
   25 import javax.swing.JFileChooser;
 
   26 import javax.swing.JPanel;
 
   27 import javax.swing.event.DocumentEvent;
 
   28 import javax.swing.event.DocumentListener;
 
   29 import org.openide.util.NbBundle.Messages;
 
   35 final class RawDSInputPanel 
extends JPanel implements DocumentListener {
 
   36     private static final long TWO_GB = 2000000000L;
 
   37     private static final long serialVersionUID = 1L;    
 
   38     private final String PROP_LASTINPUT_PATH = 
"LBL_LastInputFile_PATH";
 
   39     private final JFileChooser fc = 
new JFileChooser();
 
   41     private final String contextName;
 
   45     private RawDSInputPanel(String context) {
 
   48         errorLabel.setVisible(
false);
 
   50         fc.setDragEnabled(
false);
 
   51         fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
 
   52         fc.setMultiSelectionEnabled(
false);
 
   54         this.contextName = context;
 
   60     static synchronized RawDSInputPanel createInstance(String context) {
 
   61         RawDSInputPanel instance = 
new RawDSInputPanel(context);
 
   64         instance.createTimeZoneList();
 
   71     private void postInit() {
 
   72         pathTextField.getDocument().addDocumentListener(
this);
 
   79     private void createTimeZoneList() {
 
   81         String[] ids = SimpleTimeZone.getAvailableIDs();
 
   82         for (String 
id : ids) {
 
   83             TimeZone zone = TimeZone.getTimeZone(
id);
 
   84             int offset = zone.getRawOffset() / 1000;
 
   85             int hour = offset / 3600;
 
   86             int minutes = (offset % 3600) / 60;
 
   87             String item = String.format(
"(GMT%+d:%02d) %s", hour, minutes, 
id);
 
   89             timeZoneComboBox.addItem(item);
 
   92         TimeZone thisTimeZone = Calendar.getInstance().getTimeZone();
 
   93         int thisOffset = thisTimeZone.getRawOffset() / 1000;
 
   94         int thisHour = thisOffset / 3600;
 
   95         int thisMinutes = (thisOffset % 3600) / 60;
 
   96         String formatted = String.format(
"(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID());
 
   99         timeZoneComboBox.setSelectedItem(formatted);
 
  107     @SuppressWarnings(
"unchecked")
 
  109     private 
void initComponents() {
 
  111         infileTypeButtonGroup = 
new javax.swing.ButtonGroup();
 
  112         pathLabel = 
new javax.swing.JLabel();
 
  113         pathTextField = 
new javax.swing.JTextField();
 
  114         browseButton = 
new javax.swing.JButton();
 
  115         j2GBBreakupRadioButton = 
new javax.swing.JRadioButton();
 
  116         jBreakFileUpLabel = 
new javax.swing.JLabel();
 
  117         jNoBreakupRadioButton = 
new javax.swing.JRadioButton();
 
  118         errorLabel = 
new javax.swing.JLabel();
 
  119         timeZoneLabel = 
new javax.swing.JLabel();
 
  120         timeZoneComboBox = 
new javax.swing.JComboBox<>();
 
  122         org.openide.awt.Mnemonics.setLocalizedText(pathLabel, 
org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, 
"RawDSInputPanel.pathLabel.text")); 
 
  124         pathTextField.setText(
org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, 
"RawDSInputPanel.pathTextField.text")); 
 
  126         org.openide.awt.Mnemonics.setLocalizedText(browseButton, 
org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, 
"RawDSInputPanel.browseButton.text")); 
 
  127         browseButton.addActionListener(
new java.awt.event.ActionListener() {
 
  128             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  129                 browseButtonActionPerformed(evt);
 
  133         infileTypeButtonGroup.add(j2GBBreakupRadioButton);
 
  134         j2GBBreakupRadioButton.setSelected(
true);
 
  135         org.openide.awt.Mnemonics.setLocalizedText(j2GBBreakupRadioButton, 
org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, 
"RawDSInputPanel.j2GBBreakupRadioButton.text")); 
 
  136         j2GBBreakupRadioButton.addActionListener(
new java.awt.event.ActionListener() {
 
  137             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  138                 j2GBBreakupRadioButtonActionPerformed(evt);
 
  142         org.openide.awt.Mnemonics.setLocalizedText(jBreakFileUpLabel, 
org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, 
"RawDSInputPanel.jBreakFileUpLabel.text")); 
 
  144         infileTypeButtonGroup.add(jNoBreakupRadioButton);
 
  145         org.openide.awt.Mnemonics.setLocalizedText(jNoBreakupRadioButton, 
org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, 
"RawDSInputPanel.jNoBreakupRadioButton.text")); 
 
  146         jNoBreakupRadioButton.addActionListener(
new java.awt.event.ActionListener() {
 
  147             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  148                 jNoBreakupRadioButtonActionPerformed(evt);
 
  152         errorLabel.setForeground(
new java.awt.Color(255, 0, 0));
 
  153         org.openide.awt.Mnemonics.setLocalizedText(errorLabel, 
org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, 
"RawDSInputPanel.errorLabel.text")); 
 
  155         org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, 
org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, 
"RawDSInputPanel.timeZoneLabel.text")); 
 
  157         timeZoneComboBox.setMaximumRowCount(30);
 
  159         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  160         this.setLayout(layout);
 
  161         layout.setHorizontalGroup(
 
  162             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  163             .addGroup(layout.createSequentialGroup()
 
  164                 .addComponent(pathTextField)
 
  165                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  166                 .addComponent(browseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  167             .addGroup(layout.createSequentialGroup()
 
  168                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  169                     .addComponent(pathLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 218, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  170                     .addGroup(layout.createSequentialGroup()
 
  171                         .addComponent(timeZoneLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 168, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  172                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  173                         .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE)))
 
  174                 .addGap(0, 19, Short.MAX_VALUE))
 
  175             .addGroup(layout.createSequentialGroup()
 
  176                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  177                     .addComponent(jBreakFileUpLabel)
 
  178                     .addComponent(errorLabel)
 
  179                     .addGroup(layout.createSequentialGroup()
 
  181                         .addComponent(j2GBBreakupRadioButton)
 
  182                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  183                         .addComponent(jNoBreakupRadioButton)))
 
  184                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  186         layout.setVerticalGroup(
 
  187             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  188             .addGroup(layout.createSequentialGroup()
 
  189                 .addComponent(pathLabel)
 
  190                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  191                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  192                     .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  193                     .addComponent(browseButton))
 
  194                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  195                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  196                     .addComponent(timeZoneLabel)
 
  197                     .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  198                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  199                 .addComponent(errorLabel)
 
  201                 .addComponent(jBreakFileUpLabel)
 
  202                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  203                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  204                     .addComponent(jNoBreakupRadioButton)
 
  205                     .addComponent(j2GBBreakupRadioButton))
 
  206                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  209     @SuppressWarnings(
"deprecation")
 
  210     private 
void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  211       String oldText = pathTextField.getText();
 
  213       File currentDir = 
new File(oldText);
 
  214       if (currentDir.exists()) {
 
  215           fc.setCurrentDirectory(currentDir);
 
  218       int retval = fc.showOpenDialog(
this);
 
  219       if (retval == JFileChooser.APPROVE_OPTION) {
 
  220           String path = fc.getSelectedFile().getPath();
 
  221           pathTextField.setText(path);
 
  225     private void j2GBBreakupRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  229     private void jNoBreakupRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  234     private javax.swing.JButton browseButton;
 
  235     private javax.swing.JLabel errorLabel;
 
  236     private javax.swing.ButtonGroup infileTypeButtonGroup;
 
  237     private javax.swing.JRadioButton j2GBBreakupRadioButton;
 
  238     private javax.swing.JLabel jBreakFileUpLabel;
 
  239     private javax.swing.JRadioButton jNoBreakupRadioButton;
 
  240     private javax.swing.JLabel pathLabel;
 
  241     private javax.swing.JTextField pathTextField;
 
  242     private javax.swing.JComboBox<String> timeZoneComboBox;
 
  243     private javax.swing.JLabel timeZoneLabel;
 
  250     String getImageFilePath() {
 
  251         return pathTextField.getText();
 
  256         pathTextField.setText(null);
 
  257         j2GBBreakupRadioButton.setSelected(
true);
 
  260     long getChunkSize() {
 
  261         if (jNoBreakupRadioButton.isSelected()) {
 
  268     String getTimeZone() {
 
  269         String tz = timeZoneComboBox.getSelectedItem().toString();
 
  270         return tz.substring(tz.indexOf(
")") + 2).trim();
 
  278     boolean validatePanel() {
 
  279         errorLabel.setVisible(
false);
 
  280         String path = getImageFilePath();
 
  281         if (path == null || path.isEmpty()) {
 
  286         warnIfPathIsInvalid(path);
 
  288         boolean isExist = 
new File(path).exists();
 
  299     @Messages({
"RawDSInputPanel.error.text=Path to multi-user data source is on \"C:\" drive"})
 
  300     private void warnIfPathIsInvalid(String path) {
 
  301         if (!PathValidator.isValid(path, Case.getCurrentCase().getCaseType())) {
 
  302             errorLabel.setVisible(
true);
 
  303             errorLabel.setText(Bundle.RawDSInputPanel_error_text());
 
  307     void storeSettings() {
 
  308         String inFilePath = getImageFilePath();
 
  309         if (null != inFilePath) {
 
  310             String imagePath = inFilePath.substring(0, inFilePath.lastIndexOf(File.separator) + 1);
 
  311             ModuleSettings.setConfigSetting(contextName, PROP_LASTINPUT_PATH, imagePath);
 
  315     void readSettings() {
 
  316         String inFilePath = ModuleSettings.getConfigSetting(contextName, PROP_LASTINPUT_PATH);
 
  317         if (null != inFilePath) {
 
  318             if (!inFilePath.isEmpty()) {
 
  319                 pathTextField.setText(inFilePath);
 
  332     public void insertUpdate(DocumentEvent e) {
 
  333         firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
false, 
true);
 
  337     public void removeUpdate(DocumentEvent e) {
 
  338         firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
false, 
true);
 
  342     public void changedUpdate(DocumentEvent e) {
 
  343         firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), 
false, 
true);
 
  350         pathTextField.requestFocusInWindow();