From 96a8bf9990306d060c2fbc96de559675bfe59aeb Mon Sep 17 00:00:00 2001 From: Dick Fickling Date: Thu, 7 Jun 2012 15:45:52 -0400 Subject: [PATCH 1/4] Synchronize keyword search ingest skipnsrl boolean and checkbox --- .../autopsy/keywordsearch/KeywordSearchIngestService.java | 4 ++++ .../keywordsearch/KeywordSearchListsManagementPanel.java | 7 +------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java index a3d854285f..0b28cda2af 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java @@ -810,4 +810,8 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi void setSkipKnown(boolean skip) { this.skipKnown = skip; } + + boolean getSkipKnown() { + return skipKnown; + } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java index d5a7c8c6b1..e865af3edc 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java @@ -24,23 +24,17 @@ */ package org.sleuthkit.autopsy.keywordsearch; -import java.awt.Component; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; 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.Logger; import javax.swing.JFileChooser; import javax.swing.JOptionPane; -import javax.swing.JTable; import javax.swing.event.ListSelectionListener; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.AbstractTableModel; -import javax.swing.table.DefaultTableCellRenderer; /** * @@ -103,6 +97,7 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel { } } }); + this.skipNSRLCheckBox.setSelected(KeywordSearchIngestService.getDefault().getSkipKnown()); } From 0232dac2ea190ca5b99c61586436d44e06d0e353 Mon Sep 17 00:00:00 2001 From: Dick Fickling Date: Fri, 8 Jun 2012 09:52:34 -0400 Subject: [PATCH 2/4] Remove callback from keyword panel to ingest servece. Service proactively gets new keywords, to updating manually was unnecessary --- .../KeywordSearchConfigurationAction.java | 1 - .../KeywordSearchConfigurationPanel.java | 13 +------------ .../keywordsearch/KeywordSearchIngestService.java | 6 ------ .../keywordsearch/KeywordSearchListsAbstract.java | 2 +- .../KeywordSearchListsViewerPanel.java | 12 ------------ 5 files changed, 2 insertions(+), 32 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationAction.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationAction.java index e775682af4..b5fcfece57 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationAction.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationAction.java @@ -40,7 +40,6 @@ class KeywordSearchConfigurationAction extends CallableSystemAction{ @Override public void actionPerformed(ActionEvent e) { - panel.save(); dialog.close(); } }); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel.java index 4eb06ede8b..298045c0ff 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchConfigurationPanel.java @@ -120,16 +120,5 @@ public class KeywordSearchConfigurationPanel extends javax.swing.JPanel { private javax.swing.JPanel jPanel2; private javax.swing.JSplitPane mainSplitPane; // End of variables declaration//GEN-END:variables - - void save() { - KeywordSearchListsXML loader = KeywordSearchListsXML.getCurrent(); - KeywordSearchIngestService service = KeywordSearchIngestService.getDefault(); - if (IngestManager.getDefault().isServiceRunning(service)) { - for (KeywordSearchList list : loader.getListsL()) { - if (list.getUseForIngest()) { - service.addToKeywordLists(list.getName()); - } - } - } - } + } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java index 3bb2a90aee..f40746184e 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java @@ -388,12 +388,6 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi List getKeywordLists() { return keywordLists == null ? new ArrayList() : keywordLists; } - - void addToKeywordLists(String name) { - if (!keywordLists.contains(name)) { - keywordLists.add(name); - } - } void checkRunCommitSearch() { //check if time to commit diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsAbstract.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsAbstract.java index 5f238a50b3..0f0960742a 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsAbstract.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsAbstract.java @@ -270,7 +270,7 @@ public abstract class KeywordSearchListsAbstract { boolean deleteList(String name) { boolean deleted = false; KeywordSearchList delList = getList(name); - if (delList != null) { + if (delList != null && !delList.isLocked()) { theLists.remove(name); deleted = save(); } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsViewerPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsViewerPanel.java index e91a923711..9d3e4762a9 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsViewerPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsViewerPanel.java @@ -158,12 +158,6 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer { } } }); - ingestListener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - addToIngestAction(e); - } - }; searchListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -329,12 +323,6 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer { } } - private void addToIngestAction(ActionEvent e) { - for(KeywordSearchList list : listsTableModel.getSelectedListsL()){ - KeywordSearchIngestService.getDefault().addToKeywordLists(list.getName()); - } - } - @Override public List getQueryList() { List ret = new ArrayList(); From 98f2b540cecf4367c43b14207c504b681aa649af Mon Sep 17 00:00:00 2001 From: Dick Fickling Date: Fri, 8 Jun 2012 09:52:57 -0400 Subject: [PATCH 3/4] Add delete key handler to Lists Management panel --- .../KeywordSearchListsManagementPanel.form | 3 +++ .../KeywordSearchListsManagementPanel.java | 21 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.form index a50507a34c..536a1b4ca7 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.form +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.form @@ -78,6 +78,9 @@ + + + diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java index e865af3edc..08b69b1a6f 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java @@ -24,6 +24,7 @@ */ package org.sleuthkit.autopsy.keywordsearch; +import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; @@ -119,13 +120,17 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel { setMinimumSize(new java.awt.Dimension(200, 0)); setPreferredSize(new java.awt.Dimension(200, 297)); - jScrollPane1.setBorder(null); jScrollPane1.setPreferredSize(new java.awt.Dimension(200, 402)); listsTable.setModel(tableModel); listsTable.setShowHorizontalLines(false); listsTable.setShowVerticalLines(false); listsTable.getTableHeader().setReorderingAllowed(false); + listsTable.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyPressed(java.awt.event.KeyEvent evt) { + listsTableKeyPressed(evt); + } + }); jScrollPane1.setViewportView(listsTable); newListButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsManagementPanel.class, "KeywordSearchListsManagementPanel.newListButton.text")); // NOI18N @@ -169,7 +174,7 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel { layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 267, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 249, Short.MAX_VALUE) .addGap(0, 0, 0) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(newListButton) @@ -285,6 +290,18 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel { KeywordSearchIngestService.getDefault().setSkipKnown(skipNSRLCheckBox.isSelected()); }//GEN-LAST:event_skipNSRLCheckBoxActionPerformed + private void listsTableKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_listsTableKeyPressed + if(evt.getKeyCode() == KeyEvent.VK_DELETE) { + int[] selected = listsTable.getSelectedRows(); + if(selected.length == 0) { + return; + } + KeywordSearchListsXML deleter = KeywordSearchListsXML.getCurrent(); + String listName = deleter.getListNames().get(selected[0]); + KeywordSearchListsXML.getCurrent().deleteList(listName); + } + }//GEN-LAST:event_listsTableKeyPressed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton importButton; private javax.swing.JScrollPane jScrollPane1; From 3b10a8e9e8b103cbc0ce7dfb4ab3ce3fcfde72e9 Mon Sep 17 00:00:00 2001 From: Dick Fickling Date: Fri, 8 Jun 2012 09:53:19 -0400 Subject: [PATCH 4/4] Support importing Encase lists, preserve hierarchy --- .../KeywordSearchListsEncase.java | 190 +++++++++++++++--- 1 file changed, 159 insertions(+), 31 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsEncase.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsEncase.java index 726d05f17f..0a264e4fdf 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsEncase.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsEncase.java @@ -19,28 +19,99 @@ package org.sleuthkit.autopsy.keywordsearch; import java.io.BufferedReader; -import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; -import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.logging.Level; -import javax.swing.JOptionPane; /** - * * @author dfickling + * KeywordSearchListsEncase adds support for Encase tab-delimited + * keyword list exports to Autopsy. + * + * load() does the I/O operation, converting lines from the text file to + * an unsorted list of EncaseFileEntrys + * The next step is to recreate the original folder hierarchy, + * and finally the EncaseFileEntries are converted to KeywordSearchLists + * */ public class KeywordSearchListsEncase extends KeywordSearchListsAbstract{ + ArrayList entriesUnsorted; + EncaseFileEntry rootEntry; + public KeywordSearchListsEncase(String encasePath) { super(encasePath); } + + /** + * Follow the EncaseFileEntry hierarchy starting with given entry + * Create list for each Folder entry, add keyword for each Expression + * @param entry + * @param parentPath + */ + private void doCreateListsFromEntries(EncaseFileEntry entry, String parentPath) { + String name; + if(parentPath.isEmpty()) { + name = entry.name; + } else { + name = parentPath + "/" + entry.name; + } + + List children = new ArrayList(); + for(EncaseFileEntry child : entry.children) { + switch(child.type) { + case Folder: + doCreateListsFromEntries(child, name); + break; + case Expression: + if(child.flags.contains(EncaseFlag.pg)) { // Skip GREP keywords + break; + } + children.add(new Keyword(child.value, true)); + break; + } + } + // Give each list a unique name + if(theLists.containsKey(name)) { + int i = 2; + while(theLists.containsKey(name + "(" + i + ")")) { + i+=1; + } + name = name + "(" + i + ")"; + } + // Don't create lists if there are no keywords + if (!children.isEmpty()) { + KeywordSearchList newList = new KeywordSearchList(name, new Date(), new Date(), + true, true, children); + theLists.put(name, newList); + } + } + + /** + * Convert entriesUnsorted (a list of childless and parentless EncaseFileEntries) into an EncaseFileEntry structure + */ + private void doCreateEntryStructure(EncaseFileEntry parent) { + if (!parent.isFull()) { + EncaseFileEntry child = entriesUnsorted.remove(0); + child.hasParent = true; + child.parent = parent; + parent.addChild(child); + if(!child.isFull()) { + doCreateEntryStructure(child); + } + if (!parent.isFull()) { + doCreateEntryStructure(parent); + } + } + if (parent.hasParent) { + doCreateEntryStructure(parent.parent); + } + } @Override public boolean save() { @@ -50,37 +121,36 @@ public class KeywordSearchListsEncase extends KeywordSearchListsAbstract{ @Override public boolean load() { try { - File theFile = new File(filePath); BufferedReader readBuffer = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "utf-16")); - String line; - // If any terms are grep terms, we'll show the user a dialog at the end. - boolean anyGrep = false; - List words = new ArrayList(); - while ((line = readBuffer.readLine()) != null) { - String[] tabDelim = line.split("\t"); - if (tabDelim.length > 2) { - String expr = tabDelim[2]; - if (tabDelim.length > 8) { - boolean literal = tabDelim[8].isEmpty() || !tabDelim[8].equals("1"); - anyGrep = anyGrep || !literal; - //TODO: Stop skipping non-literal search terms - if (!expr.isEmpty() && !expr.equals("t") && literal) { - words.add(new Keyword(expr, literal)); - } + String structLine; + String metaLine; + entriesUnsorted = new ArrayList(); + for(int line = 1; line < 6; line++) { + readBuffer.readLine(); + } + while ((structLine = readBuffer.readLine()) != null && (metaLine = readBuffer.readLine()) != null) { + String[] structArr = structLine.split("\t"); + String[] metaArr = metaLine.split("\t"); + EncaseMetaType type = EncaseMetaType.getType(metaArr[0]); + String childCount = structArr[1]; + String name = metaArr[1]; + String value = metaArr[2]; + ArrayList flags = new ArrayList(); + for(int i = 0; i < 17; i++) { + if(metaArr.length < i+4) { + continue; + } + if(!metaArr[i+3].equals("")) { + flags.add(EncaseFlag.getFlag(i)); } } + entriesUnsorted.add(new EncaseFileEntry(name, value, Integer.parseInt(childCount), false, null, type, flags)); } - theLists.put(theFile.getName(), - new KeywordSearchList(theFile.getName(), - new Date(theFile.lastModified()), - new Date(theFile.lastModified()), - true, true, words)); - if(anyGrep) { - JOptionPane.showMessageDialog(null, "Importing grep (regular expression) keywords is not currently supported. Any that were in the list " - + theFile.getName() + " have not been imported."); - } - + this.rootEntry = entriesUnsorted.remove(0); + doCreateEntryStructure(this.rootEntry); + doCreateListsFromEntries(this.rootEntry, ""); return true; + } catch (FileNotFoundException ex) { logger.log(Level.INFO, "File at " + filePath + " does not exist!", ex); } catch (IOException ex) { @@ -89,4 +159,62 @@ public class KeywordSearchListsEncase extends KeywordSearchListsAbstract{ return false; } + private enum EncaseMetaType { + Expression, Folder; + + static EncaseMetaType getType(String type) { + if(type.equals("5")) { + return Folder; + } else if(type.equals("")) { + return Expression; + } else { + throw new IllegalArgumentException("Unsupported EncaseMetaType: " + type); + } + } + } + + /* + * Flags for EncaseFileEntries. + * p8 = UTF-8 + * p7 = UTF-7 + * pg = GREP + */ + private enum EncaseFlag { + pc, pu, pb, p8, p7, pg, an, ph, or, di, um, st, ww, pr, lo, ta, cp; + + static EncaseFlag getFlag(int i) { + return EncaseFlag.values()[i]; + } + } + + /** + * An entry in the Encase keyword list file. + */ + private class EncaseFileEntry { + String name; + String value; + int childCount; + List children; + EncaseFileEntry parent; + EncaseMetaType type; + boolean hasParent; + ArrayList flags; + EncaseFileEntry(String name, String value, int childCount, boolean hasParent, EncaseFileEntry parent, EncaseMetaType type, ArrayList flags) { + this.name = name; + this.value = value; + this.childCount = childCount; + this.children = new ArrayList(); + this.hasParent = hasParent; + this.parent = parent; + this.type = type; + this.flags = flags; + } + boolean isFull() { + return children.size() == childCount; + } + void addChild(EncaseFileEntry child) { + children.add(child); + } + } + }