19 package org.sleuthkit.autopsy.modules.hashdatabase;
 
   21 import java.awt.Color;
 
   22 import java.awt.event.ActionEvent;
 
   23 import java.awt.event.ActionListener;
 
   24 import java.awt.event.KeyAdapter;
 
   25 import java.awt.event.KeyEvent;
 
   26 import java.util.ArrayList;
 
   28 import org.openide.util.NbBundle;
 
   30 import javax.swing.JOptionPane;
 
   31 import javax.swing.table.DefaultTableModel;
 
   32 import javax.swing.text.AttributeSet;
 
   33 import javax.swing.text.BadLocationException;
 
   34 import javax.swing.text.PlainDocument;
 
   41 @SuppressWarnings(
"PMD.SingularField") 
 
   42 class HashDbSearchPanel extends javax.swing.JPanel implements ActionListener {
 
   44     private static final Logger logger = Logger.getLogger(HashDbSearchPanel.class.getName());
 
   45     private static HashDbSearchPanel instance;
 
   50     public static HashDbSearchPanel getDefault() {
 
   51         if (instance == null) {
 
   52             instance = 
new HashDbSearchPanel();
 
   60     public void refresh() {
 
   61         boolean running = IngestManager.getInstance().isIngestRunning();
 
   63             titleLabel.setForeground(Color.red);
 
   64             titleLabel.setText(NbBundle.getMessage(
this.getClass(), 
"HashDbSearchPanel.titleText.ingestOngoing"));
 
   66             titleLabel.setForeground(Color.black);
 
   67             titleLabel.setText(NbBundle.getMessage(
this.getClass(), 
"HashDbSearchPanel.titleLabel.text"));
 
   69         hashField.setEditable(!running);
 
   70         searchButton.setEnabled(!running);
 
   71         addButton.setEnabled(!running);
 
   72         removeButton.setEnabled(!running);
 
   73         hashTable.setEnabled(!running);
 
   74         hashLabel.setEnabled(!running);
 
   75         saveBox.setEnabled(!running);
 
   81     private HashDbSearchPanel() {
 
   82         setName(HashDbPanelSearchAction.ACTION_NAME);
 
   87     final void customInit() {
 
   88         addButton.addActionListener(
this);
 
   89         removeButton.addActionListener(
this);
 
   90         errorField.setVisible(
false);
 
   91         hashField.requestFocus();
 
   93         hashField.setDocument(
new PlainDocument() {
 
   95             public void insertString(
int offset, String str, AttributeSet a) 
throws BadLocationException {
 
   96                 if ((this.getLength() + str.length()) <= 32) {
 
   97                     super.insertString(offset, str, a);
 
  102         hashField.addKeyListener(
new KeyAdapter() {
 
  104             public void keyPressed(KeyEvent e) {
 
  105                 if (e.getKeyChar() == KeyEvent.VK_ENTER) {
 
  111         hashTable.addKeyListener(
new KeyAdapter() {
 
  113             public void keyPressed(KeyEvent e) {
 
  114                 if (e.getKeyChar() == KeyEvent.VK_DELETE) {
 
  115                     removeButton.doClick();
 
  121     void addSearchActionListener(ActionListener l) {
 
  122         for (ActionListener al : searchButton.getActionListeners()) {
 
  123             searchButton.removeActionListener(al);
 
  125         searchButton.addActionListener(l);
 
  128     void addCancelActionListener(ActionListener l) {
 
  129         cancelButton.addActionListener(l);
 
  137     @SuppressWarnings(
"rawtypes")
 
  139     private 
void initComponents() {
 
  141         jScrollPane1 = 
new javax.swing.JScrollPane();
 
  142         hashTable = 
new javax.swing.JTable();
 
  143         hashField = 
new javax.swing.JTextField();
 
  144         addButton = 
new javax.swing.JButton();
 
  145         hashLabel = 
new javax.swing.JLabel();
 
  146         searchButton = 
new javax.swing.JButton();
 
  147         removeButton = 
new javax.swing.JButton();
 
  148         jSeparator1 = 
new javax.swing.JSeparator();
 
  149         titleLabel = 
new javax.swing.JLabel();
 
  150         errorField = 
new javax.swing.JLabel();
 
  151         saveBox = 
new javax.swing.JCheckBox();
 
  152         cancelButton = 
new javax.swing.JButton();
 
  154         hashTable.setModel(
new javax.swing.table.DefaultTableModel(
 
  162             Class[] types = 
new Class [] {
 
  163                 java.lang.String.class
 
  165             boolean[] canEdit = 
new boolean [] {
 
  169             public Class getColumnClass(
int columnIndex) {
 
  170                 return types [columnIndex];
 
  173             public boolean isCellEditable(
int rowIndex, 
int columnIndex) {
 
  174                 return canEdit [columnIndex];
 
  177         jScrollPane1.setViewportView(hashTable);
 
  178         if (hashTable.getColumnModel().getColumnCount() > 0) {
 
  179             hashTable.getColumnModel().getColumn(0).setHeaderValue(
org.openide.util.NbBundle.getMessage(HashDbSearchPanel.class, 
"HashDbSearchPanel.hashTable.columnModel.title0")); 
 
  182         hashField.setText(
org.openide.util.NbBundle.getMessage(HashDbSearchPanel.class, 
"HashDbSearchPanel.hashField.text")); 
 
  184         org.openide.awt.Mnemonics.setLocalizedText(addButton, 
org.openide.util.NbBundle.getMessage(HashDbSearchPanel.class, 
"HashDbSearchPanel.addButton.text")); 
 
  186         org.openide.awt.Mnemonics.setLocalizedText(hashLabel, 
org.openide.util.NbBundle.getMessage(HashDbSearchPanel.class, 
"HashDbSearchPanel.hashLabel.text")); 
 
  188         org.openide.awt.Mnemonics.setLocalizedText(searchButton, 
org.openide.util.NbBundle.getMessage(HashDbSearchPanel.class, 
"HashDbSearchPanel.searchButton.text")); 
 
  190         org.openide.awt.Mnemonics.setLocalizedText(removeButton, 
org.openide.util.NbBundle.getMessage(HashDbSearchPanel.class, 
"HashDbSearchPanel.removeButton.text")); 
 
  192         org.openide.awt.Mnemonics.setLocalizedText(titleLabel, 
org.openide.util.NbBundle.getMessage(HashDbSearchPanel.class, 
"HashDbSearchPanel.titleLabel.text")); 
 
  194         errorField.setForeground(
new java.awt.Color(255, 0, 0));
 
  195         org.openide.awt.Mnemonics.setLocalizedText(errorField, 
org.openide.util.NbBundle.getMessage(HashDbSearchPanel.class, 
"HashDbSearchPanel.errorField.text")); 
 
  197         org.openide.awt.Mnemonics.setLocalizedText(saveBox, 
org.openide.util.NbBundle.getMessage(HashDbSearchPanel.class, 
"HashDbSearchPanel.saveBox.text")); 
 
  198         saveBox.addActionListener(
new java.awt.event.ActionListener() {
 
  199             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  200                 saveBoxActionPerformed(evt);
 
  204         org.openide.awt.Mnemonics.setLocalizedText(cancelButton, 
org.openide.util.NbBundle.getMessage(HashDbSearchPanel.class, 
"HashDbSearchPanel.cancelButton.text")); 
 
  206         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  207         this.setLayout(layout);
 
  208         layout.setHorizontalGroup(
 
  209             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  210             .addGroup(layout.createSequentialGroup()
 
  212                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  213                     .addComponent(jScrollPane1)
 
  214                     .addGroup(layout.createSequentialGroup()
 
  215                         .addComponent(hashLabel)
 
  216                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  217                         .addComponent(hashField))
 
  218                     .addComponent(jSeparator1)
 
  219                     .addGroup(layout.createSequentialGroup()
 
  220                         .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  221                             .addComponent(titleLabel)
 
  222                             .addGroup(layout.createSequentialGroup()
 
  224                                 .addComponent(addButton)
 
  225                                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  226                                 .addComponent(removeButton)
 
  227                                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  228                                 .addComponent(saveBox)))
 
  229                         .addGap(0, 0, Short.MAX_VALUE))
 
  230                     .addGroup(layout.createSequentialGroup()
 
  231                         .addComponent(errorField)
 
  232                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  233                         .addComponent(searchButton)
 
  234                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  235                         .addComponent(cancelButton)))
 
  238         layout.setVerticalGroup(
 
  239             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  240             .addGroup(layout.createSequentialGroup()
 
  242                 .addComponent(titleLabel)
 
  243                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  244                 .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 171, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  246                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  247                     .addComponent(hashLabel)
 
  248                     .addComponent(hashField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  249                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  250                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  251                     .addComponent(addButton)
 
  252                     .addComponent(removeButton)
 
  253                     .addComponent(saveBox))
 
  255                 .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  256                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  257                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  258                     .addComponent(searchButton)
 
  259                     .addComponent(errorField)
 
  260                     .addComponent(cancelButton))
 
  261                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  265     private void saveBoxActionPerformed(java.awt.event.ActionEvent evt) {
 
  270     private javax.swing.JButton addButton;
 
  271     private javax.swing.JButton cancelButton;
 
  272     private javax.swing.JLabel errorField;
 
  273     private javax.swing.JTextField hashField;
 
  274     private javax.swing.JLabel hashLabel;
 
  275     private javax.swing.JTable hashTable;
 
  276     private javax.swing.JScrollPane jScrollPane1;
 
  277     private javax.swing.JSeparator jSeparator1;
 
  278     private javax.swing.JButton removeButton;
 
  279     private javax.swing.JCheckBox saveBox;
 
  280     private javax.swing.JButton searchButton;
 
  281     private javax.swing.JLabel titleLabel;
 
  285     public void actionPerformed(ActionEvent e) {
 
  286         if (e.getSource().equals(addButton)) {
 
  288         } 
else if (e.getSource().equals(removeButton)) {
 
  297     @NbBundle.Messages ({
 
  298         "HashDbSearchPanel.noOpenCase.errMsg=No open case available." 
  302         if (hashTable.getRowCount() != 0) {
 
  305                 if (HashDbSearcher.countFilesMd5Hashed() > 0) {
 
  308                     JOptionPane.showMessageDialog(
this,
 
  309                             NbBundle.getMessage(
this.getClass(),
 
  310                                     "HashDbSearchPanel.noFilesHaveMD5HashMsg"),
 
  311                             NbBundle.getMessage(
this.getClass(), 
"HashDbSearchPanel.dlgMsg.title"),
 
  312                             JOptionPane.ERROR_MESSAGE);
 
  315             } 
catch (NoCurrentCaseException ex) {
 
  316                 JOptionPane.showMessageDialog(
this,
 
  317                         Bundle.HashDbSearchPanel_noOpenCase_errMsg(),
 
  318                         NbBundle.getMessage(this.getClass(), 
"HashDbSearchPanel.dlgMsg.title"),
 
  319                         JOptionPane.ERROR_MESSAGE);
 
  323             errorField.setText(NbBundle.getMessage(
this.getClass(), 
"HashDbSearchPanel.errorText.noHashesAddedMsg"));
 
  324             errorField.setVisible(
true);
 
  329     private boolean doSearch() {
 
  330         errorField.setVisible(
false);
 
  332         int numRows = hashTable.getRowCount();
 
  333         ArrayList<String> hashes = 
new ArrayList<>();
 
  334         for (
int i = 0; i < numRows; i++) {
 
  335             hashes.add((String) hashTable.getValueAt(i, 0));
 
  338         HashDbSearchThread hashThread = 
new HashDbSearchThread(hashes);
 
  339         hashThread.execute();
 
  347         errorField.setVisible(
false);
 
  348         DefaultTableModel model = (DefaultTableModel) hashTable.getModel();
 
  349         String hash = hashField.getText();
 
  350         if (!hash.equals(
"")) {
 
  351             if (hash.matches(
"[a-fA-F0-9]{32}")) {
 
  352                 for (
int i = 0; i < model.getRowCount(); i++) {
 
  353                     if (model.getValueAt(i, 0).equals(hashField.getText())) {
 
  354                         hashField.setText(
"");
 
  356                                 NbBundle.getMessage(
this.getClass(), 
"HashDbSearchPanel.errorText.hashAlreadyAddedMsg"));
 
  357                         errorField.setVisible(
true);
 
  358                         errorField.setVisible(
true);
 
  362                 model.addRow(
new String[]{hash});
 
  363                 hashField.setText(
""); 
 
  365                 errorField.setText(NbBundle.getMessage(
this.getClass(), 
"HashDbSearchPanel.errorText.invalidMD5HashMsg"));
 
  366                 errorField.setVisible(
true);
 
  369         hashField.requestFocus(); 
 
  376         DefaultTableModel model = (DefaultTableModel) hashTable.getModel();
 
  377         int rows[] = hashTable.getSelectedRows();
 
  380         for (
int i = rows.length - 1; i >= 0; i--) {
 
  381             model.removeRow(rows[i]);
 
  389         if (!saveBox.isSelected()) {
 
  390             DefaultTableModel model = (DefaultTableModel) hashTable.getModel();
 
  391             int numRows = hashTable.getRowCount();
 
  392             for (
int i = numRows - 1; i >= 0; i--) {
 
  396         errorField.setVisible(
false);
 
  397         hashField.setText(
"");