diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java
index 2be9a9b447..332a6d7ca7 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;
@@ -38,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
@@ -75,6 +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 EXTERNAL_HEX_EDITOR_PATH = "ExternalHexEditorPath";
// Prevent instantiation.
private UserPreferences() {
@@ -471,4 +472,23 @@ public final class UserPreferences {
public static void setLogFileCount(int count) {
preferences.putInt(MAX_NUM_OF_LOG_FILE, count);
}
+
+ /**
+ * Set the HdX path.
+ *
+ * @param executablePath User-inputted path to HxD executable
+ */
+ public static void setExternalHexEditorPath(String executablePath) {
+ preferences.put(EXTERNAL_HEX_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 Path to HdX
+ */
+ 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/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties
index 299b0e18d4..d91a751a1a 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties
@@ -193,3 +193,34 @@ 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
+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.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.form
index 745c862756..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 @@
-
+
@@ -120,7 +120,9 @@
-
+
+
+
@@ -140,7 +142,10 @@
-
+
+
+
+
@@ -289,6 +294,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java
index 6639856099..82c7df497a 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java
@@ -21,7 +21,11 @@ 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.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
@@ -31,7 +35,13 @@ import javax.swing.text.BadLocationException;
import javax.swing.text.Utilities;
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 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;
import org.sleuthkit.datamodel.TskException;
@@ -105,6 +115,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 +198,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 +232,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(146, Short.MAX_VALUE))
);
hexViewerPanelLayout.setVerticalGroup(
hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -231,17 +251,21 @@ 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))
);
+ 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, 100, 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(
@@ -249,7 +273,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, 239, Short.MAX_VALUE))
);
}// //GEN-END:initComponents
@@ -334,6 +358,37 @@ 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.getExternalHexEditorPath());
+ if(!HdXExecutable.exists() || !HdXExecutable.canExecute()) {
+ JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError());
+ return;
+ }
+
+ String tempDirectory = Case.getCurrentCaseThrows().getTempDirectory();
+ File dataSourceInTempDirectory = Paths.get(tempDirectory,
+ FileUtil.escapeFileName(dataSource.getId() + dataSource.getName())).toFile();
+ ContentUtils.writeToFile(dataSource, dataSourceInTempDirectory);
+
+ try {
+ ProcessBuilder launchHdXExecutable = new ProcessBuilder();
+ launchHdXExecutable.command(String.format("\"%s\" \"%s\"",
+ HdXExecutable.getAbsolutePath(),
+ dataSourceInTempDirectory.getAbsolutePath()));
+ launchHdXExecutable.start();
+ } catch (IOException ex) {
+ JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError());
+ dataSourceInTempDirectory.delete();
+ }
+ } catch (NoCurrentCaseException | IOException ex) {
+ logger.log(Level.SEVERE, "Unable to copy file into temp directory", ex);
+ JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError());
+ }
+ }//GEN-LAST:event_launchHxDButtonActionPerformed
+
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JMenuItem copyMenuItem;
private javax.swing.JLabel currentPageLabel;
@@ -344,6 +399,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;
@@ -504,6 +560,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
goToPageLabel.setVisible(isVisible);
goToOffsetTextField.setVisible(isVisible);
goToOffsetLabel.setVisible(isVisible);
+ launchHxDButton.setVisible(isVisible);
}
@Override
@@ -528,17 +585,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);
- }
- }
}
diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties
index 26c970b2b3..c1939adf6c 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,16 @@ 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=Add your custom rules for external viewers:
+ExternalViewerGlobalSettingsPanel.newRuleButton.text=New Rule
+ExternalViewerGlobalSettingsPanel.jButton2.text=jButton2
+ExternalViewerGlobalSettingsPanel.browseHxDDirectory.text=Browse
+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 e04dc19270..fde8a99209 100644
--- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.form
@@ -1,6 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanel.java
index f5351393dc..0cfbd7d5e5 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.
@@ -18,16 +18,21 @@
*/
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.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 java.util.List;
+import javax.swing.JFileChooser;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
-import org.sleuthkit.autopsy.coreutils.Logger;
+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;
+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
@@ -37,39 +42,67 @@ 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 java.util.List rules;
+ private ExternalViewerGlobalSettingsTableModel tableModel;
+ public ExternalViewerGlobalSettingsPanel() {
+ this(new ExternalViewerGlobalSettingsTableModel(new String[] {
+ "Mime type/Extension", "Application"}));
+ }
+
/**
* Creates new form ExternalViewerGlobalSettingsPanel
*/
- public ExternalViewerGlobalSettingsPanel() {
+ 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() {
- 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();
- }
- }
- }
+ private void customizeComponents(ExternalViewerGlobalSettingsTableModel tableModel) {
+ ExternalViewerRulesTable.setModel(tableModel);
+ ExternalViewerRulesTable.setAutoCreateRowSorter(true);
+ ExternalViewerRulesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ ListSelectionModel selectionModel = ExternalViewerRulesTable.getSelectionModel();
+
+ selectionModel.addListSelectionListener((ListSelectionEvent selection) -> {
+ enableButtons();
});
}
-
+
+ /**
+ * Simulate the delete rule button click action.
+ *
+ * @param selectedIndex Index to delete in JTable
+ */
+ public void deleteRuleButtonClick(int 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 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);
+ }
+
/**
* 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
@@ -79,60 +112,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();
+ ExternalViewerRulesTable = 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();
+ HxDPath = new javax.swing.JTextField();
+ 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
+ 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 +149,26 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
}
});
+ jScrollPane4.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(204, 204, 204)));
+
+ 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
+
+ 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,91 +179,112 @@ 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);
+ HxDPath.setEditable(false);
- jScrollPane1.setViewportView(jSplitPane1);
+ org.openide.awt.Mnemonics.setLocalizedText(HxDLabel, org.openide.util.NbBundle.getMessage(ExternalViewerGlobalSettingsPanel.class, "ExternalViewerGlobalSettingsPanel.HxDLabel.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() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ browseHxDDirectoryActionPerformed(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(ContentViewerExtensionLabel)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGroup(jPanel3Layout.createSequentialGroup()
+ .addGap(21, 21, 21)
+ .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)
+ .addComponent(browseHxDDirectory, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE))
+ );
+ jPanel3Layout.setVerticalGroup(
+ jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel3Layout.createSequentialGroup()
+ .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(HxDLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(browseHxDDirectory))
+ .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(
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
@@ -247,16 +294,13 @@ 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);
- updateRulesListModel();
- int index = rules.indexOf(newRule);
- rulesList.setSelectedIndex(index);
+ tableModel.addRule(newRule);
enableButtons();
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}
@@ -264,113 +308,107 @@ 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()));
+ int selectedIndex = ExternalViewerRulesTable.convertRowIndexToModel(ExternalViewerRulesTable.getSelectedRow());
+ ExternalViewerRule selectedRule = tableModel.getRuleAt(selectedIndex);
+ AddExternalViewerRuleDialog dialog = new AddExternalViewerRuleDialog(selectedRule);
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)) {
+ 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(selected, dialog.getRule());
- updateRulesListModel();
+ tableModel.setRule(selectedIndex, dialog.getRule());
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}
}
- rulesList.setSelectedIndex(selected);
- enableButtons();
}//GEN-LAST:event_editRuleButtonActionPerformed
private void deleteRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteRuleButtonActionPerformed
- ExternalViewerRule rule = rulesList.getSelectedValue();
- rules.remove(rule);
- updateRulesListModel();
+ tableModel.removeRule(ExternalViewerRulesTable.convertRowIndexToModel(ExternalViewerRulesTable.getSelectedRow()));
+ ExternalViewerRulesTable.getSelectionModel().clearSelection();
+ enableButtons();
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() {
+ //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.setExternalHexEditorPath(HxDPath.getText());
}
@Override
public void load() {
- rules = ExternalViewerRulesManager.getInstance().getUserRules();
- updateRulesListModel();
+ List rules = ExternalViewerRulesManager.getInstance().getUserRules();
+ for(ExternalViewerRule rule : rules) {
+ if(!tableModel.containsRule(rule)) {
+ tableModel.addRule(rule);
+ }
+ }
+ String editorPath = UserPreferences.getExternalHexEditorPath();
+ File HdXExecutable = new File(editorPath);
+ if(HdXExecutable.exists() || HdXExecutable.canExecute()) {
+ HxDPath.setText(editorPath);
+ } else {
+ HxDPath.setForeground(Color.RED);
+ HxDPath.setText(editorPath);
+ }
enableButtons();
}
/**
* Enable edit and delete buttons if there is a rule selected.
*/
- private void enableButtons() {
- boolean ruleIsSelected = rulesList.getSelectedIndex() != -1;
+ boolean enableButtons() {
+ boolean ruleIsSelected = ExternalViewerRulesTable.getSelectedRow() >= 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 updateRulesListModel() {
- rulesListModel.clear();
- 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();
+ 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.JPanel exePanel;
- private javax.swing.JLabel exePathLabel;
- private javax.swing.JLabel exePathNameLabel;
private javax.swing.JLabel externalViewerTitleLabel;
+ private javax.swing.JButton jButton2;
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.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
}
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..5662e0cd84
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModel.java
@@ -0,0 +1,166 @@
+/*
+ * 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.Arrays;
+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 {
+
+ private final List rules;
+ private final String[] columnNames;
+
+ public ExternalViewerGlobalSettingsTableModel(String... columnNames) {
+ this.columnNames = Arrays.copyOf(columnNames, columnNames.length);
+ 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) {
+ return rules.get(rowIndex).getName();
+ } else {
+ return rules.get(rowIndex).getExePath();
+ }
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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/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);
}
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;
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..cfbc5e0cf6
--- /dev/null
+++ b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsPanelTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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;
+
+/**
+ * 72% code coverage of ExternalViewerGlobalSettingsPanel
+ */
+public class ExternalViewerGlobalSettingsPanelTest {
+
+ static final String[] testColumnNames = {"A", "B"};
+
+ /**
+ * Default constructor for JUnit
+ */
+ public ExternalViewerGlobalSettingsPanelTest(){
+ //Codacy complains if there is no comment here
+ }
+
+ @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.assertFalse(panel.enableButtons());
+ panel.setSelectionInterval(0, 0);
+ 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.assertFalse(panel.enableButtons());
+ panel.setSelectionInterval(0, 0);
+ 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));
+ testPanel.setSelectionInterval(0, 0);
+ Assert.assertTrue(testPanel.enableButtons());
+ Assert.assertEquals(1, testModel.getRowCount());
+
+ testPanel.deleteRuleButtonClick(0);
+
+ 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);
+ }
+
+ @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));
+ }
+}
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..72118c7e3e
--- /dev/null
+++ b/Core/test/unit/src/org/sleuthkit/autopsy/directorytree/ExternalViewerGlobalSettingsTableModelTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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.Before;
+import org.junit.Test;
+import org.sleuthkit.autopsy.directorytree.ExternalViewerRule.RuleType;
+
+/**
+ * 100% code coverage of ExternalViewerGlobalSettingsTableModel
+ */
+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);
+ }
+
+ /**
+ * Test of addRule method, of class ExternalViewerGlobalSettingsTableModel.
+ */
+ @Test
+ public void testAddRule() {
+ ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames);
+ testModel.addRule(pngMime);
+
+ Assert.assertEquals(1, testModel.getRowCount());
+
+ ExternalViewerRule rule = testModel.getRuleAt(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(pngMime);
+ testModel.addRule(txtExt);
+ testModel.addRule(wavExt);
+
+ 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(pngMime);
+ testModel.addRule(txtExt);
+ testModel.addRule(wavExt);
+
+ 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(pngMime);
+ testModel.addRule(txtExt);
+ testModel.addRule(wavExt);
+
+ 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(pngMime);
+ testModel.addRule(txtExt);
+ testModel.addRule(wavExt);
+
+ 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, pngMime);
+ 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);
+ testModel.addRule(pngMime);
+ Assert.assertEquals(1, testModel.getRowCount());
+
+ testModel.removeRule(0);
+ Assert.assertEquals(0, testModel.getRowCount());
+ Assert.assertFalse(testModel.containsRule(pngMime));
+ }
+
+ /**
+ * Test of isCellEditable method, of class ExternalViewerGlobalSettingsTableModel.
+ */
+ @Test
+ public void testIsCellEditable() {
+ ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames);
+ Assert.assertFalse(testModel.isCellEditable(0, 0));
+ }
+
+ /**
+ * Test of containsRule method, of class ExternalViewerGlobalSettingsTableModel.
+ */
+ @Test
+ public void testContainsRule() {
+ ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames);
+ testModel.addRule(pngMime);
+ Assert.assertTrue(testModel.containsRule(pngMime));
+ }
+
+ @Test
+ public void testNotContains() {
+ ExternalViewerGlobalSettingsTableModel testModel = new ExternalViewerGlobalSettingsTableModel(testColumnNames);
+ testModel.addRule(pngMime);
+ Assert.assertFalse(testModel.containsRule(new ExternalViewerRule("not", "a rule", RuleType.EXT)));
+ Assert.assertFalse(testModel.containsRule(null));
+ }
+}
\ No newline at end of file