diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties
index c48d4da6cd..6278bc649c 100755
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties
@@ -61,3 +61,18 @@ KeywordSearchListTopComponent.cutMenuItem.text=Cut
KeywordSearchListTopComponent.copyMenuItem.text=Copy
KeywordSearchListTopComponent.pasteMenuItem.text=Paste
KeywordSearchListTopComponent.selectAllMenuItem.text=Select All
+KeywordSearchEditListPanel.saveListButton.text=Save As
+KeywordSearchEditListPanel.addWordField.text=
+KeywordSearchEditListPanel.addWordButton.text=Add
+KeywordSearchEditListPanel.chRegex.text=Regular Expression
+KeywordSearchEditListPanel.deleteWordButton.text=Remove Selected
+KeywordSearchEditListPanel.cutMenuItem.text=Cut
+KeywordSearchEditListPanel.selectAllMenuItem.text=Select All
+KeywordSearchEditListPanel.pasteMenuItem.text=Paste
+KeywordSearchEditListPanel.copyMenuItem.text=Copy
+KeywordSearchConfigurationDialog.applyButton.text=Apply
+KeywordSearchEditListPanel.importButton.text=Import
+KeywordSearchEditListPanel.exportButton.text=Export
+KeywordSearchEditListPanel.deleteListButton.text=Delete List
+KeywordSearchListsManagementPanel.newListButton.text=New List
+KeywordSearchListsManagementPanel.searchListsLabel.text=Select Keyword Search List:
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationDialog.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationDialog.form
new file mode 100644
index 0000000000..efa7653ae8
--- /dev/null
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationDialog.form
@@ -0,0 +1,63 @@
+
+
+
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationDialog.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationDialog.java
new file mode 100644
index 0000000000..d33bacb806
--- /dev/null
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationDialog.java
@@ -0,0 +1,124 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011 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.
+ */
+
+/*
+ * KeywordSearchConfigurationDialog.java
+ *
+ * Created on Feb 10, 2012, 4:32:33 PM
+ */
+package org.sleuthkit.autopsy.keywordsearch;
+
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import javax.swing.JFrame;
+
+/**
+ *
+ * @author dfickling
+ */
+public class KeywordSearchConfigurationDialog extends javax.swing.JDialog {
+
+ KeywordSearchListsManagementPanel listsManagementPanel;
+ KeywordSearchEditListPanel editListPanel;
+
+ /** Creates new form KeywordSearchConfigurationDialog */
+ public KeywordSearchConfigurationDialog() {
+ super(new JFrame("Keyword Search Configuration"), "Keyword Search Configuration", true);
+ setResizable(false);
+ initComponents();
+ customizeComponents();
+ }
+
+ private void customizeComponents() {
+ listsManagementPanel = KeywordSearchListsManagementPanel.getDefault();
+ editListPanel = KeywordSearchEditListPanel.getDefault();
+
+ listsManagementPanel.addListSelectionListener(KeywordSearchEditListPanel.getDefault());
+ mainSplitPane.setLeftComponent(listsManagementPanel);
+ mainSplitPane.setRightComponent(editListPanel);
+ mainSplitPane.revalidate();
+ mainSplitPane.repaint();
+
+ Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
+
+ // set the popUp window / JFrame
+ int w = this.getSize().width;
+ int h = this.getSize().height;
+
+ // set the location of the popUp Window on the center of the screen
+ setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
+ this.pack();
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ applyButton = new javax.swing.JButton();
+ mainSplitPane = new javax.swing.JSplitPane();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+
+ applyButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationDialog.class, "KeywordSearchConfigurationDialog.applyButton.text")); // NOI18N
+ applyButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ applyButtonActionPerformed(evt);
+ }
+ });
+
+ mainSplitPane.setDividerSize(8);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap(331, Short.MAX_VALUE)
+ .addComponent(applyButton)
+ .addContainerGap())
+ .addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(applyButton)
+ .addContainerGap())
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void applyButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_applyButtonActionPerformed
+ editListPanel.save();
+ this.dispose();
+ }//GEN-LAST:event_applyButtonActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton applyButton;
+ private javax.swing.JSplitPane mainSplitPane;
+ // End of variables declaration//GEN-END:variables
+
+}
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchEditListPanel.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchEditListPanel.form
new file mode 100644
index 0000000000..b13d77426c
--- /dev/null
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchEditListPanel.form
@@ -0,0 +1,252 @@
+
+
+
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchEditListPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchEditListPanel.java
new file mode 100644
index 0000000000..8ea4d387b9
--- /dev/null
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchEditListPanel.java
@@ -0,0 +1,775 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011 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.
+ */
+
+/*
+ * KeywordSearchEditListPanel.java
+ *
+ * Created on Feb 10, 2012, 4:20:03 PM
+ */
+package org.sleuthkit.autopsy.keywordsearch;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+import javax.swing.JFileChooser;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableColumn;
+
+/**
+ *
+ * @author dfickling
+ */
+public class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelectionListener{
+
+ private static Logger logger = Logger.getLogger(KeywordSearchEditListPanel.class.getName());
+ private KeywordTableModel tableModel;
+ private String currentKeywordList;
+
+ private static KeywordSearchEditListPanel instance = null;
+
+ /** Creates new form KeywordSearchEditListPanel */
+ public KeywordSearchEditListPanel() {
+ tableModel = new KeywordTableModel();
+ initComponents();
+ customizeComponents();
+ }
+
+ public static synchronized KeywordSearchEditListPanel getDefault() {
+ if (instance == null) {
+ instance = new KeywordSearchEditListPanel();
+ }
+ return instance;
+ }
+
+ private void customizeComponents() {
+ chRegex.setToolTipText("Keyword is a regular expression");
+ addWordButton.setToolTipText(("Add a new word to the keyword search list"));
+ addWordField.setToolTipText("Enter a new word or regex to search");
+ saveListButton.setToolTipText("Save the current keyword list to a file");
+ deleteWordButton.setToolTipText("Remove selected keyword(s) from the list");
+
+ //keywordTable.setAutoscrolls(true);
+ //keywordTable.setTableHeader(null);
+ keywordTable.setShowHorizontalLines(false);
+ keywordTable.setShowVerticalLines(false);
+
+ keywordTable.getParent().setBackground(keywordTable.getBackground());
+
+ //customize column witdhs
+ keywordTable.setSize(260, 200);
+ final int width = keywordTable.getSize().width;
+ TableColumn column = null;
+ for (int i = 0; i < 2; i++) {
+ column = keywordTable.getColumnModel().getColumn(i);
+ if (i > 0) {
+ column.setPreferredWidth(((int) (width * 0.25)));
+ //column.setCellRenderer(new CellTooltipRenderer());
+ }
+ else {
+ //column.setCellRenderer(new CellTooltipRenderer());
+ column.setPreferredWidth(((int) (width * 0.74)));
+ }
+ }
+ keywordTable.setCellSelectionEnabled(false);
+ keywordTable.setRowSelectionAllowed(true);
+
+ //loadDefaultKeywords();
+
+ initButtons();
+
+ addWordField.setComponentPopupMenu(rightClickMenu);
+ ActionListener actList = new ActionListener(){
+ @Override
+ public void actionPerformed(ActionEvent e){
+ JMenuItem jmi = (JMenuItem) e.getSource();
+ if(jmi.equals(cutMenuItem))
+ addWordField.cut();
+ else if(jmi.equals(copyMenuItem))
+ addWordField.copy();
+ else if(jmi.equals(pasteMenuItem))
+ addWordField.paste();
+ else if(jmi.equals(selectAllMenuItem))
+ addWordField.selectAll();
+ }
+ };
+ cutMenuItem.addActionListener(actList);
+ copyMenuItem.addActionListener(actList);
+ pasteMenuItem.addActionListener(actList);
+ selectAllMenuItem.addActionListener(actList);
+ }
+
+ private void initButtons() {
+ //initialize save buttons
+ if (getAllKeywords().isEmpty()) {
+ saveListButton.setEnabled(false);
+ } else {
+ saveListButton.setEnabled(true);
+ }
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ rightClickMenu = new javax.swing.JPopupMenu();
+ cutMenuItem = new javax.swing.JMenuItem();
+ copyMenuItem = new javax.swing.JMenuItem();
+ pasteMenuItem = new javax.swing.JMenuItem();
+ selectAllMenuItem = new javax.swing.JMenuItem();
+ listEditorPanel = new javax.swing.JPanel();
+ chRegex = new javax.swing.JCheckBox();
+ deleteWordButton = new javax.swing.JButton();
+ jScrollPane1 = new javax.swing.JScrollPane();
+ keywordTable = new javax.swing.JTable();
+ addWordButton = new javax.swing.JButton();
+ addWordField = new javax.swing.JTextField();
+ saveListButton = new javax.swing.JButton();
+ importButton = new javax.swing.JButton();
+ exportButton = new javax.swing.JButton();
+ deleteListButton = new javax.swing.JButton();
+
+ cutMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.cutMenuItem.text")); // NOI18N
+ rightClickMenu.add(cutMenuItem);
+
+ copyMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.copyMenuItem.text")); // NOI18N
+ rightClickMenu.add(copyMenuItem);
+
+ pasteMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.pasteMenuItem.text")); // NOI18N
+ rightClickMenu.add(pasteMenuItem);
+
+ selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.selectAllMenuItem.text")); // NOI18N
+ rightClickMenu.add(selectAllMenuItem);
+
+ setPreferredSize(new java.awt.Dimension(326, 400));
+
+ listEditorPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
+
+ chRegex.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.chRegex.text")); // NOI18N
+
+ deleteWordButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.deleteWordButton.text")); // NOI18N
+ deleteWordButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ deleteWordButtonActionPerformed(evt);
+ }
+ });
+
+ keywordTable.setModel(tableModel);
+ keywordTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
+ keywordTable.setShowHorizontalLines(false);
+ keywordTable.setShowVerticalLines(false);
+ keywordTable.getTableHeader().setReorderingAllowed(false);
+ jScrollPane1.setViewportView(keywordTable);
+
+ addWordButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.addWordButton.text")); // NOI18N
+ addWordButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ addWordButtonActionPerformed(evt);
+ }
+ });
+
+ addWordField.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.addWordField.text")); // NOI18N
+ addWordField.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ addWordFieldActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout listEditorPanelLayout = new javax.swing.GroupLayout(listEditorPanel);
+ listEditorPanel.setLayout(listEditorPanelLayout);
+ listEditorPanelLayout.setHorizontalGroup(
+ listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(listEditorPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, listEditorPanelLayout.createSequentialGroup()
+ .addGap(24, 24, 24)
+ .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(addWordField, javax.swing.GroupLayout.PREFERRED_SIZE, 152, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGroup(listEditorPanelLayout.createSequentialGroup()
+ .addGap(10, 10, 10)
+ .addComponent(chRegex)))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(addWordButton)
+ .addGap(35, 35, 35))
+ .addComponent(deleteWordButton, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+ listEditorPanelLayout.setVerticalGroup(
+ listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, listEditorPanelLayout.createSequentialGroup()
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 210, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(18, 18, 18)
+ .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(addWordButton)
+ .addGroup(listEditorPanelLayout.createSequentialGroup()
+ .addComponent(addWordField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(chRegex)))
+ .addGap(7, 7, 7)
+ .addComponent(deleteWordButton)
+ .addContainerGap())
+ );
+
+ saveListButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.saveListButton.text")); // NOI18N
+ saveListButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ saveListButtonActionPerformed(evt);
+ }
+ });
+
+ importButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.importButton.text")); // NOI18N
+ importButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ importButtonActionPerformed(evt);
+ }
+ });
+
+ exportButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.exportButton.text")); // NOI18N
+ exportButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ exportButtonActionPerformed(evt);
+ }
+ });
+
+ deleteListButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.deleteListButton.text")); // NOI18N
+ deleteListButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ deleteListButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(importButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(exportButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(deleteListButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(saveListButton)
+ .addContainerGap())
+ .addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addComponent(listEditorPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 39, Short.MAX_VALUE)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(importButton)
+ .addComponent(exportButton)
+ .addComponent(deleteListButton)
+ .addComponent(saveListButton))
+ .addContainerGap())
+ );
+ }// //GEN-END:initComponents
+
+ private void addWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addWordButtonActionPerformed
+ String newWord = addWordField.getText().trim();
+ boolean isLiteral = !chRegex.isSelected();
+ final Keyword keyword = new Keyword(newWord, isLiteral);
+
+ if (newWord.equals("")) {
+ return;
+ } else if (keywordExists(keyword)) {
+ KeywordSearchUtil.displayDialog("New Keyword Entry", "Keyword already exists in the list.", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
+ return;
+ }
+
+
+ //check if valid
+ boolean valid = true;
+ try {
+ Pattern.compile(newWord);
+ } catch (PatternSyntaxException ex1) {
+ valid = false;
+ } catch (IllegalArgumentException ex2) {
+ valid = false;
+ }
+ if (!valid) {
+ KeywordSearchUtil.displayDialog("New Keyword Entry", "Invalid keyword pattern. Use words or a correct regex pattern.", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
+ return;
+ }
+
+ //add & reset checkbox
+ tableModel.addKeyword(keyword);
+ chRegex.setSelected(false);
+ addWordField.setText("");
+
+ initButtons();
+ }//GEN-LAST:event_addWordButtonActionPerformed
+
+ private void saveListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveListButtonActionPerformed
+ final String FEATURE_NAME = "Save Keyword List";
+ KeywordSearchListsXML writer = KeywordSearchListsXML.getCurrent();
+
+ List keywords = tableModel.getAllKeywords();
+ if (keywords.isEmpty()) {
+ KeywordSearchUtil.displayDialog(FEATURE_NAME, "Keyword List is empty and cannot be saved", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
+ return;
+ }
+
+ String listName = (String) JOptionPane.showInputDialog(
+ null,
+ "New keyword list name:",
+ FEATURE_NAME,
+ JOptionPane.PLAIN_MESSAGE,
+ null,
+ null,
+ currentKeywordList != null ? currentKeywordList : "");
+ if (listName == null || listName.trim().equals("")) {
+ return;
+ }
+
+ boolean shouldAdd = false;
+ if (writer.listExists(listName)) {
+ boolean replace = KeywordSearchUtil.displayConfirmDialog(FEATURE_NAME, "Keyword List <" + listName + "> already exists, do you want to replace it?",
+ KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
+ if (replace) {
+ shouldAdd = true;
+ }
+
+ } else {
+ shouldAdd = true;
+ }
+
+ if (shouldAdd) {
+ writer.addList(listName, keywords);
+ }
+
+ currentKeywordList = listName;
+ KeywordSearchUtil.displayDialog(FEATURE_NAME, "Keyword List <" + listName + "> saved", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
+
+ }//GEN-LAST:event_saveListButtonActionPerformed
+
+ private void deleteWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteWordButtonActionPerformed
+ tableModel.deleteSelected(keywordTable.getSelectedRows());
+ }//GEN-LAST:event_deleteWordButtonActionPerformed
+
+ private void addWordFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addWordFieldActionPerformed
+ addWordButtonActionPerformed(evt);
+ }//GEN-LAST:event_addWordFieldActionPerformed
+
+ private void importButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importButtonActionPerformed
+ final String FEATURE_NAME = "Keyword List Import";
+
+ JFileChooser chooser = new JFileChooser();
+ final String EXTENSION = "xml";
+ FileNameExtensionFilter filter = new FileNameExtensionFilter(
+ "Keyword List XML file", EXTENSION);
+ chooser.setFileFilter(filter);
+ chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+
+ int returnVal = chooser.showOpenDialog(this);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File selFile = chooser.getSelectedFile();
+ if (selFile == null) {
+ return;
+ }
+
+ //force append extension if not given
+ String fileAbs = selFile.getAbsolutePath();
+
+ final KeywordSearchListsXML reader = new KeywordSearchListsXML(fileAbs);
+ if (!reader.load()) {
+ KeywordSearchUtil.displayDialog(FEATURE_NAME, "Error importing keyword list from file " + fileAbs, KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
+ return;
+ }
+
+ List toImport = reader.getListsL();
+ List toImportConfirmed = new ArrayList();
+
+ final KeywordSearchListsXML writer = KeywordSearchListsXML.getCurrent();
+
+ for (KeywordSearchList list : toImport) {
+ //check name collisions
+ if (writer.listExists(list.getName())) {
+ Object[] options = {"Yes, overwrite",
+ "No, skip",
+ "Cancel import"};
+ int choice = JOptionPane.showOptionDialog(this,
+ "Keyword list <" + list.getName() + "> already exists locally, overwrite?",
+ "Import list conflict",
+ JOptionPane.YES_NO_CANCEL_OPTION,
+ JOptionPane.QUESTION_MESSAGE,
+ null,
+ options,
+ options[0]);
+ if (choice == JOptionPane.OK_OPTION) {
+ toImportConfirmed.add(list);
+ } else if (choice == JOptionPane.CANCEL_OPTION) {
+ break;
+ }
+
+ } else {
+ //no conflict
+ toImportConfirmed.add(list);
+ }
+
+ }
+
+ if (toImportConfirmed.isEmpty()) {
+ return;
+ }
+
+ if (writer.writeLists(toImportConfirmed)) {
+ KeywordSearchUtil.displayDialog(FEATURE_NAME, "Keyword list imported", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
+ }
+
+ initButtons();
+ }
+ }//GEN-LAST:event_importButtonActionPerformed
+
+ private void exportButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportButtonActionPerformed
+ save();
+
+ final String FEATURE_NAME = "Keyword List Export";
+
+ JFileChooser chooser = new JFileChooser();
+ final String EXTENSION = "xml";
+ FileNameExtensionFilter filter = new FileNameExtensionFilter(
+ "Keyword List XML file", EXTENSION);
+ chooser.setFileFilter(filter);
+ chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+
+ int returnVal = chooser.showSaveDialog(this);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File selFile = chooser.getSelectedFile();
+ if (selFile == null) {
+ return;
+ }
+
+ //force append extension if not given
+ String fileAbs = selFile.getAbsolutePath();
+ if (!fileAbs.endsWith("." + EXTENSION)) {
+ fileAbs = fileAbs + "." + EXTENSION;
+ selFile = new File(fileAbs);
+ }
+
+ boolean shouldWrite = true;
+ if (selFile.exists()) {
+ shouldWrite = KeywordSearchUtil.displayConfirmDialog(FEATURE_NAME, "File " + selFile.getName() + " exists, overwrite?", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
+ }
+ if (!shouldWrite) {
+ return;
+ }
+
+
+ KeywordSearchListsXML reader = KeywordSearchListsXML.getCurrent();
+
+ List toWrite = new ArrayList();
+ toWrite.add(reader.getList(currentKeywordList));
+ final KeywordSearchListsXML exporter = new KeywordSearchListsXML(fileAbs);
+ boolean written = exporter.writeLists(toWrite);
+ if (written) {
+ KeywordSearchUtil.displayDialog(FEATURE_NAME, "Keyword lists exported", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
+ return;
+ }
+ }
+ }//GEN-LAST:event_exportButtonActionPerformed
+
+ private void deleteListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteListButtonActionPerformed
+ KeywordSearchListsXML deleter = KeywordSearchListsXML.getCurrent();
+ String toDelete = currentKeywordList;
+ currentKeywordList = null;
+ tableModel.deleteAll();
+ deleter.deleteList(toDelete);
+ }//GEN-LAST:event_deleteListButtonActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton addWordButton;
+ private javax.swing.JTextField addWordField;
+ private javax.swing.JCheckBox chRegex;
+ private javax.swing.JMenuItem copyMenuItem;
+ private javax.swing.JMenuItem cutMenuItem;
+ private javax.swing.JButton deleteListButton;
+ private javax.swing.JButton deleteWordButton;
+ private javax.swing.JButton exportButton;
+ private javax.swing.JButton importButton;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JTable keywordTable;
+ private javax.swing.JPanel listEditorPanel;
+ private javax.swing.JMenuItem pasteMenuItem;
+ private javax.swing.JPopupMenu rightClickMenu;
+ private javax.swing.JButton saveListButton;
+ private javax.swing.JMenuItem selectAllMenuItem;
+ // End of variables declaration//GEN-END:variables
+
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+
+ ListSelectionModel listSelectionModel = (ListSelectionModel) e.getSource();
+ if (!listSelectionModel.isSelectionEmpty()) {
+ int index = listSelectionModel.getMinSelectionIndex();
+ KeywordSearchListsManagementPanel listsPanel = KeywordSearchListsManagementPanel.getDefault();
+
+ save();
+ listSelectionModel.setSelectionInterval(index, index);
+ currentKeywordList = listsPanel.getAllLists().get(index);
+ tableModel.resync(currentKeywordList);
+ initButtons();
+ }
+ }
+
+ List getAllKeywords() {
+ return tableModel.getAllKeywords();
+ }
+
+ List getSelectedKeywords() {
+ return tableModel.getSelectedKeywords(keywordTable.getSelectedRows());
+ }
+
+ private boolean keywordExists(Keyword keyword) {
+ return tableModel.keywordExists(keyword);
+ }
+
+ void save() {
+ if (currentKeywordList != null && !currentKeywordList.equals("")) {
+ KeywordSearchListsXML loader = KeywordSearchListsXML.getCurrent();
+ KeywordSearchList oldList = loader.getList(currentKeywordList);
+ List oldKeywords = oldList.getKeywords();
+ List newKeywords = getAllKeywords();
+
+ if (!oldKeywords.equals(newKeywords)) {
+ /*boolean save = KeywordSearchUtil.displayConfirmDialog("Save List Changes",
+ "Do you want to save the changes you made to list " + currentKeywordList + "?",
+ KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);*/
+ boolean save = true;
+ if (save) {
+ loader.addList(currentKeywordList, newKeywords);
+ }
+ }
+ }
+ }
+
+ private class KeywordTableModel extends AbstractTableModel {
+ //data
+
+ private Set keywordData = new TreeSet();
+
+ @Override
+ public int getColumnCount() {
+ return 2;
+ }
+
+ @Override
+ public int getRowCount() {
+ return keywordData.size();
+ }
+
+ @Override
+ public String getColumnName(int column) {
+ String colName = null;
+
+ switch (column) {
+ case 0:
+ colName = "Keyword";
+ break;
+ case 1:
+ colName = "RegEx";
+ break;
+ default:
+ ;
+
+ }
+ return colName;
+ }
+
+
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ Object ret = null;
+ TableEntry entry = null;
+ //iterate until row
+ Iterator it = keywordData.iterator();
+ for (int i = 0; i <= rowIndex; ++i) {
+ entry = it.next();
+ }
+ switch (columnIndex) {
+ case 0:
+ ret = (Object) entry.keyword;
+ break;
+ case 1:
+ ret = (Object) !entry.isLiteral;
+ break;
+ default:
+ logger.log(Level.SEVERE, "Invalid table column index: " + columnIndex);
+ break;
+ }
+ return ret;
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return false;
+ }
+
+ @Override
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+
+ }
+
+ @Override
+ public Class getColumnClass(int c) {
+ return getValueAt(0, c).getClass();
+ }
+
+ List getAllKeywords() {
+ List ret = new ArrayList();
+ for (TableEntry e : keywordData) {
+ ret.add(new Keyword(e.keyword, e.isLiteral));
+ }
+ return ret;
+ }
+
+ List getSelectedKeywords(int[] selected) {
+ List ret = new ArrayList();
+ for(int i = 0; i < selected.length; i++){
+ Keyword word = new Keyword((String) getValueAt(0, selected[i]), !((Boolean) getValueAt(1, selected[i])));
+ ret.add(word);
+ }
+ return ret;
+ }
+
+ boolean keywordExists(Keyword keyword) {
+ List all = getAllKeywords();
+ return all.contains(keyword);
+ }
+
+ void addKeyword(Keyword keyword) {
+ if (!keywordExists(keyword)) {
+ keywordData.add(new TableEntry(keyword));
+ }
+ fireTableDataChanged();
+ }
+
+ void addKeywords(List keywords) {
+ for (Keyword keyword : keywords) {
+ if (!keywordExists(keyword)) {
+ keywordData.add(new TableEntry(keyword));
+ }
+ }
+ fireTableDataChanged();
+ }
+
+ void resync(String listName) {
+ KeywordSearchListsXML loader = KeywordSearchListsXML.getCurrent();
+ KeywordSearchList list = loader.getList(listName);
+ List keywords = list.getKeywords();
+
+ deleteAll();
+ addKeywords(keywords);
+ }
+
+ void deleteAll() {
+ keywordData.clear();
+ fireTableDataChanged();
+ }
+
+ //delete selected from handle, events are fired from the handle
+ void deleteSelected(int[] selected) {
+ List toDel = new ArrayList();
+ for(int i = 0; i < selected.length; i++){
+ Keyword word = new Keyword((String) getValueAt(selected[i], 0), !((Boolean) getValueAt(selected[i], 1)));
+ toDel.add(new TableEntry(word));
+ }
+ for (TableEntry del : toDel) {
+ keywordData.remove(del);
+ }
+ fireTableDataChanged();
+
+ }
+
+ class TableEntry implements Comparable {
+
+ String keyword;
+ Boolean isLiteral;
+
+ TableEntry(Keyword keyword) {
+ this.keyword = keyword.getQuery();
+ this.isLiteral = keyword.isLiteral();
+ }
+
+ TableEntry(String keyword, Boolean isLiteral) {
+ this.keyword = keyword;
+ this.isLiteral = isLiteral;
+ }
+
+ @Override
+ public int compareTo(Object o) {
+ int keywords = this.keyword.compareTo(((TableEntry) o).keyword);
+ if (keywords != 0)
+ return keywords;
+ else return this.isLiteral.compareTo(((TableEntry) o).isLiteral);
+ }
+
+ }
+ }
+
+ /**
+ * tooltips that show entire query string
+ */
+ private static class CellTooltipRenderer extends DefaultTableCellRenderer {
+
+ @Override
+ public Component getTableCellRendererComponent(
+ JTable table, Object value,
+ boolean isSelected, boolean hasFocus,
+ int row, int column) {
+
+ if (column == 0) {
+ String val = (String) table.getModel().getValueAt(row, column);
+ setToolTipText(val);
+ setText(val);
+ }
+
+ return this;
+ }
+ }
+}
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java
index b368f40c5a..0c82d183c3 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java
@@ -172,8 +172,16 @@ public final class KeywordSearchIngestService implements IngestServiceFsContent
ingestStatus = new HashMap();
reportedHits = new HashMap>();
-
- keywords = new ArrayList(KeywordSearchListTopComponent.getDefault().getAllKeywords());
+
+ KeywordSearchListsXML loader = KeywordSearchListsXML.getCurrent();
+
+ keywords = new ArrayList();
+
+ for(String listName : KeywordSearchListsManagementPanel.getDefault().getIngestLists()){
+ KeywordSearchList list = loader.getList(listName);
+ keywords.addAll(list.getKeywords());
+ }
+
if (keywords.isEmpty()) {
managerProxy.postMessage(IngestMessage.createErrorMessage(++messageID, instance, "No keywords in keyword list. Will index and skip search."));
}
@@ -202,6 +210,7 @@ public final class KeywordSearchIngestService implements IngestServiceFsContent
@Override
public void userConfigure() {
+ new KeywordSearchConfigurationDialog().setVisible(true);
}
@Override
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.form
new file mode 100644
index 0000000000..6d01e45a1f
--- /dev/null
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.form
@@ -0,0 +1,89 @@
+
+
+
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java
new file mode 100644
index 0000000000..e515a68e2a
--- /dev/null
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java
@@ -0,0 +1,432 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011 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.
+ */
+
+/*
+ * KeywordSearchListImportExportForm.java
+ *
+ * Created on Feb 10, 2012, 4:04:13 PM
+ */
+package org.sleuthkit.autopsy.keywordsearch;
+
+import java.awt.Component;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.logging.Logger;
+import javax.swing.JOptionPane;
+import javax.swing.JTable;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableColumn;
+
+/**
+ *
+ * @author dfickling
+ */
+public class KeywordSearchListsManagementPanel extends javax.swing.JPanel {
+
+ private Logger logger = Logger.getLogger(KeywordSearchListsManagementPanel.class.getName());
+ private KeywordListTableModel tableModel;
+
+ private static KeywordSearchListsManagementPanel instance = null;
+
+ /** Creates new form KeywordSearchListImportExportForm */
+ public KeywordSearchListsManagementPanel() {
+ tableModel = new KeywordListTableModel();
+ initComponents();
+ customizeComponents();
+ }
+
+ public static synchronized KeywordSearchListsManagementPanel getDefault() {
+ if (instance == null) {
+ instance = new KeywordSearchListsManagementPanel();
+ }
+ return instance;
+ }
+
+ private void customizeComponents() {
+
+
+ listsTable.setAutoscrolls(true);
+ //listsTable.setTableHeader(null);
+ listsTable.setShowHorizontalLines(false);
+ listsTable.setShowVerticalLines(false);
+
+ listsTable.getParent().setBackground(listsTable.getBackground());
+
+ //customize column witdhs
+ listsTable.setSize(260, 200);
+ final int width = listsTable.getSize().width;
+ TableColumn column = null;
+ for (int i = 0; i < 2; i++) {
+ column = listsTable.getColumnModel().getColumn(i);
+ switch (i) {
+ case 0:
+ column.setPreferredWidth(((int) (width * 0.69)));
+ break;
+ case 1:
+ column.setPreferredWidth(((int) (width * 0.30)));
+ break;
+ default:
+ break;
+
+ }
+
+ }
+ listsTable.setCellSelectionEnabled(false);
+ listsTable.setRowSelectionAllowed(true);
+ tableModel.resync();
+
+ KeywordSearchListsXML.getCurrent().addPropertyChangeListener(new PropertyChangeListener() {
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (evt.getPropertyName().equals(KeywordSearchListsXML.ListsEvt.LIST_ADDED.toString())) {
+ tableModel.resync();
+ for(int i = 0; i 0)
+ listsTable.getSelectionModel().setSelectionInterval(0, 0);
+ } else if (evt.getPropertyName().equals(KeywordSearchListsXML.ListsEvt.LIST_UPDATED.toString())) {
+ tableModel.resync((String) evt.getNewValue()); //changed list name
+ }
+ }
+ });
+
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jScrollPane1 = new javax.swing.JScrollPane();
+ listsTable = new javax.swing.JTable();
+ searchListsLabel = new javax.swing.JLabel();
+ newListButton = new javax.swing.JButton();
+
+ listsTable.setModel(tableModel);
+ listsTable.setShowHorizontalLines(false);
+ listsTable.setShowVerticalLines(false);
+ listsTable.getTableHeader().setReorderingAllowed(false);
+ jScrollPane1.setViewportView(listsTable);
+
+ searchListsLabel.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
+ searchListsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsManagementPanel.class, "KeywordSearchListsManagementPanel.searchListsLabel.text")); // NOI18N
+
+ newListButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsManagementPanel.class, "KeywordSearchListsManagementPanel.newListButton.text")); // NOI18N
+ newListButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ newListButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(searchListsLabel)
+ .addContainerGap(113, Short.MAX_VALUE))
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(newListButton)
+ .addContainerGap(209, Short.MAX_VALUE))
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 292, Short.MAX_VALUE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(searchListsLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 223, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(newListButton)
+ .addContainerGap())
+ );
+ }// //GEN-END:initComponents
+
+ private void newListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newListButtonActionPerformed
+ KeywordSearchListsXML writer = KeywordSearchListsXML.getCurrent();
+ String listName = (String) JOptionPane.showInputDialog(null, "New keyword list name:", "New Keyword List", JOptionPane.PLAIN_MESSAGE, null, null, "");
+ if (listName == null || listName.trim().equals("")) {
+ return;
+ }
+ boolean shouldAdd = false;
+ if (writer.listExists(listName)) {
+ boolean replace = KeywordSearchUtil.displayConfirmDialog("New Keyword List", "Keyword List <" + listName + "> already exists, do you want to replace it?", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
+ if (replace) {
+ shouldAdd = true;
+ }
+ } else {
+ shouldAdd = true;
+ }
+ if (shouldAdd) {
+ writer.addList(listName, new ArrayList());
+ }
+ for (int i = 0; i < listsTable.getRowCount(); i++) {
+ if (listsTable.getValueAt(i, 0).equals(listName)) {
+ listsTable.getSelectionModel().addSelectionInterval(i, i);
+ }
+ }
+ }//GEN-LAST:event_newListButtonActionPerformed
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JTable listsTable;
+ private javax.swing.JButton newListButton;
+ private javax.swing.JLabel searchListsLabel;
+ // End of variables declaration//GEN-END:variables
+
+
+ private class KeywordListTableModel extends AbstractTableModel {
+ //data
+
+ private KeywordSearchListsXML listsHandle = KeywordSearchListsXML.getCurrent();
+ private Set listData = new TreeSet();
+
+ @Override
+ public int getColumnCount() {
+ return 2;
+ }
+
+ @Override
+ public int getRowCount() {
+ return listData.size();
+ }
+
+ @Override
+ public String getColumnName(int column) {
+ String colName = null;
+ switch (column) {
+ case 0:
+ colName = "Name";
+ break;
+ case 1:
+ colName = "Ingest";
+ break;
+ default:
+ ;
+
+ }
+ return colName;
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ Object ret = null;
+ TableEntry entry = null;
+ //iterate until row
+ Iterator it = listData.iterator();
+ for (int i = 0; i <= rowIndex; ++i) {
+ entry = it.next();
+ }
+ switch (columnIndex) {
+ case 0:
+ ret = (Object) entry.name;
+ break;
+ case 1:
+ ret = (Object) entry.useForIngest;
+ break;
+ default:
+ break;
+ }
+ return ret;
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return columnIndex == 1 ? true : false;
+ }
+
+ @Override
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ if (columnIndex == 1) {
+ TableEntry entry = null;
+ //iterate until row
+ Iterator it = listData.iterator();
+ for (int i = 0; i <= rowIndex && it.hasNext(); ++i) {
+ entry = it.next();
+ }
+ if (entry != null){
+ if(columnIndex == 1)
+ entry.useForIngest = (Boolean) aValue;
+ }
+
+ }
+ }
+
+ @Override
+ public Class getColumnClass(int c) {
+ return getValueAt(0, c).getClass();
+ }
+
+ List getAllLists() {
+ List ret = new ArrayList();
+ for (TableEntry e : listData) {
+ ret.add(e.name);
+ }
+ return ret;
+ }
+
+ List getIngestLists() {
+ List ret = new ArrayList();
+ for (TableEntry e : listData) {
+ if (e.useForIngest && !e.name.equals("")) {
+ ret.add(e.name);
+ }
+ }
+ return ret;
+ }
+
+ List getSelectedLists(int[] selected) {
+ List ret = new ArrayList();
+ for(int i = 0; i < selected.length; i++){
+ ret.add((String) getValueAt(0, selected[i]));
+ }
+ return ret;
+ }
+
+ boolean listExists(String list) {
+ List all = getAllLists();
+ return all.contains(list);
+ }
+
+ //delete selected from handle, events are fired from the handle
+ void deleteSelected(int[] selected) {
+ List toDel = new ArrayList();
+ for(int i = 0; i < selected.length; i++){
+ toDel.add((String) getValueAt(0, selected[i]));
+ }
+ for (String del : toDel) {
+ listsHandle.deleteList(del);
+ }
+
+ }
+
+ //resync model from handle, then update table
+ void resync() {
+ listData.clear();
+ addLists(listsHandle.getListsL());
+ fireTableDataChanged();
+ }
+
+ //resync single model entry from handle, then update table
+ void resync(String listName) {
+ TableEntry found = null;
+ for (TableEntry e : listData) {
+ if (e.name.equals(listName)) {
+ found = e;
+ break;
+ }
+ }
+ if (found != null) {
+ listData.remove(found);
+ addList(listsHandle.getList(listName));
+ }
+ fireTableDataChanged();
+ }
+
+ //add list to the model
+ private void addList(KeywordSearchList list) {
+ if (!listExists(list.getName())) {
+ listData.add(new TableEntry(list));
+ }
+ }
+
+ //add lists to the model
+ private void addLists(List lists) {
+ for (KeywordSearchList list : lists) {
+ if (!listExists(list.getName())) {
+ listData.add(new TableEntry(list));
+ }
+ }
+ }
+
+ //single model entry
+ class TableEntry implements Comparable {
+
+ String name;
+ Boolean useForIngest;
+
+ TableEntry(KeywordSearchList list, Boolean useForIngest) {
+ this.name = list.getName();
+ this.useForIngest = useForIngest;
+ }
+
+ TableEntry(KeywordSearchList list) {
+ this.name = list.getName();
+ this.useForIngest = false;
+ }
+
+ @Override
+ public int compareTo(Object o) {
+ return this.name.compareTo(((TableEntry) o).name);
+ }
+ }
+ }
+
+ /**
+ * tooltips that show text
+ */
+ private static class CellTooltipRenderer extends DefaultTableCellRenderer {
+
+ @Override
+ public Component getTableCellRendererComponent(
+ JTable table, Object value,
+ boolean isSelected, boolean hasFocus,
+ int row, int column) {
+
+ if (column < 3) {
+ String val = (String) table.getModel().getValueAt(row, column);
+ setToolTipText(val);
+ setText(val);
+ }
+
+ return this;
+ }
+ }
+
+ void addListSelectionListener(ListSelectionListener l) {
+ listsTable.getSelectionModel().addListSelectionListener(l);
+ }
+
+ List getAllLists() {
+ return tableModel.getAllLists();
+ }
+
+ List getIngestLists() {
+ return tableModel.getIngestLists();
+ }
+}
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsXML.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsXML.java
index 2209884c31..d81ce44881 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsXML.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsXML.java
@@ -187,11 +187,10 @@ public class KeywordSearchListsXML {
boolean replaced = false;
KeywordSearchList curList = getList(name);
final Date now = new Date();
- final int oldSize = this.getNumberLists();
if (curList == null) {
theLists.put(name, new KeywordSearchList(name, now, now, newList));
save();
- changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), oldSize, this.getNumberLists());
+ changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, name);
} else {
theLists.put(name, new KeywordSearchList(name, curList.getDateCreated(), now, newList));
save();
@@ -212,15 +211,19 @@ public class KeywordSearchListsXML {
int oldSize = this.getNumberLists();
List overwritten = new ArrayList();
-
+ List newLists = new ArrayList();
for (KeywordSearchList list : lists) {
if (this.listExists(list.getName()))
overwritten.add(list);
+ else
+ newLists.add(list);
theLists.put(list.getName(), list);
}
boolean saved = save();
if (saved) {
- changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), oldSize, this.getNumberLists());
+ for (KeywordSearchList list : newLists) {
+ changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, list.getName());
+ }
for (KeywordSearchList over : overwritten) {
changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, over.getName());
}
@@ -235,13 +238,12 @@ public class KeywordSearchListsXML {
*/
boolean deleteList(String name) {
boolean deleted = false;
- final int oldSize = this.getNumberLists();
KeywordSearchList delList = getList(name);
if (delList != null) {
theLists.remove(name);
deleted = save();
}
- changeSupport.firePropertyChange(ListsEvt.LIST_DELETED.toString(), oldSize, this.getNumberLists());
+ changeSupport.firePropertyChange(ListsEvt.LIST_DELETED.toString(), null, name);
return deleted;
}