mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
TSK-299 Create Keyword List Export / Import Feature
This commit is contained in:
parent
3ed04eedf3
commit
f0af21f0ec
@ -1,7 +1,10 @@
|
||||
CTL_KeywordSearchListAction=List
|
||||
CTL_KeywordSearchListImportExportAction=Keyword Search List Import Export
|
||||
CTL_KeywordSearchListImportExportTopComponent=Keyword Search List Import Export Window
|
||||
CTL_KeywordSearchListTopComponent=List
|
||||
CTL_KeywordSearchTabsTopComponentAction=Keyword Search
|
||||
CTL_KeywordSearchTabsTopComponentTopComponent=Keyword Search
|
||||
HINT_KeywordSearchListImportExportTopComponent=Keyword Search List Import Export window
|
||||
HINT_KeywordSearchListTopComponent=Keyword Search List
|
||||
HINT_KeywordSearchTabsTopComponentTopComponent=Keyword Search window
|
||||
OpenIDE-Module-Name=KeywordSearch
|
||||
@ -34,3 +37,13 @@ KeywordSearchListTopComponent.addWordLabel.text=Add a new keyword:
|
||||
KeywordSearchListTopComponent.deleteWordButton.text=Delete
|
||||
KeywordSearchListTopComponent.deleteAllWordsButton.text=Delete All
|
||||
KeywordSearchSimpleTopComponent.chRegex.text=RegEx
|
||||
KeywordSearchListImportExportTopComponent.topLabel.text=Manage (import, export, delete) lists of keywords
|
||||
KeywordSearchListImportExportTopComponent.curKeywordsLabel.text=Current lists:
|
||||
KeywordSearchListImportExportTopComponent.importButton.text=Import
|
||||
KeywordSearchListImportExportTopComponent.exportButton.text=Export
|
||||
KeywordSearchListImportExportTopComponent.deleteButton.text=Delete
|
||||
KeywordSearchListImportExportTopComponent.filesIndexedNameLabel.text=Files indexed:
|
||||
KeywordSearchListImportExportTopComponent.filesIndexedValLabel.text=-
|
||||
KeywordSearchListTopComponent.curListNameLabel.text=Loaded list name:
|
||||
KeywordSearchListTopComponent.curListValLabel.text=-
|
||||
KeywordSearchListTopComponent.importButton.text=Import
|
||||
|
@ -0,0 +1,148 @@
|
||||
<?xml version="1.1" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane1" alignment="0" min="-2" pref="266" max="-2" attributes="1"/>
|
||||
<Component id="topLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="curKeywordsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="importButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="22" max="-2" attributes="0"/>
|
||||
<Component id="exportButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="deleteButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="filesIndexedNameLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="filesIndexedValLabel" min="-2" pref="62" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace pref="20" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="topLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="35" max="-2" attributes="0"/>
|
||||
<Component id="curKeywordsLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" min="-2" pref="227" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="29" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="importButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="deleteButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="exportButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="37" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="filesIndexedNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="filesIndexedValLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="62" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTable" name="listsTable">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="tableModel" type="code"/>
|
||||
</Property>
|
||||
<Property name="showHorizontalLines" type="boolean" value="false"/>
|
||||
<Property name="showVerticalLines" type="boolean" value="false"/>
|
||||
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
|
||||
<TableHeader reorderingAllowed="false" resizingAllowed="true"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="topLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchListImportExportTopComponent.topLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="curKeywordsLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchListImportExportTopComponent.curKeywordsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="importButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchListImportExportTopComponent.importButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="importButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="exportButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchListImportExportTopComponent.exportButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="exportButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="deleteButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchListImportExportTopComponent.deleteButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="filesIndexedNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchListImportExportTopComponent.filesIndexedNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="filesIndexedValLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchListImportExportTopComponent.filesIndexedValLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -0,0 +1,648 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.windows.TopComponent;
|
||||
import org.netbeans.api.settings.ConvertAsProperties;
|
||||
import org.openide.awt.ActionID;
|
||||
import org.openide.awt.ActionReference;
|
||||
|
||||
/**
|
||||
* Top component which displays something.
|
||||
*/
|
||||
@ConvertAsProperties(dtd = "-//org.sleuthkit.autopsy.keywordsearch//KeywordSearchListImportExport//EN",
|
||||
autostore = false)
|
||||
@TopComponent.Description(preferredID = "KeywordSearchListImportExportTopComponent",
|
||||
//iconBase="SET/PATH/TO/ICON/HERE",
|
||||
persistenceType = TopComponent.PERSISTENCE_NEVER)
|
||||
@TopComponent.Registration(mode = "explorer", openAtStartup = false)
|
||||
@ActionID(category = "Window", id = "org.sleuthkit.autopsy.keywordsearch.KeywordSearchListImportExportTopComponent")
|
||||
@ActionReference(path = "Menu/Window" /*, position = 333 */)
|
||||
@TopComponent.OpenActionRegistration(displayName = "#CTL_KeywordSearchListImportExportAction",
|
||||
preferredID = "KeywordSearchListImportExportTopComponent")
|
||||
public final class KeywordSearchListImportExportTopComponent extends TopComponent implements KeywordSearchTopComponentInterface {
|
||||
|
||||
private Logger logger = Logger.getLogger(KeywordSearchListImportExportTopComponent.class.getName());
|
||||
private KeywordListTableModel tableModel;
|
||||
|
||||
public KeywordSearchListImportExportTopComponent() {
|
||||
tableModel = new KeywordListTableModel();
|
||||
initComponents();
|
||||
customizeComponents();
|
||||
setName(NbBundle.getMessage(KeywordSearchListImportExportTopComponent.class, "CTL_KeywordSearchListImportExportTopComponent"));
|
||||
setToolTipText(NbBundle.getMessage(KeywordSearchListImportExportTopComponent.class, "HINT_KeywordSearchListImportExportTopComponent"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void customizeComponents() {
|
||||
|
||||
importButton.setToolTipText("Import list(s) of keywords from an external file.");
|
||||
exportButton.setToolTipText("Export selected list(s) of keywords to an external file.");
|
||||
deleteButton.setToolTipText("Delete selected list(s) of keywords.");
|
||||
|
||||
|
||||
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 < 4; i++) {
|
||||
column = listsTable.getColumnModel().getColumn(i);
|
||||
switch (i) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
column.setCellRenderer(new CellTooltipRenderer());
|
||||
column.setPreferredWidth(((int) (width * 0.28)));
|
||||
column.setResizable(true);
|
||||
break;
|
||||
case 3:
|
||||
column.setPreferredWidth(((int) (width * 0.15)));
|
||||
column.setResizable(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
listsTable.setCellSelectionEnabled(false);
|
||||
tableModel.resync();
|
||||
if (KeywordSearchListsXML.getCurrent().getNumberLists() == 0) {
|
||||
exportButton.setEnabled(false);
|
||||
}
|
||||
|
||||
KeywordSearchListsXML.getCurrent().addPropertyChangeListener(new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getPropertyName().equals(KeywordSearchListsXML.ListsEvt.LIST_ADDED.toString())
|
||||
|| evt.getPropertyName().equals(KeywordSearchListsXML.ListsEvt.LIST_DELETED.toString())) {
|
||||
tableModel.resync();
|
||||
|
||||
if (Integer.valueOf((Integer) evt.getNewValue()) == 0) {
|
||||
exportButton.setEnabled(false);
|
||||
} else if (Integer.valueOf((Integer) evt.getOldValue()) == 0) {
|
||||
exportButton.setEnabled(true);
|
||||
}
|
||||
} 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.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
listsTable = new javax.swing.JTable();
|
||||
topLabel = new javax.swing.JLabel();
|
||||
curKeywordsLabel = new javax.swing.JLabel();
|
||||
importButton = new javax.swing.JButton();
|
||||
exportButton = new javax.swing.JButton();
|
||||
deleteButton = new javax.swing.JButton();
|
||||
filesIndexedNameLabel = new javax.swing.JLabel();
|
||||
filesIndexedValLabel = new javax.swing.JLabel();
|
||||
|
||||
listsTable.setModel(tableModel);
|
||||
listsTable.setShowHorizontalLines(false);
|
||||
listsTable.setShowVerticalLines(false);
|
||||
listsTable.getTableHeader().setReorderingAllowed(false);
|
||||
jScrollPane1.setViewportView(listsTable);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(topLabel, org.openide.util.NbBundle.getMessage(KeywordSearchListImportExportTopComponent.class, "KeywordSearchListImportExportTopComponent.topLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(curKeywordsLabel, org.openide.util.NbBundle.getMessage(KeywordSearchListImportExportTopComponent.class, "KeywordSearchListImportExportTopComponent.curKeywordsLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(importButton, org.openide.util.NbBundle.getMessage(KeywordSearchListImportExportTopComponent.class, "KeywordSearchListImportExportTopComponent.importButton.text")); // NOI18N
|
||||
importButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
importButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(exportButton, org.openide.util.NbBundle.getMessage(KeywordSearchListImportExportTopComponent.class, "KeywordSearchListImportExportTopComponent.exportButton.text")); // NOI18N
|
||||
exportButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
exportButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(deleteButton, org.openide.util.NbBundle.getMessage(KeywordSearchListImportExportTopComponent.class, "KeywordSearchListImportExportTopComponent.deleteButton.text")); // NOI18N
|
||||
deleteButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
deleteButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(filesIndexedNameLabel, org.openide.util.NbBundle.getMessage(KeywordSearchListImportExportTopComponent.class, "KeywordSearchListImportExportTopComponent.filesIndexedNameLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(filesIndexedValLabel, org.openide.util.NbBundle.getMessage(KeywordSearchListImportExportTopComponent.class, "KeywordSearchListImportExportTopComponent.filesIndexedValLabel.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 266, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(topLabel)
|
||||
.addComponent(curKeywordsLabel)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(importButton)
|
||||
.addGap(22, 22, 22)
|
||||
.addComponent(exportButton)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(deleteButton))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(filesIndexedNameLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(filesIndexedValLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 62, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addContainerGap(20, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(topLabel)
|
||||
.addGap(35, 35, 35)
|
||||
.addComponent(curKeywordsLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 227, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(29, 29, 29)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(importButton)
|
||||
.addComponent(deleteButton)
|
||||
.addComponent(exportButton))
|
||||
.addGap(37, 37, 37)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(filesIndexedNameLabel)
|
||||
.addComponent(filesIndexedValLabel))
|
||||
.addContainerGap(62, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
public void importButtonAction(java.awt.event.ActionEvent evt) {
|
||||
importButtonActionPerformed(evt);
|
||||
}
|
||||
|
||||
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<KeywordSearchList> toImport = reader.getListsL();
|
||||
List<KeywordSearchList> toImportConfirmed = new ArrayList<KeywordSearchList>();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}//GEN-LAST:event_importButtonActionPerformed
|
||||
|
||||
private void exportButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportButtonActionPerformed
|
||||
final String FEATURE_NAME = "Keyword List Export";
|
||||
|
||||
List<String> toExport = tableModel.getSelectedLists();
|
||||
if (toExport.isEmpty()) {
|
||||
KeywordSearchUtil.displayDialog(FEATURE_NAME, "Please select keyword lists to export", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
final KeywordSearchListsXML reader = KeywordSearchListsXML.getCurrent();
|
||||
|
||||
List<KeywordSearchList> toWrite = new ArrayList<KeywordSearchList>();
|
||||
for (String listName : toExport) {
|
||||
toWrite.add(reader.getList(listName));
|
||||
}
|
||||
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 deleteButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteButtonActionPerformed
|
||||
tableModel.deleteSelected();
|
||||
}//GEN-LAST:event_deleteButtonActionPerformed
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JLabel curKeywordsLabel;
|
||||
private javax.swing.JButton deleteButton;
|
||||
private javax.swing.JButton exportButton;
|
||||
private javax.swing.JLabel filesIndexedNameLabel;
|
||||
private javax.swing.JLabel filesIndexedValLabel;
|
||||
private javax.swing.JButton importButton;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JTable listsTable;
|
||||
private javax.swing.JLabel topLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
@Override
|
||||
public void componentOpened() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentClosed() {
|
||||
}
|
||||
|
||||
void writeProperties(java.util.Properties p) {
|
||||
|
||||
p.setProperty("version", "1.0");
|
||||
|
||||
}
|
||||
|
||||
void readProperties(java.util.Properties p) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSearchButtonListener(ActionListener l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getQueryList() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLuceneQuerySelected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMultiwordQuery() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegexQuerySelected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFilesIndexed(int filesIndexed) {
|
||||
filesIndexedValLabel.setText(Integer.toString(filesIndexed));
|
||||
}
|
||||
|
||||
static class KeywordListTableModel extends AbstractTableModel {
|
||||
//data
|
||||
|
||||
private KeywordSearchListsXML listsHandle = KeywordSearchListsXML.getCurrent();
|
||||
private Set<TableEntry> listData = new TreeSet<TableEntry>();
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@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 = "Created";
|
||||
break;
|
||||
case 2:
|
||||
colName = "Modified";
|
||||
break;
|
||||
case 3:
|
||||
colName = "Sel.";
|
||||
break;
|
||||
default:
|
||||
;
|
||||
|
||||
}
|
||||
return colName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
Object ret = null;
|
||||
TableEntry entry = null;
|
||||
//iterate until row
|
||||
Iterator<TableEntry> 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.created;
|
||||
break;
|
||||
case 2:
|
||||
ret = (Object) entry.modified;
|
||||
break;
|
||||
case 3:
|
||||
ret = (Object) entry.isActive;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
return columnIndex == 3 ? true : false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
if (columnIndex == 3) {
|
||||
TableEntry entry = null;
|
||||
//iterate until row
|
||||
Iterator<TableEntry> it = listData.iterator();
|
||||
for (int i = 0; i <= rowIndex; ++i) {
|
||||
entry = it.next();
|
||||
}
|
||||
entry.isActive = (Boolean) aValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getColumnClass(int c) {
|
||||
return getValueAt(0, c).getClass();
|
||||
}
|
||||
|
||||
List<String> getAllLists() {
|
||||
List<String> ret = new ArrayList<String>();
|
||||
for (TableEntry e : listData) {
|
||||
ret.add(e.name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
List<String> getSelectedLists() {
|
||||
List<String> ret = new ArrayList<String>();
|
||||
for (TableEntry e : listData) {
|
||||
if (e.isActive && !e.name.equals("")) {
|
||||
ret.add(e.name);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
boolean listExists(String list) {
|
||||
List<String> all = getAllLists();
|
||||
return all.contains(list);
|
||||
}
|
||||
|
||||
//delete selected from handle, events are fired from the handle
|
||||
void deleteSelected() {
|
||||
List<TableEntry> toDel = new ArrayList<TableEntry>();
|
||||
for (TableEntry e : listData) {
|
||||
if (e.isActive && !e.name.equals("")) {
|
||||
toDel.add(e);
|
||||
}
|
||||
}
|
||||
for (TableEntry del : toDel) {
|
||||
listsHandle.deleteList(del.name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//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<KeywordSearchList> lists) {
|
||||
for (KeywordSearchList list : lists) {
|
||||
if (!listExists(list.getName())) {
|
||||
listData.add(new TableEntry(list));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//single model entry
|
||||
class TableEntry implements Comparable {
|
||||
|
||||
private DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
String name;
|
||||
String created;
|
||||
String modified;
|
||||
Boolean isActive;
|
||||
|
||||
TableEntry(KeywordSearchList list, Boolean isActive) {
|
||||
this.name = list.getName();
|
||||
this.created = dateFormatter.format(list.getDateCreated());
|
||||
this.modified = dateFormatter.format(list.getDateModified());
|
||||
this.isActive = isActive;
|
||||
}
|
||||
|
||||
TableEntry(KeywordSearchList list) {
|
||||
this.name = list.getName();
|
||||
this.created = dateFormatter.format(list.getDateCreated());
|
||||
this.modified = dateFormatter.format(list.getDateModified());
|
||||
this.isActive = 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -21,15 +21,12 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="chLiteralWord" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="titleLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="loadListButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="addWordLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="1">
|
||||
<Component id="deleteWordButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="deleteAllWordsButton" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="loadListButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="saveListButton" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="importButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="addWordLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="addWordField" min="-2" pref="152" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="31" max="-2" attributes="0"/>
|
||||
@ -43,6 +40,20 @@
|
||||
<Component id="filesIndexedValLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jScrollPane1" alignment="0" min="-2" pref="272" max="-2" attributes="0"/>
|
||||
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="1">
|
||||
<Component id="curListNameLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="curListValLabel" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="1">
|
||||
<Component id="deleteWordButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="deleteAllWordsButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="saveListButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace pref="15" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
@ -54,7 +65,10 @@
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="titleLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="loadListButton" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="loadListButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="importButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
|
||||
<Component id="addWordLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
@ -76,7 +90,12 @@
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="29" max="-2" attributes="0"/>
|
||||
<Component id="searchButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="38" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="curListNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="curListValLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="filesIndexedNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="filesIndexedValLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
@ -218,5 +237,29 @@
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="curListNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchListTopComponent.curListNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="curListValLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchListTopComponent.curListValLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="importButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchListTopComponent.importButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="importButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -23,6 +23,8 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
@ -40,6 +42,7 @@ import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
@ -49,6 +52,7 @@ import org.openide.windows.TopComponent;
|
||||
import org.netbeans.api.settings.ConvertAsProperties;
|
||||
import org.openide.awt.ActionID;
|
||||
import org.openide.awt.ActionReference;
|
||||
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchTabsTopComponent.TABS;
|
||||
|
||||
/**
|
||||
* Top component which displays something.
|
||||
@ -58,7 +62,7 @@ autostore = false)
|
||||
@TopComponent.Description(preferredID = "KeywordSearchListTopComponent",
|
||||
//iconBase="SET/PATH/TO/ICON/HERE",
|
||||
persistenceType = TopComponent.PERSISTENCE_NEVER)
|
||||
@TopComponent.Registration(mode = "output", openAtStartup = false)
|
||||
@TopComponent.Registration(mode = "explorer", openAtStartup = false)
|
||||
@ActionID(category = "Window", id = "org.sleuthkit.autopsy.keywordsearch.KeywordSearchListTopComponent")
|
||||
@ActionReference(path = "Menu/Window" /*, position = 333 */)
|
||||
@TopComponent.OpenActionRegistration(displayName = "#CTL_KeywordSearchListAction",
|
||||
@ -84,6 +88,7 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
addWordField.setToolTipText("Enter a new word or regex to search");
|
||||
|
||||
loadListButton.setToolTipText("Load a new keyword list from file or delete an existing list");
|
||||
importButton.setToolTipText("Import list(s) of keywords from an external file.");
|
||||
saveListButton.setToolTipText("Save the current keyword list to a file");
|
||||
searchButton.setToolTipText("Execute the keyword list search using the current list");
|
||||
deleteWordButton.setToolTipText("Delete selected keyword(s) from the list");
|
||||
@ -114,7 +119,26 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
|
||||
loadDefaultKeywords();
|
||||
|
||||
if (KeywordSearchListsXML.getInstance().getNumberLists() == 0) {
|
||||
KeywordSearchListsXML.getCurrent().addPropertyChangeListener(new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getPropertyName().equals(KeywordSearchListsXML.ListsEvt.LIST_DELETED.toString())) {
|
||||
//still keep keywords from deleted list in widgetm just disassociate the name
|
||||
currentKeywordList = null;
|
||||
curListValLabel.setText("-");
|
||||
if (Integer.valueOf((Integer) evt.getNewValue()) == 0) {
|
||||
loadListButton.setEnabled(false);
|
||||
}
|
||||
} else if (evt.getPropertyName().equals(KeywordSearchListsXML.ListsEvt.LIST_ADDED.toString())) {
|
||||
if (Integer.valueOf((Integer) evt.getOldValue()) == 0) {
|
||||
loadListButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (KeywordSearchListsXML.getCurrent().getNumberLists() == 0) {
|
||||
loadListButton.setEnabled(false);
|
||||
}
|
||||
}
|
||||
@ -160,6 +184,9 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
chLiteralWord = new javax.swing.JCheckBox();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
keywordTable = new javax.swing.JTable();
|
||||
curListNameLabel = new javax.swing.JLabel();
|
||||
curListValLabel = new javax.swing.JLabel();
|
||||
importButton = new javax.swing.JButton();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(searchButton, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.searchButton.text")); // NOI18N
|
||||
searchButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@ -228,6 +255,17 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
keywordTable.setShowVerticalLines(false);
|
||||
jScrollPane1.setViewportView(keywordTable);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(curListNameLabel, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.curListNameLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(curListValLabel, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.curListValLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(importButton, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.importButton.text")); // NOI18N
|
||||
importButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
importButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
@ -237,14 +275,11 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(chLiteralWord)
|
||||
.addComponent(titleLabel)
|
||||
.addComponent(loadListButton)
|
||||
.addComponent(addWordLabel)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(deleteWordButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(deleteAllWordsButton)
|
||||
.addComponent(loadListButton)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(saveListButton))
|
||||
.addComponent(importButton))
|
||||
.addComponent(addWordLabel)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(addWordField, javax.swing.GroupLayout.PREFERRED_SIZE, 152, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(31, 31, 31)
|
||||
@ -255,7 +290,18 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
.addComponent(filesIndexedNameLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(filesIndexedValLabel))
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 272, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 272, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addComponent(curListNameLabel)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(curListValLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addComponent(deleteWordButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(deleteAllWordsButton)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(saveListButton))))
|
||||
.addContainerGap(15, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
@ -264,7 +310,9 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
.addContainerGap()
|
||||
.addComponent(titleLabel)
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(loadListButton)
|
||||
.addComponent(importButton))
|
||||
.addGap(19, 19, 19)
|
||||
.addComponent(addWordLabel)
|
||||
.addGap(18, 18, 18)
|
||||
@ -284,7 +332,11 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
.addComponent(saveListButton))
|
||||
.addGap(29, 29, 29)
|
||||
.addComponent(searchButton)
|
||||
.addGap(38, 38, 38)
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(curListNameLabel)
|
||||
.addComponent(curListValLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(filesIndexedNameLabel)
|
||||
.addComponent(filesIndexedValLabel))
|
||||
@ -337,7 +389,7 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
|
||||
private void saveListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveListButtonActionPerformed
|
||||
final String FEATURE_NAME = "Save Keyword List";
|
||||
KeywordSearchListsXML writer = KeywordSearchListsXML.getInstance();
|
||||
KeywordSearchListsXML writer = KeywordSearchListsXML.getCurrent();
|
||||
|
||||
String listName = (String) JOptionPane.showInputDialog(
|
||||
null,
|
||||
@ -352,32 +404,27 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
}
|
||||
|
||||
List<String> keywords = tableModel.getAllKeywords();
|
||||
boolean shouldWrite = false;
|
||||
boolean written = false;
|
||||
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) {
|
||||
shouldWrite = true;
|
||||
shouldAdd = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
shouldWrite = true;
|
||||
shouldAdd = true;
|
||||
}
|
||||
|
||||
if (shouldWrite) {
|
||||
if (shouldAdd) {
|
||||
writer.addList(listName, keywords);
|
||||
written = writer.save();
|
||||
}
|
||||
|
||||
if (written) {
|
||||
currentKeywordList = listName;
|
||||
curListValLabel.setText(listName);
|
||||
KeywordSearchUtil.displayDialog(FEATURE_NAME, "Keyword List <" + listName + "> saved", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
|
||||
//enable load button if it was previously disabled, as lists now exist
|
||||
if (loadListButton.isEnabled() == false) {
|
||||
loadListButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}//GEN-LAST:event_saveListButtonActionPerformed
|
||||
|
||||
private void chLiteralWordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chLiteralWordActionPerformed
|
||||
@ -395,35 +442,44 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
|
||||
final String FEATURE_NAME = "Load Keyword List";
|
||||
|
||||
KeywordSearchListsXML loader = KeywordSearchListsXML.getInstance();
|
||||
KeywordSearchListsXML loader = KeywordSearchListsXML.getCurrent();
|
||||
|
||||
final String listName = showLoadDeleteListDialog(FEATURE_NAME, loader.getListNames().toArray(), currentKeywordList, true);
|
||||
|
||||
if (listName == null || listName.equals("")) {
|
||||
return;
|
||||
}
|
||||
|
||||
KeywordSearchList list = loader.getList(listName);
|
||||
if (list != null) {
|
||||
List<String> keywords = list.getKeywords();
|
||||
|
||||
//TODO clear/append option ?
|
||||
tableModel.deleteAll();
|
||||
tableModel.addKeywords(keywords);
|
||||
currentKeywordList = listName;
|
||||
tableModel.resync(currentKeywordList);
|
||||
curListValLabel.setText(listName);
|
||||
|
||||
KeywordSearchUtil.displayDialog(FEATURE_NAME, "Keyword List <" + listName + "> loaded", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
|
||||
}
|
||||
|
||||
|
||||
}//GEN-LAST:event_loadListButtonActionPerformed
|
||||
|
||||
private void importButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importButtonActionPerformed
|
||||
//delegate to lists component
|
||||
JTabbedPane tabs = (JTabbedPane) this.getParent();
|
||||
KeywordSearchListImportExportTopComponent lists = (KeywordSearchListImportExportTopComponent) tabs.getComponentAt(TABS.Lists.ordinal());
|
||||
if (lists != null) {
|
||||
lists.importButtonAction(evt);
|
||||
}
|
||||
|
||||
}//GEN-LAST:event_importButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton addWordButton;
|
||||
private javax.swing.JTextField addWordField;
|
||||
private javax.swing.JLabel addWordLabel;
|
||||
private javax.swing.JCheckBox chLiteralWord;
|
||||
private javax.swing.JLabel curListNameLabel;
|
||||
private javax.swing.JLabel curListValLabel;
|
||||
private javax.swing.JButton deleteAllWordsButton;
|
||||
private javax.swing.JButton deleteWordButton;
|
||||
private javax.swing.JLabel filesIndexedNameLabel;
|
||||
private javax.swing.JLabel filesIndexedValLabel;
|
||||
private javax.swing.JButton importButton;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JTable keywordTable;
|
||||
private javax.swing.JLabel listLabel;
|
||||
@ -432,6 +488,23 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
private javax.swing.JButton searchButton;
|
||||
private javax.swing.JLabel titleLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
private JComboBox loadListCombo;
|
||||
|
||||
private JComboBox findDialogComponent(Component component) {
|
||||
if (component instanceof JComboBox) {
|
||||
loadListCombo = (JComboBox) component;
|
||||
} else if (component instanceof JPanel) {
|
||||
for (Component c : ((JPanel) component).getComponents()) {
|
||||
findDialogComponent(c);
|
||||
}
|
||||
} else if (component instanceof JOptionPane) {
|
||||
for (Component c : ((JOptionPane) component).getComponents()) {
|
||||
findDialogComponent(c);
|
||||
}
|
||||
|
||||
}
|
||||
return loadListCombo;
|
||||
}
|
||||
|
||||
private String showLoadDeleteListDialog(final String title, Object[] choices, Object initialChoice, boolean deleteOption) {
|
||||
if (deleteOption) {
|
||||
@ -444,64 +517,11 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
loadPane.setWantsInput(true);
|
||||
loadPane.setSelectionValues(choices);
|
||||
loadPane.setInitialSelectionValue(initialChoice);
|
||||
//loadPane.setValue(initialChoice);
|
||||
|
||||
final JDialog loadDialog = loadPane.createDialog(null, title);
|
||||
final JPopupMenu rightClickMenu = new JPopupMenu();
|
||||
JMenuItem delItem = new JMenuItem("Delete List");
|
||||
|
||||
delItem.addActionListener(new ActionListener() {
|
||||
JComboBox combo;
|
||||
//find the combo component
|
||||
private JComboBox getDialogComponent(Component component) {
|
||||
if (component instanceof JComboBox) {
|
||||
combo = (JComboBox)component;
|
||||
} else if (component instanceof JPanel) {
|
||||
for (Component c : ((JPanel) component).getComponents()) {
|
||||
getDialogComponent(c);
|
||||
}
|
||||
} else if (component instanceof JOptionPane) {
|
||||
for (Component c : ((JOptionPane) component).getComponents()) {
|
||||
getDialogComponent(c);
|
||||
}
|
||||
|
||||
}
|
||||
return combo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
//there is no JOptionPane API to get current from combobox before OK is pressed
|
||||
//workaround traversing the widgets
|
||||
String selList = null;
|
||||
combo = getDialogComponent(loadPane);
|
||||
if (combo != null) {
|
||||
selList = (String) combo.getSelectedItem();
|
||||
}
|
||||
|
||||
|
||||
if (selList != null && selList != JOptionPane.UNINITIALIZED_VALUE) {
|
||||
KeywordSearchListsXML loader = KeywordSearchListsXML.getInstance();
|
||||
boolean deleted = loader.deleteList(selList);
|
||||
if (deleted) {
|
||||
Object[] choices = loader.getListNames().toArray();
|
||||
loadPane.setSelectionValues(choices);
|
||||
if (choices.length > 0) {
|
||||
loadPane.setInitialSelectionValue(choices[0]);
|
||||
}
|
||||
loadPane.selectInitialValue();
|
||||
KeywordSearchUtil.displayDialog(title, "Keyword List <" + selList + "> deleted", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
rightClickMenu.setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
rightClickMenu.add(delItem);
|
||||
|
||||
loadPane.addMouseListener(new MouseListener() {
|
||||
final MouseListener rightClickListener = new MouseListener() {
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
@ -526,15 +546,59 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
rightClickMenu.setVisible(false);
|
||||
}
|
||||
};
|
||||
JMenuItem delItem = new JMenuItem("Delete List");
|
||||
|
||||
delItem.addActionListener(new ActionListener() {
|
||||
|
||||
JComboBox combo;
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
String selList = null;
|
||||
//there is no JOptionPane API to get current from combobox before OK is pressed
|
||||
//workaround traversing the widgets
|
||||
combo = findDialogComponent(loadPane);
|
||||
|
||||
if (combo != null) {
|
||||
selList = (String) combo.getSelectedItem();
|
||||
}
|
||||
|
||||
if (selList != null && selList != JOptionPane.UNINITIALIZED_VALUE) {
|
||||
KeywordSearchListsXML loader = KeywordSearchListsXML.getCurrent();
|
||||
boolean deleted = loader.deleteList(selList);
|
||||
if (deleted) {
|
||||
Object[] choices = loader.getListNames().toArray();
|
||||
loadPane.setSelectionValues(choices);
|
||||
if (choices.length > 0) {
|
||||
loadPane.setInitialSelectionValue(choices[0]);
|
||||
}
|
||||
loadPane.selectInitialValue();
|
||||
combo = findDialogComponent(loadPane);
|
||||
combo.addMouseListener(rightClickListener);
|
||||
KeywordSearchUtil.displayDialog(title, "Keyword List <" + selList + "> deleted", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
|
||||
}
|
||||
}
|
||||
rightClickMenu.setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
rightClickMenu.add(delItem);
|
||||
|
||||
JComboBox combo = findDialogComponent(loadPane);
|
||||
combo.addMouseListener(rightClickListener);
|
||||
|
||||
loadPane.selectInitialValue();
|
||||
loadDialog.setVisible(true);
|
||||
loadDialog.dispose();
|
||||
String retString = (String) loadPane.getInputValue();
|
||||
if (retString == JOptionPane.UNINITIALIZED_VALUE) //no choice was made
|
||||
{
|
||||
retString = null;
|
||||
}
|
||||
|
||||
return (String) loadPane.getInputValue();
|
||||
return retString;
|
||||
} else {
|
||||
return (String) JOptionPane.showInputDialog(
|
||||
null,
|
||||
@ -629,9 +693,8 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
}
|
||||
|
||||
static class KeywordTableModel extends AbstractTableModel {
|
||||
|
||||
private static Logger logger = Logger.getLogger(KeywordTableModel.class.getName());
|
||||
//data
|
||||
|
||||
private Set<TableEntry> keywordData = new TreeSet<TableEntry>();
|
||||
|
||||
@Override
|
||||
@ -729,6 +792,15 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
void resync(String listName) {
|
||||
KeywordSearchListsXML loader = KeywordSearchListsXML.getCurrent();
|
||||
KeywordSearchList list = loader.getList(listName);
|
||||
List<String> keywords = list.getKeywords();
|
||||
|
||||
deleteAll();
|
||||
addKeywords(keywords);
|
||||
}
|
||||
|
||||
void deleteAll() {
|
||||
keywordData.clear();
|
||||
fireTableDataChanged();
|
||||
@ -736,7 +808,7 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
|
||||
void deleteSelected() {
|
||||
List<TableEntry> toDel = new ArrayList<TableEntry>();
|
||||
int i = 0;
|
||||
|
||||
for (TableEntry e : keywordData) {
|
||||
if (e.isActive && !e.keyword.equals("")) {
|
||||
toDel.add(e);
|
||||
@ -774,7 +846,7 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
|
||||
/**
|
||||
* tooltips that show entire query string
|
||||
*/
|
||||
public static class CellTooltipRenderer extends DefaultTableCellRenderer {
|
||||
private static class CellTooltipRenderer extends DefaultTableCellRenderer {
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
@ -54,6 +56,7 @@ import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Manages reading and writing of keyword lists to user settings XML file keywords.xml
|
||||
* or to any file provided in constructor
|
||||
*/
|
||||
public class KeywordSearchListsXML {
|
||||
|
||||
@ -63,25 +66,49 @@ public class KeywordSearchListsXML {
|
||||
private static final String LIST_CREATE_ATTR = "created";
|
||||
private static final String LIST_MOD_ATTR = "modified";
|
||||
private static final String KEYWORD_EL = "keyword";
|
||||
private static final String LISTS_FILE_NAME = "keywords.xml";
|
||||
private static final String CUR_LISTS_FILE_NAME = "keywords.xml";
|
||||
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||
private static final String ENCODING = "UTF-8";
|
||||
private String LISTS_FILE = AutopsyPropFile.getUserDirPath() + File.separator + LISTS_FILE_NAME;
|
||||
private static String CUR_LISTS_FILE = AutopsyPropFile.getUserDirPath() + File.separator + CUR_LISTS_FILE_NAME;
|
||||
private static final Logger logger = Logger.getLogger(KeywordSearchListsXML.class.getName());
|
||||
|
||||
Map<String, KeywordSearchList> theLists; //the keyword data
|
||||
static KeywordSearchListsXML currentInstance = null;
|
||||
private String xmlFile;
|
||||
private DateFormat dateFormatter;
|
||||
|
||||
static KeywordSearchListsXML theInstance = null;
|
||||
//property support
|
||||
public enum ListsEvt {
|
||||
|
||||
private KeywordSearchListsXML() {
|
||||
LIST_ADDED, LIST_DELETED, LIST_UPDATED
|
||||
};
|
||||
private PropertyChangeSupport changeSupport;
|
||||
|
||||
/**
|
||||
* Constructor to obtain handle on other that the current keyword list
|
||||
* (such as for import or export)
|
||||
* @param xmlFile xmlFile to obtain KeywordSearchListsXML handle on
|
||||
*/
|
||||
KeywordSearchListsXML(String xmlFile) {
|
||||
theLists = new LinkedHashMap<String, KeywordSearchList>();
|
||||
this.xmlFile = xmlFile;
|
||||
changeSupport = new PropertyChangeSupport(this);
|
||||
|
||||
dateFormatter = new SimpleDateFormat(DATE_FORMAT);
|
||||
}
|
||||
|
||||
static KeywordSearchListsXML getInstance() {
|
||||
if (theInstance == null) {
|
||||
theInstance = new KeywordSearchListsXML();
|
||||
theInstance.reload();
|
||||
/**
|
||||
* get instance for managing the current keyword list of the application
|
||||
*/
|
||||
static KeywordSearchListsXML getCurrent() {
|
||||
if (currentInstance == null) {
|
||||
currentInstance = new KeywordSearchListsXML(CUR_LISTS_FILE);
|
||||
currentInstance.reload();
|
||||
}
|
||||
return theInstance;
|
||||
return currentInstance;
|
||||
}
|
||||
|
||||
void addPropertyChangeListener(PropertyChangeListener l) {
|
||||
changeSupport.addPropertyChangeListener(l);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,33 +116,36 @@ public class KeywordSearchListsXML {
|
||||
*/
|
||||
public void reload() {
|
||||
boolean created = false;
|
||||
theLists = new LinkedHashMap<String, KeywordSearchList>();
|
||||
|
||||
theLists.clear();
|
||||
if (!this.listFileExists()) {
|
||||
//create new if it doesn't exist
|
||||
save();
|
||||
created = true;
|
||||
}
|
||||
|
||||
//load, if fails to laod create new
|
||||
if (!load() && !created) {
|
||||
//create new if failed to load
|
||||
save();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* get all loaded keyword lists
|
||||
* @return List of keyword list objects
|
||||
*/
|
||||
Map<String, KeywordSearchList> getLists() {
|
||||
return theLists;
|
||||
List<KeywordSearchList> getListsL() {
|
||||
List<KeywordSearchList> ret = new ArrayList<KeywordSearchList>();
|
||||
for (KeywordSearchList list : theLists.values()) {
|
||||
ret.add(list);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* get list of all loaded keyword list names
|
||||
* @return List of keyword list names
|
||||
*/
|
||||
List<String>getListNames() {
|
||||
List<String> getListNames() {
|
||||
return new ArrayList<String>(theLists.keySet());
|
||||
}
|
||||
|
||||
@ -148,7 +178,6 @@ public class KeywordSearchListsXML {
|
||||
/**
|
||||
* adds the new word list using name id
|
||||
* replacing old one if exists with the same name
|
||||
* requires following call to save() to make permanent changes
|
||||
* @param name the name of the new list or list to replace
|
||||
* @param newList list of keywords
|
||||
* @return true if old list was replaced
|
||||
@ -157,15 +186,47 @@ 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());
|
||||
} else {
|
||||
theLists.put(name, new KeywordSearchList(name, curList.getDateCreated(), now, newList));
|
||||
save();
|
||||
replaced = true;
|
||||
changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, name);
|
||||
}
|
||||
|
||||
return replaced;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* write out multiple lists
|
||||
* @param lists
|
||||
* @return
|
||||
*/
|
||||
boolean writeLists(List<KeywordSearchList> lists) {
|
||||
int oldSize = this.getNumberLists();
|
||||
|
||||
List<KeywordSearchList> overwritten = new ArrayList<KeywordSearchList>();
|
||||
|
||||
for (KeywordSearchList list : lists) {
|
||||
if (this.listExists(list.getName()))
|
||||
overwritten.add(list);
|
||||
theLists.put(list.getName(), list);
|
||||
}
|
||||
boolean saved = save();
|
||||
if (saved) {
|
||||
changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), oldSize, this.getNumberLists());
|
||||
for (KeywordSearchList over : overwritten) {
|
||||
changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, over.getName());
|
||||
}
|
||||
}
|
||||
return saved;
|
||||
}
|
||||
|
||||
/**
|
||||
* delete list if exists and save new list
|
||||
* @param name of list to delete
|
||||
@ -173,11 +234,13 @@ 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());
|
||||
return deleted;
|
||||
|
||||
}
|
||||
@ -185,9 +248,9 @@ public class KeywordSearchListsXML {
|
||||
/**
|
||||
* writes out current list replacing the last lists file
|
||||
*/
|
||||
boolean save() {
|
||||
private boolean save() {
|
||||
boolean success = false;
|
||||
DateFormat dateFormatter = new SimpleDateFormat(DATE_FORMAT);
|
||||
|
||||
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
|
||||
|
||||
try {
|
||||
@ -223,18 +286,14 @@ public class KeywordSearchListsXML {
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* load and parse XML, then dispose
|
||||
*/
|
||||
private boolean load() {
|
||||
public boolean load() {
|
||||
final Document doc = loadDoc();
|
||||
if (doc == null) {
|
||||
return false;
|
||||
}
|
||||
DateFormat dateFormatter = new SimpleDateFormat(DATE_FORMAT);
|
||||
|
||||
|
||||
Element root = doc.getDocumentElement();
|
||||
if (root == null) {
|
||||
@ -273,7 +332,7 @@ public class KeywordSearchListsXML {
|
||||
}
|
||||
|
||||
private boolean listFileExists() {
|
||||
File f = new File(LISTS_FILE);
|
||||
File f = new File(xmlFile);
|
||||
return f.exists() && f.canRead() && f.canWrite();
|
||||
}
|
||||
|
||||
@ -287,7 +346,7 @@ public class KeywordSearchListsXML {
|
||||
try {
|
||||
DocumentBuilder builder = builderFactory.newDocumentBuilder();
|
||||
ret = builder.parse(
|
||||
new FileInputStream(LISTS_FILE));
|
||||
new FileInputStream(xmlFile));
|
||||
} catch (ParserConfigurationException e) {
|
||||
logger.log(Level.SEVERE, "Error loading keyword list: can't initialize parser.", e);
|
||||
|
||||
@ -314,9 +373,14 @@ public class KeywordSearchListsXML {
|
||||
xformer.setOutputProperty(OutputKeys.ENCODING, ENCODING);
|
||||
xformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
|
||||
xformer.setOutputProperty(OutputKeys.VERSION, "1.0");
|
||||
Result out = new StreamResult(new OutputStreamWriter(new FileOutputStream(new File(LISTS_FILE)), ENCODING));
|
||||
File file = new File(xmlFile);
|
||||
FileOutputStream stream = new FileOutputStream(file);
|
||||
Result out = new StreamResult(new OutputStreamWriter(stream, ENCODING));
|
||||
xformer.transform(new DOMSource(doc), out);
|
||||
stream.flush();
|
||||
stream.close();
|
||||
success = true;
|
||||
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
logger.log(Level.SEVERE, "Should not happen", e);
|
||||
} catch (TransformerConfigurationException e) {
|
||||
@ -324,7 +388,9 @@ public class KeywordSearchListsXML {
|
||||
} catch (TransformerException e) {
|
||||
logger.log(Level.SEVERE, "Error writing keyword lists XML", e);
|
||||
} catch (FileNotFoundException e) {
|
||||
logger.log(Level.SEVERE, "Error writing keyword lists XML: cannot write to file: " + LISTS_FILE, e);
|
||||
logger.log(Level.SEVERE, "Error writing keyword lists XML: cannot write to file: " + xmlFile, e);
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.SEVERE, "Error writing keyword lists XML: cannot write to file: " + xmlFile, e);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@ -348,6 +414,27 @@ class KeywordSearchList {
|
||||
this.keywords = keywords;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final KeywordSearchList other = (KeywordSearchList) obj;
|
||||
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
return hash;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
@ -49,6 +50,8 @@ public final class KeywordSearchTabsTopComponent extends TopComponent implements
|
||||
private Logger logger = Logger.getLogger(KeywordSearchTabsTopComponent.class.getName());
|
||||
private PropertyChangeListener serverChangeListener;
|
||||
|
||||
public enum TABS{Simple, List, Lists};
|
||||
|
||||
public KeywordSearchTabsTopComponent() {
|
||||
initComponents();
|
||||
initTabs();
|
||||
@ -89,8 +92,9 @@ public final class KeywordSearchTabsTopComponent extends TopComponent implements
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
private void initTabs() {
|
||||
tabs.addTab("Simple", null, new KeywordSearchSimpleTopComponent(), "Single keyword or regex search");
|
||||
tabs.addTab("List", null, new KeywordSearchListTopComponent(), "Search for or load a saved list of keywords.");
|
||||
tabs.addTab(TABS.Simple.name(), null, new KeywordSearchSimpleTopComponent(), "Single keyword or regex search");
|
||||
tabs.addTab(TABS.List.name(), null, new KeywordSearchListTopComponent(), "Search for or load a saved list of keywords.");
|
||||
tabs.addTab(TABS.Lists.name(), null, new KeywordSearchListImportExportTopComponent(), "Manage (import, export, delete) lists of keywords.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user