2018-08-10 09:45:04 -04:00

290 lines
12 KiB
Java

/*
* Autopsy Forensic Browser
*
* Copyright 2011-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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.experimental.autoingest;
import java.io.File;
import java.util.List;
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.filechooser.FileFilter;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import static org.sleuthkit.autopsy.experimental.autoingest.Bundle.*;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
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;
/**
* Panel for adding an archive file which is supported by 7zip library (e.g.
* "zip", "rar", "arj", "7z", "7zip", "gzip, etc). Allows the user to select a
* file.
*/
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
class ArchiveFilePanel extends JPanel implements DocumentListener {
private static final Logger logger = Logger.getLogger(ArchiveFilePanel.class.getName());
private static final String PROP_LAST_ARCHIVE_PATH = "LBL_LastImage_PATH"; //NON-NLS
private final JFileChooser fileChooser = new JFileChooser();
/**
* Externally supplied name is used to store settings
*/
private final String contextName;
/**
* Creates new form ArchiveFilePanel
*
* @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 ArchiveFilePanel(String context, List<FileFilter> fileChooserFilters) {
this.contextName = context;
initComponents();
errorLabel.setVisible(false);
fileChooser.setDragEnabled(false);
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setMultiSelectionEnabled(false);
fileChooserFilters.forEach(fileChooser::addChoosableFileFilter);
if (fileChooserFilters.isEmpty() == false) {
fileChooser.setFileFilter(fileChooserFilters.get(0));
}
}
/**
* Creates and returns an instance of a ArchiveFilePanel.
*
* @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 ArchiveFilePanel
*/
public static synchronized ArchiveFilePanel createInstance(String context, List<FileFilter> fileChooserFilters) {
ArchiveFilePanel instance = new ArchiveFilePanel(context, fileChooserFilters);
// post-constructor initialization of listener support without leaking references of uninitialized objects
instance.pathTextField.getDocument().addDocumentListener(instance);
return instance;
}
/**
* 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.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
pathLabel = new javax.swing.JLabel();
browseButton = new javax.swing.JButton();
pathTextField = new javax.swing.JTextField();
errorLabel = new javax.swing.JLabel();
setMinimumSize(new java.awt.Dimension(0, 65));
setPreferredSize(new java.awt.Dimension(403, 65));
org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(ArchiveFilePanel.class, "ArchiveFilePanel.pathLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(ArchiveFilePanel.class, "ArchiveFilePanel.browseButton.text")); // NOI18N
browseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
browseButtonActionPerformed(evt);
}
});
pathTextField.setText(org.openide.util.NbBundle.getMessage(ArchiveFilePanel.class, "ArchiveFilePanel.pathTextField.text")); // NOI18N
errorLabel.setForeground(new java.awt.Color(255, 0, 0));
org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(ArchiveFilePanel.class, "ArchiveFilePanel.errorLabel.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()
.addComponent(pathTextField)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(browseButton)
.addGap(2, 2, 2))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pathLabel)
.addComponent(errorLabel))
.addGap(0, 277, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(pathLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(browseButton)
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(3, 3, 3)
.addComponent(errorLabel)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
String oldText = getContentPaths();
// set the current directory of the FileChooser if the ArchivePath Field is valid
File currentDir = new File(oldText);
if (currentDir.exists()) {
fileChooser.setCurrentDirectory(currentDir);
}
if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
String path = fileChooser.getSelectedFile().getPath();
setContentPath(path);
}
updateHelper();
}//GEN-LAST:event_browseButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton browseButton;
private javax.swing.JLabel errorLabel;
private javax.swing.JLabel pathLabel;
private javax.swing.JTextField pathTextField;
// End of variables declaration//GEN-END:variables
/**
* Get the path of the user selected archive.
*
* @return the archive path
*/
public String getContentPaths() {
return pathTextField.getText();
}
/**
* Set the path of the archive file.
*
* @param s path of the archive file
*/
public void setContentPath(String s) {
pathTextField.setText(s);
}
public void reset() {
//reset the UI elements to default
pathTextField.setText(null);
}
/**
* Should we enable the next button of the wizard?
*
* @return true if a proper archive has been selected, false otherwise
*/
@NbBundle.Messages({"DataSourceOnCDriveError.text=Warning: Path to multi-user data source is on \"C:\" drive",
"DataSourceOnCDriveError.noOpenCase.errMsg=Warning: Exception while getting open case."
})
public boolean validatePanel() {
errorLabel.setVisible(false);
String path = getContentPaths();
if (StringUtils.isBlank(path)) {
return false;
}
// display warning if there is one (but don't disable "next" button)
try {
if (false == PathValidator.isValidForMultiUserCase(path, Case.getCurrentCaseThrows().getCaseType())) {
errorLabel.setVisible(true);
errorLabel.setText(Bundle.DataSourceOnCDriveError_text());
}
} catch (NoCurrentCaseException ex) {
errorLabel.setVisible(true);
errorLabel.setText(Bundle.DataSourceOnCDriveError_noOpenCase_errMsg());
}
return new File(path).isFile()
|| DriveUtils.isPhysicalDrive(path)
|| DriveUtils.isPartition(path);
}
public void storeSettings() {
String archivePathName = getContentPaths();
if (null != archivePathName) {
String archivePath = archivePathName.substring(0, archivePathName.lastIndexOf(File.separator) + 1);
ModuleSettings.setConfigSetting(contextName, PROP_LAST_ARCHIVE_PATH, archivePath);
}
}
public void readSettings() {
String lastArchivePath = ModuleSettings.getConfigSetting(contextName, PROP_LAST_ARCHIVE_PATH);
if (StringUtils.isNotBlank(lastArchivePath)) {
setContentPath(lastArchivePath);
}
}
@Override
public void insertUpdate(DocumentEvent e) {
updateHelper();
}
@Override
public void removeUpdate(DocumentEvent e) {
updateHelper();
}
@Override
public void changedUpdate(DocumentEvent e) {
updateHelper();
}
/**
* Update functions are called by the pathTextField which has this set as
* it's DocumentEventListener. Each update function fires a property change
* to be caught by the parent panel.
*
*/
@NbBundle.Messages({"ArchiveFilePanel.moduleErr=Module Error",
"ArchiveFilePanel.moduleErr.msg=A module caused an error listening to ArchiveFilePanel 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 e) {
logger.log(Level.SEVERE, "ArchiveFilePanel listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.error(ArchiveFilePanel_moduleErr(), ArchiveFilePanel_moduleErr_msg());
}
}
/**
* Set the focus to the pathTextField.
*/
public void select() {
pathTextField.requestFocusInWindow();
}
}