mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 07:56:16 +00:00
290 lines
12 KiB
Java
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();
|
|
}
|
|
}
|