mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 09:17:42 +00:00
Implemented an options panel for setting user external viewer rules
This commit is contained in:
parent
fb7c184a30
commit
ec432bbb47
@ -158,6 +158,7 @@ CueBannerPanel.title.text=Open Recent Case
|
||||
GeneralFilter.rawImageDesc.text=Raw Images (*.img, *.dd, *.001, *.aa, *.raw, *.bin)
|
||||
GeneralFilter.encaseImageDesc.text=Encase Images (*.e01)
|
||||
GeneralFilter.virtualMachineImageDesc.text=Virtual Machines (*.vmdk, *.vhd)
|
||||
GeneralFilter.executableDesc.text=Executables (*.exe)
|
||||
ImageDSProcessor.dsType.text=Image or VM File
|
||||
ImageDSProcessor.allDesc.text=All Supported Types
|
||||
ImageFilePanel.moduleErr=Module Error
|
||||
|
@ -42,6 +42,9 @@ public class GeneralFilter extends FileFilter {
|
||||
public static final String VIRTUAL_MACHINE_DESC = NbBundle.getMessage(GeneralFilter.class,
|
||||
"GeneralFilter.virtualMachineImageDesc.text");
|
||||
|
||||
public static final List<String> EXECUTABLE_EXTS = Arrays.asList(new String[]{".exe"}); //NON-NLS
|
||||
public static final String EXECUTABLE_DESC = NbBundle.getMessage(GeneralFilter.class, "GeneralFilter.executableDesc.text");
|
||||
|
||||
private List<String> extensions;
|
||||
private String desc;
|
||||
|
||||
|
@ -5,15 +5,173 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.directorytree;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author smori
|
||||
* A dialog for adding or editing an external viewer rule
|
||||
*/
|
||||
public class AddRuleDialog extends JDialog {
|
||||
|
||||
|
||||
private ExternalViewerRule rule;
|
||||
private final AddRulePanel addRulePanel;
|
||||
private BUTTON_PRESSED result;
|
||||
private JButton saveButton;
|
||||
private JButton closeButton;
|
||||
|
||||
enum BUTTON_PRESSED {
|
||||
OK, CANCEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dialog for creating an external viewer rule
|
||||
*/
|
||||
@Messages({"AddRuleDialog.title=External Viewer Rule"})
|
||||
AddRuleDialog() {
|
||||
super(new JFrame(Bundle.AddRuleDialog_title()), Bundle.AddRuleDialog_title(), true);
|
||||
addRulePanel = new AddRulePanel();
|
||||
this.display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dialog for editing an external viewer rule
|
||||
*
|
||||
* @param rule ExternalViewerRule to be edited
|
||||
*/
|
||||
AddRuleDialog(ExternalViewerRule rule) {
|
||||
super(new JFrame(Bundle.AddRuleDialog_title()), Bundle.AddRuleDialog_title(), true);
|
||||
addRulePanel = new AddRulePanel(rule);
|
||||
this.display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the add external viewer rule dialog.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"AddRuleDialog.addButton.title=Save",
|
||||
"AddRuleDialog.cancelButton.title=Cancel"})
|
||||
private void display() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
/**
|
||||
* Center the dialog.
|
||||
*/
|
||||
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
int width = this.getSize().width;
|
||||
int height = this.getSize().height;
|
||||
setLocation((screenDimension.width - width) / 2, (screenDimension.height - height) / 2);
|
||||
|
||||
add(this.addRulePanel, BorderLayout.PAGE_START);
|
||||
|
||||
// Add a save button.
|
||||
saveButton = new JButton(Bundle.AddRuleDialog_addButton_title());
|
||||
saveButton.addActionListener((ActionEvent e) -> {
|
||||
doButtonAction(true);
|
||||
});
|
||||
|
||||
// Add a close button.
|
||||
closeButton = new JButton(Bundle.AddRuleDialog_cancelButton_title());
|
||||
closeButton.addActionListener((ActionEvent e) -> {
|
||||
doButtonAction(false);
|
||||
});
|
||||
|
||||
// Put the buttons in their own panel, under the settings panel.
|
||||
JPanel buttonPanel = new JPanel();
|
||||
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
|
||||
buttonPanel.add(new javax.swing.Box.Filler(new Dimension(10, 10), new Dimension(10, 10), new Dimension(10, 10)));
|
||||
buttonPanel.add(saveButton);
|
||||
buttonPanel.add(new javax.swing.Box.Filler(new Dimension(10, 10), new Dimension(10, 10), new Dimension(10, 10)));
|
||||
buttonPanel.add(closeButton);
|
||||
add(buttonPanel, BorderLayout.LINE_START);
|
||||
|
||||
/**
|
||||
* Add a handler for when the dialog window is closed directly,
|
||||
* bypassing the buttons.
|
||||
*/
|
||||
this.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
doButtonAction(false);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Add a listener to enable the save button when a text field in the
|
||||
* AddRulePanel is changed or modified.
|
||||
*/
|
||||
this.addRulePanel.addPropertyChangeListener((PropertyChangeEvent evt) -> {
|
||||
if (evt.getPropertyName().equals(AddRulePanel.EVENT.CHANGED.toString())) {
|
||||
enableSaveButton();
|
||||
}
|
||||
});
|
||||
|
||||
enableSaveButton();
|
||||
|
||||
/**
|
||||
* Show the dialog.
|
||||
*/
|
||||
pack();
|
||||
setResizable(false);
|
||||
setVisible(true);
|
||||
getRootPane().setDefaultButton(saveButton);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs actions based on whether the save button was pressed or not.
|
||||
*
|
||||
* @param savePressed Whether save was pressed.
|
||||
*/
|
||||
private void doButtonAction(boolean savePressed) {
|
||||
if (savePressed) {
|
||||
ExternalViewerRule ruleFromPanel = addRulePanel.getRule();
|
||||
if (null != ruleFromPanel) {
|
||||
this.rule = ruleFromPanel;
|
||||
this.result = BUTTON_PRESSED.OK;
|
||||
setVisible(false);
|
||||
}
|
||||
} else {
|
||||
this.rule = null;
|
||||
this.result = BUTTON_PRESSED.CANCEL;
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the external viewer rule of this dialog
|
||||
*
|
||||
* @return The external viewer rule
|
||||
*/
|
||||
ExternalViewerRule getRule() {
|
||||
return rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the button pressed on this dialog
|
||||
*
|
||||
* @return The button pressed to close the dialog
|
||||
*/
|
||||
BUTTON_PRESSED getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables save button once addRulePanel's fields have text in them. Maps
|
||||
* enter key to the save button.
|
||||
*/
|
||||
private void enableSaveButton() {
|
||||
this.saveButton.setEnabled(addRulePanel.hasFields());
|
||||
getRootPane().setDefaultButton(saveButton);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
@ -16,13 +16,84 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="400" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="nameTextField" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="nameLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="exePathLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="80" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="exePathTextField" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="300" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="nameLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="nameTextField" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="exePathLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="exePathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="nameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="AddRulePanel.nameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="nameTextField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="AddRulePanel.nameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="exePathLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="AddRulePanel.exePathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="exePathTextField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="AddRulePanel.exePathTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="browseButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="AddRulePanel.browseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -5,17 +5,137 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.directorytree;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.GeneralFilter;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author smori
|
||||
* Panel found in an AddRuleDialog
|
||||
*/
|
||||
public class AddRulePanel extends javax.swing.JPanel {
|
||||
class AddRulePanel extends javax.swing.JPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AddRulePanel.class.getName());
|
||||
private final JFileChooser fc = new JFileChooser();
|
||||
private static final GeneralFilter exeFilter = new GeneralFilter(GeneralFilter.EXECUTABLE_EXTS, GeneralFilter.EXECUTABLE_DESC);
|
||||
|
||||
enum EVENT {
|
||||
CHANGED
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new form AddRulePanel
|
||||
*/
|
||||
public AddRulePanel() {
|
||||
AddRulePanel() {
|
||||
initComponents();
|
||||
fc.setDragEnabled(false);
|
||||
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
fc.setMultiSelectionEnabled(false);
|
||||
fc.setFileFilter(exeFilter);
|
||||
addListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new form AddRulePanel if the user is editing a rule. Loads
|
||||
* information of the rule being edited.
|
||||
*
|
||||
* @param rule to be edited
|
||||
*/
|
||||
AddRulePanel(ExternalViewerRule rule) {
|
||||
this();
|
||||
nameTextField.setText(rule.getName());
|
||||
exePathTextField.setText(rule.getExePath());
|
||||
addListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows listeners for when the name or exePath text fields are modified.
|
||||
*/
|
||||
private void addListener() {
|
||||
nameTextField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
fire();
|
||||
}
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
fire();
|
||||
}
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
fire();
|
||||
}
|
||||
private void fire() {
|
||||
firePropertyChange(EVENT.CHANGED.toString(), null, null);
|
||||
}
|
||||
});
|
||||
exePathTextField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
fire();
|
||||
}
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
fire();
|
||||
}
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
fire();
|
||||
}
|
||||
private void fire() {
|
||||
firePropertyChange(EVENT.CHANGED.toString(), null, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the text fields are empty or not.
|
||||
*
|
||||
* @return true if neither of the text fields are empty
|
||||
*/
|
||||
boolean hasFields() {
|
||||
return !exePathTextField.getText().isEmpty() && !nameTextField.getText().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ExternalViewerRule created from input text. Returns null if
|
||||
* the name is not a valid MIME type (as defined by both autopsy and the
|
||||
* user, checked through FileTypeDetector) or in the form of a valid
|
||||
* extension.
|
||||
*
|
||||
* @return ExternalViewerRule or null
|
||||
*/
|
||||
ExternalViewerRule getRule() {
|
||||
String name = nameTextField.getText();
|
||||
FileTypeDetector detector;
|
||||
try {
|
||||
detector = new FileTypeDetector();
|
||||
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
|
||||
logger.log(Level.WARNING, "Couldn't create file type detector for file ext mismatch settings.", ex);
|
||||
return null;
|
||||
}
|
||||
// Regex for MIME: ^[-\\w]+/[-\\w]+$
|
||||
if (name.isEmpty() || (!detector.isDetectable(name) && !name.matches("^\\.\\w+$"))) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.invalidExtOrMIME.message"),
|
||||
NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.invalidExtOrMIME.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return null;
|
||||
}
|
||||
String exePath = exePathTextField.getText();
|
||||
if (exePath.isEmpty()) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.invalidExePath.message"),
|
||||
NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.invalidExePath.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return null;
|
||||
}
|
||||
return new ExternalViewerRule(name, exePath);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -27,19 +147,77 @@ public class AddRulePanel extends javax.swing.JPanel {
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
nameLabel = new javax.swing.JLabel();
|
||||
nameTextField = new javax.swing.JTextField();
|
||||
exePathLabel = new javax.swing.JLabel();
|
||||
exePathTextField = new javax.swing.JTextField();
|
||||
browseButton = new javax.swing.JButton();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(nameLabel, org.openide.util.NbBundle.getMessage(AddRulePanel.class, "AddRulePanel.nameLabel.text")); // NOI18N
|
||||
|
||||
nameTextField.setText(org.openide.util.NbBundle.getMessage(AddRulePanel.class, "AddRulePanel.nameTextField.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(exePathLabel, org.openide.util.NbBundle.getMessage(AddRulePanel.class, "AddRulePanel.exePathLabel.text")); // NOI18N
|
||||
|
||||
exePathTextField.setText(org.openide.util.NbBundle.getMessage(AddRulePanel.class, "AddRulePanel.exePathTextField.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(AddRulePanel.class, "AddRulePanel.browseButton.text")); // NOI18N
|
||||
browseButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
browseButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 400, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(nameTextField)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(nameLabel)
|
||||
.addComponent(exePathLabel))
|
||||
.addGap(0, 80, Short.MAX_VALUE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(exePathTextField)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(browseButton)))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 300, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(nameLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(exePathLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(exePathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(browseButton))
|
||||
.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
|
||||
int returnState = fc.showOpenDialog(this);
|
||||
if (returnState == JFileChooser.APPROVE_OPTION) {
|
||||
String path = fc.getSelectedFile().getPath();
|
||||
exePathTextField.setText(path);
|
||||
}
|
||||
}//GEN-LAST:event_browseButtonActionPerformed
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton browseButton;
|
||||
private javax.swing.JLabel exePathLabel;
|
||||
private javax.swing.JTextField exePathTextField;
|
||||
private javax.swing.JLabel nameLabel;
|
||||
private javax.swing.JTextField nameTextField;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -99,6 +99,18 @@ ExternalViewerGlobalSettingsPanel.newRuleButton.text=New Rule
|
||||
ExternalViewerGlobalSettingsPanel.editRuleButton.text=Edit Rule
|
||||
ExternalViewerGlobalSettingsPanel.deleteRuleButton.toolTipText=
|
||||
ExternalViewerGlobalSettingsPanel.deleteRuleButton.text=Delete Rule
|
||||
ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text=jLabel1
|
||||
ExternalViewerGlobalSettingsPanel.ruleListLabel.text=jLabel2
|
||||
ExternalViewerGlobalSettingsPanel.exePathLabel.text=jLabel1
|
||||
ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text=Add your custom rules for external viewers
|
||||
ExternalViewerGlobalSettingsPanel.ruleListLabel.text=MIME type and extensions
|
||||
ExternalViewerGlobalSettingsPanel.exePathLabel.text=Program associated with this MIME type or extension
|
||||
AddRulePanel.nameLabel.text=MIME type or extension
|
||||
AddRulePanel.nameTextField.text=
|
||||
AddRulePanel.browseButton.text=Browse
|
||||
AddRulePanel.exePathLabel.text=Path of the program to use for files with this type or extension
|
||||
AddRulePanel.exePathTextField.text=
|
||||
ExternalViewerGlobalSettingsPanel.JOptionPane.invalidExtOrMIME.message=Extension or MIME type is invalid. Extensions should start with a "." character.
|
||||
ExternalViewerGlobalSettingsPanel.JOptionPane.invalidExtOrMIME.title=Invalid Name
|
||||
ExternalViewerGlobalSettingsPanel.JOptionPane.invalidExePath.message=The path to the program executable is invalid
|
||||
ExternalViewerGlobalSettingsPanel.JOptionPane.invalidExePath.title=Invalid Path
|
||||
ExternalViewerGlobalSettingsPanel.exePathNameLabel.text=No MIME type or extension currently selected
|
||||
ExternalViewerGlobalSettingsPanel.JOptionPane.ruleAlreadyExists.message=A rule already exists with this MIME type or extension. Please edit that one.
|
||||
ExternalViewerGlobalSettingsPanel.JOptionPane.ruleAlreadyExists.title=Rule not added
|
@ -33,14 +33,15 @@ import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
|
||||
/**
|
||||
* Extracts a File object to a temporary file in the case directory, and then
|
||||
* tries to open it in the user's system with the default associated
|
||||
* application.
|
||||
* tries to open it in the user's system with the default or user specified
|
||||
* associated application.
|
||||
*/
|
||||
public class ExternalViewerAction extends AbstractAction {
|
||||
|
||||
private final static Logger logger = Logger.getLogger(ExternalViewerAction.class.getName());
|
||||
private org.sleuthkit.datamodel.AbstractFile fileObject;
|
||||
final static String[] EXECUTABLE_EXT = {".exe", ".dll", ".com", ".bat", ".msi", ".reg", ".scr"}; //NON-NLS
|
||||
private String fileObjectExt;
|
||||
|
||||
public ExternalViewerAction(String title, Node fileNode) {
|
||||
super(title);
|
||||
@ -53,12 +54,15 @@ public class ExternalViewerAction extends AbstractAction {
|
||||
boolean isExecutable = false;
|
||||
if (extPos != -1) {
|
||||
String extension = fileName.substring(extPos, fileName.length()).toLowerCase();
|
||||
fileObjectExt = extension;
|
||||
for (int i = 0; i < EXECUTABLE_EXT.length; ++i) {
|
||||
if (EXECUTABLE_EXT[i].equals(extension)) {
|
||||
isExecutable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fileObjectExt = "";
|
||||
}
|
||||
|
||||
// no point opening a file if it's empty, and java doesn't know how to
|
||||
@ -89,13 +93,31 @@ public class ExternalViewerAction extends AbstractAction {
|
||||
logger.log(Level.WARNING, "Can't save to temporary file.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
try {
|
||||
Desktop.getDesktop().open(tempFile);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Could not find a viewer for the given file: " + tempFile.getName(), ex); //NON-NLS
|
||||
JOptionPane.showMessageDialog(null, Bundle.ExternalViewerAction_actionPerformed_failure_message(), Bundle.ExternalViewerAction_actionPerformed_failure_title(), JOptionPane.ERROR_MESSAGE);
|
||||
/**
|
||||
* Check if the file MIME type or extension exists in the user defined
|
||||
* settings. Otherwise open with the default associated application.
|
||||
*/
|
||||
String exePath = ExternalViewerRulesManager.getInstance().getExePathForName(fileObject.getMIMEType());
|
||||
if (exePath.equals("")) {
|
||||
exePath = ExternalViewerRulesManager.getInstance().getExePathForName(fileObjectExt);
|
||||
}
|
||||
if (!exePath.equals("")) {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
String[] s = new String[]{exePath, tempFile.getAbsolutePath()};
|
||||
try {
|
||||
runtime.exec(s);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Could not open the specified viewer for the given file: " + tempFile.getName(), ex); //NON-NLS
|
||||
JOptionPane.showMessageDialog(null, Bundle.ExternalViewerAction_actionPerformed_failure_message(), Bundle.ExternalViewerAction_actionPerformed_failure_title(), JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
Desktop.getDesktop().open(tempFile);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Could not find a viewer for the given file: " + tempFile.getName(), ex); //NON-NLS
|
||||
JOptionPane.showMessageDialog(null, Bundle.ExternalViewerAction_actionPerformed_failure_message(), Bundle.ExternalViewerAction_actionPerformed_failure_title(), JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
// delete the file on exit
|
||||
tempFile.deleteOnExit();
|
||||
}
|
||||
|
@ -37,7 +37,7 @@
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="externalViewerTitleLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jSplitPane1" max="32767" attributes="0"/>
|
||||
<Component id="jSplitPane1" pref="458" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -53,7 +53,7 @@
|
||||
</Component>
|
||||
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
|
||||
<Properties>
|
||||
<Property name="dividerLocation" type="int" value="400"/>
|
||||
<Property name="dividerLocation" type="int" value="350"/>
|
||||
<Property name="dividerSize" type="int" value="1"/>
|
||||
</Properties>
|
||||
|
||||
@ -69,10 +69,13 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="exePathLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="284" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="exePathLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="exePathNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="114" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -81,7 +84,9 @@
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="exePathLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="435" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="exePathNameLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="411" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -94,6 +99,13 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="exePathNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.exePathNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="rulesPanel">
|
||||
@ -112,7 +124,7 @@
|
||||
<Component id="ruleListLabel" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="rulesScrollPane" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="newRuleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@ -121,7 +133,7 @@
|
||||
<Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="68" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="18" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@ -134,7 +146,7 @@
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="ruleListLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" min="-2" pref="387" max="-2" attributes="0"/>
|
||||
<Component id="rulesScrollPane" min="-2" pref="387" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="newRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
@ -154,7 +166,7 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<Container class="javax.swing.JScrollPane" name="rulesScrollPane">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
@ -164,13 +176,7 @@
|
||||
<Component class="javax.swing.JList" name="rulesList">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
|
||||
<StringArray count="5">
|
||||
<StringItem index="0" value="Item 1"/>
|
||||
<StringItem index="1" value="Item 2"/>
|
||||
<StringItem index="2" value="Item 3"/>
|
||||
<StringItem index="3" value="Item 4"/>
|
||||
<StringItem index="4" value="Item 5"/>
|
||||
</StringArray>
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
|
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.directorytree;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
@ -16,8 +17,9 @@ import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author smori
|
||||
* An options panel for the user to create, edit, and delete associations for
|
||||
* opening files in external viewers. Users can associate a file by either MIME
|
||||
* type or by extension to an executable file.
|
||||
*/
|
||||
public class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implements OptionsPanel {
|
||||
|
||||
@ -33,23 +35,25 @@ public class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implem
|
||||
customizeComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes field variables. Adds a listener to the list of rules.
|
||||
*/
|
||||
private void customizeComponents() {
|
||||
rulesListModel = new DefaultListModel<>();
|
||||
rules = new ArrayList<>();
|
||||
rulesList.setModel(rulesListModel);
|
||||
|
||||
rulesList.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
if (e.getValueIsAdjusting() == false) {
|
||||
if (rulesList.getSelectedIndex() == -1) {
|
||||
clearRuleDetailsComponents();
|
||||
clearExePath();
|
||||
} else {
|
||||
populateRuleDetailsComponents();
|
||||
populateExePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,9 +69,10 @@ public class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implem
|
||||
jSplitPane1 = new javax.swing.JSplitPane();
|
||||
exePanel = new javax.swing.JPanel();
|
||||
exePathLabel = new javax.swing.JLabel();
|
||||
exePathNameLabel = new javax.swing.JLabel();
|
||||
rulesPanel = new javax.swing.JPanel();
|
||||
ruleListLabel = new javax.swing.JLabel();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
rulesScrollPane = new javax.swing.JScrollPane();
|
||||
rulesList = new javax.swing.JList<>();
|
||||
newRuleButton = new javax.swing.JButton();
|
||||
editRuleButton = new javax.swing.JButton();
|
||||
@ -77,38 +82,39 @@ public class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implem
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(externalViewerTitleLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text")); // NOI18N
|
||||
|
||||
jSplitPane1.setDividerLocation(400);
|
||||
jSplitPane1.setDividerLocation(350);
|
||||
jSplitPane1.setDividerSize(1);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(exePathLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.exePathLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(exePathNameLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.exePathNameLabel.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout exePanelLayout = new javax.swing.GroupLayout(exePanel);
|
||||
exePanel.setLayout(exePanelLayout);
|
||||
exePanelLayout.setHorizontalGroup(
|
||||
exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(exePanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(exePathLabel)
|
||||
.addContainerGap(284, Short.MAX_VALUE))
|
||||
.addGroup(exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(exePathLabel)
|
||||
.addComponent(exePathNameLabel))
|
||||
.addContainerGap(114, Short.MAX_VALUE))
|
||||
);
|
||||
exePanelLayout.setVerticalGroup(
|
||||
exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(exePanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(exePathLabel)
|
||||
.addContainerGap(435, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(exePathNameLabel)
|
||||
.addContainerGap(411, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
jSplitPane1.setRightComponent(exePanel);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(ruleListLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.ruleListLabel.text")); // NOI18N
|
||||
|
||||
rulesList.setModel(new javax.swing.AbstractListModel<ExternalViewerRule>() {
|
||||
String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
|
||||
public int getSize() { return strings.length; }
|
||||
public Object getElementAt(int i) { return strings[i]; }
|
||||
});
|
||||
jScrollPane1.setViewportView(rulesList);
|
||||
rulesScrollPane.setViewportView(rulesList);
|
||||
|
||||
newRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(newRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.newRuleButton.text")); // NOI18N
|
||||
@ -145,14 +151,14 @@ public class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implem
|
||||
.addComponent(ruleListLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(rulesPanelLayout.createSequentialGroup()
|
||||
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(rulesScrollPane, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, rulesPanelLayout.createSequentialGroup()
|
||||
.addComponent(newRuleButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(editRuleButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(deleteRuleButton)))
|
||||
.addGap(0, 68, Short.MAX_VALUE)))
|
||||
.addGap(0, 18, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
rulesPanelLayout.setVerticalGroup(
|
||||
@ -161,7 +167,7 @@ public class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implem
|
||||
.addContainerGap()
|
||||
.addComponent(ruleListLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 387, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(rulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 387, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(newRuleButton)
|
||||
@ -189,7 +195,7 @@ public class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implem
|
||||
.addContainerGap()
|
||||
.addComponent(externalViewerTitleLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jSplitPane1)
|
||||
.addComponent(jSplitPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 458, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
@ -198,9 +204,18 @@ public class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implem
|
||||
AddRuleDialog dialog = new AddRuleDialog();
|
||||
AddRuleDialog.BUTTON_PRESSED result = dialog.getResult();
|
||||
if (result == AddRuleDialog.BUTTON_PRESSED.OK) {
|
||||
rules.add(dialog.getRule());
|
||||
updateRulesListModel();
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
ExternalViewerRule newRule = dialog.getRule();
|
||||
// Only allow one association for each MIME type or extension.
|
||||
if (rules.contains(newRule)) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.ruleAlreadyExists.message"),
|
||||
NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.ruleAlreadyExists.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else {
|
||||
rules.add(dialog.getRule());
|
||||
updateRulesListModel();
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_newRuleButtonActionPerformed
|
||||
|
||||
@ -210,73 +225,101 @@ public class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implem
|
||||
AddRuleDialog.BUTTON_PRESSED result = dialog.getResult();
|
||||
if (result == AddRuleDialog.BUTTON_PRESSED.OK) {
|
||||
rules.remove(selected);
|
||||
rules.add(selected, dialog.getRule());
|
||||
updateRulesListModel();
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
ExternalViewerRule newRule = dialog.getRule();
|
||||
// Only allow one association for each MIME type or extension.
|
||||
if (rules.contains(newRule)) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.ruleAlreadyExists.message"),
|
||||
NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.ruleAlreadyExists.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else {
|
||||
rules.add(selected, dialog.getRule());
|
||||
updateRulesListModel();
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_editRuleButtonActionPerformed
|
||||
|
||||
|
||||
private void deleteRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteRuleButtonActionPerformed
|
||||
ExternalViewerRule rule = rulesList.getSelectedValue();
|
||||
rules.remove(rule);
|
||||
updateRulesListModel();
|
||||
if (!rulesListModel.isEmpty()) {
|
||||
rulesList.setSelectedIndex(0);
|
||||
}
|
||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||
}//GEN-LAST:event_deleteRuleButtonActionPerformed
|
||||
|
||||
|
||||
@Override
|
||||
public void store() {
|
||||
try {
|
||||
ExternalViewerRulesManager.getInstance().setUserRules(rules);
|
||||
} catch (ExternalViewerRulesManager.CustomRulesException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to set custom rules", ex);
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.saveFileTypes.errorMessage"),
|
||||
NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.storeFailed.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
ExternalViewerRulesManager.getInstance().setUserRules(rules);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
rules = ExternalViewerRulesManager.getInstance().getUserRules();
|
||||
updateRulesListModel();
|
||||
if (!rulesListModel.isEmpty()) {
|
||||
rulesList.setSelectedIndex(0);
|
||||
}
|
||||
enableButtons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list model for the file types list component.
|
||||
* Enable edit and delete buttons if there is a rule selected.
|
||||
*/
|
||||
private void enableButtons() {
|
||||
boolean ruleIsSelected = rulesList.getSelectedIndex() != -1;
|
||||
editRuleButton.setEnabled(ruleIsSelected);
|
||||
deleteRuleButton.setEnabled(ruleIsSelected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list model for the rules list component, sorted by the MIME
|
||||
* type or extension alphabetically.
|
||||
*/
|
||||
private void updateRulesListModel() {
|
||||
rulesListModel.clear();
|
||||
Collections.sort(rules, (ExternalViewerRule rule1, ExternalViewerRule rule2) -> {
|
||||
return rule1.getName().compareTo(rule2.getName());
|
||||
});
|
||||
for (ExternalViewerRule rule : rules) {
|
||||
rulesListModel.addElement(rule);
|
||||
}
|
||||
if (!rulesListModel.isEmpty()) {
|
||||
rulesList.setSelectedIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void populateRuleDetailsComponents() {
|
||||
/**
|
||||
* Fills in the .exe file path label if a rule is selected.
|
||||
*/
|
||||
private void populateExePath() {
|
||||
ExternalViewerRule rule = rulesList.getSelectedValue();
|
||||
exePathLabel.setText(rule.getExePath());
|
||||
if (rule != null) {
|
||||
exePathNameLabel.setText(rule.getExePath());
|
||||
}
|
||||
enableButtons();
|
||||
}
|
||||
|
||||
private void clearRuleDetailsComponents() {
|
||||
/**
|
||||
* Clears the .exe file path label.
|
||||
*/
|
||||
private void clearExePath() {
|
||||
rulesList.clearSelection();
|
||||
exePathLabel.setText("");
|
||||
exePathNameLabel.setText("");
|
||||
enableButtons();
|
||||
}
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton deleteRuleButton;
|
||||
private javax.swing.JButton editRuleButton;
|
||||
private javax.swing.JPanel exePanel;
|
||||
private javax.swing.JLabel exePathLabel;
|
||||
private javax.swing.JLabel exePathNameLabel;
|
||||
private javax.swing.JLabel externalViewerTitleLabel;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JSplitPane jSplitPane1;
|
||||
private javax.swing.JButton newRuleButton;
|
||||
private javax.swing.JLabel ruleListLabel;
|
||||
private javax.swing.JList<ExternalViewerRule> rulesList;
|
||||
private javax.swing.JPanel rulesPanel;
|
||||
private javax.swing.JScrollPane rulesScrollPane;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
*/
|
||||
package org.sleuthkit.autopsy.directorytree;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
@ -13,6 +13,9 @@ import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.Lookup;
|
||||
|
||||
/**
|
||||
* Controller for the ExternalViewerGlobalSettingsPanel
|
||||
*/
|
||||
@OptionsPanelController.TopLevelRegistration(
|
||||
categoryName = "#OptionsCategory_Name_ExternalViewer",
|
||||
iconBase = "org/sleuthkit/autopsy/modules/filetypeid/user-defined-file-types-settings.png",
|
||||
@ -21,17 +24,17 @@ import org.openide.util.Lookup;
|
||||
position = 9
|
||||
)
|
||||
public final class ExternalViewerOptionsPanelController extends OptionsPanelController {
|
||||
|
||||
|
||||
private ExternalViewerGlobalSettingsPanel panel;
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
private boolean changed;
|
||||
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
getPanel().load();
|
||||
changed = false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void applyChanges() {
|
||||
if (changed) {
|
||||
@ -39,56 +42,53 @@ public final class ExternalViewerOptionsPanelController extends OptionsPanelCont
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isChanged() {
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public JComponent getComponent(Lookup lkp) {
|
||||
return getPanel();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HelpCtx getHelpCtx() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addPropertyChangeListener(PropertyChangeListener l) {
|
||||
pcs.addPropertyChangeListener(l);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void removePropertyChangeListener(PropertyChangeListener l) {
|
||||
pcs.removePropertyChangeListener(l);
|
||||
}
|
||||
|
||||
|
||||
private ExternalViewerGlobalSettingsPanel getPanel() {
|
||||
if (panel == null) {
|
||||
panel = new ExternalViewerGlobalSettingsPanel();
|
||||
panel.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getPropertyName().equals(OptionsPanelController.PROP_CHANGED)) {
|
||||
changed();
|
||||
}
|
||||
panel.addPropertyChangeListener((PropertyChangeEvent evt) -> {
|
||||
if (evt.getPropertyName().equals(OptionsPanelController.PROP_CHANGED)) {
|
||||
changed();
|
||||
}
|
||||
});
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
void changed() {
|
||||
if (!changed) {
|
||||
changed = true;
|
||||
|
@ -5,33 +5,60 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.directorytree;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author smori
|
||||
* An object that represents an association between a MIME type or extension
|
||||
* name to a user defined executable.
|
||||
*/
|
||||
class ExternalViewerRule {
|
||||
private String name;
|
||||
private String exePath;
|
||||
|
||||
|
||||
private final String name;
|
||||
private final String exePath;
|
||||
|
||||
/**
|
||||
* Creates a new ExternalViewerRule
|
||||
*
|
||||
* @param name MIME type or extension
|
||||
* @param exePath Absolute path of the exe file
|
||||
*/
|
||||
ExternalViewerRule(String name, String exePath) {
|
||||
this.name = name;
|
||||
this.exePath = exePath;
|
||||
}
|
||||
|
||||
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
String getExePath() {
|
||||
return exePath;
|
||||
}
|
||||
|
||||
void editName(String newName) {
|
||||
name = newName;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
void editExePath(String newExePath) {
|
||||
exePath = newExePath;
|
||||
|
||||
/**
|
||||
* Only one association is allowed per MIME type or extension, so rules are
|
||||
* equal if the names are the same.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other != null && other instanceof ExternalViewerRule) {
|
||||
ExternalViewerRule that = (ExternalViewerRule) other;
|
||||
if (this.getName().equals(that.getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 67 * hash + Objects.hashCode(this.name);
|
||||
return hash;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,10 +5,91 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.directorytree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author smori
|
||||
* Manager for user's external viewer rules, used by the options panel and the
|
||||
* ExternalViewerAction. Reads from and writes to a preferences file.
|
||||
*/
|
||||
public class ExternalViewerRulesManager {
|
||||
|
||||
|
||||
private static final String RULES_SETTINGS_NAME = "ExternalViewerRules"; //NON-NLS
|
||||
private static final String RULES_SETTINGS_KEY = "Rules"; //NON-NLS
|
||||
private static ExternalViewerRulesManager instance;
|
||||
private List<ExternalViewerRule> userRules = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Gets the singleton manager of the external viewer rules defined by users.
|
||||
*
|
||||
* @return The external viewer rules manager singleton.
|
||||
*/
|
||||
synchronized static ExternalViewerRulesManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ExternalViewerRulesManager();
|
||||
instance.loadUserDefinedRules();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ExternalViewerRulesManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads user defined rules from the configuration settings file.
|
||||
*/
|
||||
private void loadUserDefinedRules() {
|
||||
String setting = ModuleSettings.getConfigSetting(RULES_SETTINGS_NAME, RULES_SETTINGS_KEY);
|
||||
if (setting != null && !setting.isEmpty()) {
|
||||
List<String> ruleTuples = Arrays.asList(setting.split("\\|"));
|
||||
for (String ruleTuple : ruleTuples) {
|
||||
String[] ruleParts = ruleTuple.split(">");
|
||||
userRules.add(new ExternalViewerRule(ruleParts[0], ruleParts[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a list of ExternalViewerRule objects to a configuration settings
|
||||
* file.
|
||||
*
|
||||
* @param rules to be written and saved.
|
||||
*/
|
||||
synchronized void setUserRules(List<ExternalViewerRule> rules) {
|
||||
StringBuilder setting = new StringBuilder();
|
||||
for (ExternalViewerRule rule : rules) {
|
||||
if (setting.length() != 0) {
|
||||
setting.append("|");
|
||||
}
|
||||
setting.append(rule.getName()).append(">");
|
||||
setting.append(rule.getExePath());
|
||||
}
|
||||
ModuleSettings.setConfigSetting(RULES_SETTINGS_NAME, RULES_SETTINGS_KEY, setting.toString());
|
||||
userRules = new ArrayList<>(rules);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a list of the user's rules as ExternalViewerRule objects
|
||||
*/
|
||||
synchronized List<ExternalViewerRule> getUserRules() {
|
||||
// ExternalViewerRule objects are immutable
|
||||
return new ArrayList<>(userRules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the executable path associated with a rule name (MIME type or
|
||||
* extension). Returns an empty string if the rule name is not found.
|
||||
* @param name of MIME type or extension.
|
||||
* @return the associated executable absolute path.
|
||||
*/
|
||||
synchronized String getExePathForName(String name) {
|
||||
for (ExternalViewerRule rule : userRules) {
|
||||
if (rule.getName().equals(name)) {
|
||||
return rule.getExePath();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
@ -372,7 +372,7 @@ final class CustomFileTypesManager {
|
||||
return filesSetsSettings.getUserDefinedFileTypes();
|
||||
}
|
||||
} catch (IOException | ClassNotFoundException ex) {
|
||||
throw new CustomFileTypesException(String.format("Failed to read ssettings from %s", filePath), ex); //NON-NLS
|
||||
throw new CustomFileTypesException(String.format("Failed to read settings from %s", filePath), ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user