From 2ca0c7de960965c28cec4da336c54856506ecb3e Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Fri, 21 Dec 2018 12:37:51 -0500 Subject: [PATCH 01/18] Added HxD button --- .../autopsy/corecomponents/Bundle.properties | 1 + .../corecomponents/DataContentViewerHex.form | 23 +++++-- .../corecomponents/DataContentViewerHex.java | 63 ++++++++++++++----- 3 files changed, 66 insertions(+), 21 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 299b0e18d4..38f8388cc4 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -193,3 +193,4 @@ ViewPreferencesPanel.keepCurrentViewerRadioButton.text=Stay on the same file vie ViewPreferencesPanel.useBestViewerRadioButton.toolTipText=For example, change from Hex to Media when a JPEG is selected. ViewPreferencesPanel.useBestViewerRadioButton.text=Change to the most specific file viewer ViewPreferencesPanel.fileNameTranslationColumnCheckbox.text=Add column in result viewer for file name translation +DataContentViewerHex.launchHxDButton.text=Launch in HxD diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form index 745c862756..8c9b3c36a2 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form @@ -45,7 +45,7 @@ - + @@ -54,7 +54,7 @@ - + @@ -120,7 +120,9 @@ - + + + @@ -140,7 +142,10 @@ - + + + + @@ -289,6 +294,16 @@ + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java index 6639856099..8d855b7aa0 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java @@ -21,6 +21,9 @@ package org.sleuthkit.autopsy.corecomponents; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; import java.util.logging.Level; import org.openide.util.NbBundle; @@ -29,9 +32,14 @@ import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.text.BadLocationException; import javax.swing.text.Utilities; +import org.openide.modules.InstalledFileLocator; import org.openide.nodes.Node; import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; +import org.sleuthkit.autopsy.coreutils.ExecUtil; +import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.DataConversion; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskException; @@ -105,6 +113,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont goToPageLabel = new javax.swing.JLabel(); goToOffsetLabel = new javax.swing.JLabel(); goToOffsetTextField = new javax.swing.JTextField(); + launchHxDButton = new javax.swing.JButton(); copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.copyMenuItem.text")); // NOI18N rightClickMenu.add(copyMenuItem); @@ -187,6 +196,13 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont } }); + launchHxDButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerHex.class, "DataContentViewerHex.launchHxDButton.text")); // NOI18N + launchHxDButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + launchHxDButtonActionPerformed(evt); + } + }); + javax.swing.GroupLayout hexViewerPanelLayout = new javax.swing.GroupLayout(hexViewerPanel); hexViewerPanel.setLayout(hexViewerPanelLayout); hexViewerPanelLayout.setHorizontalGroup( @@ -214,7 +230,9 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont .addComponent(goToOffsetLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(32, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(launchHxDButton) + .addContainerGap(39, Short.MAX_VALUE)) ); hexViewerPanelLayout.setVerticalGroup( hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -231,7 +249,9 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont .addComponent(goToPageLabel) .addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(goToOffsetLabel) - .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(launchHxDButton))) .addGap(0, 0, 0)) ); @@ -241,7 +261,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 686, Short.MAX_VALUE) .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) ); layout.setVerticalGroup( @@ -249,7 +269,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE)) + .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 267, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -334,6 +354,27 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont } }//GEN-LAST:event_goToOffsetTextFieldActionPerformed + private void launchHxDButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_launchHxDButtonActionPerformed + try { + String tempDirectory = Case.getCurrentCaseThrows().getTempDirectory(); + File dataSourceInTempDirectory = Paths.get(tempDirectory, dataSource.getId() + dataSource.getName()).toFile(); + ContentUtils.writeToFile(dataSource, dataSourceInTempDirectory); + + String HdXExecutableToFind = Paths.get("HxD", "HxD64.exe").toString(); + File HdXExecutable = InstalledFileLocator.getDefault().locate(HdXExecutableToFind, DataContentViewerHex.class.getPackage().getName(), false); + if (null == HdXExecutable) { + throw new IOException(String.format("Could not find HdXExecutable at %s", HdXExecutableToFind)); + } + + ProcessBuilder launchHdXExecutable = new ProcessBuilder(); + launchHdXExecutable.command(String.format("%s \"%s\"", HdXExecutable.getAbsolutePath(), dataSourceInTempDirectory.getAbsolutePath())); + ExecUtil.execute(launchHdXExecutable); + } catch (NoCurrentCaseException | IOException ex) { + logger.log(Level.SEVERE, "Unable to launch HxD Editor", ex); + //TODO - Make pop-up appear saying there were problems attempting to launch editor + } + }//GEN-LAST:event_launchHxDButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JMenuItem copyMenuItem; private javax.swing.JLabel currentPageLabel; @@ -344,6 +385,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont private javax.swing.JPanel hexViewerPanel; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JScrollPane jScrollPane3; + private javax.swing.JButton launchHxDButton; private javax.swing.JButton nextPageButton; private javax.swing.JLabel ofLabel; private javax.swing.JTextArea outputTextArea; @@ -528,17 +570,4 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont public Component getComponent() { return this; } - - /* - * Show the right click menu only if evt is the correct mouse event - */ - private void maybeShowPopup(java.awt.event.MouseEvent evt) { - if (evt.isPopupTrigger()) { - rightClickMenu.setLocation(evt.getLocationOnScreen()); - rightClickMenu.setVisible(true); - copyMenuItem.setEnabled(outputTextArea.getSelectedText() != null); - } else { - rightClickMenu.setVisible(false); - } - } } From 25f40787a475524cf47b04613f9441482602b482 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Fri, 21 Dec 2018 17:35:38 -0500 Subject: [PATCH 02/18] Making significant progress on redoing UI and adding in new HxD path --- .../autopsy/directorytree/Bundle.properties | 23 +- .../ExternalViewerGlobalSettingsPanel.form | 467 ++++++++++-------- .../ExternalViewerGlobalSettingsPanel.java | 378 +++++++------- 3 files changed, 443 insertions(+), 425 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties index 26c970b2b3..1526f404c0 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties @@ -90,12 +90,6 @@ ExtractUnallocAction.done.errMsg.msg=Error extracting unallocated space\: {0} ExtractAction.done.notifyMsg.extractErr=Error extracting files\: {0} OptionsCategory_Name_ExternalViewer=External Viewer OptionsCategory_Keywords_ExternalViewer=ExternalViewer -ExternalViewerGlobalSettingsPanel.newRuleButton.text=New Rule -ExternalViewerGlobalSettingsPanel.editRuleButton.text=Edit Rule -ExternalViewerGlobalSettingsPanel.deleteRuleButton.text=Delete Rule -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 ExternalViewerGlobalSettingsPanel.exePathLabel.MIME.text=Program associated with this MIME type ExternalViewerGlobalSettingsPanel.exePathLabel.EXT.text=Program associated with this extension ExternalViewerGlobalSettingsPanel.exePathLabel.empty.text=No MIME type or extension selected @@ -108,7 +102,6 @@ ExternalViewerGlobalSettingsPanel.JOptionPane.invalidExt.message=The extension i ExternalViewerGlobalSettingsPanel.JOptionPane.invalidExt.title=Invalid extension 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 AddExternalViewerRulePanel.mimeRadioButton.text=MIME type @@ -124,3 +117,19 @@ GroupDataSourcesDialog.yesButton.text=Yes GroupDataSourcesDialog.noButton.text=No GroupDataSourcesDialog.title=Group by Data Source? DirectoryTreeTopComponent.openViewPreferencesButton.text= +ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title3=Title 4 +ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title2=Title 3 +ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title3_1=Title 4 +ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title2_1=Title 3 +ExternalViewerGlobalSettingsPanel.newRuleButton1.text=New Rule +ExternalViewerGlobalSettingsPanel.editRuleButton.text=Edit Rule +ExternalViewerGlobalSettingsPanel.deleteRuleButton.text=Delete Rule +ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text=Set aplication viewer to use for files with specific mime types/extensions: +ExternalViewerGlobalSettingsPanel.newRuleButton.text=New Rule +ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title1=Application +ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title0=Mime type/Extension +ExternalViewerGlobalSettingsPanel.jLabel1.text=HxD Editor Path: +ExternalViewerGlobalSettingsPanel.jTextField1.text=C:/Program Files/HxD +ExternalViewerGlobalSettingsPanel.jButton1.text=Browse +ExternalViewerGlobalSettingsPanel.jButton2.text=jButton2 +ExternalViewerGlobalSettingsPanel.jLabel2.text=Set launchable content viewer extensions diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form index e04dc19270..e082b56e6f 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form @@ -1,6 +1,31 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + @@ -21,12 +46,12 @@ - + - + @@ -41,241 +66,257 @@ - - - - - - - - - - + + + + + + + + - - - - - - - - - - + + + + + - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + <ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + <ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index f5351393dc..aab3d3acf9 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2018 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. @@ -20,14 +20,11 @@ package org.sleuthkit.autopsy.directorytree; import java.util.ArrayList; import java.util.Collections; -import javax.swing.DefaultListModel; -import javax.swing.JOptionPane; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import org.netbeans.spi.options.OptionsPanelController; -import org.openide.util.NbBundle; +import javax.swing.table.DefaultTableModel; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; -import org.sleuthkit.autopsy.coreutils.Logger; +import javax.swing.JOptionPane; +import org.openide.util.NbBundle; +import org.netbeans.spi.options.OptionsPanelController; /** * An options panel for the user to create, edit, and delete associations for @@ -37,8 +34,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implements OptionsPanel { - private static final Logger logger = Logger.getLogger(ExternalViewerGlobalSettingsPanel.class.getName()); - private DefaultListModel rulesListModel; + private DefaultTableModel rulesTableModel; private java.util.List rules; /** @@ -53,21 +49,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme * 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) { - clearExePath(); - } else { - populateExePath(); - } - } - } - }); } /** @@ -79,60 +61,33 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme // //GEN-BEGIN:initComponents private void initComponents() { + newRuleButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); jPanel1 = new javax.swing.JPanel(); - externalViewerTitleLabel = new javax.swing.JLabel(); - jScrollPane1 = new javax.swing.JScrollPane(); - 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(); + jPanel2 = new javax.swing.JPanel(); newRuleButton = new javax.swing.JButton(); - editRuleButton = new javax.swing.JButton(); + jScrollPane4 = new javax.swing.JScrollPane(); + jTable1 = new javax.swing.JTable(); + externalViewerTitleLabel = new javax.swing.JLabel(); deleteRuleButton = new javax.swing.JButton(); - jScrollPane2 = new javax.swing.JScrollPane(); - rulesList = new javax.swing.JList<>(); + editRuleButton = new javax.swing.JButton(); + jPanel3 = new javax.swing.JPanel(); + jTextField1 = new javax.swing.JTextField(); + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + jButton1 = new javax.swing.JButton(); + + newRuleButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(newRuleButton1, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.newRuleButton1.text")); // NOI18N + newRuleButton1.setMaximumSize(new java.awt.Dimension(111, 25)); + newRuleButton1.setMinimumSize(new java.awt.Dimension(111, 25)); + + org.openide.awt.Mnemonics.setLocalizedText(jButton2, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jButton2.text")); // NOI18N setPreferredSize(new java.awt.Dimension(701, 453)); jPanel1.setPreferredSize(new java.awt.Dimension(701, 453)); - org.openide.awt.Mnemonics.setLocalizedText(externalViewerTitleLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text")); // NOI18N - - jSplitPane1.setDividerSize(1); - - exePanel.setPreferredSize(new java.awt.Dimension(311, 224)); - - 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() - .addGroup(exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(exePathLabel) - .addComponent(exePathNameLabel)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - exePanelLayout.setVerticalGroup( - exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(exePanelLayout.createSequentialGroup() - .addContainerGap() - .addComponent(exePathLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(exePathNameLabel) - .addContainerGap(355, Short.MAX_VALUE)) - ); - - jSplitPane1.setRightComponent(exePanel); - - org.openide.awt.Mnemonics.setLocalizedText(ruleListLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.ruleListLabel.text")); // NOI18N - 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 newRuleButton.setMaximumSize(new java.awt.Dimension(111, 25)); @@ -143,6 +98,40 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme } }); + jScrollPane4.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(204, 204, 204))); + + rulesTableModel = new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "Mime type/Extension", "Application" + } + ) { + @Override + public boolean isCellEditable(int i, int i1) { + return false; + } + }; + jTable1.setModel(rulesTableModel); + jScrollPane4.setViewportView(jTable1); + if (jTable1.getColumnModel().getColumnCount() > 0) { + jTable1.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title0")); // NOI18N + jTable1.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title1")); // NOI18N + } + + org.openide.awt.Mnemonics.setLocalizedText(externalViewerTitleLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text")); // NOI18N + + deleteRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/delete16.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(deleteRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.deleteRuleButton.text")); // NOI18N + deleteRuleButton.setMaximumSize(new java.awt.Dimension(111, 25)); + deleteRuleButton.setMinimumSize(new java.awt.Dimension(111, 25)); + deleteRuleButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + deleteRuleButtonActionPerformed(evt); + } + }); + editRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/edit16.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(editRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.editRuleButton.text")); // NOI18N editRuleButton.setMaximumSize(new java.awt.Dimension(111, 25)); @@ -153,94 +142,126 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme } }); - deleteRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/delete16.png"))); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(deleteRuleButton, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.deleteRuleButton.text")); // NOI18N - deleteRuleButton.setMaximumSize(new java.awt.Dimension(111, 25)); - deleteRuleButton.setMinimumSize(new java.awt.Dimension(111, 25)); - deleteRuleButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - deleteRuleButtonActionPerformed(evt); - } - }); - - jScrollPane2.setViewportView(rulesList); - - javax.swing.GroupLayout rulesPanelLayout = new javax.swing.GroupLayout(rulesPanel); - rulesPanel.setLayout(rulesPanelLayout); - rulesPanelLayout.setHorizontalGroup( - rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(rulesPanelLayout.createSequentialGroup() + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() .addContainerGap() - .addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(ruleListLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, rulesPanelLayout.createSequentialGroup() - .addGap(6, 6, 6) - .addComponent(newRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(16, 16, 16) - .addComponent(editRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(16, 16, 16) - .addComponent(deleteRuleButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addComponent(jScrollPane2)) - .addContainerGap()) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 634, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(jPanel2Layout.createSequentialGroup() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(externalViewerTitleLabel) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(newRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, 97, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(editRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(deleteRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) ); - rulesPanelLayout.setVerticalGroup( - rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(rulesPanelLayout.createSequentialGroup() - .addContainerGap() - .addComponent(ruleListLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane2) + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(externalViewerTitleLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGap(12, 12, 12) - .addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(newRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(editRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 219, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(newRuleButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(editRuleButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(deleteRuleButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap()) ); - jSplitPane1.setLeftComponent(rulesPanel); + jTextField1.setText(org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jTextField1.text")); // NOI18N + jTextField1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jTextField1ActionPerformed(evt); + } + }); - jScrollPane1.setViewportView(jSplitPane1); + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jLabel1.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jLabel2.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jLabel2) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(jPanel3Layout.createSequentialGroup() + .addGap(21, 21, 21) + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 441, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jButton1)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addComponent(externalViewerTitleLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 681, Short.MAX_VALUE) - .addContainerGap()) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addComponent(jScrollPane1) - .addContainerGap())) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGap(547, 547, 547)) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() - .addComponent(externalViewerTitleLabel) - .addContainerGap(428, Short.MAX_VALUE)) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(32, 32, 32) - .addComponent(jScrollPane1) - .addContainerGap())) + .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(83, Short.MAX_VALUE)) ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 1191, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); }// //GEN-END:initComponents + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_jButton1ActionPerformed + + private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField1ActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_jTextField1ActionPerformed + private void newRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newRuleButtonActionPerformed AddExternalViewerRuleDialog dialog = new AddExternalViewerRuleDialog(); AddExternalViewerRuleDialog.BUTTON_PRESSED result = dialog.getResult(); @@ -254,9 +275,9 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme JOptionPane.ERROR_MESSAGE); } else { rules.add(newRule); - updateRulesListModel(); + updateRulesTableModel(); int index = rules.indexOf(newRule); - rulesList.setSelectedIndex(index); + jTable1.getSelectionModel().setSelectionInterval(index, index); enableButtons(); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); } @@ -264,33 +285,11 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme }//GEN-LAST:event_newRuleButtonActionPerformed private void editRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editRuleButtonActionPerformed - int selected = rulesList.getSelectedIndex(); - AddExternalViewerRuleDialog dialog = new AddExternalViewerRuleDialog(rulesListModel.get(rulesList.getSelectedIndex())); - AddExternalViewerRuleDialog.BUTTON_PRESSED result = dialog.getResult(); - if (result == AddExternalViewerRuleDialog.BUTTON_PRESSED.OK) { - rules.remove(selected); - ExternalViewerRule newRule = dialog.getRule(); - // Only allow one association for each MIME type or extension. - if (rules.contains(newRule)) { - JOptionPane.showMessageDialog(this, - 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); - } - } - rulesList.setSelectedIndex(selected); - enableButtons(); + // TODO add your handling code here: }//GEN-LAST:event_editRuleButtonActionPerformed private void deleteRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteRuleButtonActionPerformed - ExternalViewerRule rule = rulesList.getSelectedValue(); - rules.remove(rule); - updateRulesListModel(); - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + // TODO add your handling code here: }//GEN-LAST:event_deleteRuleButtonActionPerformed @Override @@ -301,7 +300,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme @Override public void load() { rules = ExternalViewerRulesManager.getInstance().getUserRules(); - updateRulesListModel(); + updateRulesTableModel(); enableButtons(); } @@ -309,68 +308,37 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme * Enable edit and delete buttons if there is a rule selected. */ private void enableButtons() { - boolean ruleIsSelected = rulesList.getSelectedIndex() != -1; + boolean ruleIsSelected = jTable1.getSelectedRow() != -1; editRuleButton.setEnabled(ruleIsSelected); deleteRuleButton.setEnabled(ruleIsSelected); } /** - * Sets the list model for the rules list component, sorted by the MIME - * type or extension alphabetically. + * Sets the list model for the rules list component, sorted by the MIME type + * or extension alphabetically. */ - private void updateRulesListModel() { - rulesListModel.clear(); + private void updateRulesTableModel() { Collections.sort(rules); - for (ExternalViewerRule rule : rules) { - rulesListModel.addElement(rule); - } - } - - /** - * Fills in the .exe file path label if a rule is selected. - */ - private void populateExePath() { - ExternalViewerRule rule = rulesList.getSelectedValue(); - if (rule != null) { - if (rule.getRuleType() == ExternalViewerRule.RuleType.MIME) { - exePathLabel.setText(NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, - "ExternalViewerGlobalSettingsPanel.exePathLabel.MIME.text")); - } else { - exePathLabel.setText(NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, - "ExternalViewerGlobalSettingsPanel.exePathLabel.EXT.text")); - } - exePathNameLabel.setText(rule.getExePath()); - } - enableButtons(); - } - - /** - * Clears the .exe file path label. - */ - private void clearExePath() { - rulesList.clearSelection(); - exePathLabel.setText(NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, - "ExternalViewerGlobalSettingsPanel.exePathLabel.text")); - exePathNameLabel.setText(NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, - "ExternalViewerGlobalSettingsPanel.exePathLabel.empty.text")); - enableButtons(); + rules.forEach((rule) -> { + rulesTableModel.addRow(new Object[]{rule.getName(), rule.getExePath()}); + }); } // 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.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; private javax.swing.JPanel jPanel1; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JScrollPane jScrollPane2; - private javax.swing.JSplitPane jSplitPane1; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JScrollPane jScrollPane4; + private javax.swing.JTable jTable1; + private javax.swing.JTextField jTextField1; private javax.swing.JButton newRuleButton; - private javax.swing.JLabel ruleListLabel; - private javax.swing.JList rulesList; - private javax.swing.JPanel rulesPanel; - private javax.swing.JScrollPane rulesScrollPane; + private javax.swing.JButton newRuleButton1; // End of variables declaration//GEN-END:variables } From 5cc79ecce93cecaf0b1a92cc81fd5fffd418a8ff Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Mon, 31 Dec 2018 11:58:01 -0500 Subject: [PATCH 03/18] Reorganized the settings panel for External viewers --- .../autopsy/directorytree/Bundle.properties | 4 +- .../ExternalViewerGlobalSettingsPanel.form | 26 +-- .../ExternalViewerGlobalSettingsPanel.java | 190 ++++++++++++------ 3 files changed, 145 insertions(+), 75 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties index 1526f404c0..5857deb2b9 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties @@ -129,7 +129,7 @@ ExternalViewerGlobalSettingsPanel.newRuleButton.text=New Rule ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title1=Application ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title0=Mime type/Extension ExternalViewerGlobalSettingsPanel.jLabel1.text=HxD Editor Path: -ExternalViewerGlobalSettingsPanel.jTextField1.text=C:/Program Files/HxD -ExternalViewerGlobalSettingsPanel.jButton1.text=Browse ExternalViewerGlobalSettingsPanel.jButton2.text=jButton2 ExternalViewerGlobalSettingsPanel.jLabel2.text=Set launchable content viewer extensions +ExternalViewerGlobalSettingsPanel.browseHxDDirectory.text=Browse +ExternalViewerGlobalSettingsPanel.HxDPath.text=C:/Program Files/HxD/HxD.exe diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form index e082b56e6f..b3d33e0b2b 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form @@ -169,9 +169,6 @@ - - - @@ -196,7 +193,6 @@ - @@ -261,9 +257,9 @@ - + - + @@ -273,9 +269,9 @@ - + - + @@ -283,15 +279,13 @@ - + + - + - - - @@ -307,14 +301,14 @@ - + - + - + diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index aab3d3acf9..1903729ec5 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -18,13 +18,16 @@ */ package org.sleuthkit.autopsy.directorytree; +import java.io.File; import java.util.ArrayList; -import java.util.Collections; -import javax.swing.table.DefaultTableModel; +import javax.swing.JFileChooser; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import javax.swing.JOptionPane; +import javax.swing.table.AbstractTableModel; import org.openide.util.NbBundle; import org.netbeans.spi.options.OptionsPanelController; +import org.sleuthkit.autopsy.casemodule.GeneralFilter; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; /** * An options panel for the user to create, edit, and delete associations for @@ -34,8 +37,10 @@ import org.netbeans.spi.options.OptionsPanelController; @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implements OptionsPanel { - private DefaultTableModel rulesTableModel; + private RulesTableModel rulesTableModel; private java.util.List rules; + private static final String MODULE_NAME = ExternalViewerGlobalSettingsPanel.class.getName(); + private static final String HXD_PATH_NAME = "HxDExecutablePath"; /** * Creates new form ExternalViewerGlobalSettingsPanel @@ -50,6 +55,10 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme */ private void customizeComponents() { rules = new ArrayList<>(); + rulesTableModel = new RulesTableModel(new String[] { + "Mime type/Extension", "Application"}); + jTable1.setModel(rulesTableModel); + jTable1.setAutoCreateRowSorter(true); } /** @@ -72,10 +81,10 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme deleteRuleButton = new javax.swing.JButton(); editRuleButton = new javax.swing.JButton(); jPanel3 = new javax.swing.JPanel(); - jTextField1 = new javax.swing.JTextField(); + HxDPath = new javax.swing.JTextField(); jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); - jButton1 = new javax.swing.JButton(); + browseHxDDirectory = new javax.swing.JButton(); newRuleButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(newRuleButton1, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.newRuleButton1.text")); // NOI18N @@ -100,20 +109,6 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme jScrollPane4.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(204, 204, 204))); - rulesTableModel = new javax.swing.table.DefaultTableModel( - new Object [][] { - - }, - new String [] { - "Mime type/Extension", "Application" - } - ) { - @Override - public boolean isCellEditable(int i, int i1) { - return false; - } - }; - jTable1.setModel(rulesTableModel); jScrollPane4.setViewportView(jTable1); if (jTable1.getColumnModel().getColumnCount() > 0) { jTable1.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title0")); // NOI18N @@ -175,21 +170,17 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme .addContainerGap()) ); - jTextField1.setText(org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jTextField1.text")); // NOI18N - jTextField1.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jTextField1ActionPerformed(evt); - } - }); + HxDPath.setEditable(false); + HxDPath.setText(org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.HxDPath.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jLabel1.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jLabel2.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jButton1.text")); // NOI18N - jButton1.addActionListener(new java.awt.event.ActionListener() { + org.openide.awt.Mnemonics.setLocalizedText(browseHxDDirectory, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.browseHxDDirectory.text")); // NOI18N + browseHxDDirectory.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton1ActionPerformed(evt); + browseHxDDirectoryActionPerformed(evt); } }); @@ -204,9 +195,9 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme .addGap(21, 21, 21) .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 441, Short.MAX_VALUE) + .addComponent(HxDPath, javax.swing.GroupLayout.DEFAULT_SIZE, 441, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(browseHxDDirectory, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)) ); jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -214,9 +205,9 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(HxDPath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jButton1)) + .addComponent(browseHxDDirectory)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); @@ -254,13 +245,24 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme ); }// //GEN-END:initComponents - private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_jButton1ActionPerformed - - private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField1ActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_jTextField1ActionPerformed + private void browseHxDDirectoryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseHxDDirectoryActionPerformed + JFileChooser fileWindow = new JFileChooser(); + fileWindow.setFileSelectionMode(JFileChooser.FILES_ONLY); + GeneralFilter exeFilter = new GeneralFilter(GeneralFilter.EXECUTABLE_EXTS, GeneralFilter.EXECUTABLE_DESC); + File HxDPathFile = new File(HxDPath.getText()); + if(HxDPathFile.exists() && HxDPathFile.canExecute()) { + fileWindow.setCurrentDirectory(new File(HxDPath.getText())); + } + fileWindow.setDragEnabled(false); + fileWindow.setFileFilter(exeFilter); + fileWindow.setMultiSelectionEnabled(false); + int returnVal = fileWindow.showSaveDialog(this); + if(returnVal == JFileChooser.APPROVE_OPTION) { + File HxDExecutable = fileWindow.getSelectedFile(); + HxDPath.setText(HxDExecutable.getAbsolutePath()); + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + } + }//GEN-LAST:event_browseHxDDirectoryActionPerformed private void newRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newRuleButtonActionPerformed AddExternalViewerRuleDialog dialog = new AddExternalViewerRuleDialog(); @@ -275,60 +277,135 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme JOptionPane.ERROR_MESSAGE); } else { rules.add(newRule); - updateRulesTableModel(); + rulesTableModel.fireTableDataChanged(); int index = rules.indexOf(newRule); + jTable1.getSelectionModel().clearSelection(); jTable1.getSelectionModel().setSelectionInterval(index, index); - enableButtons(); + checkButtons(); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); } } }//GEN-LAST:event_newRuleButtonActionPerformed private void editRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editRuleButtonActionPerformed - // TODO add your handling code here: + int selectedIndex = jTable1.convertRowIndexToModel(jTable1.getSelectedRow()); + ExternalViewerRule selectedRule = rulesTableModel.getRuleAt(selectedIndex); + AddExternalViewerRuleDialog dialog = new AddExternalViewerRuleDialog(selectedRule); + AddExternalViewerRuleDialog.BUTTON_PRESSED result = dialog.getResult(); + if (result == AddExternalViewerRuleDialog.BUTTON_PRESSED.OK) { + ExternalViewerRule newRule = dialog.getRule(); + // Only allow one association for each MIME type or extension. + if (rules.contains(newRule)) { + JOptionPane.showMessageDialog(this, + NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.ruleAlreadyExists.message"), + NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.ruleAlreadyExists.title"), + JOptionPane.ERROR_MESSAGE); + } else { + rules.set(selectedIndex, dialog.getRule()); + rulesTableModel.fireTableDataChanged(); + jTable1.getSelectionModel().clearSelection(); + int tableIndex = jTable1.convertRowIndexToView(selectedIndex); + jTable1.getSelectionModel().setSelectionInterval(tableIndex, tableIndex); + checkButtons(); + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + } + } }//GEN-LAST:event_editRuleButtonActionPerformed private void deleteRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteRuleButtonActionPerformed - // TODO add your handling code here: + ExternalViewerRule selectedRule = rulesTableModel.getRuleAt(jTable1.convertRowIndexToModel(jTable1.getSelectedRow())); + rules.remove(selectedRule); + rulesTableModel.fireTableDataChanged(); + jTable1.getSelectionModel().clearSelection(); + checkButtons(); + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_deleteRuleButtonActionPerformed @Override public void store() { ExternalViewerRulesManager.getInstance().setUserRules(rules); + ModuleSettings.setConfigSetting(MODULE_NAME, HXD_PATH_NAME, HxDPath.getText()); } @Override public void load() { rules = ExternalViewerRulesManager.getInstance().getUserRules(); - updateRulesTableModel(); - enableButtons(); + if(ModuleSettings.settingExists(MODULE_NAME, HXD_PATH_NAME)) { + HxDPath.setText(ModuleSettings.getConfigSetting(MODULE_NAME, HXD_PATH_NAME)); + } + rulesTableModel.fireTableDataChanged(); + checkButtons(); } /** * Enable edit and delete buttons if there is a rule selected. */ - private void enableButtons() { - boolean ruleIsSelected = jTable1.getSelectedRow() != -1; + private void checkButtons() { + boolean ruleIsSelected = jTable1.getRowCount() > 0; 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 updateRulesTableModel() { - Collections.sort(rules); - rules.forEach((rule) -> { - rulesTableModel.addRow(new Object[]{rule.getName(), rule.getExePath()}); - }); + private class RulesTableModel extends AbstractTableModel { + private final String[] columnNames; + + public RulesTableModel(String[] columnNames) { + this.columnNames = columnNames; + } + + public void addRule(ExternalViewerRule rule) { + rules.add(rule); + fireTableRowsInserted(rules.size()-1, rules.size()-1); + } + + @Override + public int getRowCount() { + return rules.size(); + } + + @Override + public String getColumnName(int columnIndex) { + return columnNames[columnIndex]; + } + + @Override + public Class getColumnClass(int columnIndex) { + return String.class; + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + if(columnIndex == 0) { + return rules.get(rowIndex).getName(); + } else { + return rules.get(rowIndex).getExePath(); + } + } + + public ExternalViewerRule getRuleAt(int rowIndex) { + return rules.get(rowIndex); + } + + @Override + public boolean isCellEditable(int rowIndex, int colIndex) { + return false; + } } // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JTextField HxDPath; + private javax.swing.JButton browseHxDDirectory; private javax.swing.JButton deleteRuleButton; private javax.swing.JButton editRuleButton; private javax.swing.JLabel externalViewerTitleLabel; - private javax.swing.JButton jButton1; private javax.swing.JButton jButton2; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; @@ -337,7 +414,6 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme private javax.swing.JPanel jPanel3; private javax.swing.JScrollPane jScrollPane4; private javax.swing.JTable jTable1; - private javax.swing.JTextField jTextField1; private javax.swing.JButton newRuleButton; private javax.swing.JButton newRuleButton1; // End of variables declaration//GEN-END:variables From 490ea446cda7e01f5bf3e4a4fbd8b3c0ba49910c Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Mon, 31 Dec 2018 14:47:39 -0500 Subject: [PATCH 04/18] HdXViewer capability has been added to the Hex Viewer --- .../autopsy/core/UserPreferences.java | 18 ++++++ .../autopsy/corecomponents/Bundle.properties | 30 ++++++++++ .../corecomponents/DataContentViewerHex.java | 35 +++++++---- .../autopsy/directorytree/Bundle.properties | 9 +-- .../ExternalViewerGlobalSettingsPanel.form | 3 - .../ExternalViewerGlobalSettingsPanel.java | 58 ++++++++++--------- 6 files changed, 105 insertions(+), 48 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index 2be9a9b447..bf4d5dc3c1 100644 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.core; +import java.nio.file.Paths; import org.sleuthkit.autopsy.coreutils.TextConverter; import java.util.prefs.BackingStoreException; import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo; @@ -75,6 +76,7 @@ public final class UserPreferences { public static final String SHOW_ONLY_CURRENT_USER_TAGS = "ShowOnlyCurrentUserTags"; public static final String HIDE_CENTRAL_REPO_COMMENTS_AND_OCCURRENCES = "HideCentralRepoCommentsAndOccurrences"; public static final String DISPLAY_TRANSLATED_NAMES = "DisplayTranslatedNames"; + public static final String HDX_EDITOR_PATH = "HdXEditorPath"; // Prevent instantiation. private UserPreferences() { @@ -471,4 +473,20 @@ public final class UserPreferences { public static void setLogFileCount(int count) { preferences.putInt(MAX_NUM_OF_LOG_FILE, count); } + + /** + * + * @param executablePath + */ + public static void setHdXEditorPath(String executablePath) { + preferences.put(HDX_EDITOR_PATH, executablePath); + } + + /** + * + * @return + */ + public static String getHdXEditorPath() { + return preferences.get(HDX_EDITOR_PATH, Paths.get("C:", "Program Files", "HxD", "HxD.exe").toString()); + } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 38f8388cc4..d91a751a1a 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -194,3 +194,33 @@ ViewPreferencesPanel.useBestViewerRadioButton.toolTipText=For example, change fr ViewPreferencesPanel.useBestViewerRadioButton.text=Change to the most specific file viewer ViewPreferencesPanel.fileNameTranslationColumnCheckbox.text=Add column in result viewer for file name translation DataContentViewerHex.launchHxDButton.text=Launch in HxD +ExternalViewerGlobalSettingsPanel.jButton2.text=jButton2 +ExternalViewerGlobalSettingsPanel.newRuleButton1.text=New Rule +ExternalViewerGlobalSettingsPanel.newRuleButton.text=New Rule +ExternalViewerGlobalSettingsPanel.browseHxDDirectory.text=Browse +ExternalViewerGlobalSettingsPanel.jLabel2.text=Set launchable content viewer extensions +ExternalViewerGlobalSettingsPanel.jLabel1.text=HxD Editor Path: +ExternalViewerGlobalSettingsPanel.editRuleButton.text=Edit Rule +ExternalViewerGlobalSettingsPanel.deleteRuleButton.text=Delete Rule +ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text=Set aplication viewer to use for files with specific mime types/extensions: +ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title1=Application +ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title0=Mime type/Extension +AddExternalViewerRulePanel.nameLabel.text=MIME type or extension +AddExternalViewerRulePanel.browseButton.text=Browse +AddExternalViewerRulePanel.exePathTextField.text= +AddExternalViewerRulePanel.exePathLabel.text=Path of the program to use for files with this type or extension +AddExternalViewerRulePanel.extRadioButton.text=Extension +AddExternalViewerRulePanel.mimeRadioButton.text=MIME type +AddExternalViewerRulePanel.nameTextField.text= +ExternalViewerGlobalSettingsPanel.jButton2.text_1=jButton2 +ExternalViewerGlobalSettingsPanel.newRuleButton1.text_1=New Rule +ExternalViewerGlobalSettingsPanel.newRuleButton.text_1=New Rule +ExternalViewerGlobalSettingsPanel.browseHxDDirectory.text_1=Browse +ExternalViewerGlobalSettingsPanel.jLabel2.text_1=Set launchable content viewer extensions +ExternalViewerGlobalSettingsPanel.jLabel1.text_1=HxD Editor Path: +ExternalViewerGlobalSettingsPanel.HxDPath.text=C:/Program Files/HxD/HxD.exe +ExternalViewerGlobalSettingsPanel.editRuleButton.text_1=Edit Rule +ExternalViewerGlobalSettingsPanel.deleteRuleButton.text_1=Delete Rule +ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text_1=Set aplication viewer to use for files with specific mime types/extensions: +ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title1_1=Application +ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title0_1=Mime type/Extension diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java index 8d855b7aa0..ddc6c8f43b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java @@ -32,13 +32,12 @@ import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.text.BadLocationException; import javax.swing.text.Utilities; -import org.openide.modules.InstalledFileLocator; import org.openide.nodes.Node; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; -import org.sleuthkit.autopsy.coreutils.ExecUtil; import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.DataConversion; import org.sleuthkit.datamodel.Content; @@ -356,22 +355,33 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont private void launchHxDButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_launchHxDButtonActionPerformed try { + File HdXExecutable = new File(UserPreferences.getHdXEditorPath()); + if(!HdXExecutable.exists() || !HdXExecutable.canExecute()) { + JOptionPane.showMessageDialog(null, "Unable to launch HxD Editor. " + + "Please set-up the HdX install location in Tools -> " + + "Options -> External Viewer"); + return; + } + String tempDirectory = Case.getCurrentCaseThrows().getTempDirectory(); File dataSourceInTempDirectory = Paths.get(tempDirectory, dataSource.getId() + dataSource.getName()).toFile(); ContentUtils.writeToFile(dataSource, dataSourceInTempDirectory); - String HdXExecutableToFind = Paths.get("HxD", "HxD64.exe").toString(); - File HdXExecutable = InstalledFileLocator.getDefault().locate(HdXExecutableToFind, DataContentViewerHex.class.getPackage().getName(), false); - if (null == HdXExecutable) { - throw new IOException(String.format("Could not find HdXExecutable at %s", HdXExecutableToFind)); + try { + ProcessBuilder launchHdXExecutable = new ProcessBuilder(); + launchHdXExecutable.command(String.format("\"%s\" \"%s\"", + HdXExecutable.getAbsolutePath(), + dataSourceInTempDirectory.getAbsolutePath())); + launchHdXExecutable.start(); + } catch (IOException ex) { + JOptionPane.showMessageDialog(null, "Unable to launch HxD Editor. " + + "Please set-up the HdX install location in Tools -> " + + "Options -> External Viewer"); + dataSourceInTempDirectory.delete(); } - - ProcessBuilder launchHdXExecutable = new ProcessBuilder(); - launchHdXExecutable.command(String.format("%s \"%s\"", HdXExecutable.getAbsolutePath(), dataSourceInTempDirectory.getAbsolutePath())); - ExecUtil.execute(launchHdXExecutable); } catch (NoCurrentCaseException | IOException ex) { - logger.log(Level.SEVERE, "Unable to launch HxD Editor", ex); - //TODO - Make pop-up appear saying there were problems attempting to launch editor + logger.log(Level.SEVERE, "Unable to copy file into temp directory", ex); + //Should we add a pop-up for this? } }//GEN-LAST:event_launchHxDButtonActionPerformed @@ -546,6 +556,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont goToPageLabel.setVisible(isVisible); goToOffsetTextField.setVisible(isVisible); goToOffsetLabel.setVisible(isVisible); + launchHxDButton.setVisible(isVisible); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties index 5857deb2b9..22ad15405a 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties @@ -124,12 +124,9 @@ ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title2_1=Title 3 ExternalViewerGlobalSettingsPanel.newRuleButton1.text=New Rule ExternalViewerGlobalSettingsPanel.editRuleButton.text=Edit Rule ExternalViewerGlobalSettingsPanel.deleteRuleButton.text=Delete Rule -ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text=Set aplication viewer to use for files with specific mime types/extensions: +ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text=Add your custom rules for external viewers: ExternalViewerGlobalSettingsPanel.newRuleButton.text=New Rule -ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title1=Application -ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title0=Mime type/Extension -ExternalViewerGlobalSettingsPanel.jLabel1.text=HxD Editor Path: ExternalViewerGlobalSettingsPanel.jButton2.text=jButton2 -ExternalViewerGlobalSettingsPanel.jLabel2.text=Set launchable content viewer extensions +ExternalViewerGlobalSettingsPanel.jLabel1.text=HxD Editor Path: ExternalViewerGlobalSettingsPanel.browseHxDDirectory.text=Browse -ExternalViewerGlobalSettingsPanel.HxDPath.text=C:/Program Files/HxD/HxD.exe +ExternalViewerGlobalSettingsPanel.jLabel2.text=Add content viewer extensions: diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form index b3d33e0b2b..5ca99ba3bf 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form @@ -282,9 +282,6 @@ - - - diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index 1903729ec5..4df9b933fd 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.directorytree; +import java.awt.Color; import java.io.File; import java.util.ArrayList; import javax.swing.JFileChooser; @@ -27,7 +28,7 @@ import javax.swing.table.AbstractTableModel; import org.openide.util.NbBundle; import org.netbeans.spi.options.OptionsPanelController; import org.sleuthkit.autopsy.casemodule.GeneralFilter; -import org.sleuthkit.autopsy.coreutils.ModuleSettings; +import org.sleuthkit.autopsy.core.UserPreferences; /** * An options panel for the user to create, edit, and delete associations for @@ -39,8 +40,6 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme private RulesTableModel rulesTableModel; private java.util.List rules; - private static final String MODULE_NAME = ExternalViewerGlobalSettingsPanel.class.getName(); - private static final String HXD_PATH_NAME = "HxDExecutablePath"; /** * Creates new form ExternalViewerGlobalSettingsPanel @@ -171,7 +170,6 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme ); HxDPath.setEditable(false); - HxDPath.setText(org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.HxDPath.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jLabel1.text")); // NOI18N @@ -245,25 +243,6 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme ); }// //GEN-END:initComponents - private void browseHxDDirectoryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseHxDDirectoryActionPerformed - JFileChooser fileWindow = new JFileChooser(); - fileWindow.setFileSelectionMode(JFileChooser.FILES_ONLY); - GeneralFilter exeFilter = new GeneralFilter(GeneralFilter.EXECUTABLE_EXTS, GeneralFilter.EXECUTABLE_DESC); - File HxDPathFile = new File(HxDPath.getText()); - if(HxDPathFile.exists() && HxDPathFile.canExecute()) { - fileWindow.setCurrentDirectory(new File(HxDPath.getText())); - } - fileWindow.setDragEnabled(false); - fileWindow.setFileFilter(exeFilter); - fileWindow.setMultiSelectionEnabled(false); - int returnVal = fileWindow.showSaveDialog(this); - if(returnVal == JFileChooser.APPROVE_OPTION) { - File HxDExecutable = fileWindow.getSelectedFile(); - HxDPath.setText(HxDExecutable.getAbsolutePath()); - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - } - }//GEN-LAST:event_browseHxDDirectoryActionPerformed - private void newRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newRuleButtonActionPerformed AddExternalViewerRuleDialog dialog = new AddExternalViewerRuleDialog(); AddExternalViewerRuleDialog.BUTTON_PRESSED result = dialog.getResult(); @@ -321,18 +300,43 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_deleteRuleButtonActionPerformed + private void browseHxDDirectoryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseHxDDirectoryActionPerformed + JFileChooser fileWindow = new JFileChooser(); + fileWindow.setFileSelectionMode(JFileChooser.FILES_ONLY); + GeneralFilter exeFilter = new GeneralFilter(GeneralFilter.EXECUTABLE_EXTS, GeneralFilter.EXECUTABLE_DESC); + File HxDPathFile = new File(HxDPath.getText()); + if(HxDPathFile.exists() && HxDPathFile.canExecute()) { + fileWindow.setCurrentDirectory(new File(HxDPath.getText())); + } + fileWindow.setDragEnabled(false); + fileWindow.setFileFilter(exeFilter); + fileWindow.setMultiSelectionEnabled(false); + int returnVal = fileWindow.showSaveDialog(this); + if(returnVal == JFileChooser.APPROVE_OPTION) { + File HxDExecutable = fileWindow.getSelectedFile(); + HxDPath.setForeground(Color.BLACK); + HxDPath.setText(HxDExecutable.getAbsolutePath()); + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + } + }//GEN-LAST:event_browseHxDDirectoryActionPerformed + @Override public void store() { ExternalViewerRulesManager.getInstance().setUserRules(rules); - ModuleSettings.setConfigSetting(MODULE_NAME, HXD_PATH_NAME, HxDPath.getText()); + UserPreferences.setHdXEditorPath(HxDPath.getText()); } @Override public void load() { rules = ExternalViewerRulesManager.getInstance().getUserRules(); - if(ModuleSettings.settingExists(MODULE_NAME, HXD_PATH_NAME)) { - HxDPath.setText(ModuleSettings.getConfigSetting(MODULE_NAME, HXD_PATH_NAME)); - } + String editorPath = UserPreferences.getHdXEditorPath(); + File HdXExecutable = new File(editorPath); + if(HdXExecutable.exists() || HdXExecutable.canExecute()) { + HxDPath.setText(editorPath); + } else { + HxDPath.setForeground(Color.RED); + HxDPath.setText(editorPath); + } rulesTableModel.fireTableDataChanged(); checkButtons(); } From ca54e9b570ad0ad93275e5fab283702c163a64cf Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Wed, 2 Jan 2019 13:50:25 -0500 Subject: [PATCH 05/18] Added 100% code coverage to new Table model class and 75% to existing panel --- .../ExternalViewerGlobalSettingsPanel.java | 126 +++------- ...xternalViewerGlobalSettingsTableModel.java | 85 +++++++ ...ExternalViewerGlobalSettingsPanelTest.java | 70 ++++++ ...nalViewerGlobalSettingsTableModelTest.java | 225 ++++++++++++++++++ 4 files changed, 412 insertions(+), 94 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java create mode 100755 Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java create mode 100755 Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index 4df9b933fd..bd369ab86b 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -19,12 +19,12 @@ package org.sleuthkit.autopsy.directorytree; import java.awt.Color; +import java.awt.event.ActionListener; import java.io.File; -import java.util.ArrayList; +import java.util.List; import javax.swing.JFileChooser; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import javax.swing.JOptionPane; -import javax.swing.table.AbstractTableModel; import org.openide.util.NbBundle; import org.netbeans.spi.options.OptionsPanelController; import org.sleuthkit.autopsy.casemodule.GeneralFilter; @@ -38,28 +38,34 @@ import org.sleuthkit.autopsy.core.UserPreferences; @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel implements OptionsPanel { - private RulesTableModel rulesTableModel; - private java.util.List rules; + private ExternalViewerGlobalSettingsTableModel tableModel; /** * Creates new form ExternalViewerGlobalSettingsPanel */ public ExternalViewerGlobalSettingsPanel() { + this(new ExternalViewerGlobalSettingsTableModel(new String[] {"Mime type/Extension", "Application"})); + } + + public ExternalViewerGlobalSettingsPanel(ExternalViewerGlobalSettingsTableModel tableModel) { initComponents(); - customizeComponents(); + this.tableModel = tableModel; + customizeComponents(tableModel); } /** * Initializes field variables. Adds a listener to the list of rules. */ - private void customizeComponents() { - rules = new ArrayList<>(); - rulesTableModel = new RulesTableModel(new String[] { - "Mime type/Extension", "Application"}); - jTable1.setModel(rulesTableModel); + private void customizeComponents(ExternalViewerGlobalSettingsTableModel tableModel) { + jTable1.setModel(tableModel); jTable1.setAutoCreateRowSorter(true); } - + + public void deleteRuleButtonClick(int selectedIndex) { + jTable1.getSelectionModel().setSelectionInterval(selectedIndex, selectedIndex); + deleteRuleButton.getListeners(ActionListener.class)[0].actionPerformed(null); + } + /** * 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 @@ -109,10 +115,6 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme jScrollPane4.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(204, 204, 204))); jScrollPane4.setViewportView(jTable1); - if (jTable1.getColumnModel().getColumnCount() > 0) { - jTable1.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title0")); // NOI18N - jTable1.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title1")); // NOI18N - } org.openide.awt.Mnemonics.setLocalizedText(externalViewerTitleLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text")); // NOI18N @@ -249,18 +251,14 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme if (result == AddExternalViewerRuleDialog.BUTTON_PRESSED.OK) { ExternalViewerRule newRule = dialog.getRule(); // Only allow one association for each MIME type or extension. - if (rules.contains(newRule)) { + if (tableModel.containsRule(newRule)) { JOptionPane.showMessageDialog(this, NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.ruleAlreadyExists.message"), NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.ruleAlreadyExists.title"), JOptionPane.ERROR_MESSAGE); } else { - rules.add(newRule); - rulesTableModel.fireTableDataChanged(); - int index = rules.indexOf(newRule); - jTable1.getSelectionModel().clearSelection(); - jTable1.getSelectionModel().setSelectionInterval(index, index); - checkButtons(); + tableModel.addRule(newRule); + enableButtons(); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); } } @@ -268,35 +266,28 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme private void editRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editRuleButtonActionPerformed int selectedIndex = jTable1.convertRowIndexToModel(jTable1.getSelectedRow()); - ExternalViewerRule selectedRule = rulesTableModel.getRuleAt(selectedIndex); + ExternalViewerRule selectedRule = tableModel.getRuleAt(selectedIndex); AddExternalViewerRuleDialog dialog = new AddExternalViewerRuleDialog(selectedRule); AddExternalViewerRuleDialog.BUTTON_PRESSED result = dialog.getResult(); if (result == AddExternalViewerRuleDialog.BUTTON_PRESSED.OK) { ExternalViewerRule newRule = dialog.getRule(); // Only allow one association for each MIME type or extension. - if (rules.contains(newRule)) { + if (tableModel.containsRule(newRule)) { JOptionPane.showMessageDialog(this, NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.ruleAlreadyExists.message"), NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.JOptionPane.ruleAlreadyExists.title"), JOptionPane.ERROR_MESSAGE); } else { - rules.set(selectedIndex, dialog.getRule()); - rulesTableModel.fireTableDataChanged(); - jTable1.getSelectionModel().clearSelection(); - int tableIndex = jTable1.convertRowIndexToView(selectedIndex); - jTable1.getSelectionModel().setSelectionInterval(tableIndex, tableIndex); - checkButtons(); + tableModel.setRule(selectedIndex, dialog.getRule()); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); } } }//GEN-LAST:event_editRuleButtonActionPerformed private void deleteRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteRuleButtonActionPerformed - ExternalViewerRule selectedRule = rulesTableModel.getRuleAt(jTable1.convertRowIndexToModel(jTable1.getSelectedRow())); - rules.remove(selectedRule); - rulesTableModel.fireTableDataChanged(); + tableModel.removeRule(jTable1.convertRowIndexToModel(jTable1.getSelectedRow())); jTable1.getSelectionModel().clearSelection(); - checkButtons(); + enableButtons(); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_deleteRuleButtonActionPerformed @@ -322,13 +313,14 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme @Override public void store() { - ExternalViewerRulesManager.getInstance().setUserRules(rules); + ExternalViewerRulesManager.getInstance().setUserRules(tableModel.getRules()); UserPreferences.setHdXEditorPath(HxDPath.getText()); } @Override public void load() { - rules = ExternalViewerRulesManager.getInstance().getUserRules(); + List rules = ExternalViewerRulesManager.getInstance().getUserRules(); + rules.forEach((rule) -> tableModel.addRule(rule)); String editorPath = UserPreferences.getHdXEditorPath(); File HdXExecutable = new File(editorPath); if(HdXExecutable.exists() || HdXExecutable.canExecute()) { @@ -336,72 +328,18 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme } else { HxDPath.setForeground(Color.RED); HxDPath.setText(editorPath); - } - rulesTableModel.fireTableDataChanged(); - checkButtons(); + } + enableButtons(); } /** * Enable edit and delete buttons if there is a rule selected. */ - private void checkButtons() { + boolean enableButtons() { boolean ruleIsSelected = jTable1.getRowCount() > 0; editRuleButton.setEnabled(ruleIsSelected); deleteRuleButton.setEnabled(ruleIsSelected); - } - - /** - * - */ - private class RulesTableModel extends AbstractTableModel { - private final String[] columnNames; - - public RulesTableModel(String[] columnNames) { - this.columnNames = columnNames; - } - - public void addRule(ExternalViewerRule rule) { - rules.add(rule); - fireTableRowsInserted(rules.size()-1, rules.size()-1); - } - - @Override - public int getRowCount() { - return rules.size(); - } - - @Override - public String getColumnName(int columnIndex) { - return columnNames[columnIndex]; - } - - @Override - public Class getColumnClass(int columnIndex) { - return String.class; - } - - @Override - public int getColumnCount() { - return columnNames.length; - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - if(columnIndex == 0) { - return rules.get(rowIndex).getName(); - } else { - return rules.get(rowIndex).getExePath(); - } - } - - public ExternalViewerRule getRuleAt(int rowIndex) { - return rules.get(rowIndex); - } - - @Override - public boolean isCellEditable(int rowIndex, int colIndex) { - return false; - } + return ruleIsSelected; } // Variables declaration - do not modify//GEN-BEGIN:variables diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java new file mode 100755 index 0000000000..31689a98f8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java @@ -0,0 +1,85 @@ +/* + * 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.ArrayList; +import java.util.List; +import javax.swing.table.AbstractTableModel; + +/** +* + */ +class ExternalViewerGlobalSettingsTableModel extends AbstractTableModel { + + private final ArrayList rules; + private final String[] columnNames; + + public ExternalViewerGlobalSettingsTableModel(String[] columnNames) { + this.columnNames = columnNames; + this.rules = new ArrayList<>(); + } + + public void addRule(ExternalViewerRule rule) { + rules.add(rule); + fireTableRowsInserted(getRowCount() - 1, getRowCount() - 1); + } + + @Override + public int getRowCount() { + return rules.size(); + } + + @Override + public String getColumnName(int columnIndex) { + return columnNames[columnIndex]; + } + + @Override + public Class getColumnClass(int columnIndex) { + return String.class; + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + if (columnIndex == 0) { + return rules.get(rowIndex).getName(); + } else { + return rules.get(rowIndex).getExePath(); + } + } + + public ExternalViewerRule getRuleAt(int rowIndex) { + return rules.get(rowIndex); + } + + public void setRule(int rowIndex, ExternalViewerRule rule) { + rules.set(rowIndex, rule); + fireTableDataChanged(); + } + + public void removeRule(int rowIndex) { + rules.remove(rowIndex); + fireTableDataChanged(); + } + + @Override + public boolean isCellEditable(int rowIndex, int colIndex) { + return false; + } + + public List getRules() { + return rules; + } + + public boolean containsRule(ExternalViewerRule rule) { + return rules.contains(rule); + } +} diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java new file mode 100755 index 0000000000..51ca1aa287 --- /dev/null +++ b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java @@ -0,0 +1,70 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 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.directorytree; + +import junit.framework.Assert; +import org.junit.Test; +import org.sleuthkit.autopsy.directorytree.ExternalViewerRule.RuleType; + +public class ExternalViewerGlobalSettingsPanelTest { + + static final String[] testColumnNames = {"A", "B"}; + + public ExternalViewerGlobalSettingsPanelTest(){ + } + + @Test + public void testEnableButtons() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + ExternalViewerGlobalSettingsPanel panel = new ExternalViewerGlobalSettingsPanel(testModel); + Assert.assertFalse(panel.enableButtons()); + + testModel.addRule(new ExternalViewerRule("image/png", "fake.exe", RuleType.MIME)); + + Assert.assertTrue(panel.enableButtons()); + } + + @Test + public void testDisableButtons() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + ExternalViewerGlobalSettingsPanel panel = new ExternalViewerGlobalSettingsPanel(testModel); + + testModel.addRule(new ExternalViewerRule("image/png", "fake.exe", RuleType.MIME)); + Assert.assertTrue(panel.enableButtons()); + + testModel.removeRule(0); + Assert.assertFalse(panel.enableButtons()); + } + + @Test + public void testDeleteRuleButtonClick() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + ExternalViewerGlobalSettingsPanel testPanel = new ExternalViewerGlobalSettingsPanel(testModel); + Assert.assertFalse(testPanel.enableButtons()); + + testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + Assert.assertTrue(testPanel.enableButtons()); + Assert.assertEquals(1, testModel.getRowCount()); + + testPanel.deleteRuleButtonClick(0); + + Assert.assertFalse(testPanel.enableButtons()); + Assert.assertEquals(0, testModel.getRowCount()); + } +} diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java new file mode 100755 index 0000000000..f59e400910 --- /dev/null +++ b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java @@ -0,0 +1,225 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 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.directorytree; + +import java.util.List; +import junit.framework.Assert; +import org.junit.Test; +import org.sleuthkit.autopsy.directorytree.ExternalViewerRule.RuleType; + +/** + * + * @author dsmyda + */ +public class ExternalViewerGlobalSettingsTableModelTest { + + static final String[] testColumnNames = {"A", "B"}; + + public ExternalViewerGlobalSettingsTableModelTest() { + } + + /** + * Test of addRule method, of class ExternalViewerGlobalSettingsTableModel. + */ + @Test + public void testAddRule() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + testModel.addRule(new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); + + List rules = testModel.getRules(); + Assert.assertEquals(1, rules.size()); + + ExternalViewerRule rule = rules.get(0); + Assert.assertEquals("image/png", rule.getName()); + Assert.assertEquals("test.exe", rule.getExePath()); + Assert.assertEquals(RuleType.MIME, rule.getRuleType()); + } + + /** + * Test of getRowCount method, of class ExternalViewerGlobalSettingsTableModel. + */ + @Test + public void testGetRowCount() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + Assert.assertEquals(0, testModel.getRowCount()); + + testModel.addRule(new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); + testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + testModel.addRule(new ExternalViewerRule(".wav", "video.exe", RuleType.EXT)); + + Assert.assertEquals(3, testModel.getRowCount()); + } + + /** + * Test of getColumnName method, of class ExternalViewerGlobalSettingsTableModel. + */ + @Test + public void testGetColumnName() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + Assert.assertEquals("A", testModel.getColumnName(0)); + Assert.assertEquals("B", testModel.getColumnName(1)); + } + + @Test(expected = ArrayIndexOutOfBoundsException.class) + public void testColumnNameOutOfBounds() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + testModel.getColumnName(2); + } + + /** + * Test of getColumnClass method, of class ExternalViewerGlobalSettingsTableModel. + */ + @Test + public void testGetColumnClass() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + Assert.assertEquals(String.class, testModel.getColumnClass(0)); + } + + /** + * Test of getColumnCount method, of class ExternalViewerGlobalSettingsTableModel. + */ + @Test + public void testGetColumnCount() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + Assert.assertEquals(2, testModel.getColumnCount()); + ExternalViewerGlobalSettingsTableModel testModelTwo = new ExternalViewerGlobalSettingsTableModel(new String[] {"A", "B", "C", "D", "E"}); + Assert.assertEquals(5, testModelTwo.getColumnCount()); + } + + /** + * Test of getValueAt method, of class ExternalViewerGlobalSettingsTableModel. + */ + @Test + public void testGetValueAt() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + testModel.addRule(new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); + testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + testModel.addRule(new ExternalViewerRule(".wav", "video.exe", RuleType.EXT)); + + Assert.assertEquals(".txt", testModel.getValueAt(1,0)); + Assert.assertEquals("notepad.exe", testModel.getValueAt(1,1)); + Assert.assertEquals("image/png", testModel.getValueAt(0,0)); + Assert.assertEquals("test.exe", testModel.getValueAt(0,1)); + } + + /** + * Test of getRuleAt method, of class ExternalViewerGlobalSettingsTableModel. + */ + @Test + public void testGetRuleAt() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + testModel.addRule(new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); + testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + testModel.addRule(new ExternalViewerRule(".wav", "video.exe", RuleType.EXT)); + + ExternalViewerRule rule = testModel.getRuleAt(1); + Assert.assertEquals(".txt", rule.getName()); + Assert.assertEquals("notepad.exe", rule.getExePath()); + Assert.assertEquals(RuleType.EXT, rule.getRuleType()); + + ExternalViewerRule ruleTwo = testModel.getRuleAt(0); + Assert.assertEquals("image/png", ruleTwo.getName()); + Assert.assertEquals("test.exe", ruleTwo.getExePath()); + Assert.assertEquals(RuleType.MIME, ruleTwo.getRuleType()); + } + + /** + * Test of setRule method, of class ExternalViewerGlobalSettingsTableModel. + */ + @Test + public void testSetRule() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + testModel.addRule(new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); + testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + testModel.addRule(new ExternalViewerRule(".wav", "video.exe", RuleType.EXT)); + + testModel.setRule(0, new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + ExternalViewerRule rule = testModel.getRuleAt(1); + Assert.assertEquals(".txt", rule.getName()); + Assert.assertEquals("notepad.exe", rule.getExePath()); + Assert.assertEquals(RuleType.EXT, rule.getRuleType()); + + testModel.setRule(2, new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); + ExternalViewerRule ruleTwo = testModel.getRuleAt(2); + Assert.assertEquals("image/png", ruleTwo.getName()); + Assert.assertEquals("test.exe", ruleTwo.getExePath()); + Assert.assertEquals(RuleType.MIME, ruleTwo.getRuleType()); + } + + /** + * Test of removeRule method, of class ExternalViewerGlobalSettingsTableModel. + */ + @Test + public void testRemoveRule() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + ExternalViewerRule rule = new ExternalViewerRule("image/png", "test.ext", RuleType.MIME); + testModel.addRule(rule); + Assert.assertEquals(1, testModel.getRules().size()); + + testModel.removeRule(0); + Assert.assertEquals(0, testModel.getRules().size()); + Assert.assertFalse(testModel.containsRule(rule)); + } + + /** + * Test of isCellEditable method, of class ExternalViewerGlobalSettingsTableModel. + */ + @Test + public void testIsCellEditable() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + Assert.assertFalse(testModel.isCellEditable(0, 0)); + } + + /** + * Test of getRules method, of class ExternalViewerGlobalSettingsTableModel. + */ + @Test + public void testGetRules() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + Assert.assertNotNull(testModel.getRules()); + Assert.assertEquals(0, testModel.getRules().size()); + + testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + Assert.assertEquals(1, testModel.getRules().size()); + ExternalViewerRule rule = testModel.getRuleAt(0); + Assert.assertEquals(".txt", rule.getName()); + Assert.assertEquals("notepad.exe", rule.getExePath()); + Assert.assertEquals(RuleType.EXT, rule.getRuleType()); + } + + /** + * Test of containsRule method, of class ExternalViewerGlobalSettingsTableModel. + */ + @Test + public void testContainsRule() { + ExternalViewerRule rule = new ExternalViewerRule("image/png", "test.exe", RuleType.MIME); + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + testModel.addRule(rule); + Assert.assertTrue(testModel.containsRule(rule)); + } + + @Test + public void testNotContains() { + ExternalViewerRule rule = new ExternalViewerRule("image/png", "test.exe", RuleType.MIME); + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + testModel.addRule(rule); + Assert.assertFalse(testModel.containsRule(new ExternalViewerRule("not", "a rule", RuleType.EXT))); + Assert.assertFalse(testModel.containsRule(null)); + } +} \ No newline at end of file From 8afeb39a0039b5cb7b8303d2c85fd184bdaa5a4e Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Wed, 2 Jan 2019 14:30:11 -0500 Subject: [PATCH 06/18] Added some comments to Table Model and Panel --- .../autopsy/directorytree/Bundle.properties | 4 +- .../ExternalViewerGlobalSettingsPanel.form | 22 ++--- .../ExternalViewerGlobalSettingsPanel.java | 63 +++++++----- ...xternalViewerGlobalSettingsTableModel.java | 97 +++++++++++++++++-- ...ExternalViewerGlobalSettingsPanelTest.java | 3 + ...nalViewerGlobalSettingsTableModelTest.java | 30 +----- 6 files changed, 148 insertions(+), 71 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties index 22ad15405a..c1939adf6c 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties @@ -127,6 +127,6 @@ ExternalViewerGlobalSettingsPanel.deleteRuleButton.text=Delete Rule ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text=Add your custom rules for external viewers: ExternalViewerGlobalSettingsPanel.newRuleButton.text=New Rule ExternalViewerGlobalSettingsPanel.jButton2.text=jButton2 -ExternalViewerGlobalSettingsPanel.jLabel1.text=HxD Editor Path: ExternalViewerGlobalSettingsPanel.browseHxDDirectory.text=Browse -ExternalViewerGlobalSettingsPanel.jLabel2.text=Add content viewer extensions: +ExternalViewerGlobalSettingsPanel.HxDLabel.text=HxD Editor Path: +ExternalViewerGlobalSettingsPanel.ContentViewerExtensionLabel.text=Add content viewer extensions: diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form index 5ca99ba3bf..7a6fc16278 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form @@ -167,20 +167,20 @@ - + - <ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + <ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.ExternalViewerRulesTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - <ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + <ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.ExternalViewerRulesTable.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> @@ -250,12 +250,12 @@ - + - + @@ -266,11 +266,11 @@ - + - + @@ -284,17 +284,17 @@ - + - + - + - + diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index bd369ab86b..47f58a520e 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.directorytree; import java.awt.Color; import java.awt.event.ActionListener; import java.io.File; +import java.util.ArrayList; import java.util.List; import javax.swing.JFileChooser; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; @@ -40,13 +41,13 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme private ExternalViewerGlobalSettingsTableModel tableModel; - /** - * Creates new form ExternalViewerGlobalSettingsPanel - */ public ExternalViewerGlobalSettingsPanel() { this(new ExternalViewerGlobalSettingsTableModel(new String[] {"Mime type/Extension", "Application"})); } + /** + * Creates new form ExternalViewerGlobalSettingsPanel + */ public ExternalViewerGlobalSettingsPanel(ExternalViewerGlobalSettingsTableModel tableModel) { initComponents(); this.tableModel = tableModel; @@ -57,12 +58,17 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme * Initializes field variables. Adds a listener to the list of rules. */ private void customizeComponents(ExternalViewerGlobalSettingsTableModel tableModel) { - jTable1.setModel(tableModel); - jTable1.setAutoCreateRowSorter(true); + ExternalViewerRulesTable.setModel(tableModel); + ExternalViewerRulesTable.setAutoCreateRowSorter(true); } + /** + * Simulate the delete rule button click action. + * + * @param selectedIndex Index to delete in JTable + */ public void deleteRuleButtonClick(int selectedIndex) { - jTable1.getSelectionModel().setSelectionInterval(selectedIndex, selectedIndex); + ExternalViewerRulesTable.getSelectionModel().setSelectionInterval(selectedIndex, selectedIndex); deleteRuleButton.getListeners(ActionListener.class)[0].actionPerformed(null); } @@ -81,14 +87,14 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme jPanel2 = new javax.swing.JPanel(); newRuleButton = new javax.swing.JButton(); jScrollPane4 = new javax.swing.JScrollPane(); - jTable1 = new javax.swing.JTable(); + ExternalViewerRulesTable = new javax.swing.JTable(); externalViewerTitleLabel = new javax.swing.JLabel(); deleteRuleButton = new javax.swing.JButton(); editRuleButton = new javax.swing.JButton(); jPanel3 = new javax.swing.JPanel(); HxDPath = new javax.swing.JTextField(); - jLabel1 = new javax.swing.JLabel(); - jLabel2 = new javax.swing.JLabel(); + HxDLabel = new javax.swing.JLabel(); + ContentViewerExtensionLabel = new javax.swing.JLabel(); browseHxDDirectory = new javax.swing.JButton(); newRuleButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N @@ -114,7 +120,11 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme jScrollPane4.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(204, 204, 204))); - jScrollPane4.setViewportView(jTable1); + jScrollPane4.setViewportView(ExternalViewerRulesTable); + if (ExternalViewerRulesTable.getColumnModel().getColumnCount() > 0) { + ExternalViewerRulesTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.ExternalViewerRulesTable.columnModel.title0")); // NOI18N + ExternalViewerRulesTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.ExternalViewerRulesTable.columnModel.title1")); // NOI18N + } org.openide.awt.Mnemonics.setLocalizedText(externalViewerTitleLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text")); // NOI18N @@ -173,9 +183,9 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme HxDPath.setEditable(false); - org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jLabel1.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(HxDLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.HxDLabel.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.jLabel2.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(ContentViewerExtensionLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.ContentViewerExtensionLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(browseHxDDirectory, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.browseHxDDirectory.text")); // NOI18N browseHxDDirectory.addActionListener(new java.awt.event.ActionListener() { @@ -189,11 +199,11 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme jPanel3Layout.setHorizontalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel3Layout.createSequentialGroup() - .addComponent(jLabel2) + .addComponent(ContentViewerExtensionLabel) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGroup(jPanel3Layout.createSequentialGroup() .addGap(21, 21, 21) - .addComponent(jLabel1) + .addComponent(HxDLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(HxDPath, javax.swing.GroupLayout.DEFAULT_SIZE, 441, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -202,11 +212,11 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel3Layout.createSequentialGroup() - .addComponent(jLabel2) + .addComponent(ContentViewerExtensionLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(HxDPath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(HxDLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(browseHxDDirectory)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); @@ -265,7 +275,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme }//GEN-LAST:event_newRuleButtonActionPerformed private void editRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editRuleButtonActionPerformed - int selectedIndex = jTable1.convertRowIndexToModel(jTable1.getSelectedRow()); + int selectedIndex = ExternalViewerRulesTable.convertRowIndexToModel(ExternalViewerRulesTable.getSelectedRow()); ExternalViewerRule selectedRule = tableModel.getRuleAt(selectedIndex); AddExternalViewerRuleDialog dialog = new AddExternalViewerRuleDialog(selectedRule); AddExternalViewerRuleDialog.BUTTON_PRESSED result = dialog.getResult(); @@ -285,8 +295,8 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme }//GEN-LAST:event_editRuleButtonActionPerformed private void deleteRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteRuleButtonActionPerformed - tableModel.removeRule(jTable1.convertRowIndexToModel(jTable1.getSelectedRow())); - jTable1.getSelectionModel().clearSelection(); + tableModel.removeRule(ExternalViewerRulesTable.convertRowIndexToModel(ExternalViewerRulesTable.getSelectedRow())); + ExternalViewerRulesTable.getSelectionModel().clearSelection(); enableButtons(); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_deleteRuleButtonActionPerformed @@ -313,7 +323,12 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme @Override public void store() { - ExternalViewerRulesManager.getInstance().setUserRules(tableModel.getRules()); + //Dump rules from table model into a list to be stored by the rules manager. + List rules = new ArrayList<>(); + for(int i = 0; i < tableModel.getRowCount(); i++) { + rules.add(tableModel.getRuleAt(i)); + } + ExternalViewerRulesManager.getInstance().setUserRules(rules); UserPreferences.setHdXEditorPath(HxDPath.getText()); } @@ -336,26 +351,26 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme * Enable edit and delete buttons if there is a rule selected. */ boolean enableButtons() { - boolean ruleIsSelected = jTable1.getRowCount() > 0; + boolean ruleIsSelected = ExternalViewerRulesTable.getRowCount() > 0; editRuleButton.setEnabled(ruleIsSelected); deleteRuleButton.setEnabled(ruleIsSelected); return ruleIsSelected; } // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel ContentViewerExtensionLabel; + private javax.swing.JTable ExternalViewerRulesTable; + private javax.swing.JLabel HxDLabel; private javax.swing.JTextField HxDPath; private javax.swing.JButton browseHxDDirectory; private javax.swing.JButton deleteRuleButton; private javax.swing.JButton editRuleButton; private javax.swing.JLabel externalViewerTitleLabel; private javax.swing.JButton jButton2; - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel2; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel2; private javax.swing.JPanel jPanel3; private javax.swing.JScrollPane jScrollPane4; - private javax.swing.JTable jTable1; private javax.swing.JButton newRuleButton; private javax.swing.JButton newRuleButton1; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java index 31689a98f8..424c12d4d3 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java @@ -1,16 +1,29 @@ /* - * 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. + * Autopsy Forensic Browser + * + * Copyright 2018 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.directorytree; import java.util.ArrayList; -import java.util.List; import javax.swing.table.AbstractTableModel; /** -* + * Model that stores the External Viewer rules for Mime types and extensions. + * Located at Tools -> Options -> External Viewer */ class ExternalViewerGlobalSettingsTableModel extends AbstractTableModel { @@ -22,31 +35,68 @@ class ExternalViewerGlobalSettingsTableModel extends AbstractTableModel { this.rules = new ArrayList<>(); } + /** + * Stores a new external viewer rule. + * + * @param rule User-inputted rule + */ public void addRule(ExternalViewerRule rule) { rules.add(rule); fireTableRowsInserted(getRowCount() - 1, getRowCount() - 1); } + /** + * Returns the number of rules stored in this model. + * + * @return Integer denoting row count in table model + */ @Override public int getRowCount() { return rules.size(); } + /** + * Returns the column name at the given index. + * + * @param columnIndex + * + * @return Column name + */ @Override public String getColumnName(int columnIndex) { return columnNames[columnIndex]; } + /** + * Retrieves column class type. As for now, this is only type string. + * + * @param columnIndex + * + * @return String.class + */ @Override public Class getColumnClass(int columnIndex) { return String.class; } + /** + * Retrieves the number of columns in this table model. + * + * @return Integer denoting column count + */ @Override public int getColumnCount() { return columnNames.length; } + /** + * Retrieves value at a given row and column in the table. + * + * @param rowIndex Desired row index + * @param columnIndex Desired column index + * + * @return A generic pointer to the underlying data. + */ @Override public Object getValueAt(int rowIndex, int columnIndex) { if (columnIndex == 0) { @@ -56,29 +106,58 @@ class ExternalViewerGlobalSettingsTableModel extends AbstractTableModel { } } + /** + * Gets an entire rule instance from a given index. + * + * @param rowIndex Desired row + * + * @return User-inputted rule at the desired rowIndex + */ public ExternalViewerRule getRuleAt(int rowIndex) { return rules.get(rowIndex); } + /** + * Replaces an existing rule in the table. + * + * @param rowIndex Desired row index + * @param rule New rule to overwrite the old. + */ public void setRule(int rowIndex, ExternalViewerRule rule) { rules.set(rowIndex, rule); fireTableDataChanged(); } + /** + * Removes the rule from the table model. + * + * @param rowIndex Desired row index to delete + */ public void removeRule(int rowIndex) { rules.remove(rowIndex); fireTableDataChanged(); } + /** + * This table model is not editable. + * + * @param rowIndex + * @param colIndex + * + * @return False + */ @Override public boolean isCellEditable(int rowIndex, int colIndex) { return false; } - public List getRules() { - return rules; - } - + /** + * Tests containment of a given rule in the table model. + * + * @param rule Rule in question + * + * @return + */ public boolean containsRule(ExternalViewerRule rule) { return rules.contains(rule); } diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java index 51ca1aa287..07c09f89e1 100755 --- a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java @@ -22,6 +22,9 @@ import junit.framework.Assert; import org.junit.Test; import org.sleuthkit.autopsy.directorytree.ExternalViewerRule.RuleType; +/** + * 72% code coverage of ExternalViewerGlobalSettingsPanel + */ public class ExternalViewerGlobalSettingsPanelTest { static final String[] testColumnNames = {"A", "B"}; diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java index f59e400910..341143e0b5 100755 --- a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java @@ -18,14 +18,12 @@ */ package org.sleuthkit.autopsy.directorytree; -import java.util.List; import junit.framework.Assert; import org.junit.Test; import org.sleuthkit.autopsy.directorytree.ExternalViewerRule.RuleType; /** - * - * @author dsmyda + * 100% code coverage of ExternalViewerGlobalSettingsTableModel */ public class ExternalViewerGlobalSettingsTableModelTest { @@ -42,10 +40,9 @@ public class ExternalViewerGlobalSettingsTableModelTest { ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); testModel.addRule(new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); - List rules = testModel.getRules(); - Assert.assertEquals(1, rules.size()); + Assert.assertEquals(1, testModel.getRowCount()); - ExternalViewerRule rule = rules.get(0); + ExternalViewerRule rule = testModel.getRuleAt(0); Assert.assertEquals("image/png", rule.getName()); Assert.assertEquals("test.exe", rule.getExePath()); Assert.assertEquals(RuleType.MIME, rule.getRuleType()); @@ -170,10 +167,10 @@ public class ExternalViewerGlobalSettingsTableModelTest { ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); ExternalViewerRule rule = new ExternalViewerRule("image/png", "test.ext", RuleType.MIME); testModel.addRule(rule); - Assert.assertEquals(1, testModel.getRules().size()); + Assert.assertEquals(1, testModel.getRowCount()); testModel.removeRule(0); - Assert.assertEquals(0, testModel.getRules().size()); + Assert.assertEquals(0, testModel.getRowCount()); Assert.assertFalse(testModel.containsRule(rule)); } @@ -186,23 +183,6 @@ public class ExternalViewerGlobalSettingsTableModelTest { Assert.assertFalse(testModel.isCellEditable(0, 0)); } - /** - * Test of getRules method, of class ExternalViewerGlobalSettingsTableModel. - */ - @Test - public void testGetRules() { - ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); - Assert.assertNotNull(testModel.getRules()); - Assert.assertEquals(0, testModel.getRules().size()); - - testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); - Assert.assertEquals(1, testModel.getRules().size()); - ExternalViewerRule rule = testModel.getRuleAt(0); - Assert.assertEquals(".txt", rule.getName()); - Assert.assertEquals("notepad.exe", rule.getExePath()); - Assert.assertEquals(RuleType.EXT, rule.getRuleType()); - } - /** * Test of containsRule method, of class ExternalViewerGlobalSettingsTableModel. */ From bb80bfde1542fd9366908da92a6678acebc12ddd Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Wed, 2 Jan 2019 14:42:56 -0500 Subject: [PATCH 07/18] Commented new methods in UserPreferences --- Core/src/org/sleuthkit/autopsy/core/UserPreferences.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index bf4d5dc3c1..f96cd05969 100644 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -475,16 +475,19 @@ public final class UserPreferences { } /** + * Set the HdX path. * - * @param executablePath + * @param executablePath User-inputted path to HxD executable */ public static void setHdXEditorPath(String executablePath) { preferences.put(HDX_EDITOR_PATH, executablePath); } /** + * Retrieves the HdXEditor path set by the User. If not found, the default + * will be the default install location of HxD. * - * @return + * @return Path to HdX */ public static String getHdXEditorPath() { return preferences.get(HDX_EDITOR_PATH, Paths.get("C:", "Program Files", "HxD", "HxD.exe").toString()); From 9e3d5bbe1baad4379459b50ce1c9805f1b859730 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Wed, 2 Jan 2019 14:59:52 -0500 Subject: [PATCH 08/18] Disabled feature for non-windows machines --- .../autopsy/corecomponents/DataContentViewerHex.form | 9 ++++++--- .../autopsy/corecomponents/DataContentViewerHex.java | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form index 8c9b3c36a2..0b59085cb8 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form @@ -45,7 +45,7 @@ - + @@ -54,7 +54,7 @@ - + @@ -122,7 +122,7 @@ - + @@ -303,6 +303,9 @@ + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java index ddc6c8f43b..d8368d75fc 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java @@ -25,6 +25,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Paths; import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; @@ -231,7 +232,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(launchHxDButton) - .addContainerGap(39, Short.MAX_VALUE)) + .addContainerGap(146, Short.MAX_VALUE)) ); hexViewerPanelLayout.setVerticalGroup( hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -254,13 +255,15 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont .addGap(0, 0, 0)) ); + launchHxDButton.setEnabled(PlatformUtil.isWindowsOS()); + jScrollPane2.setViewportView(hexViewerPanel); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 686, Short.MAX_VALUE) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 827, Short.MAX_VALUE) .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) ); layout.setVerticalGroup( @@ -268,7 +271,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 267, Short.MAX_VALUE)) + .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 239, Short.MAX_VALUE)) ); }// //GEN-END:initComponents From 19adadf467a3c73e69fec58c3844d4e0c944cdb0 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Wed, 2 Jan 2019 15:01:42 -0500 Subject: [PATCH 09/18] Disabled browse button for choose exe path for non-windows machine --- .../directorytree/ExternalViewerGlobalSettingsPanel.form | 3 +++ .../directorytree/ExternalViewerGlobalSettingsPanel.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form index 7a6fc16278..fde8a99209 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form @@ -307,6 +307,9 @@ + + + diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index 47f58a520e..cb30626845 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -30,6 +30,7 @@ import org.openide.util.NbBundle; import org.netbeans.spi.options.OptionsPanelController; import org.sleuthkit.autopsy.casemodule.GeneralFilter; import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; /** * An options panel for the user to create, edit, and delete associations for @@ -221,6 +222,8 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); + browseHxDDirectory.setEnabled(PlatformUtil.isWindowsOS()); + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( From e3265d4b28e66b24b4e3a8de62f0c38eae7c0f4e Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Thu, 3 Jan 2019 08:53:57 -0500 Subject: [PATCH 10/18] Codacy suggestions, all but one because I don't agree with it. --- ...xternalViewerGlobalSettingsTableModel.java | 8 ++- ...ExternalViewerGlobalSettingsPanelTest.java | 4 ++ ...nalViewerGlobalSettingsTableModelTest.java | 58 +++++++++++-------- 3 files changed, 44 insertions(+), 26 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java index 424c12d4d3..5662e0cd84 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java @@ -19,6 +19,8 @@ package org.sleuthkit.autopsy.directorytree; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import javax.swing.table.AbstractTableModel; /** @@ -27,11 +29,11 @@ import javax.swing.table.AbstractTableModel; */ class ExternalViewerGlobalSettingsTableModel extends AbstractTableModel { - private final ArrayList rules; + private final List rules; private final String[] columnNames; - public ExternalViewerGlobalSettingsTableModel(String[] columnNames) { - this.columnNames = columnNames; + public ExternalViewerGlobalSettingsTableModel(String... columnNames) { + this.columnNames = Arrays.copyOf(columnNames, columnNames.length); this.rules = new ArrayList<>(); } diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java index 07c09f89e1..e24884e3b7 100755 --- a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java @@ -29,7 +29,11 @@ public class ExternalViewerGlobalSettingsPanelTest { static final String[] testColumnNames = {"A", "B"}; + /** + * Default constructor for JUnit + */ public ExternalViewerGlobalSettingsPanelTest(){ + //Codacy complains if there is no comment here } @Test diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java index 341143e0b5..72118c7e3e 100755 --- a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.directorytree; import junit.framework.Assert; +import org.junit.Before; import org.junit.Test; import org.sleuthkit.autopsy.directorytree.ExternalViewerRule.RuleType; @@ -28,8 +29,22 @@ import org.sleuthkit.autopsy.directorytree.ExternalViewerRule.RuleType; public class ExternalViewerGlobalSettingsTableModelTest { static final String[] testColumnNames = {"A", "B"}; + private ExternalViewerRule pngMime; + private ExternalViewerRule txtExt; + private ExternalViewerRule wavExt; + /** + * Initialize JUnit test + */ public ExternalViewerGlobalSettingsTableModelTest() { + //Empty constructor + } + + @Before + public void setUp() { + pngMime = new ExternalViewerRule("image/png", "test.exe", RuleType.MIME); + txtExt = new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT); + wavExt = new ExternalViewerRule(".wav", "video.exe", RuleType.EXT); } /** @@ -38,7 +53,7 @@ public class ExternalViewerGlobalSettingsTableModelTest { @Test public void testAddRule() { ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); - testModel.addRule(new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); + testModel.addRule(pngMime); Assert.assertEquals(1, testModel.getRowCount()); @@ -56,9 +71,9 @@ public class ExternalViewerGlobalSettingsTableModelTest { ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); Assert.assertEquals(0, testModel.getRowCount()); - testModel.addRule(new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); - testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); - testModel.addRule(new ExternalViewerRule(".wav", "video.exe", RuleType.EXT)); + testModel.addRule(pngMime); + testModel.addRule(txtExt); + testModel.addRule(wavExt); Assert.assertEquals(3, testModel.getRowCount()); } @@ -105,9 +120,9 @@ public class ExternalViewerGlobalSettingsTableModelTest { @Test public void testGetValueAt() { ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); - testModel.addRule(new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); - testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); - testModel.addRule(new ExternalViewerRule(".wav", "video.exe", RuleType.EXT)); + testModel.addRule(pngMime); + testModel.addRule(txtExt); + testModel.addRule(wavExt); Assert.assertEquals(".txt", testModel.getValueAt(1,0)); Assert.assertEquals("notepad.exe", testModel.getValueAt(1,1)); @@ -121,9 +136,9 @@ public class ExternalViewerGlobalSettingsTableModelTest { @Test public void testGetRuleAt() { ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); - testModel.addRule(new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); - testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); - testModel.addRule(new ExternalViewerRule(".wav", "video.exe", RuleType.EXT)); + testModel.addRule(pngMime); + testModel.addRule(txtExt); + testModel.addRule(wavExt); ExternalViewerRule rule = testModel.getRuleAt(1); Assert.assertEquals(".txt", rule.getName()); @@ -142,17 +157,17 @@ public class ExternalViewerGlobalSettingsTableModelTest { @Test public void testSetRule() { ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); - testModel.addRule(new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); - testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); - testModel.addRule(new ExternalViewerRule(".wav", "video.exe", RuleType.EXT)); + testModel.addRule(pngMime); + testModel.addRule(txtExt); + testModel.addRule(wavExt); - testModel.setRule(0, new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + testModel.setRule(0, txtExt); ExternalViewerRule rule = testModel.getRuleAt(1); Assert.assertEquals(".txt", rule.getName()); Assert.assertEquals("notepad.exe", rule.getExePath()); Assert.assertEquals(RuleType.EXT, rule.getRuleType()); - testModel.setRule(2, new ExternalViewerRule("image/png", "test.exe", RuleType.MIME)); + testModel.setRule(2, pngMime); ExternalViewerRule ruleTwo = testModel.getRuleAt(2); Assert.assertEquals("image/png", ruleTwo.getName()); Assert.assertEquals("test.exe", ruleTwo.getExePath()); @@ -165,13 +180,12 @@ public class ExternalViewerGlobalSettingsTableModelTest { @Test public void testRemoveRule() { ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); - ExternalViewerRule rule = new ExternalViewerRule("image/png", "test.ext", RuleType.MIME); - testModel.addRule(rule); + testModel.addRule(pngMime); Assert.assertEquals(1, testModel.getRowCount()); testModel.removeRule(0); Assert.assertEquals(0, testModel.getRowCount()); - Assert.assertFalse(testModel.containsRule(rule)); + Assert.assertFalse(testModel.containsRule(pngMime)); } /** @@ -188,17 +202,15 @@ public class ExternalViewerGlobalSettingsTableModelTest { */ @Test public void testContainsRule() { - ExternalViewerRule rule = new ExternalViewerRule("image/png", "test.exe", RuleType.MIME); ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); - testModel.addRule(rule); - Assert.assertTrue(testModel.containsRule(rule)); + testModel.addRule(pngMime); + Assert.assertTrue(testModel.containsRule(pngMime)); } @Test public void testNotContains() { - ExternalViewerRule rule = new ExternalViewerRule("image/png", "test.exe", RuleType.MIME); ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); - testModel.addRule(rule); + testModel.addRule(pngMime); Assert.assertFalse(testModel.containsRule(new ExternalViewerRule("not", "a rule", RuleType.EXT))); Assert.assertFalse(testModel.containsRule(null)); } From 1d5815030d3c16e55c11f78fff79bcc0e1798830 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Sat, 5 Jan 2019 01:51:57 -0500 Subject: [PATCH 11/18] Tweaked SevenZipExtractor; uncommented test. --- .../SevenZipExtractor.java | 4 +- .../autopsy/ingest/EmbeddedFileTest.java | 90 +++++++++---------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java index 8b55988fa7..1fb60cf0cb 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2018 Basis Technology Corp. + * Copyright 2013-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -258,7 +258,7 @@ class SevenZipExtractor { org.sleuthkit.datamodel.Blackboard tskBlackboard = tskCase.getBlackboard(); // Create artifact if it doesn't already exist. if (!tskBlackboard.artifactExists(archiveFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, attributes)) { - BlackboardArtifact artifact = archiveFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); + BlackboardArtifact artifact = rootArchive.getArchiveFile().newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); artifact.addAttributes(attributes); try { diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java index af9266b36f..25d691ddbc 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java @@ -90,51 +90,51 @@ public class EmbeddedFileTest extends NbTestCase { CaseUtils.closeCurrentCase(); } -// public void testEncryptionAndZipBomb() { -// try { -// List results = openCase.getSleuthkitCase().findAllFilesWhere("name LIKE '%%'"); -// final String zipBombSetName = "Possible Zip Bomb"; -// final String protectedName1 = "password_protected.zip"; -// final String protectedName2 = "level1_protected.zip"; -// final String protectedName3 = "42.zip"; -// final String depthZipBomb = "DepthTriggerZipBomb.zip"; -// final String ratioZipBomb = "RatioTriggerZipBomb.zip"; -// int zipBombs = 0; -// assertEquals("The number of files in the test image has changed", 2221, results.size()); -// int passwdProtectedZips = 0; -// for (AbstractFile file : results) { -// //.zip file has artifact TSK_ENCRYPTION_DETECTED -// if (file.getName().equalsIgnoreCase(protectedName1) || file.getName().equalsIgnoreCase(protectedName2) || file.getName().equalsIgnoreCase(protectedName3)) { -// ArrayList artifacts = file.getAllArtifacts(); -// assertEquals("Password protected zip file " + file.getName() + " has incorrect number of artifacts", 1, artifacts.size()); -// for (BlackboardArtifact artifact : artifacts) { -// assertEquals("Artifact for password protected zip file " + file.getName() + " has incorrect type ID", artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID()); -// passwdProtectedZips++; -// } -// } else if (file.getName().equalsIgnoreCase(depthZipBomb) || file.getName().equalsIgnoreCase(ratioZipBomb)) { -// ArrayList artifacts = file.getAllArtifacts(); -// assertEquals("Zip bomb " + file.getName() + " has incorrect number of artifacts", 1, artifacts.size()); -// for (BlackboardArtifact artifact : artifacts) { -// assertEquals("Artifact for Zip bomb " + file.getName() + " has incorrect type ID", artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()); -// BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)); -// assertNotNull("No attribute found for artifact on zip bomb " + file.getName(), attribute); -// assertEquals("Interesting artifact on file, " + file.getName() + ", does not reflect it being a zip bomb", zipBombSetName, attribute.getDisplayString()); -// zipBombs++; -// } -// } else {//No other files have artifact defined -// assertEquals("Unexpected file, " + file.getName() + ", has artifacts", 0, file.getAllArtifacts().size()); -// } -// -// } -// //Make sure 3 password protected zip files have been tested: password_protected.zip, level1_protected.zip and 42.zip that we download for bomb testing. -// assertEquals("Unexpected number of artifacts reflecting password protected zip files found", 3, passwdProtectedZips); -// //Make sure 2 zip bomb files have been tested: DepthTriggerZipBomb.zip and RatioTriggerZipBomb.zip. -// assertEquals("Unexpected number of artifacts reflecting zip bombs found", 2, zipBombs); -// } catch (TskCoreException ex) { -// Exceptions.printStackTrace(ex); -// Assert.fail(ex.getMessage()); -// } -// } + public void testEncryptionAndZipBomb() { + try { + List results = openCase.getSleuthkitCase().findAllFilesWhere("name LIKE '%%'"); + final String zipBombSetName = "Possible Zip Bomb"; + final String protectedName1 = "password_protected.zip"; + final String protectedName2 = "level1_protected.zip"; + final String protectedName3 = "42.zip"; + final String depthZipBomb = "DepthTriggerZipBomb.zip"; + final String ratioZipBomb = "RatioTriggerZipBomb.zip"; + int zipBombs = 0; + assertEquals("The number of files in the test image has changed", 2221, results.size()); + int passwdProtectedZips = 0; + for (AbstractFile file : results) { + //.zip file has artifact TSK_ENCRYPTION_DETECTED + if (file.getName().equalsIgnoreCase(protectedName1) || file.getName().equalsIgnoreCase(protectedName2) || file.getName().equalsIgnoreCase(protectedName3)) { + ArrayList artifacts = file.getAllArtifacts(); + assertEquals("Password protected zip file " + file.getName() + " has incorrect number of artifacts", 1, artifacts.size()); + for (BlackboardArtifact artifact : artifacts) { + assertEquals("Artifact for password protected zip file " + file.getName() + " has incorrect type ID", artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID()); + passwdProtectedZips++; + } + } else if (file.getName().equalsIgnoreCase(depthZipBomb) || file.getName().equalsIgnoreCase(ratioZipBomb)) { + ArrayList artifacts = file.getAllArtifacts(); + assertEquals("Zip bomb " + file.getName() + " has incorrect number of artifacts", 1, artifacts.size()); + for (BlackboardArtifact artifact : artifacts) { + assertEquals("Artifact for Zip bomb " + file.getName() + " has incorrect type ID", artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()); + BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)); + assertNotNull("No attribute found for artifact on zip bomb " + file.getName(), attribute); + assertEquals("Interesting artifact on file, " + file.getName() + ", does not reflect it being a zip bomb", zipBombSetName, attribute.getDisplayString()); + zipBombs++; + } + } else {//No other files have artifact defined + assertEquals("Unexpected file, " + file.getName() + ", has artifacts", 0, file.getAllArtifacts().size()); + } + + } + //Make sure 3 password protected zip files have been tested: password_protected.zip, level1_protected.zip and 42.zip that we download for bomb testing. + assertEquals("Unexpected number of artifacts reflecting password protected zip files found", 3, passwdProtectedZips); + //Make sure 2 zip bomb files have been tested: DepthTriggerZipBomb.zip and RatioTriggerZipBomb.zip. + assertEquals("Unexpected number of artifacts reflecting zip bombs found", 2, zipBombs); + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex.getMessage()); + } + } public void testBigFolder() { final int numOfFilesToTest = 1000; From 3dffd34d1837f7c87e2687c6d21a92c38f341405 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Mon, 7 Jan 2019 09:03:40 -0500 Subject: [PATCH 12/18] Review changes --- .../corecomponents/DataContentViewerHex.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java index d8368d75fc..861076505c 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java @@ -39,6 +39,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; +import static org.sleuthkit.autopsy.corecomponents.Bundle.*; import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.DataConversion; import org.sleuthkit.datamodel.Content; @@ -356,13 +357,13 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont } }//GEN-LAST:event_goToOffsetTextFieldActionPerformed + @NbBundle.Messages({"DataContentViewerHex.launchError=Unable to launch HxD Editor. " + + "Please set-up the HdX install location in Tools -> Options -> External Viewer"}) private void launchHxDButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_launchHxDButtonActionPerformed try { File HdXExecutable = new File(UserPreferences.getHdXEditorPath()); if(!HdXExecutable.exists() || !HdXExecutable.canExecute()) { - JOptionPane.showMessageDialog(null, "Unable to launch HxD Editor. " - + "Please set-up the HdX install location in Tools -> " - + "Options -> External Viewer"); + JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError()); return; } @@ -377,14 +378,12 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont dataSourceInTempDirectory.getAbsolutePath())); launchHdXExecutable.start(); } catch (IOException ex) { - JOptionPane.showMessageDialog(null, "Unable to launch HxD Editor. " - + "Please set-up the HdX install location in Tools -> " - + "Options -> External Viewer"); + JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError()); dataSourceInTempDirectory.delete(); } } catch (NoCurrentCaseException | IOException ex) { logger.log(Level.SEVERE, "Unable to copy file into temp directory", ex); - //Should we add a pop-up for this? + JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError()); } }//GEN-LAST:event_launchHxDButtonActionPerformed From d0eea2db857cb41953406e39cc9d4a49bae6eb6c Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Mon, 7 Jan 2019 09:31:52 -0500 Subject: [PATCH 13/18] External Rules bug fix --- .../directorytree/ExternalViewerGlobalSettingsPanel.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index cb30626845..704573fca9 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -43,7 +43,8 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme private ExternalViewerGlobalSettingsTableModel tableModel; public ExternalViewerGlobalSettingsPanel() { - this(new ExternalViewerGlobalSettingsTableModel(new String[] {"Mime type/Extension", "Application"})); + this(new ExternalViewerGlobalSettingsTableModel(new String[] { + "Mime type/Extension", "Application"})); } /** @@ -338,7 +339,11 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme @Override public void load() { List rules = ExternalViewerRulesManager.getInstance().getUserRules(); - rules.forEach((rule) -> tableModel.addRule(rule)); + for(ExternalViewerRule rule : rules) { + if(!tableModel.containsRule(rule)) { + tableModel.addRule(rule); + } + } String editorPath = UserPreferences.getHdXEditorPath(); File HdXExecutable = new File(editorPath); if(HdXExecutable.exists() || HdXExecutable.canExecute()) { From 3c24597fac87fca1e7cf9e97c02f78f9f14f7346 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 7 Jan 2019 12:00:31 -0500 Subject: [PATCH 14/18] Send event for verification failed artifact --- .../dataSourceIntegrity/DataSourceIntegrityIngestModule.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/modules/dataSourceIntegrity/DataSourceIntegrityIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/dataSourceIntegrity/DataSourceIntegrityIngestModule.java index 4389fe5bb7..fa8d70794a 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/dataSourceIntegrity/DataSourceIntegrityIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/dataSourceIntegrity/DataSourceIntegrityIngestModule.java @@ -32,6 +32,7 @@ import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType; import org.sleuthkit.autopsy.ingest.IngestServices; +import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.TskCoreException; @@ -300,6 +301,8 @@ public class DataSourceIntegrityIngestModule implements DataSourceIngestModule { BlackboardArtifact verificationFailedArtifact = Case.getCurrentCase().getSleuthkitCase().newBlackboardArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_VERIFICATION_FAILED, img.getId()); verificationFailedArtifact.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, DataSourceIntegrityModuleFactory.getModuleName(), artifactComment)); + IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(DataSourceIntegrityModuleFactory.getModuleName(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_VERIFICATION_FAILED)); } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Error creating verification failed artifact", ex); } From 6b2736a4ecca670ce8490b915aa33c8a373aeef0 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Tue, 8 Jan 2019 09:18:57 -0500 Subject: [PATCH 15/18] Bug fixes and update to tests --- .../corecomponents/DataContentViewerHex.java | 4 +++- .../ExternalViewerGlobalSettingsPanel.java | 21 +++++++++++++++++-- ...ExternalViewerGlobalSettingsPanelTest.java | 13 ++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java index 861076505c..db4fa74c6e 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java @@ -40,6 +40,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import static org.sleuthkit.autopsy.corecomponents.Bundle.*; +import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.DataConversion; import org.sleuthkit.datamodel.Content; @@ -368,7 +369,8 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont } String tempDirectory = Case.getCurrentCaseThrows().getTempDirectory(); - File dataSourceInTempDirectory = Paths.get(tempDirectory, dataSource.getId() + dataSource.getName()).toFile(); + File dataSourceInTempDirectory = Paths.get(tempDirectory, + FileUtil.escapeFileName(dataSource.getId() + dataSource.getName())).toFile(); ContentUtils.writeToFile(dataSource, dataSourceInTempDirectory); try { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index 704573fca9..a72a223a26 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -26,6 +26,8 @@ import java.util.List; import javax.swing.JFileChooser; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import javax.swing.JOptionPane; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; import org.openide.util.NbBundle; import org.netbeans.spi.options.OptionsPanelController; import org.sleuthkit.autopsy.casemodule.GeneralFilter; @@ -62,6 +64,12 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme private void customizeComponents(ExternalViewerGlobalSettingsTableModel tableModel) { ExternalViewerRulesTable.setModel(tableModel); ExternalViewerRulesTable.setAutoCreateRowSorter(true); + ExternalViewerRulesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + ListSelectionModel selectionModel = ExternalViewerRulesTable.getSelectionModel(); + + selectionModel.addListSelectionListener((ListSelectionEvent e) -> { + enableButtons(); + }); } /** @@ -70,9 +78,18 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme * @param selectedIndex Index to delete in JTable */ public void deleteRuleButtonClick(int selectedIndex) { - ExternalViewerRulesTable.getSelectionModel().setSelectionInterval(selectedIndex, selectedIndex); + selectRowIndex(selectedIndex); deleteRuleButton.getListeners(ActionListener.class)[0].actionPerformed(null); } + + /** + * Simulate selecting an entry in the JTable. + * + * @param rowIndex Index to select + */ + public void selectRowIndex(int rowIndex) { + ExternalViewerRulesTable.getSelectionModel().setSelectionInterval(rowIndex, rowIndex); + } /** * This method is called from within the constructor to initialize the form. @@ -359,7 +376,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme * Enable edit and delete buttons if there is a rule selected. */ boolean enableButtons() { - boolean ruleIsSelected = ExternalViewerRulesTable.getRowCount() > 0; + boolean ruleIsSelected = ExternalViewerRulesTable.getSelectedRow() >= 0; editRuleButton.setEnabled(ruleIsSelected); deleteRuleButton.setEnabled(ruleIsSelected); return ruleIsSelected; diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java index e24884e3b7..475d1cda5d 100755 --- a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java @@ -44,6 +44,8 @@ public class ExternalViewerGlobalSettingsPanelTest { testModel.addRule(new ExternalViewerRule("image/png", "fake.exe", RuleType.MIME)); + Assert.assertFalse(panel.enableButtons()); + panel.selectRowIndex(0); Assert.assertTrue(panel.enableButtons()); } @@ -53,6 +55,8 @@ public class ExternalViewerGlobalSettingsPanelTest { ExternalViewerGlobalSettingsPanel panel = new ExternalViewerGlobalSettingsPanel(testModel); testModel.addRule(new ExternalViewerRule("image/png", "fake.exe", RuleType.MIME)); + Assert.assertFalse(panel.enableButtons()); + panel.selectRowIndex(0); Assert.assertTrue(panel.enableButtons()); testModel.removeRule(0); @@ -66,6 +70,7 @@ public class ExternalViewerGlobalSettingsPanelTest { Assert.assertFalse(testPanel.enableButtons()); testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + testPanel.selectRowIndex(0); Assert.assertTrue(testPanel.enableButtons()); Assert.assertEquals(1, testModel.getRowCount()); @@ -74,4 +79,12 @@ public class ExternalViewerGlobalSettingsPanelTest { Assert.assertFalse(testPanel.enableButtons()); Assert.assertEquals(0, testModel.getRowCount()); } + + @Test(expected = IndexOutOfBoundsException.class) + public void testDeleteButtonClickFail() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + ExternalViewerGlobalSettingsPanel testPanel = new ExternalViewerGlobalSettingsPanel(testModel); + + testPanel.deleteRuleButtonClick(-1); + } } From dfbfeb6ea5106ade254a8cf21a3d06e6273ce947 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Tue, 8 Jan 2019 09:31:27 -0500 Subject: [PATCH 16/18] Added a test for ensuring single selection --- .../ExternalViewerGlobalSettingsPanel.java | 18 ++++++++++++--- ...ExternalViewerGlobalSettingsPanelTest.java | 23 ++++++++++++++++--- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index a72a223a26..ef0cc08b8f 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -78,17 +78,29 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme * @param selectedIndex Index to delete in JTable */ public void deleteRuleButtonClick(int selectedIndex) { - selectRowIndex(selectedIndex); + setSelectionInterval(selectedIndex, selectedIndex); deleteRuleButton.getListeners(ActionListener.class)[0].actionPerformed(null); } /** * Simulate selecting an entry in the JTable. * + * In single selection mode, only the endIndex is used. + * * @param rowIndex Index to select */ - public void selectRowIndex(int rowIndex) { - ExternalViewerRulesTable.getSelectionModel().setSelectionInterval(rowIndex, rowIndex); + public void setSelectionInterval(int startingIndex, int endIndex) { + ExternalViewerRulesTable.getSelectionModel().setSelectionInterval(startingIndex, endIndex); + } + + /** + * Tests whether the index is selected. + * + * @param index + * @return + */ + public boolean isSelected(int index) { + return ExternalViewerRulesTable.getSelectionModel().isSelectedIndex(index); } /** diff --git a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java index 475d1cda5d..cfbc5e0cf6 100755 --- a/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java +++ b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java @@ -45,7 +45,7 @@ public class ExternalViewerGlobalSettingsPanelTest { testModel.addRule(new ExternalViewerRule("image/png", "fake.exe", RuleType.MIME)); Assert.assertFalse(panel.enableButtons()); - panel.selectRowIndex(0); + panel.setSelectionInterval(0, 0); Assert.assertTrue(panel.enableButtons()); } @@ -56,7 +56,7 @@ public class ExternalViewerGlobalSettingsPanelTest { testModel.addRule(new ExternalViewerRule("image/png", "fake.exe", RuleType.MIME)); Assert.assertFalse(panel.enableButtons()); - panel.selectRowIndex(0); + panel.setSelectionInterval(0, 0); Assert.assertTrue(panel.enableButtons()); testModel.removeRule(0); @@ -70,7 +70,7 @@ public class ExternalViewerGlobalSettingsPanelTest { Assert.assertFalse(testPanel.enableButtons()); testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); - testPanel.selectRowIndex(0); + testPanel.setSelectionInterval(0, 0); Assert.assertTrue(testPanel.enableButtons()); Assert.assertEquals(1, testModel.getRowCount()); @@ -87,4 +87,21 @@ public class ExternalViewerGlobalSettingsPanelTest { testPanel.deleteRuleButtonClick(-1); } + + @Test + public void testSingleSelection() { + ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames); + ExternalViewerGlobalSettingsPanel testPanel = new ExternalViewerGlobalSettingsPanel(testModel); + testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + testModel.addRule(new ExternalViewerRule(".txt", "notepad.exe", RuleType.EXT)); + + testPanel.setSelectionInterval(0, 2); + + Assert.assertFalse(testPanel.isSelected(0)); + Assert.assertFalse(testPanel.isSelected(1)); + Assert.assertTrue(testPanel.isSelected(2)); + } } From 1756c1e0b74165107fbaa657a99defdcf2a867fc Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Thu, 10 Jan 2019 10:27:53 -0500 Subject: [PATCH 17/18] Changed the public API methods to be more generic --- .../org/sleuthkit/autopsy/core/UserPreferences.java | 11 +++++------ .../autopsy/corecomponents/DataContentViewerHex.java | 2 +- .../ExternalViewerGlobalSettingsPanel.java | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index f96cd05969..332a6d7ca7 100644 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -39,7 +39,6 @@ import org.sleuthkit.datamodel.TskData.DbType; */ public final class UserPreferences { - private static final boolean IS_WINDOWS_OS = PlatformUtil.isWindowsOS(); private static final Preferences preferences = NbPreferences.forModule(UserPreferences.class); public static final String KEEP_PREFERRED_VIEWER = "KeepPreferredViewer"; // NON-NLS public static final String HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE = "HideKnownFilesInDataSourcesTree"; //NON-NLS @@ -76,7 +75,7 @@ public final class UserPreferences { public static final String SHOW_ONLY_CURRENT_USER_TAGS = "ShowOnlyCurrentUserTags"; public static final String HIDE_CENTRAL_REPO_COMMENTS_AND_OCCURRENCES = "HideCentralRepoCommentsAndOccurrences"; public static final String DISPLAY_TRANSLATED_NAMES = "DisplayTranslatedNames"; - public static final String HDX_EDITOR_PATH = "HdXEditorPath"; + public static final String EXTERNAL_HEX_EDITOR_PATH = "ExternalHexEditorPath"; // Prevent instantiation. private UserPreferences() { @@ -479,8 +478,8 @@ public final class UserPreferences { * * @param executablePath User-inputted path to HxD executable */ - public static void setHdXEditorPath(String executablePath) { - preferences.put(HDX_EDITOR_PATH, executablePath); + public static void setExternalHexEditorPath(String executablePath) { + preferences.put(EXTERNAL_HEX_EDITOR_PATH, executablePath); } /** @@ -489,7 +488,7 @@ public final class UserPreferences { * * @return Path to HdX */ - public static String getHdXEditorPath() { - return preferences.get(HDX_EDITOR_PATH, Paths.get("C:", "Program Files", "HxD", "HxD.exe").toString()); + public static String getExternalHexEditorPath() { + return preferences.get(EXTERNAL_HEX_EDITOR_PATH, Paths.get("C:", "Program Files", "HxD", "HxD.exe").toString()); } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java index db4fa74c6e..82c7df497a 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java @@ -362,7 +362,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont + "Please set-up the HdX install location in Tools -> Options -> External Viewer"}) private void launchHxDButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_launchHxDButtonActionPerformed try { - File HdXExecutable = new File(UserPreferences.getHdXEditorPath()); + File HdXExecutable = new File(UserPreferences.getExternalHexEditorPath()); if(!HdXExecutable.exists() || !HdXExecutable.canExecute()) { JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError()); return; diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index ef0cc08b8f..2d5439cf69 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -362,7 +362,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme rules.add(tableModel.getRuleAt(i)); } ExternalViewerRulesManager.getInstance().setUserRules(rules); - UserPreferences.setHdXEditorPath(HxDPath.getText()); + UserPreferences.setExternalHexEditorPath(HxDPath.getText()); } @Override @@ -373,7 +373,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme tableModel.addRule(rule); } } - String editorPath = UserPreferences.getHdXEditorPath(); + String editorPath = UserPreferences.getExternalHexEditorPath(); File HdXExecutable = new File(editorPath); if(HdXExecutable.exists() || HdXExecutable.canExecute()) { HxDPath.setText(editorPath); From 35408cfcf35132729ae90aca2a5943abd3b68a28 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Thu, 10 Jan 2019 10:59:51 -0500 Subject: [PATCH 18/18] Small codacy suggestion --- .../directorytree/ExternalViewerGlobalSettingsPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java index 2d5439cf69..0cfbd7d5e5 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java @@ -67,7 +67,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme ExternalViewerRulesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ListSelectionModel selectionModel = ExternalViewerRulesTable.getSelectionModel(); - selectionModel.addListSelectionListener((ListSelectionEvent e) -> { + selectionModel.addListSelectionListener((ListSelectionEvent selection) -> { enableButtons(); }); }