From 4f8266805c1491952f26cc27665a5ff6e26e80d6 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 29 Apr 2020 09:00:35 -0400 Subject: [PATCH 01/90] purely gui changes without event listeners --- .../modules/hashdatabase/Bundle.properties | 4 + .../modules/hashdatabase/Bundle_ja.properties | 3 + .../HashDbCreateDatabaseDialog.form | 28 +++- .../HashDbCreateDatabaseDialog.java | 31 ++++- .../HashDbImportDatabaseDialog.form | 105 ++++++++------ .../HashDbImportDatabaseDialog.java | 90 +++++++----- .../HashLookupModuleSettingsPanel.form | 131 +++++++++++++----- .../HashLookupModuleSettingsPanel.java | 92 ++++++++---- 8 files changed, 333 insertions(+), 151 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties index d9fb142cf4..69a349aeb7 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties @@ -241,3 +241,7 @@ AddHashValuesToDatabaseDialog.okButton.text_2=OK HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.text=Copy hash set into user configuration folder HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.toolTipText=In Live Triage situations, this option ensures that path to the hash set will be valid HashLookupSettingsPanel.indexPathLabel.text= +HashDbImportDatabaseDialog.unspecifiedRadioButton.text=Unspecified +HashDbImportDatabaseDialog.unspecifiedRadioButton.toolTipText= +HashLookupModuleSettingsPanel.unspecifiedHashDbsLabel.text=Select unspecified hash sets to use: +HashDbCreateDatabaseDialog.unspecifiedRadioButton.text=Unspecified diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties index 3f5ea43a61..6f361b96ba 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties @@ -295,3 +295,6 @@ AddHashValuesToDatabaseDialog.okButton.text_2=OK HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u3092\u30e6\u30fc\u30b6\u30fc\u69cb\u6210\u30d5\u30a1\u30a4\u30eb\u306b\u30b3\u30d4\u30fc HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.toolTipText=\u30e9\u30a4\u30d6\u30c8\u30ea\u30a2\u30fc\u30b8\u306e\u72b6\u6cc1\u3067\u306f\u3001\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306b\u3088\u3063\u3066\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u3078\u306e\u30d1\u30b9\u304c\u6709\u52b9\u3067\u3042\u308b\u3053\u3068\u304c\u4fdd\u8a3c\u3055\u308c\u307e\u3059\u3002 HashLookupSettingsPanel.indexPathLabel.text= +HashDbImportDatabaseDialog.unspecifiedRadioButton.text=\u9855\u8457 +HashLookupModuleSettingsPanel.unspecifiedHashDbsLabel.text=\u4f7f\u7528\u3059\u308b\u9855\u8457\u306a\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u3092\u9078\u629e: +HashDbCreateDatabaseDialog.unspecifiedRadioButton.text=\u9855\u8457 diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.form index 7c74b4b583..142b2ed500 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.form @@ -78,6 +78,7 @@ + @@ -125,19 +126,21 @@ - + - - - - + + + + + + @@ -183,7 +186,6 @@ - @@ -313,5 +315,19 @@ + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index 5470b385fb..95b4596348 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -198,6 +198,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { lbOrg = new javax.swing.JLabel(); orgComboBox = new javax.swing.JComboBox<>(); orgButton = new javax.swing.JButton(); + unspecifiedRadioButton = new javax.swing.JRadioButton(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); @@ -224,7 +225,6 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { }); buttonGroup1.add(knownBadRadioButton); - knownBadRadioButton.setSelected(true); org.openide.awt.Mnemonics.setLocalizedText(knownBadRadioButton, org.openide.util.NbBundle.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.knownBadRadioButton.text")); // NOI18N knownBadRadioButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -292,6 +292,15 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { } }); + buttonGroup1.add(unspecifiedRadioButton); + unspecifiedRadioButton.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(unspecifiedRadioButton, org.openide.util.NbBundle.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.unspecifiedRadioButton.text")); // NOI18N + unspecifiedRadioButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + unspecifiedRadioButtonActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -334,7 +343,8 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { .addGap(32, 32, 32) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(knownRadioButton) - .addComponent(knownBadRadioButton))) + .addComponent(knownBadRadioButton) + .addComponent(unspecifiedRadioButton))) .addGroup(layout.createSequentialGroup() .addGap(12, 12, 12) .addComponent(jLabel2)) @@ -374,16 +384,18 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { .addComponent(knownRadioButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(knownBadRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(sendIngestMessagesCheckbox) - .addGap(0, 0, Short.MAX_VALUE)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(cancelButton) - .addComponent(okButton)))) + .addComponent(okButton))) + .addGroup(layout.createSequentialGroup() + .addComponent(unspecifiedRadioButton) + .addGap(24, 24, 24) + .addComponent(sendIngestMessagesCheckbox) + .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); @@ -586,6 +598,10 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { enableComponents(); }//GEN-LAST:event_centralRepoRadioButtonActionPerformed + private void unspecifiedRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_unspecifiedRadioButtonActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_unspecifiedRadioButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.ButtonGroup buttonGroup1; private javax.swing.JButton cancelButton; @@ -606,5 +622,6 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { private javax.swing.JButton saveAsButton; private javax.swing.JCheckBox sendIngestMessagesCheckbox; private javax.swing.ButtonGroup storageTypeButtonGroup; + private javax.swing.JRadioButton unspecifiedRadioButton; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form index e285e99a12..d192e1713d 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form @@ -29,7 +29,7 @@ - + @@ -54,10 +54,6 @@ - - - - @@ -76,7 +72,16 @@ - + + + + + + + + + + @@ -86,16 +91,17 @@ - - + + + @@ -113,52 +119,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + @@ -220,7 +228,6 @@ - @@ -367,5 +374,21 @@ + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index a08f324a44..72e90fad30 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -182,6 +182,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { centralRepoRadioButton = new javax.swing.JRadioButton(); jLabel4 = new javax.swing.JLabel(); saveInUserConfigFolderCheckbox = new javax.swing.JCheckBox(); + unspecifiedRadioButton = new javax.swing.JRadioButton(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); @@ -218,7 +219,6 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { }); buttonGroup1.add(knownBadRadioButton); - knownBadRadioButton.setSelected(true); org.openide.awt.Mnemonics.setLocalizedText(knownBadRadioButton, org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.knownBadRadioButton.text")); // NOI18N knownBadRadioButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -291,6 +291,15 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { org.openide.awt.Mnemonics.setLocalizedText(saveInUserConfigFolderCheckbox, org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.text")); // NOI18N saveInUserConfigFolderCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.toolTipText")); // NOI18N + buttonGroup1.add(unspecifiedRadioButton); + org.openide.awt.Mnemonics.setLocalizedText(unspecifiedRadioButton, org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.unspecifiedRadioButton.text")); // NOI18N + unspecifiedRadioButton.setToolTipText(org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.unspecifiedRadioButton.toolTipText")); // NOI18N + unspecifiedRadioButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + unspecifiedRadioButtonActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -315,9 +324,6 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { .addComponent(openButton)))) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(sendIngestMessagesCheckbox) - .addGap(0, 0, Short.MAX_VALUE)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(lbOrg) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -331,7 +337,13 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { .addGap(40, 40, 40) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(versionTextField) - .addComponent(hashSetNameTextField))) + .addComponent(hashSetNameTextField)))) + .addGap(81, 81, 81)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(sendIngestMessagesCheckbox) + .addGap(0, 0, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(okButton))) @@ -339,14 +351,15 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { .addComponent(cancelButton)) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(saveInUserConfigFolderCheckbox) .addComponent(jLabel2) - .addComponent(readOnlyCheckbox) .addGroup(layout.createSequentialGroup() .addGap(19, 19, 19) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(knownRadioButton) - .addComponent(knownBadRadioButton)))) + .addComponent(knownBadRadioButton) + .addComponent(unspecifiedRadioButton))) + .addComponent(saveInUserConfigFolderCheckbox) + .addComponent(readOnlyCheckbox)) .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); @@ -361,44 +374,46 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { .addComponent(databasePathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel3) .addComponent(openButton)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(fileTypeRadioButton) + .addComponent(centralRepoRadioButton) + .addComponent(jLabel4)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(hashSetNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lbVersion) + .addComponent(versionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(5, 5, 5) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(orgButton) + .addComponent(orgComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lbOrg)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(knownRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(knownBadRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(unspecifiedRadioButton) + .addGap(5, 5, 5) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(fileTypeRadioButton) - .addComponent(centralRepoRadioButton) - .addComponent(jLabel4)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel1) - .addComponent(hashSetNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lbVersion) - .addComponent(versionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(5, 5, 5) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(orgButton) - .addComponent(orgComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lbOrg)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jLabel2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(knownRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(knownBadRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(readOnlyCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(sendIngestMessagesCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(saveInUserConfigFolderCheckbox) - .addGap(0, 29, Short.MAX_VALUE)) + .addGap(0, 0, Short.MAX_VALUE)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) + .addGap(81, 81, 81) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(cancelButton) .addComponent(okButton)))) - .addContainerGap()) + .addGap(18, 18, 18)) ); pack(); @@ -629,6 +644,10 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { enableComponents(); }//GEN-LAST:event_readOnlyCheckboxActionPerformed + private void unspecifiedRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_unspecifiedRadioButtonActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_unspecifiedRadioButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.ButtonGroup buttonGroup1; private javax.swing.JButton cancelButton; @@ -652,6 +671,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { private javax.swing.JCheckBox saveInUserConfigFolderCheckbox; private javax.swing.JCheckBox sendIngestMessagesCheckbox; private javax.swing.ButtonGroup storageTypeButtonGroup; + private javax.swing.JRadioButton unspecifiedRadioButton; private javax.swing.JTextField versionTextField; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.form index c0a486fce9..f369da6e78 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.form @@ -28,18 +28,31 @@ - + - - + + + + + + + + + + + + + + + @@ -48,20 +61,34 @@ - + - + + + + + + + + - + + + + + + + + @@ -93,35 +120,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -155,5 +154,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java index 6dcd567226..f27e895781 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java @@ -66,8 +66,8 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe } private void customizeComponents(HashLookupModuleSettings settings) { - customizeHashSetsTable(jScrollPane1, knownHashTable, knownHashSetsTableModel); - customizeHashSetsTable(jScrollPane2, knownBadHashTable, knownBadHashSetsTableModel); + customizeHashSetsTable(knownHashDbsScrollPane, knownHashTable, knownHashSetsTableModel); + customizeHashSetsTable(knownBadHashDbsScrollPane, knownBadHashTable, knownBadHashSetsTableModel); alwaysCalcHashesCheckbox.setSelected(settings.shouldCalculateHashes()); hashDbManager.addPropertyChangeListener(this); alwaysCalcHashesCheckbox.setText("" + org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text") + ""); // NOI18N NON-NLS @@ -285,36 +285,31 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe // //GEN-BEGIN:initComponents private void initComponents() { - jScrollPane1 = new javax.swing.JScrollPane(); + knownHashDbsLabel = new javax.swing.JLabel(); + knownHashDbsScrollPane = new javax.swing.JScrollPane(); knownHashTable = new javax.swing.JTable(); knownBadHashDbsLabel = new javax.swing.JLabel(); - knownHashDbsLabel = new javax.swing.JLabel(); - alwaysCalcHashesCheckbox = new javax.swing.JCheckBox(); - jScrollPane2 = new javax.swing.JScrollPane(); + knownBadHashDbsScrollPane = new javax.swing.JScrollPane(); knownBadHashTable = new javax.swing.JTable(); + unspecifiedHashDbsLabel = new javax.swing.JLabel(); + unspecifiedHashDbsScrollPane = new javax.swing.JScrollPane(); + unspecifiedHashTable = new javax.swing.JTable(); + alwaysCalcHashesCheckbox = new javax.swing.JCheckBox(); setPreferredSize(new java.awt.Dimension(292, 150)); - jScrollPane1.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + knownHashDbsLabel.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.knownHashDbsLabel.text")); // NOI18N + + knownHashDbsScrollPane.setBorder(javax.swing.BorderFactory.createEtchedBorder()); knownHashTable.setBackground(new java.awt.Color(240, 240, 240)); knownHashTable.setShowHorizontalLines(false); knownHashTable.setShowVerticalLines(false); - jScrollPane1.setViewportView(knownHashTable); + knownHashDbsScrollPane.setViewportView(knownHashTable); knownBadHashDbsLabel.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.knownBadHashDbsLabel.text")); // NOI18N - knownHashDbsLabel.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.knownHashDbsLabel.text")); // NOI18N - - alwaysCalcHashesCheckbox.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text")); // NOI18N - alwaysCalcHashesCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.toolTipText")); // NOI18N - alwaysCalcHashesCheckbox.setMaximumSize(new java.awt.Dimension(290, 35)); - alwaysCalcHashesCheckbox.setMinimumSize(new java.awt.Dimension(290, 35)); - alwaysCalcHashesCheckbox.setPreferredSize(new java.awt.Dimension(271, 35)); - alwaysCalcHashesCheckbox.setVerticalAlignment(javax.swing.SwingConstants.TOP); - alwaysCalcHashesCheckbox.setVerticalTextPosition(javax.swing.SwingConstants.TOP); - - jScrollPane2.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + knownBadHashDbsScrollPane.setBorder(javax.swing.BorderFactory.createEtchedBorder()); knownBadHashTable.setBackground(new java.awt.Color(240, 240, 240)); knownBadHashTable.setModel(new javax.swing.table.DefaultTableModel( @@ -327,7 +322,32 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe )); knownBadHashTable.setShowHorizontalLines(false); knownBadHashTable.setShowVerticalLines(false); - jScrollPane2.setViewportView(knownBadHashTable); + knownBadHashDbsScrollPane.setViewportView(knownBadHashTable); + + unspecifiedHashDbsLabel.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.unspecifiedHashDbsLabel.text")); // NOI18N + + unspecifiedHashDbsScrollPane.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + unspecifiedHashTable.setBackground(new java.awt.Color(240, 240, 240)); + unspecifiedHashTable.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + + } + )); + unspecifiedHashTable.setShowHorizontalLines(false); + unspecifiedHashTable.setShowVerticalLines(false); + unspecifiedHashDbsScrollPane.setViewportView(unspecifiedHashTable); + + alwaysCalcHashesCheckbox.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text")); // NOI18N + alwaysCalcHashesCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.toolTipText")); // NOI18N + alwaysCalcHashesCheckbox.setMaximumSize(new java.awt.Dimension(290, 35)); + alwaysCalcHashesCheckbox.setMinimumSize(new java.awt.Dimension(290, 35)); + alwaysCalcHashesCheckbox.setPreferredSize(new java.awt.Dimension(271, 35)); + alwaysCalcHashesCheckbox.setVerticalAlignment(javax.swing.SwingConstants.TOP); + alwaysCalcHashesCheckbox.setVerticalTextPosition(javax.swing.SwingConstants.TOP); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); @@ -339,14 +359,23 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe .addGroup(layout.createSequentialGroup() .addComponent(knownHashDbsLabel) .addGap(0, 0, Short.MAX_VALUE)) - .addComponent(knownBadHashDbsLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 290, Short.MAX_VALUE) + .addComponent(knownBadHashDbsLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 347, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addGap(10, 10, 10) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))) + .addComponent(knownHashDbsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addComponent(knownBadHashDbsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))) .addComponent(alwaysCalcHashesCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(unspecifiedHashDbsLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 347, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(unspecifiedHashDbsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))) + .addContainerGap())) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -354,24 +383,33 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe .addGap(2, 2, 2) .addComponent(knownHashDbsLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 29, Short.MAX_VALUE) + .addComponent(knownHashDbsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 68, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(knownBadHashDbsLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 29, Short.MAX_VALUE) + .addComponent(knownBadHashDbsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 67, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(unspecifiedHashDbsLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(unspecifiedHashDbsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 68, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(alwaysCalcHashesCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 330, Short.MAX_VALUE)) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JCheckBox alwaysCalcHashesCheckbox; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JScrollPane jScrollPane2; private javax.swing.JLabel knownBadHashDbsLabel; + private javax.swing.JScrollPane knownBadHashDbsScrollPane; private javax.swing.JTable knownBadHashTable; private javax.swing.JLabel knownHashDbsLabel; + private javax.swing.JScrollPane knownHashDbsScrollPane; private javax.swing.JTable knownHashTable; + private javax.swing.JLabel unspecifiedHashDbsLabel; + private javax.swing.JScrollPane unspecifiedHashDbsScrollPane; + private javax.swing.JTable unspecifiedHashTable; // End of variables declaration//GEN-END:variables } From a0824372d393812712681588059e8f143abc084c Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 29 Apr 2020 11:12:04 -0400 Subject: [PATCH 02/90] updated settings panel gui --- .../AnnotationsContentViewer.form | 4 +- .../AnnotationsContentViewer.java | 4 +- .../modules/hashdatabase/Bundle.properties | 4 +- .../modules/hashdatabase/Bundle_ja.properties | 4 +- .../HashLookupModuleSettingsPanel.form | 128 ++--------------- .../HashLookupModuleSettingsPanel.java | 131 ++++-------------- 6 files changed, 43 insertions(+), 232 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.form index 4fe61b2fb5..986492a810 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.form @@ -21,12 +21,12 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index c5c92b11c0..84b68b02df 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -399,11 +399,11 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 907, Short.MAX_VALUE) + .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 696, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane5, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE) + .addComponent(jScrollPane5, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 494, Short.MAX_VALUE) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties index 69a349aeb7..58e1214518 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties @@ -162,8 +162,6 @@ AddContentToHashDbAction.multipleSelectionNameEmpty=Add Files to Hash Set (Empty HashDbManager.ingestRunningExceptionMsg=Ingest is ongoing; this service will be unavailable until it finishes. HashDbManager.saveErrorExceptionMsg=Error saving hash configuration HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text=Calculate MD5 even if no hash set is selected -HashLookupModuleSettingsPanel.knownHashDbsLabel.text=Select known hash sets to use: -HashLookupModuleSettingsPanel.knownBadHashDbsLabel.text=Select notable hash sets to use: AddContentToHashDbAction.addFilesToHashSet.files=files AddContentToHashDbAction.addFilesToHashSet.file=file HashDbManager.errCreatingIndex.title=Error creating index @@ -243,5 +241,5 @@ HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.toolTipText=In Live Tr HashLookupSettingsPanel.indexPathLabel.text= HashDbImportDatabaseDialog.unspecifiedRadioButton.text=Unspecified HashDbImportDatabaseDialog.unspecifiedRadioButton.toolTipText= -HashLookupModuleSettingsPanel.unspecifiedHashDbsLabel.text=Select unspecified hash sets to use: HashDbCreateDatabaseDialog.unspecifiedRadioButton.text=Unspecified +HashLookupModuleSettingsPanel.hashDbsLabel.text=Select hash sets to use: diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties index 6f361b96ba..3cd52c36ae 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties @@ -216,8 +216,6 @@ HashLookupSettingsPanel.jLabel6.text=\u30bf\u30a4\u30d7: HashLookupSettingsPanel.jLabel4.text=\u5834\u6240: HashLookupSettingsPanel.jLabel2.text=\u540d\u524d: HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u306a\u3044\u5834\u5408\u3067\u3082MD5\u3092\u8a08\u7b97 -HashLookupModuleSettingsPanel.knownHashDbsLabel.text=\u4f7f\u7528\u3059\u308b\u65e2\u77e5\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u3092\u9078\u629e: -HashLookupModuleSettingsPanel.knownBadHashDbsLabel.text=\u4f7f\u7528\u3059\u308b\u9855\u8457\u306a\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u3092\u9078\u629e: AddContentToHashDbAction.addFilesToHashSet.files=\u30d5\u30a1\u30a4\u30eb AddContentToHashDbAction.addFilesToHashSet.file=\u30d5\u30a1\u30a4\u30eb HashDbManager.errCreatingIndex.title=\u7d22\u5f15\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f @@ -296,5 +294,5 @@ HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.text=\u30cf\u30c3\u30b HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.toolTipText=\u30e9\u30a4\u30d6\u30c8\u30ea\u30a2\u30fc\u30b8\u306e\u72b6\u6cc1\u3067\u306f\u3001\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306b\u3088\u3063\u3066\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u3078\u306e\u30d1\u30b9\u304c\u6709\u52b9\u3067\u3042\u308b\u3053\u3068\u304c\u4fdd\u8a3c\u3055\u308c\u307e\u3059\u3002 HashLookupSettingsPanel.indexPathLabel.text= HashDbImportDatabaseDialog.unspecifiedRadioButton.text=\u9855\u8457 -HashLookupModuleSettingsPanel.unspecifiedHashDbsLabel.text=\u4f7f\u7528\u3059\u308b\u9855\u8457\u306a\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u3092\u9078\u629e: HashDbCreateDatabaseDialog.unspecifiedRadioButton.text=\u9855\u8457 +HashLookupModuleSettingsPanel.hashDbsLabel.text=\u4f7f\u7528\u3059\u308b\u65e2\u77e5\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u3092\u9078\u629e: diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.form index f369da6e78..3e2e525560 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.form @@ -25,70 +25,42 @@ - + - - - - - + - - - - - - - - - - - - - - + - + - - - - - - - - - - - - + - + - + - + @@ -102,7 +74,7 @@ - + @@ -113,88 +85,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java index f27e895781..be13e5e2af 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java @@ -44,8 +44,6 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe private final HashDbManager hashDbManager = HashDbManager.getInstance(); private final List knownHashSetModels = new ArrayList<>(); private final HashSetsTableModel knownHashSetsTableModel = new HashSetsTableModel(knownHashSetModels); - private final List knownBadHashSetModels = new ArrayList<>(); - private final HashSetsTableModel knownBadHashSetsTableModel = new HashSetsTableModel(knownBadHashSetModels); HashLookupModuleSettingsPanel(HashLookupModuleSettings settings) { initializeHashSetModels(settings); @@ -54,20 +52,15 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe } private void initializeHashSetModels(HashLookupModuleSettings settings) { - initializeHashSetModels(settings, validSetsOnly(hashDbManager.getKnownFileHashSets()), knownHashSetModels); - initializeHashSetModels(settings, validSetsOnly(hashDbManager.getKnownBadFileHashSets()), knownBadHashSetModels); - } - - private void initializeHashSetModels(HashLookupModuleSettings settings, List hashDbs, List hashSetModels) { - hashSetModels.clear(); + List hashDbs = validSetsOnly(hashDbManager.getAllHashSets()); + knownHashSetModels.clear(); for (HashDb db : hashDbs) { - hashSetModels.add(new HashSetModel(db, settings.isHashSetEnabled(db), isHashDbValid(db))); + knownHashSetModels.add(new HashSetModel(db, settings.isHashSetEnabled(db), isHashDbValid(db))); } } private void customizeComponents(HashLookupModuleSettings settings) { - customizeHashSetsTable(knownHashDbsScrollPane, knownHashTable, knownHashSetsTableModel); - customizeHashSetsTable(knownBadHashDbsScrollPane, knownBadHashTable, knownBadHashSetsTableModel); + customizeHashSetsTable(hashDbsScrollPane, hashTable, knownHashSetsTableModel); alwaysCalcHashesCheckbox.setSelected(settings.shouldCalculateHashes()); hashDbManager.addPropertyChangeListener(this); alwaysCalcHashesCheckbox.setText("" + org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text") + ""); // NOI18N NON-NLS @@ -78,7 +71,7 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe table.setTableHeader(null); table.setRowSelectionAllowed(false); final int width1 = scrollPane.getPreferredSize().width; - knownHashTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN); + hashTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN); TableColumn column; for (int i = 0; i < table.getColumnCount(); i++) { column = table.getColumnModel().getColumn(i); @@ -104,7 +97,6 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe List enabledHashSets = new ArrayList<>(); List disabledHashSets = new ArrayList<>(); addHashSets(knownHashSetModels, enabledHashSets, disabledHashSets); - addHashSets(knownBadHashSetModels, enabledHashSets, disabledHashSets); return new HashLookupModuleSettings(alwaysCalcHashesCheckbox.isSelected(), enabledHashSets, disabledHashSets); } @@ -122,12 +114,10 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe void update() { updateHashSetModels(); knownHashSetsTableModel.fireTableDataChanged(); - knownBadHashSetsTableModel.fireTableDataChanged(); } private void updateHashSetModels() { - updateHashSetModels(validSetsOnly(hashDbManager.getKnownFileHashSets()), knownHashSetModels); - updateHashSetModels(validSetsOnly(hashDbManager.getKnownBadFileHashSets()), knownBadHashSetModels); + updateHashSetModels(validSetsOnly(hashDbManager.getAllHashSets()), knownHashSetModels); } private List validSetsOnly(List hashDbs){ @@ -180,7 +170,6 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe initializeHashSetModels(newSettings); alwaysCalcHashesCheckbox.setSelected(newSettings.shouldCalculateHashes()); knownHashSetsTableModel.fireTableDataChanged(); - knownBadHashSetsTableModel.fireTableDataChanged(); } private boolean isHashDbValid(HashDb hashDb) { @@ -213,6 +202,10 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe return db.getDisplayName(); } + String getFormattedName() { + return String.format("%s (%s)", db.getDisplayName(), db.getKnownFilesType()); + } + void setEnabled(boolean enabled) { this.enabled = enabled; } @@ -254,7 +247,7 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe if (columnIndex == 0) { return hashSets.get(rowIndex).isEnabled(); } else { - return hashSets.get(rowIndex).getName(); + return hashSets.get(rowIndex).getFormattedName(); } } @@ -285,61 +278,21 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe // //GEN-BEGIN:initComponents private void initComponents() { - knownHashDbsLabel = new javax.swing.JLabel(); - knownHashDbsScrollPane = new javax.swing.JScrollPane(); - knownHashTable = new javax.swing.JTable(); - knownBadHashDbsLabel = new javax.swing.JLabel(); - knownBadHashDbsScrollPane = new javax.swing.JScrollPane(); - knownBadHashTable = new javax.swing.JTable(); - unspecifiedHashDbsLabel = new javax.swing.JLabel(); - unspecifiedHashDbsScrollPane = new javax.swing.JScrollPane(); - unspecifiedHashTable = new javax.swing.JTable(); + hashDbsLabel = new javax.swing.JLabel(); + hashDbsScrollPane = new javax.swing.JScrollPane(); + hashTable = new javax.swing.JTable(); alwaysCalcHashesCheckbox = new javax.swing.JCheckBox(); setPreferredSize(new java.awt.Dimension(292, 150)); - knownHashDbsLabel.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.knownHashDbsLabel.text")); // NOI18N + hashDbsLabel.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.hashDbsLabel.text")); // NOI18N - knownHashDbsScrollPane.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + hashDbsScrollPane.setBorder(javax.swing.BorderFactory.createEtchedBorder()); - knownHashTable.setBackground(new java.awt.Color(240, 240, 240)); - knownHashTable.setShowHorizontalLines(false); - knownHashTable.setShowVerticalLines(false); - knownHashDbsScrollPane.setViewportView(knownHashTable); - - knownBadHashDbsLabel.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.knownBadHashDbsLabel.text")); // NOI18N - - knownBadHashDbsScrollPane.setBorder(javax.swing.BorderFactory.createEtchedBorder()); - - knownBadHashTable.setBackground(new java.awt.Color(240, 240, 240)); - knownBadHashTable.setModel(new javax.swing.table.DefaultTableModel( - new Object [][] { - - }, - new String [] { - - } - )); - knownBadHashTable.setShowHorizontalLines(false); - knownBadHashTable.setShowVerticalLines(false); - knownBadHashDbsScrollPane.setViewportView(knownBadHashTable); - - unspecifiedHashDbsLabel.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.unspecifiedHashDbsLabel.text")); // NOI18N - - unspecifiedHashDbsScrollPane.setBorder(javax.swing.BorderFactory.createEtchedBorder()); - - unspecifiedHashTable.setBackground(new java.awt.Color(240, 240, 240)); - unspecifiedHashTable.setModel(new javax.swing.table.DefaultTableModel( - new Object [][] { - - }, - new String [] { - - } - )); - unspecifiedHashTable.setShowHorizontalLines(false); - unspecifiedHashTable.setShowVerticalLines(false); - unspecifiedHashDbsScrollPane.setViewportView(unspecifiedHashTable); + hashTable.setBackground(new java.awt.Color(240, 240, 240)); + hashTable.setShowHorizontalLines(false); + hashTable.setShowVerticalLines(false); + hashDbsScrollPane.setViewportView(hashTable); alwaysCalcHashesCheckbox.setText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text")); // NOI18N alwaysCalcHashesCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.toolTipText")); // NOI18N @@ -357,59 +310,31 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(knownHashDbsLabel) + .addComponent(hashDbsLabel) .addGap(0, 0, Short.MAX_VALUE)) - .addComponent(knownBadHashDbsLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 347, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addGap(10, 10, 10) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(knownHashDbsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addComponent(knownBadHashDbsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))) + .addComponent(hashDbsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 494, Short.MAX_VALUE)) .addComponent(alwaysCalcHashesCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(unspecifiedHashDbsLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 347, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addGap(10, 10, 10) - .addComponent(unspecifiedHashDbsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))) - .addContainerGap())) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(2, 2, 2) - .addComponent(knownHashDbsLabel) + .addComponent(hashDbsLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(knownHashDbsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 68, Short.MAX_VALUE) + .addComponent(hashDbsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 207, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(knownBadHashDbsLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(knownBadHashDbsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 67, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(unspecifiedHashDbsLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(unspecifiedHashDbsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 68, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(alwaysCalcHashesCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, 0)) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 330, Short.MAX_VALUE)) + .addContainerGap()) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JCheckBox alwaysCalcHashesCheckbox; - private javax.swing.JLabel knownBadHashDbsLabel; - private javax.swing.JScrollPane knownBadHashDbsScrollPane; - private javax.swing.JTable knownBadHashTable; - private javax.swing.JLabel knownHashDbsLabel; - private javax.swing.JScrollPane knownHashDbsScrollPane; - private javax.swing.JTable knownHashTable; - private javax.swing.JLabel unspecifiedHashDbsLabel; - private javax.swing.JScrollPane unspecifiedHashDbsScrollPane; - private javax.swing.JTable unspecifiedHashTable; + private javax.swing.JLabel hashDbsLabel; + private javax.swing.JScrollPane hashDbsScrollPane; + private javax.swing.JTable hashTable; // End of variables declaration//GEN-END:variables } From 60068ec93a876966b80a28db1d7c4e7525134443 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 29 Apr 2020 12:26:00 -0400 Subject: [PATCH 03/90] updates for naming --- .../HashLookupModuleSettingsPanel.java | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java index be13e5e2af..55959db35c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java @@ -27,6 +27,7 @@ import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumn; +import org.apache.commons.lang.StringUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; @@ -42,8 +43,8 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe private static final long serialVersionUID = 1L; private final HashDbManager hashDbManager = HashDbManager.getInstance(); - private final List knownHashSetModels = new ArrayList<>(); - private final HashSetsTableModel knownHashSetsTableModel = new HashSetsTableModel(knownHashSetModels); + private final List hashSetModels = new ArrayList<>(); + private final HashSetsTableModel hashSetsTableModel = new HashSetsTableModel(hashSetModels); HashLookupModuleSettingsPanel(HashLookupModuleSettings settings) { initializeHashSetModels(settings); @@ -53,14 +54,14 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe private void initializeHashSetModels(HashLookupModuleSettings settings) { List hashDbs = validSetsOnly(hashDbManager.getAllHashSets()); - knownHashSetModels.clear(); + hashSetModels.clear(); for (HashDb db : hashDbs) { - knownHashSetModels.add(new HashSetModel(db, settings.isHashSetEnabled(db), isHashDbValid(db))); + hashSetModels.add(new HashSetModel(db, settings.isHashSetEnabled(db), isHashDbValid(db))); } } private void customizeComponents(HashLookupModuleSettings settings) { - customizeHashSetsTable(hashDbsScrollPane, hashTable, knownHashSetsTableModel); + customizeHashSetsTable(hashDbsScrollPane, hashTable, hashSetsTableModel); alwaysCalcHashesCheckbox.setSelected(settings.shouldCalculateHashes()); hashDbManager.addPropertyChangeListener(this); alwaysCalcHashesCheckbox.setText("" + org.openide.util.NbBundle.getMessage(HashLookupModuleSettingsPanel.class, "HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text") + ""); // NOI18N NON-NLS @@ -96,7 +97,7 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe public IngestModuleIngestJobSettings getSettings() { List enabledHashSets = new ArrayList<>(); List disabledHashSets = new ArrayList<>(); - addHashSets(knownHashSetModels, enabledHashSets, disabledHashSets); + addHashSets(hashSetModels, enabledHashSets, disabledHashSets); return new HashLookupModuleSettings(alwaysCalcHashesCheckbox.isSelected(), enabledHashSets, disabledHashSets); } @@ -113,13 +114,9 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe void update() { updateHashSetModels(); - knownHashSetsTableModel.fireTableDataChanged(); + hashSetsTableModel.fireTableDataChanged(); } - private void updateHashSetModels() { - updateHashSetModels(validSetsOnly(hashDbManager.getAllHashSets()), knownHashSetModels); - } - private List validSetsOnly(List hashDbs){ List validDbs = new ArrayList<>(); for(HashDb db:hashDbs){ @@ -134,8 +131,9 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe return validDbs; } - void updateHashSetModels(List hashDbs, List hashSetModels) { - + void updateHashSetModels() { + List hashDbs = validSetsOnly(hashDbManager.getAllHashSets()); + List hashDatabases = new ArrayList<>(hashDbs); // Update the hash sets and detect deletions. @@ -169,7 +167,7 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe void reset(HashLookupModuleSettings newSettings) { initializeHashSetModels(newSettings); alwaysCalcHashesCheckbox.setSelected(newSettings.shouldCalculateHashes()); - knownHashSetsTableModel.fireTableDataChanged(); + hashSetsTableModel.fireTableDataChanged(); } private boolean isHashDbValid(HashDb hashDb) { @@ -203,7 +201,12 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe } String getFormattedName() { - return String.format("%s (%s)", db.getDisplayName(), db.getKnownFilesType()); + String knownTypeName = (db != null && db.getKnownFilesType() != null) ? db.getKnownFilesType().getDisplayName() : ""; + if (!StringUtils.isBlank(knownTypeName)) + knownTypeName = String.format(" (%s)", knownTypeName); + + String displayName = db != null ? db.getDisplayName() : ""; + return displayName + knownTypeName; } void setEnabled(boolean enabled) { From 72ef5267e18d9bd5b9543fcd44135b7d322d3324 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 29 Apr 2020 16:22:33 -0400 Subject: [PATCH 04/90] added NO_CHANGE KnownFileType --- .../modules/hashdatabase/Bundle.properties | 6 +- .../hashdatabase/Bundle.properties-MERGED | 1 + .../modules/hashdatabase/Bundle_ja.properties | 4 +- .../HashDbCreateDatabaseDialog.form | 10 +-- .../HashDbCreateDatabaseDialog.java | 49 ++++++----- .../HashDbImportDatabaseDialog.form | 12 +-- .../HashDbImportDatabaseDialog.java | 39 +++++---- .../modules/hashdatabase/HashDbManager.java | 83 +++++++++++++------ .../hashdatabase/HashLookupSettingsPanel.java | 2 +- .../ImportCentralRepoDbProgressDialog.java | 7 +- 10 files changed, 127 insertions(+), 86 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties index 58e1214518..ffd0a535ac 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties @@ -239,7 +239,7 @@ AddHashValuesToDatabaseDialog.okButton.text_2=OK HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.text=Copy hash set into user configuration folder HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.toolTipText=In Live Triage situations, this option ensures that path to the hash set will be valid HashLookupSettingsPanel.indexPathLabel.text= -HashDbImportDatabaseDialog.unspecifiedRadioButton.text=Unspecified -HashDbImportDatabaseDialog.unspecifiedRadioButton.toolTipText= -HashDbCreateDatabaseDialog.unspecifiedRadioButton.text=Unspecified HashLookupModuleSettingsPanel.hashDbsLabel.text=Select hash sets to use: +HashDbCreateDatabaseDialog.noChangeRadioButton.text=No Change +HashDbImportDatabaseDialog.noChangeRadioButton.toolTipText= +HashDbImportDatabaseDialog.noChangeRadioButton.text=No Change diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED index 44057d0016..44e551c028 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED @@ -190,6 +190,7 @@ HashDbManager.hashDbAlreadyAddedExceptionMsg=The hash set at\n{0}\nhas already b HashDbManager.illegalHashDbFileNameExtensionMsg=The hash set file name must have a .{0} extension. HashDbManager.moduleErr=Module Error HashDbManager.knownBad.text=Notable +HashDbManager.noChange.text=No Change HashDbManager.known.text=Known HashDbManager.fileNameExtensionFilter.title=Hash Set File HashDbSearchAction.dlgMsg.title=File Search by MD5 Hash diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties index 3cd52c36ae..c800aca094 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties @@ -293,6 +293,6 @@ AddHashValuesToDatabaseDialog.okButton.text_2=OK HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u3092\u30e6\u30fc\u30b6\u30fc\u69cb\u6210\u30d5\u30a1\u30a4\u30eb\u306b\u30b3\u30d4\u30fc HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.toolTipText=\u30e9\u30a4\u30d6\u30c8\u30ea\u30a2\u30fc\u30b8\u306e\u72b6\u6cc1\u3067\u306f\u3001\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306b\u3088\u3063\u3066\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u3078\u306e\u30d1\u30b9\u304c\u6709\u52b9\u3067\u3042\u308b\u3053\u3068\u304c\u4fdd\u8a3c\u3055\u308c\u307e\u3059\u3002 HashLookupSettingsPanel.indexPathLabel.text= -HashDbImportDatabaseDialog.unspecifiedRadioButton.text=\u9855\u8457 -HashDbCreateDatabaseDialog.unspecifiedRadioButton.text=\u9855\u8457 HashLookupModuleSettingsPanel.hashDbsLabel.text=\u4f7f\u7528\u3059\u308b\u65e2\u77e5\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u3092\u9078\u629e: +HashDbCreateDatabaseDialog.noChangeRadioButton.text=\u9855\u8457 +HashDbImportDatabaseDialog.noChangeRadioButton.text=\u9855\u8457 diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.form index 142b2ed500..8eae9f15c4 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.form @@ -78,7 +78,7 @@ - + @@ -136,7 +136,7 @@ - + @@ -315,18 +315,18 @@ - + - + - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index 95b4596348..5b7c0f1944 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -198,7 +198,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { lbOrg = new javax.swing.JLabel(); orgComboBox = new javax.swing.JComboBox<>(); orgButton = new javax.swing.JButton(); - unspecifiedRadioButton = new javax.swing.JRadioButton(); + noChangeRadioButton = new javax.swing.JRadioButton(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); @@ -292,12 +292,12 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { } }); - buttonGroup1.add(unspecifiedRadioButton); - unspecifiedRadioButton.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(unspecifiedRadioButton, org.openide.util.NbBundle.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.unspecifiedRadioButton.text")); // NOI18N - unspecifiedRadioButton.addActionListener(new java.awt.event.ActionListener() { + buttonGroup1.add(noChangeRadioButton); + noChangeRadioButton.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(noChangeRadioButton, org.openide.util.NbBundle.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.noChangeRadioButton.text")); // NOI18N + noChangeRadioButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - unspecifiedRadioButtonActionPerformed(evt); + noChangeRadioButtonActionPerformed(evt); } }); @@ -344,7 +344,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(knownRadioButton) .addComponent(knownBadRadioButton) - .addComponent(unspecifiedRadioButton))) + .addComponent(noChangeRadioButton))) .addGroup(layout.createSequentialGroup() .addGap(12, 12, 12) .addComponent(jLabel2)) @@ -392,7 +392,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { .addComponent(cancelButton) .addComponent(okButton))) .addGroup(layout.createSequentialGroup() - .addComponent(unspecifiedRadioButton) + .addComponent(noChangeRadioButton) .addGap(24, 24, 24) .addComponent(sendIngestMessagesCheckbox) .addGap(0, 0, Short.MAX_VALUE))) @@ -403,13 +403,13 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { }// //GEN-END:initComponents private void knownRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownRadioButtonActionPerformed - sendIngestMessagesCheckbox.setSelected(false); - sendIngestMessagesCheckbox.setEnabled(false); + sendIngestMessagesCheckbox.setSelected(KnownFilesType.KNOWN.isDefaultInboxMessages()); + sendIngestMessagesCheckbox.setEnabled(KnownFilesType.KNOWN.isInboxMessagesAllowed()); }//GEN-LAST:event_knownRadioButtonActionPerformed private void knownBadRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownBadRadioButtonActionPerformed - sendIngestMessagesCheckbox.setSelected(true); - sendIngestMessagesCheckbox.setEnabled(true); + sendIngestMessagesCheckbox.setSelected(KnownFilesType.KNOWN_BAD.isDefaultInboxMessages()); + sendIngestMessagesCheckbox.setEnabled(KnownFilesType.KNOWN_BAD.isInboxMessagesAllowed()); }//GEN-LAST:event_knownBadRadioButtonActionPerformed private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed @@ -488,14 +488,18 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { } KnownFilesType type; - TskData.FileKnown fileKnown; + if (knownRadioButton.isSelected()) { - type = KnownFilesType.KNOWN; - fileKnown = TskData.FileKnown.KNOWN; - } else { - type = KnownFilesType.KNOWN_BAD; - fileKnown = TskData.FileKnown.BAD; + type = KnownFilesType.KNOWN; + } + else if (noChangeRadioButton.isSelected()) { + type = KnownFilesType.NO_CHANGE; } + else { + type = KnownFilesType.KNOWN_BAD; + } + + TskData.FileKnown fileKnown = type.getFileKnown(); String errorMessage = NbBundle .getMessage(this.getClass(), "HashDbCreateDatabaseDialog.errMsg.hashDbCreationErr"); @@ -598,9 +602,10 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { enableComponents(); }//GEN-LAST:event_centralRepoRadioButtonActionPerformed - private void unspecifiedRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_unspecifiedRadioButtonActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_unspecifiedRadioButtonActionPerformed + private void noChangeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_noChangeRadioButtonActionPerformed + sendIngestMessagesCheckbox.setSelected(KnownFilesType.NO_CHANGE.isDefaultInboxMessages()); + sendIngestMessagesCheckbox.setEnabled(KnownFilesType.NO_CHANGE.isInboxMessagesAllowed()); + }//GEN-LAST:event_noChangeRadioButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.ButtonGroup buttonGroup1; @@ -616,12 +621,12 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { private javax.swing.JRadioButton knownBadRadioButton; private javax.swing.JRadioButton knownRadioButton; private javax.swing.JLabel lbOrg; + private javax.swing.JRadioButton noChangeRadioButton; private javax.swing.JButton okButton; private javax.swing.JButton orgButton; private javax.swing.JComboBox orgComboBox; private javax.swing.JButton saveAsButton; private javax.swing.JCheckBox sendIngestMessagesCheckbox; private javax.swing.ButtonGroup storageTypeButtonGroup; - private javax.swing.JRadioButton unspecifiedRadioButton; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form index d192e1713d..720d3763a2 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form @@ -97,7 +97,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -374,20 +374,20 @@ - + - + - + - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index 72e90fad30..10b9827404 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -182,7 +182,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { centralRepoRadioButton = new javax.swing.JRadioButton(); jLabel4 = new javax.swing.JLabel(); saveInUserConfigFolderCheckbox = new javax.swing.JCheckBox(); - unspecifiedRadioButton = new javax.swing.JRadioButton(); + noChangeRadioButton = new javax.swing.JRadioButton(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); @@ -291,12 +291,12 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { org.openide.awt.Mnemonics.setLocalizedText(saveInUserConfigFolderCheckbox, org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.text")); // NOI18N saveInUserConfigFolderCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.toolTipText")); // NOI18N - buttonGroup1.add(unspecifiedRadioButton); - org.openide.awt.Mnemonics.setLocalizedText(unspecifiedRadioButton, org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.unspecifiedRadioButton.text")); // NOI18N - unspecifiedRadioButton.setToolTipText(org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.unspecifiedRadioButton.toolTipText")); // NOI18N - unspecifiedRadioButton.addActionListener(new java.awt.event.ActionListener() { + buttonGroup1.add(noChangeRadioButton); + org.openide.awt.Mnemonics.setLocalizedText(noChangeRadioButton, org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.noChangeRadioButton.text")); // NOI18N + noChangeRadioButton.setToolTipText(org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.noChangeRadioButton.toolTipText")); // NOI18N + noChangeRadioButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - unspecifiedRadioButtonActionPerformed(evt); + noChangeRadioButtonActionPerformed(evt); } }); @@ -357,7 +357,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(knownRadioButton) .addComponent(knownBadRadioButton) - .addComponent(unspecifiedRadioButton))) + .addComponent(noChangeRadioButton))) .addComponent(saveInUserConfigFolderCheckbox) .addComponent(readOnlyCheckbox)) .addGap(0, 0, Short.MAX_VALUE))) @@ -398,7 +398,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(knownBadRadioButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(unspecifiedRadioButton) + .addComponent(noChangeRadioButton) .addGap(5, 5, 5) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() @@ -451,13 +451,13 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { }//GEN-LAST:event_openButtonActionPerformed private void knownRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownRadioButtonActionPerformed - sendIngestMessagesCheckbox.setSelected(false); - sendIngestMessagesCheckbox.setEnabled(false); + sendIngestMessagesCheckbox.setSelected(KnownFilesType.KNOWN.isDefaultInboxMessages()); + sendIngestMessagesCheckbox.setEnabled(KnownFilesType.KNOWN.isInboxMessagesAllowed()); }//GEN-LAST:event_knownRadioButtonActionPerformed private void knownBadRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownBadRadioButtonActionPerformed - sendIngestMessagesCheckbox.setSelected(true); - sendIngestMessagesCheckbox.setEnabled(true); + sendIngestMessagesCheckbox.setSelected(KnownFilesType.KNOWN_BAD.isDefaultInboxMessages()); + sendIngestMessagesCheckbox.setEnabled(KnownFilesType.KNOWN_BAD.isInboxMessagesAllowed()); }//GEN-LAST:event_knownBadRadioButtonActionPerformed private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed @@ -546,7 +546,11 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { KnownFilesType type; if (knownRadioButton.isSelected()) { type = KnownFilesType.KNOWN; - } else { + } + else if (noChangeRadioButton.isSelected()) { + type = KnownFilesType.NO_CHANGE; + } + else { type = KnownFilesType.KNOWN_BAD; } @@ -644,9 +648,10 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { enableComponents(); }//GEN-LAST:event_readOnlyCheckboxActionPerformed - private void unspecifiedRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_unspecifiedRadioButtonActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_unspecifiedRadioButtonActionPerformed + private void noChangeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_noChangeRadioButtonActionPerformed + sendIngestMessagesCheckbox.setSelected(KnownFilesType.NO_CHANGE.isDefaultInboxMessages()); + sendIngestMessagesCheckbox.setEnabled(KnownFilesType.NO_CHANGE.isInboxMessagesAllowed()); + }//GEN-LAST:event_noChangeRadioButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.ButtonGroup buttonGroup1; @@ -663,6 +668,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { private javax.swing.JRadioButton knownRadioButton; private javax.swing.JLabel lbOrg; private javax.swing.JLabel lbVersion; + private javax.swing.JRadioButton noChangeRadioButton; private javax.swing.JButton okButton; private javax.swing.JButton openButton; private javax.swing.JButton orgButton; @@ -671,7 +677,6 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { private javax.swing.JCheckBox saveInUserConfigFolderCheckbox; private javax.swing.JCheckBox sendIngestMessagesCheckbox; private javax.swing.ButtonGroup storageTypeButtonGroup; - private javax.swing.JRadioButton unspecifiedRadioButton; private javax.swing.JTextField versionTextField; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index c6ae0d5ef4..372538be64 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -28,9 +28,11 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.logging.Level; +import java.util.stream.Stream; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.SwingWorker; @@ -58,6 +60,7 @@ import org.sleuthkit.datamodel.SleuthkitJNI; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; /** * This class implements a singleton that manages the set of hash databases used @@ -499,9 +502,9 @@ public class HashDbManager implements PropertyChangeListener { // Defaults for fields not stored in the central repository: // searchDuringIngest: false // sendIngestMessages: true if the hash set is notable - boolean sendIngestMessages = convertFileKnown(globalSet.getFileKnownStatus()).equals(HashDb.KnownFilesType.KNOWN_BAD); + boolean sendIngestMessages = KnownFilesType.fromFileKnown(globalSet.getFileKnownStatus()).equals(HashDb.KnownFilesType.KNOWN_BAD); crHashSets.add(new HashDbInfo(globalSet.getSetName(), globalSet.getVersion(), - globalSet.getGlobalSetID(), convertFileKnown(globalSet.getFileKnownStatus()), globalSet.isReadOnly(), false, sendIngestMessages)); + globalSet.getGlobalSetID(), KnownFilesType.fromFileKnown(globalSet.getFileKnownStatus()), globalSet.isReadOnly(), false, sendIngestMessages)); } } catch (CentralRepoException ex){ Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS @@ -509,13 +512,6 @@ public class HashDbManager implements PropertyChangeListener { } return crHashSets; } - - private static HashDb.KnownFilesType convertFileKnown(TskData.FileKnown fileKnown){ - if(fileKnown.equals(TskData.FileKnown.BAD)){ - return HashDb.KnownFilesType.KNOWN_BAD; - } - return HashDb.KnownFilesType.KNOWN; - } /** * Restores the last saved hash sets configuration. This supports @@ -701,17 +697,65 @@ public class HashDbManager implements PropertyChangeListener { */ public enum KnownFilesType { - KNOWN(NbBundle.getMessage(HashDbManager.class, "HashDbManager.known.text")), - KNOWN_BAD(NbBundle.getMessage(HashDbManager.class, "HashDbManager.knownBad.text")); + KNOWN(NbBundle.getMessage(HashDbManager.class, "HashDbManager.known.text"), TskData.FileKnown.KNOWN, false, false), + KNOWN_BAD(NbBundle.getMessage(HashDbManager.class, "HashDbManager.knownBad.text"), TskData.FileKnown.BAD, true, true), + NO_CHANGE(NbBundle.getMessage(HashDbManager.class, "HashDbManager.noChange.text"), TskData.FileKnown.UNKNOWN, true , false); + private final String displayName; + private final TskData.FileKnown fileKnown; + private final boolean allowSendInboxMessages; + private final boolean defaultSendInboxMessages; - private KnownFilesType(String displayName) { + private KnownFilesType(String displayName, TskData.FileKnown fileKnown, boolean allowSendInboxMessages, boolean defaultSendInboxMessages) { this.displayName = displayName; + this.fileKnown = fileKnown; + this.allowSendInboxMessages = allowSendInboxMessages; + this.defaultSendInboxMessages = defaultSendInboxMessages; } + /** + * Returns whether or not it is allowable to send inbox messages with this known files type. + * @return Whether or not it is allowable to send inbox messages with this known files type. + */ + boolean isInboxMessagesAllowed() { + return allowSendInboxMessages; + } + + /** + * Returns whether or not by default for this type is to send inbox messages. + * @return Whether or not by default for this type is to send inbox messages. + */ + boolean isDefaultInboxMessages() { + return defaultSendInboxMessages; + } + + public String getDisplayName() { return this.displayName; } + + /** + * Retrieves the corresponding TskData.FileKnown enum type that relates to this. + * @return The corresponding TskData.FileKnown. + */ + TskData.FileKnown getFileKnown() { + return this.fileKnown; + } + + /** + * Converts a TskData.FileKnown to the corresponding KnownFilesType. + * @param fileKnown The TskData.FileKnown type. + * @return The corresponding KnownFilesType. + */ + static KnownFilesType fromFileKnown(TskData.FileKnown fileKnown) { + if (fileKnown == null) + return null; + + return Stream.of(KnownFilesType.values()) + .filter((type) -> type.getFileKnown() == fileKnown) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Unknown TskData.FileKnown type: " + fileKnown)); + } } /** @@ -1229,12 +1273,7 @@ public class HashDbManager implements PropertyChangeListener { if (content instanceof AbstractFile) { AbstractFile file = (AbstractFile) content; if (null != file.getMd5Hash()) { - TskData.FileKnown type; - if(knownFilesType.equals(HashDb.KnownFilesType.KNOWN_BAD)){ - type = TskData.FileKnown.BAD; - } else { - type = TskData.FileKnown.KNOWN; - } + TskData.FileKnown type = knownFilesType.getFileKnown(); try{ CentralRepoFileInstance fileInstance = new CentralRepoFileInstance(referenceSetID, file.getMd5Hash(), @@ -1258,12 +1297,8 @@ public class HashDbManager implements PropertyChangeListener { public void addHashes(List hashes) throws TskCoreException { Set globalFileInstances = new HashSet<>(); for(HashEntry hashEntry:hashes){ - TskData.FileKnown type; - if(knownFilesType.equals(HashDb.KnownFilesType.KNOWN_BAD)){ - type = TskData.FileKnown.BAD; - } else { - type = TskData.FileKnown.KNOWN; - } + TskData.FileKnown type = knownFilesType.getFileKnown(); + try { globalFileInstances.add(new CentralRepoFileInstance(referenceSetID, hashEntry.getMd5Hash(), type, hashEntry.getComment())); } catch (CentralRepoException | CorrelationAttributeNormalizationException ex){ diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index 0f1f97ba97..0f9f99d79b 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -282,7 +282,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan // Update ingest option components. sendIngestMessagesCheckBox.setSelected(db.getSendIngestMessages()); - sendIngestMessagesCheckBox.setEnabled(!ingestIsRunning && db.getKnownFilesType().equals(KnownFilesType.KNOWN_BAD)); + sendIngestMessagesCheckBox.setEnabled(!ingestIsRunning && db.getKnownFilesType().isInboxMessagesAllowed()); // Update database action buttons. createDatabaseButton.setEnabled(true); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index f25471b0e0..355f509a37 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -231,12 +231,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P try { // Conver to the FileKnown enum used by EamGlobalSet - TskData.FileKnown knownStatus; - if (knownFilesType.equals(HashDbManager.HashDb.KnownFilesType.KNOWN)) { - knownStatus = TskData.FileKnown.KNOWN; - } else { - knownStatus = TskData.FileKnown.BAD; - } + TskData.FileKnown knownStatus = knownFilesType.getFileKnown(); // Create an empty hashset in the central repository CentralRepository dbManager = CentralRepository.getInstance(); From 842ccc52f3a155afa1a0444a4dae3f63c9931ed0 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 30 Apr 2020 11:17:49 -0400 Subject: [PATCH 05/90] working through kdb hashsetparser --- .../modules/hashdatabase/HashSetParser.java | 15 +++++ .../hashdatabase/KdbHashSetParser.java | 61 +++++++++++++------ 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java index 8a7a3ae034..9bd77717ce 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.modules.hashdatabase; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.HashEntry; interface HashSetParser { @@ -50,4 +51,18 @@ interface HashSetParser { * Closes the import file */ void close(); + + /** + * Get the next hash to import as a HashEntry object. + * + * @return A new hash entry for the next item parsed or null if no more items. + * @throws TskCoreException + */ + default HashEntry getNextHashEntry() throws TskCoreException { + String next = getNextHash(); + if (next == null) + return null; + + return new HashEntry(null, next, null, null, null); + } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java index 94d2724995..46eee12b6e 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java @@ -25,6 +25,7 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.HashEntry; import org.sleuthkit.datamodel.TskCoreException; /** @@ -68,7 +69,7 @@ public class KdbHashSetParser implements HashSetParser { } // Get the hashes - resultSet = statement.executeQuery("SELECT md5 FROM hashes"); + resultSet = statement.executeQuery("SELECT id, md5 FROM hashes"); // At this point, getNextHash can read each hash from the result set } catch (ClassNotFoundException | SQLException ex) { @@ -76,6 +77,38 @@ public class KdbHashSetParser implements HashSetParser { } } + + private static class HashRow { + private final String md5Hash; + private + } + + private Stuff getNextHashEntry() throws TskCoreException { + try { + if (resultSet.next()) { + long hashId = resultSet.getLong("id"); + byte[] hashBytes = resultSet.getBytes("md5"); + StringBuilder sb = new StringBuilder(); + for (byte b : hashBytes) { + sb.append(String.format("%02x", b)); + } + + if (sb.toString().length() != 32) { + throw new TskCoreException("Hash has incorrect length: " + sb.toString()); + } + + String md5Hash = sb.toString(); + return new + + totalHashesRead++; + + } else { + throw new TskCoreException("Could not read expected number of hashes from hash set " + filename); + } + } catch (SQLException ex) { + throw new TskCoreException("Error reading hash from result set for hash set " + filename, ex); + } + } /** * Get the next hash to import @@ -86,28 +119,16 @@ public class KdbHashSetParser implements HashSetParser { @Override public String getNextHash() throws TskCoreException { - try { - if (resultSet.next()) { - byte[] hashBytes = resultSet.getBytes("md5"); - StringBuilder sb = new StringBuilder(); - for (byte b : hashBytes) { - sb.append(String.format("%02x", b)); - } - if (sb.toString().length() != 32) { - throw new TskCoreException("Hash has incorrect length: " + sb.toString()); - } - - totalHashesRead++; - return sb.toString(); - } else { - throw new TskCoreException("Could not read expected number of hashes from hash set " + filename); - } - } catch (SQLException ex) { - throw new TskCoreException("Error reading hash from result set for hash set " + filename, ex); - } } + @Override + public HashEntry getNextHashEntry() throws TskCoreException { + return HashSetParser.super.getNextHashEntry(); //To change body of generated methods, choose Tools | Templates. + } + + + /** * Check if there are more hashes to read * From e4b13b9df1b5468ea4574beeb3e374ea8326c65c Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 30 Apr 2020 13:17:25 -0400 Subject: [PATCH 06/90] worked through kdb parser and integration --- .../modules/hashdatabase/HashSetParser.java | 2 +- .../ImportCentralRepoDbProgressDialog.java | 7 +-- .../hashdatabase/KdbHashSetParser.java | 48 +++++++++++++++---- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java index 9bd77717ce..e4b5d55632 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java @@ -55,7 +55,7 @@ interface HashSetParser { /** * Get the next hash to import as a HashEntry object. * - * @return A new hash entry for the next item parsed or null if no more items. + * @return A new hash entry for the next item parsed. * @throws TskCoreException */ default HashEntry getNextHashEntry() throws TskCoreException { diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 355f509a37..d626bd5c98 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -41,6 +41,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.datamodel.HashEntry; /** * Imports a hash set into the central repository and updates a progress dialog @@ -250,14 +251,14 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P return null; } - String newHash = hashSetParser.getNextHash(); + HashEntry newHash = hashSetParser.getNextHashEntry(); if (newHash != null) { CentralRepoFileInstance eamGlobalFileInstance = new CentralRepoFileInstance( referenceSetID.get(), - newHash, + newHash.getMd5Hash(), knownStatus, - ""); + newHash.getComment() != null ? newHash.getComment() : ""); globalInstances.add(eamGlobalFileInstance); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java index 46eee12b6e..d9b29b257c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java @@ -20,9 +20,12 @@ package org.sleuthkit.autopsy.modules.hashdatabase; import java.sql.Connection; import java.sql.DriverManager; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.HashEntry; @@ -80,10 +83,28 @@ public class KdbHashSetParser implements HashSetParser { private static class HashRow { private final String md5Hash; - private + private final long hashId; + + HashRow(String md5Hash, long hashId) { + this.md5Hash = md5Hash; + this.hashId = hashId; + } + + String getMd5Hash() { + return md5Hash; + } + + long getHashId() { + return hashId; + } } - private Stuff getNextHashEntry() throws TskCoreException { + /** + * Retrieves the row id and md5 hash for the next item in the hashes table. + * @return A hash row object containing the hash and id. + * @throws TskCoreException + */ + private HashRow getNextHashRow() throws TskCoreException { try { if (resultSet.next()) { long hashId = resultSet.getLong("id"); @@ -98,10 +119,8 @@ public class KdbHashSetParser implements HashSetParser { } String md5Hash = sb.toString(); - return new - totalHashesRead++; - + return new HashRow(md5Hash, hashId); } else { throw new TskCoreException("Could not read expected number of hashes from hash set " + filename); } @@ -118,13 +137,26 @@ public class KdbHashSetParser implements HashSetParser { */ @Override public String getNextHash() throws TskCoreException { - - + return getNextHashRow().getMd5Hash(); } @Override public HashEntry getNextHashEntry() throws TskCoreException { - return HashSetParser.super.getNextHashEntry(); //To change body of generated methods, choose Tools | Templates. + HashRow row = getNextHashRow(); + try { + PreparedStatement getComment = conn.prepareStatement("SELECT comment FROM comments WHERE hash_id = ?"); + getComment.setLong(0, row.getHashId()); + ResultSet commentResults = getComment.executeQuery(); + List comments = new ArrayList<>(); + while (commentResults.next()) + comments.add(commentResults.getString("comment")); + + String comment = comments.size() > 0 ? String.join(" ", comments) : null; + return new HashEntry(null, row.getMd5Hash(), null, null, comment); + } + catch (SQLException ex) { + throw new TskCoreException("Error opening/reading hash set " + filename, ex); + } } From 98ee56978e2bba6d209e388dd3cff81679420c41 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 30 Apr 2020 16:01:39 -0400 Subject: [PATCH 07/90] mostly worked through HashDbIngestModule --- .../modules/hashdatabase/Bundle.properties | 1 + .../hashdatabase/HashDbIngestModule.java | 407 ++++++++++++------ .../ImportCentralRepoDbProgressDialog.java | 2 +- 3 files changed, 274 insertions(+), 136 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties index ffd0a535ac..2e32d65089 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties @@ -95,6 +95,7 @@ HashDbIngestModule.calcHashValueErr=Error encountered while calculating the hash HashDbIngestModule.hashLookupErrorMsg=Hash Lookup Error: {0} HashDbIngestModule.settingKnownBadStateErr=Error encountered while setting notable state for {0}. HashDbIngestModule.lookingUpKnownBadHashValueErr=Error encountered while looking up notable hash value for {0}. +HashDbIngestModule.lookingUpNoChangeHashValueErr=Error encountered while looking up no change hash value for {0}. HashDbIngestModule.lookingUpKnownHashValueErr=Error encountered while looking up known hash value for {0}. HashDbIngestModule.postToBB.fileName=File Name HashDbIngestModule.postToBB.md5Hash=MD5 Hash diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index a562ab2a22..32268ccf53 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -24,7 +24,9 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Function; import java.util.logging.Level; +import java.util.stream.Collectors; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; @@ -38,6 +40,7 @@ import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Blackboard; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -63,6 +66,16 @@ import org.sleuthkit.datamodel.TskException; public class HashDbIngestModule implements FileIngestModule { private static final Logger logger = Logger.getLogger(HashDbIngestModule.class.getName()); + + private final Function knownBadLookupError = + (file) -> NbBundle.getMessage(this.getClass(), "HashDbIngestModule.lookingUpKnownBadHashValueErr", file.getName()); + + private final Function noChangeLookupError = + (file) -> NbBundle.getMessage(this.getClass(), "HashDbIngestModule.lookingUpNoChangeHashValueErr", file.getName()); + + private final Function knownLookupError = + (file) -> NbBundle.getMessage(this.getClass(), "HashDbIngestModule.lookingUpKnownHashValueErr", file.getName()); + private static final int MAX_COMMENT_SIZE = 500; private final IngestServices services = IngestServices.getInstance(); private final SleuthkitCase skCase; @@ -70,6 +83,7 @@ public class HashDbIngestModule implements FileIngestModule { private final HashLookupModuleSettings settings; private final List knownBadHashSets = new ArrayList<>(); private final List knownHashSets = new ArrayList<>(); + private final List noChangeHashSets = new ArrayList<>(); private long jobId; private static final HashMap totalsForIngestJobs = new HashMap<>(); private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); @@ -81,6 +95,7 @@ public class HashDbIngestModule implements FileIngestModule { private static class IngestJobTotals { private final AtomicLong totalKnownBadCount = new AtomicLong(0); + private final AtomicLong totalNoChangeCount = new AtomicLong(0); private final AtomicLong totalCalctime = new AtomicLong(0); private final AtomicLong totalLookuptime = new AtomicLong(0); } @@ -111,12 +126,11 @@ public class HashDbIngestModule implements FileIngestModule { @Override public void startUp(org.sleuthkit.autopsy.ingest.IngestJobContext context) throws IngestModuleException { jobId = context.getJobId(); - if (!hashDbManager.verifyAllDatabasesLoadedCorrectly()) { + if (!hashDbManager.verifyAllDatabasesLoadedCorrectly()) throw new IngestModuleException("Could not load all hash sets"); - } - updateEnabledHashSets(hashDbManager.getKnownBadFileHashSets(), knownBadHashSets); - updateEnabledHashSets(hashDbManager.getKnownFileHashSets(), knownHashSets); + initializeHashsets(hashDbManager.getAllHashSets()); + if (refCounter.incrementAndGet(jobId) == 1) { // initialize job totals getTotalsForIngestJobs(jobId); @@ -139,18 +153,27 @@ public class HashDbIngestModule implements FileIngestModule { } /** - * Cycle through list of hashsets and return the subset that is enabled. + * Cycle through list of hashsets and place each HashDB in the appropriate list based on KnownFilesType. * * @param allHashSets List of all hashsets from DB manager - * @param enabledHashSets List of enabled ones to return. */ - private void updateEnabledHashSets(List allHashSets, List enabledHashSets) { - enabledHashSets.clear(); + private void initializeHashsets(List allHashSets) { for (HashDb db : allHashSets) { if (settings.isHashSetEnabled(db)) { try { if (db.isValid()) { - enabledHashSets.add(db); + switch (db.getKnownFilesType()) { + case KNOWN: + knownHashSets.add(db); + break; + case KNOWN_BAD: + knownBadHashSets.add(db); + break; + case NO_CHANGE: + noChangeHashSets.add(db); + break; + default: throw new TskCoreException("Unknown KnownFilesType: " + db.getKnownFilesType()); + } } } catch (TskCoreException ex) { logger.log(Level.WARNING, "Error getting index status for " + db.getDisplayName() + " hash set", ex); //NON-NLS @@ -173,135 +196,41 @@ public class HashDbIngestModule implements FileIngestModule { logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS return ProcessResult.ERROR; } - - // Skip unallocated space files. - if ((file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) - || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK))) { + + if (shouldSkip(file)) return ProcessResult.OK; - } - - /* - * Skip directories. One reason for this is because we won't accurately - * calculate hashes of NTFS directories that have content that spans the - * IDX_ROOT and IDX_ALLOC artifacts. So we disable that until a solution - * for it is developed. - */ - if (file.isDir()) { - return ProcessResult.OK; - } - - // bail out if we have no hashes set - if ((knownHashSets.isEmpty()) && (knownBadHashSets.isEmpty()) && (!settings.shouldCalculateHashes())) { - return ProcessResult.OK; - } // Safely get a reference to the totalsForIngestJobs object IngestJobTotals totals = getTotalsForIngestJobs(jobId); - // calc hash value - String name = file.getName(); - long fileId = file.getId(); - String md5Hash = file.getMd5Hash(); - if (md5Hash == null || md5Hash.isEmpty()) { - try { - TimingMetric metric = HealthMonitor.getTimingMetric("Disk Reads: Hash calculation"); - long calcstart = System.currentTimeMillis(); - md5Hash = HashUtility.calculateMd5Hash(file); - if (file.getSize() > 0) { - // Surprisingly, the hash calculation does not seem to be correlated that - // strongly with file size until the files get large. - // Only normalize if the file size is greater than ~1MB. - if (file.getSize() < 1000000) { - HealthMonitor.submitTimingMetric(metric); - } else { - // In testing, this normalization gave reasonable resuls - HealthMonitor.submitNormalizedTimingMetric(metric, file.getSize() / 500000); - } - } - file.setMd5Hash(md5Hash); - long delta = (System.currentTimeMillis() - calcstart); - totals.totalCalctime.addAndGet(delta); + // calc hash value + String md5Hash = GetHash(file, totals); + if (md5Hash == null) + return ProcessResult.ERROR; - } catch (IOException ex) { - logger.log(Level.WARNING, String.format("Error calculating hash of file '%s' (id=%d).", name, fileId), ex); //NON-NLS - services.postMessage(IngestMessage.createErrorMessage( - HashLookupModuleFactory.getModuleName(), - NbBundle.getMessage(this.getClass(), "HashDbIngestModule.fileReadErrorMsg", name), - NbBundle.getMessage(this.getClass(), "HashDbIngestModule.calcHashValueErr", - file.getParentPath() + file.getName(), - file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)?"Allocated File" : "Deleted File"))); - return ProcessResult.ERROR; - } - } - - // look up in notable first - boolean foundBad = false; + // the processing result of handling this file ProcessResult ret = ProcessResult.OK; - for (HashDb db : knownBadHashSets) { - try { - long lookupstart = System.currentTimeMillis(); - HashHitInfo hashInfo = db.lookupMD5(file); - if (null != hashInfo) { - foundBad = true; - totals.totalKnownBadCount.incrementAndGet(); + + // look up in notable first + FindInHashsetsResult knownBadResult = findInHashsets(file, totals.totalKnownBadCount, + totals.totalLookuptime, knownBadHashSets, TskData.FileKnown.BAD, knownBadLookupError); + + boolean foundBad = knownBadResult.isFound(); + if (knownBadResult.isError()) + ret = ProcessResult.ERROR; - file.setKnown(TskData.FileKnown.BAD); - - String hashSetName = db.getDisplayName(); - - String comment = ""; - ArrayList comments = hashInfo.getComments(); - int i = 0; - for (String c : comments) { - if (++i > 1) { - comment += " "; - } - comment += c; - if (comment.length() > MAX_COMMENT_SIZE) { - comment = comment.substring(0, MAX_COMMENT_SIZE) + "..."; - break; - } - } - - /* - * We have a match. Now create an artifact if it is - * determined that one hasn't been created yet. - */ - List attributesList = new ArrayList<>(); - attributesList.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, HashLookupModuleFactory.getModuleName(), hashSetName)); - try { - org.sleuthkit.datamodel.Blackboard tskBlackboard = skCase.getBlackboard(); - if (tskBlackboard.artifactExists(file, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT, attributesList) == false) { - postHashSetHitToBlackboard(file, md5Hash, hashSetName, comment, db.getSendIngestMessages()); - } - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, String.format( - "A problem occurred while checking for existing artifacts for file '%s' (id=%d).", name, fileId), ex); //NON-NLS - services.postMessage(IngestMessage.createErrorMessage( - HashLookupModuleFactory.getModuleName(), - Bundle.HashDbIngestModule_dialogTitle_errorFindingArtifacts(name), - Bundle.HashDbIngestModule_errorMessage_lookingForFileArtifacts(name))); - ret = ProcessResult.ERROR; - } - } - long delta = (System.currentTimeMillis() - lookupstart); - totals.totalLookuptime.addAndGet(delta); - - } catch (TskException ex) { - logger.log(Level.WARNING, String.format( - "Couldn't lookup notable hash for file '%s' (id=%d) - see sleuthkit log for details", name, fileId), ex); //NON-NLS - services.postMessage(IngestMessage.createErrorMessage( - HashLookupModuleFactory.getModuleName(), - NbBundle.getMessage(this.getClass(), "HashDbIngestModule.hashLookupErrorMsg", name), - NbBundle.getMessage(this.getClass(), "HashDbIngestModule.lookingUpKnownBadHashValueErr", name))); - ret = ProcessResult.ERROR; - } - } + // look up no change items next + FindInHashsetsResult noChangeResult = findInHashsets(file, totals.totalNoChangeCount, + totals.totalLookuptime, noChangeHashSets, TskData.FileKnown.BAD, noChangeLookupError); + + boolean foundNoChange = noChangeResult.isFound(); + if (noChangeResult.isError()) + ret = ProcessResult.ERROR; // If the file is not in the notable sets, search for it in the known sets. // Any hit is sufficient to classify it as known, and there is no need to create // a hit artifact or send a message to the application inbox. - if (!foundBad) { + if (!foundBad && !foundNoChange) { for (HashDb db : knownHashSets) { try { long lookupstart = System.currentTimeMillis(); @@ -313,12 +242,7 @@ public class HashDbIngestModule implements FileIngestModule { totals.totalLookuptime.addAndGet(delta); } catch (TskException ex) { - logger.log(Level.WARNING, String.format( - "Couldn't lookup known hash for file '%s' (id=%d) - see sleuthkit log for details", name, fileId), ex); //NON-NLS - services.postMessage(IngestMessage.createErrorMessage( - HashLookupModuleFactory.getModuleName(), - NbBundle.getMessage(this.getClass(), "HashDbIngestModule.hashLookupErrorMsg", name), - NbBundle.getMessage(this.getClass(), "HashDbIngestModule.lookingUpKnownHashValueErr", name))); + reportLookupError(ex, file, knownLookupError); ret = ProcessResult.ERROR; } } @@ -326,6 +250,218 @@ public class HashDbIngestModule implements FileIngestModule { return ret; } + + /** + * Returns true if this file should be skipped for processing. + * @param file The file to potentially skip. + * @return True if this file should be skipped. + */ + private boolean shouldSkip(AbstractFile file) { + // Skip unallocated space files. + if ((file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) + || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK))) { + return true; + } + + /* + * Skip directories. One reason for this is because we won't accurately + * calculate hashes of NTFS directories that have content that spans the + * IDX_ROOT and IDX_ALLOC artifacts. So we disable that until a solution + * for it is developed. + */ + if (file.isDir()) + return true; + + // bail out if we have no hashes set + if ((knownHashSets.isEmpty()) && (knownBadHashSets.isEmpty()) && (!settings.shouldCalculateHashes())) + return true; + + return false; + } + + + /** + * Reports an error when an issue is encountered looking up a file. + * @param ex The exception thrown in the error. + * @param file The file for which this error applies. + * @param lookupErrorMessage The function that generates an error message specific to which piece of the ingest processing failed. + */ + private void reportLookupError(TskException ex, AbstractFile file, Function lookupErrorMessage) { + logger.log(Level.WARNING, String.format( + "Couldn't lookup notable hash for file '%s' (id=%d) - see sleuthkit log for details", file.getName(), file.getId()), ex); //NON-NLS + services.postMessage(IngestMessage.createErrorMessage( + HashLookupModuleFactory.getModuleName(), + NbBundle.getMessage(this.getClass(), "HashDbIngestModule.hashLookupErrorMsg", file.getName()), + lookupErrorMessage.apply(file))); + } + + /** + * The result of attempting to find a file in a list of HashDB objects. + */ + private static class FindInHashsetsResult { + private final boolean found; + private final boolean error; + + FindInHashsetsResult(boolean found, boolean error) { + this.found = found; + this.error = error; + } + + /** + * Returns true if the file was found in the HashDB. + * @return True if the file was found in the HashDB. + */ + boolean isFound() { + return found; + } + + /** + * Returns true if there was an error in the process of finding a file in a HashDB. + * @return True if there was an error in the process of finding a file in a HashDB. + */ + boolean isError() { + return error; + } + } + + /** + * Attempts to find an abstract file in a list of HashDB objects. + * @param file The file to find. + * @param totalCount The total cound of files found in this type + * @param totalLookupTime The counter tracking the total amount of run time for this operation. + * @param hashSets The HashDB objects to cycle through looking for a hash hit. + * @param statusIfFound The FileKnown status to set on the file if the file is found in the hashSets. + * @param lookupErrorMessage The function that generates a message should there be an error in looking up the file in the hashSets. + * @return Whether or not the file was found and whether or not there was an error during the operation. + */ + private FindInHashsetsResult findInHashsets(AbstractFile file, AtomicLong totalCount, AtomicLong totalLookupTime, + List hashSets, TskData.FileKnown statusIfFound, Function lookupErrorMessage) { + + boolean found = false; + boolean wasError = false; + for (HashDb db : hashSets) { + try { + long lookupstart = System.currentTimeMillis(); + HashHitInfo hashInfo = db.lookupMD5(file); + if (null != hashInfo) { + found = true; + + totalCount.incrementAndGet(); + file.setKnown(statusIfFound); + String hashSetName = db.getDisplayName(); + String comment = generateComment(hashInfo); + if (!createArtifactIfNoneExists(hashSetName, file, comment, db)) + wasError = true; + } + long delta = (System.currentTimeMillis() - lookupstart); + totalLookupTime.addAndGet(delta); + + } catch (TskException ex) { + reportLookupError(ex, file, lookupErrorMessage); + wasError = true; + } + } + + return new FindInHashsetsResult(found, wasError); + } + + /** + * Generates a formatted comment. + * @param hashInfo The HashHitInfo. + * @return The formatted comment. + */ + private String generateComment(HashHitInfo hashInfo) { + String comment = ""; + ArrayList comments = hashInfo.getComments(); + int i = 0; + for (String c : comments) { + if (++i > 1) { + comment += " "; + } + comment += c; + if (comment.length() > MAX_COMMENT_SIZE) { + comment = comment.substring(0, MAX_COMMENT_SIZE) + "..."; + break; + } + } + return comment; + } + + /** + * Creates a BlackboardArtifact if no TSK_HASHSET_HIT artifact exists for this file. + * @param hashSetName The name of the hashset found. + * @param file The file that had a hash hit. + * @param comment The comment to associate with this artifact. + * @param db the database in which this file was found. + * @return True if the operation occurred successfully and without error. + */ + private boolean createArtifactIfNoneExists(String hashSetName, AbstractFile file, String comment, HashDb db) { + /* + * We have a match. Now create an artifact if it is + * determined that one hasn't been created yet. + */ + List attributesList = new ArrayList<>(); + attributesList.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, HashLookupModuleFactory.getModuleName(), hashSetName)); + try { + Blackboard tskBlackboard = skCase.getBlackboard(); + if (tskBlackboard.artifactExists(file, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT, attributesList) == false) { + postHashSetHitToBlackboard(file, file.getMd5Hash(), hashSetName, comment, db.getSendIngestMessages()); + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format( + "A problem occurred while checking for existing artifacts for file '%s' (id=%d).", file.getName(), file.getId()), ex); //NON-NLS + services.postMessage(IngestMessage.createErrorMessage( + HashLookupModuleFactory.getModuleName(), + Bundle.HashDbIngestModule_dialogTitle_errorFindingArtifacts(file.getName()), + Bundle.HashDbIngestModule_errorMessage_lookingForFileArtifacts(file.getName()))); + return false; + } + return true; + } + + /** + * Retrieves the md5 hash for a file or generates one if no one exists on the file. + * @param file The file in order to determine the hash. + * @param totals The timing metrics for this process. + * @return The found or determined md5 hash or null if none could be determined. + */ + private String GetHash(AbstractFile file, IngestJobTotals totals) { + String md5Hash = file.getMd5Hash(); + if (md5Hash != null && md5Hash.isEmpty()) + return md5Hash; + + try { + TimingMetric metric = HealthMonitor.getTimingMetric("Disk Reads: Hash calculation"); + long calcstart = System.currentTimeMillis(); + md5Hash = HashUtility.calculateMd5Hash(file); + if (file.getSize() > 0) { + // Surprisingly, the hash calculation does not seem to be correlated that + // strongly with file size until the files get large. + // Only normalize if the file size is greater than ~1MB. + if (file.getSize() < 1000000) { + HealthMonitor.submitTimingMetric(metric); + } + else { + // In testing, this normalization gave reasonable resuls + HealthMonitor.submitNormalizedTimingMetric(metric, file.getSize() / 500000); + } + } + file.setMd5Hash(md5Hash); + long delta = (System.currentTimeMillis() - calcstart); + totals.totalCalctime.addAndGet(delta); + return md5Hash; + } + catch (IOException ex) { + logger.log(Level.WARNING, String.format("Error calculating hash of file '%s' (id=%d).", file.getName(), file.getId()), ex); //NON-NLS + services.postMessage(IngestMessage.createErrorMessage( + HashLookupModuleFactory.getModuleName(), + NbBundle.getMessage(this.getClass(), "HashDbIngestModule.fileReadErrorMsg", file.getName()), + NbBundle.getMessage(this.getClass(), "HashDbIngestModule.calcHashValueErr", + file.getParentPath() + file.getName(), + file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)?"Allocated File" : "Deleted File"))); + return null; + } + } /** * Post a hash set hit to the blackboard. @@ -413,8 +549,9 @@ public class HashDbIngestModule implements FileIngestModule { * @param knownBadHashSets The list of hash sets for "known bad" files. * @param knownHashSets The list of hash sets for "known" files. */ - private static synchronized void postSummary(long jobId, - List knownBadHashSets, List knownHashSets) { + private static synchronized void postSummary(long jobId, List knownBadHashSets, + List noChangeHashSets, List knownHashSets) { + IngestJobTotals jobTotals = getTotalsForIngestJobs(jobId); totalsForIngestJobs.remove(jobId); @@ -456,7 +593,7 @@ public class HashDbIngestModule implements FileIngestModule { @Override public void shutDown() { if (refCounter.decrementAndGet(jobId) == 0) { - postSummary(jobId, knownBadHashSets, knownHashSets); + postSummary(jobId, knownBadHashSets, noChangeHashSets, knownHashSets); } } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index d626bd5c98..030a38cb35 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -258,7 +258,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P referenceSetID.get(), newHash.getMd5Hash(), knownStatus, - newHash.getComment() != null ? newHash.getComment() : ""); + newHash.getComment()); globalInstances.add(eamGlobalFileInstance); From 928bbd40ed362743b32c8bc8e7e9e08ebdd5e113 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 1 May 2020 08:45:09 -0400 Subject: [PATCH 08/90] requires comma for comment --- ...AddHashValuesToDatabaseProgressDialog.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java index 99eecf50d2..73d1a02314 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java @@ -30,6 +30,7 @@ import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingWorker; +import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.datamodel.HashEntry; @@ -46,7 +47,14 @@ public class AddHashValuesToDatabaseProgressDialog extends javax.swing.JDialog { private final HashDb hashDb; private final List hashes; private final List invalidHashes; - private final Pattern md5Pattern; + + // Matches hash with optional comma separated comment. + private static final Pattern HASH_LINE_PATTERN = Pattern.compile("^([a-fA-F0-9]{32})(,(.*))?$"); + // The regex group for the hash. + private static final int HASH_GROUP = 1; + // The regex group for the comment. + private static final int COMMENT_GROUP = 3; + private String errorTitle; private String errorMessage; private final String text; @@ -64,7 +72,6 @@ public class AddHashValuesToDatabaseProgressDialog extends javax.swing.JDialog { display(parent); this.hashes = new ArrayList<>(); this.invalidHashes = new ArrayList<>(); - this.md5Pattern = Pattern.compile("^([a-fA-F0-9]{32})"); // NON-NLS this.parentRef = parent; this.hashDb = hashDb; this.text = text; @@ -161,17 +168,15 @@ public class AddHashValuesToDatabaseProgressDialog extends javax.swing.JDialog { // These entries may be of or format for (String hashEntry : linesInTextArea) { hashEntry = hashEntry.trim(); - Matcher m = md5Pattern.matcher(hashEntry); + Matcher m = HASH_LINE_PATTERN.matcher(hashEntry); if (m.find()) { - // Is there any text left on this line? If so, treat it as a comment. - String comment = hashEntry.substring(m.end()).trim(); - if (comment.length() > 0) { - comment = (comment.charAt(0) == ',') ? comment.substring(1) : comment; - hashes.add(new HashEntry(null, m.group(0), null, null, comment)); - } else { - // more information can be added to the HashEntry - sha-1, sha-512, comment - hashes.add(new HashEntry(null, m.group(0), null, null, null)); - } + String hash = m.group(HASH_GROUP); + + // if there was a match and the match is not empty, assign to comment + String comment = StringUtils.isNotBlank(m.group(COMMENT_GROUP)) ? + m.group(COMMENT_GROUP).trim() : null; + + hashes.add(new HashEntry(null, hash, null, null, comment)); } else { if (!hashEntry.isEmpty()) { invalidHashes.add(hashEntry); From d542a29a27670b9f282db7ec183ab53ab21a6373 Mon Sep 17 00:00:00 2001 From: apriestman Date: Fri, 1 May 2020 11:34:56 -0400 Subject: [PATCH 09/90] AddImageTask no longer gets write lock --- Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java index 17980cd0cd..2a26a714f9 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -132,7 +132,7 @@ class AddImageTask implements Runnable { List errorMessages = new ArrayList<>(); List newDataSources = new ArrayList<>(); try { - currentCase.getSleuthkitCase().acquireSingleUserCaseWriteLock(); + //currentCase.getSleuthkitCase().acquireSingleUserCaseWriteLock(); synchronized (tskAddImageProcessLock) { if (!tskAddImageProcessStopped) { tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles, imageWriterPath); @@ -147,7 +147,7 @@ class AddImageTask implements Runnable { commitOrRevertAddImageProcess(currentCase, errorMessages, newDataSources); progressMonitor.setProgress(100); } finally { - currentCase.getSleuthkitCase().releaseSingleUserCaseWriteLock(); + //currentCase.getSleuthkitCase().releaseSingleUserCaseWriteLock(); DataSourceProcessorCallback.DataSourceProcessorResult result; if (criticalErrorOccurred) { result = DataSourceProcessorResult.CRITICAL_ERRORS; From bcb4927cdc090dde61d7517f59e6ff08ce1e77a3 Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Mon, 4 May 2020 10:35:37 -0400 Subject: [PATCH 10/90] 6323: Persona UI skeleton --- .../autopsy/persona/Bundle.properties | 3 + .../autopsy/persona/Bundle.properties-MERGED | 5 + .../autopsy/persona/OpenPersonasAction.java | 95 +++++++++++++++++++ .../autopsy/persona/PersonasTopComponent.form | 49 ++++++++++ .../autopsy/persona/PersonasTopComponent.java | 63 ++++++++++++ .../netbeans/core/startup/Bundle.properties | 4 +- .../core/windows/view/ui/Bundle.properties | 6 +- 7 files changed, 220 insertions(+), 5 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/persona/Bundle.properties create mode 100644 Core/src/org/sleuthkit/autopsy/persona/Bundle.properties-MERGED create mode 100644 Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java create mode 100644 Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form create mode 100644 Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java diff --git a/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties b/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties new file mode 100644 index 0000000000..2ddf32efdc --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties @@ -0,0 +1,3 @@ +CTL_OpenPersonas=Personas +CTL_PersonasTopComponentAction=PersonasTopComponent +CTL_PersonasTopComponent=Personas \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties-MERGED new file mode 100644 index 0000000000..1e9b1769d2 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties-MERGED @@ -0,0 +1,5 @@ +CTL_OpenPersonas=Personas +CTL_PersonasTopComponentAction=PersonasTopComponent +CTL_PersonasTopComponent=Personas +OpenPersonasAction.displayName=Personas +PTopComponent_Name=Personas diff --git a/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java b/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java new file mode 100644 index 0000000000..5f37eb92d9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java @@ -0,0 +1,95 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014-2018 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.persona; + +import javax.swing.JMenuItem; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionReferences; +import org.openide.awt.ActionRegistration; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.actions.CallableSystemAction; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; + +/** + * An Action that opens the Personas window. + */ + +@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.persona.Personas") +@ActionRegistration(displayName = "#CTL_OpenPersonas", lazy = false) +@ActionReferences(value = { + @ActionReference(path = "Menu/Tools", position = 105) +}) +public final class OpenPersonasAction extends CallableSystemAction { + + private static final long serialVersionUID = 1L; + private static final Logger logger = Logger.getLogger(OpenPersonasAction.class.getName()); + + private final JMenuItem menuItem; + + + public OpenPersonasAction() { + menuItem = super.getMenuPresenter(); + this.setEnabled(true); + } + + @Override + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + public void performAction() { + final TopComponent topComponent = WindowManager.getDefault().findTopComponent("PersonasTopComponent"); + if (topComponent != null) { + if (topComponent.isOpened() == false) { + topComponent.open(); + } + topComponent.toFront(); + topComponent.requestActive(); + } + } + + @Override + @NbBundle.Messages("OpenPersonasAction.displayName=Personas") + public String getName() { + return Bundle.OpenPersonasAction_displayName(); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + public boolean asynchronous() { + return false; // run on edt + } + + @Override + public void setEnabled(boolean enable) { + super.setEnabled(enable); + menuItem.setEnabled(enable); + } + + @Override + public JMenuItem getMenuPresenter() { + return menuItem; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form new file mode 100644 index 0000000000..6fe1c2a940 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form @@ -0,0 +1,49 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java new file mode 100644 index 0000000000..fbac97559e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java @@ -0,0 +1,63 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014-2018 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.persona; + +import org.openide.util.NbBundle.Messages; +import org.openide.windows.RetainLocation; +import org.openide.windows.TopComponent; + + +@TopComponent.Description(preferredID = "PersonasTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER) +@TopComponent.Registration(mode = "personas", openAtStartup = false) +@RetainLocation("personas") +@SuppressWarnings("PMD.SingularField") +public final class PersonasTopComponent extends TopComponent { + + @Messages({ + "PTopComponent_Name=Personas" + }) + public PersonasTopComponent() { + initComponents(); + setName(Bundle.PTopComponent_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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 300, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + +} diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index b20ccf5912..8cc172caa2 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Tue, 12 Nov 2019 17:21:46 -0500 +#Thu, 30 Apr 2020 11:26:58 -0400 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 4.13.0 +currentVersion=Autopsy 4.15.0 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 998d3f715c..53e196424c 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #Updated by build script -#Tue, 12 Nov 2019 17:21:46 -0500 -CTL_MainWindow_Title=Autopsy 4.13.0 -CTL_MainWindow_Title_No_Project=Autopsy 4.13.0 +#Thu, 30 Apr 2020 11:26:58 -0400 +CTL_MainWindow_Title=Autopsy 4.15.0 +CTL_MainWindow_Title_No_Project=Autopsy 4.15.0 From 9c86982ca2db3812e5ab85817c48cef6624b1fef Mon Sep 17 00:00:00 2001 From: apriestman Date: Mon, 4 May 2020 14:21:04 -0400 Subject: [PATCH 11/90] Cleanup --- Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java index 2a26a714f9..a1443bde31 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -132,7 +132,6 @@ class AddImageTask implements Runnable { List errorMessages = new ArrayList<>(); List newDataSources = new ArrayList<>(); try { - //currentCase.getSleuthkitCase().acquireSingleUserCaseWriteLock(); synchronized (tskAddImageProcessLock) { if (!tskAddImageProcessStopped) { tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles, imageWriterPath); @@ -147,7 +146,6 @@ class AddImageTask implements Runnable { commitOrRevertAddImageProcess(currentCase, errorMessages, newDataSources); progressMonitor.setProgress(100); } finally { - //currentCase.getSleuthkitCase().releaseSingleUserCaseWriteLock(); DataSourceProcessorCallback.DataSourceProcessorResult result; if (criticalErrorOccurred) { result = DataSourceProcessorResult.CRITICAL_ERRORS; From 781d6fd65516dd1b28a3558698e6596dc94df4d6 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 5 May 2020 10:03:41 -0400 Subject: [PATCH 12/90] fix for initial selected --- .../modules/hashdatabase/HashDbCreateDatabaseDialog.form | 2 +- .../modules/hashdatabase/HashDbCreateDatabaseDialog.java | 2 +- .../modules/hashdatabase/HashDbImportDatabaseDialog.form | 1 + .../modules/hashdatabase/HashDbImportDatabaseDialog.java | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.form index 8eae9f15c4..b274f93d3c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.form @@ -186,6 +186,7 @@ + @@ -320,7 +321,6 @@ - diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index 5b7c0f1944..7f15bb47ac 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -225,6 +225,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { }); buttonGroup1.add(knownBadRadioButton); + knownBadRadioButton.setSelected(true); org.openide.awt.Mnemonics.setLocalizedText(knownBadRadioButton, org.openide.util.NbBundle.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.knownBadRadioButton.text")); // NOI18N knownBadRadioButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -293,7 +294,6 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { }); buttonGroup1.add(noChangeRadioButton); - noChangeRadioButton.setSelected(true); org.openide.awt.Mnemonics.setLocalizedText(noChangeRadioButton, org.openide.util.NbBundle.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.noChangeRadioButton.text")); // NOI18N noChangeRadioButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form index 720d3763a2..13ed7fbf57 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form @@ -228,6 +228,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index 10b9827404..c2716c4927 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -219,6 +219,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { }); buttonGroup1.add(knownBadRadioButton); + knownBadRadioButton.setSelected(true); org.openide.awt.Mnemonics.setLocalizedText(knownBadRadioButton, org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.knownBadRadioButton.text")); // NOI18N knownBadRadioButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { From ca79ad38de9d4419f5f3ebacc11f296224241640 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 5 May 2020 10:06:18 -0400 Subject: [PATCH 13/90] revert annotations viewer --- .../autopsy/contentviewers/AnnotationsContentViewer.form | 4 ++-- .../autopsy/contentviewers/AnnotationsContentViewer.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.form index 986492a810..4fe61b2fb5 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.form @@ -21,12 +21,12 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index 84b68b02df..c5c92b11c0 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -399,11 +399,11 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 696, Short.MAX_VALUE) + .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 907, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane5, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 494, Short.MAX_VALUE) + .addComponent(jScrollPane5, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE) ); }// //GEN-END:initComponents From 17f44ae56039b714a6666f62d188d22930383d96 Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Tue, 5 May 2020 10:10:56 -0400 Subject: [PATCH 14/90] 6323 Updating copyright years --- Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java | 2 +- .../src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java b/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java index 5f37eb92d9..c4ca19bb4f 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java +++ b/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014-2018 Basis Technology Corp. + * Copyright 2014-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java index fbac97559e..44ea5fb534 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014-2018 Basis Technology Corp. + * Copyright 2014-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); From aa9991ef0391b510d20d58e8ccefb7351b85378b Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Tue, 5 May 2020 10:13:45 -0400 Subject: [PATCH 15/90] 6323 Restoring .properties --- .../core.jar/org/netbeans/core/startup/Bundle.properties | 4 ++-- .../org/netbeans/core/windows/view/ui/Bundle.properties | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 8cc172caa2..b20ccf5912 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Thu, 30 Apr 2020 11:26:58 -0400 +#Tue, 12 Nov 2019 17:21:46 -0500 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 4.15.0 +currentVersion=Autopsy 4.13.0 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 53e196424c..998d3f715c 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #Updated by build script -#Thu, 30 Apr 2020 11:26:58 -0400 -CTL_MainWindow_Title=Autopsy 4.15.0 -CTL_MainWindow_Title_No_Project=Autopsy 4.15.0 +#Tue, 12 Nov 2019 17:21:46 -0500 +CTL_MainWindow_Title=Autopsy 4.13.0 +CTL_MainWindow_Title_No_Project=Autopsy 4.13.0 From f6c06488c51ee32485f8d1afc5d441748ccff0fb Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Tue, 5 May 2020 10:21:55 -0400 Subject: [PATCH 16/90] Fixed date filter NPE when no waypoints or tracks have timestamps --- .../geolocation/AbstractWaypointFetcher.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java b/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java index e923d6dbd6..0e398b9f22 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java @@ -120,13 +120,15 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter // Figure out what the most recent time is given the filtered // waypoints and the tracks. timeRangeEnd = getMostRecent(waypoints, tracks); - timeRangeStart = timeRangeEnd - (86400 * filters.getMostRecentNumDays()); + if (timeRangeEnd != null) { + timeRangeStart = timeRangeEnd - (86400 * filters.getMostRecentNumDays()); - completeList.addAll(getWaypointsInRange(timeRangeStart, timeRangeEnd, waypoints)); - - filteredTracks = getTracksInRange(timeRangeStart, timeRangeEnd, tracks); - for (List filteredTrack : filteredTracks) { - completeList.addAll(filteredTrack); + completeList.addAll(getWaypointsInRange(timeRangeStart, timeRangeEnd, waypoints)); + + filteredTracks = getTracksInRange(timeRangeStart, timeRangeEnd, tracks); + for (List filteredTrack : filteredTracks) { + completeList.addAll(filteredTrack); + } } } else { completeList.addAll(waypoints); From 306632cc3cfb205aa2aa8d676abb3111b788d062 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 5 May 2020 11:40:13 -0400 Subject: [PATCH 17/90] some minor bug fixes --- .../autopsy/modules/hashdatabase/Bundle.properties | 5 ----- .../modules/hashdatabase/HashDbIngestModule.java | 14 ++++++++------ .../modules/hashdatabase/HashDbManager.java | 11 ++++++++--- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties index 2e32d65089..e7ed2dedd7 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties @@ -94,9 +94,6 @@ HashDbIngestModule.fileReadErrorMsg=Read Error: {0} HashDbIngestModule.calcHashValueErr=Error encountered while calculating the hash value for {0} ({1}). HashDbIngestModule.hashLookupErrorMsg=Hash Lookup Error: {0} HashDbIngestModule.settingKnownBadStateErr=Error encountered while setting notable state for {0}. -HashDbIngestModule.lookingUpKnownBadHashValueErr=Error encountered while looking up notable hash value for {0}. -HashDbIngestModule.lookingUpNoChangeHashValueErr=Error encountered while looking up no change hash value for {0}. -HashDbIngestModule.lookingUpKnownHashValueErr=Error encountered while looking up known hash value for {0}. HashDbIngestModule.postToBB.fileName=File Name HashDbIngestModule.postToBB.md5Hash=MD5 Hash HashDbIngestModule.postToBB.hashsetName=Hash Set Name @@ -146,8 +143,6 @@ HashDbManager.hashDbFileExistsExceptionMsg=A file already exists at\n{0} HashDbManager.hashDbAlreadyAddedExceptionMsg=The hash set at\n{0}\nhas already been created or imported. HashDbManager.illegalHashDbFileNameExtensionMsg=The hash set file name must have a .{0} extension. HashDbManager.moduleErr=Module Error -HashDbManager.knownBad.text=Notable -HashDbManager.known.text=Known HashDbManager.fileNameExtensionFilter.title=Hash Set File HashDbSearchAction.dlgMsg.title=File Search by MD5 Hash HashDbSearchAction.getName.text=Hash Search diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index 32268ccf53..0f471c0f76 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -61,20 +61,23 @@ import org.sleuthkit.datamodel.TskException; "HashDbIngestModule.noKnownBadHashDbSetMsg=No notable hash set.", "HashDbIngestModule.knownBadFileSearchWillNotExecuteWarn=Notable file search will not be executed.", "HashDbIngestModule.noKnownHashDbSetMsg=No known hash set.", - "HashDbIngestModule.knownFileSearchWillNotExecuteWarn=Known file search will not be executed." + "HashDbIngestModule.knownFileSearchWillNotExecuteWarn=Known file search will not be executed.", + "# {0} - fileName", "HashDbIngestModule.lookingUpKnownBadHashValueErr=Error encountered while looking up notable hash value for {0}.", + "# {0} - fileName", "HashDbIngestModule.lookingUpNoChangeHashValueErr=Error encountered while looking up no change hash value for {0}.", + "# {0} - fileName", "HashDbIngestModule.lookingUpKnownHashValueErr=Error encountered while looking up known hash value for {0}.", }) public class HashDbIngestModule implements FileIngestModule { private static final Logger logger = Logger.getLogger(HashDbIngestModule.class.getName()); private final Function knownBadLookupError = - (file) -> NbBundle.getMessage(this.getClass(), "HashDbIngestModule.lookingUpKnownBadHashValueErr", file.getName()); + (file) -> Bundle.HashDbIngestModule_lookingUpKnownBadHashValueErr(file.getName()); private final Function noChangeLookupError = - (file) -> NbBundle.getMessage(this.getClass(), "HashDbIngestModule.lookingUpNoChangeHashValueErr", file.getName()); + (file) -> Bundle.HashDbIngestModule_lookingUpNoChangeHashValueErr(file.getName()); private final Function knownLookupError = - (file) -> NbBundle.getMessage(this.getClass(), "HashDbIngestModule.lookingUpKnownHashValueErr", file.getName()); + (file) -> Bundle.HashDbIngestModule_lookingUpKnownHashValueErr(file.getName()); private static final int MAX_COMMENT_SIZE = 500; private final IngestServices services = IngestServices.getInstance(); @@ -223,14 +226,13 @@ public class HashDbIngestModule implements FileIngestModule { FindInHashsetsResult noChangeResult = findInHashsets(file, totals.totalNoChangeCount, totals.totalLookuptime, noChangeHashSets, TskData.FileKnown.BAD, noChangeLookupError); - boolean foundNoChange = noChangeResult.isFound(); if (noChangeResult.isError()) ret = ProcessResult.ERROR; // If the file is not in the notable sets, search for it in the known sets. // Any hit is sufficient to classify it as known, and there is no need to create // a hit artifact or send a message to the application inbox. - if (!foundBad && !foundNoChange) { + if (!foundBad) { for (HashDb db : knownHashSets) { try { long lookupstart = System.currentTimeMillis(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index 372538be64..ebc31b1d4a 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -695,11 +695,16 @@ public class HashDbManager implements PropertyChangeListener { * Indicates how files with hashes stored in a particular hash database * object should be classified. */ + @Messages({ + "HashDbManager.noChange.text=No Change", + "HashDbManager.known.text=Known", + "HashDbManager.knownBad.text=Notable" + }) public enum KnownFilesType { - KNOWN(NbBundle.getMessage(HashDbManager.class, "HashDbManager.known.text"), TskData.FileKnown.KNOWN, false, false), - KNOWN_BAD(NbBundle.getMessage(HashDbManager.class, "HashDbManager.knownBad.text"), TskData.FileKnown.BAD, true, true), - NO_CHANGE(NbBundle.getMessage(HashDbManager.class, "HashDbManager.noChange.text"), TskData.FileKnown.UNKNOWN, true , false); + KNOWN(Bundle.HashDbManager_known_text(), TskData.FileKnown.KNOWN, false, false), + KNOWN_BAD(Bundle.HashDbManager_knownBad_text(), TskData.FileKnown.BAD, true, true), + NO_CHANGE(Bundle.HashDbManager_noChange_text(), TskData.FileKnown.UNKNOWN, true , false); private final String displayName; private final TskData.FileKnown fileKnown; From d1b1bb88ae59d872c49c87630cb3486d629f1833 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 5 May 2020 12:04:13 -0400 Subject: [PATCH 18/90] naming convention change --- .../autopsy/modules/hashdatabase/HashDbIngestModule.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index 0f471c0f76..dc8646dbe4 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -352,7 +352,7 @@ public class HashDbIngestModule implements FileIngestModule { file.setKnown(statusIfFound); String hashSetName = db.getDisplayName(); String comment = generateComment(hashInfo); - if (!createArtifactIfNoneExists(hashSetName, file, comment, db)) + if (!createArtifactIfNotExists(hashSetName, file, comment, db)) wasError = true; } long delta = (System.currentTimeMillis() - lookupstart); @@ -390,14 +390,14 @@ public class HashDbIngestModule implements FileIngestModule { } /** - * Creates a BlackboardArtifact if no TSK_HASHSET_HIT artifact exists for this file. + * Creates a BlackboardArtifact if artifact does not already exist. * @param hashSetName The name of the hashset found. * @param file The file that had a hash hit. * @param comment The comment to associate with this artifact. * @param db the database in which this file was found. * @return True if the operation occurred successfully and without error. */ - private boolean createArtifactIfNoneExists(String hashSetName, AbstractFile file, String comment, HashDb db) { + private boolean createArtifactIfNotExists(String hashSetName, AbstractFile file, String comment, HashDb db) { /* * We have a match. Now create an artifact if it is * determined that one hasn't been created yet. From be99f86a2bf75f3d57cf3c152721f833546c4ae8 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Tue, 5 May 2020 12:55:48 -0400 Subject: [PATCH 19/90] Made mostRecentEnd negative rather than null when no timestamps can be found --- .../geolocation/AbstractWaypointFetcher.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java b/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java index 0e398b9f22..2c33d054cb 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/AbstractWaypointFetcher.java @@ -120,15 +120,13 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter // Figure out what the most recent time is given the filtered // waypoints and the tracks. timeRangeEnd = getMostRecent(waypoints, tracks); - if (timeRangeEnd != null) { - timeRangeStart = timeRangeEnd - (86400 * filters.getMostRecentNumDays()); + timeRangeStart = timeRangeEnd - (86400 * filters.getMostRecentNumDays()); - completeList.addAll(getWaypointsInRange(timeRangeStart, timeRangeEnd, waypoints)); - - filteredTracks = getTracksInRange(timeRangeStart, timeRangeEnd, tracks); - for (List filteredTrack : filteredTracks) { - completeList.addAll(filteredTrack); - } + completeList.addAll(getWaypointsInRange(timeRangeStart, timeRangeEnd, waypoints)); + + filteredTracks = getTracksInRange(timeRangeStart, timeRangeEnd, tracks); + for (List filteredTrack : filteredTracks) { + completeList.addAll(filteredTrack); } } else { completeList.addAll(waypoints); @@ -259,6 +257,6 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter return waypointMostRecent; } - return null; + return -1L; } } From aeb78fe9046916572d4357a0a834c23c59481ffe Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 5 May 2020 14:25:06 -0400 Subject: [PATCH 20/90] added reporting of no change items --- .../modules/hashdatabase/HashDbIngestModule.java | 15 +++++++++++---- .../modules/hashdatabase/KdbHashSetParser.java | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index dc8646dbe4..2f5b4f9c51 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -27,6 +27,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; import java.util.logging.Level; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; @@ -551,13 +552,14 @@ public class HashDbIngestModule implements FileIngestModule { * @param knownBadHashSets The list of hash sets for "known bad" files. * @param knownHashSets The list of hash sets for "known" files. */ + @Messages("HashDbIngestModule.complete.noChangesFound=No Change items found:") private static synchronized void postSummary(long jobId, List knownBadHashSets, List noChangeHashSets, List knownHashSets) { IngestJobTotals jobTotals = getTotalsForIngestJobs(jobId); totalsForIngestJobs.remove(jobId); - if ((!knownBadHashSets.isEmpty()) || (!knownHashSets.isEmpty())) { + if ((!knownBadHashSets.isEmpty()) || (!knownHashSets.isEmpty()) || (!noChangeHashSets.isEmpty())) { StringBuilder detailsSb = new StringBuilder(); //details detailsSb.append("
"); //NON-NLS @@ -567,6 +569,11 @@ public class HashDbIngestModule implements FileIngestModule { .append(""); //NON-NLS detailsSb.append(""); //NON-NLS + detailsSb.append(""); //NON-NLS + detailsSb.append(""); //NON-NLS + detailsSb.append("\n"); //NON-NLS @@ -578,9 +585,9 @@ public class HashDbIngestModule implements FileIngestModule { detailsSb.append("

") //NON-NLS .append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.databasesUsed")) .append("

\n
    "); //NON-NLS - for (HashDb db : knownBadHashSets) { - detailsSb.append("
  • ").append(db.getHashSetName()).append("
  • \n"); //NON-NLS - } + Stream.concat(knownBadHashSets.stream(), noChangeHashSets.stream()).forEach((db) -> { + detailsSb.append("
  • ").append(db.getHashSetName()).append("
  • \n"); //NON-NLS + }); detailsSb.append("
"); //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java index d9b29b257c..023314bab0 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java @@ -145,7 +145,7 @@ public class KdbHashSetParser implements HashSetParser { HashRow row = getNextHashRow(); try { PreparedStatement getComment = conn.prepareStatement("SELECT comment FROM comments WHERE hash_id = ?"); - getComment.setLong(0, row.getHashId()); + getComment.setLong(1, row.getHashId()); ResultSet commentResults = getComment.executeQuery(); List comments = new ArrayList<>(); while (commentResults.next()) From f838c2217fe6d49ace0428da169caa2f278c1860 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 6 May 2020 09:48:58 -0400 Subject: [PATCH 21/90] comment fixes --- .../HashDbCreateDatabaseDialog.java | 12 +- .../HashDbImportDatabaseDialog.java | 6 +- .../hashdatabase/HashDbIngestModule.java | 237 +++++----- .../modules/hashdatabase/HashDbManager.java | 406 +++++++++--------- .../HashLookupModuleSettingsPanel.java | 40 +- .../hashdatabase/HashLookupSettingsPanel.java | 9 +- .../modules/hashdatabase/HashSetParser.java | 15 +- .../ImportCentralRepoDbProgressDialog.java | 6 +- .../hashdatabase/KdbHashSetParser.java | 22 +- 9 files changed, 398 insertions(+), 355 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index 7f15bb47ac..63a8c84e93 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -488,17 +488,15 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { } KnownFilesType type; - + if (knownRadioButton.isSelected()) { - type = KnownFilesType.KNOWN; - } - else if (noChangeRadioButton.isSelected()) { + type = KnownFilesType.KNOWN; + } else if (noChangeRadioButton.isSelected()) { type = KnownFilesType.NO_CHANGE; - } - else { + } else { type = KnownFilesType.KNOWN_BAD; } - + TskData.FileKnown fileKnown = type.getFileKnown(); String errorMessage = NbBundle diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index c2716c4927..c854cb165d 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -547,11 +547,9 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { KnownFilesType type; if (knownRadioButton.isSelected()) { type = KnownFilesType.KNOWN; - } - else if (noChangeRadioButton.isSelected()) { + } else if (noChangeRadioButton.isSelected()) { type = KnownFilesType.NO_CHANGE; - } - else { + } else { type = KnownFilesType.KNOWN_BAD; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index 2f5b4f9c51..4752d80186 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -26,7 +26,6 @@ import java.util.List; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; import java.util.logging.Level; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; @@ -41,7 +40,6 @@ import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; -import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Blackboard; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -65,21 +63,20 @@ import org.sleuthkit.datamodel.TskException; "HashDbIngestModule.knownFileSearchWillNotExecuteWarn=Known file search will not be executed.", "# {0} - fileName", "HashDbIngestModule.lookingUpKnownBadHashValueErr=Error encountered while looking up notable hash value for {0}.", "# {0} - fileName", "HashDbIngestModule.lookingUpNoChangeHashValueErr=Error encountered while looking up no change hash value for {0}.", - "# {0} - fileName", "HashDbIngestModule.lookingUpKnownHashValueErr=Error encountered while looking up known hash value for {0}.", -}) + "# {0} - fileName", "HashDbIngestModule.lookingUpKnownHashValueErr=Error encountered while looking up known hash value for {0}.",}) public class HashDbIngestModule implements FileIngestModule { private static final Logger logger = Logger.getLogger(HashDbIngestModule.class.getName()); - - private final Function knownBadLookupError = - (file) -> Bundle.HashDbIngestModule_lookingUpKnownBadHashValueErr(file.getName()); - - private final Function noChangeLookupError = - (file) -> Bundle.HashDbIngestModule_lookingUpNoChangeHashValueErr(file.getName()); - - private final Function knownLookupError = - (file) -> Bundle.HashDbIngestModule_lookingUpKnownHashValueErr(file.getName()); - + + private final Function knownBadLookupError + = (file) -> Bundle.HashDbIngestModule_lookingUpKnownBadHashValueErr(file.getName()); + + private final Function noChangeLookupError + = (file) -> Bundle.HashDbIngestModule_lookingUpNoChangeHashValueErr(file.getName()); + + private final Function knownLookupError + = (file) -> Bundle.HashDbIngestModule_lookingUpKnownHashValueErr(file.getName()); + private static final int MAX_COMMENT_SIZE = 500; private final IngestServices services = IngestServices.getInstance(); private final SleuthkitCase skCase; @@ -130,11 +127,12 @@ public class HashDbIngestModule implements FileIngestModule { @Override public void startUp(org.sleuthkit.autopsy.ingest.IngestJobContext context) throws IngestModuleException { jobId = context.getJobId(); - if (!hashDbManager.verifyAllDatabasesLoadedCorrectly()) + if (!hashDbManager.verifyAllDatabasesLoadedCorrectly()) { throw new IngestModuleException("Could not load all hash sets"); + } initializeHashsets(hashDbManager.getAllHashSets()); - + if (refCounter.incrementAndGet(jobId) == 1) { // initialize job totals getTotalsForIngestJobs(jobId); @@ -157,9 +155,10 @@ public class HashDbIngestModule implements FileIngestModule { } /** - * Cycle through list of hashsets and place each HashDB in the appropriate list based on KnownFilesType. + * Cycle through list of hashsets and place each HashDB in the appropriate + * list based on KnownFilesType. * - * @param allHashSets List of all hashsets from DB manager + * @param allHashSets List of all hashsets from DB manager */ private void initializeHashsets(List allHashSets) { for (HashDb db : allHashSets) { @@ -167,7 +166,7 @@ public class HashDbIngestModule implements FileIngestModule { try { if (db.isValid()) { switch (db.getKnownFilesType()) { - case KNOWN: + case KNOWN: knownHashSets.add(db); break; case KNOWN_BAD: @@ -176,7 +175,8 @@ public class HashDbIngestModule implements FileIngestModule { case NO_CHANGE: noChangeHashSets.add(db); break; - default: throw new TskCoreException("Unknown KnownFilesType: " + db.getKnownFilesType()); + default: + throw new TskCoreException("Unknown KnownFilesType: " + db.getKnownFilesType()); } } } catch (TskCoreException ex) { @@ -200,35 +200,39 @@ public class HashDbIngestModule implements FileIngestModule { logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS return ProcessResult.ERROR; } - - if (shouldSkip(file)) + + if (shouldSkip(file)) { return ProcessResult.OK; + } // Safely get a reference to the totalsForIngestJobs object IngestJobTotals totals = getTotalsForIngestJobs(jobId); // calc hash value String md5Hash = GetHash(file, totals); - if (md5Hash == null) + if (md5Hash == null) { return ProcessResult.ERROR; + } // the processing result of handling this file ProcessResult ret = ProcessResult.OK; - + // look up in notable first - FindInHashsetsResult knownBadResult = findInHashsets(file, totals.totalKnownBadCount, - totals.totalLookuptime, knownBadHashSets, TskData.FileKnown.BAD, knownBadLookupError); - + FindInHashsetsResult knownBadResult = findInHashsets(file, totals.totalKnownBadCount, + totals.totalLookuptime, knownBadHashSets, TskData.FileKnown.BAD, knownBadLookupError); + boolean foundBad = knownBadResult.isFound(); - if (knownBadResult.isError()) + if (knownBadResult.isError()) { ret = ProcessResult.ERROR; + } // look up no change items next - FindInHashsetsResult noChangeResult = findInHashsets(file, totals.totalNoChangeCount, - totals.totalLookuptime, noChangeHashSets, TskData.FileKnown.BAD, noChangeLookupError); - - if (noChangeResult.isError()) - ret = ProcessResult.ERROR; + FindInHashsetsResult noChangeResult = findInHashsets(file, totals.totalNoChangeCount, + totals.totalLookuptime, noChangeHashSets, TskData.FileKnown.BAD, noChangeLookupError); + + if (noChangeResult.isError()) { + ret = ProcessResult.ERROR; + } // If the file is not in the notable sets, search for it in the known sets. // Any hit is sufficient to classify it as known, and there is no need to create @@ -253,16 +257,18 @@ public class HashDbIngestModule implements FileIngestModule { return ret; } - + /** * Returns true if this file should be skipped for processing. + * * @param file The file to potentially skip. + * * @return True if this file should be skipped. */ private boolean shouldSkip(AbstractFile file) { // Skip unallocated space files. if ((file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) - || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK))) { + || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK))) { return true; } @@ -272,36 +278,41 @@ public class HashDbIngestModule implements FileIngestModule { * IDX_ROOT and IDX_ALLOC artifacts. So we disable that until a solution * for it is developed. */ - if (file.isDir()) + if (file.isDir()) { return true; + } // bail out if we have no hashes set - if ((knownHashSets.isEmpty()) && (knownBadHashSets.isEmpty()) && (!settings.shouldCalculateHashes())) + if ((knownHashSets.isEmpty()) && (knownBadHashSets.isEmpty()) && (!settings.shouldCalculateHashes())) { return true; + } return false; } - /** - * Reports an error when an issue is encountered looking up a file. - * @param ex The exception thrown in the error. - * @param file The file for which this error applies. - * @param lookupErrorMessage The function that generates an error message specific to which piece of the ingest processing failed. + * Reports an error when an issue is encountered looking up a file. + * + * @param ex The exception thrown in the error. + * @param file The file for which this error applies. + * @param lookupErrorMessage The function that generates an error message + * specific to which piece of the ingest + * processing failed. */ private void reportLookupError(TskException ex, AbstractFile file, Function lookupErrorMessage) { logger.log(Level.WARNING, String.format( - "Couldn't lookup notable hash for file '%s' (id=%d) - see sleuthkit log for details", file.getName(), file.getId()), ex); //NON-NLS + "Couldn't lookup notable hash for file '%s' (id=%d) - see sleuthkit log for details", file.getName(), file.getId()), ex); //NON-NLS services.postMessage(IngestMessage.createErrorMessage( HashLookupModuleFactory.getModuleName(), NbBundle.getMessage(this.getClass(), "HashDbIngestModule.hashLookupErrorMsg", file.getName()), lookupErrorMessage.apply(file))); } - + /** * The result of attempting to find a file in a list of HashDB objects. */ private static class FindInHashsetsResult { + private final boolean found; private final boolean error; @@ -312,6 +323,7 @@ public class HashDbIngestModule implements FileIngestModule { /** * Returns true if the file was found in the HashDB. + * * @return True if the file was found in the HashDB. */ boolean isFound() { @@ -319,8 +331,11 @@ public class HashDbIngestModule implements FileIngestModule { } /** - * Returns true if there was an error in the process of finding a file in a HashDB. - * @return True if there was an error in the process of finding a file in a HashDB. + * Returns true if there was an error in the process of finding a file + * in a HashDB. + * + * @return True if there was an error in the process of finding a file + * in a HashDB. */ boolean isError() { return error; @@ -329,17 +344,25 @@ public class HashDbIngestModule implements FileIngestModule { /** * Attempts to find an abstract file in a list of HashDB objects. - * @param file The file to find. - * @param totalCount The total cound of files found in this type - * @param totalLookupTime The counter tracking the total amount of run time for this operation. - * @param hashSets The HashDB objects to cycle through looking for a hash hit. - * @param statusIfFound The FileKnown status to set on the file if the file is found in the hashSets. - * @param lookupErrorMessage The function that generates a message should there be an error in looking up the file in the hashSets. - * @return Whether or not the file was found and whether or not there was an error during the operation. + * + * @param file The file to find. + * @param totalCount The total cound of files found in this type + * @param totalLookupTime The counter tracking the total amount of run + * time for this operation. + * @param hashSets The HashDB objects to cycle through looking for + * a hash hit. + * @param statusIfFound The FileKnown status to set on the file if the + * file is found in the hashSets. + * @param lookupErrorMessage The function that generates a message should + * there be an error in looking up the file in the + * hashSets. + * + * @return Whether or not the file was found and whether or not there was an + * error during the operation. */ - private FindInHashsetsResult findInHashsets(AbstractFile file, AtomicLong totalCount, AtomicLong totalLookupTime, + private FindInHashsetsResult findInHashsets(AbstractFile file, AtomicLong totalCount, AtomicLong totalLookupTime, List hashSets, TskData.FileKnown statusIfFound, Function lookupErrorMessage) { - + boolean found = false; boolean wasError = false; for (HashDb db : hashSets) { @@ -348,13 +371,14 @@ public class HashDbIngestModule implements FileIngestModule { HashHitInfo hashInfo = db.lookupMD5(file); if (null != hashInfo) { found = true; - + totalCount.incrementAndGet(); file.setKnown(statusIfFound); String hashSetName = db.getDisplayName(); String comment = generateComment(hashInfo); - if (!createArtifactIfNotExists(hashSetName, file, comment, db)) + if (!createArtifactIfNotExists(hashSetName, file, comment, db)) { wasError = true; + } } long delta = (System.currentTimeMillis() - lookupstart); totalLookupTime.addAndGet(delta); @@ -364,13 +388,15 @@ public class HashDbIngestModule implements FileIngestModule { wasError = true; } } - + return new FindInHashsetsResult(found, wasError); } /** * Generates a formatted comment. + * * @param hashInfo The HashHitInfo. + * * @return The formatted comment. */ private String generateComment(HashHitInfo hashInfo) { @@ -392,16 +418,18 @@ public class HashDbIngestModule implements FileIngestModule { /** * Creates a BlackboardArtifact if artifact does not already exist. + * * @param hashSetName The name of the hashset found. - * @param file The file that had a hash hit. - * @param comment The comment to associate with this artifact. - * @param db the database in which this file was found. + * @param file The file that had a hash hit. + * @param comment The comment to associate with this artifact. + * @param db the database in which this file was found. + * * @return True if the operation occurred successfully and without error. */ private boolean createArtifactIfNotExists(String hashSetName, AbstractFile file, String comment, HashDb db) { /* - * We have a match. Now create an artifact if it is - * determined that one hasn't been created yet. + * We have a match. Now create an artifact if it is determined that one + * hasn't been created yet. */ List attributesList = new ArrayList<>(); attributesList.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, HashLookupModuleFactory.getModuleName(), hashSetName)); @@ -421,49 +449,52 @@ public class HashDbIngestModule implements FileIngestModule { } return true; } - + /** - * Retrieves the md5 hash for a file or generates one if no one exists on the file. - * @param file The file in order to determine the hash. + * Retrieves the md5 hash for a file or generates one if no one exists on + * the file. + * + * @param file The file in order to determine the hash. * @param totals The timing metrics for this process. - * @return The found or determined md5 hash or null if none could be determined. + * + * @return The found or determined md5 hash or null if none could be + * determined. */ private String GetHash(AbstractFile file, IngestJobTotals totals) { String md5Hash = file.getMd5Hash(); - if (md5Hash != null && md5Hash.isEmpty()) + if (md5Hash != null && md5Hash.isEmpty()) { return md5Hash; - + } + try { - TimingMetric metric = HealthMonitor.getTimingMetric("Disk Reads: Hash calculation"); - long calcstart = System.currentTimeMillis(); - md5Hash = HashUtility.calculateMd5Hash(file); - if (file.getSize() > 0) { - // Surprisingly, the hash calculation does not seem to be correlated that - // strongly with file size until the files get large. - // Only normalize if the file size is greater than ~1MB. - if (file.getSize() < 1000000) { - HealthMonitor.submitTimingMetric(metric); - } - else { - // In testing, this normalization gave reasonable resuls - HealthMonitor.submitNormalizedTimingMetric(metric, file.getSize() / 500000); - } - } - file.setMd5Hash(md5Hash); - long delta = (System.currentTimeMillis() - calcstart); - totals.totalCalctime.addAndGet(delta); - return md5Hash; - } - catch (IOException ex) { - logger.log(Level.WARNING, String.format("Error calculating hash of file '%s' (id=%d).", file.getName(), file.getId()), ex); //NON-NLS - services.postMessage(IngestMessage.createErrorMessage( - HashLookupModuleFactory.getModuleName(), - NbBundle.getMessage(this.getClass(), "HashDbIngestModule.fileReadErrorMsg", file.getName()), - NbBundle.getMessage(this.getClass(), "HashDbIngestModule.calcHashValueErr", - file.getParentPath() + file.getName(), - file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)?"Allocated File" : "Deleted File"))); - return null; - } + TimingMetric metric = HealthMonitor.getTimingMetric("Disk Reads: Hash calculation"); + long calcstart = System.currentTimeMillis(); + md5Hash = HashUtility.calculateMd5Hash(file); + if (file.getSize() > 0) { + // Surprisingly, the hash calculation does not seem to be correlated that + // strongly with file size until the files get large. + // Only normalize if the file size is greater than ~1MB. + if (file.getSize() < 1000000) { + HealthMonitor.submitTimingMetric(metric); + } else { + // In testing, this normalization gave reasonable resuls + HealthMonitor.submitNormalizedTimingMetric(metric, file.getSize() / 500000); + } + } + file.setMd5Hash(md5Hash); + long delta = (System.currentTimeMillis() - calcstart); + totals.totalCalctime.addAndGet(delta); + return md5Hash; + } catch (IOException ex) { + logger.log(Level.WARNING, String.format("Error calculating hash of file '%s' (id=%d).", file.getName(), file.getId()), ex); //NON-NLS + services.postMessage(IngestMessage.createErrorMessage( + HashLookupModuleFactory.getModuleName(), + NbBundle.getMessage(this.getClass(), "HashDbIngestModule.fileReadErrorMsg", file.getName()), + NbBundle.getMessage(this.getClass(), "HashDbIngestModule.calcHashValueErr", + file.getParentPath() + file.getName(), + file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC) ? "Allocated File" : "Deleted File"))); + return null; + } } /** @@ -553,9 +584,9 @@ public class HashDbIngestModule implements FileIngestModule { * @param knownHashSets The list of hash sets for "known" files. */ @Messages("HashDbIngestModule.complete.noChangesFound=No Change items found:") - private static synchronized void postSummary(long jobId, List knownBadHashSets, + private static synchronized void postSummary(long jobId, List knownBadHashSets, List noChangeHashSets, List knownHashSets) { - + IngestJobTotals jobTotals = getTotalsForIngestJobs(jobId); totalsForIngestJobs.remove(jobId); @@ -573,7 +604,7 @@ public class HashDbIngestModule implements FileIngestModule { .append(Bundle.HashDbIngestModule_complete_noChangesFound()) .append(""); //NON-NLS detailsSb.append(""); //NON-NLS - + detailsSb.append("\n"); //NON-NLS @@ -585,7 +616,7 @@ public class HashDbIngestModule implements FileIngestModule { detailsSb.append("

") //NON-NLS .append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.databasesUsed")) .append("

\n
    "); //NON-NLS - Stream.concat(knownBadHashSets.stream(), noChangeHashSets.stream()).forEach((db) -> { + Stream.concat(knownBadHashSets.stream(), noChangeHashSets.stream()).forEach((db) -> { detailsSb.append("
  • ").append(db.getHashSetName()).append("
  • \n"); //NON-NLS }); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index ebc31b1d4a..b9833ecafb 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,12 +23,10 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.File; import java.io.IOException; -import java.io.Serializable; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.logging.Level; @@ -106,8 +104,8 @@ public class HashDbManager implements PropertyChangeListener { public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { changeSupport.removePropertyChangeListener(listener); } - - synchronized boolean verifyAllDatabasesLoadedCorrectly(){ + + synchronized boolean verifyAllDatabasesLoadedCorrectly() { return allDatabasesLoadedCorrectly; } @@ -241,7 +239,7 @@ public class HashDbManager implements PropertyChangeListener { } return hashDb; } - + private SleuthkitHashSet addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws TskCoreException { // Wrap an object around the handle. SleuthkitHashSet hashDb = new SleuthkitHashSet(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType); @@ -276,22 +274,22 @@ public class HashDbManager implements PropertyChangeListener { } return hashDb; } - - CentralRepoHashSet addExistingCentralRepoHashSet(String hashSetName, String version, int referenceSetID, - boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType, - boolean readOnly) throws TskCoreException{ - - if(! CentralRepository.isEnabled()){ + + CentralRepoHashSet addExistingCentralRepoHashSet(String hashSetName, String version, int referenceSetID, + boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType, + boolean readOnly) throws TskCoreException { + + if (!CentralRepository.isEnabled()) { throw new TskCoreException("Could not load central repository hash set " + hashSetName + " - central repository is not enabled"); } - + CentralRepoHashSet db = new CentralRepoHashSet(hashSetName, version, referenceSetID, searchDuringIngest, - sendIngestMessages, knownFilesType, readOnly); - - if(! db.isValid()){ + sendIngestMessages, knownFilesType, readOnly); + + if (!db.isValid()) { throw new TskCoreException("Error finding hash set " + hashSetName + " in central repository"); } - + // Add the hash database to the collection hashSets.add(db); @@ -305,8 +303,8 @@ public class HashDbManager implements PropertyChangeListener { NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"), MessageNotifyUtil.MessageType.ERROR); } - return db; - + return db; + } synchronized void indexHashDatabase(SleuthkitHashSet hashDb) { @@ -344,7 +342,7 @@ public class HashDbManager implements PropertyChangeListener { this.removeHashDatabaseNoSave(hashDb); this.save(); } - + public synchronized void removeHashDatabaseNoSave(HashDb hashDb) throws HashDbManagerException { // Don't remove a database if ingest is running boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning(); @@ -360,17 +358,16 @@ public class HashDbManager implements PropertyChangeListener { hashSets.remove(hashDb); // Now undertake the operations that could throw. - // Indexing is only relevanet for sleuthkit hashsets - if(hashDb instanceof SleuthkitHashSet){ - SleuthkitHashSet hashDatabase = (SleuthkitHashSet)hashDb; + if (hashDb instanceof SleuthkitHashSet) { + SleuthkitHashSet hashDatabase = (SleuthkitHashSet) hashDb; try { - if(hashDatabase.hasIndex()){ + if (hashDatabase.hasIndex()) { hashSetPaths.remove(hashDatabase.getIndexPath()); } } catch (TskCoreException ex) { Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting index path of " + hashDatabase.getHashSetName() + " hash set when removing the hash set", ex); //NON-NLS - } + } try { if (!hashDatabase.hasIndexOnly()) { @@ -379,7 +376,7 @@ public class HashDbManager implements PropertyChangeListener { } catch (TskCoreException ex) { Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting hash set path of " + hashDatabase.getHashSetName() + " hash set when removing the hash set", ex); //NON-NLS } - + try { hashDatabase.close(); } catch (TskCoreException ex) { @@ -408,7 +405,7 @@ public class HashDbManager implements PropertyChangeListener { throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg")); } } - + /** * Gets all of the hash databases used to classify files as known or known * bad. Will add any new central repository databases to the list before @@ -417,12 +414,12 @@ public class HashDbManager implements PropertyChangeListener { * @return A list, possibly empty, of hash databases. */ public synchronized List getAllHashSets() { - try{ + try { updateHashSetsFromCentralRepository(); - } catch (TskCoreException ex){ + } catch (TskCoreException ex) { Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS } - + List hashDbs = new ArrayList<>(); hashDbs.addAll(this.hashSets); return hashDbs; @@ -435,9 +432,9 @@ public class HashDbManager implements PropertyChangeListener { */ public synchronized List getKnownFileHashSets() { List hashDbs = new ArrayList<>(); - try{ + try { updateHashSetsFromCentralRepository(); - } catch (TskCoreException ex){ + } catch (TskCoreException ex) { Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS } this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN)).forEach((db) -> { @@ -453,9 +450,9 @@ public class HashDbManager implements PropertyChangeListener { */ public synchronized List getKnownBadFileHashSets() { List hashDbs = new ArrayList<>(); - try{ + try { updateHashSetsFromCentralRepository(); - } catch (TskCoreException ex){ + } catch (TskCoreException ex) { Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS } this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN_BAD)).forEach((db) -> { @@ -475,9 +472,9 @@ public class HashDbManager implements PropertyChangeListener { private List getUpdateableHashSets(List hashDbs) { ArrayList updateableDbs = new ArrayList<>(); - try{ + try { updateHashSetsFromCentralRepository(); - } catch (TskCoreException ex){ + } catch (TskCoreException ex) { Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS } for (HashDb db : hashDbs) { @@ -491,22 +488,22 @@ public class HashDbManager implements PropertyChangeListener { } return updateableDbs; } - - private List getCentralRepoHashSetsFromDatabase(){ + + private List getCentralRepoHashSetsFromDatabase() { List crHashSets = new ArrayList<>(); - if(CentralRepository.isEnabled()){ - try{ + if (CentralRepository.isEnabled()) { + try { List crSets = CentralRepository.getInstance().getAllReferenceSets(CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID)); - for(CentralRepoFileSet globalSet:crSets){ - + for (CentralRepoFileSet globalSet : crSets) { + // Defaults for fields not stored in the central repository: // searchDuringIngest: false // sendIngestMessages: true if the hash set is notable boolean sendIngestMessages = KnownFilesType.fromFileKnown(globalSet.getFileKnownStatus()).equals(HashDb.KnownFilesType.KNOWN_BAD); crHashSets.add(new HashDbInfo(globalSet.getSetName(), globalSet.getVersion(), - globalSet.getGlobalSetID(), KnownFilesType.fromFileKnown(globalSet.getFileKnownStatus()), globalSet.isReadOnly(), false, sendIngestMessages)); - } - } catch (CentralRepoException ex){ + globalSet.getGlobalSetID(), KnownFilesType.fromFileKnown(globalSet.getFileKnownStatus()), globalSet.isReadOnly(), false, sendIngestMessages)); + } + } catch (CentralRepoException ex) { Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS } } @@ -527,9 +524,9 @@ public class HashDbManager implements PropertyChangeListener { private void closeHashDatabases(List hashDatabases) { for (HashDb database : hashDatabases) { - if(database instanceof SleuthkitHashSet){ + if (database instanceof SleuthkitHashSet) { try { - ((SleuthkitHashSet)database).close(); + ((SleuthkitHashSet) database).close(); } catch (TskCoreException ex) { Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + database.getHashSetName() + " hash set", ex); //NON-NLS } @@ -554,13 +551,13 @@ public class HashDbManager implements PropertyChangeListener { * @param settings The settings to configure. */ @Messages({"# {0} - hash set name", "HashDbManager.noDbPath.message=Couldn't get valid hash set path for: {0}", - "HashDbManager.centralRepoLoadError.message=Error loading central repository hash sets"}) + "HashDbManager.centralRepoLoadError.message=Error loading central repository hash sets"}) private void configureSettings(HashLookupSettings settings) { allDatabasesLoadedCorrectly = true; List hashDbInfoList = settings.getHashDbInfo(); for (HashDbInfo hashDbInfo : hashDbInfoList) { try { - if(hashDbInfo.isFileDatabaseType()){ + if (hashDbInfo.isFileDatabaseType()) { String dbPath = this.getValidFilePath(hashDbInfo.getHashSetName(), hashDbInfo.getPath()); if (dbPath != null) { addHashDatabase(SleuthkitJNI.openHashDatabase(dbPath), hashDbInfo.getHashSetName(), hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType()); @@ -569,10 +566,10 @@ public class HashDbManager implements PropertyChangeListener { allDatabasesLoadedCorrectly = false; } } else { - if(CentralRepository.isEnabled()){ - addExistingCentralRepoHashSet(hashDbInfo.getHashSetName(), hashDbInfo.getVersion(), - hashDbInfo.getReferenceSetID(), - hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), + if (CentralRepository.isEnabled()) { + addExistingCentralRepoHashSet(hashDbInfo.getHashSetName(), hashDbInfo.getVersion(), + hashDbInfo.getReferenceSetID(), + hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType(), hashDbInfo.isReadOnly()); } } @@ -586,13 +583,13 @@ public class HashDbManager implements PropertyChangeListener { allDatabasesLoadedCorrectly = false; } } - - if(CentralRepository.isEnabled()){ - try{ + + if (CentralRepository.isEnabled()) { + try { updateHashSetsFromCentralRepository(); - } catch (TskCoreException ex){ + } catch (TskCoreException ex) { Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error opening hash set", ex); //NON-NLS - + JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), Bundle.HashDbManager_centralRepoLoadError_message(), NbBundle.getMessage(this.getClass(), "HashDbManager.openHashDbErr"), @@ -600,14 +597,17 @@ public class HashDbManager implements PropertyChangeListener { allDatabasesLoadedCorrectly = false; } } - - /* NOTE: When RuntimeProperties.coreComponentsAreActive() is "false", - I don't think we should overwrite hash db settings file because we - were unable to load a database. The user should have to fix the issue or - remove the database from settings. Overwiting the settings effectively removes - the database from HashLookupSettings and the user may not know about this - because the dialogs are not being displayed. The next time user starts Autopsy, HashDB - will load without errors and the user may think that the problem was solved.*/ + + /* + * NOTE: When RuntimeProperties.coreComponentsAreActive() is "false", I + * don't think we should overwrite hash db settings file because we were + * unable to load a database. The user should have to fix the issue or + * remove the database from settings. Overwiting the settings + * effectively removes the database from HashLookupSettings and the user + * may not know about this because the dialogs are not being displayed. + * The next time user starts Autopsy, HashDB will load without errors + * and the user may think that the problem was solved. + */ if (!allDatabasesLoadedCorrectly && RuntimeProperties.runningWithGUI()) { try { HashLookupSettings.writeSettings(new HashLookupSettings(HashLookupSettings.convertHashSetList(this.hashSets))); @@ -618,31 +618,31 @@ public class HashDbManager implements PropertyChangeListener { } } } - + private void updateHashSetsFromCentralRepository() throws TskCoreException { - if(CentralRepository.isEnabled()){ + if (CentralRepository.isEnabled()) { List crHashDbInfoList = getCentralRepoHashSetsFromDatabase(); - for(HashDbInfo hashDbInfo : crHashDbInfoList) { - if(hashDbInfoIsNew(hashDbInfo)){ - addExistingCentralRepoHashSet(hashDbInfo.getHashSetName(), hashDbInfo.getVersion(), - hashDbInfo.getReferenceSetID(), - hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType(), - hashDbInfo.isReadOnly()); + for (HashDbInfo hashDbInfo : crHashDbInfoList) { + if (hashDbInfoIsNew(hashDbInfo)) { + addExistingCentralRepoHashSet(hashDbInfo.getHashSetName(), hashDbInfo.getVersion(), + hashDbInfo.getReferenceSetID(), + hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType(), + hashDbInfo.isReadOnly()); } } } } - - private boolean hashDbInfoIsNew(HashDbInfo dbInfo){ - for(HashDb db:this.hashSets){ - if(dbInfo.matches(db)){ + + private boolean hashDbInfoIsNew(HashDbInfo dbInfo) { + for (HashDb db : this.hashSets) { + if (dbInfo.matches(db)) { return false; } } return true; } - private String getValidFilePath(String hashSetName, String configuredPath) { + private String getValidFilePath(String hashSetName, String configuredPath) { // Check the configured path. File database = new File(configuredPath); if (database.exists()) { @@ -651,12 +651,12 @@ public class HashDbManager implements PropertyChangeListener { // Give the user an opportunity to find the desired file. String newPath = null; - if (RuntimeProperties.runningWithGUI() && - JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), - NbBundle.getMessage(this.getClass(), "HashDbManager.dlgMsg.dbNotFoundAtLoc", - hashSetName, configuredPath), - NbBundle.getMessage(this.getClass(), "HashDbManager.dlgTitle.MissingDb"), - JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { + if (RuntimeProperties.runningWithGUI() + && JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), + NbBundle.getMessage(this.getClass(), "HashDbManager.dlgMsg.dbNotFoundAtLoc", + hashSetName, configuredPath), + NbBundle.getMessage(this.getClass(), "HashDbManager.dlgTitle.MissingDb"), + JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { newPath = searchForFile(); if (null != newPath && !newPath.isEmpty()) { database = new File(newPath); @@ -688,24 +688,24 @@ public class HashDbManager implements PropertyChangeListener { } return filePath; } - + public static abstract class HashDb { - + /** * Indicates how files with hashes stored in a particular hash database * object should be classified. */ @Messages({ - "HashDbManager.noChange.text=No Change", - "HashDbManager.known.text=Known", - "HashDbManager.knownBad.text=Notable" + "HashDbManager.noChange.text=No Change", + "HashDbManager.known.text=Known", + "HashDbManager.knownBad.text=Notable" }) public enum KnownFilesType { KNOWN(Bundle.HashDbManager_known_text(), TskData.FileKnown.KNOWN, false, false), KNOWN_BAD(Bundle.HashDbManager_knownBad_text(), TskData.FileKnown.BAD, true, true), - NO_CHANGE(Bundle.HashDbManager_noChange_text(), TskData.FileKnown.UNKNOWN, true , false); - + NO_CHANGE(Bundle.HashDbManager_noChange_text(), TskData.FileKnown.UNKNOWN, true, false); + private final String displayName; private final TskData.FileKnown fileKnown; private final boolean allowSendInboxMessages; @@ -719,47 +719,57 @@ public class HashDbManager implements PropertyChangeListener { } /** - * Returns whether or not it is allowable to send inbox messages with this known files type. - * @return Whether or not it is allowable to send inbox messages with this known files type. + * Returns whether or not it is allowable to send inbox messages + * with this known files type. + * + * @return Whether or not it is allowable to send inbox messages + * with this known files type. */ boolean isInboxMessagesAllowed() { return allowSendInboxMessages; } /** - * Returns whether or not by default for this type is to send inbox messages. - * @return Whether or not by default for this type is to send inbox messages. + * Returns whether or not by default for this type is to send inbox + * messages. + * + * @return Whether or not by default for this type is to send inbox + * messages. */ boolean isDefaultInboxMessages() { return defaultSendInboxMessages; } - - + public String getDisplayName() { return this.displayName; } - + /** - * Retrieves the corresponding TskData.FileKnown enum type that relates to this. - * @return The corresponding TskData.FileKnown. + * Retrieves the corresponding TskData.FileKnown enum type that + * relates to this. + * + * @return The corresponding TskData.FileKnown. */ TskData.FileKnown getFileKnown() { return this.fileKnown; } - + /** * Converts a TskData.FileKnown to the corresponding KnownFilesType. - * @param fileKnown The TskData.FileKnown type. - * @return The corresponding KnownFilesType. + * + * @param fileKnown The TskData.FileKnown type. + * + * @return The corresponding KnownFilesType. */ static KnownFilesType fromFileKnown(TskData.FileKnown fileKnown) { - if (fileKnown == null) + if (fileKnown == null) { return null; - + } + return Stream.of(KnownFilesType.values()) - .filter((type) -> type.getFileKnown() == fileKnown) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Unknown TskData.FileKnown type: " + fileKnown)); + .filter((type) -> type.getFileKnown() == fileKnown) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Unknown TskData.FileKnown type: " + fileKnown)); } } @@ -770,9 +780,9 @@ public class HashDbManager implements PropertyChangeListener { INDEXING_DONE } - + public abstract String getHashSetName(); - + abstract String getDisplayName(); public abstract String getDatabasePath() throws TskCoreException; @@ -780,7 +790,7 @@ public class HashDbManager implements PropertyChangeListener { public abstract HashDb.KnownFilesType getKnownFilesType(); public abstract boolean getSearchDuringIngest(); - + abstract void setSearchDuringIngest(boolean useForIngest); public abstract boolean getSendIngestMessages(); @@ -813,28 +823,30 @@ public class HashDbManager implements PropertyChangeListener { public abstract boolean lookupMD5Quick(Content content) throws TskCoreException; public abstract HashHitInfo lookupMD5(Content content) throws TskCoreException; - + /** - * Returns whether this database can be enabled. - * For file type, this is the same as checking that it has an index + * Returns whether this database can be enabled. For file type, this is + * the same as checking that it has an index + * * @return true if is valid, false otherwise - * @throws TskCoreException + * + * @throws TskCoreException */ abstract boolean isValid() throws TskCoreException; - + public abstract String getIndexPath() throws TskCoreException; - + public abstract boolean hasIndexOnly() throws TskCoreException; - + public abstract void firePropertyChange(String propertyName, Object oldValue, Object newValue); - + public abstract void addPropertyChangeListener(PropertyChangeListener pcl); - + public abstract void removePropertyChangeListener(PropertyChangeListener pcl); - + @Override public abstract String toString(); - + } /** @@ -842,13 +854,13 @@ public class HashDbManager implements PropertyChangeListener { * as known or know bad. */ class SleuthkitHashSet extends HashDb { - + private static final long serialVersionUID = 1L; private final int handle; private final String hashSetName; private boolean searchDuringIngest; private boolean sendIngestMessages; - private final HashDb.KnownFilesType knownFilesType; + private final HashDb.KnownFilesType knownFilesType; private boolean indexing; private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); @@ -862,8 +874,8 @@ public class HashDbManager implements PropertyChangeListener { } /** - * Adds a listener for the events defined in HashDb.Event. - * Listeners are used during indexing. + * Adds a listener for the events defined in HashDb.Event. Listeners are + * used during indexing. * * @param pcl */ @@ -881,8 +893,8 @@ public class HashDbManager implements PropertyChangeListener { public void removePropertyChangeListener(PropertyChangeListener pcl) { propertyChangeSupport.removePropertyChangeListener(pcl); } - - int getHandle(){ + + int getHandle() { return handle; } @@ -890,9 +902,9 @@ public class HashDbManager implements PropertyChangeListener { public String getHashSetName() { return hashSetName; } - + @Override - String getDisplayName(){ + String getDisplayName() { return getHashSetName(); } @@ -900,9 +912,9 @@ public class HashDbManager implements PropertyChangeListener { public String getDatabasePath() throws TskCoreException { return SleuthkitJNI.getHashDatabasePath(handle); } - - public void setIndexing(boolean indexing){ - this.indexing = indexing; + + public void setIndexing(boolean indexing) { + this.indexing = indexing; } @Override @@ -1038,12 +1050,14 @@ public class HashDbManager implements PropertyChangeListener { } return result; } - + /** - * Returns whether this database can be enabled. - * For file type, this is the same as checking that it has an index + * Returns whether this database can be enabled. For file type, this is + * the same as checking that it has an index + * * @return true if is valid, false otherwise - * @throws TskCoreException + * + * @throws TskCoreException */ @Override boolean isValid() throws TskCoreException { @@ -1066,21 +1080,20 @@ public class HashDbManager implements PropertyChangeListener { boolean isIndexing() { return indexing; } - + @Override - public void firePropertyChange(String propertyName, Object oldValue, Object newValue){ + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); } private void close() throws TskCoreException { SleuthkitJNI.closeHashDatabase(handle); } - + @Override - public String toString(){ + public String toString() { return getHashSetName(); } - @Override public int hashCode() { @@ -1115,13 +1128,13 @@ public class HashDbManager implements PropertyChangeListener { * Instances of this class represent hash databases used to classify files * as known or know bad. */ - class CentralRepoHashSet extends HashDb{ + class CentralRepoHashSet extends HashDb { private static final long serialVersionUID = 1L; private final String hashSetName; private boolean searchDuringIngest; private boolean sendIngestMessages; - private final HashDb.KnownFilesType knownFilesType; + private final HashDb.KnownFilesType knownFilesType; private final int referenceSetID; private final String version; private String orgName; @@ -1129,10 +1142,10 @@ public class HashDbManager implements PropertyChangeListener { private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); @Messages({"HashDbManager.CentralRepoHashDb.orgError=Error loading organization"}) - private CentralRepoHashSet(String hashSetName, String version, int referenceSetID, - boolean useForIngest, boolean sendHitMessages, HashDb.KnownFilesType knownFilesType, + private CentralRepoHashSet(String hashSetName, String version, int referenceSetID, + boolean useForIngest, boolean sendHitMessages, HashDb.KnownFilesType knownFilesType, boolean readOnly) - throws TskCoreException{ + throws TskCoreException { this.hashSetName = hashSetName; this.version = version; this.referenceSetID = referenceSetID; @@ -1140,18 +1153,18 @@ public class HashDbManager implements PropertyChangeListener { this.sendIngestMessages = sendHitMessages; this.knownFilesType = knownFilesType; this.readOnly = readOnly; - - try{ + + try { orgName = CentralRepository.getInstance().getReferenceSetOrganization(referenceSetID).getName(); - } catch (CentralRepoException ex){ + } catch (CentralRepoException ex) { Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error looking up central repository organization for reference set " + referenceSetID, ex); //NON-NLS orgName = Bundle.HashDbManager_CentralRepoHashDb_orgError(); } } /** - * Adds a listener for the events defined in HashDb.Event. - * Listeners are used during indexing. + * Adds a listener for the events defined in HashDb.Event. Listeners are + * used during indexing. * * @param pcl */ @@ -1169,9 +1182,9 @@ public class HashDbManager implements PropertyChangeListener { public void removePropertyChangeListener(PropertyChangeListener pcl) { propertyChangeSupport.removePropertyChangeListener(pcl); } - + @Override - public boolean hasIndexOnly() throws TskCoreException{ + public boolean hasIndexOnly() throws TskCoreException { return true; } @@ -1179,25 +1192,25 @@ public class HashDbManager implements PropertyChangeListener { public String getHashSetName() { return hashSetName; } - + @Override - public String getDisplayName(){ - if(! getVersion().isEmpty()){ + public String getDisplayName() { + if (!getVersion().isEmpty()) { return getHashSetName() + " " + getVersion() + " (remote)"; } else { return getHashSetName() + " (remote)"; } } - - String getVersion(){ + + String getVersion() { return version; } - - String getOrgName(){ + + String getOrgName() { return orgName; } - - int getReferenceSetID(){ + + int getReferenceSetID() { return referenceSetID; } @@ -1245,7 +1258,7 @@ public class HashDbManager implements PropertyChangeListener { */ @Override public boolean isUpdateable() throws TskCoreException { - return (! readOnly); + return (!readOnly); } /** @@ -1279,12 +1292,12 @@ public class HashDbManager implements PropertyChangeListener { AbstractFile file = (AbstractFile) content; if (null != file.getMd5Hash()) { TskData.FileKnown type = knownFilesType.getFileKnown(); - - try{ + + try { CentralRepoFileInstance fileInstance = new CentralRepoFileInstance(referenceSetID, file.getMd5Hash(), - type, comment); - CentralRepository.getInstance().addReferenceInstance(fileInstance,CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID)); - } catch (CentralRepoException | CorrelationAttributeNormalizationException ex){ + type, comment); + CentralRepository.getInstance().addReferenceInstance(fileInstance, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID)); + } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) { throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex); //NON-NLS } } @@ -1301,20 +1314,20 @@ public class HashDbManager implements PropertyChangeListener { @Override public void addHashes(List hashes) throws TskCoreException { Set globalFileInstances = new HashSet<>(); - for(HashEntry hashEntry:hashes){ + for (HashEntry hashEntry : hashes) { TskData.FileKnown type = knownFilesType.getFileKnown(); - + try { globalFileInstances.add(new CentralRepoFileInstance(referenceSetID, hashEntry.getMd5Hash(), type, hashEntry.getComment())); - } catch (CentralRepoException | CorrelationAttributeNormalizationException ex){ + } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) { throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex); } } - - try{ - CentralRepository.getInstance().bulkInsertReferenceTypeEntries(globalFileInstances, + + try { + CentralRepository.getInstance().bulkInsertReferenceTypeEntries(globalFileInstances, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID)); - } catch (CentralRepoException ex){ + } catch (CentralRepoException ex) { throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex); } } @@ -1335,9 +1348,9 @@ public class HashDbManager implements PropertyChangeListener { if (content instanceof AbstractFile) { AbstractFile file = (AbstractFile) content; if (null != file.getMd5Hash()) { - try{ + try { return CentralRepository.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID); - } catch (CentralRepoException | CorrelationAttributeNormalizationException ex){ + } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) { Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash " + file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS throw new TskCoreException("Error performing central reposiotry hash lookup", ex); @@ -1364,12 +1377,12 @@ public class HashDbManager implements PropertyChangeListener { if (content instanceof AbstractFile) { AbstractFile file = (AbstractFile) content; if (null != file.getMd5Hash()) { - try{ - if(CentralRepository.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID)){ + try { + if (CentralRepository.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID)) { // Make a bare-bones HashHitInfo for now result = new HashHitInfo(file.getMd5Hash(), "", ""); } - } catch (CentralRepoException | CorrelationAttributeNormalizationException ex){ + } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) { Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash " + file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS throw new TskCoreException("Error performing central reposiotry hash lookup", ex); @@ -1378,35 +1391,34 @@ public class HashDbManager implements PropertyChangeListener { } return result; } - + /** * Returns whether this database can be enabled. - * + * * @return true if is valid, false otherwise */ @Override boolean isValid() { - if(! CentralRepository.isEnabled()) { + if (!CentralRepository.isEnabled()) { return false; } - try{ + try { return CentralRepository.getInstance().referenceSetIsValid(this.referenceSetID, this.hashSetName, this.version); - } catch (CentralRepoException ex){ + } catch (CentralRepoException ex) { Logger.getLogger(CentralRepoHashSet.class.getName()).log(Level.SEVERE, "Error validating hash set " + hashSetName, ex); //NON-NLS return false; } } - + @Override - public void firePropertyChange(String propertyName, Object oldValue, Object newValue){ + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); } - + @Override - public String toString(){ + public String toString() { return getDisplayName(); } - @Override public int hashCode() { @@ -1438,8 +1450,8 @@ public class HashDbManager implements PropertyChangeListener { } return true; } - } - + } + /** * Worker thread to make an index of a database */ diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java index 55959db35c..e804e0bea7 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettingsPanel.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -34,7 +34,6 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; - /** * Ingest job settings panel for hash lookup file ingest modules. */ @@ -117,14 +116,14 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe hashSetsTableModel.fireTableDataChanged(); } - private List validSetsOnly(List hashDbs){ + private List validSetsOnly(List hashDbs) { List validDbs = new ArrayList<>(); - for(HashDb db:hashDbs){ - try{ - if(db.isValid()){ + for (HashDb db : hashDbs) { + try { + if (db.isValid()) { validDbs.add(db); } - } catch (TskCoreException ex){ + } catch (TskCoreException ex) { Logger.getLogger(HashLookupModuleSettingsPanel.class.getName()).log(Level.SEVERE, "Error checking validity for hash set (name = " + db.getHashSetName() + ")", ex); //NON-NLS } } @@ -133,22 +132,22 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe void updateHashSetModels() { List hashDbs = validSetsOnly(hashDbManager.getAllHashSets()); - + List hashDatabases = new ArrayList<>(hashDbs); - + // Update the hash sets and detect deletions. List deletedHashSetModels = new ArrayList<>(); for (HashSetModel model : hashSetModels) { boolean foundDatabase = false; - for(HashDb db : hashDatabases){ - if(model.getDatabase().equals(db)){ + for (HashDb db : hashDatabases) { + if (model.getDatabase().equals(db)) { model.setValid(isHashDbValid(db)); hashDatabases.remove(db); foundDatabase = true; break; } } - if(! foundDatabase){ + if (!foundDatabase) { deletedHashSetModels.add(model); } } @@ -191,8 +190,8 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe this.enabled = enabled; this.valid = valid; } - - HashDb getDatabase(){ + + HashDb getDatabase() { return db; } @@ -202,13 +201,14 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe String getFormattedName() { String knownTypeName = (db != null && db.getKnownFilesType() != null) ? db.getKnownFilesType().getDisplayName() : ""; - if (!StringUtils.isBlank(knownTypeName)) + if (!StringUtils.isBlank(knownTypeName)) { knownTypeName = String.format(" (%s)", knownTypeName); - + } + String displayName = db != null ? db.getDisplayName() : ""; return displayName + knownTypeName; } - + void setEnabled(boolean enabled) { this.enabled = enabled; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index 0f9f99d79b..fade3e47c5 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -49,7 +49,6 @@ import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.SleuthkitHashSet; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashSet; -import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.SetEvt; @@ -95,16 +94,16 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan } } }); - + HashDbManager.getInstance().addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { String propName = evt.getPropertyName(); - if(propName.equals(SetEvt.DB_ADDED.toString()) || - propName.equals(SetEvt.DB_DELETED.toString())) { + if (propName.equals(SetEvt.DB_ADDED.toString()) + || propName.equals(SetEvt.DB_DELETED.toString())) { hashSetTableModel.refreshModel(); } - } + } }); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java index e4b5d55632..85d28231a9 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java @@ -27,7 +27,8 @@ interface HashSetParser { * Get the next hash to import * * @return The hash as a string, or null if the end of file was reached - * without error + * without error + * * @throws TskCoreException */ String getNextHash() throws TskCoreException; @@ -51,18 +52,20 @@ interface HashSetParser { * Closes the import file */ void close(); - + /** * Get the next hash to import as a HashEntry object. - * + * * @return A new hash entry for the next item parsed. - * @throws TskCoreException + * + * @throws TskCoreException */ default HashEntry getNextHashEntry() throws TskCoreException { String next = getNextHash(); - if (next == null) + if (next == null) { return null; - + } + return new HashEntry(null, next, null, null, null); } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 030a38cb35..d868b39189 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -187,7 +187,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P * Get the newly created database * * @return the imported database. May be null if an error occurred or - * the user canceled + * the user canceled */ synchronized HashDbManager.CentralRepoHashSet getDatabase() { return newHashDb; @@ -206,7 +206,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P * Check if the import was successful or if there was an error. * * @return true if the import process completed without error, false - * otherwise + * otherwise */ boolean getImportSuccess() { return importSuccess.get(); @@ -236,7 +236,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P // Create an empty hashset in the central repository CentralRepository dbManager = CentralRepository.getInstance(); - referenceSetID.set(dbManager.newReferenceSet(new CentralRepoFileSet(orgId, hashSetName, version, knownStatus, + referenceSetID.set(dbManager.newReferenceSet(new CentralRepoFileSet(orgId, hashSetName, version, knownStatus, readOnly, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID)))); // Get the "FILES" content type. This is a database lookup so we diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java index 023314bab0..fd79636757 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java @@ -80,8 +80,9 @@ public class KdbHashSetParser implements HashSetParser { } } - + private static class HashRow { + private final String md5Hash; private final long hashId; @@ -98,11 +99,13 @@ public class KdbHashSetParser implements HashSetParser { return hashId; } } - + /** * Retrieves the row id and md5 hash for the next item in the hashes table. + * * @return A hash row object containing the hash and id. - * @throws TskCoreException + * + * @throws TskCoreException */ private HashRow getNextHashRow() throws TskCoreException { try { @@ -117,10 +120,10 @@ public class KdbHashSetParser implements HashSetParser { if (sb.toString().length() != 32) { throw new TskCoreException("Hash has incorrect length: " + sb.toString()); } - + String md5Hash = sb.toString(); totalHashesRead++; - return new HashRow(md5Hash, hashId); + return new HashRow(md5Hash, hashId); } else { throw new TskCoreException("Could not read expected number of hashes from hash set " + filename); } @@ -133,6 +136,7 @@ public class KdbHashSetParser implements HashSetParser { * Get the next hash to import * * @return The hash as a string + * * @throws TskCoreException */ @Override @@ -148,18 +152,16 @@ public class KdbHashSetParser implements HashSetParser { getComment.setLong(1, row.getHashId()); ResultSet commentResults = getComment.executeQuery(); List comments = new ArrayList<>(); - while (commentResults.next()) + while (commentResults.next()) { comments.add(commentResults.getString("comment")); + } String comment = comments.size() > 0 ? String.join(" ", comments) : null; return new HashEntry(null, row.getMd5Hash(), null, null, comment); - } - catch (SQLException ex) { + } catch (SQLException ex) { throw new TskCoreException("Error opening/reading hash set " + filename, ex); } } - - /** * Check if there are more hashes to read From 3b054c9a7b9fea2b4246de8097caf5e8f8a2d462 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 6 May 2020 12:11:16 -0400 Subject: [PATCH 22/90] bug fixes --- .../datamodel/CentralRepository.java | 17 ++++++++ .../datamodel/RdbmsCentralRepo.java | 40 +++++++++++++++++++ .../hashdatabase/Bundle.properties-MERGED | 37 +++++++++++------ .../hashdatabase/HashDbIngestModule.java | 13 +++++- .../modules/hashdatabase/HashDbManager.java | 5 +-- 5 files changed, 93 insertions(+), 19 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java index 6a4a138cfb..945e279123 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java @@ -25,6 +25,7 @@ import org.sleuthkit.datamodel.TskData; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount.CentralRepoAccountType; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; +import org.sleuthkit.datamodel.HashHitInfo; /** * Main interface for interacting with the database @@ -541,6 +542,22 @@ public interface CentralRepository { */ public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws CentralRepoException, CorrelationAttributeNormalizationException; + + /** + * Retrieves the given file HashHitInfo if the given file hash is in this + * reference set. Only searches the reference_files table. + * + * @param hash The hash to find in a search. + * @param referenceSetID The referenceSetID within which the file should exist. + * + * @return The HashHitInfo if found or null if not found. + * + * @throws CentralRepoException + * @throws CorrelationAttributeNormalizationException + */ + public HashHitInfo getFileHashInReferenceSet(String hash, int referenceSetID) throws CentralRepoException, CorrelationAttributeNormalizationException; + + /** * Check if the given value is in a specific reference set * diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java index 24d02ae2c2..a8b65da9d6 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java @@ -51,6 +51,7 @@ import org.sleuthkit.autopsy.healthmonitor.HealthMonitor; import org.sleuthkit.autopsy.healthmonitor.TimingMetric; import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.CaseDbSchemaVersionNumber; +import org.sleuthkit.datamodel.HashHitInfo; import org.sleuthkit.datamodel.TskData; /** @@ -2277,6 +2278,45 @@ abstract class RdbmsCentralRepo implements CentralRepository { return isValueInReferenceSet(hash, referenceSetID, CorrelationAttributeInstance.FILES_TYPE_ID); } + @Override + public HashHitInfo getFileHashInReferenceSet(String hash, int referenceSetID) throws CentralRepoException, CorrelationAttributeNormalizationException { + int correlationTypeID = CorrelationAttributeInstance.FILES_TYPE_ID; + String normalizeValued = CorrelationAttributeNormalizer.normalize(this.getCorrelationTypeById(correlationTypeID), hash); + + Connection conn = connect(); + + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + String sql = "SELECT value,comment FROM %s WHERE value=? AND reference_set_id=?"; + + String fileTableName = CentralRepoDbUtil.correlationTypeToReferenceTableName(getCorrelationTypeById(correlationTypeID)); + + try { + preparedStatement = conn.prepareStatement(String.format(sql, fileTableName)); + preparedStatement.setString(1, normalizeValued); + preparedStatement.setInt(2, referenceSetID); + resultSet = preparedStatement.executeQuery(); + if (resultSet.next()) { + String comment = resultSet.getString("comment"); + String hashFound = resultSet.getString("value"); + HashHitInfo found = new HashHitInfo(hashFound, "", ""); + found.addComment(comment); + return found; + } + else { + return null; + } + } catch (SQLException ex) { + throw new CentralRepoException("Error determining if value (" + normalizeValued + ") is in reference set " + referenceSetID, ex); // NON-NLS + } finally { + CentralRepoDbUtil.closeStatement(preparedStatement); + CentralRepoDbUtil.closeResultSet(resultSet); + CentralRepoDbUtil.closeConnection(conn); + } + } + + + /** * Check if the given value is in a specific reference set * diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED index 44e551c028..853a23d0db 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED @@ -9,6 +9,7 @@ HashDbImportDatabaseDialog.missingOrg=An organization must be selected HashDbImportDatabaseDialog.missingVersion=A version must be entered HashDbImportDatabaseDialog.mustEnterHashSetNameMsg=A hash set name must be entered. HashDbImportDatabaseDialog.populateOrgsError.message=Failure loading organizations. +HashDbIngestModule.complete.noChangesFound=No Change items found: # {0} - File name HashDbIngestModule.dialogTitle.errorFindingArtifacts=Error Finding Artifacts: {0} # {0} - File name @@ -16,10 +17,21 @@ HashDbIngestModule.errorMessage.lookingForFileArtifacts=Error encountered while HashDbIngestModule.indexError.message=Failed to index hashset hit artifact for keyword search. HashDbIngestModule.knownBadFileSearchWillNotExecuteWarn=Notable file search will not be executed. HashDbIngestModule.knownFileSearchWillNotExecuteWarn=Known file search will not be executed. +# {0} - fileName +HashDbIngestModule.lookingUpKnownBadHashValueErr=Error encountered while looking up notable hash value for {0}. +# {0} - fileName +HashDbIngestModule.lookingUpKnownHashValueErr=Error encountered while looking up known hash value for {0}. +# {0} - fileName +HashDbIngestModule.lookingUpNoChangeHashValueErr=Error encountered while looking up no change hash value for {0}. +HashDbIngestModule.noChangeFileSearchWillNotExecuteWarn='No Change' file search will not be executed. +HashDbIngestModule.noChangeHashDbSetMsg=No 'No Change' hash set. HashDbIngestModule.noKnownBadHashDbSetMsg=No notable hash set. HashDbIngestModule.noKnownHashDbSetMsg=No known hash set. HashDbManager.CentralRepoHashDb.orgError=Error loading organization HashDbManager.centralRepoLoadError.message=Error loading central repository hash sets +HashDbManager.known.text=Known +HashDbManager.knownBad.text=Notable +HashDbManager.noChange.text=No Change # {0} - hash set name HashDbManager.noDbPath.message=Couldn't get valid hash set path for: {0} HashDbSearchAction.noOpenCase.errMsg=No open case available. @@ -49,7 +61,10 @@ ImportCentralRepoDbProgressDialog.errorParsingFile.message=Error parsing hash se ImportCentralRepoDbProgressDialog.linesProcessed.message=\ hashes processed ImportCentralRepoDbProgressDialog.title.text=Central Repository Import Progress OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Hash Set ingest module. \n\nThe ingest module analyzes files in the disk image and marks them as "known" (based on NSRL hashset lookup for "known" files) and "bad / interesting" (based on one or more hash sets supplied by the user).\n\nThe module also contains additional non-ingest tools that are integrated in the GUI, such as file lookup by hash and hash set configuration. +OpenIDE-Module-Long-Description=\ + Hash Set ingest module. \n\n\ + The ingest module analyzes files in the disk image and marks them as "known" (based on NSRL hashset lookup for "known" files) and "bad / interesting" (based on one or more hash sets supplied by the user).\n\n\ + The module also contains additional non-ingest tools that are integrated in the GUI, such as file lookup by hash and hash set configuration. OpenIDE-Module-Name=HashDatabases OptionsCategory_Name_HashDatabase=Hash Sets OptionsCategory_Keywords_HashDatabase=Hash Sets @@ -141,8 +156,6 @@ HashDbIngestModule.fileReadErrorMsg=Read Error: {0} HashDbIngestModule.calcHashValueErr=Error encountered while calculating the hash value for {0} ({1}). HashDbIngestModule.hashLookupErrorMsg=Hash Lookup Error: {0} HashDbIngestModule.settingKnownBadStateErr=Error encountered while setting notable state for {0}. -HashDbIngestModule.lookingUpKnownBadHashValueErr=Error encountered while looking up notable hash value for {0}. -HashDbIngestModule.lookingUpKnownHashValueErr=Error encountered while looking up known hash value for {0}. HashDbIngestModule.postToBB.fileName=File Name HashDbIngestModule.postToBB.md5Hash=MD5 Hash HashDbIngestModule.postToBB.hashsetName=Hash Set Name @@ -178,7 +191,10 @@ HashDbSearchThread.name.searching=Searching HashDbSearchThread.noMoreFilesWithMD5Msg=No other files with the same MD5 hash were found. ModalNoButtons.indexingDbsTitle=Indexing hash sets ModalNoButtons.indexingDbTitle=Indexing hash set -ModalNoButtons.exitHashDbIndexingMsg=You are about to exit out of indexing your hash sets. \nThe generated index will be left unusable. If you choose to continue,\nplease delete the corresponding -md5.idx file in the hash folder.\nExit indexing? +ModalNoButtons.exitHashDbIndexingMsg=You are about to exit out of indexing your hash sets. \n\ +The generated index will be left unusable. If you choose to continue,\n\ + please delete the corresponding -md5.idx file in the hash folder.\n\ + Exit indexing? ModalNoButtons.dlgTitle.unfinishedIndexing=Unfinished Indexing ModalNoButtons.indexThis.currentlyIndexing1Db=Currently indexing 1 hash set ModalNoButtons.indexThese.currentlyIndexing1OfNDbs=Currently indexing 1 of {0} @@ -189,9 +205,6 @@ HashDbManager.hashDbFileExistsExceptionMsg=A file already exists at\n{0} HashDbManager.hashDbAlreadyAddedExceptionMsg=The hash set at\n{0}\nhas already been created or imported. HashDbManager.illegalHashDbFileNameExtensionMsg=The hash set file name must have a .{0} extension. HashDbManager.moduleErr=Module Error -HashDbManager.knownBad.text=Notable -HashDbManager.noChange.text=No Change -HashDbManager.known.text=Known HashDbManager.fileNameExtensionFilter.title=Hash Set File HashDbSearchAction.dlgMsg.title=File Search by MD5 Hash HashDbSearchAction.getName.text=Hash Search @@ -206,13 +219,7 @@ AddContentToHashDbAction.singleSelectionNameEmpty=Add File to Hash Set (Empty Fi AddContentToHashDbAction.multipleSelectionNameEmpty=Add Files to Hash Set (Empty File) HashDbManager.ingestRunningExceptionMsg=Ingest is ongoing; this service will be unavailable until it finishes. HashDbManager.saveErrorExceptionMsg=Error saving hash configuration -HashLookupSettingsPanel.jButton3.text=Import Hash Set -HashLookupSettingsPanel.jLabel6.text=Type: -HashLookupSettingsPanel.jLabel4.text=Location: -HashLookupSettingsPanel.jLabel2.text=Name: HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text=Calculate MD5 even if no hash set is selected -HashLookupModuleSettingsPanel.knownHashDbsLabel.text=Select known hash sets to use: -HashLookupModuleSettingsPanel.knownBadHashDbsLabel.text=Select notable hash sets to use: AddContentToHashDbAction.addFilesToHashSet.files=files AddContentToHashDbAction.addFilesToHashSet.file=file HashDbManager.errCreatingIndex.title=Error creating index @@ -290,3 +297,7 @@ AddHashValuesToDatabaseDialog.okButton.text_2=OK HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.text=Copy hash set into user configuration folder HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.toolTipText=In Live Triage situations, this option ensures that path to the hash set will be valid HashLookupSettingsPanel.indexPathLabel.text= +HashLookupModuleSettingsPanel.hashDbsLabel.text=Select hash sets to use: +HashDbCreateDatabaseDialog.noChangeRadioButton.text=No Change +HashDbImportDatabaseDialog.noChangeRadioButton.toolTipText= +HashDbImportDatabaseDialog.noChangeRadioButton.text=No Change diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index 4752d80186..352a89ab55 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -59,6 +59,8 @@ import org.sleuthkit.datamodel.TskException; @Messages({ "HashDbIngestModule.noKnownBadHashDbSetMsg=No notable hash set.", "HashDbIngestModule.knownBadFileSearchWillNotExecuteWarn=Notable file search will not be executed.", + "HashDbIngestModule.noChangeHashDbSetMsg=No 'No Change' hash set.", + "HashDbIngestModule.noChangeFileSearchWillNotExecuteWarn='No Change' file search will not be executed.", "HashDbIngestModule.noKnownHashDbSetMsg=No known hash set.", "HashDbIngestModule.knownFileSearchWillNotExecuteWarn=Known file search will not be executed.", "# {0} - fileName", "HashDbIngestModule.lookingUpKnownBadHashValueErr=Error encountered while looking up notable hash value for {0}.", @@ -144,6 +146,13 @@ public class HashDbIngestModule implements FileIngestModule { Bundle.HashDbIngestModule_noKnownBadHashDbSetMsg(), Bundle.HashDbIngestModule_knownBadFileSearchWillNotExecuteWarn())); } + + if (noChangeHashSets.isEmpty()) { + services.postMessage(IngestMessage.createWarningMessage( + HashLookupModuleFactory.getModuleName(), + Bundle.HashDbIngestModule_noChangeHashDbSetMsg(), + Bundle.HashDbIngestModule_noChangeFileSearchWillNotExecuteWarn())); + } if (knownHashSets.isEmpty()) { services.postMessage(IngestMessage.createWarningMessage( @@ -209,7 +218,7 @@ public class HashDbIngestModule implements FileIngestModule { IngestJobTotals totals = getTotalsForIngestJobs(jobId); // calc hash value - String md5Hash = GetHash(file, totals); + String md5Hash = getHash(file, totals); if (md5Hash == null) { return ProcessResult.ERROR; } @@ -460,7 +469,7 @@ public class HashDbIngestModule implements FileIngestModule { * @return The found or determined md5 hash or null if none could be * determined. */ - private String GetHash(AbstractFile file, IngestJobTotals totals) { + private String getHash(AbstractFile file, IngestJobTotals totals) { String md5Hash = file.getMd5Hash(); if (md5Hash != null && md5Hash.isEmpty()) { return md5Hash; diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index b9833ecafb..ee48978295 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -1378,10 +1378,7 @@ public class HashDbManager implements PropertyChangeListener { AbstractFile file = (AbstractFile) content; if (null != file.getMd5Hash()) { try { - if (CentralRepository.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID)) { - // Make a bare-bones HashHitInfo for now - result = new HashHitInfo(file.getMd5Hash(), "", ""); - } + return CentralRepository.getInstance().getFileHashInReferenceSet(file.getMd5Hash(), referenceSetID); } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) { Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash " + file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS From 57a22dee94cc69b9c90ae504f95c75ca49b619fe Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Wed, 6 May 2020 13:25:58 -0400 Subject: [PATCH 23/90] 6323: Changing copyright year range --- Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java | 2 +- .../src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java b/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java index c4ca19bb4f..d9e52349df 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java +++ b/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014-2020 Basis Technology Corp. + * Copyright 2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java index 44ea5fb534..a88d66faa0 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014-2020 Basis Technology Corp. + * Copyright 2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); From 984507f2ecc2eed4af50e4d92401d513ff5a3507 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 6 May 2020 14:27:48 -0400 Subject: [PATCH 24/90] annotations viewer update for tsk hash hit --- .../AnnotationsContentViewer.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index c5c92b11c0..22a8bfe08b 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -22,11 +22,13 @@ import java.awt.Component; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringEscapeUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.openide.nodes.Node; +import org.openide.util.Exceptions; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -46,6 +48,8 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; /** * Annotations view of file contents. @@ -109,12 +113,86 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data if (sourceFile instanceof AbstractFile) { populateCentralRepositoryData(html, artifact, (AbstractFile) sourceFile); + populateHashHitData(html, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT); + populateHashHitData(html, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); } setText(html.toString()); jTextPane1.setCaretPosition(0); } + private void populateHashHitData(StringBuilder html, Content content, BlackboardArtifact.ARTIFACT_TYPE artifactType) { + String artifactTypeName = artifactType.getDisplayName(); + + try { + SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + + startSection(html, artifactTypeName); + List fileHitInfo = tskCase.getBlackboardArtifacts(artifactType, content.getId()); + if (fileHitInfo.isEmpty()) { + addMessage(html, String.format("There are no %s for the selected content.", artifactTypeName)); + } else { + for (BlackboardArtifact fileHit : fileHitInfo) { + addFileHitEntry(html, fileHit); + } + } + endSection(html); + } catch (NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS + } + } + + + private String tryGetAttribute(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE attributeType) { + if (artifact == null) { + return null; + } + + BlackboardAttribute attr = null; + try { + attr = artifact.getAttribute(new BlackboardAttribute.Type(attributeType)); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Unable to fetch attribute of type %s for artifact %s", attributeType, artifact), ex); + } + + if (attr == null) { + return null; + } + + return attr.getValueString(); + } + + /** + * Add a data table containing information about an file hit artifact (i.e. + * hash hit). + * + * @param html The HTML text to add the table to. + * @param tag The blackboard artifact with hash hit information whose + * information will be used to populate the table. + */ + @NbBundle.Messages({ + "AnnotationsContentViewer.addHashHitEntry.hashSet=Hash Set:", + "AnnotationsContentViewer.addHashHitEntry.comment=Comment:" + }) + private void addFileHitEntry(StringBuilder html, BlackboardArtifact artifact) { + startTable(html); + + String hashset = tryGetAttribute(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME); + String comment = tryGetAttribute(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT); + + if (StringUtils.isNotBlank(hashset)) { + addRow(html, Bundle.AnnotationsContentViewer_addHashHitEntry_hashSet(), hashset); + } + + if (StringUtils.isNotBlank(comment)) { + addRow(html, Bundle.AnnotationsContentViewer_tagEntryDataLabel_comment(), comment); + } + + endTable(html); + } + /** * Populate the "Selected Item" sections with tag data for the supplied * content. From f1f1786779175d3fdfee38131838fa81718fefc4 Mon Sep 17 00:00:00 2001 From: apriestman Date: Wed, 6 May 2020 15:05:12 -0400 Subject: [PATCH 25/90] Don't load data sources for TIMELINE_EVENT_ADDED --- .../org/sleuthkit/autopsy/timeline/EventsModel.java | 12 +++++++++++- .../autopsy/timeline/TimeLineController.java | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/EventsModel.java b/Core/src/org/sleuthkit/autopsy/timeline/EventsModel.java index 146bc156ed..f80eef206b 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/EventsModel.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/EventsModel.java @@ -657,6 +657,17 @@ public final class EventsModel { } return postTagsDeleted(updatedEventIDs); } + + /** + * Updates the events model for a data source added event. + * + * @throws TskCoreException If there is an error reading model data from the + * case database. + */ + synchronized void handleDataSourceAdded() throws TskCoreException { + populateDataSourcesCache(); + invalidateCaches(null); + } /** * Updates the events model for an artifact tag deleted event and publishes @@ -782,7 +793,6 @@ public final class EventsModel { * @throws TskCoreException */ public synchronized void invalidateCaches(Collection updatedEventIDs) throws TskCoreException { - populateDataSourcesCache(); minEventTimeCache.invalidateAll(); maxEventTimeCache.invalidateAll(); idsToEventsCache.invalidateAll(emptyIfNull(updatedEventIDs)); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index cf8e9c46f7..6b41d849d8 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -783,7 +783,7 @@ public class TimeLineController { break; case DATA_SOURCE_ADDED: future = executor.submit(() -> { - filteredEvents.invalidateCaches(null); + filteredEvents.handleDataSourceAdded(); return null; }); break; From 23782a90ccd4e5b8fbc001e09ea48f4cc803ef34 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 6 May 2020 15:16:15 -0400 Subject: [PATCH 26/90] updates for comments and formatting --- .../AnnotationsContentViewer.java | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index 22a8bfe08b..c87178bade 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -28,7 +28,6 @@ import org.apache.commons.lang3.StringEscapeUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.openide.nodes.Node; -import org.openide.util.Exceptions; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -49,7 +48,6 @@ import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; /** * Annotations view of file contents. @@ -113,17 +111,25 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data if (sourceFile instanceof AbstractFile) { populateCentralRepositoryData(html, artifact, (AbstractFile) sourceFile); - populateHashHitData(html, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT); - populateHashHitData(html, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); + populateFileSetData(html, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT); + populateFileSetData(html, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); } setText(html.toString()); jTextPane1.setCaretPosition(0); } - private void populateHashHitData(StringBuilder html, Content content, BlackboardArtifact.ARTIFACT_TYPE artifactType) { + /** + * Populates the html provided with data concerning the source file and + * whether it appears in a file set. + * + * @param html The html to append information. + * @param content The source content to check for blackboard artifacts. + * @param artifactType The artifact type to check for. + */ + private void populateFileSetData(StringBuilder html, Content content, BlackboardArtifact.ARTIFACT_TYPE artifactType) { String artifactTypeName = artifactType.getDisplayName(); - + try { SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); @@ -132,9 +138,9 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data if (fileHitInfo.isEmpty()) { addMessage(html, String.format("There are no %s for the selected content.", artifactTypeName)); } else { - for (BlackboardArtifact fileHit : fileHitInfo) { + fileHitInfo.forEach((fileHit) -> { addFileHitEntry(html, fileHit); - } + }); } endSection(html); } catch (NoCurrentCaseException ex) { @@ -144,7 +150,15 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } } - + /** + * Attempts to retrieve the attribute of a particular type from a blackboard + * artifact. + * + * @param artifact The artifact from which to retrieve the information. + * @param attributeType The attribute type to retrieve from the artifact. + * + * @return The string value of the attribute or null if not found. + */ private String tryGetAttribute(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE attributeType) { if (artifact == null) { return null; @@ -165,8 +179,8 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } /** - * Add a data table containing information about an file hit artifact (i.e. - * hash hit). + * Add a data table containing information about an file set hit artifact + * (i.e. hash hit). * * @param html The HTML text to add the table to. * @param tag The blackboard artifact with hash hit information whose From 4e83fdfc60fc997567b6d25e28b8986a0e29c390 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 6 May 2020 15:59:34 -0400 Subject: [PATCH 27/90] method rename --- .../autopsy/centralrepository/datamodel/CentralRepository.java | 2 +- .../autopsy/centralrepository/datamodel/RdbmsCentralRepo.java | 2 +- .../sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java index 945e279123..abeb2bd067 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java @@ -555,7 +555,7 @@ public interface CentralRepository { * @throws CentralRepoException * @throws CorrelationAttributeNormalizationException */ - public HashHitInfo getFileHashInReferenceSet(String hash, int referenceSetID) throws CentralRepoException, CorrelationAttributeNormalizationException; + public HashHitInfo lookupHash(String hash, int referenceSetID) throws CentralRepoException, CorrelationAttributeNormalizationException; /** diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java index a8b65da9d6..0a245f9057 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java @@ -2279,7 +2279,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { } @Override - public HashHitInfo getFileHashInReferenceSet(String hash, int referenceSetID) throws CentralRepoException, CorrelationAttributeNormalizationException { + public HashHitInfo lookupHash(String hash, int referenceSetID) throws CentralRepoException, CorrelationAttributeNormalizationException { int correlationTypeID = CorrelationAttributeInstance.FILES_TYPE_ID; String normalizeValued = CorrelationAttributeNormalizer.normalize(this.getCorrelationTypeById(correlationTypeID), hash); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index ee48978295..495e9f6705 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -1378,7 +1378,7 @@ public class HashDbManager implements PropertyChangeListener { AbstractFile file = (AbstractFile) content; if (null != file.getMd5Hash()) { try { - return CentralRepository.getInstance().getFileHashInReferenceSet(file.getMd5Hash(), referenceSetID); + return CentralRepository.getInstance().lookupHash(file.getMd5Hash(), referenceSetID); } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) { Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash " + file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS From eaa58efc48b7027c89e8ba6b7ee81eb21f11d6c4 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 7 May 2020 07:54:23 -0400 Subject: [PATCH 28/90] bug fix --- .../autopsy/modules/hashdatabase/HashDbIngestModule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index 352a89ab55..9f03c0ab78 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -237,7 +237,7 @@ public class HashDbIngestModule implements FileIngestModule { // look up no change items next FindInHashsetsResult noChangeResult = findInHashsets(file, totals.totalNoChangeCount, - totals.totalLookuptime, noChangeHashSets, TskData.FileKnown.BAD, noChangeLookupError); + totals.totalLookuptime, noChangeHashSets, TskData.FileKnown.UNKNOWN, noChangeLookupError); if (noChangeResult.isError()) { ret = ProcessResult.ERROR; From 5c7d860ea14afe8f134b0240af71fd60e815238d Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Thu, 7 May 2020 10:53:17 -0400 Subject: [PATCH 29/90] 6336 Persona UI elements added --- .../autopsy/persona/Bundle.properties | 13 +- .../autopsy/persona/PersonasTopComponent.form | 328 +++++++++++++++++- .../autopsy/persona/PersonasTopComponent.java | 238 ++++++++++++- 3 files changed, 573 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties b/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties index 2ddf32efdc..de9095c342 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties @@ -1,3 +1,14 @@ CTL_OpenPersonas=Personas CTL_PersonasTopComponentAction=PersonasTopComponent -CTL_PersonasTopComponent=Personas \ No newline at end of file +CTL_PersonasTopComponent=Personas +PersonasTopComponent.jTextField1.text=John Doe +PersonasTopComponent.jRadioButton1.text=Name +PersonasTopComponent.jRadioButton2.text=Account +PersonasTopComponent.jLabel2.text=Name: +PersonasTopComponent.jTextField2.text=Johnathan Dough +PersonasTopComponent.jLabel3.text=Aliases: +PersonasTopComponent.jLabel4.text=Accounts: +PersonasTopComponent.jLabel5.text=Cases found in: +PersonasTopComponent.jTable2.columnModel.title0=ID +PersonasTopComponent.jTable2.columnModel.title1=Name +PersonasTopComponent.jButton1.text=Search diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form index 6fe1c2a940..16eaf6ecbb 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form @@ -21,7 +21,18 @@ --> -
    + + + + + + + + + + + + @@ -37,13 +48,324 @@ - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
").append(jobTotals.totalKnownBadCount.get()).append("
") //NON-NLS + .append(Bundle.HashDbIngestModule_complete_noChangesFound()) + .append("").append(jobTotals.totalNoChangeCount.get()).append("
") //NON-NLS .append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.totalCalcTime")) .append("").append(jobTotals.totalCalctime.get()).append("
").append(jobTotals.totalNoChangeCount.get()).append("
") //NON-NLS .append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.totalCalcTime")) .append("").append(jobTotals.totalCalctime.get()).append("
+ + + + + + + + + + + + +
+
+ + + + + <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonasTopComponent.jTable2.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonasTopComponent.jTable2.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java index a88d66faa0..86bad69c59 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java @@ -45,19 +45,253 @@ public final class PersonasTopComponent extends TopComponent { // //GEN-BEGIN:initComponents private void initComponents() { + buttonGroup1 = new javax.swing.ButtonGroup(); + jDesktopPane1 = new javax.swing.JDesktopPane(); + jPanel1 = new javax.swing.JPanel(); + jTextField1 = new javax.swing.JTextField(); + jRadioButton1 = new javax.swing.JRadioButton(); + jRadioButton2 = new javax.swing.JRadioButton(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTable2 = new javax.swing.JTable(); + jButton1 = new javax.swing.JButton(); + jPanel2 = new javax.swing.JPanel(); + jLabel2 = new javax.swing.JLabel(); + jTextField2 = new javax.swing.JTextField(); + jLabel3 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + jScrollPane4 = new javax.swing.JScrollPane(); + jTable1 = new javax.swing.JTable(); + jLabel5 = new javax.swing.JLabel(); + jScrollPane3 = new javax.swing.JScrollPane(); + jList2 = new javax.swing.JList<>(); + jScrollPane5 = new javax.swing.JScrollPane(); + jList3 = new javax.swing.JList<>(); + + setMinimumSize(new java.awt.Dimension(400, 400)); + + jTextField1.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jTextField1.text")); // NOI18N + + buttonGroup1.add(jRadioButton1); + org.openide.awt.Mnemonics.setLocalizedText(jRadioButton1, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jRadioButton1.text")); // NOI18N + jRadioButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jRadioButton1ActionPerformed(evt); + } + }); + + buttonGroup1.add(jRadioButton2); + org.openide.awt.Mnemonics.setLocalizedText(jRadioButton2, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jRadioButton2.text")); // NOI18N + + jTable2.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + {"0", "Johnathn Dough"}, + {"3", "Joe Schmoe"}, + {"2", "Michael Schmoe"}, + {"1", "Ethan Schmoe"} + }, + new String [] { + "ID", "Name" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + }); + jScrollPane1.setViewportView(jTable2); + if (jTable2.getColumnModel().getColumnCount() > 0) { + jTable2.getColumnModel().getColumn(0).setMaxWidth(25); + jTable2.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jTable2.columnModel.title0")); // NOI18N + jTable2.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jTable2.columnModel.title1")); // NOI18N + } + + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jButton1.text")); // NOI18N + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addComponent(jTextField1, javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jRadioButton1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jRadioButton2)) + .addComponent(jButton1)) + .addGap(0, 63, Short.MAX_VALUE))) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jRadioButton1) + .addComponent(jRadioButton2)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1) + .addGap(18, 18, 18) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addContainerGap()) + ); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jLabel2.text")); // NOI18N + + jTextField2.setEditable(false); + jTextField2.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jTextField2.text")); // NOI18N + jTextField2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jTextField2ActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jLabel3.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jLabel4.text")); // NOI18N + + jTable1.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + {"Email", "jdb@yahoo.com"}, + {"Phone", "865-555-5555"}, + {"Twitter", "@jd93.bread"}, + {null, null} + }, + new String [] { + "Type", "Data" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + false, false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + jScrollPane4.setViewportView(jTable1); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jLabel5.text")); // NOI18N + + jList2.setModel(new javax.swing.AbstractListModel() { + String[] strings = { "Investigation 13", "Scene 5" }; + public int getSize() { return strings.length; } + public String getElementAt(int i) { return strings[i]; } + }); + jScrollPane3.setViewportView(jList2); + + jList3.setModel(new javax.swing.AbstractListModel() { + String[] strings = { "J.D.", "Fred Smidge", "Ethan Roseman" }; + public int getSize() { return strings.length; } + public String getElementAt(int i) { return strings[i]; } + }); + jScrollPane5.setViewportView(jList3); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addGroup(jPanel2Layout.createSequentialGroup() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jScrollPane5) + .addComponent(jScrollPane3) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel2Layout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 299, Short.MAX_VALUE)) + .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jLabel4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()))) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel2) + .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 18, 18) + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jLabel4) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 153, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jLabel5) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 63, Short.MAX_VALUE) + .addContainerGap()) + ); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 400, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 300, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); }// //GEN-END:initComponents + private void jRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButton1ActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_jRadioButton1ActionPerformed + + private void jTextField2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField2ActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_jTextField2ActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.ButtonGroup buttonGroup1; + private javax.swing.JButton jButton1; + private javax.swing.JDesktopPane jDesktopPane1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JList jList2; + private javax.swing.JList jList3; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JRadioButton jRadioButton1; + private javax.swing.JRadioButton jRadioButton2; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane3; + private javax.swing.JScrollPane jScrollPane4; + private javax.swing.JScrollPane jScrollPane5; + private javax.swing.JTable jTable1; + private javax.swing.JTable jTable2; + private javax.swing.JTextField jTextField1; + private javax.swing.JTextField jTextField2; // End of variables declaration//GEN-END:variables } From b25b3a4b3b28efc84bddd0b91c05937f759589c6 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 7 May 2020 12:31:36 -0400 Subject: [PATCH 30/90] address codacy remarks --- .../datamodel/CentralRepository.java | 2 +- .../hashdatabase/HashDbIngestModule.java | 4 +- .../modules/hashdatabase/HashDbManager.java | 2 +- .../hashdatabase/KdbHashSetParser.java | 69 ++++--------------- 4 files changed, 18 insertions(+), 59 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java index b3d8437a7c..a4ce71cb36 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java @@ -567,7 +567,7 @@ public interface CentralRepository { * @throws CentralRepoException * @throws CorrelationAttributeNormalizationException */ - public HashHitInfo lookupHash(String hash, int referenceSetID) throws CentralRepoException, CorrelationAttributeNormalizationException; + HashHitInfo lookupHash(String hash, int referenceSetID) throws CentralRepoException, CorrelationAttributeNormalizationException; /** diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index 9f03c0ab78..3533fb34d8 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -612,7 +612,7 @@ public class HashDbIngestModule implements FileIngestModule { detailsSb.append("") //NON-NLS .append(Bundle.HashDbIngestModule_complete_noChangesFound()) .append(""); //NON-NLS - detailsSb.append("").append(jobTotals.totalNoChangeCount.get()).append(""); //NON-NLS + detailsSb.append("" + jobTotals.totalNoChangeCount.get() + ""); //NON-NLS detailsSb.append("") //NON-NLS .append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.totalCalcTime")) @@ -626,7 +626,7 @@ public class HashDbIngestModule implements FileIngestModule { .append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.databasesUsed")) .append("

\n
    "); //NON-NLS Stream.concat(knownBadHashSets.stream(), noChangeHashSets.stream()).forEach((db) -> { - detailsSb.append("
  • ").append(db.getHashSetName()).append("
  • \n"); //NON-NLS + detailsSb.append("
  • " + db.getHashSetName() + "
  • \n"); //NON-NLS }); detailsSb.append("
"); //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index 495e9f6705..7559649689 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -711,7 +711,7 @@ public class HashDbManager implements PropertyChangeListener { private final boolean allowSendInboxMessages; private final boolean defaultSendInboxMessages; - private KnownFilesType(String displayName, TskData.FileKnown fileKnown, boolean allowSendInboxMessages, boolean defaultSendInboxMessages) { + KnownFilesType(String displayName, TskData.FileKnown fileKnown, boolean allowSendInboxMessages, boolean defaultSendInboxMessages) { this.displayName = displayName; this.fileKnown = fileKnown; this.allowSendInboxMessages = allowSendInboxMessages; diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java index fd79636757..4045abcda7 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java @@ -72,7 +72,9 @@ public class KdbHashSetParser implements HashSetParser { } // Get the hashes - resultSet = statement.executeQuery("SELECT id, md5 FROM hashes"); + resultSet = statement.executeQuery("SELECT h.md5 as md5, " + + " (SELECT group_concat(c.comment, ' ') FROM comments c WHERE h.id = c.hash_id) as comment " + + " from hashes h"); // At this point, getNextHash can read each hash from the result set } catch (ClassNotFoundException | SQLException ex) { @@ -81,36 +83,23 @@ public class KdbHashSetParser implements HashSetParser { } - private static class HashRow { - - private final String md5Hash; - private final long hashId; - - HashRow(String md5Hash, long hashId) { - this.md5Hash = md5Hash; - this.hashId = hashId; - } - - String getMd5Hash() { - return md5Hash; - } - - long getHashId() { - return hashId; - } - } /** - * Retrieves the row id and md5 hash for the next item in the hashes table. + * Get the next hash to import * - * @return A hash row object containing the hash and id. + * @return The hash as a string * * @throws TskCoreException */ - private HashRow getNextHashRow() throws TskCoreException { + @Override + public String getNextHash() throws TskCoreException { + return getNextHashEntry().getMd5Hash(); + } + + @Override + public HashEntry getNextHashEntry() throws TskCoreException { try { if (resultSet.next()) { - long hashId = resultSet.getLong("id"); byte[] hashBytes = resultSet.getBytes("md5"); StringBuilder sb = new StringBuilder(); for (byte b : hashBytes) { @@ -122,42 +111,12 @@ public class KdbHashSetParser implements HashSetParser { } String md5Hash = sb.toString(); + String comment = resultSet.getString("comment"); totalHashesRead++; - return new HashRow(md5Hash, hashId); + return new HashEntry(null, md5Hash, null, null, comment); } else { throw new TskCoreException("Could not read expected number of hashes from hash set " + filename); } - } catch (SQLException ex) { - throw new TskCoreException("Error reading hash from result set for hash set " + filename, ex); - } - } - - /** - * Get the next hash to import - * - * @return The hash as a string - * - * @throws TskCoreException - */ - @Override - public String getNextHash() throws TskCoreException { - return getNextHashRow().getMd5Hash(); - } - - @Override - public HashEntry getNextHashEntry() throws TskCoreException { - HashRow row = getNextHashRow(); - try { - PreparedStatement getComment = conn.prepareStatement("SELECT comment FROM comments WHERE hash_id = ?"); - getComment.setLong(1, row.getHashId()); - ResultSet commentResults = getComment.executeQuery(); - List comments = new ArrayList<>(); - while (commentResults.next()) { - comments.add(commentResults.getString("comment")); - } - - String comment = comments.size() > 0 ? String.join(" ", comments) : null; - return new HashEntry(null, row.getMd5Hash(), null, null, comment); } catch (SQLException ex) { throw new TskCoreException("Error opening/reading hash set " + filename, ex); } From f04398567e6fcefe5ab02d81c0c779fc1462a1f5 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 7 May 2020 12:46:15 -0400 Subject: [PATCH 31/90] more codacy items --- .../autopsy/core/Bundle.properties-MERGED | 8 +++- .../corecomponents/Bundle.properties-MERGED | 12 +++--- .../coreutils/Bundle.properties-MERGED | 4 +- .../directorytree/Bundle.properties-MERGED | 6 +-- .../filesearch/Bundle.properties-MERGED | 10 ++--- .../autopsy/ingest/Bundle.properties-MERGED | 2 +- .../livetriage/Bundle.properties-MERGED | 4 +- .../Bundle.properties-MERGED | 4 +- .../Bundle.properties-MERGED | 8 +++- .../modules/exif/Bundle.properties-MERGED | 4 +- .../fileextmismatch/Bundle.properties-MERGED | 18 ++++----- .../filetypeid/Bundle.properties-MERGED | 6 +-- .../hashdatabase/HashDbIngestModule.java | 37 ++++++++----------- .../hashdatabase/KdbHashSetParser.java | 3 -- .../interestingitems/Bundle.properties-MERGED | 18 ++++----- .../photoreccarver/Bundle.properties-MERGED | 2 +- .../modules/html/Bundle.properties-MERGED | 6 +-- .../ui/Bundle.properties-MERGED | 1 + .../autoingest/Bundle.properties-MERGED | 12 ++++++ .../configuration/Bundle.properties-MERGED | 1 + .../keywordsearch/Bundle.properties-MERGED | 20 +++++----- .../recentactivity/Bundle.properties-MERGED | 8 +++- .../netbeans/core/startup/Bundle.properties | 4 +- .../core/windows/view/ui/Bundle.properties | 6 +-- 24 files changed, 114 insertions(+), 90 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED index c84f1f1b86..0b16a9701f 100755 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED @@ -3,7 +3,13 @@ Installer.closing.confirmationDialog.title=Ingest is Running # {0} - exception message Installer.closing.messageBox.caseCloseExceptionMessage=Error closing case: {0} OpenIDE-Module-Display-Category=Infrastructure -OpenIDE-Module-Long-Description=This is the core Autopsy module.\n\nThe module contains the core components needed for the bare application to run; the RCP platform, windowing GUI, sleuthkit bindings, datamodel / storage, explorer, result viewers, content viewers, ingest framework, reporting, and core tools, such as the file search.\n\nThe framework included in the module contains APIs for developing modules for ingest, viewers and reporting. The modules can be deployed as Plugins using the Autopsy plugin installer.\nThis module should not be uninstalled - without it, Autopsy will not run.\n\nFor more information, see http://www.sleuthkit.org/autopsy/ +OpenIDE-Module-Long-Description=\ + This is the core Autopsy module.\n\n\ + The module contains the core components needed for the bare application to run; the RCP platform, windowing GUI, sleuthkit bindings, datamodel / storage, explorer, result viewers, content viewers, ingest framework, reporting, and core tools, such as the file search.\n\n\ + The framework included in the module contains APIs for developing modules for ingest, viewers and reporting. \ + The modules can be deployed as Plugins using the Autopsy plugin installer.\n\ + This module should not be uninstalled - without it, Autopsy will not run.\n\n\ + For more information, see http://www.sleuthkit.org/autopsy/ OpenIDE-Module-Name=Autopsy-Core OpenIDE-Module-Short-Description=Autopsy Core Module org_sleuthkit_autopsy_core_update_center=http://sleuthkit.org/autopsy/updates.xml diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED index f252420726..544cfa63c0 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED @@ -63,9 +63,9 @@ DataContentViewerHex.totalPageLabel.text_1=100 DataContentViewerHex.pageLabel2.text=Page # Product Information panel -LBL_Description=
\n Product Version: {0} ({9})
Sleuth Kit Version: {7}
Netbeans RCP Build: {8}
Java: {1}; {2}
System: {3}; {4}; {5}
Userdir: {6}
+LBL_Description=
\n Product Version: {0} ({9})
Sleuth Kit Version: {7}
Netbeans RCP Build: {8}
Java: {1}; {2}
System: {3}; {4}; {5}
Userdir: {6}
Format_OperatingSystem_Value={0} version {1} running on {2} -LBL_Copyright=
Autopsy™ is a digital forensics platform based on The Sleuth Kit™ and other tools.
Copyright © 2003-2018.
+LBL_Copyright=
Autopsy™ is a digital forensics platform based on The Sleuth Kit™ and other tools.
Copyright © 2003-2018.
SortChooser.dialogTitle=Choose Sort Criteria ThumbnailViewChildren.progress.cancelling=(Cancelling) # {0} - file name @@ -95,7 +95,7 @@ DataResultViewerThumbnail.pageNextButton.text= DataResultViewerThumbnail.imagesLabel.text=Images: DataResultViewerThumbnail.imagesRangeLabel.text=- DataResultViewerThumbnail.pageNumLabel.text=- -DataResultViewerThumbnail.filePathLabel.text=\ +DataResultViewerThumbnail.filePathLabel.text=\ \ \ DataResultViewerThumbnail.goToPageLabel.text=Go to Page: DataResultViewerThumbnail.goToPageField.text= AdvancedConfigurationDialog.cancelButton.text=Cancel @@ -129,9 +129,9 @@ DataResultViewerThumbnail.switchPage.done.errMsg=Error making thumbnails: {0} AboutWindowPanel.actVerboseLogging.text=Activate verbose logging OptionsCategory_Name_Multi_User_Settings=Multi-User OptionsCategory_Keywords_Multi_User_Options=Multi-User Settings -MultiUserSettingsPanel.lbSolrSettings.text=Solr Settings +MultiUserSettingsPanel.lbSolrSettings.text=Solr Server Settings MultiUserSettingsPanel.cbEnableMultiUser.text=Enable multi-user cases -MultiUserSettingsPanel.lbDatabaseSettings.text=Database Settings +MultiUserSettingsPanel.lbDatabaseSettings.text=Database Server Settings MultiUserSettingsPanel.validationErrMsg.incomplete=Fill in all values MultiUserSettingsPanel.nonWindowsOs.msg=Multi-user cases are only available on Windows platforms MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database port number @@ -159,7 +159,7 @@ MultiUserSettingsPanel.tbSolrHostname.toolTipText=Hostname or IP Address MultiUserSettingsPanel.tbSolrPort.toolTipText=Port Number MultiUserSettingsPanel.lbTestMessageService.text= MultiUserSettingsPanel.bnTestMessageService.text=Test -MultiUserSettingsPanel.lbMessageServiceSettings.text=ActiveMQ Message Service Settings +MultiUserSettingsPanel.lbMessageServiceSettings.text=ActiveMQ Message Server Settings MultiUserSettingsPanel.tbMsgPort.toolTipText=Port Number MultiUserSettingsPanel.tbMsgPort.text= MultiUserSettingsPanel.tbMsgUsername.toolTipText=User Name (optional) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties-MERGED index 18e279dd2c..a0d535f8e6 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties-MERGED @@ -30,7 +30,9 @@ PlatformUtil.getProcVmUsed.sigarNotInit.msg=Cannot get virt mem used, sigar not PlatformUtil.getProcVmUsed.gen.msg=Cannot get virt mem used, {0} PlatformUtil.getJvmMemInfo.usageText=JVM heap usage: {0}, JVM non-heap usage: {1} PlatformUtil.getPhysicalMemInfo.usageText=Physical memory usage (max, total, free): {0}, {1}, {2} -PlatformUtil.getAllMemUsageInfo.usageText={0}\n{1}\nProcess Virtual Memory: {2} +PlatformUtil.getAllMemUsageInfo.usageText={0}\n\ +{1}\n\ +Process Virtual Memory: {2} # {0} - file name ReadImageTask.mesageText=Reading image: {0} StringExtract.illegalStateException.cannotInit.msg=Unicode table not properly initialized, cannot instantiate StringExtract diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties-MERGED index 63b416b176..7e96d8fdaa 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties-MERGED @@ -38,8 +38,6 @@ HINT_DirectoryTreeTopComponent=This is a DirectoryTree window OpenIDE-Module-Name=DirectoryTree FileSystemDetailsPanel.imgOffsetLabel.text=Image Offset: FileSystemDetailsPanel.fsTypeLabel.text=FileSystem Type: -FileSystemDetailsPanel.jLabel2.text=bytes -FileSystemDetailsPanel.jLabel3.text=bytes FileSystemDetailsPanel.fsTypeValue.text=... FileSystemDetailsPanel.imgOffsetValue.text=... FileSystemDetailsPanel.volumeIDValue.text=... @@ -71,7 +69,6 @@ VolumeDetailsPanel.startLabel.text=Starting Sector: VolumeDetailsPanel.lengthLabel.text=Length in Sectors: VolumeDetailsPanel.descLabel.text=Description: VolumeDetailsPanel.flagsLabel.text=Flags: -VolumeDetailsPanel.jLabel1.text=General Volume Information VolumeDetailsPanel.OKButton.text=OK ImageDetailsPanel.imageInfoLabel.text=Image Information ImageDetailsPanel.imgNameLabel.text=Name: @@ -160,3 +157,6 @@ ExternalViewerGlobalSettingsPanel.jButton2.text=jButton2 ExternalViewerGlobalSettingsPanel.browseHxDDirectory.text=Browse ExternalViewerGlobalSettingsPanel.HxDLabel.text=HxD Editor Path: ExternalViewerGlobalSettingsPanel.ContentViewerExtensionLabel.text=Add content viewer extensions: +FileSystemDetailsPanel.bytesLabel1.text=bytes +FileSystemDetailsPanel.bytesLabel2.text=bytes +VolumeDetailsPanel.generalVolumeLabel.text=General Volume Information diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED index c585d0edf5..b304bc1342 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED @@ -14,11 +14,9 @@ KnownStatusSearchPanel.knownCheckBox.text=Known Status: KnownStatusSearchPanel.knownBadOptionCheckBox.text=Notable KnownStatusSearchPanel.knownOptionCheckBox.text=Known (NSRL or other) KnownStatusSearchPanel.unknownOptionCheckBox.text=Unknown -DateSearchFilter.noneSelectedMsg.text=At least one date type must be selected! +DateSearchFilter.noneSelectedMsg.text=At least one date type must be selected\! DateSearchPanel.dateCheckBox.text=Date: DateSearchPanel.jLabel4.text=Timezone: -DateSearchPanel.jLabel3.text=*The date format is mm/dd/yyyy -DateSearchPanel.jLabel2.text=*Empty fields mean "No Limit" DateSearchPanel.createdCheckBox.text=Created DateSearchPanel.accessedCheckBox.text=Accessed DateSearchPanel.changedCheckBox.text=Changed @@ -57,12 +55,11 @@ FileSearchPanel.search.results.details=Large number of matches may impact perfor FileSearchPanel.search.exception.noFilterSelected.msg=At least one filter must be selected. FileSearchPanel.search.validationErr.msg=Validation Error: {0} FileSearchPanel.emptyWhereClause.text=Invalid options, nothing to show. -KnownStatusSearchFilter.noneSelectedMsg.text=At least one known status must be selected! +KnownStatusSearchFilter.noneSelectedMsg.text=At least one known status must be selected\! NameSearchFilter.emptyNameMsg.text=Must enter something for name search. SizeSearchPanel.sizeCompareComboBox.equalTo=equal to SizeSearchPanel.sizeCompareComboBox.greaterThan=greater than SizeSearchPanel.sizeCompareComboBox.lessThan=less than -MimeTypePanel.jLabel1.text=*Note: Multiple MIME types can be selected FileSearchPanel.searchButton.text=Search MimeTypePanel.mimeTypeCheckBox.text=MIME Type: HashSearchPanel.md5CheckBox.text=MD5: @@ -72,3 +69,6 @@ DataSourcePanel.dataSourceCheckBox.label=Data Source: DataSourcePanel.dataSourceCheckBox.actionCommand=Data Source: DataSourcePanel.dataSourceCheckBox.text=Data Source: DataSourcePanel.dataSourceNoteLabel.text=*Note: Multiple data sources can be selected +DateSearchPanel.noLimitLabel.text=*Empty fields mean "No Limit" +DateSearchPanel.dateFormatLabel.text=*The date format is mm/dd/yyyy +MimeTypePanel.noteLabel.text=*Note: Multiple MIME types can be selected diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties-MERGED index 6be3e48e71..9e4f612b6b 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties-MERGED @@ -140,7 +140,7 @@ IngestJob.cancelReason.outOfDiskSpace.text=Out of disk space IngestJob.cancelReason.servicesDown.text=Services Down IngestJob.cancelReason.caseClosed.text=Case closed IngestJobSettingsPanel.globalSettingsButton.text=Global Settings -gest= +gest IngestJobSettingsPanel.globalSettingsButton.actionCommand=Advanced IngestJobSettingsPanel.globalSettingsButton.text=Global Settings IngestJobSettingsPanel.pastJobsButton.text=History diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties-MERGED index e0a2ab0413..309a07d3da 100755 --- a/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties-MERGED @@ -18,10 +18,10 @@ SelectDriveDialog.diskTable.column2.title=Disk Size SelectDriveDialog.errLabel.disksNotDetected.text=Disks were not detected. On some systems it requires admin privileges SelectDriveDialog.errLabel.disksNotDetected.toolTipText=Disks were not detected. SelectDriveDialog.lbSelectDrive.text=Select the drive to copy the application and script to: -SelectDriveDialog.jLabel1.text=Select drive to use for live triage (may take time to load): SelectDriveDialog.errorLabel.text=jLabel2 SelectDriveDialog.bnCancel.text=Cancel -SelectDriveDialog.jTextArea1.text=This feature copies the application and a batch file to a removable drive,\nallowing systems to be analyzed without installing the software or\nimaging the drives.\n\nTo analyze a system, insert the drive and run "RunFromUSB.bat" as\nadministrator, then select the "Local Disk" option on the Add Data Source\npanel. +SelectDriveDialog.descriptionTextArea.text=This feature copies the application and a batch file to a removable drive,\nallowing systems to be analyzed without installing the software or\nimaging the drives.\n\nTo analyze a system, insert the drive and run "RunFromUSB.bat" as\nadministrator, then select the "Local Disk" option on the Add Data Source\npanel. SelectDriveDialog.localDiskModel.loading.msg= SelectDriveDialog.localDiskModel.nodrives.msg=Executable could not be found +SelectDriveDialog.selectDriveLabel.text=Select drive to use for live triage (may take time to load): SelectDriveDialog.title=Create Live Triage Drive diff --git a/Core/src/org/sleuthkit/autopsy/modules/dataSourceIntegrity/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/dataSourceIntegrity/Bundle.properties-MERGED index b006deb22d..e69126f939 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/dataSourceIntegrity/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/dataSourceIntegrity/Bundle.properties-MERGED @@ -45,6 +45,6 @@ DataSourceIntegrityIngestModule.shutDown.resultLi=
  • Result:{0}
  • DataSourceIntegrityIngestModule.shutDown.calcHashLi=
  • Calculated hash: {0}
  • DataSourceIntegrityIngestModule.shutDown.storedHashLi=
  • Stored hash: {0}
  • DataSourceIntegrityIngestSettingsPanel.computeHashesCheckbox.text=Calculate data source hashes if none are present -DataSourceIntegrityIngestSettingsPanel.jLabel1.text=Note that this module will not run on logical files -DataSourceIntegrityIngestSettingsPanel.jLabel3.text=Ingest Settings DataSourceIntegrityIngestSettingsPanel.verifyHashesCheckbox.text=Verify existing data source hashes +DataSourceIntegrityIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings +DataSourceIntegrityIngestSettingsPanel.noteLabel.text=Note that this module will not run on logical files diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties-MERGED index 4729293fb9..4585d86449 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties-MERGED @@ -11,7 +11,12 @@ ExtractArchiveWithPasswordAction.progress.text=Unpacking contents of archive: {0 ExtractArchiveWithPasswordAction.prompt.text=Enter Password ExtractArchiveWithPasswordAction.prompt.title=Enter Password OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Embedded File Extraction Ingest Module\n\nThe Embedded File Extraction Ingest Module processes document files (such as doc, docx, ppt, pptx, xls, xlsx) and archive files (such as zip and others archive types supported by the 7zip extractor).\nContents of these files are extracted and the derived files are added back to the current ingest to be processed by the configured ingest modules.\nIf the derived file happens to be an archive file, it will be re-processed by the 7zip extractor - the extractor will process archive files N-levels deep.\n\nThe extracted files are navigable in the directory tree.\n\nThe module is supported on Windows, Linux and Mac operating systems. +OpenIDE-Module-Long-Description=\ + Embedded File Extraction Ingest Module\n\nThe Embedded File Extraction Ingest Module processes document files (such as doc, docx, ppt, pptx, xls, xlsx) and archive files (such as zip and others archive types supported by the 7zip extractor).\n\ + Contents of these files are extracted and the derived files are added back to the current ingest to be processed by the configured ingest modules.\n\ + If the derived file happens to be an archive file, it will be re-processed by the 7zip extractor - the extractor will process archive files N-levels deep.\n\n\ + The extracted files are navigable in the directory tree.\n\n\ + The module is supported on Windows, Linux and Mac operating systems. OpenIDE-Module-Name=Embedded File Extraction OpenIDE-Module-Short-Description=Embedded File Extraction Ingest Module EmbeddedFileExtractorIngestModule.SevenZipContentReadStream.seek.exception.invalidOrigin=Invalid seek origin: {0} @@ -23,7 +28,6 @@ EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnMsg=Possib EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnDetails=Compression ratio is {0}, skipping items in {1}. EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.warnMsg.zipBomb=Possible ZIP bomb detected: {0} EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.warnDetails.zipBomb=The archive is {0} levels deep, skipping processing of {1} -EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.unknownPath.msg=Unknown item path in archive: {0}, will use: {1} EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.notEnoughDiskSpace.msg=Not enough disk space to unpack archive item: {0}, {1} EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.notEnoughDiskSpace.details=The archive item is too large to unpack, skipping unpacking this item. EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.errUnpacking.msg=Error unpacking {0} diff --git a/Core/src/org/sleuthkit/autopsy/modules/exif/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/exif/Bundle.properties-MERGED index 4915d5a124..f9a5a88b1b 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/exif/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/exif/Bundle.properties-MERGED @@ -2,7 +2,9 @@ CannotRunFileTypeDetection=Cannot run file type detection. ExifParserFileIngestModule.indexError.message=Failed to post EXIF Metadata artifact(s). ExifParserFileIngestModule.userContent.description=EXIF metadata exists for this file. OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Exif metadata ingest module. \n\nThe ingest module analyzes image files, extracts Exif information and posts the Exif data as results. +OpenIDE-Module-Long-Description=\ + Exif metadata ingest module. \n\n\ + The ingest module analyzes image files, extracts Exif information and posts the Exif data as results. OpenIDE-Module-Name=ExifParser OpenIDE-Module-Short-Description=Exif metadata ingest module ExifParserFileIngestModule.moduleName.text=Exif Parser diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties-MERGED index 5063bd55fa..cfaadf1635 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties-MERGED @@ -36,27 +36,27 @@ FileExtMismatchSettingsPanel.jLabel1.text=File Types: FileExtMismatchSettingsPanel.newExtButton.text=New Extension FileExtMismatchSettingsPanel.newMimePrompt.message=Add a new MIME file type: FileExtMismatchSettingsPanel.newMimePrompt.title=New MIME -FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.message=MIME type text is empty! +FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.message=MIME type text is empty\! FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.title=Empty type -FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.message=MIME type not supported! +FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.message=MIME type not supported\! FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.title=Type not supported -FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.message=MIME type already exists! +FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.message=MIME type already exists\! FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.title=Type already exists FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotDetectable.message=MIME type is not detectable by this module. FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotDetectable.title=Type not detectable -FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.message=No MIME type selected! +FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.message=No MIME type selected\! FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.title=No type selected FileExtMismatchSettingsPanel.newExtPrompt.message=Add an allowed extension: FileExtMismatchSettingsPanel.newExtPrompt.title=New allowed extension -FileExtMismatchSettingsPanel.newExtPrompt.empty.message=Extension text is empty! +FileExtMismatchSettingsPanel.newExtPrompt.empty.message=Extension text is empty\! FileExtMismatchSettingsPanel.newExtPrompt.empty.title=Extension text empty -FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.message=No MIME type selected! +FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.message=No MIME type selected\! FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.title=No MIME type selected -FileExtMismatchSettingsPanel.newExtPrompt.extExists.message=Extension already exists! +FileExtMismatchSettingsPanel.newExtPrompt.extExists.message=Extension already exists\! FileExtMismatchSettingsPanel.newExtPrompt.extExists.title=Extension already exists -FileExtMismatchSettingsPanel.removeExtButton.noneSelected.message=No extension selected! +FileExtMismatchSettingsPanel.removeExtButton.noneSelected.message=No extension selected\! FileExtMismatchSettingsPanel.removeExtButton.noneSelected.title=No extension selected -FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.message=No MIME type selected! +FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.message=No MIME type selected\! FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.title=No MIME type selected FileExtMismatchSettingsPanel.removeTypeButton.toolTipText= FileExtMismatchModuleSettingsPanel.checkAllRadioButton.text=Check all file types diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties-MERGED index ccc55e18b0..ca866a4a13 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties-MERGED @@ -51,7 +51,6 @@ FileTypeIdGlobalSettingsPanel.JOptionPane.loadFailed.title=Load Failed FileTypeIdGlobalSettingsPanel.loadFileTypes.errorMessage=Failed to load existing file type definitions. FileTypeIdGlobalSettingsPanel.saveFileTypes.errorMessage=Failed to save file type definitions. FileTypeIdGlobalSettingsPanel.newTypeButton.text=New Type -FileTypeIdGlobalSettingsPanel.jLabel2.text=Custom MIME Types: FileTypeIdGlobalSettingsPanel.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector. AddFileTypeSignaturePanel.offsetLabel.text=Byte Offset AddFileTypeSignaturePanel.signatureTextField.text= @@ -60,7 +59,6 @@ AddFileTypeSignaturePanel.signatureLabel.text=Signature AddFileTypeSignaturePanel.hexPrefixLabel.text=0x AddFileTypeSignaturePanel.offsetRelativeToLabel.text=Offset is relative to AddFileTypeSignaturePanel.offsetTextField.text= -FileTypeIdGlobalSettingsPanel.jLabel1.text=Signatures FileTypeIdGlobalSettingsPanel.editTypeButton.text=Edit Type AddFileTypePanel.mimeTypeTextField.text= AddFileTypePanel.mimeTypeLabel.text=MIME Type @@ -72,4 +70,6 @@ AddFileTypePanel.postHitCheckBox.text=Alert as an "Interesting File" when found AddFileTypePanel.setNameLabel.text=Set Name AddFileTypePanel.setNameTextField.text= FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes to file type definitions when ingest is running! -FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy can automatically detect many file types. Add your custom file types here. +FileTypeIdGlobalSettingsPanel.descriptionLabel.text=Autopsy can automatically detect many file types. Add your custom file types here. +FileTypeIdGlobalSettingsPanel.customTypesLabel.text=Custom MIME Types: +FileTypeIdGlobalSettingsPanel.signaturesLabel.text=Signatures diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index 3533fb34d8..873f891ad0 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -602,29 +602,22 @@ public class HashDbIngestModule implements FileIngestModule { if ((!knownBadHashSets.isEmpty()) || (!knownHashSets.isEmpty()) || (!noChangeHashSets.isEmpty())) { StringBuilder detailsSb = new StringBuilder(); //details - detailsSb.append(""); //NON-NLS + detailsSb.append( + "
    " + + "" + + "" + + + "" + + "" + + + "\n" + + + "\n
    " + NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.knownBadsFound") + "" + jobTotals.totalKnownBadCount.get() + "
    " + Bundle.HashDbIngestModule_complete_noChangesFound() + "" + jobTotals.totalNoChangeCount.get() + "
    " + NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.totalCalcTime") + + "" + jobTotals.totalCalctime.get() + "
    " + NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.totalLookupTime") + + "" + jobTotals.totalLookuptime.get() + "
    " + - detailsSb.append("") //NON-NLS - .append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.knownBadsFound")) - .append(""); //NON-NLS - detailsSb.append("").append(jobTotals.totalKnownBadCount.get()).append(""); //NON-NLS - - detailsSb.append("") //NON-NLS - .append(Bundle.HashDbIngestModule_complete_noChangesFound()) - .append(""); //NON-NLS - detailsSb.append("" + jobTotals.totalNoChangeCount.get() + ""); //NON-NLS - - detailsSb.append("") //NON-NLS - .append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.totalCalcTime")) - .append("").append(jobTotals.totalCalctime.get()).append("\n"); //NON-NLS - detailsSb.append("") //NON-NLS - .append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.totalLookupTime")) - .append("").append(jobTotals.totalLookuptime.get()).append("\n"); //NON-NLS - detailsSb.append(""); //NON-NLS - - detailsSb.append("

    ") //NON-NLS - .append(NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.databasesUsed")) - .append("

    \n
      "); //NON-NLS + "

      " + NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.complete.databasesUsed") + "

      \n
        "); //NON-NLS + Stream.concat(knownBadHashSets.stream(), noChangeHashSets.stream()).forEach((db) -> { detailsSb.append("
      • " + db.getHashSetName() + "
      • \n"); //NON-NLS }); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java index 4045abcda7..55bd974be4 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java @@ -20,12 +20,9 @@ package org.sleuthkit.autopsy.modules.hashdatabase; import java.sql.Connection; import java.sql.DriverManager; -import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.HashEntry; diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties-MERGED index 31a0690b82..3c275ee9cb 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties-MERGED @@ -83,8 +83,8 @@ FilesSetRulePanel.nameTextField.text= FilesSetRulePanel.ruleNameLabel.text=Rule Name (Optional): FilesSetRulePanel.messages.emptyNameCondition=You must specify a name pattern for this rule. FilesSetRulePanel.messages.invalidNameRegex=The name regular expression is not valid:\n\n{0} -FilesSetRulePanel.messages.invalidCharInName=The name cannot contain \\, /, :, *, ?, ", <, or > unless it is a regular expression. -FilesSetRulePanel.messages.invalidCharInPath=The path cannot contain \\, :, *, ?, ", <, or > unless it is a regular expression. +FilesSetRulePanel.messages.invalidCharInName=The name cannot contain \\, /, :, *, ?, \", <, or > unless it is a regular expression. +FilesSetRulePanel.messages.invalidCharInPath=The path cannot contain \\, :, *, ?, \", <, or > unless it is a regular expression. FilesSetRulePanel.messages.invalidPathRegex=The path regular expression is not valid:\n\n{0} FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text=Rule set with name {0} already exists. FilesSetRulePanel.pathSeparatorInfoLabel.text=Folder must be in parent path. Use '/' to give consecutive names @@ -109,21 +109,14 @@ FilesSetDefsPanel.ingest.deleteSetButton.text=Delete Filter FilesSetDefsPanel.interesting.jLabel6.text=Set Details FilesSetDefsPanel.ingest.jLabel6.text=Filter Details FilesSetDefsPanel.newRuleButton.text=New Rule -FilesSetDefsPanel.jLabel8.text=File Size: -FilesSetDefsPanel.jLabel7.text=MIME Type: FilesSetDefsPanel.rulePathConditionRegexCheckBox.text=Regex -FilesSetDefsPanel.jLabel4.text=Path Substring: -FilesSetDefsPanel.jLabel1.text=Rule Details FilesSetDefsPanel.dirsRadioButton.text=Directories -FilesSetDefsPanel.jLabel2.text=File Type: FilesSetDefsPanel.deleteRuleButton.text=Delete Rule FilesSetDefsPanel.fileNameRegexCheckbox.text=Substring / Regex FilesSetDefsPanel.ignoreKnownFilesCheckbox.text=Ignore Known Files FilesSetDefsPanel.rulePathConditionTextField.text= FilesSetDefsPanel.fileNameRadioButton.text=Full Name -FilesSetDefsPanel.jLabel5.text=Description: FilesSetDefsPanel.fileNameTextField.text= -FilesSetDefsPanel.jLabel3.text=Name: FilesSetDefsPanel.fileNameExtensionRadioButton.text=Extension Only FilesSetDefsPanel.rulesListLabel.text=Rules: FilesSetDefsPanel.editRuleButton.text=Edit Rule @@ -140,3 +133,10 @@ FilesSetDefsPanel.modifiedDateLabel.text=Modified Within: FilesSetDefsPanel.daysIncludedTextField.text= FilesSetDefsPanel.daysIncludedLabel.text=day(s) FilesSetRulePanel.daysIncludedLabel.text=day(s) +FilesSetDefsPanel.nameLabel.text=Name: +FilesSetDefsPanel.descriptionLabel.text=Description: +FilesSetDefsPanel.fileTypeLabel.text=File Type: +FilesSetDefsPanel.ruleLabel.text=Rule Details +FilesSetDefsPanel.pathLabel.text=Path Substring: +FilesSetDefsPanel.mimeTypeLabel.text=MIME Type: +FilesSetDefsPanel.fileSizeLabel.text=File Size: diff --git a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties-MERGED index 2dc971a40d..87dacfc16c 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties-MERGED @@ -21,7 +21,7 @@ PhotoRecIngestModule.complete.totalParsetime=Total Parsing Time: PhotoRecIngestModule.complete.photoRecResults=PhotoRec Results PhotoRecIngestModule.NotEnoughDiskSpace.detail.msg=PhotoRec error processing {0} with {1} Not enough space on primary disk to save unallocated space. PhotoRecIngestModule.cancelledByUser=PhotoRec cancelled by user. -PhotoRecIngestModule.error.exitValue=PhotoRec carver returned error exit value = {0} when scanning {1} +PhotoRecIngestModule.error.exitValue=PhotoRec carver returned error exit value \= {0} when scanning {1} PhotoRecIngestModule.error.msg=Error processing {0} with PhotoRec carver. PhotoRecIngestModule.complete.numberOfErrors=Number of Errors while Carving: PhotoRecCarverIngestJobSettingsPanel.detectionSettingsLabel.text=PhotoRec Settings diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle.properties-MERGED index 0be7595111..32f6867f0c 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle.properties-MERGED @@ -5,8 +5,8 @@ ReportHTML.getName.text=HTML Report ReportHTML.getDesc.text=A report about results and tagged items in HTML format. ReportHTML.writeIndex.title=for case {0} ReportHTML.writeIndex.noFrames.msg=Your browser is not compatible with our frame setup. -ReportHTML.writeIndex.noFrames.seeNav=Please see the navigation page for artifact links, -ReportHTML.writeIndex.seeSum=and the summary page for a case summary. +ReportHTML.writeIndex.noFrames.seeNav=Please see the navigation page for artifact links, +ReportHTML.writeIndex.seeSum=and the summary page for a case summary. ReportHTML.writeNav.title=Report Navigation ReportHTML.writeNav.h1=Report Navigation ReportHTML.writeNav.summary=Case Summary @@ -16,7 +16,7 @@ ReportHTML.writeSum.caseNumber=Case Number: ReportHTML.writeSum.caseNumImages=Number of Images: ReportHTML.writeSum.examiner=Examiner: ReportHTML.writeSum.title=Case Summary -ReportHTML.writeSum.warningMsg=Warning, this report was run before ingest services completed! +ReportHTML.writeSum.warningMsg=Warning, this report was run before ingest services completed\! # # autopsy/test/scripts/regression.py._html_report_diff() uses reportGenOn.text, caseName, caseNum, # examiner as a regex signature to skip report.html and summary.html diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties-MERGED index fa1a250e44..802b117c35 100644 --- a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle.properties-MERGED @@ -19,3 +19,4 @@ TranslationContentPanel.ocrLabel.text=OCR: TranslationOptionsPanelController.moduleErr=Module Error TranslationOptionsPanelController.moduleErr.msg=A module caused an error listening to TranslationSettingsPanelController updates. See log to determine which module. Some data could be incomplete. TranslationContentPanel.showLabel.text=Show: +TranslationContentPanel.jSepLarge1.AccessibleContext.accessibleName= diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED index adb7693b48..823399e0d0 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED @@ -89,6 +89,10 @@ AutoIngestControlPanel.runningTable.toolTipText=The Running table displays the c AutoIngestControlPanel.SharedConfigurationDisabled=Shared configuration disabled AutoIngestControlPanel.ShowLogFailed.Message=Case log file does not exist AutoIngestControlPanel.ShowLogFailed.Title=Unable to display case log +# {0} - case db status +# {1} - search svc Status +# {2} - coord svc Status +# {3} - msg broker status AutoIngestControlPanel.tbServicesStatusMessage.Message=Case databases {0}, keyword search {1}, coordination {2}, messaging {3} AutoIngestControlPanel.tbServicesStatusMessage.Message.Down=down AutoIngestControlPanel.tbServicesStatusMessage.Message.Unknown=unknown @@ -182,16 +186,22 @@ DeleteCaseTask.progress.acquiringManifestLocks=Acquiring exclusive manifest file DeleteCaseTask.progress.connectingToCoordSvc=Connecting to the coordination service... DeleteCaseTask.progress.deletingCaseDirCoordSvcNode=Deleting case directory znode... DeleteCaseTask.progress.deletingCaseNameCoordSvcNode=Deleting case name znode... +# {0} - data source path DeleteCaseTask.progress.deletingDataSource=Deleting data source {0}... DeleteCaseTask.progress.deletingJobLogLockNode=Deleting case auto ingest log znode... +# {0} - manifest file path DeleteCaseTask.progress.deletingManifest=Deleting manifest file {0}... +# {0} - manifest file path DeleteCaseTask.progress.deletingManifestFileNode=Deleting the manifest file znode for {0}... DeleteCaseTask.progress.deletingResourcesLockNode=Deleting case resources znode... DeleteCaseTask.progress.gettingManifestPaths=Getting manifest file paths... +# {0} - manifest file path DeleteCaseTask.progress.lockingManifest=Locking manifest file {0}... DeleteCaseTask.progress.openingCaseDatabase=Opening the case database... DeleteCaseTask.progress.openingCaseMetadataFile=Opening case metadata file... +# {0} - manifest file path DeleteCaseTask.progress.parsingManifest=Parsing manifest file {0}... +# {0} - manifest file path DeleteCaseTask.progress.releasingManifestLock=Releasing lock on the manifest file {0}... DeleteCaseTask.progress.startMessage=Starting deletion... DeleteOrphanCaseNodesAction.progressDisplayName=Cleanup Case Znodes @@ -207,6 +217,7 @@ DeleteOrphanCaseNodesTask.progress.lookingForOrphanedCaseZnodes=Looking for orph DeleteOrphanCaseNodesTask.progress.startMessage=Starting orphaned case znode cleanup DeleteOrphanManifestNodesAction.progressDisplayName=Cleanup Manifest File Znodes DeleteOrphanManifestNodesTask.progress.connectingToCoordSvc=Connecting to the coordination service +# {0} - node path DeleteOrphanManifestNodesTask.progress.deletingOrphanedManifestNode=Deleting orphaned manifest file znode {0} DeleteOrphanManifestNodesTask.progress.gettingManifestNodes=Querying the coordination service for manifest file znodes DeleteOrphanManifestNodesTask.progress.lookingForOrphanedManifestFileZnodes=Looking for orphaned manifest file znodes @@ -215,6 +226,7 @@ HINT_CasesDashboardTopComponent=This is an adminstrative dashboard for multi-use OpenAutoIngestLogAction.deletedLogErrorMsg=The case auto ingest log has been deleted. OpenAutoIngestLogAction.logOpenFailedErrorMsg=Failed to open case auto ingest log. See application log for details. OpenAutoIngestLogAction.menuItemText=Open Auto Ingest Log File +# {0} - caseErrorMessage OpenCaseAction.errorMsg=Failed to open case: {0} OpenCaseAction.menuItemText=Open OpenIDE-Module-Long-Description=This module contains features that are being developed by Basis Technology and are not part of the default Autopsy distribution. You can enable this module to use the new features. The features should be stable, but their exact behavior and API are subject to change.\n\nWe make no guarantee that the API of this module will not change, so developers should be careful when relying on it. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties-MERGED b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties-MERGED index 91e2bebd08..337e80b346 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties-MERGED +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties-MERGED @@ -75,6 +75,7 @@ MultiUserTestTool.unableCreatFile=Unable to create a file in case output directo MultiUserTestTool.unableToCheckService=Unable to check Multi User service state: {0} MultiUserTestTool.unableToCreateCase=Unable to create case MultiUserTestTool.unableToInitializeDatabase=Case database was not successfully initialized +MultiUserTestTool.unableToInitializeFilTypeDetector=Unable to initialize File Type Detector MultiUserTestTool.unableToReadDatabase=Unable to read from case database MultiUserTestTool.unableToReadTestFileFromDatabase=Unable to read test file info from case database MultiUserTestTool.unableToRunIngest=Unable to run ingest on test data source diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED index 9aeeabc046..79a4135ce4 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED @@ -36,7 +36,7 @@ KeywordSearchResultFactory.createNodeForKey.noResultsFound.text=No results found KeywordSearchResultFactory.query.exception.msg=Could not perform the query OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\nThe module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. +OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. OpenIDE-Module-Name=KeywordSearch OptionsCategory_Name_KeywordSearchOptions=Keyword Search OptionsCategory_Keywords_KeywordSearchOptions=Keyword Search @@ -360,24 +360,24 @@ DropdownListSearchPanel.jSaveSearchResults.text=Save search results GlobalEditListPanel.ingestWarningLabel.text=Ingest is ongoing, some settings will be unavailable until it finishes. KeywordSearchGlobalLanguageSettingsPanel.ingestWarningLabel.text=Ingest is ongoing, some settings will be unavailable until it finishes. KeywordSearchGlobalSearchSettingsPanel.ingestWarningLabel.text=Ingest is ongoing, some settings will be unavailable until it finishes. -ExtractedContentPanel.hitCountLabel.text=- +ExtractedContentPanel.AccessibleContext.accessibleName= +ExtractedContentPanel.jLabel1.text=Text Source: +ExtractedContentPanel.hitNextButton.text= ExtractedContentPanel.hitPreviousButton.text= +ExtractedContentPanel.hitButtonsLabel.text=Match ExtractedContentPanel.hitTotalLabel.text=- ExtractedContentPanel.hitOfLabel.text=of -ExtractedContentPanel.hitNextButton.text= -ExtractedContentPanel.hitButtonsLabel.text=Match +ExtractedContentPanel.hitCountLabel.text=- ExtractedContentPanel.hitLabel.toolTipText= ExtractedContentPanel.hitLabel.text=Matches on page: -ExtractedContentPanel.pageCurLabel.text=- +ExtractedContentPanel.pageNextButton.text= ExtractedContentPanel.pagePreviousButton.actionCommand=pagePreviousButton ExtractedContentPanel.pagePreviousButton.text= -ExtractedContentPanel.pageNextButton.text= -ExtractedContentPanel.pagesLabel.text=Page: -ExtractedContentPanel.pageTotalLabel.text=- ExtractedContentPanel.pageButtonsLabel.text=Page +ExtractedContentPanel.pageTotalLabel.text=- ExtractedContentPanel.pageOfLabel.text=of -ExtractedContentPanel.jLabel1.text=Text Source: -ExtractedContentPanel.AccessibleContext.accessibleName= +ExtractedContentPanel.pageCurLabel.text=- +ExtractedContentPanel.pagesLabel.text=Page: TextZoomPanel.zoomInButton.text= TextZoomPanel.zoomOutButton.text= TextZoomPanel.zoomResetButton.text=Reset diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED index 310602b0f9..26823e1150 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED @@ -5,10 +5,15 @@ ChromeCacheExtract_adding_artifacts_msg=Chrome Cache: Adding %d artifacts for an ChromeCacheExtract_adding_extracted_files_msg=Chrome Cache: Adding %d extracted files for analysis. ChromeCacheExtract_loading_files_msg=Chrome Cache: Loading files from %s. ChromeCacheExtractor.moduleName=ChromeCacheExtractor +# {0} - module name +# {1} - row number +# {2} - table length +# {3} - cache path ChromeCacheExtractor.progressMsg={0}: Extracting cache entry {1} of {2} entries from {3} DataSourceUsage_AndroidMedia=Android Media Card DataSourceUsage_DJU_Drone_DAT=DJI Internal SD Card DataSourceUsage_FlashDrive=Flash Drive +# {0} - OS name DataSourceUsageAnalyzer.customVolume.label=OS Drive ({0}) DataSourceUsageAnalyzer.parentModuleName=Recent Activity Extract.indexError.message=Failed to index artifact for keyword search. @@ -71,7 +76,7 @@ ExtractZone_progress_Msg=Extracting :Zone.Identifer files ExtractZone_Restricted=Restricted Sites Zone ExtractZone_Trusted=Trusted Sites Zone OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\nThe module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web activity (sites visited, stored cookies, book marked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. +OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\n\The module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web activity (sites visited, stored cookies, book marked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. OpenIDE-Module-Name=RecentActivity OpenIDE-Module-Short-Description=Recent Activity finder ingest module Chrome.moduleName=Chrome @@ -202,6 +207,7 @@ Recently_Used_Artifacts_Officedocs=Recently opened according to Office MRU Recently_Used_Artifacts_Winrar=Recently opened according to WinRAR MRU RegRipperFullNotFound=Full version RegRipper executable not found. RegRipperNotFound=Autopsy RegRipper executable not found. +# {0} - file name SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}. SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine SearchEngineURLQueryAnalyzer.engineName.none=NONE diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index b20ccf5912..b4afb53dd0 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Tue, 12 Nov 2019 17:21:46 -0500 +#Thu, 07 May 2020 12:32:20 -0400 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 4.13.0 +currentVersion=Autopsy 4.15.0 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 998d3f715c..1ebd8cc685 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #Updated by build script -#Tue, 12 Nov 2019 17:21:46 -0500 -CTL_MainWindow_Title=Autopsy 4.13.0 -CTL_MainWindow_Title_No_Project=Autopsy 4.13.0 +#Thu, 07 May 2020 12:32:20 -0400 +CTL_MainWindow_Title=Autopsy 4.15.0 +CTL_MainWindow_Title_No_Project=Autopsy 4.15.0 From f6ed6462a2f6be1c7603e71ff9e36e325a1de53e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 7 May 2020 16:33:27 -0400 Subject: [PATCH 32/90] integrating jsoup --- .../AnnotationsContentViewer.java | 275 ++++++++++-------- 1 file changed, 158 insertions(+), 117 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index c87178bade..907538cc72 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -20,8 +20,14 @@ package org.sleuthkit.autopsy.contentviewers; import java.awt.Component; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.function.Function; import java.util.logging.Level; +import java.util.stream.Collectors; +import javax.swing.JLabel; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringEscapeUtils; @@ -48,6 +54,10 @@ import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.datamodel.BlackboardAttribute; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; + /** * Annotations view of file contents. @@ -77,7 +87,8 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return; } - StringBuilder html = new StringBuilder(); + Document html = Jsoup.parse(EMPTY_HTML); + Element body = html.getElementsByTag("body").first(); BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class); Content sourceFile = null; @@ -104,20 +115,22 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } if (artifact != null) { - populateTagData(html, artifact, sourceFile); + populateTagData(body, artifact, sourceFile); } else { - populateTagData(html, sourceFile); + populateTagData(body, sourceFile); } if (sourceFile instanceof AbstractFile) { - populateCentralRepositoryData(html, artifact, (AbstractFile) sourceFile); - populateFileSetData(html, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT); - populateFileSetData(html, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); + populateCentralRepositoryData(body, artifact, (AbstractFile) sourceFile); + populateFileSetData(body, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT); + populateFileSetData(body, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); } - setText(html.toString()); + jTextPane1.setText(html.html()); jTextPane1.setCaretPosition(0); } + + /** * Populates the html provided with data concerning the source file and @@ -285,9 +298,15 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data * @param sourceFile A selected file, or a source file of the selected * artifact. */ - private void populateCentralRepositoryData(StringBuilder html, BlackboardArtifact artifact, AbstractFile sourceFile) { + @NbBundle.Messages({ + "AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=Case:", + "AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type:", + "AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment:", + "AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path:" + }) + private List populateCentralRepositoryData(StringBuilder html, BlackboardArtifact artifact, AbstractFile sourceFile) { if (CentralRepository.isEnabled()) { - startSection(html, "Central Repository Comments"); + //startSection(html, "Central Repository Comments"); List instancesList = new ArrayList<>(); if (artifact != null) { instancesList.addAll(CorrelationAttributeUtil.makeCorrAttrsForCorrelation(artifact)); @@ -338,38 +357,6 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } } - /** - * Set the text of the text panel. - * - * @param text The text to set to the text panel. - */ - private void setText(String text) { - jTextPane1.setText("" + text + ""); //NON-NLS - } - - /** - * Start a new data section. - * - * @param html The HTML text to add the section to. - * @param sectionName The name of the section. - */ - private void startSection(StringBuilder html, String sectionName) { - html.append("

        ") - .append(sectionName) - .append("


        "); //NON-NLS - } - - /** - * Add a message. - * - * @param html The HTML text to add the message to. - * @param message The message text. - */ - private void addMessage(StringBuilder html, String message) { - html.append("

        ") - .append(message) - .append("


        "); //NON-NLS - } /** * Add a data table containing information about a tag. @@ -390,83 +377,137 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data endTable(html); } - /** - * Add a data table containing information about a correlation attribute - * instance in the Central Repository. - * - * @param html The HTML text to add the table to. - * @param attributeInstance The attribute instance whose information will be - * used to populate the table. - */ - @NbBundle.Messages({ - "AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=Case:", - "AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type:", - "AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment:", - "AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path:" - }) - private void addCentralRepositoryEntry(StringBuilder html, CorrelationAttributeInstance attributeInstance) { - startTable(html); - addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(), attributeInstance.getCorrelationCase().getDisplayName()); - addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_type(), attributeInstance.getCorrelationType().getDisplayName()); - addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_comment(), formatHtmlString(attributeInstance.getComment())); - addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), attributeInstance.getFilePath()); - endTable(html); + + private static final String EMPTY_HTML = ""; + + private static final int DEFAULT_FONT_SIZE = new JLabel().getFont().getSize(); + private static final int SUBHEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 12 / 11; + private static final int HEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 14 / 11; + + private static final String HEADER_STYLE = "font-size:" + HEADER_FONT_SIZE + "px;font-weight:bold;"; + private static final String SUBHEADER_STYLE = "font-size:" + SUBHEADER_FONT_SIZE + "px;font-weight:bold;"; + private static final String MESSAGE_STYLE = "font-size:" + DEFAULT_FONT_SIZE + "px;font-style:italic;"; + private static final String CONTENT_STYLE = "font-size:" + DEFAULT_FONT_SIZE + "px;"; + + private static final int DEFAULT_TABLE_SPACING = DEFAULT_FONT_SIZE * 2; + private static final int DEFAULT_SECTION_SPACING = DEFAULT_FONT_SIZE; + private static final int DEFAULT_SUBSECTION_SPACING = DEFAULT_FONT_SIZE; + + + private static final List> CENTRAL_REPO_COMMENTS = Arrays.asList( + new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(), cai -> cai.getCorrelationCase().getDisplayName()), + new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_type(), cai -> cai.getCorrelationType().getDisplayName()), + new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_comment(), cai -> cai.getComment()), + new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), cai -> cai.getFilePath()) + ); + + private static class ColumnEntry { + private final String columnName; + private final Function valueRetriever; + + ColumnEntry(String columnName, Function valueRetriever) { + this.columnName = columnName; + this.valueRetriever = valueRetriever; + } + + String getColumnName() { + return columnName; + } + + Function getValueRetriever() { + return valueRetriever; + } + + String retrieveValue(T object) { + return valueRetriever.apply(object); + } + } + + private Element appendVerticalEntryTables(Element parent, List items, List> rowHeaders) { + items.stream() + .filter(item -> item != null) + .forEach((item) -> { + List> tableData = rowHeaders.stream() + .map(row -> Arrays.asList(row.getColumnName(), row.retrieveValue(item))) + .collect(Collectors.toList()); + + Element childTable = appendTable(parent, 2, tableData, null); + childTable.attr("style", String.format("margin-bottom: %dpx", DEFAULT_TABLE_SPACING)); + }); + + return parent; + } + + private Element appendEntryTable(Element parent, List items, List> columns) { + int columnNumber = columns.size(); + List columnHeaders = columns.stream().map(c -> c.getColumnName()).collect(Collectors.toList()); + List> rows = items.stream() + .filter(r -> r != null) + .map(r -> { + return columns.stream() + .map(c -> c.retrieveValue(r)) + .collect(Collectors.toList()); + }) + .collect(Collectors.toList()); + + Element table = appendTable(parent, columnNumber, rows, columnHeaders); + table.attr("style", String.format("margin-bottom: %dpx", DEFAULT_TABLE_SPACING)); + return table; + } + + + private Element appendTable(Element parent, int columnNumber, List> content, List columnHeaders) { + Element table = parent.appendElement("table"); + if (columnHeaders != null && !columnHeaders.isEmpty()) { + Element header = parent.appendElement("thead"); + appendRow(header, columnHeaders, columnNumber, true); + } + Element tableBody = table.appendElement("tbody"); + + content.forEach((rowData) -> appendRow(tableBody, rowData, columnNumber, false)); + return table; + } + + // TODO test sanitizing string + private Element appendRow(Element rowParent, List data, int columnNumber, boolean isHeader) { + String cellType = isHeader ? "th" : "td"; + Element row = rowParent.appendElement("tr"); + for (int i = 0; i < columnNumber; i++) { + Element cell = row.appendElement(cellType); + if (data != null && i < data.size()) { + cell.attr("valign", "top"); + cell.attr("style", CONTENT_STYLE); + cell.text(StringUtils.isEmpty(data.get(i)) ? "" : data.get(i)); + } + } + return row; + } + + private Element appendSection(Element parent, String headerText) { + Element parentDiv = parent.appendElement("div"); + parentDiv.attr("style", String.format("margin-bottom: %dpx;", DEFAULT_SECTION_SPACING)); + Element header = parentDiv.appendElement("h1"); + header.text(headerText); + header.attr("style", HEADER_STYLE); + return parentDiv; + } + + private Element appendSubsection(Element parent, String headerText) { + Element parentDiv = parent.appendElement("div"); + parentDiv.attr("style", String.format("margin-bottom: %dpx;", DEFAULT_SUBSECTION_SPACING)); + Element header = parentDiv.appendElement("h2"); + header.text(headerText); + header.attr("style", SUBHEADER_STYLE); + return parentDiv; + } + + private Element appendMessage(Element parent, String message) { + Element messageEl = parent.appendElement("p"); + messageEl.text(message); + messageEl.attr("style", MESSAGE_STYLE); + return messageEl; } - /** - * Start a data table. - * - * @param html The HTML text to add the table to. - */ - private void startTable(StringBuilder html) { - html.append(""); //NON-NLS - } - - /** - * Add a data row to a table. - * - * @param html The HTML text to add the row to. - * @param key The key for the left column of the data row. - * @param value The value for the right column of the data row. - */ - private void addRow(StringBuilder html, String key, String value) { - html.append(""); //NON-NLS - } - - /** - * End a data table. - * - * @param html The HTML text on which to end a table. - */ - private void endTable(StringBuilder html) { - html.append("
        "); //NON-NLS - html.append(key); - html.append(""); //NON-NLS - html.append(value); - html.append("


        "); //NON-NLS - } - - /** - * End a data section. - * - * @param html The HTML text on which to end a section. - */ - private void endSection(StringBuilder html) { - html.append("
        "); //NON-NLS - } - - /** - * Apply escape sequence to special characters. Line feed and carriage - * return character combinations will be converted to HTML line breaks. - * - * @param text The text to format. - * - * @return The formatted text. - */ - private String formatHtmlString(String text) { - String formattedString = StringEscapeUtils.escapeHtml4(text); - return formattedString.replaceAll("(\r\n|\r|\n|\n\r)", "
        "); - } /** * This method is called from within the constructor to initialize the form. @@ -554,6 +595,6 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data @Override public void resetComponent() { - setText(""); + jTextPane1.setText(EMPTY_HTML); } } From 9fbf13649a33de17fe2e9577a4deadb21c029d63 Mon Sep 17 00:00:00 2001 From: apriestman Date: Fri, 8 May 2020 09:37:10 -0400 Subject: [PATCH 33/90] Add max number of images to preload and an exception firewall. --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 47fff7320f..d9d369cb2c 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -2060,6 +2060,7 @@ public class Case { private final SleuthkitCase tskCase; private final String caseName; + private final long MAX_IMAGE_THRESHOLD = 100; private final ProgressIndicator progressIndicator; /** @@ -2153,6 +2154,13 @@ public class Case { if (images == null) { return; } + + if (images.size() > MAX_IMAGE_THRESHOLD) { + // If we have a large number of images, don't try to preload anything + logger.log( + Level.INFO, + String.format("Skipping background load of file systems due to large number of images in case (%d)", images.size())); + } checkIfCancelled(); openFileSystems(images); @@ -2160,6 +2168,9 @@ public class Case { logger.log( Level.INFO, String.format("Background operation opening all file systems in %s has been cancelled.", caseName)); + } catch (Exception ex) { + // Exception firewall + logger.log(Level.WARNING, "Error while opening file systems in background", ex); } } From b0373a7e612dacedf170a7b73de5203c4cec0ea6 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 8 May 2020 10:46:27 -0400 Subject: [PATCH 34/90] refactoring --- .../AnnotationsContentViewer.java | 574 +++++++++--------- 1 file changed, 279 insertions(+), 295 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index 907538cc72..bc8ef25642 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -31,7 +31,7 @@ import javax.swing.JLabel; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringEscapeUtils; -import org.openide.util.NbBundle; +import static org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; import org.openide.nodes.Node; import org.openide.util.lookup.ServiceProvider; @@ -58,20 +58,101 @@ import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; - /** * Annotations view of file contents. */ @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives @ServiceProvider(service = DataContentViewer.class, position = 8) -@NbBundle.Messages({ +@Messages({ "AnnotationsContentViewer.title=Annotations", - "AnnotationsContentViewer.toolTip=Displays tags and comments associated with the selected content." + "AnnotationsContentViewer.toolTip=Displays tags and comments associated with the selected content.", + "AnnotationsContentViewer.centralRepositoryEntry.title=Central Repository Comments", + "AnnotationsContentViewer.centralRepositoryEntry.onEmpty=There is no comment data for the selected content in the Central Repository.", + "AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=Case:", + "AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type:", + "AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment:", + "AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path:", + "AnnotationsContentViewer.tagEntry.title=Tag Comments", + "AnnotationsContentViewer.tagEntry.onContentEmpty=There are no tags for the selected content.", + "AnnotationsContentViewer.tagEntry.onArtifactEmpty=There are no tags for the selected artifact.", + "AnnotationsContentViewer.tagEntryDataLabel.tag=Tag:", + "AnnotationsContentViewer.tagEntryDataLabel.tagUser=Examiner:", + "AnnotationsContentViewer.tagEntryDataLabel.comment=Comment:", + "AnnotationsContentViewer.fileHitEntry.hashSetHitTitle=Hash Set Hit Comments", + "AnnotationsContentViewer.fileHitEntry.onHashSetHitEmpty=There are no hash set hits for the selected content.", + "AnnotationsContentViewer.fileHitEntry.interestingFileHitTitle=Interesting File Hit Comments", + "AnnotationsContentViewer.fileHitEntry.onInterestingFileHitEmpty=There are no interesting file hits for the selected content.", + "AnnotationsContentViewer.fileHitEntry.setName=Set Name", + "AnnotationsContentViewer.fileHitEntry.comment=Comment", + "AnnotationsContentViewer.sourceFile.title=Source File" }) public class AnnotationsContentViewer extends javax.swing.JPanel implements DataContentViewer { private static final Logger logger = Logger.getLogger(AnnotationsContentViewer.class.getName()); + private static final String EMPTY_HTML = ""; + + private static final int DEFAULT_FONT_SIZE = new JLabel().getFont().getSize(); + private static final int SUBHEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 12 / 11; + private static final int HEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 14 / 11; + + private static final int DEFAULT_SUBSECTION_LEFT_PAD = DEFAULT_FONT_SIZE; + + private static final String HEADER_STYLE = "font-size:" + HEADER_FONT_SIZE + "px;font-weight:bold;"; + private static final String SUBHEADER_STYLE = "font-size:" + SUBHEADER_FONT_SIZE + "px;font-weight:bold;"; + private static final String MESSAGE_STYLE = "font-size:" + DEFAULT_FONT_SIZE + "px;font-style:italic;"; + private static final String CONTENT_STYLE = "font-size:" + DEFAULT_FONT_SIZE + "px;"; + + private static final int DEFAULT_TABLE_SPACING = DEFAULT_FONT_SIZE * 2; + private static final int DEFAULT_SECTION_SPACING = DEFAULT_FONT_SIZE; + private static final int DEFAULT_SUBSECTION_SPACING = DEFAULT_FONT_SIZE; + + private static final List> TAG_COLUMNS = Arrays.asList( + new ColumnEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_tag(), + (tag) -> (tag.getName() != null) ? tag.getName().getDisplayName() : null), + new ColumnEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_tagUser(), (tag) -> tag.getUserName()), + new ColumnEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_comment(), (tag) -> tag.getComment()) + ); + + private static final List> FILESET_HIT_COLUMNS = Arrays.asList( + new ColumnEntry<>(Bundle.AnnotationsContentViewer_fileHitEntry_setName(), + (bba) -> tryGetAttribute(bba, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)), + new ColumnEntry<>(Bundle.AnnotationsContentViewer_fileHitEntry_comment(), + (bba) -> tryGetAttribute(bba, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT)) + ); + + private static final List> CENTRAL_REPO_COMMENTS_COLUMNS = Arrays.asList( + new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(), + cai -> (cai.getCorrelationCase() != null) ? cai.getCorrelationCase().getDisplayName() : null), + new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_type(), + cai -> (cai.getCorrelationType() != null) ? cai.getCorrelationType().getDisplayName() : null), + new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_comment(), cai -> cai.getComment()), + new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), cai -> cai.getFilePath()) + ); + + private static class ColumnEntry { + + private final String columnName; + private final Function valueRetriever; + + ColumnEntry(String columnName, Function valueRetriever) { + this.columnName = columnName; + this.valueRetriever = valueRetriever; + } + + String getColumnName() { + return columnName; + } + + Function getValueRetriever() { + return valueRetriever; + } + + String retrieveValue(T object) { + return valueRetriever.apply(object); + } + } + /** * Creates an instance of AnnotationsContentViewer. */ @@ -115,54 +196,121 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } if (artifact != null) { - populateTagData(body, artifact, sourceFile); + renderArtifact(body, artifact, sourceFile); } else { - populateTagData(body, sourceFile); - } - - if (sourceFile instanceof AbstractFile) { - populateCentralRepositoryData(body, artifact, (AbstractFile) sourceFile); - populateFileSetData(body, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT); - populateFileSetData(body, sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); + renderAbstractFile(body, sourceFile, false); } jTextPane1.setText(html.html()); jTextPane1.setCaretPosition(0); } - - - /** - * Populates the html provided with data concerning the source file and - * whether it appears in a file set. - * - * @param html The html to append information. - * @param content The source content to check for blackboard artifacts. - * @param artifactType The artifact type to check for. - */ - private void populateFileSetData(StringBuilder html, Content content, BlackboardArtifact.ARTIFACT_TYPE artifactType) { - String artifactTypeName = artifactType.getDisplayName(); + private static void renderArtifact(Element parent, BlackboardArtifact bba, Content sourceContent) { + appendEntries(parent, + Bundle.AnnotationsContentViewer_tagEntry_title(), + Bundle.AnnotationsContentViewer_tagEntry_onArtifactEmpty(), + getTags(bba), TAG_COLUMNS, false, true); + if (sourceContent instanceof AbstractFile) { + AbstractFile sourceFile = (AbstractFile) sourceContent; + + if (CentralRepository.isEnabled()) { + List centralRepoComments = getCentralRepositoryData(bba, sourceFile); + appendEntries(parent, + Bundle.AnnotationsContentViewer_centralRepositoryEntry_title(), + Bundle.AnnotationsContentViewer_centralRepositoryEntry_onEmpty(), + centralRepoComments, CENTRAL_REPO_COMMENTS_COLUMNS, false, true); + } + } + + if (BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == bba.getArtifactTypeID()) { + appendEntries(parent, + Bundle.AnnotationsContentViewer_fileHitEntry_hashSetHitTitle(), + Bundle.AnnotationsContentViewer_fileHitEntry_onHashSetHitEmpty(), + Arrays.asList(bba), FILESET_HIT_COLUMNS, false, false); + } + + if (BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID()) { + appendEntries(parent, + Bundle.AnnotationsContentViewer_fileHitEntry_interestingFileHitTitle(), + Bundle.AnnotationsContentViewer_fileHitEntry_onInterestingFileHitEmpty(), + Arrays.asList(bba), FILESET_HIT_COLUMNS, false, false); + } + + Element sourceFileSection = appendSection(parent, Bundle.AnnotationsContentViewer_sourceFile_title()); + renderAbstractFile(sourceFileSection, sourceContent, true); + } + + private static void renderAbstractFile(Element parent, Content sourceContent, boolean isSubheader) { + appendEntries(parent, + Bundle.AnnotationsContentViewer_tagEntry_title(), + Bundle.AnnotationsContentViewer_tagEntry_onContentEmpty(), + getTags(sourceContent), TAG_COLUMNS, isSubheader, true); + + if (sourceContent instanceof AbstractFile) { + AbstractFile sourceFile = (AbstractFile) sourceContent; + + if (CentralRepository.isEnabled()) { + List centralRepoComments = getCentralRepositoryData(null, sourceFile); + appendEntries(parent, + Bundle.AnnotationsContentViewer_centralRepositoryEntry_title(), + Bundle.AnnotationsContentViewer_centralRepositoryEntry_onEmpty(), + centralRepoComments, CENTRAL_REPO_COMMENTS_COLUMNS, isSubheader, true); + } + + appendEntries(parent, + Bundle.AnnotationsContentViewer_fileHitEntry_hashSetHitTitle(), + Bundle.AnnotationsContentViewer_fileHitEntry_onHashSetHitEmpty(), + getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT), + FILESET_HIT_COLUMNS, isSubheader, false); + + appendEntries(parent, + Bundle.AnnotationsContentViewer_fileHitEntry_interestingFileHitTitle(), + Bundle.AnnotationsContentViewer_fileHitEntry_onInterestingFileHitEmpty(), + getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT), + FILESET_HIT_COLUMNS, isSubheader, false); + } + + } + + private static List getTags(Content sourceContent) { try { SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - - startSection(html, artifactTypeName); - List fileHitInfo = tskCase.getBlackboardArtifacts(artifactType, content.getId()); - if (fileHitInfo.isEmpty()) { - addMessage(html, String.format("There are no %s for the selected content.", artifactTypeName)); - } else { - fileHitInfo.forEach((fileHit) -> { - addFileHitEntry(html, fileHit); - }); - } - endSection(html); + return tskCase.getContentTagsByContent(sourceContent); } catch (NoCurrentCaseException ex) { logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS } + return new ArrayList<>(); } + private static List getTags(BlackboardArtifact bba) { + try { + SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + return tskCase.getBlackboardArtifactTagsByArtifact(bba); + } catch (NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS + } + return new ArrayList<>(); + } + + private static List getFileSetHits(AbstractFile sourceFile, BlackboardArtifact.ARTIFACT_TYPE type) { + try { + SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + return tskCase.getBlackboardArtifacts(type, sourceFile.getId()); + } catch (NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Exception while getting file set hits from the case database.", ex); //NON-NLS + } + return new ArrayList<>(); + } + + + /** * Attempts to retrieve the attribute of a particular type from a blackboard * artifact. @@ -172,7 +320,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data * * @return The string value of the attribute or null if not found. */ - private String tryGetAttribute(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE attributeType) { + private static String tryGetAttribute(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE attributeType) { if (artifact == null) { return null; } @@ -191,285 +339,122 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return attr.getValueString(); } - /** - * Add a data table containing information about an file set hit artifact - * (i.e. hash hit). - * - * @param html The HTML text to add the table to. - * @param tag The blackboard artifact with hash hit information whose - * information will be used to populate the table. - */ - @NbBundle.Messages({ - "AnnotationsContentViewer.addHashHitEntry.hashSet=Hash Set:", - "AnnotationsContentViewer.addHashHitEntry.comment=Comment:" - }) - private void addFileHitEntry(StringBuilder html, BlackboardArtifact artifact) { - startTable(html); - - String hashset = tryGetAttribute(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME); - String comment = tryGetAttribute(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT); - - if (StringUtils.isNotBlank(hashset)) { - addRow(html, Bundle.AnnotationsContentViewer_addHashHitEntry_hashSet(), hashset); - } - - if (StringUtils.isNotBlank(comment)) { - addRow(html, Bundle.AnnotationsContentViewer_tagEntryDataLabel_comment(), comment); - } - - endTable(html); - } - - /** - * Populate the "Selected Item" sections with tag data for the supplied - * content. - * - * @param html The HTML text to update. - * @param content Selected content. - */ - private void populateTagData(StringBuilder html, Content content) { - try { - SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - - startSection(html, "Selected Item"); - List fileTagsList = tskCase.getContentTagsByContent(content); - if (fileTagsList.isEmpty()) { - addMessage(html, "There are no tags for the selected content."); - } else { - for (ContentTag tag : fileTagsList) { - addTagEntry(html, tag); - } - } - endSection(html); - } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS - } - } - - /** - * Populate the "Selected Item" and "Source File" sections with tag data for - * a supplied artifact. - * - * @param html The HTML text to update. - * @param artifact A selected artifact. - * @param sourceFile The source content of the selected artifact. - */ - private void populateTagData(StringBuilder html, BlackboardArtifact artifact, Content sourceFile) { - try { - SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - - startSection(html, "Selected Item"); - List artifactTagsList = tskCase.getBlackboardArtifactTagsByArtifact(artifact); - if (artifactTagsList.isEmpty()) { - addMessage(html, "There are no tags for the selected artifact."); - } else { - for (BlackboardArtifactTag tag : artifactTagsList) { - addTagEntry(html, tag); - } - } - endSection(html); - - if (sourceFile != null) { - startSection(html, "Source File"); - List fileTagsList = tskCase.getContentTagsByContent(sourceFile); - if (fileTagsList.isEmpty()) { - addMessage(html, "There are no tags for the source content."); - } else { - for (ContentTag tag : fileTagsList) { - addTagEntry(html, tag); - } - } - endSection(html); - } - } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS - } - } - /** * Populate the "Central Repository Comments" section with data. * - * @param html The HTML text to update. * @param artifact A selected artifact (can be null). * @param sourceFile A selected file, or a source file of the selected * artifact. */ - @NbBundle.Messages({ - "AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=Case:", - "AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type:", - "AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment:", - "AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path:" - }) - private List populateCentralRepositoryData(StringBuilder html, BlackboardArtifact artifact, AbstractFile sourceFile) { - if (CentralRepository.isEnabled()) { - //startSection(html, "Central Repository Comments"); - List instancesList = new ArrayList<>(); - if (artifact != null) { - instancesList.addAll(CorrelationAttributeUtil.makeCorrAttrsForCorrelation(artifact)); - } - try { - List artifactTypes = CentralRepository.getInstance().getDefinedCorrelationTypes(); - String md5 = sourceFile.getMd5Hash(); - if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) { - for (CorrelationAttributeInstance.Type attributeType : artifactTypes) { - if (attributeType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) { - CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCase()); - instancesList.add(new CorrelationAttributeInstance( - attributeType, - md5, - correlationCase, - CorrelationDataSource.fromTSKDataSource(correlationCase, sourceFile.getDataSource()), - sourceFile.getParentPath() + sourceFile.getName(), - "", - sourceFile.getKnown(), - sourceFile.getId())); - break; - } + private static List getCentralRepositoryData(BlackboardArtifact artifact, AbstractFile sourceFile) { + List toReturn = new ArrayList<>(); + + List instancesList = new ArrayList<>(); + if (artifact != null) { + instancesList.addAll(CorrelationAttributeUtil.makeCorrAttrsForCorrelation(artifact)); + } + + try { + List artifactTypes = CentralRepository.getInstance().getDefinedCorrelationTypes(); + String md5 = sourceFile.getMd5Hash(); + if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) { + for (CorrelationAttributeInstance.Type attributeType : artifactTypes) { + if (attributeType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) { + CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCase()); + instancesList.add(new CorrelationAttributeInstance( + attributeType, + md5, + correlationCase, + CorrelationDataSource.fromTSKDataSource(correlationCase, sourceFile.getDataSource()), + sourceFile.getParentPath() + sourceFile.getName(), + "", + sourceFile.getKnown(), + sourceFile.getId())); + break; } } + } - boolean commentDataFound = false; - - for (CorrelationAttributeInstance instance : instancesList) { - List correlatedInstancesList - = CentralRepository.getInstance().getArtifactInstancesByTypeValue(instance.getCorrelationType(), instance.getCorrelationValue()); - for (CorrelationAttributeInstance correlatedInstance : correlatedInstancesList) { - if (correlatedInstance.getComment() != null && correlatedInstance.getComment().isEmpty() == false) { - commentDataFound = true; - addCentralRepositoryEntry(html, correlatedInstance); - } + for (CorrelationAttributeInstance instance : instancesList) { + List correlatedInstancesList + = CentralRepository.getInstance().getArtifactInstancesByTypeValue(instance.getCorrelationType(), instance.getCorrelationValue()); + for (CorrelationAttributeInstance correlatedInstance : correlatedInstancesList) { + if (StringUtils.isNotEmpty(correlatedInstance.getComment())) { + toReturn.add(correlatedInstance); } } - - if (commentDataFound == false) { - addMessage(html, "There is no comment data for the selected content in the Central Repository."); - } - } catch (CentralRepoException | TskCoreException ex) { - logger.log(Level.SEVERE, "Error connecting to the Central Repository database.", ex); // NON-NLS - } catch (CorrelationAttributeNormalizationException ex) { - logger.log(Level.SEVERE, "Error normalizing instance from Central Repository database.", ex); // NON-NLS } - endSection(html); + + } catch (CentralRepoException | TskCoreException ex) { + logger.log(Level.SEVERE, "Error connecting to the Central Repository database.", ex); // NON-NLS + } catch (CorrelationAttributeNormalizationException ex) { + logger.log(Level.SEVERE, "Error normalizing instance from Central Repository database.", ex); // NON-NLS + } + + return toReturn; + } + + + private static void appendEntries(Element parent, String title, String errorMessage, List items, + List> fields, boolean isSubsection, boolean isVerticalTable) { + + Element sectionDiv = (isSubsection) ? appendSubsection(parent, title) : appendSection(parent, title); + + if (items == null || items.isEmpty()) { + appendMessage(sectionDiv, errorMessage); + } else if (isVerticalTable) { + appendVerticalEntryTables(sectionDiv, items, fields); + } else { + appendEntryTable(sectionDiv, items, fields); } } - - /** - * Add a data table containing information about a tag. - * - * @param html The HTML text to add the table to. - * @param tag The tag whose information will be used to populate the table. - */ - @NbBundle.Messages({ - "AnnotationsContentViewer.tagEntryDataLabel.tag=Tag:", - "AnnotationsContentViewer.tagEntryDataLabel.tagUser=Tag User:", - "AnnotationsContentViewer.tagEntryDataLabel.comment=Comment:" - }) - private void addTagEntry(StringBuilder html, Tag tag) { - startTable(html); - addRow(html, Bundle.AnnotationsContentViewer_tagEntryDataLabel_tag(), tag.getName().getDisplayName()); - addRow(html, Bundle.AnnotationsContentViewer_tagEntryDataLabel_tagUser(), tag.getUserName()); - addRow(html, Bundle.AnnotationsContentViewer_tagEntryDataLabel_comment(), formatHtmlString(tag.getComment())); - endTable(html); - } - - - private static final String EMPTY_HTML = ""; - - private static final int DEFAULT_FONT_SIZE = new JLabel().getFont().getSize(); - private static final int SUBHEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 12 / 11; - private static final int HEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 14 / 11; - - private static final String HEADER_STYLE = "font-size:" + HEADER_FONT_SIZE + "px;font-weight:bold;"; - private static final String SUBHEADER_STYLE = "font-size:" + SUBHEADER_FONT_SIZE + "px;font-weight:bold;"; - private static final String MESSAGE_STYLE = "font-size:" + DEFAULT_FONT_SIZE + "px;font-style:italic;"; - private static final String CONTENT_STYLE = "font-size:" + DEFAULT_FONT_SIZE + "px;"; - - private static final int DEFAULT_TABLE_SPACING = DEFAULT_FONT_SIZE * 2; - private static final int DEFAULT_SECTION_SPACING = DEFAULT_FONT_SIZE; - private static final int DEFAULT_SUBSECTION_SPACING = DEFAULT_FONT_SIZE; - - - private static final List> CENTRAL_REPO_COMMENTS = Arrays.asList( - new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(), cai -> cai.getCorrelationCase().getDisplayName()), - new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_type(), cai -> cai.getCorrelationType().getDisplayName()), - new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_comment(), cai -> cai.getComment()), - new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), cai -> cai.getFilePath()) - ); - - private static class ColumnEntry { - private final String columnName; - private final Function valueRetriever; - - ColumnEntry(String columnName, Function valueRetriever) { - this.columnName = columnName; - this.valueRetriever = valueRetriever; - } - - String getColumnName() { - return columnName; - } - - Function getValueRetriever() { - return valueRetriever; - } - - String retrieveValue(T object) { - return valueRetriever.apply(object); - } - } - - private Element appendVerticalEntryTables(Element parent, List items, List> rowHeaders) { + private static Element appendVerticalEntryTables(Element parent, List items, List> rowHeaders) { items.stream() - .filter(item -> item != null) - .forEach((item) -> { - List> tableData = rowHeaders.stream() - .map(row -> Arrays.asList(row.getColumnName(), row.retrieveValue(item))) - .collect(Collectors.toList()); - - Element childTable = appendTable(parent, 2, tableData, null); - childTable.attr("style", String.format("margin-bottom: %dpx", DEFAULT_TABLE_SPACING)); - }); - + .filter(item -> item != null) + .forEach((item) -> { + List> tableData = rowHeaders.stream() + .map(row -> Arrays.asList(row.getColumnName(), row.retrieveValue(item))) + .collect(Collectors.toList()); + + Element childTable = appendTable(parent, 2, tableData, null); + childTable.attr("style", String.format("margin-bottom: %dpx", DEFAULT_TABLE_SPACING)); + }); + return parent; } - - private Element appendEntryTable(Element parent, List items, List> columns) { + + private static Element appendEntryTable(Element parent, List items, List> columns) { int columnNumber = columns.size(); List columnHeaders = columns.stream().map(c -> c.getColumnName()).collect(Collectors.toList()); List> rows = items.stream() - .filter(r -> r != null) - .map(r -> { - return columns.stream() - .map(c -> c.retrieveValue(r)) - .collect(Collectors.toList()); - }) - .collect(Collectors.toList()); - + .filter(r -> r != null) + .map(r -> { + return columns.stream() + .map(c -> c.retrieveValue(r)) + .collect(Collectors.toList()); + }) + .collect(Collectors.toList()); + Element table = appendTable(parent, columnNumber, rows, columnHeaders); table.attr("style", String.format("margin-bottom: %dpx", DEFAULT_TABLE_SPACING)); return table; } - - - private Element appendTable(Element parent, int columnNumber, List> content, List columnHeaders) { + + private static Element appendTable(Element parent, int columnNumber, List> content, List columnHeaders) { Element table = parent.appendElement("table"); if (columnHeaders != null && !columnHeaders.isEmpty()) { Element header = parent.appendElement("thead"); - appendRow(header, columnHeaders, columnNumber, true); + appendRow(header, columnHeaders, columnNumber, true); } Element tableBody = table.appendElement("tbody"); - + content.forEach((rowData) -> appendRow(tableBody, rowData, columnNumber, false)); return table; } - + // TODO test sanitizing string - private Element appendRow(Element rowParent, List data, int columnNumber, boolean isHeader) { + private static Element appendRow(Element rowParent, List data, int columnNumber, boolean isHeader) { String cellType = isHeader ? "th" : "td"; Element row = rowParent.appendElement("tr"); for (int i = 0; i < columnNumber; i++) { @@ -482,33 +467,32 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } return row; } - - private Element appendSection(Element parent, String headerText) { - Element parentDiv = parent.appendElement("div"); - parentDiv.attr("style", String.format("margin-bottom: %dpx;", DEFAULT_SECTION_SPACING)); - Element header = parentDiv.appendElement("h1"); + + private static Element appendSection(Element parent, String headerText) { + Element sectionDiv = parent.appendElement("div"); + sectionDiv.attr("style", String.format("margin-bottom: %dpx;", DEFAULT_SECTION_SPACING)); + Element header = sectionDiv.appendElement("h1"); header.text(headerText); header.attr("style", HEADER_STYLE); - return parentDiv; + return sectionDiv; } - - private Element appendSubsection(Element parent, String headerText) { - Element parentDiv = parent.appendElement("div"); - parentDiv.attr("style", String.format("margin-bottom: %dpx;", DEFAULT_SUBSECTION_SPACING)); - Element header = parentDiv.appendElement("h2"); + + private static Element appendSubsection(Element parent, String headerText) { + Element subsectionDiv = parent.appendElement("div"); + subsectionDiv.attr("style", String.format("margin-bottom: %dpx; padding-left: %dpx;", DEFAULT_SUBSECTION_SPACING, DEFAULT_SUBSECTION_LEFT_PAD)); + Element header = subsectionDiv.appendElement("h2"); header.text(headerText); header.attr("style", SUBHEADER_STYLE); - return parentDiv; + return subsectionDiv; } - - private Element appendMessage(Element parent, String message) { + + private static Element appendMessage(Element parent, String message) { Element messageEl = parent.appendElement("p"); messageEl.text(message); messageEl.attr("style", MESSAGE_STYLE); return messageEl; } - /** * 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 From 51639a09680a043978e57206d70968935067b748 Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Fri, 8 May 2020 10:46:43 -0400 Subject: [PATCH 35/90] 6323 Address codacy --- .../org/sleuthkit/autopsy/persona/OpenPersonasAction.java | 2 -- .../org/sleuthkit/autopsy/persona/PersonasTopComponent.java | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java b/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java index d9e52349df..157b25d1cc 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java +++ b/Core/src/org/sleuthkit/autopsy/persona/OpenPersonasAction.java @@ -28,7 +28,6 @@ import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; -import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; /** @@ -43,7 +42,6 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined; public final class OpenPersonasAction extends CallableSystemAction { private static final long serialVersionUID = 1L; - private static final Logger logger = Logger.getLogger(OpenPersonasAction.class.getName()); private final JMenuItem menuItem; diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java index a88d66faa0..8ad405abd3 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java @@ -22,7 +22,10 @@ import org.openide.util.NbBundle.Messages; import org.openide.windows.RetainLocation; import org.openide.windows.TopComponent; - +/** + * Top component for the Personas tool + * + */ @TopComponent.Description(preferredID = "PersonasTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER) @TopComponent.Registration(mode = "personas", openAtStartup = false) @RetainLocation("personas") From 278cfd0817d8bc2ed43655d3898654c76515e0da Mon Sep 17 00:00:00 2001 From: apriestman Date: Fri, 8 May 2020 11:29:42 -0400 Subject: [PATCH 36/90] Use new version of getImageFileSystems. Stop trying to read if a read fails. --- .../org/sleuthkit/autopsy/casemodule/Case.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index d9d369cb2c..9ce6b62094 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -2118,28 +2118,18 @@ public class Case { * event that the operation is * cancelled prior to completion. */ - private void openFileSystems(List images) throws InterruptedException { + private void openFileSystems(List images) throws TskCoreException, InterruptedException { byte[] tempBuff = new byte[512]; - + for (Image image : images) { String imageStr = image.getName(); progressIndicator.progress(Bundle.Case_openFileSystems_openingImage(imageStr)); - Collection fileSystems = this.tskCase.getFileSystems(image); + Collection fileSystems = this.tskCase.getImageFileSystems(image); checkIfCancelled(); for (FileSystem fileSystem : fileSystems) { - try { - fileSystem.read(tempBuff, 0, 512); - } catch (TskCoreException ex) { - String fileSysStr = fileSystem.getName(); - - logger.log( - Level.WARNING, - String.format("Could not open filesystem: %s in image: %s for case: %s.", fileSysStr, imageStr, caseName), - ex); - } - + fileSystem.read(tempBuff, 0, 512); checkIfCancelled(); } From 474b314d4a202ab5dfc8b8e5c0e930c946651c23 Mon Sep 17 00:00:00 2001 From: apriestman Date: Fri, 8 May 2020 11:39:25 -0400 Subject: [PATCH 37/90] Forgot to return if number of images is over the threshold --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 9ce6b62094..0147f31750 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -2150,6 +2150,7 @@ public class Case { logger.log( Level.INFO, String.format("Skipping background load of file systems due to large number of images in case (%d)", images.size())); + return; } checkIfCancelled(); From cda026869e665a159b3b75235b3d48d87ce195e3 Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Fri, 8 May 2020 14:17:17 -0400 Subject: [PATCH 38/90] 6354 First steps to name search --- .../autopsy/persona/Bundle.properties | 10 +- .../autopsy/persona/PersonasTopComponent.form | 580 +++++++++--------- .../autopsy/persona/PersonasTopComponent.java | 85 ++- .../netbeans/core/startup/Bundle.properties | 4 +- .../core/windows/view/ui/Bundle.properties | 6 +- 5 files changed, 360 insertions(+), 325 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties b/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties index de9095c342..214677936e 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties @@ -4,11 +4,11 @@ CTL_PersonasTopComponent=Personas PersonasTopComponent.jTextField1.text=John Doe PersonasTopComponent.jRadioButton1.text=Name PersonasTopComponent.jRadioButton2.text=Account -PersonasTopComponent.jLabel2.text=Name: -PersonasTopComponent.jTextField2.text=Johnathan Dough -PersonasTopComponent.jLabel3.text=Aliases: -PersonasTopComponent.jLabel4.text=Accounts: -PersonasTopComponent.jLabel5.text=Cases found in: PersonasTopComponent.jTable2.columnModel.title0=ID PersonasTopComponent.jTable2.columnModel.title1=Name PersonasTopComponent.jButton1.text=Search +PersonasTopComponent.jLabel2.text=Name: +PersonasTopComponent.jLabel5.text=Cases found in: +PersonasTopComponent.jLabel4.text=Accounts: +PersonasTopComponent.jLabel3.text=Aliases: +PersonasTopComponent.jTextField2.text=Johnathan Dough diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form index 16eaf6ecbb..a6d69d58bf 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form @@ -21,7 +21,7 @@ --> -
        + @@ -48,321 +48,333 @@ - - - - - + - - + - + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - - - - - - - - - - -
        -
        - - - - - <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonasTopComponent.jTable2.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - - - - - - - <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonasTopComponent.jTable2.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - - - - - - - - + +
        -
        -
        - - - - - - - -
        -
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - -
        + + + + + + + +
        + + + +
        + + + + + + + -
        -
        - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + +
        +
        + + + + + <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonasTopComponent.jTable2.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonasTopComponent.jTable2.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + + + +
        +
        +
        +
        + + + + + +
        - - - - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        +
        +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java index bd87905204..1a872fc8ed 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java @@ -18,9 +18,12 @@ */ package org.sleuthkit.autopsy.persona; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import org.openide.util.NbBundle.Messages; import org.openide.windows.RetainLocation; import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; /** * Top component for the Personas tool @@ -38,6 +41,23 @@ public final class PersonasTopComponent extends TopComponent { public PersonasTopComponent() { initComponents(); setName(Bundle.PTopComponent_Name()); + + jButton1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + executeSearch(); + } + }); + } + + void executeSearch() { + System.out.println("Search!"); + } + + @Override + public void componentOpened() { + super.componentOpened(); + WindowManager.getDefault().setTopComponentFloating(this, true); } /** @@ -50,6 +70,7 @@ public final class PersonasTopComponent extends TopComponent { buttonGroup1 = new javax.swing.ButtonGroup(); jDesktopPane1 = new javax.swing.JDesktopPane(); + jSplitPane2 = new javax.swing.JSplitPane(); jPanel1 = new javax.swing.JPanel(); jTextField1 = new javax.swing.JTextField(); jRadioButton1 = new javax.swing.JRadioButton(); @@ -75,6 +96,7 @@ public final class PersonasTopComponent extends TopComponent { jTextField1.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jTextField1.text")); // NOI18N buttonGroup1.add(jRadioButton1); + jRadioButton1.setSelected(true); org.openide.awt.Mnemonics.setLocalizedText(jRadioButton1, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jRadioButton1.text")); // NOI18N jRadioButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -117,20 +139,22 @@ public final class PersonasTopComponent extends TopComponent { jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addComponent(jTextField1, javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTextField1) .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(jRadioButton1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jRadioButton2)) - .addComponent(jButton1)) - .addGap(0, 63, Short.MAX_VALUE))) - .addContainerGap()) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jRadioButton1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jRadioButton2)) + .addComponent(jButton1)) + .addGap(0, 25, Short.MAX_VALUE))) + .addContainerGap()))) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -148,6 +172,8 @@ public final class PersonasTopComponent extends TopComponent { .addContainerGap()) ); + jSplitPane2.setLeftComponent(jPanel1); + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jLabel2.text")); // NOI18N jTextField2.setEditable(false); @@ -210,22 +236,20 @@ public final class PersonasTopComponent extends TopComponent { jPanel2.setLayout(jPanel2Layout); jPanel2Layout.setHorizontalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel2Layout.createSequentialGroup() + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() .addContainerGap() - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addGroup(jPanel2Layout.createSequentialGroup() - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(jScrollPane5) - .addComponent(jScrollPane3) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel2Layout.createSequentialGroup() - .addComponent(jLabel2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 299, Short.MAX_VALUE)) - .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jLabel4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap()))) + .addComponent(jScrollPane5) + .addComponent(jScrollPane3) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel2Layout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)) + .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jLabel4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) ); jPanel2Layout.setVerticalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -245,23 +269,21 @@ public final class PersonasTopComponent extends TopComponent { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jLabel5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 63, Short.MAX_VALUE) + .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 68, Short.MAX_VALUE) .addContainerGap()) ); + jSplitPane2.setRightComponent(jPanel2); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jSplitPane2) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jSplitPane2) ); }// //GEN-END:initComponents @@ -291,6 +313,7 @@ public final class PersonasTopComponent extends TopComponent { private javax.swing.JScrollPane jScrollPane3; private javax.swing.JScrollPane jScrollPane4; private javax.swing.JScrollPane jScrollPane5; + private javax.swing.JSplitPane jSplitPane2; private javax.swing.JTable jTable1; private javax.swing.JTable jTable2; private javax.swing.JTextField jTextField1; diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index b20ccf5912..42ff0c5da4 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Tue, 12 Nov 2019 17:21:46 -0500 +#Fri, 08 May 2020 11:13:24 -0400 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 4.13.0 +currentVersion=Autopsy 4.15.0 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 998d3f715c..7a54b6f1f2 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #Updated by build script -#Tue, 12 Nov 2019 17:21:46 -0500 -CTL_MainWindow_Title=Autopsy 4.13.0 -CTL_MainWindow_Title_No_Project=Autopsy 4.13.0 +#Fri, 08 May 2020 11:13:24 -0400 +CTL_MainWindow_Title=Autopsy 4.15.0 +CTL_MainWindow_Title_No_Project=Autopsy 4.15.0 From 54c0eb6f62a55798e3210563699eaf82c0cd2d81 Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Fri, 8 May 2020 14:18:02 -0400 Subject: [PATCH 39/90] 6336 Ui changes --- .../autopsy/persona/PersonasTopComponent.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java index 1a872fc8ed..e78afa9a17 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java @@ -34,26 +34,15 @@ import org.openide.windows.WindowManager; @RetainLocation("personas") @SuppressWarnings("PMD.SingularField") public final class PersonasTopComponent extends TopComponent { - + @Messages({ "PTopComponent_Name=Personas" }) public PersonasTopComponent() { initComponents(); setName(Bundle.PTopComponent_Name()); - - jButton1.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - executeSearch(); - } - }); } - - void executeSearch() { - System.out.println("Search!"); - } - + @Override public void componentOpened() { super.componentOpened(); From 5251ea50ae77abd550fd35c5824988e30745b6af Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 8 May 2020 14:28:41 -0400 Subject: [PATCH 40/90] Fixed getNotableTagDisplayName --- .../casemodule/services/TagsManager.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 49388d619e..7355a8db03 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -146,6 +146,12 @@ public class TagsManager implements Closeable { return tagDisplayNames; } + /** + * Gets the set of display names of notable (TskData.FileKnown.BAD) tag types. + * If a case is not open the list will only include only the user defined + * custom tags. Otherwise the list will include all notable tags. + * @return + */ public static List getNotableTagDisplayNames() { List tagDisplayNames = new ArrayList<>(); for (TagNameDefinition tagDef : TagNameDefinition.getTagNameDefinitions()) { @@ -153,6 +159,22 @@ public class TagsManager implements Closeable { tagDisplayNames.add(tagDef.getDisplayName()); } } + + try { + TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager(); + for (TagName tagName : tagsManager.getAllTagNames()) { + if(tagName.getKnownStatus() == TskData.FileKnown.BAD && + !tagDisplayNames.contains(tagName.getDisplayName())) { + tagDisplayNames.add(tagName.getDisplayName()); + } + } + } catch (NoCurrentCaseException ignored) { + /* + * No current case, nothing more to add to the set. + */ + } catch(TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Faile to get list of TagNams from tagsManager."); + } return tagDisplayNames; } From 0932bf5d68cecb23730eced453032d0caca68f52 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 8 May 2020 14:45:32 -0400 Subject: [PATCH 41/90] Fixed tag warnings --- .../modules/portablecase/PortableCaseReportModule.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java index 046331ca9f..8c88f29f53 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java @@ -65,6 +65,7 @@ import org.sleuthkit.datamodel.Pool; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction; import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TaggingManager.ContentTagChange; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskDataException; import org.sleuthkit.datamodel.TskData; @@ -740,13 +741,13 @@ public class PortableCaseReportModule implements ReportModule { if (! oldTagNameToNewTagName.containsKey(tag.getName())) { throw new TskCoreException("TagName map is missing entry for ID " + tag.getName().getId() + " with display name " + tag.getName().getDisplayName()); // NON-NLS } - ContentTag newContentTag = portableSkCase.addContentTag(newIdToContent.get(newFileId), oldTagNameToNewTagName.get(tag.getName()), tag.getComment(), tag.getBeginByteOffset(), tag.getEndByteOffset()); + ContentTagChange newContentTag = portableSkCase.getTaggingManager().addContentTag(newIdToContent.get(newFileId), oldTagNameToNewTagName.get(tag.getName()), tag.getComment(), tag.getBeginByteOffset(), tag.getEndByteOffset()); // Get the image tag data associated with this tag (empty string if there is none) // and save it if present String appData = getImageTagDataForContentTag(tag); if (! appData.isEmpty()) { - addImageTagToPortableCase(newContentTag, appData); + addImageTagToPortableCase(newContentTag.getAddedTag(), appData); } } } @@ -847,7 +848,7 @@ public class PortableCaseReportModule implements ReportModule { if (! oldTagNameToNewTagName.containsKey(tag.getName())) { throw new TskCoreException("TagName map is missing entry for ID " + tag.getName().getId() + " with display name " + tag.getName().getDisplayName()); // NON-NLS } - portableSkCase.addBlackboardArtifactTag(newArtifact, oldTagNameToNewTagName.get(tag.getName()), tag.getComment()); + portableSkCase.getTaggingManager().addArtifactTag(newArtifact, oldTagNameToNewTagName.get(tag.getName()), tag.getComment()); } } From 341f15e8ae3f2941c45762d6dfe0089d6f540550 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Fri, 8 May 2020 14:53:52 -0400 Subject: [PATCH 42/90] Interim checkpoint commit. --- .../contentviewers/ArtifactContentViewer.java | 57 + .../autopsy/contentviewers/Bundle.properties | 15 +- .../contentviewers/Bundle_ja.properties | 9 + .../DefaultArtifactContentViewer.form | 266 +++++ .../DefaultArtifactContentViewer.java | 983 ++++++++++++++++++ .../DummyArtifactContentViewer.form | 85 ++ .../DummyArtifactContentViewer.java | 108 ++ .../autopsy/corecomponents/Bundle.properties | 1 + .../DataContentViewerArtifact.form | 54 +- .../DataContentViewerArtifact.java | 48 +- 10 files changed, 1618 insertions(+), 8 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/ArtifactContentViewer.java create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.form create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.java create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/DummyArtifactContentViewer.form create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/DummyArtifactContentViewer.java diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ArtifactContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ArtifactContentViewer.java new file mode 100644 index 0000000000..4e3dae286b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ArtifactContentViewer.java @@ -0,0 +1,57 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.contentviewers; + +import java.awt.Component; +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * Common interface implemented by artifact viewers. + * + * An artifact viewer displays the artifact in a custom + * layout panel suitable for the artifact type. + * + */ +public interface ArtifactContentViewer { + + /** + * Called to display the contents of the given artifact. + * + * @param artifact the node which is used to obtain and display the + * artifacts. + */ + void setArtifact(BlackboardArtifact artifact); + + /** + * Returns the panel. + * + * @return display panel. + */ + Component getComponent(); + + /** + * Checks whether the given artifact is supported by the viewer. + * + * @param artifact Artifact to check. + * + * @return True if the node can be displayed / processed, else false + */ + boolean isSupported(BlackboardArtifact artifact); + +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties index ebc9a58e1a..1064a8e354 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties @@ -953,4 +953,17 @@ manager.properties.lafError =\ manager.properties.brokenProperty = Broken default property {0} value: {1} -manager.properties.missingProperty = Missing default property {0} value: {1} \ No newline at end of file +manager.properties.missingProperty = Missing default property {0} value: {1} +DefaultArtifactContentViewer.copyMenuItem.text=Copy +DefaultArtifactContentViewer.prevPageButton.text= +DefaultArtifactContentViewer.pageLabel2.text=Result +DefaultArtifactContentViewer.nextPageButton.text= +DefaultArtifactContentViewer.pageLabel.text=Result: +DefaultArtifactContentViewer.currentPageLabel.text=1 +DefaultArtifactContentViewer.ofLabel.text=of +DefaultArtifactContentViewer.totalPageLabel.text=100 +DefaultArtifactContentViewer.selectAllMenuItem.text=Select All +DummyArtifactContentViewer.jLabel1.text=Artifact Type: +DummyArtifactContentViewer.artifactTypeTextField.text=jTextField1 +DummyArtifactContentViewer.jLabel2.text=Artifact Id: +DummyArtifactContentViewer.artifactIdTextField.text=jTextField1 diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle_ja.properties index f7b7844e60..31e821797d 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle_ja.properties @@ -164,3 +164,12 @@ MediaViewImagePanel.tagsMenu.text_1=\u30bf\u30b0\u30e1\u30cb\u30e5\u30fc SQLiteViewer.readTable.errorText=\u6b21\u306e\u30c6\u30fc\u30d6\u30eb\u306e\u884c\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0} # {0} - tableName SQLiteViewer.selectTable.errorText=\u6b21\u306e\u30c6\u30fc\u30d6\u30eb\u306e\u884c\u30ab\u30a6\u30f3\u30c8\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0} +DefaultArtifactContentViewer.prevPageButton.text= +DefaultArtifactContentViewer.pageLabel2.text=\u7d50\u679c +DefaultArtifactContentViewer.nextPageButton.text= +DefaultArtifactContentViewer.pageLabel.text=\u7d50\u679c: +DefaultArtifactContentViewer.currentPageLabel.text=1 +DefaultArtifactContentViewer.ofLabel.text=/ +DefaultArtifactContentViewer.totalPageLabel.text=100 +DefaultArtifactContentViewer.selectAllMenuItem.text=\u3059\u3079\u3066\u3092\u9078\u629e +DefaultArtifactContentViewer.copyMenuItem.text=\u30b3\u30d4\u30fc diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.form new file mode 100644 index 0000000000..08d2fc0205 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.form @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.java new file mode 100644 index 0000000000..b72320c8b9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.java @@ -0,0 +1,983 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.contentviewers; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.datatransfer.StringSelection; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import javax.swing.JMenuItem; +import javax.swing.JTextArea; +import javax.swing.SwingWorker; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.TableColumnModelEvent; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableColumn; +import javax.swing.event.TableColumnModelListener; +import javax.swing.text.View; +import org.apache.commons.lang.StringUtils; +import org.openide.nodes.Node; +import org.openide.util.Lookup; +import org.openide.util.NbBundle; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskException; +import org.netbeans.swing.etable.ETable; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonArray; +import java.util.Map; + +/** + * Instances of this class display the BlackboardArtifacts associated with the + * Content represented by a Node. Each BlackboardArtifact is rendered displayed + * in a JTable representation of its BlackboardAttributes. + */ +@ServiceProvider(service = DataContentViewer.class, position = 11) +@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives +public class DefaultArtifactContentViewer extends javax.swing.JPanel implements DataContentViewer { + + @NbBundle.Messages({ + "DataContentViewerArtifact.attrsTableHeader.type=Type", + "DataContentViewerArtifact.attrsTableHeader.value=Value", + "DataContentViewerArtifact.attrsTableHeader.sources=Source(s)", + "DataContentViewerArtifact.failedToGetSourcePath.message=Failed to get source file path from case database", + "DataContentViewerArtifact.failedToGetAttributes.message=Failed to get some or all attributes from case database" + }) + private final static Logger logger = Logger.getLogger(DefaultArtifactContentViewer.class.getName()); + private final static String WAIT_TEXT = NbBundle.getMessage(DefaultArtifactContentViewer.class, "DataContentViewerArtifact.waitText"); + private final static String ERROR_TEXT = NbBundle.getMessage(DefaultArtifactContentViewer.class, "DataContentViewerArtifact.errorText"); + private Node currentNode; // @@@ Remove this when the redundant setNode() calls problem is fixed. + private int currentPage = 1; + private final Object lock = new Object(); + private List artifactTableContents; // Accessed by multiple threads, use getArtifactContents() and setArtifactContents() + SwingWorker currentTask; // Accessed by multiple threads, use startNewTask() + private static final String[] COLUMN_HEADERS = { + Bundle.DataContentViewerArtifact_attrsTableHeader_type(), + Bundle.DataContentViewerArtifact_attrsTableHeader_value(), + Bundle.DataContentViewerArtifact_attrsTableHeader_sources()}; + private static final int[] COLUMN_WIDTHS = {100, 800, 100}; + private static final int CELL_BOTTOM_MARGIN = 5; + private static final int CELL_RIGHT_MARGIN = 1; + + public DefaultArtifactContentViewer() { + initResultsTable(); + initComponents(); + resultsTableScrollPane.setViewportView(resultsTable); + customizeComponents(); + resetComponents(); + resultsTable.setDefaultRenderer(Object.class, new MultiLineTableCellRenderer()); + } + + private void initResultsTable() { + resultsTable = new ETable(); + resultsTable.setModel(new javax.swing.table.DefaultTableModel() { + private static final long serialVersionUID = 1L; + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return false; + } + }); + resultsTable.setCellSelectionEnabled(true); + resultsTable.getTableHeader().setReorderingAllowed(false); + resultsTable.setColumnHidingAllowed(false); + resultsTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION); + resultsTable.getColumnModel().addColumnModelListener(new TableColumnModelListener() { + + @Override + public void columnAdded(TableColumnModelEvent e) { + } + + @Override + public void columnRemoved(TableColumnModelEvent e) { + } + + @Override + public void columnMoved(TableColumnModelEvent e) { + + } + + @Override + public void columnMarginChanged(ChangeEvent e) { + updateRowHeights(); //When the user changes column width we may need to resize row height + } + + @Override + public void columnSelectionChanged(ListSelectionEvent e) { + } + }); + resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN); + + } + + /** + * Sets the row heights to the heights of the content in their Value column. + */ + private void updateRowHeights() { + int valueColIndex = -1; + for (int col = 0; col < resultsTable.getColumnCount(); col++) { + if (resultsTable.getColumnName(col).equals(COLUMN_HEADERS[1])) { + valueColIndex = col; + } + } + if (valueColIndex != -1) { + for (int row = 0; row < resultsTable.getRowCount(); row++) { + Component comp = resultsTable.prepareRenderer( + resultsTable.getCellRenderer(row, valueColIndex), row, valueColIndex); + final int rowHeight; + if (comp instanceof JTextArea) { + final JTextArea tc = (JTextArea) comp; + final View rootView = tc.getUI().getRootView(tc); + java.awt.Insets i = tc.getInsets(); + rootView.setSize(resultsTable.getColumnModel().getColumn(valueColIndex) + .getWidth() - (i.left + i.right +CELL_RIGHT_MARGIN), //current width minus borders + Integer.MAX_VALUE); + rowHeight = (int) rootView.getPreferredSpan(View.Y_AXIS); + } else { + rowHeight = comp.getPreferredSize().height; + } + if (rowHeight > 0) { + resultsTable.setRowHeight(row, rowHeight + CELL_BOTTOM_MARGIN); + } + } + } + } + + /** + * Update the column widths so that the Value column has most of the space. + */ + private void updateColumnSizes() { + Enumeration columns = resultsTable.getColumnModel().getColumns(); + while (columns.hasMoreElements()) { + TableColumn col = columns.nextElement(); + if (col.getHeaderValue().equals(COLUMN_HEADERS[0])) { + col.setPreferredWidth(COLUMN_WIDTHS[0]); + } else if (col.getHeaderValue().equals(COLUMN_HEADERS[1])) { + col.setPreferredWidth(COLUMN_WIDTHS[1]); + } else if (col.getHeaderValue().equals(COLUMN_HEADERS[2])) { + col.setPreferredWidth(COLUMN_WIDTHS[2]); + } + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + rightClickMenu = new javax.swing.JPopupMenu(); + copyMenuItem = new javax.swing.JMenuItem(); + selectAllMenuItem = new javax.swing.JMenuItem(); + jScrollPane1 = new javax.swing.JScrollPane(); + jPanel1 = new javax.swing.JPanel(); + totalPageLabel = new javax.swing.JLabel(); + ofLabel = new javax.swing.JLabel(); + currentPageLabel = new javax.swing.JLabel(); + pageLabel = new javax.swing.JLabel(); + nextPageButton = new javax.swing.JButton(); + pageLabel2 = new javax.swing.JLabel(); + prevPageButton = new javax.swing.JButton(); + artifactLabel = new javax.swing.JLabel(); + filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0)); + resultsTableScrollPane = new javax.swing.JScrollPane(); + + copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DefaultArtifactContentViewer.class, "DefaultArtifactContentViewer.copyMenuItem.text")); // NOI18N + rightClickMenu.add(copyMenuItem); + + selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(DefaultArtifactContentViewer.class, "DefaultArtifactContentViewer.selectAllMenuItem.text")); // NOI18N + rightClickMenu.add(selectAllMenuItem); + + setPreferredSize(new java.awt.Dimension(100, 58)); + + jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); + + jPanel1.setPreferredSize(new java.awt.Dimension(620, 58)); + jPanel1.setLayout(new java.awt.GridBagLayout()); + + totalPageLabel.setText(org.openide.util.NbBundle.getMessage(DefaultArtifactContentViewer.class, "DefaultArtifactContentViewer.totalPageLabel.text")); // NOI18N + totalPageLabel.setMaximumSize(new java.awt.Dimension(40, 16)); + totalPageLabel.setPreferredSize(new java.awt.Dimension(25, 16)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 3; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(3, 12, 0, 0); + jPanel1.add(totalPageLabel, gridBagConstraints); + + ofLabel.setText(org.openide.util.NbBundle.getMessage(DefaultArtifactContentViewer.class, "DefaultArtifactContentViewer.ofLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(3, 12, 0, 0); + jPanel1.add(ofLabel, gridBagConstraints); + + currentPageLabel.setText(org.openide.util.NbBundle.getMessage(DefaultArtifactContentViewer.class, "DefaultArtifactContentViewer.currentPageLabel.text")); // NOI18N + currentPageLabel.setMaximumSize(new java.awt.Dimension(38, 14)); + currentPageLabel.setMinimumSize(new java.awt.Dimension(18, 14)); + currentPageLabel.setPreferredSize(new java.awt.Dimension(20, 14)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(4, 7, 0, 0); + jPanel1.add(currentPageLabel, gridBagConstraints); + + pageLabel.setText(org.openide.util.NbBundle.getMessage(DefaultArtifactContentViewer.class, "DefaultArtifactContentViewer.pageLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(3, 12, 0, 0); + jPanel1.add(pageLabel, gridBagConstraints); + + nextPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"))); // NOI18N + nextPageButton.setText(org.openide.util.NbBundle.getMessage(DefaultArtifactContentViewer.class, "DefaultArtifactContentViewer.nextPageButton.text")); // NOI18N + nextPageButton.setBorderPainted(false); + nextPageButton.setContentAreaFilled(false); + nextPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"))); // NOI18N + nextPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0)); + nextPageButton.setPreferredSize(new java.awt.Dimension(23, 23)); + nextPageButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"))); // NOI18N + nextPageButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + nextPageButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 6; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 35, 0); + jPanel1.add(nextPageButton, gridBagConstraints); + + pageLabel2.setText(org.openide.util.NbBundle.getMessage(DefaultArtifactContentViewer.class, "DefaultArtifactContentViewer.pageLabel2.text")); // NOI18N + pageLabel2.setMaximumSize(new java.awt.Dimension(29, 14)); + pageLabel2.setMinimumSize(new java.awt.Dimension(29, 14)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 4; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(3, 41, 0, 0); + jPanel1.add(pageLabel2, gridBagConstraints); + + prevPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"))); // NOI18N + prevPageButton.setText(org.openide.util.NbBundle.getMessage(DefaultArtifactContentViewer.class, "DefaultArtifactContentViewer.prevPageButton.text")); // NOI18N + prevPageButton.setBorderPainted(false); + prevPageButton.setContentAreaFilled(false); + prevPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"))); // NOI18N + prevPageButton.setMargin(new java.awt.Insets(2, 0, 2, 0)); + prevPageButton.setPreferredSize(new java.awt.Dimension(23, 23)); + prevPageButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"))); // NOI18N + prevPageButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + prevPageButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 5; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 35, 0); + jPanel1.add(prevPageButton, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 8; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; + gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 8); + jPanel1.add(artifactLabel, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 7; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 0.1; + jPanel1.add(filler1, gridBagConstraints); + + jScrollPane1.setViewportView(jPanel1); + + resultsTableScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + resultsTableScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + resultsTableScrollPane.setPreferredSize(new java.awt.Dimension(620, 34)); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1) + .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageButtonActionPerformed + currentPage = currentPage + 1; + currentPageLabel.setText(Integer.toString(currentPage)); + artifactLabel.setText(artifactTableContents.get(currentPage - 1).getArtifactDisplayName()); + startNewTask(new SelectedArtifactChangedTask(currentPage)); + }//GEN-LAST:event_nextPageButtonActionPerformed + + private void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevPageButtonActionPerformed + currentPage = currentPage - 1; + currentPageLabel.setText(Integer.toString(currentPage)); + artifactLabel.setText(artifactTableContents.get(currentPage - 1).getArtifactDisplayName()); + startNewTask(new SelectedArtifactChangedTask(currentPage)); + }//GEN-LAST:event_prevPageButtonActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel artifactLabel; + private javax.swing.JMenuItem copyMenuItem; + private javax.swing.JLabel currentPageLabel; + private javax.swing.Box.Filler filler1; + private javax.swing.JPanel jPanel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JButton nextPageButton; + private javax.swing.JLabel ofLabel; + private javax.swing.JLabel pageLabel; + private javax.swing.JLabel pageLabel2; + private javax.swing.JButton prevPageButton; + private javax.swing.JScrollPane resultsTableScrollPane; + private javax.swing.JPopupMenu rightClickMenu; + private javax.swing.JMenuItem selectAllMenuItem; + private javax.swing.JLabel totalPageLabel; + // End of variables declaration//GEN-END:variables + private ETable resultsTable; + + private void customizeComponents() { + resultsTable.setComponentPopupMenu(rightClickMenu); + ActionListener actList = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JMenuItem jmi = (JMenuItem) e.getSource(); + if (jmi.equals(copyMenuItem)) { + StringBuilder selectedText = new StringBuilder(512); + for (int row : resultsTable.getSelectedRows()) { + for (int col : resultsTable.getSelectedColumns()) { + selectedText.append((String) resultsTable.getValueAt(row, col)); + selectedText.append("\t"); + } + //if its the last row selected don't add a new line + if (row != resultsTable.getSelectedRows()[resultsTable.getSelectedRows().length - 1]) { + selectedText.append(System.lineSeparator()); + } + } + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(selectedText.toString()), null); + } else if (jmi.equals(selectAllMenuItem)) { + resultsTable.selectAll(); + } + } + }; + copyMenuItem.addActionListener(actList); + + selectAllMenuItem.addActionListener(actList); + } + + /** + * Resets the components to an empty view state. + */ + private void resetComponents() { + currentPage = 1; + currentPageLabel.setText(""); + artifactLabel.setText(""); + totalPageLabel.setText(""); + ((DefaultTableModel) resultsTable.getModel()).setRowCount(0); + prevPageButton.setEnabled(false); + nextPageButton.setEnabled(false); + currentNode = null; + } + + @Override + public void setNode(Node selectedNode) { + if (currentNode == selectedNode) { + return; + } + currentNode = selectedNode; + + // Make sure there is a node. Null might be passed to reset the viewer. + if (selectedNode == null) { + return; + } + + // Make sure the node is of the correct type. + Lookup lookup = selectedNode.getLookup(); + Content content = lookup.lookup(Content.class); + if (content == null) { + return; + } + + startNewTask(new SelectedNodeChangedTask(selectedNode)); + } + + @Override + public String getTitle() { + return NbBundle.getMessage(this.getClass(), "DataContentViewerArtifact.title"); + } + + @Override + public String getToolTip() { + return NbBundle.getMessage(this.getClass(), "DataContentViewerArtifact.toolTip"); + } + + @Override + public DataContentViewer createInstance() { + return new DefaultArtifactContentViewer(); + } + + @Override + public Component getComponent() { + return this; + } + + @Override + public void resetComponent() { + resetComponents(); + } + + @Override + public boolean isSupported(Node node) { + if (node == null) { + return false; + } + + for (Content content : node.getLookup().lookupAll(Content.class)) { + if ( (content != null) && (!(content instanceof BlackboardArtifact)) ){ + try { + return content.getAllArtifactsCount() > 0; + } catch (TskException ex) { + logger.log(Level.SEVERE, "Couldn't get count of BlackboardArtifacts for content", ex); //NON-NLS + } + } + } + return false; + } + + @Override + public int isPreferred(Node node) { + BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class); + // low priority if node doesn't have an artifact (meaning it was found from normal directory + // browsing, or if the artifact is something that means the user really wants to see the original + // file and not more details about the artifact + if ((artifact == null) + || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) + || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) + || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()) + || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID()) + || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()) + || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID())) { + return 3; + } else { + return 6; + } + } + + /** + * This class is a container to hold the data necessary for each of the + * result pages associated with file or artifact beivng viewed. + */ + private class ResultsTableArtifact { + + private final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private String[][] rowData = null; + private final String artifactDisplayName; + private final Content content; + + ResultsTableArtifact(BlackboardArtifact artifact, Content content) { + artifactDisplayName = artifact.getDisplayName(); + this.content = content; + addRows(artifact); + } + + ResultsTableArtifact(String errorMsg) { + artifactDisplayName = errorMsg; + rowData = new String[1][3]; + rowData[0] = new String[]{"", errorMsg, ""}; + content = null; + } + + private String[][] getRows() { + return rowData; + } + + private void addRows(BlackboardArtifact artifact) { + List rowsToAdd = new ArrayList<>(); + try { + /* + * Add rows for each attribute. + */ + for (BlackboardAttribute attr : artifact.getAttributes()) { + /* + * Attribute value column. + */ + String value = ""; + switch (attr.getAttributeType().getValueType()) { + case STRING: + case INTEGER: + case LONG: + case DOUBLE: + case BYTE: + default: + value = attr.getDisplayString(); + break; + // Use Autopsy date formatting settings, not TSK defaults + case DATETIME: + value = epochTimeToString(attr.getValueLong()); + break; + case JSON: + // Get the attribute's JSON value and convert to indented multiline display string + String jsonVal = attr.getValueString(); + JsonParser parser = new JsonParser(); + JsonObject json = parser.parse(jsonVal).getAsJsonObject(); + + value = toJsonDisplayString(json, ""); + break; + } + /* + * Attribute sources column. + */ + String sources = StringUtils.join(attr.getSources(), ", "); + rowsToAdd.add(new String[]{attr.getAttributeType().getDisplayName(), value, sources}); + } + /* + * Add a row for the source content path. + */ + String path = ""; + try { + if (null != content) { + path = content.getUniquePath(); + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error getting source content path for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); + path = Bundle.DataContentViewerArtifact_failedToGetSourcePath_message(); + } + rowsToAdd.add(new String[]{"Source File Path", path, ""}); + /* + * Add a row for the artifact id. + */ + rowsToAdd.add(new String[]{"Artifact ID", Long.toString(artifact.getArtifactID()), ""}); + } catch (TskCoreException ex) { + rowsToAdd.add(new String[]{"", Bundle.DataContentViewerArtifact_failedToGetAttributes_message(), ""}); + } + rowData = rowsToAdd.toArray(new String[0][0]); + } + + /** + * @return the artifactDisplayName + */ + String getArtifactDisplayName() { + return artifactDisplayName; + } + + private static final String INDENT_RIGHT = " "; + private static final String NEW_LINE = "\n"; + + /** + * Recursively converts a JSON element into an indented multi-line + * display string. + * + * @param element JSON element to convert + * @param startIndent Starting indentation for the element. + * + * @return A multi-line display string. + */ + private String toJsonDisplayString(JsonElement element, String startIndent) { + + StringBuilder sb = new StringBuilder(""); + JsonObject obj = element.getAsJsonObject(); + + for (Map.Entry entry : obj.entrySet()) { + appendJsonElementToString(entry.getKey(), entry.getValue(), startIndent, sb ); + } + + String returnString = sb.toString(); + if (startIndent.length() == 0 && returnString.startsWith(NEW_LINE)) { + returnString = returnString.substring(NEW_LINE.length()); + } + return returnString; + } + + + /** + * Converts the given JSON element into string and appends to the given string builder. + * + * @param jsonKey + * @param jsonElement + * @param startIndent Starting indentation for the element. + * @param sb String builder to append to. + */ + private void appendJsonElementToString(String jsonKey, JsonElement jsonElement, String startIndent, StringBuilder sb) { + if (jsonElement.isJsonArray()) { + JsonArray jsonArray = jsonElement.getAsJsonArray(); + if (jsonArray.size() > 0) { + int count = 1; + sb.append(NEW_LINE).append(String.format("%s%s", startIndent, jsonKey)); + for (JsonElement arrayMember : jsonArray) { + sb.append(NEW_LINE).append(String.format("%s%d", startIndent.concat(INDENT_RIGHT), count)); + sb.append(toJsonDisplayString(arrayMember, startIndent.concat(INDENT_RIGHT).concat(INDENT_RIGHT))); + count++; + } + } + } else if (jsonElement.isJsonObject()) { + sb.append(NEW_LINE).append(String.format("%s%s %s", startIndent, jsonKey, toJsonDisplayString(jsonElement.getAsJsonObject(), startIndent + INDENT_RIGHT))); + } else if (jsonElement.isJsonPrimitive()) { + String attributeName = jsonKey; + String attributeValue; + if (attributeName.toUpperCase().contains("DATETIME")) { + attributeValue = epochTimeToString(Long.parseLong(jsonElement.getAsString())); + } else { + attributeValue = jsonElement.getAsString(); + } + sb.append(NEW_LINE).append(String.format("%s%s = %s", startIndent, attributeName, attributeValue)); + } else if (jsonElement.isJsonNull()) { + sb.append(NEW_LINE).append(String.format("%s%s = null", startIndent, jsonKey)); + } + } + + /** + * Converts epoch time to readable string. + * + * @param epochTime epoch time value to be converted to string. + * @return String with human readable time. + */ + private String epochTimeToString(long epochTime) { + String dateTimeString = "0000-00-00 00:00:00"; + if (null != content && 0 != epochTime) { + dateFormatter.setTimeZone(ContentUtils.getTimeZone(content)); + dateTimeString = dateFormatter.format(new java.util.Date(epochTime * 1000)); + } + return dateTimeString; + } + + } + + /** + * Instances of this class are simple containers for view update information + * generated by a background thread. + */ + private class ViewUpdate { + + int numberOfPages; + int currentPage; + ResultsTableArtifact tableContents; + + ViewUpdate(int numberOfPages, int currentPage, ResultsTableArtifact contents) { + this.currentPage = currentPage; + this.numberOfPages = numberOfPages; + this.tableContents = contents; + } + + ViewUpdate(int numberOfPages, int currentPage, String errorMsg) { + this.currentPage = currentPage; + this.numberOfPages = numberOfPages; + this.tableContents = new ResultsTableArtifact(errorMsg); + } + } + + /** + * Called from queued SwingWorker done() methods on the EDT thread, so + * doesn't need to be synchronized. + * + * @param viewUpdate A simple container for display update information from + * a background thread. + */ + private void updateView(ViewUpdate viewUpdate) { + this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + nextPageButton.setEnabled(viewUpdate.currentPage < viewUpdate.numberOfPages); + prevPageButton.setEnabled(viewUpdate.currentPage > 1); + currentPage = viewUpdate.currentPage; + totalPageLabel.setText(Integer.toString(viewUpdate.numberOfPages)); + currentPageLabel.setText(Integer.toString(currentPage)); + artifactLabel.setText(viewUpdate.tableContents.getArtifactDisplayName()); + DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel()); + tModel.setDataVector(viewUpdate.tableContents.getRows(), COLUMN_HEADERS); + updateColumnSizes(); + updateRowHeights(); + resultsTable.clearSelection(); + + this.setCursor(null); + } + + /** + * Start a new task on its own background thread, canceling the previous + * task. + * + * @param task A new SwingWorker object to execute as a background thread. + */ + private synchronized void startNewTask(SwingWorker task) { + String[][] waitRow = new String[1][3]; + waitRow[0] = new String[]{"", WAIT_TEXT, ""}; + DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel()); + tModel.setDataVector(waitRow, COLUMN_HEADERS); + updateColumnSizes(); + updateRowHeights(); + resultsTable.clearSelection(); + // The output of the previous task is no longer relevant. + if (currentTask != null) { + // This call sets a cancellation flag. It does not terminate the background thread running the task. + // The task must check the cancellation flag and react appropriately. + currentTask.cancel(false); + } + + // Start the new task. + currentTask = task; + currentTask.execute(); + } + + /** + * Populate the cache of artifact represented as ResultsTableArtifacts. + * + * @param artifactList A list of ResultsTableArtifact representations of + * artifacts. + */ + private void setArtifactContents(List artifactList) { + synchronized (lock) { + this.artifactTableContents = artifactList; + } + } + + /** + * Retrieve the cache of artifact represented as ResultsTableArtifacts. + * + * @return A list of ResultsTableArtifact representations of artifacts. + */ + private List getArtifactContents() { + synchronized (lock) { + return artifactTableContents; + } + } + + /** + * Instances of this class use a background thread to generate a ViewUpdate + * when a node is selected, changing the set of blackboard artifacts + * ("results") to be displayed. + */ + private class SelectedNodeChangedTask extends SwingWorker { + + private final Node selectedNode; + + SelectedNodeChangedTask(Node selectedNode) { + this.selectedNode = selectedNode; + } + + @Override + protected ViewUpdate doInBackground() { + // Get the lookup for the node for access to its underlying content and + // blackboard artifact, if any. + Lookup lookup = selectedNode.getLookup(); + + // Get the content. We may get BlackboardArtifacts, ignore those here. + ArrayList artifacts = new ArrayList<>(); + Collection contents = lookup.lookupAll(Content.class); + if (contents.isEmpty()) { + return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT); + } + Content underlyingContent = null; + for (Content content : contents) { + if ( (content != null) && (!(content instanceof BlackboardArtifact)) ) { + // Get all of the blackboard artifacts associated with the content. These are what this + // viewer displays. + try { + artifacts = content.getAllArtifacts(); + underlyingContent = content; + break; + } catch (TskException ex) { + logger.log(Level.SEVERE, "Couldn't get artifacts", ex); //NON-NLS + return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT); + } + } + } + + if (isCancelled()) { + return null; + } + + // Build the new artifact contents cache. + ArrayList artifactContents = new ArrayList<>(); + for (BlackboardArtifact artifact : artifacts) { + artifactContents.add(new ResultsTableArtifact(artifact, underlyingContent)); + } + + // If the node has an underlying blackboard artifact, show it. If not, + // show the first artifact. + int index = 0; + BlackboardArtifact artifact = lookup.lookup(BlackboardArtifact.class); + if (artifact != null) { + index = artifacts.indexOf(artifact); + if (index == -1) { + index = 0; + } else { + // if the artifact has an ASSOCIATED ARTIFACT, then we display the associated artifact instead + try { + for (BlackboardAttribute attr : artifact.getAttributes()) { + if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) { + long assocArtifactId = attr.getValueLong(); + int assocArtifactIndex = -1; + for (BlackboardArtifact art : artifacts) { + if (assocArtifactId == art.getArtifactID()) { + assocArtifactIndex = artifacts.indexOf(art); + break; + } + } + if (assocArtifactIndex >= 0) { + index = assocArtifactIndex; + } + break; + } + } + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Couldn't get associated artifact to display in Content Viewer.", ex); //NON-NLS + } + } + + } + + if (isCancelled()) { + return null; + } + + // Add one to the index of the artifact content for the corresponding page index. + ViewUpdate viewUpdate = new ViewUpdate(artifactContents.size(), index + 1, artifactContents.get(index)); + + // It may take a considerable amount of time to fetch the attributes of the selected artifact + if (isCancelled()) { + return null; + } + + // Update the artifact contents cache. + setArtifactContents(artifactContents); + + return viewUpdate; + } + + @Override + protected void done() { + if (!isCancelled()) { + try { + ViewUpdate viewUpdate = get(); + if (viewUpdate != null) { + updateView(viewUpdate); + } + } catch (InterruptedException | ExecutionException ex) { + logger.log(Level.WARNING, "Artifact display task unexpectedly interrupted or failed", ex); //NON-NLS + } + } + } + } + + /** + * Instances of this class use a background thread to generate a ViewUpdate + * when the user pages the view to look at another blackboard artifact + * ("result"). + */ + private class SelectedArtifactChangedTask extends SwingWorker { + + private final int pageIndex; + + SelectedArtifactChangedTask(final int pageIndex) { + this.pageIndex = pageIndex; + } + + @Override + protected ViewUpdate doInBackground() { + // Get the artifact content to display from the cache. Note that one must be subtracted from the + // page index to get the corresponding artifact content index. + List artifactContents = getArtifactContents(); + ResultsTableArtifact artifactContent = artifactContents.get(pageIndex - 1); + + // It may take a considerable amount of time to fetch the attributes of the selected artifact so check for cancellation. + if (isCancelled()) { + return null; + } + + return new ViewUpdate(artifactContents.size(), pageIndex, artifactContent); + } + + @Override + protected void done() { + if (!isCancelled()) { + try { + ViewUpdate viewUpdate = get(); + if (viewUpdate != null) { + updateView(viewUpdate); + } + } catch (InterruptedException | ExecutionException ex) { + logger.log(Level.WARNING, "Artifact display task unexpectedly interrupted or failed", ex); //NON-NLS + } + } + } + } + + /** + * TableCellRenderer for displaying multiline text. + */ + private class MultiLineTableCellRenderer implements javax.swing.table.TableCellRenderer { + + @Override + public Component getTableCellRendererComponent(javax.swing.JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + javax.swing.JTextArea jtex = new javax.swing.JTextArea(); + if (value instanceof String) { + jtex.setText((String) value); + jtex.setLineWrap(true); + jtex.setWrapStyleWord(false); + } + //cell backgroud color when selected + if (isSelected) { + jtex.setBackground(javax.swing.UIManager.getColor("Table.selectionBackground")); + } else { + jtex.setBackground(javax.swing.UIManager.getColor("Table.background")); + } + return jtex; + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/DummyArtifactContentViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/DummyArtifactContentViewer.form new file mode 100644 index 0000000000..b7cef5505b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/DummyArtifactContentViewer.form @@ -0,0 +1,85 @@ + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/DummyArtifactContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/DummyArtifactContentViewer.java new file mode 100644 index 0000000000..edc793f98b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/DummyArtifactContentViewer.java @@ -0,0 +1,108 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.contentviewers; + +import java.awt.Component; +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * + * @author raman + */ +public class DummyArtifactContentViewer extends javax.swing.JPanel implements ArtifactContentViewer { + + /** + * Creates new form DummyArtifactContentViewer + */ + public DummyArtifactContentViewer() { + initComponents(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + artifactTypeTextField = new javax.swing.JTextField(); + jLabel2 = new javax.swing.JLabel(); + artifactIdTextField = new javax.swing.JTextField(); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(DummyArtifactContentViewer.class, "DummyArtifactContentViewer.jLabel1.text")); // NOI18N + + artifactTypeTextField.setText(org.openide.util.NbBundle.getMessage(DummyArtifactContentViewer.class, "DummyArtifactContentViewer.artifactTypeTextField.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(DummyArtifactContentViewer.class, "DummyArtifactContentViewer.jLabel2.text")); // NOI18N + + artifactIdTextField.setText(org.openide.util.NbBundle.getMessage(DummyArtifactContentViewer.class, "DummyArtifactContentViewer.artifactIdTextField.text")); // NOI18N + artifactIdTextField.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + artifactIdTextFieldActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1) + .addComponent(jLabel2)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(artifactTypeTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE) + .addComponent(artifactIdTextField)) + .addContainerGap(165, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(16, 16, 16) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(artifactTypeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel2) + .addComponent(artifactIdTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(218, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void artifactIdTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_artifactIdTextFieldActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_artifactIdTextFieldActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JTextField artifactIdTextField; + private javax.swing.JTextField artifactTypeTextField; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + // End of variables declaration//GEN-END:variables + + @Override + public void setArtifact(BlackboardArtifact artifact) { + artifactTypeTextField.setText(artifact.getArtifactTypeName()); + artifactIdTextField.setText(String.format("%d", artifact.getId())); + } + + @Override + public Component getComponent() { + return this; + } + + @Override + public boolean isSupported(BlackboardArtifact artifact) { + return true; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 4571bcc3df..4eb87c3496 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -218,3 +218,4 @@ DataResultViewerTable.exportCSVButton.text=Save Table as CSV ViewPreferencesPanel.scoColumnsCheckbox.text=S(core), C(omments), and O(ccurences) ViewPreferencesPanel.scoColumnsWrapAroundText.text=to reduce loading times ViewPreferencesPanel.scoColumnsLabel.text=Do not add columns for: +DataContentViewerArtifact.jLabel1.text=Artifact Content View diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form index 5827ce617f..52207ebf35 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form @@ -1,6 +1,6 @@ -
        + @@ -45,8 +45,14 @@ - - + + + + + + + + @@ -54,7 +60,11 @@ - + + + + + @@ -262,5 +272,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java index 78ccd6e4ec..a5779005a8 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java @@ -61,6 +61,8 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonArray; import java.util.Map; +import org.sleuthkit.autopsy.contentviewers.ArtifactContentViewer; +import org.sleuthkit.autopsy.contentviewers.DummyArtifactContentViewer; /** * Instances of this class display the BlackboardArtifacts associated with the @@ -219,6 +221,8 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat artifactLabel = new javax.swing.JLabel(); filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0)); resultsTableScrollPane = new javax.swing.JScrollPane(); + jLabel1 = new javax.swing.JLabel(); + artifactContentPanel = new javax.swing.JPanel(); copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.copyMenuItem.text")); // NOI18N rightClickMenu.add(copyMenuItem); @@ -345,19 +349,32 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat resultsTableScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); resultsTableScrollPane.setPreferredSize(new java.awt.Dimension(620, 34)); + jLabel1.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.jLabel1.text")); // NOI18N + + artifactContentPanel.setLayout(new javax.swing.OverlayLayout(artifactContentPanel)); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1) - .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 476, Short.MAX_VALUE) + .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 476, Short.MAX_VALUE) + .addComponent(artifactContentPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addGap(166, 166, 166) + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 129, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(artifactContentPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 134, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -376,10 +393,12 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat }//GEN-LAST:event_prevPageButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel artifactContentPanel; private javax.swing.JLabel artifactLabel; private javax.swing.JMenuItem copyMenuItem; private javax.swing.JLabel currentPageLabel; private javax.swing.Box.Filler filler1; + private javax.swing.JLabel jLabel1; private javax.swing.JPanel jPanel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JButton nextPageButton; @@ -521,6 +540,11 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat } } + private ArtifactContentViewer getArtifactViewer(BlackboardArtifact artifact) { + + return new DummyArtifactContentViewer(); + + } /** * This class is a container to hold the data necessary for each of the * result pages associated with file or artifact beivng viewed. @@ -531,10 +555,12 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat private String[][] rowData = null; private final String artifactDisplayName; private final Content content; + private final BlackboardArtifact artifact; ResultsTableArtifact(BlackboardArtifact artifact, Content content) { artifactDisplayName = artifact.getDisplayName(); this.content = content; + this.artifact = artifact; addRows(artifact); } @@ -543,12 +569,17 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat rowData = new String[1][3]; rowData[0] = new String[]{"", errorMsg, ""}; content = null; + artifact = null; } private String[][] getRows() { return rowData; } + BlackboardArtifact getArtifact() { + return this.artifact; + } + private void addRows(BlackboardArtifact artifact) { List rowsToAdd = new ArrayList<>(); try { @@ -618,6 +649,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat return artifactDisplayName; } + private static final String INDENT_RIGHT = " "; private static final String NEW_LINE = "\n"; @@ -745,7 +777,17 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat updateRowHeights(); resultsTable.clearSelection(); + BlackboardArtifact artifact = viewUpdate.tableContents.getArtifact(); + ArtifactContentViewer viewer = this.getArtifactViewer(artifact); + viewer.setArtifact(artifact); + + artifactContentPanel.removeAll(); + artifactContentPanel.add(viewer.getComponent()); + artifactContentPanel.revalidate(); + this.setCursor(null); + + this.revalidate(); } /** From 373247be4cb2127552a93eb837c870e638e9936d Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Fri, 8 May 2020 15:12:53 -0400 Subject: [PATCH 43/90] 6336 Restoring properties files --- .../core.jar/org/netbeans/core/startup/Bundle.properties | 4 ++-- .../org/netbeans/core/windows/view/ui/Bundle.properties | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 42ff0c5da4..409b08ee57 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Fri, 08 May 2020 11:13:24 -0400 +#Tue, 12 Nov 2019 17:21:46 -0500 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 4.15.0 +currentVersion=Autopsy 4.13.0 \ No newline at end of file diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 7a54b6f1f2..23ae40d7b4 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #Updated by build script -#Fri, 08 May 2020 11:13:24 -0400 -CTL_MainWindow_Title=Autopsy 4.15.0 -CTL_MainWindow_Title_No_Project=Autopsy 4.15.0 +#Tue, 12 Nov 2019 17:21:46 -0500 +CTL_MainWindow_Title=Autopsy 4.13.0 +CTL_MainWindow_Title_No_Project=Autopsy 4.13.0 \ No newline at end of file From a57e08b3e2d3bd1e9963bf5ccdfc3eb6adb4a730 Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Fri, 8 May 2020 15:13:25 -0400 Subject: [PATCH 44/90] 6336 Restoring properties files --- .../core/core.jar/org/netbeans/core/startup/Bundle.properties | 2 +- .../org/netbeans/core/windows/view/ui/Bundle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 409b08ee57..b20ccf5912 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 4.13.0 \ No newline at end of file +currentVersion=Autopsy 4.13.0 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 23ae40d7b4..998d3f715c 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #Updated by build script #Tue, 12 Nov 2019 17:21:46 -0500 CTL_MainWindow_Title=Autopsy 4.13.0 -CTL_MainWindow_Title_No_Project=Autopsy 4.13.0 \ No newline at end of file +CTL_MainWindow_Title_No_Project=Autopsy 4.13.0 From 861f4bb2d51cccaa6a8a777f7db59d3deb0f1146 Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Fri, 8 May 2020 15:31:15 -0400 Subject: [PATCH 45/90] 6336 PR suggestions --- .../autopsy/persona/Bundle.properties | 22 +- .../autopsy/persona/PersonasTopComponent.form | 130 +++++---- .../autopsy/persona/PersonasTopComponent.java | 264 +++++++++--------- 3 files changed, 206 insertions(+), 210 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties b/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties index 214677936e..59ec5eaeed 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties @@ -1,14 +1,14 @@ CTL_OpenPersonas=Personas CTL_PersonasTopComponentAction=PersonasTopComponent CTL_PersonasTopComponent=Personas -PersonasTopComponent.jTextField1.text=John Doe -PersonasTopComponent.jRadioButton1.text=Name -PersonasTopComponent.jRadioButton2.text=Account -PersonasTopComponent.jTable2.columnModel.title0=ID -PersonasTopComponent.jTable2.columnModel.title1=Name -PersonasTopComponent.jButton1.text=Search -PersonasTopComponent.jLabel2.text=Name: -PersonasTopComponent.jLabel5.text=Cases found in: -PersonasTopComponent.jLabel4.text=Accounts: -PersonasTopComponent.jLabel3.text=Aliases: -PersonasTopComponent.jTextField2.text=Johnathan Dough +PersonasTopComponent.searchField.text=John Doe +PersonasTopComponent.searchBtn.text=Search +PersonasTopComponent.searchNameRadio.text=Name +PersonasTopComponent.searchAccountRadio.text=Account +PersonasTopComponent.filterResultsTable.columnModel.title1=Name +PersonasTopComponent.filterResultsTable.columnModel.title0=ID +PersonasTopComponent.resultAccountsLbl.text=Accounts: +PersonasTopComponent.resultAliasesLbl.text=Aliases: +PersonasTopComponent.resultNameLbl.text=Name: +PersonasTopComponent.resultCasesLbl.text=Cases found in: +PersonasTopComponent.resultNameField.text=Johnathan Dough diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form index a6d69d58bf..83638e2f02 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form @@ -23,10 +23,8 @@
        - + - - @@ -48,21 +46,21 @@ - + - + - + - + @@ -75,18 +73,18 @@ - + - + - + - + - + @@ -101,61 +99,61 @@ - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -177,14 +175,14 @@ - <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonasTopComponent.jTable2.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonasTopComponent.filterResultsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonasTopComponent.jTable2.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonasTopComponent.filterResultsTable.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> @@ -198,16 +196,16 @@ - + - + - + @@ -220,17 +218,17 @@ - - - + + + - + - + - - - + + + @@ -241,67 +239,67 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
        @@ -323,21 +321,21 @@ - + - + - + - + @@ -352,14 +350,14 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java index e78afa9a17..a760cc7693 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java @@ -57,46 +57,45 @@ public final class PersonasTopComponent extends TopComponent { // //GEN-BEGIN:initComponents private void initComponents() { - buttonGroup1 = new javax.swing.ButtonGroup(); - jDesktopPane1 = new javax.swing.JDesktopPane(); - jSplitPane2 = new javax.swing.JSplitPane(); - jPanel1 = new javax.swing.JPanel(); - jTextField1 = new javax.swing.JTextField(); - jRadioButton1 = new javax.swing.JRadioButton(); - jRadioButton2 = new javax.swing.JRadioButton(); - jScrollPane1 = new javax.swing.JScrollPane(); - jTable2 = new javax.swing.JTable(); - jButton1 = new javax.swing.JButton(); - jPanel2 = new javax.swing.JPanel(); - jLabel2 = new javax.swing.JLabel(); - jTextField2 = new javax.swing.JTextField(); - jLabel3 = new javax.swing.JLabel(); - jLabel4 = new javax.swing.JLabel(); - jScrollPane4 = new javax.swing.JScrollPane(); - jTable1 = new javax.swing.JTable(); - jLabel5 = new javax.swing.JLabel(); - jScrollPane3 = new javax.swing.JScrollPane(); - jList2 = new javax.swing.JList<>(); - jScrollPane5 = new javax.swing.JScrollPane(); - jList3 = new javax.swing.JList<>(); + searchButtonGroup = new javax.swing.ButtonGroup(); + splitPane = new javax.swing.JSplitPane(); + searchPanel = new javax.swing.JPanel(); + searchField = new javax.swing.JTextField(); + searchNameRadio = new javax.swing.JRadioButton(); + searchAccountRadio = new javax.swing.JRadioButton(); + filterResultsPane = new javax.swing.JScrollPane(); + filterResultsTable = new javax.swing.JTable(); + searchBtn = new javax.swing.JButton(); + detailsPanel = new javax.swing.JPanel(); + resultNameLbl = new javax.swing.JLabel(); + resultNameField = new javax.swing.JTextField(); + resultAliasesLbl = new javax.swing.JLabel(); + resultAccountsLbl = new javax.swing.JLabel(); + accountsTablePane = new javax.swing.JScrollPane(); + accountsTable = new javax.swing.JTable(); + resultCasesLbl = new javax.swing.JLabel(); + casesListPane = new javax.swing.JScrollPane(); + casesList = new javax.swing.JList<>(); + aliasesListPane = new javax.swing.JScrollPane(); + aliasesList = new javax.swing.JList<>(); setMinimumSize(new java.awt.Dimension(400, 400)); - jTextField1.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jTextField1.text")); // NOI18N + searchField.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchField.text")); // NOI18N - buttonGroup1.add(jRadioButton1); - jRadioButton1.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(jRadioButton1, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jRadioButton1.text")); // NOI18N - jRadioButton1.addActionListener(new java.awt.event.ActionListener() { + searchButtonGroup.add(searchNameRadio); + searchNameRadio.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(searchNameRadio, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchNameRadio.text")); // NOI18N + searchNameRadio.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - jRadioButton1ActionPerformed(evt); + searchNameRadioActionPerformed(evt); } }); - buttonGroup1.add(jRadioButton2); - org.openide.awt.Mnemonics.setLocalizedText(jRadioButton2, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jRadioButton2.text")); // NOI18N + searchButtonGroup.add(searchAccountRadio); + org.openide.awt.Mnemonics.setLocalizedText(searchAccountRadio, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchAccountRadio.text")); // NOI18N - jTable2.setModel(new javax.swing.table.DefaultTableModel( + filterResultsTable.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { {"0", "Johnathn Dough"}, {"3", "Joe Schmoe"}, @@ -115,69 +114,69 @@ public final class PersonasTopComponent extends TopComponent { return types [columnIndex]; } }); - jScrollPane1.setViewportView(jTable2); - if (jTable2.getColumnModel().getColumnCount() > 0) { - jTable2.getColumnModel().getColumn(0).setMaxWidth(25); - jTable2.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jTable2.columnModel.title0")); // NOI18N - jTable2.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jTable2.columnModel.title1")); // NOI18N + filterResultsPane.setViewportView(filterResultsTable); + if (filterResultsTable.getColumnModel().getColumnCount() > 0) { + filterResultsTable.getColumnModel().getColumn(0).setMaxWidth(25); + filterResultsTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.filterResultsTable.columnModel.title0")); // NOI18N + filterResultsTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.filterResultsTable.columnModel.title1")); // NOI18N } - org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jButton1.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(searchBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchBtn.text")); // NOI18N - javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); - jPanel1.setLayout(jPanel1Layout); - jPanel1Layout.setHorizontalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() + javax.swing.GroupLayout searchPanelLayout = new javax.swing.GroupLayout(searchPanel); + searchPanel.setLayout(searchPanelLayout); + searchPanelLayout.setHorizontalGroup( + searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(searchPanelLayout.createSequentialGroup() .addContainerGap() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jTextField1) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(jRadioButton1) + .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(filterResultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addGroup(searchPanelLayout.createSequentialGroup() + .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(searchField) + .addGroup(searchPanelLayout.createSequentialGroup() + .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(searchPanelLayout.createSequentialGroup() + .addComponent(searchNameRadio) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jRadioButton2)) - .addComponent(jButton1)) + .addComponent(searchAccountRadio)) + .addComponent(searchBtn)) .addGap(0, 25, Short.MAX_VALUE))) .addContainerGap()))) ); - jPanel1Layout.setVerticalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() + searchPanelLayout.setVerticalGroup( + searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(searchPanelLayout.createSequentialGroup() .addContainerGap() - .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(searchField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jRadioButton1) - .addComponent(jRadioButton2)) + .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(searchNameRadio) + .addComponent(searchAccountRadio)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jButton1) + .addComponent(searchBtn) .addGap(18, 18, 18) - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addComponent(filterResultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) .addContainerGap()) ); - jSplitPane2.setLeftComponent(jPanel1); + splitPane.setLeftComponent(searchPanel); - org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jLabel2.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(resultNameLbl, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultNameLbl.text")); // NOI18N - jTextField2.setEditable(false); - jTextField2.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jTextField2.text")); // NOI18N - jTextField2.addActionListener(new java.awt.event.ActionListener() { + resultNameField.setEditable(false); + resultNameField.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultNameField.text")); // NOI18N + resultNameField.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - jTextField2ActionPerformed(evt); + resultNameFieldActionPerformed(evt); } }); - org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jLabel3.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(resultAliasesLbl, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultAliasesLbl.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jLabel4.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(resultAccountsLbl, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultAccountsLbl.text")); // NOI18N - jTable1.setModel(new javax.swing.table.DefaultTableModel( + accountsTable.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { {"Email", "jdb@yahoo.com"}, {"Phone", "865-555-5555"}, @@ -203,110 +202,109 @@ public final class PersonasTopComponent extends TopComponent { return canEdit [columnIndex]; } }); - jScrollPane4.setViewportView(jTable1); + accountsTablePane.setViewportView(accountsTable); - org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.jLabel5.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(resultCasesLbl, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultCasesLbl.text")); // NOI18N - jList2.setModel(new javax.swing.AbstractListModel() { + casesList.setModel(new javax.swing.AbstractListModel() { String[] strings = { "Investigation 13", "Scene 5" }; public int getSize() { return strings.length; } public String getElementAt(int i) { return strings[i]; } }); - jScrollPane3.setViewportView(jList2); + casesListPane.setViewportView(casesList); - jList3.setModel(new javax.swing.AbstractListModel() { + aliasesList.setModel(new javax.swing.AbstractListModel() { String[] strings = { "J.D.", "Fred Smidge", "Ethan Roseman" }; public int getSize() { return strings.length; } public String getElementAt(int i) { return strings[i]; } }); - jScrollPane5.setViewportView(jList3); + aliasesListPane.setViewportView(aliasesList); - javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); - jPanel2.setLayout(jPanel2Layout); - jPanel2Layout.setHorizontalGroup( - jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() + javax.swing.GroupLayout detailsPanelLayout = new javax.swing.GroupLayout(detailsPanel); + detailsPanel.setLayout(detailsPanelLayout); + detailsPanelLayout.setHorizontalGroup( + detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, detailsPanelLayout.createSequentialGroup() .addContainerGap() - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addComponent(jScrollPane5) - .addComponent(jScrollPane3) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel2Layout.createSequentialGroup() - .addComponent(jLabel2) + .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(accountsTablePane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addComponent(aliasesListPane) + .addComponent(casesListPane) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, detailsPanelLayout.createSequentialGroup() + .addComponent(resultNameLbl) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)) - .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jLabel4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(resultNameField, javax.swing.GroupLayout.DEFAULT_SIZE, 447, Short.MAX_VALUE)) + .addComponent(resultAliasesLbl, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(resultAccountsLbl, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(resultCasesLbl, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); - jPanel2Layout.setVerticalGroup( - jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel2Layout.createSequentialGroup() + detailsPanelLayout.setVerticalGroup( + detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(detailsPanelLayout.createSequentialGroup() .addContainerGap() - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel2) - .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(resultNameLbl) + .addComponent(resultNameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(18, 18, 18) - .addComponent(jLabel3) + .addComponent(resultAliasesLbl) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(aliasesListPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jLabel4) + .addComponent(resultAccountsLbl) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 153, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(accountsTablePane, javax.swing.GroupLayout.PREFERRED_SIZE, 153, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jLabel5) + .addComponent(resultCasesLbl) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 68, Short.MAX_VALUE) + .addComponent(casesListPane, javax.swing.GroupLayout.DEFAULT_SIZE, 118, Short.MAX_VALUE) .addContainerGap()) ); - jSplitPane2.setRightComponent(jPanel2); + splitPane.setRightComponent(detailsPanel); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jSplitPane2) + .addComponent(splitPane) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jSplitPane2) + .addComponent(splitPane) ); }// //GEN-END:initComponents - private void jRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButton1ActionPerformed + private void searchNameRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchNameRadioActionPerformed // TODO add your handling code here: - }//GEN-LAST:event_jRadioButton1ActionPerformed + }//GEN-LAST:event_searchNameRadioActionPerformed - private void jTextField2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField2ActionPerformed + private void resultNameFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resultNameFieldActionPerformed // TODO add your handling code here: - }//GEN-LAST:event_jTextField2ActionPerformed + }//GEN-LAST:event_resultNameFieldActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.ButtonGroup buttonGroup1; - private javax.swing.JButton jButton1; - private javax.swing.JDesktopPane jDesktopPane1; - private javax.swing.JLabel jLabel2; - private javax.swing.JLabel jLabel3; - private javax.swing.JLabel jLabel4; - private javax.swing.JLabel jLabel5; - private javax.swing.JList jList2; - private javax.swing.JList jList3; - private javax.swing.JPanel jPanel1; - private javax.swing.JPanel jPanel2; - private javax.swing.JRadioButton jRadioButton1; - private javax.swing.JRadioButton jRadioButton2; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JScrollPane jScrollPane3; - private javax.swing.JScrollPane jScrollPane4; - private javax.swing.JScrollPane jScrollPane5; - private javax.swing.JSplitPane jSplitPane2; - private javax.swing.JTable jTable1; - private javax.swing.JTable jTable2; - private javax.swing.JTextField jTextField1; - private javax.swing.JTextField jTextField2; + private javax.swing.JTable accountsTable; + private javax.swing.JScrollPane accountsTablePane; + private javax.swing.JList aliasesList; + private javax.swing.JScrollPane aliasesListPane; + private javax.swing.JList casesList; + private javax.swing.JScrollPane casesListPane; + private javax.swing.JPanel detailsPanel; + private javax.swing.JScrollPane filterResultsPane; + private javax.swing.JTable filterResultsTable; + private javax.swing.JLabel resultAccountsLbl; + private javax.swing.JLabel resultAliasesLbl; + private javax.swing.JLabel resultCasesLbl; + private javax.swing.JTextField resultNameField; + private javax.swing.JLabel resultNameLbl; + private javax.swing.JRadioButton searchAccountRadio; + private javax.swing.JButton searchBtn; + private javax.swing.ButtonGroup searchButtonGroup; + private javax.swing.JTextField searchField; + private javax.swing.JRadioButton searchNameRadio; + private javax.swing.JPanel searchPanel; + private javax.swing.JSplitPane splitPane; // End of variables declaration//GEN-END:variables } From 474a1cbede89ce273ca395a756860bab9eeed421 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 8 May 2020 15:41:34 -0400 Subject: [PATCH 46/90] finishing comments and some rough edges --- .../AnnotationsContentViewer.java | 387 ++++++++++++------ 1 file changed, 260 insertions(+), 127 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index bc8ef25642..7884f1a630 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -21,15 +21,14 @@ package org.sleuthkit.autopsy.contentviewers; import java.awt.Component; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.function.Function; import java.util.logging.Level; import java.util.stream.Collectors; import javax.swing.JLabel; +import javax.swing.text.EditorKit; +import javax.swing.text.html.HTMLEditorKit; import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang3.StringEscapeUtils; import static org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; @@ -72,7 +71,7 @@ import org.jsoup.nodes.Element; "AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type:", "AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment:", "AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path:", - "AnnotationsContentViewer.tagEntry.title=Tag Comments", + "AnnotationsContentViewer.tagEntry.title=Tags", "AnnotationsContentViewer.tagEntry.onContentEmpty=There are no tags for the selected content.", "AnnotationsContentViewer.tagEntry.onArtifactEmpty=There are no tags for the selected artifact.", "AnnotationsContentViewer.tagEntryDataLabel.tag=Tag:", @@ -88,60 +87,18 @@ import org.jsoup.nodes.Element; }) public class AnnotationsContentViewer extends javax.swing.JPanel implements DataContentViewer { - private static final Logger logger = Logger.getLogger(AnnotationsContentViewer.class.getName()); + private static class ItemEntry { - private static final String EMPTY_HTML = ""; - - private static final int DEFAULT_FONT_SIZE = new JLabel().getFont().getSize(); - private static final int SUBHEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 12 / 11; - private static final int HEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 14 / 11; - - private static final int DEFAULT_SUBSECTION_LEFT_PAD = DEFAULT_FONT_SIZE; - - private static final String HEADER_STYLE = "font-size:" + HEADER_FONT_SIZE + "px;font-weight:bold;"; - private static final String SUBHEADER_STYLE = "font-size:" + SUBHEADER_FONT_SIZE + "px;font-weight:bold;"; - private static final String MESSAGE_STYLE = "font-size:" + DEFAULT_FONT_SIZE + "px;font-style:italic;"; - private static final String CONTENT_STYLE = "font-size:" + DEFAULT_FONT_SIZE + "px;"; - - private static final int DEFAULT_TABLE_SPACING = DEFAULT_FONT_SIZE * 2; - private static final int DEFAULT_SECTION_SPACING = DEFAULT_FONT_SIZE; - private static final int DEFAULT_SUBSECTION_SPACING = DEFAULT_FONT_SIZE; - - private static final List> TAG_COLUMNS = Arrays.asList( - new ColumnEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_tag(), - (tag) -> (tag.getName() != null) ? tag.getName().getDisplayName() : null), - new ColumnEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_tagUser(), (tag) -> tag.getUserName()), - new ColumnEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_comment(), (tag) -> tag.getComment()) - ); - - private static final List> FILESET_HIT_COLUMNS = Arrays.asList( - new ColumnEntry<>(Bundle.AnnotationsContentViewer_fileHitEntry_setName(), - (bba) -> tryGetAttribute(bba, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)), - new ColumnEntry<>(Bundle.AnnotationsContentViewer_fileHitEntry_comment(), - (bba) -> tryGetAttribute(bba, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT)) - ); - - private static final List> CENTRAL_REPO_COMMENTS_COLUMNS = Arrays.asList( - new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(), - cai -> (cai.getCorrelationCase() != null) ? cai.getCorrelationCase().getDisplayName() : null), - new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_type(), - cai -> (cai.getCorrelationType() != null) ? cai.getCorrelationType().getDisplayName() : null), - new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_comment(), cai -> cai.getComment()), - new ColumnEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), cai -> cai.getFilePath()) - ); - - private static class ColumnEntry { - - private final String columnName; + private final String itemName; private final Function valueRetriever; - ColumnEntry(String columnName, Function valueRetriever) { - this.columnName = columnName; + ItemEntry(String itemName, Function valueRetriever) { + this.itemName = itemName; this.valueRetriever = valueRetriever; } - String getColumnName() { - return columnName; + String getItemName() { + return itemName; } Function getValueRetriever() { @@ -153,12 +110,140 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } } + private static class SectionConfig { + + private final String title; + private final String onEmpty; + private final List> attributes; + private final boolean isVerticalTable; + + SectionConfig(String title, String onEmpty, List> attributes, boolean isVerticalTable) { + this.title = title; + this.onEmpty = onEmpty; + this.attributes = attributes; + this.isVerticalTable = isVerticalTable; + } + + String getTitle() { + return title; + } + + String getOnEmpty() { + return onEmpty; + } + + List> getAttributes() { + return attributes; + } + + boolean isIsVerticalTable() { + return isVerticalTable; + } + } + + private static final Logger logger = Logger.getLogger(AnnotationsContentViewer.class.getName()); + + private static final String EMPTY_HTML = ""; + + private static final int DEFAULT_FONT_SIZE = new JLabel().getFont().getSize(); + + // how big the subheader should be + private static final int SUBHEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 12 / 11; + + // how big the header should be + private static final int HEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 14 / 11; + + // the subsection indent + private static final int DEFAULT_SUBSECTION_LEFT_PAD = DEFAULT_FONT_SIZE; + + // spacing occurring after an item + private static final int DEFAULT_TABLE_SPACING = DEFAULT_FONT_SIZE; + private static final int DEFAULT_SECTION_SPACING = DEFAULT_FONT_SIZE * 2; + private static final int DEFAULT_SUBSECTION_SPACING = DEFAULT_FONT_SIZE / 2; + private static final int CELL_SPACING = DEFAULT_FONT_SIZE / 2; + + // html stylesheet classnames for components + private static final String MESSAGE_CLASSNAME = "message"; + private static final String SUBSECTION_CLASSNAME = "subsection"; + private static final String SUBHEADER_CLASSNAME = "subheader"; + private static final String SECTION_CLASSNAME = "section"; + private static final String HEADER_CLASSNAME = "header"; + private static final String ENTRY_TABLE_CLASSNAME = "entry-table"; + private static final String VERTICAL_TABLE_CLASSNAME = "vertical-table"; + + // additional styling for components + private static final String STYLE_SHEET_RULE + = String.format(" .%s { font-size: %dpx;font-style:italic; margin: 0px; padding: 0px; } ", MESSAGE_CLASSNAME, DEFAULT_FONT_SIZE) + + String.format(" .%s {font-size:%dpx;font-weight:bold; margin: 0px; margin-top: %dpx; padding: 0px; } ", SUBHEADER_CLASSNAME, SUBHEADER_FONT_SIZE, DEFAULT_SUBSECTION_SPACING) + + String.format(" .%s { font-size:%dpx;font-weight:bold; margin: 0px; padding: 0px; } ", HEADER_CLASSNAME, HEADER_FONT_SIZE) + + String.format(" td { vertical-align: top; font-size:%dpx; text-align: left; margin: 0px; padding: 0px %dpx 0px 0px;} ", DEFAULT_FONT_SIZE, CELL_SPACING) + + String.format(" th { vertical-align: top; text-align: left; margin: 0px; padding: 0px %dpx 0px 0px} ", DEFAULT_FONT_SIZE, CELL_SPACING) + + String.format(" .%s { margin: %dpx 0px; padding-left: %dpx; } ", SUBSECTION_CLASSNAME, DEFAULT_SUBSECTION_SPACING, DEFAULT_SUBSECTION_LEFT_PAD) + + String.format(" .%s { margin-bottom: %dpx; } ", SECTION_CLASSNAME, DEFAULT_SECTION_SPACING); + + // describing table values for a tag + private static final List> TAG_ENTRIES = Arrays.asList( + new ItemEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_tag(), + (tag) -> (tag.getName() != null) ? tag.getName().getDisplayName() : null), + new ItemEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_tagUser(), (tag) -> tag.getUserName()), + new ItemEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_comment(), (tag) -> tag.getComment()) + ); + + private static final SectionConfig ARTIFACT_TAG_CONFIG = new SectionConfig<>( + Bundle.AnnotationsContentViewer_tagEntry_title(), + Bundle.AnnotationsContentViewer_tagEntry_onArtifactEmpty(), + TAG_ENTRIES, true); + + private static final SectionConfig CONTENT_TAG_CONFIG = new SectionConfig<>( + Bundle.AnnotationsContentViewer_tagEntry_title(), + Bundle.AnnotationsContentViewer_tagEntry_onContentEmpty(), + TAG_ENTRIES, true); + + // file set attributes and table configurations + private static final List> FILESET_HIT_ENTRIES = Arrays.asList( + new ItemEntry<>(Bundle.AnnotationsContentViewer_fileHitEntry_setName(), + (bba) -> tryGetAttribute(bba, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)), + new ItemEntry<>(Bundle.AnnotationsContentViewer_fileHitEntry_comment(), + (bba) -> tryGetAttribute(bba, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT)) + ); + + private static final SectionConfig INTERESTING_FILE_CONFIG = new SectionConfig<>( + Bundle.AnnotationsContentViewer_fileHitEntry_interestingFileHitTitle(), + Bundle.AnnotationsContentViewer_fileHitEntry_onInterestingFileHitEmpty(), + FILESET_HIT_ENTRIES, false); + + private static final SectionConfig HASHSET_CONFIG = new SectionConfig<>( + Bundle.AnnotationsContentViewer_fileHitEntry_hashSetHitTitle(), + Bundle.AnnotationsContentViewer_fileHitEntry_onHashSetHitEmpty(), + FILESET_HIT_ENTRIES, false); + + // central repository attributes and table configuration + private static final List> CR_COMMENTS_ENTRIES = Arrays.asList( + new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(), + cai -> (cai.getCorrelationCase() != null) ? cai.getCorrelationCase().getDisplayName() : null), + new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_type(), + cai -> (cai.getCorrelationType() != null) ? cai.getCorrelationType().getDisplayName() : null), + new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_comment(), cai -> cai.getComment()), + new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), cai -> cai.getFilePath()) + ); + + private static final SectionConfig CR_COMMENTS_CONFIG = new SectionConfig<>( + Bundle.AnnotationsContentViewer_centralRepositoryEntry_title(), + Bundle.AnnotationsContentViewer_centralRepositoryEntry_onEmpty(), + CR_COMMENTS_ENTRIES, true); + /** * Creates an instance of AnnotationsContentViewer. */ public AnnotationsContentViewer() { initComponents(); Utilities.configureTextPaneAsHtml(jTextPane1); + // get html editor kit and apply additional style rules + EditorKit editorKit = jTextPane1.getEditorKit(); + if (editorKit instanceof HTMLEditorKit) { + HTMLEditorKit htmlKit = (HTMLEditorKit) editorKit; + htmlKit.getStyleSheet().addRule(STYLE_SHEET_RULE); + } } @Override @@ -198,81 +283,79 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data if (artifact != null) { renderArtifact(body, artifact, sourceFile); } else { - renderAbstractFile(body, sourceFile, false); + renderContent(body, sourceFile, false); } jTextPane1.setText(html.html()); jTextPane1.setCaretPosition(0); } + /** + * Renders annotations for an artifact. + * + * @param parent The html element to render content int. + * @param bba The blackboard artifact to render. + * @param sourceContent The content from which the blackboard artifact + * comes. + */ private static void renderArtifact(Element parent, BlackboardArtifact bba, Content sourceContent) { - appendEntries(parent, - Bundle.AnnotationsContentViewer_tagEntry_title(), - Bundle.AnnotationsContentViewer_tagEntry_onArtifactEmpty(), - getTags(bba), TAG_COLUMNS, false, true); + appendEntries(parent, ARTIFACT_TAG_CONFIG, getTags(bba), false); - if (sourceContent instanceof AbstractFile) { + if (sourceContent instanceof AbstractFile && CentralRepository.isEnabled()) { AbstractFile sourceFile = (AbstractFile) sourceContent; - - if (CentralRepository.isEnabled()) { - List centralRepoComments = getCentralRepositoryData(bba, sourceFile); - appendEntries(parent, - Bundle.AnnotationsContentViewer_centralRepositoryEntry_title(), - Bundle.AnnotationsContentViewer_centralRepositoryEntry_onEmpty(), - centralRepoComments, CENTRAL_REPO_COMMENTS_COLUMNS, false, true); - } + List centralRepoComments = getCentralRepositoryData(bba, sourceFile); + appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, false); } if (BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == bba.getArtifactTypeID()) { - appendEntries(parent, - Bundle.AnnotationsContentViewer_fileHitEntry_hashSetHitTitle(), - Bundle.AnnotationsContentViewer_fileHitEntry_onHashSetHitEmpty(), - Arrays.asList(bba), FILESET_HIT_COLUMNS, false, false); + appendEntries(parent, HASHSET_CONFIG, Arrays.asList(bba), false); } if (BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID()) { - appendEntries(parent, - Bundle.AnnotationsContentViewer_fileHitEntry_interestingFileHitTitle(), - Bundle.AnnotationsContentViewer_fileHitEntry_onInterestingFileHitEmpty(), - Arrays.asList(bba), FILESET_HIT_COLUMNS, false, false); + appendEntries(parent, INTERESTING_FILE_CONFIG, Arrays.asList(bba), false); } Element sourceFileSection = appendSection(parent, Bundle.AnnotationsContentViewer_sourceFile_title()); - renderAbstractFile(sourceFileSection, sourceContent, true); + renderContent(sourceFileSection, sourceContent, true); } - private static void renderAbstractFile(Element parent, Content sourceContent, boolean isSubheader) { - appendEntries(parent, - Bundle.AnnotationsContentViewer_tagEntry_title(), - Bundle.AnnotationsContentViewer_tagEntry_onContentEmpty(), - getTags(sourceContent), TAG_COLUMNS, isSubheader, true); + /** + * Renders annotations for a content item. + * + * @param parent The parent within which to render. + * @param sourceContent The content for which annotations will be gathered. + * @param isSubheader True if this section should be rendered as a + * subheader as opposed to a top-level header. + */ + private static void renderContent(Element parent, Content sourceContent, boolean isSubheader) { + appendEntries(parent, CONTENT_TAG_CONFIG, getTags(sourceContent), isSubheader); if (sourceContent instanceof AbstractFile) { AbstractFile sourceFile = (AbstractFile) sourceContent; if (CentralRepository.isEnabled()) { List centralRepoComments = getCentralRepositoryData(null, sourceFile); - appendEntries(parent, - Bundle.AnnotationsContentViewer_centralRepositoryEntry_title(), - Bundle.AnnotationsContentViewer_centralRepositoryEntry_onEmpty(), - centralRepoComments, CENTRAL_REPO_COMMENTS_COLUMNS, isSubheader, true); + appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, isSubheader); } - appendEntries(parent, - Bundle.AnnotationsContentViewer_fileHitEntry_hashSetHitTitle(), - Bundle.AnnotationsContentViewer_fileHitEntry_onHashSetHitEmpty(), - getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT), - FILESET_HIT_COLUMNS, isSubheader, false); + appendEntries(parent, HASHSET_CONFIG, + getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT), + isSubheader); - appendEntries(parent, - Bundle.AnnotationsContentViewer_fileHitEntry_interestingFileHitTitle(), - Bundle.AnnotationsContentViewer_fileHitEntry_onInterestingFileHitEmpty(), - getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT), - FILESET_HIT_COLUMNS, isSubheader, false); + appendEntries(parent, INTERESTING_FILE_CONFIG, + getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT), + isSubheader); } } + /** + * Retrieves tags associated with a content item. + * + * @param sourceContent The content for which to gather content. + * + * @return The Tags associated with this item. + */ private static List getTags(Content sourceContent) { try { SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); @@ -285,6 +368,12 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return new ArrayList<>(); } + /** + *Retrieves tags for blackboard artifact tags. + * @param bba The blackboard artifact for which to retrieve tags. + * + * @return The found tags. + */ private static List getTags(BlackboardArtifact bba) { try { SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); @@ -297,6 +386,12 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return new ArrayList<>(); } + /** + * Retrieves the blackboard artifacts for a source file matching a certain type. + * @param sourceFile The source file for which to fetch artifacts. + * @param type The type of blackboard artifact to fetch. + * @return The artifacts found matching this type. + */ private static List getFileSetHits(AbstractFile sourceFile, BlackboardArtifact.ARTIFACT_TYPE type) { try { SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); @@ -309,8 +404,6 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return new ArrayList<>(); } - - /** * Attempts to retrieve the attribute of a particular type from a blackboard * artifact. @@ -340,11 +433,12 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } /** - * Populate the "Central Repository Comments" section with data. + * Gets the "Central Repository Comments" section with data. * * @param artifact A selected artifact (can be null). * @param sourceFile A selected file, or a source file of the selected * artifact. + * @return The Correlation Attribute Instances associated with the artifact and/or sourcefile. */ private static List getCentralRepositoryData(BlackboardArtifact artifact, AbstractFile sourceFile) { List toReturn = new ArrayList<>(); @@ -393,40 +487,73 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return toReturn; } - - - private static void appendEntries(Element parent, String title, String errorMessage, List items, - List> fields, boolean isSubsection, boolean isVerticalTable) { - Element sectionDiv = (isSubsection) ? appendSubsection(parent, title) : appendSection(parent, title); + /** + * Append entries to the parent element in the annotations viewer. Entries will be formatted as a table + * in the format specified in the SectionConfig. + * @param The item type. + * @param parent The parent element for which the entries will be attached. + * @param config The display configuration for this entry type (i.e. table type, name, if data is not present). + * @param items The items to display. + * @param isSubsection Whether or not this should be displayed as a subsection. If not displayed as a top-level section. + */ + private static void appendEntries(Element parent, SectionConfig config, List items, + boolean isSubsection) { + + Element sectionDiv = (isSubsection) ? appendSubsection(parent, config.getTitle()) : appendSection(parent, config.getTitle()); if (items == null || items.isEmpty()) { - appendMessage(sectionDiv, errorMessage); - } else if (isVerticalTable) { - appendVerticalEntryTables(sectionDiv, items, fields); + appendMessage(sectionDiv, config.getOnEmpty()); + } else if (config.isIsVerticalTable()) { + appendVerticalEntryTables(sectionDiv, items, config.getAttributes()); } else { - appendEntryTable(sectionDiv, items, fields); + appendEntryTable(sectionDiv, items, config.getAttributes()); } } - private static Element appendVerticalEntryTables(Element parent, List items, List> rowHeaders) { - items.stream() - .filter(item -> item != null) - .forEach((item) -> { - List> tableData = rowHeaders.stream() - .map(row -> Arrays.asList(row.getColumnName(), row.retrieveValue(item))) - .collect(Collectors.toList()); + /** + * Appends a table where items are displayed in rows of key-value pairs. + * @param + * @param parent The parent to append the table. + * @param items The items to process into a series of tables. + * @param rowHeaders The keys and the means to process items in order to get key-value pairs. + * @return The parent element provided as parameter. + */ + private static Element appendVerticalEntryTables(Element parent, List items, List> rowHeaders) { + boolean isFirst = true; + for (T item : items) { + if (item == null) { + continue; + } - Element childTable = appendTable(parent, 2, tableData, null); - childTable.attr("style", String.format("margin-bottom: %dpx", DEFAULT_TABLE_SPACING)); - }); + List> tableData = rowHeaders.stream() + .map(row -> Arrays.asList(row.getItemName(), row.retrieveValue(item))) + .collect(Collectors.toList()); + + Element childTable = appendTable(parent, 2, tableData, null); + childTable.attr("class", VERTICAL_TABLE_CLASSNAME); + + if (isFirst) { + isFirst = false; + } else { + childTable.attr("style", String.format("margin-top: %dpx;", DEFAULT_TABLE_SPACING)); + } + } return parent; } - private static Element appendEntryTable(Element parent, List items, List> columns) { + /** + * Appends a table with column headers to the parent element. + * @param The item type. + * @param parent The element that will have this table appended to it. + * @param items The items to place as a row in this table. + * @param columns The columns for this table and the means to process each data item to retrieve a cell. + * @return The generated table element. + */ + private static Element appendEntryTable(Element parent, List items, List> columns) { int columnNumber = columns.size(); - List columnHeaders = columns.stream().map(c -> c.getColumnName()).collect(Collectors.toList()); + List columnHeaders = columns.stream().map(c -> c.getItemName()).collect(Collectors.toList()); List> rows = items.stream() .filter(r -> r != null) .map(r -> { @@ -437,14 +564,22 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data .collect(Collectors.toList()); Element table = appendTable(parent, columnNumber, rows, columnHeaders); - table.attr("style", String.format("margin-bottom: %dpx", DEFAULT_TABLE_SPACING)); + table.attr("class", ENTRY_TABLE_CLASSNAME); return table; } + /** + * Appends a generic table to the parent element. + * @param parent The parent element that will have a table appended to it. + * @param columnNumber The number of columns to append. + * @param content The content in content.get(row).get(column) format. + * @param columnHeaders The column headers or null if no column headers should be created. + * @return + */ private static Element appendTable(Element parent, int columnNumber, List> content, List columnHeaders) { Element table = parent.appendElement("table"); if (columnHeaders != null && !columnHeaders.isEmpty()) { - Element header = parent.appendElement("thead"); + Element header = table.appendElement("thead"); appendRow(header, columnHeaders, columnNumber, true); } Element tableBody = table.appendElement("tbody"); @@ -460,8 +595,6 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data for (int i = 0; i < columnNumber; i++) { Element cell = row.appendElement(cellType); if (data != null && i < data.size()) { - cell.attr("valign", "top"); - cell.attr("style", CONTENT_STYLE); cell.text(StringUtils.isEmpty(data.get(i)) ? "" : data.get(i)); } } @@ -470,26 +603,26 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data private static Element appendSection(Element parent, String headerText) { Element sectionDiv = parent.appendElement("div"); - sectionDiv.attr("style", String.format("margin-bottom: %dpx;", DEFAULT_SECTION_SPACING)); + sectionDiv.attr("class", SECTION_CLASSNAME); Element header = sectionDiv.appendElement("h1"); header.text(headerText); - header.attr("style", HEADER_STYLE); + header.attr("class", HEADER_CLASSNAME); return sectionDiv; } private static Element appendSubsection(Element parent, String headerText) { Element subsectionDiv = parent.appendElement("div"); - subsectionDiv.attr("style", String.format("margin-bottom: %dpx; padding-left: %dpx;", DEFAULT_SUBSECTION_SPACING, DEFAULT_SUBSECTION_LEFT_PAD)); + subsectionDiv.attr("class", SUBSECTION_CLASSNAME); Element header = subsectionDiv.appendElement("h2"); header.text(headerText); - header.attr("style", SUBHEADER_STYLE); + header.attr("class", SUBHEADER_CLASSNAME); return subsectionDiv; } private static Element appendMessage(Element parent, String message) { Element messageEl = parent.appendElement("p"); messageEl.text(message); - messageEl.attr("style", MESSAGE_STYLE); + messageEl.attr("class", MESSAGE_CLASSNAME); return messageEl; } From 6356a72591c2be46ca7b73302c9c3b885ae5e0f9 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 8 May 2020 16:02:40 -0400 Subject: [PATCH 47/90] commenting --- .../AnnotationsContentViewer.java | 140 ++++++++++++++---- .../contentviewers/Bundle.properties-MERGED | 14 +- 2 files changed, 122 insertions(+), 32 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index 7884f1a630..464574d977 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -81,12 +81,17 @@ import org.jsoup.nodes.Element; "AnnotationsContentViewer.fileHitEntry.onHashSetHitEmpty=There are no hash set hits for the selected content.", "AnnotationsContentViewer.fileHitEntry.interestingFileHitTitle=Interesting File Hit Comments", "AnnotationsContentViewer.fileHitEntry.onInterestingFileHitEmpty=There are no interesting file hits for the selected content.", - "AnnotationsContentViewer.fileHitEntry.setName=Set Name", - "AnnotationsContentViewer.fileHitEntry.comment=Comment", + "AnnotationsContentViewer.fileHitEntry.setName=Set Name:", + "AnnotationsContentViewer.fileHitEntry.comment=Comment:", "AnnotationsContentViewer.sourceFile.title=Source File" }) public class AnnotationsContentViewer extends javax.swing.JPanel implements DataContentViewer { + /** + * Describes a key value pair for an item of type T where the key is the field name to display and + * the value is retrieved from item of type T using a provided Function. + * @param The item type. + */ private static class ItemEntry { private final String itemName; @@ -110,6 +115,10 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } } + /** + * Describes a section that will be appended to the annotations view panel. + * @param The item type for items to display. + */ private static class SectionConfig { private final String title; @@ -124,18 +133,32 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data this.isVerticalTable = isVerticalTable; } + /** + * @return The title for the section. + */ String getTitle() { return title; } + /** + * @return The message to display if no items provided. + */ String getOnEmpty() { return onEmpty; } + /** + * @return Describes key-value pairs on the object to display to the user. + */ List> getAttributes() { return attributes; } + /** + * @return If the table should be shown as a series of key-value pairs as rows. Otherwise, + * data is shown in a table where the column headers are the keys and each row represents one + * item to display. + */ boolean isIsVerticalTable() { return isVerticalTable; } @@ -210,19 +233,17 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data private static final SectionConfig INTERESTING_FILE_CONFIG = new SectionConfig<>( Bundle.AnnotationsContentViewer_fileHitEntry_interestingFileHitTitle(), Bundle.AnnotationsContentViewer_fileHitEntry_onInterestingFileHitEmpty(), - FILESET_HIT_ENTRIES, false); + FILESET_HIT_ENTRIES, true); private static final SectionConfig HASHSET_CONFIG = new SectionConfig<>( Bundle.AnnotationsContentViewer_fileHitEntry_hashSetHitTitle(), Bundle.AnnotationsContentViewer_fileHitEntry_onHashSetHitEmpty(), - FILESET_HIT_ENTRIES, false); + FILESET_HIT_ENTRIES, true); // central repository attributes and table configuration private static final List> CR_COMMENTS_ENTRIES = Arrays.asList( new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(), cai -> (cai.getCorrelationCase() != null) ? cai.getCorrelationCase().getDisplayName() : null), - new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_type(), - cai -> (cai.getCorrelationType() != null) ? cai.getCorrelationType().getDisplayName() : null), new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_comment(), cai -> cai.getComment()), new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), cai -> cai.getFilePath()) ); @@ -369,8 +390,9 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } /** - *Retrieves tags for blackboard artifact tags. - * @param bba The blackboard artifact for which to retrieve tags. + * Retrieves tags for blackboard artifact tags. + * + * @param bba The blackboard artifact for which to retrieve tags. * * @return The found tags. */ @@ -387,9 +409,12 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } /** - * Retrieves the blackboard artifacts for a source file matching a certain type. + * Retrieves the blackboard artifacts for a source file matching a certain + * type. + * * @param sourceFile The source file for which to fetch artifacts. - * @param type The type of blackboard artifact to fetch. + * @param type The type of blackboard artifact to fetch. + * * @return The artifacts found matching this type. */ private static List getFileSetHits(AbstractFile sourceFile, BlackboardArtifact.ARTIFACT_TYPE type) { @@ -438,7 +463,9 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data * @param artifact A selected artifact (can be null). * @param sourceFile A selected file, or a source file of the selected * artifact. - * @return The Correlation Attribute Instances associated with the artifact and/or sourcefile. + * + * @return The Correlation Attribute Instances associated with the artifact + * and/or sourcefile. */ private static List getCentralRepositoryData(BlackboardArtifact artifact, AbstractFile sourceFile) { List toReturn = new ArrayList<>(); @@ -489,13 +516,18 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } /** - * Append entries to the parent element in the annotations viewer. Entries will be formatted as a table - * in the format specified in the SectionConfig. - * @param The item type. - * @param parent The parent element for which the entries will be attached. - * @param config The display configuration for this entry type (i.e. table type, name, if data is not present). - * @param items The items to display. - * @param isSubsection Whether or not this should be displayed as a subsection. If not displayed as a top-level section. + * Append entries to the parent element in the annotations viewer. Entries + * will be formatted as a table in the format specified in the + * SectionConfig. + * + * @param The item type. + * @param parent The parent element for which the entries will be + * attached. + * @param config The display configuration for this entry type (i.e. + * table type, name, if data is not present). + * @param items The items to display. + * @param isSubsection Whether or not this should be displayed as a + * subsection. If not displayed as a top-level section. */ private static void appendEntries(Element parent, SectionConfig config, List items, boolean isSubsection) { @@ -513,10 +545,13 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data /** * Appends a table where items are displayed in rows of key-value pairs. + * * @param - * @param parent The parent to append the table. - * @param items The items to process into a series of tables. - * @param rowHeaders The keys and the means to process items in order to get key-value pairs. + * @param parent The parent to append the table. + * @param items The items to process into a series of tables. + * @param rowHeaders The keys and the means to process items in order to get + * key-value pairs. + * * @return The parent element provided as parameter. */ private static Element appendVerticalEntryTables(Element parent, List items, List> rowHeaders) { @@ -545,10 +580,13 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data /** * Appends a table with column headers to the parent element. - * @param The item type. - * @param parent The element that will have this table appended to it. - * @param items The items to place as a row in this table. - * @param columns The columns for this table and the means to process each data item to retrieve a cell. + * + * @param The item type. + * @param parent The element that will have this table appended to it. + * @param items The items to place as a row in this table. + * @param columns The columns for this table and the means to process each + * data item to retrieve a cell. + * * @return The generated table element. */ private static Element appendEntryTable(Element parent, List items, List> columns) { @@ -570,11 +608,15 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data /** * Appends a generic table to the parent element. - * @param parent The parent element that will have a table appended to it. - * @param columnNumber The number of columns to append. - * @param content The content in content.get(row).get(column) format. - * @param columnHeaders The column headers or null if no column headers should be created. - * @return + * + * @param parent The parent element that will have a table appended + * to it. + * @param columnNumber The number of columns to append. + * @param content The content in content.get(row).get(column) format. + * @param columnHeaders The column headers or null if no column headers + * should be created. + * + * @return The created table. */ private static Element appendTable(Element parent, int columnNumber, List> content, List columnHeaders) { Element table = parent.appendElement("table"); @@ -588,7 +630,17 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return table; } - // TODO test sanitizing string + /** + * Appends a row to the parent element (should be thead or tbody). + * + * @param rowParent The parent table element. + * @param data The data to place in columns within the table. + * @param columnNumber The number of columns to append. + * @param isHeader Whether or not this should have header cells ('th') + * instead of regular cells ('td'). + * + * @return The row created. + */ private static Element appendRow(Element rowParent, List data, int columnNumber, boolean isHeader) { String cellType = isHeader ? "th" : "td"; Element row = rowParent.appendElement("tr"); @@ -601,6 +653,14 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return row; } + /** + * Appends a new section with a section header to the parent element. + * + * @param parent The element to append this section to. + * @param headerText The text for the section. + * + * @return The div for the new section. + */ private static Element appendSection(Element parent, String headerText) { Element sectionDiv = parent.appendElement("div"); sectionDiv.attr("class", SECTION_CLASSNAME); @@ -610,6 +670,14 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return sectionDiv; } + /** + * Appends a new subsection with a subsection header to the parent element. + * + * @param parent The element to append this subsection to. + * @param headerText The text for the subsection. + * + * @return The div for the new subsection. + */ private static Element appendSubsection(Element parent, String headerText) { Element subsectionDiv = parent.appendElement("div"); subsectionDiv.attr("class", SUBSECTION_CLASSNAME); @@ -619,6 +687,16 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return subsectionDiv; } + /** + * Appends a message to the parent element. This is typically used in the + * event that no data exists for a certain type. + * + * @param parent The parent element that will have this message appended to + * it. + * @param message The message to append. + * + * @return The paragraph element for the new message. + */ private static Element appendMessage(Element parent, String message) { Element messageEl = parent.appendElement("p"); messageEl.text(message); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED index fd9d2d345e..893d2f705a 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED @@ -15,13 +15,25 @@ # governing permissions and limitations under the License. # +AnnotationsContentViewer.centralRepositoryEntry.onEmpty=There is no comment data for the selected content in the Central Repository. +AnnotationsContentViewer.centralRepositoryEntry.title=Central Repository Comments AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=Case: AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment: AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path: AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type: +AnnotationsContentViewer.fileHitEntry.comment=Comment: +AnnotationsContentViewer.fileHitEntry.hashSetHitTitle=Hash Set Hit Comments +AnnotationsContentViewer.fileHitEntry.interestingFileHitTitle=Interesting File Hit Comments +AnnotationsContentViewer.fileHitEntry.onHashSetHitEmpty=There are no hash set hits for the selected content. +AnnotationsContentViewer.fileHitEntry.onInterestingFileHitEmpty=There are no interesting file hits for the selected content. +AnnotationsContentViewer.fileHitEntry.setName=Set Name: +AnnotationsContentViewer.sourceFile.title=Source File +AnnotationsContentViewer.tagEntry.onArtifactEmpty=There are no tags for the selected artifact. +AnnotationsContentViewer.tagEntry.onContentEmpty=There are no tags for the selected content. +AnnotationsContentViewer.tagEntry.title=Tags AnnotationsContentViewer.tagEntryDataLabel.comment=Comment: AnnotationsContentViewer.tagEntryDataLabel.tag=Tag: -AnnotationsContentViewer.tagEntryDataLabel.tagUser=Tag User: +AnnotationsContentViewer.tagEntryDataLabel.tagUser=Examiner: AnnotationsContentViewer.title=Annotations AnnotationsContentViewer.toolTip=Displays tags and comments associated with the selected content. ApplicationContentViewer.title=Application From f5ec04548b5a20f100cba26e1b364e8a9ae06c0b Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Fri, 8 May 2020 16:23:42 -0400 Subject: [PATCH 48/90] Interim commit - DefaultArtifactContentViewer now implements ArtifactContentViewer, though it does nothing with the artifact yet. --- .../DefaultArtifactContentViewer.java | 95 +++---------------- 1 file changed, 14 insertions(+), 81 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.java index b72320c8b9..3b6515a8ca 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.java @@ -45,12 +45,9 @@ import org.apache.commons.lang.StringUtils; import org.openide.nodes.Node; import org.openide.util.Lookup; import org.openide.util.NbBundle; -import org.openide.util.lookup.ServiceProvider; -import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskCoreException; @@ -63,13 +60,12 @@ import com.google.gson.JsonArray; import java.util.Map; /** - * Instances of this class display the BlackboardArtifacts associated with the - * Content represented by a Node. Each BlackboardArtifact is rendered displayed - * in a JTable representation of its BlackboardAttributes. + * This class displays a Blackboard artifact as a table listing all the + * attribute names and values. */ -@ServiceProvider(service = DataContentViewer.class, position = 11) + @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives -public class DefaultArtifactContentViewer extends javax.swing.JPanel implements DataContentViewer { +public class DefaultArtifactContentViewer extends javax.swing.JPanel implements ArtifactContentViewer { @NbBundle.Messages({ "DataContentViewerArtifact.attrsTableHeader.type=Type", @@ -81,11 +77,16 @@ public class DefaultArtifactContentViewer extends javax.swing.JPanel implements private final static Logger logger = Logger.getLogger(DefaultArtifactContentViewer.class.getName()); private final static String WAIT_TEXT = NbBundle.getMessage(DefaultArtifactContentViewer.class, "DataContentViewerArtifact.waitText"); private final static String ERROR_TEXT = NbBundle.getMessage(DefaultArtifactContentViewer.class, "DataContentViewerArtifact.errorText"); + + private static final long serialVersionUID = 1L; + private Node currentNode; // @@@ Remove this when the redundant setNode() calls problem is fixed. private int currentPage = 1; private final Object lock = new Object(); + private List artifactTableContents; // Accessed by multiple threads, use getArtifactContents() and setArtifactContents() SwingWorker currentTask; // Accessed by multiple threads, use startNewTask() + private static final String[] COLUMN_HEADERS = { Bundle.DataContentViewerArtifact_attrsTableHeader_type(), Bundle.DataContentViewerArtifact_attrsTableHeader_value(), @@ -437,88 +438,20 @@ public class DefaultArtifactContentViewer extends javax.swing.JPanel implements currentNode = null; } - @Override - public void setNode(Node selectedNode) { - if (currentNode == selectedNode) { - return; - } - currentNode = selectedNode; - - // Make sure there is a node. Null might be passed to reset the viewer. - if (selectedNode == null) { - return; - } - - // Make sure the node is of the correct type. - Lookup lookup = selectedNode.getLookup(); - Content content = lookup.lookup(Content.class); - if (content == null) { - return; - } - - startNewTask(new SelectedNodeChangedTask(selectedNode)); - } - - @Override - public String getTitle() { - return NbBundle.getMessage(this.getClass(), "DataContentViewerArtifact.title"); - } - - @Override - public String getToolTip() { - return NbBundle.getMessage(this.getClass(), "DataContentViewerArtifact.toolTip"); - } - - @Override - public DataContentViewer createInstance() { - return new DefaultArtifactContentViewer(); - } - @Override public Component getComponent() { return this; } @Override - public void resetComponent() { - resetComponents(); + public void setArtifact(BlackboardArtifact artifact) { + // RAMAN TBD: ****************** IMPLMENT THIS. ********************** + } @Override - public boolean isSupported(Node node) { - if (node == null) { - return false; - } - - for (Content content : node.getLookup().lookupAll(Content.class)) { - if ( (content != null) && (!(content instanceof BlackboardArtifact)) ){ - try { - return content.getAllArtifactsCount() > 0; - } catch (TskException ex) { - logger.log(Level.SEVERE, "Couldn't get count of BlackboardArtifacts for content", ex); //NON-NLS - } - } - } - return false; - } - - @Override - public int isPreferred(Node node) { - BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class); - // low priority if node doesn't have an artifact (meaning it was found from normal directory - // browsing, or if the artifact is something that means the user really wants to see the original - // file and not more details about the artifact - if ((artifact == null) - || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) - || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) - || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()) - || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID()) - || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()) - || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID())) { - return 3; - } else { - return 6; - } + public boolean isSupported(BlackboardArtifact artifact) { + return true; } /** From 3925645114b1aa1e156df07b8eba25f1a01bac3b Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Sun, 10 May 2020 15:56:45 -0400 Subject: [PATCH 49/90] Fixed IG button typo --- .../autopsy/imagegallery/gui/drawableviews/GroupPane.fxml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.fxml b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.fxml index 5dcd725381..d01cea5c08 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.fxml +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.fxml @@ -61,7 +61,7 @@ -
        - - - - - - - - - - - - -
        + diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java index 5631f80a78..d22ad25f39 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java @@ -18,10 +18,20 @@ */ package org.sleuthkit.autopsy.persona; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Collection; +import java.util.Collections; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableModel; +import org.openide.util.Exceptions; import org.openide.util.NbBundle.Messages; import org.openide.windows.RetainLocation; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; +import org.sleuthkit.autopsy.centralrepository.datamodel.Persona; /** * Top component for the Personas tool @@ -39,6 +49,50 @@ public final class PersonasTopComponent extends TopComponent { public PersonasTopComponent() { initComponents(); setName(Bundle.PTopComponent_Name()); + executeSearch(); + + searchBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + executeSearch(); + } + }); + } + + public class PersonaFilterTableModel extends DefaultTableModel { + PersonaFilterTableModel(Object[][] rows, String[] colNames) { + super(rows, colNames); + } + + public boolean isCellEditable(int row, int column) { + return false; + } + } + + void updateResultsTable(Collection results) { + Object[][] rows = new Object[results.size()][2]; + int i = 0; + for (Persona result : results) { + rows[i] = new String[]{String.valueOf(result.getId()), result.getName()}; + i++; + } + DefaultTableModel updatedTableModel = new PersonaFilterTableModel( + rows, + new String[]{"ID", "Name"} + ); + + filterResultsTable.setModel(updatedTableModel); + } + + void executeSearch() { + System.out.println("Search!"); + Collection results = Collections.EMPTY_LIST; + try { + results = Persona.getPersonaByName(searchField.getText()); + } catch (CentralRepoException ex) { + Exceptions.printStackTrace(ex); + } + updateResultsTable(results); } @Override @@ -95,23 +149,15 @@ public final class PersonasTopComponent extends TopComponent { filterResultsTable.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { - {"0", "Johnathn Dough"}, - {"3", "Joe Schmoe"}, - {"2", "Michael Schmoe"}, - {"1", "Ethan Schmoe"} + {}, + {}, + {}, + {} }, new String [] { - "ID", "Name" - } - ) { - Class[] types = new Class [] { - java.lang.String.class, java.lang.String.class - }; - public Class getColumnClass(int columnIndex) { - return types [columnIndex]; } - }); + )); filterResultsPane.setViewportView(filterResultsTable); if (filterResultsTable.getColumnModel().getColumnCount() > 0) { filterResultsTable.getColumnModel().getColumn(0).setMaxWidth(25); From d30bcda8a942aa152656104898c0b7d3994d8ab3 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Tue, 12 May 2020 12:35:29 -0400 Subject: [PATCH 59/90] Removed an unused subpanel that was causing extra white space. --- .../DefaultArtifactContentViewer.form | 28 ++----------------- .../DefaultArtifactContentViewer.java | 19 ++----------- 2 files changed, 4 insertions(+), 43 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.form index 37ea0f00fa..eb1f729611 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.form @@ -45,40 +45,16 @@ - - + - - - - - + - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.java index 660f67a516..d77ca887d8 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/DefaultArtifactContentViewer.java @@ -199,8 +199,6 @@ public class DefaultArtifactContentViewer extends javax.swing.JPanel implements rightClickMenu = new javax.swing.JPopupMenu(); copyMenuItem = new javax.swing.JMenuItem(); selectAllMenuItem = new javax.swing.JMenuItem(); - jScrollPane1 = new javax.swing.JScrollPane(); - jPanel1 = new javax.swing.JPanel(); resultsTableScrollPane = new javax.swing.JScrollPane(); copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DefaultArtifactContentViewer.class, "DefaultArtifactContentViewer.copyMenuItem.text")); // NOI18N @@ -211,13 +209,6 @@ public class DefaultArtifactContentViewer extends javax.swing.JPanel implements setPreferredSize(new java.awt.Dimension(100, 58)); - jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); - - jPanel1.setPreferredSize(new java.awt.Dimension(620, 58)); - jPanel1.setLayout(new java.awt.GridBagLayout()); - jScrollPane1.setViewportView(jPanel1); - resultsTableScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); resultsTableScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); resultsTableScrollPane.setPreferredSize(new java.awt.Dimension(620, 34)); @@ -226,22 +217,16 @@ public class DefaultArtifactContentViewer extends javax.swing.JPanel implements this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1) - .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(resultsTableScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 58, Short.MAX_VALUE) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JMenuItem copyMenuItem; - private javax.swing.JPanel jPanel1; - private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane resultsTableScrollPane; private javax.swing.JPopupMenu rightClickMenu; private javax.swing.JMenuItem selectAllMenuItem; From df1c1763a8b0ca2875719f7198322382e4e496c5 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 12 May 2020 12:46:37 -0400 Subject: [PATCH 60/90] update for Artifact Comment --- .../AnnotationsContentViewer.java | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index 464574d977..a96b6c8d74 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -77,6 +77,7 @@ import org.jsoup.nodes.Element; "AnnotationsContentViewer.tagEntryDataLabel.tag=Tag:", "AnnotationsContentViewer.tagEntryDataLabel.tagUser=Examiner:", "AnnotationsContentViewer.tagEntryDataLabel.comment=Comment:", + "AnnotationsContentViewer.fileHitEntry.artifactCommentTitle=Artifact Comment", "AnnotationsContentViewer.fileHitEntry.hashSetHitTitle=Hash Set Hit Comments", "AnnotationsContentViewer.fileHitEntry.onHashSetHitEmpty=There are no hash set hits for the selected content.", "AnnotationsContentViewer.fileHitEntry.interestingFileHitTitle=Interesting File Hit Comments", @@ -88,8 +89,10 @@ import org.jsoup.nodes.Element; public class AnnotationsContentViewer extends javax.swing.JPanel implements DataContentViewer { /** - * Describes a key value pair for an item of type T where the key is the field name to display and - * the value is retrieved from item of type T using a provided Function. + * Describes a key value pair for an item of type T where the key is the + * field name to display and the value is retrieved from item of type T + * using a provided Function. + * * @param The item type. */ private static class ItemEntry { @@ -117,6 +120,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data /** * Describes a section that will be appended to the annotations view panel. + * * @param The item type for items to display. */ private static class SectionConfig { @@ -148,16 +152,18 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } /** - * @return Describes key-value pairs on the object to display to the user. + * @return Describes key-value pairs on the object to display to the + * user. */ List> getAttributes() { return attributes; } /** - * @return If the table should be shown as a series of key-value pairs as rows. Otherwise, - * data is shown in a table where the column headers are the keys and each row represents one - * item to display. + * @return If the table should be shown as a series of key-value pairs + * as rows. Otherwise, data is shown in a table where the column + * headers are the keys and each row represents one item to + * display. */ boolean isIsVerticalTable() { return isVerticalTable; @@ -240,6 +246,11 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data Bundle.AnnotationsContentViewer_fileHitEntry_onHashSetHitEmpty(), FILESET_HIT_ENTRIES, true); + private static final SectionConfig ARTIFACT_COMMENT_CONFIG = new SectionConfig<>( + Bundle.AnnotationsContentViewer_fileHitEntry_artifactCommentTitle(), + "", + FILESET_HIT_ENTRIES, true); + // central repository attributes and table configuration private static final List> CR_COMMENTS_ENTRIES = Arrays.asList( new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(), @@ -328,12 +339,9 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, false); } - if (BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == bba.getArtifactTypeID()) { - appendEntries(parent, HASHSET_CONFIG, Arrays.asList(bba), false); - } - - if (BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID()) { - appendEntries(parent, INTERESTING_FILE_CONFIG, Arrays.asList(bba), false); + if (BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == bba.getArtifactTypeID() + || BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID()) { + appendEntries(parent, ARTIFACT_COMMENT_CONFIG, Arrays.asList(bba), false); } Element sourceFileSection = appendSection(parent, Bundle.AnnotationsContentViewer_sourceFile_title()); From 6fe57311560909b3322af89b6eb8c8dfcbd2e2d1 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 12 May 2020 13:13:46 -0400 Subject: [PATCH 61/90] only accept local events --- .../centralrepository/eventlisteners/CaseEventListener.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index d8bd1c43c3..67c194fda7 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -55,6 +55,7 @@ import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.events.AutopsyEvent; /** * Listen for case events and update entries in the Central Repository database @@ -86,6 +87,10 @@ final class CaseEventListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { + if (!(evt instanceof AutopsyEvent) || (((AutopsyEvent) evt).getSourceType() != AutopsyEvent.SourceType.LOCAL)) { + return; + } + CentralRepository dbManager; try { dbManager = CentralRepository.getInstance(); From 72e647b349112834daf0f624267b0149698d5002 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 12 May 2020 13:20:15 -0400 Subject: [PATCH 62/90] TagsManager review changes --- .../org/sleuthkit/autopsy/casemodule/services/TagsManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 7355a8db03..d53a7b7c72 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -173,7 +173,7 @@ public class TagsManager implements Closeable { * No current case, nothing more to add to the set. */ } catch(TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Faile to get list of TagNams from tagsManager."); + LOGGER.log(Level.SEVERE, "Failed to get list of TagNams from tagsManager.", ex); } return tagDisplayNames; } From cec1c897b322f62ff407cf0dd70848a4f8ec957a Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 12 May 2020 15:47:51 -0400 Subject: [PATCH 63/90] Fixed typo in TagsManager error message --- .../org/sleuthkit/autopsy/casemodule/services/TagsManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index d53a7b7c72..8af7cd7efa 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -173,7 +173,7 @@ public class TagsManager implements Closeable { * No current case, nothing more to add to the set. */ } catch(TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Failed to get list of TagNams from tagsManager.", ex); + LOGGER.log(Level.SEVERE, "Failed to get list of TagNames from TagsManager.", ex); } return tagDisplayNames; } From d119704a64d4adb6a0211c769246a6612ea7819b Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Tue, 12 May 2020 17:03:09 -0400 Subject: [PATCH 64/90] Interim commit - Skeleton for Contact Artifact viewer --- .../autopsy/contentviewers/Bundle.properties | 3 + .../contentviewers/ContactArtifactViewer.form | 101 +++++++++ .../contentviewers/ContactArtifactViewer.java | 206 ++++++++++++++++++ .../DataContentViewerArtifact.java | 3 +- 4 files changed, 312 insertions(+), 1 deletion(-) create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form create mode 100644 Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties index 60afbe4051..8bec0c4b15 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties @@ -956,3 +956,6 @@ manager.properties.brokenProperty = Broken default property {0} value: {1} manager.properties.missingProperty = Missing default property {0} value: {1} DefaultArtifactContentViewer.copyMenuItem.text=Copy DefaultArtifactContentViewer.selectAllMenuItem.text=Select All +ContactArtifactViewer.contactNameLabel.text=Joanna Doe +ContactArtifactViewer.phonesLabel.text=Phone +ContactArtifactViewer.emailsLabel.text=Email diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form new file mode 100644 index 0000000000..58e8520202 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form @@ -0,0 +1,101 @@ + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java new file mode 100644 index 0000000000..33cb2258bc --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java @@ -0,0 +1,206 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.contentviewers; + +import java.awt.Component; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * This class displays TSK_CONTACT artifact. + */ +public class ContactArtifactViewer extends javax.swing.JPanel implements ArtifactContentViewer { + + private final static Logger logger = Logger.getLogger(ContactArtifactViewer.class.getName()); + private static final long serialVersionUID = 1L; + + /** + * Creates new form ContactArtifactViewer + */ + public ContactArtifactViewer() { + initComponents(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + namePanel = new javax.swing.JPanel(); + contactNameLabel = new javax.swing.JLabel(); + phonesLabel = new javax.swing.JLabel(); + phoneNumbersPanel = new javax.swing.JPanel(); + emailsLabel = new javax.swing.JLabel(); + emailsPanel = new javax.swing.JPanel(); + + setLayout(new java.awt.GridBagLayout()); + + contactNameLabel.setFont(new java.awt.Font("Dialog", 2, 18)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(contactNameLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.contactNameLabel.text")); // NOI18N + + javax.swing.GroupLayout namePanelLayout = new javax.swing.GroupLayout(namePanel); + namePanel.setLayout(namePanelLayout); + namePanelLayout.setHorizontalGroup( + namePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(namePanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(contactNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 161, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(233, Short.MAX_VALUE)) + ); + namePanelLayout.setVerticalGroup( + namePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(namePanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(contactNameLabel) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.ipadx = 227; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + add(namePanel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(phonesLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.phonesLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(12, 19, 0, 0); + add(phonesLabel, gridBagConstraints); + + phoneNumbersPanel.setLayout(new java.awt.GridBagLayout()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.ipadx = 400; + gridBagConstraints.ipady = 101; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0); + add(phoneNumbersPanel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(emailsLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.emailsLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); + add(emailsLabel, gridBagConstraints); + + emailsPanel.setLayout(new java.awt.GridBagLayout()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 4; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.ipadx = 400; + gridBagConstraints.ipady = 106; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 0); + add(emailsPanel, gridBagConstraints); + }// //GEN-END:initComponents + + @Override + public void setArtifact(BlackboardArtifact artifact) { + + // wipe the panel clean + this.removeAll(); + initComponents(); + + List phoneNumList = new ArrayList<>(); + List emailList = new ArrayList<>(); + List nameList = new ArrayList<>(); + List otherList = new ArrayList<>(); + + + + try { + // RAMAN TBD: populate the display components from the artifact + for (BlackboardAttribute bba : artifact.getAttributes()) { + if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) { + phoneNumList.add(bba); + } else if (bba.getAttributeType().getTypeName().startsWith("TSK_EMAIL")) { + emailList.add(bba); + } else if (bba.getAttributeType().getTypeName().startsWith("TSK_NAME")) { + nameList.add(bba); + } else { + otherList.add(bba); + } + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); + } + + setContactName(nameList); + + // TBD: set the phones + //this.phonesLabel.setVisible(true); + + // TBD: set the emails + + + // repaint + + this.revalidate(); + } + + @Override + public Component getComponent() { + return this; + } + + @Override + public boolean isSupported(BlackboardArtifact artifact) { + return artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID(); + } + + private void setContactName(List attributesList) { + for (BlackboardAttribute bba : attributesList) { + if (bba.getAttributeType().getTypeName().startsWith("TSK_NAME")) { + contactNameLabel.setText(bba.getDisplayString()); + System.out.println("Setting contact name to: " + bba.getDisplayString()); + break; + } + } + + contactNameLabel.revalidate(); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel contactNameLabel; + private javax.swing.JLabel emailsLabel; + private javax.swing.JPanel emailsPanel; + private javax.swing.JPanel namePanel; + private javax.swing.JPanel phoneNumbersPanel; + private javax.swing.JLabel phonesLabel; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java index 23116a5d11..d6afb1f420 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java @@ -41,6 +41,7 @@ import org.sleuthkit.datamodel.TskException; import java.util.Arrays; import java.util.Collections; import org.sleuthkit.autopsy.contentviewers.ArtifactContentViewer; +import org.sleuthkit.autopsy.contentviewers.ContactArtifactViewer; import org.sleuthkit.autopsy.contentviewers.DefaultArtifactContentViewer; /** @@ -73,7 +74,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat private final Collection KNOWN_ARTIFACT_VIEWERS = Arrays.asList( - // TBD: populate with custom artifact viewers. + new ContactArtifactViewer() ); public DataContentViewerArtifact() { From 559d317bb406d4a3bc9d31b9c904922c994c3043 Mon Sep 17 00:00:00 2001 From: apriestman Date: Wed, 13 May 2020 09:45:11 -0400 Subject: [PATCH 65/90] Remove locking around DSPs --- .../datasourceprocessors/AddRawImageTask.java | 4 +- .../dsp/AddMultipleImagesTask.java | 43 ++++++++----------- .../volatilityDSP/AddMemoryImageTask.java | 39 ++++++++--------- 3 files changed, 35 insertions(+), 51 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java index e85f1ac3d5..b416197e19 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java @@ -126,6 +126,7 @@ final class AddRawImageTask implements Runnable { "AddRawImageTask.noOpenCase.errMsg=No open case available."}) private void addImageToCase(List dataSources, List errorMessages) { SleuthkitCase caseDatabase; + System.out.println("\n### AddRawImageTask: Adding image to case!"); try { caseDatabase = Case.getCurrentCaseThrows().getSleuthkitCase(); } catch (NoCurrentCaseException ex) { @@ -147,7 +148,6 @@ final class AddRawImageTask implements Runnable { } imageFilePaths.add(imageFilePath); try { - caseDatabase.acquireSingleUserCaseWriteLock(); /* * Get Image that will be added to case */ @@ -187,8 +187,6 @@ final class AddRawImageTask implements Runnable { errorMessages.add(errorMessage); logger.log(Level.SEVERE, errorMessage, ex); criticalErrorOccurred = true; - } finally { - caseDatabase.releaseSingleUserCaseWriteLock(); } } diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddMultipleImagesTask.java b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddMultipleImagesTask.java index 54bf3590db..bedf15bdae 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddMultipleImagesTask.java +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddMultipleImagesTask.java @@ -116,30 +116,25 @@ class AddMultipleImagesTask implements Runnable { * Try to add the input image files as images. */ List corruptedImageFilePaths = new ArrayList<>(); - try { - currentCase.getSleuthkitCase().acquireSingleUserCaseWriteLock(); - progressMonitor.setIndeterminate(true); - for (String imageFilePath : imageFilePaths) { - synchronized (tskAddImageProcessLock) { - if (!tskAddImageProcessStopped) { - addImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, false, false, ""); - } else { - return; - } - } - run(imageFilePath, corruptedImageFilePaths, errorMessages); - commitOrRevertAddImageProcess(imageFilePath, errorMessages, newDataSources); - synchronized (tskAddImageProcessLock) { - if (tskAddImageProcessStopped) { - errorMessages.add(Bundle.AddMultipleImagesTask_cancelled()); - result = DataSourceProcessorResult.CRITICAL_ERRORS; - newDataSources = emptyDataSources; - return; - } + progressMonitor.setIndeterminate(true); + for (String imageFilePath : imageFilePaths) { + synchronized (tskAddImageProcessLock) { + if (!tskAddImageProcessStopped) { + addImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, false, false, ""); + } else { + return; + } + } + run(imageFilePath, corruptedImageFilePaths, errorMessages); + commitOrRevertAddImageProcess(imageFilePath, errorMessages, newDataSources); + synchronized (tskAddImageProcessLock) { + if (tskAddImageProcessStopped) { + errorMessages.add(Bundle.AddMultipleImagesTask_cancelled()); + result = DataSourceProcessorResult.CRITICAL_ERRORS; + newDataSources = emptyDataSources; + return; } } - } finally { - currentCase.getSleuthkitCase().releaseSingleUserCaseWriteLock(); } /* @@ -153,8 +148,6 @@ class AddMultipleImagesTask implements Runnable { try { progressMonitor.setProgressText(Bundle.AddMultipleImagesTask_addingFileAsLogicalFile(corruptedImageFilePaths.toString())); - caseDatabase.acquireSingleUserCaseWriteLock(); - Image dataSource = caseDatabase.addImageInfo(0, corruptedImageFilePaths, timeZone); newDataSources.add(dataSource); List fileRanges = new ArrayList<>(); @@ -177,8 +170,6 @@ class AddMultipleImagesTask implements Runnable { } catch (TskCoreException ex) { errorMessages.add(Bundle.AddMultipleImagesTask_errorAddingImgWithoutFileSystem(deviceId, ex.getLocalizedMessage())); criticalErrorOccurred = true; - } finally { - caseDatabase.releaseSingleUserCaseWriteLock(); } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/AddMemoryImageTask.java b/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/AddMemoryImageTask.java index bcae2b3153..7262d9f53e 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/AddMemoryImageTask.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/AddMemoryImageTask.java @@ -146,30 +146,25 @@ final class AddMemoryImageTask implements Runnable { progressMonitor.setProgressText(Bundle.AddMemoryImageTask_progressMessage_addingImageFile( memoryImagePath)); SleuthkitCase caseDatabase = Case.getCurrentCaseThrows().getSleuthkitCase(); - caseDatabase.acquireSingleUserCaseWriteLock(); - try { - /* - * Verify the memory image file exists. - */ - File imageFile = Paths.get(memoryImagePath).toFile(); - if (!imageFile.exists()) { - throw new TskCoreException(Bundle.AddMemoryImageTask_exceptionMessage_noImageFile(memoryImagePath, deviceId)); - } - /* - * Add the data source. - * - * NOTE: The object id for device passed to - * SleuthkitCase.addImageInfo is hard-coded to zero for now. This - * will need to be changed when a Device abstraction is added to the - * SleuthKit data model. - */ - Image dataSource = caseDatabase.addImageInfo(0, new ArrayList<>(Arrays.asList(memoryImagePath)), timeZone); - return dataSource; - - } finally { - caseDatabase.releaseSingleUserCaseWriteLock(); + /* + * Verify the memory image file exists. + */ + File imageFile = Paths.get(memoryImagePath).toFile(); + if (!imageFile.exists()) { + throw new TskCoreException(Bundle.AddMemoryImageTask_exceptionMessage_noImageFile(memoryImagePath, deviceId)); } + + /* + * Add the data source. + * + * NOTE: The object id for device passed to + * SleuthkitCase.addImageInfo is hard-coded to zero for now. This + * will need to be changed when a Device abstraction is added to the + * SleuthKit data model. + */ + Image dataSource = caseDatabase.addImageInfo(0, new ArrayList<>(Arrays.asList(memoryImagePath)), timeZone); + return dataSource; } /** From 6a462ccd0b3187c45ff2893acd644a714496ad6a Mon Sep 17 00:00:00 2001 From: apriestman Date: Wed, 13 May 2020 12:37:59 -0400 Subject: [PATCH 66/90] Revert "Remove locking around DSPs" This reverts commit 559d317bb406d4a3bc9d31b9c904922c994c3043. --- .../datasourceprocessors/AddRawImageTask.java | 4 +- .../dsp/AddMultipleImagesTask.java | 43 +++++++++++-------- .../volatilityDSP/AddMemoryImageTask.java | 39 +++++++++-------- 3 files changed, 51 insertions(+), 35 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java index b416197e19..e85f1ac3d5 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java @@ -126,7 +126,6 @@ final class AddRawImageTask implements Runnable { "AddRawImageTask.noOpenCase.errMsg=No open case available."}) private void addImageToCase(List dataSources, List errorMessages) { SleuthkitCase caseDatabase; - System.out.println("\n### AddRawImageTask: Adding image to case!"); try { caseDatabase = Case.getCurrentCaseThrows().getSleuthkitCase(); } catch (NoCurrentCaseException ex) { @@ -148,6 +147,7 @@ final class AddRawImageTask implements Runnable { } imageFilePaths.add(imageFilePath); try { + caseDatabase.acquireSingleUserCaseWriteLock(); /* * Get Image that will be added to case */ @@ -187,6 +187,8 @@ final class AddRawImageTask implements Runnable { errorMessages.add(errorMessage); logger.log(Level.SEVERE, errorMessage, ex); criticalErrorOccurred = true; + } finally { + caseDatabase.releaseSingleUserCaseWriteLock(); } } diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddMultipleImagesTask.java b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddMultipleImagesTask.java index bedf15bdae..54bf3590db 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddMultipleImagesTask.java +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddMultipleImagesTask.java @@ -116,25 +116,30 @@ class AddMultipleImagesTask implements Runnable { * Try to add the input image files as images. */ List corruptedImageFilePaths = new ArrayList<>(); - progressMonitor.setIndeterminate(true); - for (String imageFilePath : imageFilePaths) { - synchronized (tskAddImageProcessLock) { - if (!tskAddImageProcessStopped) { - addImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, false, false, ""); - } else { - return; - } - } - run(imageFilePath, corruptedImageFilePaths, errorMessages); - commitOrRevertAddImageProcess(imageFilePath, errorMessages, newDataSources); - synchronized (tskAddImageProcessLock) { - if (tskAddImageProcessStopped) { - errorMessages.add(Bundle.AddMultipleImagesTask_cancelled()); - result = DataSourceProcessorResult.CRITICAL_ERRORS; - newDataSources = emptyDataSources; - return; + try { + currentCase.getSleuthkitCase().acquireSingleUserCaseWriteLock(); + progressMonitor.setIndeterminate(true); + for (String imageFilePath : imageFilePaths) { + synchronized (tskAddImageProcessLock) { + if (!tskAddImageProcessStopped) { + addImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, false, false, ""); + } else { + return; + } + } + run(imageFilePath, corruptedImageFilePaths, errorMessages); + commitOrRevertAddImageProcess(imageFilePath, errorMessages, newDataSources); + synchronized (tskAddImageProcessLock) { + if (tskAddImageProcessStopped) { + errorMessages.add(Bundle.AddMultipleImagesTask_cancelled()); + result = DataSourceProcessorResult.CRITICAL_ERRORS; + newDataSources = emptyDataSources; + return; + } } } + } finally { + currentCase.getSleuthkitCase().releaseSingleUserCaseWriteLock(); } /* @@ -148,6 +153,8 @@ class AddMultipleImagesTask implements Runnable { try { progressMonitor.setProgressText(Bundle.AddMultipleImagesTask_addingFileAsLogicalFile(corruptedImageFilePaths.toString())); + caseDatabase.acquireSingleUserCaseWriteLock(); + Image dataSource = caseDatabase.addImageInfo(0, corruptedImageFilePaths, timeZone); newDataSources.add(dataSource); List fileRanges = new ArrayList<>(); @@ -170,6 +177,8 @@ class AddMultipleImagesTask implements Runnable { } catch (TskCoreException ex) { errorMessages.add(Bundle.AddMultipleImagesTask_errorAddingImgWithoutFileSystem(deviceId, ex.getLocalizedMessage())); criticalErrorOccurred = true; + } finally { + caseDatabase.releaseSingleUserCaseWriteLock(); } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/AddMemoryImageTask.java b/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/AddMemoryImageTask.java index 7262d9f53e..bcae2b3153 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/AddMemoryImageTask.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/AddMemoryImageTask.java @@ -146,25 +146,30 @@ final class AddMemoryImageTask implements Runnable { progressMonitor.setProgressText(Bundle.AddMemoryImageTask_progressMessage_addingImageFile( memoryImagePath)); SleuthkitCase caseDatabase = Case.getCurrentCaseThrows().getSleuthkitCase(); + caseDatabase.acquireSingleUserCaseWriteLock(); + try { + /* + * Verify the memory image file exists. + */ + File imageFile = Paths.get(memoryImagePath).toFile(); + if (!imageFile.exists()) { + throw new TskCoreException(Bundle.AddMemoryImageTask_exceptionMessage_noImageFile(memoryImagePath, deviceId)); + } - /* - * Verify the memory image file exists. - */ - File imageFile = Paths.get(memoryImagePath).toFile(); - if (!imageFile.exists()) { - throw new TskCoreException(Bundle.AddMemoryImageTask_exceptionMessage_noImageFile(memoryImagePath, deviceId)); + /* + * Add the data source. + * + * NOTE: The object id for device passed to + * SleuthkitCase.addImageInfo is hard-coded to zero for now. This + * will need to be changed when a Device abstraction is added to the + * SleuthKit data model. + */ + Image dataSource = caseDatabase.addImageInfo(0, new ArrayList<>(Arrays.asList(memoryImagePath)), timeZone); + return dataSource; + + } finally { + caseDatabase.releaseSingleUserCaseWriteLock(); } - - /* - * Add the data source. - * - * NOTE: The object id for device passed to - * SleuthkitCase.addImageInfo is hard-coded to zero for now. This - * will need to be changed when a Device abstraction is added to the - * SleuthKit data model. - */ - Image dataSource = caseDatabase.addImageInfo(0, new ArrayList<>(Arrays.asList(memoryImagePath)), timeZone); - return dataSource; } /** From 77f17598ce93281f7b7eae37a9f1603a5a3a27d1 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 13 May 2020 15:40:48 -0400 Subject: [PATCH 67/90] updates to annotation viewer to not show sections with no data --- .../AnnotationsContentViewer.java | 161 ++++++------------ 1 file changed, 55 insertions(+), 106 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index a96b6c8d74..f3689aebce 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -66,25 +66,21 @@ import org.jsoup.nodes.Element; "AnnotationsContentViewer.title=Annotations", "AnnotationsContentViewer.toolTip=Displays tags and comments associated with the selected content.", "AnnotationsContentViewer.centralRepositoryEntry.title=Central Repository Comments", - "AnnotationsContentViewer.centralRepositoryEntry.onEmpty=There is no comment data for the selected content in the Central Repository.", "AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=Case:", "AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type:", "AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment:", "AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path:", "AnnotationsContentViewer.tagEntry.title=Tags", - "AnnotationsContentViewer.tagEntry.onContentEmpty=There are no tags for the selected content.", - "AnnotationsContentViewer.tagEntry.onArtifactEmpty=There are no tags for the selected artifact.", "AnnotationsContentViewer.tagEntryDataLabel.tag=Tag:", "AnnotationsContentViewer.tagEntryDataLabel.tagUser=Examiner:", "AnnotationsContentViewer.tagEntryDataLabel.comment=Comment:", "AnnotationsContentViewer.fileHitEntry.artifactCommentTitle=Artifact Comment", "AnnotationsContentViewer.fileHitEntry.hashSetHitTitle=Hash Set Hit Comments", - "AnnotationsContentViewer.fileHitEntry.onHashSetHitEmpty=There are no hash set hits for the selected content.", "AnnotationsContentViewer.fileHitEntry.interestingFileHitTitle=Interesting File Hit Comments", - "AnnotationsContentViewer.fileHitEntry.onInterestingFileHitEmpty=There are no interesting file hits for the selected content.", "AnnotationsContentViewer.fileHitEntry.setName=Set Name:", "AnnotationsContentViewer.fileHitEntry.comment=Comment:", - "AnnotationsContentViewer.sourceFile.title=Source File" + "AnnotationsContentViewer.sourceFile.title=Source File", + "AnnotationsContentViewer.onEmpty=No annotations were found for this particular item." }) public class AnnotationsContentViewer extends javax.swing.JPanel implements DataContentViewer { @@ -126,15 +122,11 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data private static class SectionConfig { private final String title; - private final String onEmpty; private final List> attributes; - private final boolean isVerticalTable; - SectionConfig(String title, String onEmpty, List> attributes, boolean isVerticalTable) { + SectionConfig(String title, List> attributes) { this.title = title; - this.onEmpty = onEmpty; this.attributes = attributes; - this.isVerticalTable = isVerticalTable; } /** @@ -144,13 +136,6 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return title; } - /** - * @return The message to display if no items provided. - */ - String getOnEmpty() { - return onEmpty; - } - /** * @return Describes key-value pairs on the object to display to the * user. @@ -158,16 +143,6 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data List> getAttributes() { return attributes; } - - /** - * @return If the table should be shown as a series of key-value pairs - * as rows. Otherwise, data is shown in a table where the column - * headers are the keys and each row represents one item to - * display. - */ - boolean isIsVerticalTable() { - return isVerticalTable; - } } private static final Logger logger = Logger.getLogger(AnnotationsContentViewer.class.getName()); @@ -197,13 +172,13 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data private static final String SUBHEADER_CLASSNAME = "subheader"; private static final String SECTION_CLASSNAME = "section"; private static final String HEADER_CLASSNAME = "header"; - private static final String ENTRY_TABLE_CLASSNAME = "entry-table"; private static final String VERTICAL_TABLE_CLASSNAME = "vertical-table"; // additional styling for components private static final String STYLE_SHEET_RULE = String.format(" .%s { font-size: %dpx;font-style:italic; margin: 0px; padding: 0px; } ", MESSAGE_CLASSNAME, DEFAULT_FONT_SIZE) - + String.format(" .%s {font-size:%dpx;font-weight:bold; margin: 0px; margin-top: %dpx; padding: 0px; } ", SUBHEADER_CLASSNAME, SUBHEADER_FONT_SIZE, DEFAULT_SUBSECTION_SPACING) + + String.format(" .%s {font-size:%dpx;font-weight:bold; margin: 0px; margin-top: %dpx; padding: 0px; } ", + SUBHEADER_CLASSNAME, SUBHEADER_FONT_SIZE, DEFAULT_SUBSECTION_SPACING) + String.format(" .%s { font-size:%dpx;font-weight:bold; margin: 0px; padding: 0px; } ", HEADER_CLASSNAME, HEADER_FONT_SIZE) + String.format(" td { vertical-align: top; font-size:%dpx; text-align: left; margin: 0px; padding: 0px %dpx 0px 0px;} ", DEFAULT_FONT_SIZE, CELL_SPACING) + String.format(" th { vertical-align: top; text-align: left; margin: 0px; padding: 0px %dpx 0px 0px} ", DEFAULT_FONT_SIZE, CELL_SPACING) @@ -218,15 +193,8 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data new ItemEntry<>(Bundle.AnnotationsContentViewer_tagEntryDataLabel_comment(), (tag) -> tag.getComment()) ); - private static final SectionConfig ARTIFACT_TAG_CONFIG = new SectionConfig<>( - Bundle.AnnotationsContentViewer_tagEntry_title(), - Bundle.AnnotationsContentViewer_tagEntry_onArtifactEmpty(), - TAG_ENTRIES, true); - - private static final SectionConfig CONTENT_TAG_CONFIG = new SectionConfig<>( - Bundle.AnnotationsContentViewer_tagEntry_title(), - Bundle.AnnotationsContentViewer_tagEntry_onContentEmpty(), - TAG_ENTRIES, true); + private static final SectionConfig TAG_CONFIG + = new SectionConfig<>(Bundle.AnnotationsContentViewer_tagEntry_title(), TAG_ENTRIES); // file set attributes and table configurations private static final List> FILESET_HIT_ENTRIES = Arrays.asList( @@ -236,20 +204,14 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data (bba) -> tryGetAttribute(bba, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT)) ); - private static final SectionConfig INTERESTING_FILE_CONFIG = new SectionConfig<>( - Bundle.AnnotationsContentViewer_fileHitEntry_interestingFileHitTitle(), - Bundle.AnnotationsContentViewer_fileHitEntry_onInterestingFileHitEmpty(), - FILESET_HIT_ENTRIES, true); + private static final SectionConfig INTERESTING_FILE_CONFIG + = new SectionConfig<>(Bundle.AnnotationsContentViewer_fileHitEntry_interestingFileHitTitle(), FILESET_HIT_ENTRIES); - private static final SectionConfig HASHSET_CONFIG = new SectionConfig<>( - Bundle.AnnotationsContentViewer_fileHitEntry_hashSetHitTitle(), - Bundle.AnnotationsContentViewer_fileHitEntry_onHashSetHitEmpty(), - FILESET_HIT_ENTRIES, true); + private static final SectionConfig HASHSET_CONFIG + = new SectionConfig<>(Bundle.AnnotationsContentViewer_fileHitEntry_hashSetHitTitle(), FILESET_HIT_ENTRIES); - private static final SectionConfig ARTIFACT_COMMENT_CONFIG = new SectionConfig<>( - Bundle.AnnotationsContentViewer_fileHitEntry_artifactCommentTitle(), - "", - FILESET_HIT_ENTRIES, true); + private static final SectionConfig ARTIFACT_COMMENT_CONFIG + = new SectionConfig<>(Bundle.AnnotationsContentViewer_fileHitEntry_artifactCommentTitle(), FILESET_HIT_ENTRIES); // central repository attributes and table configuration private static final List> CR_COMMENTS_ENTRIES = Arrays.asList( @@ -259,10 +221,8 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data new ItemEntry<>(Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), cai -> cai.getFilePath()) ); - private static final SectionConfig CR_COMMENTS_CONFIG = new SectionConfig<>( - Bundle.AnnotationsContentViewer_centralRepositoryEntry_title(), - Bundle.AnnotationsContentViewer_centralRepositoryEntry_onEmpty(), - CR_COMMENTS_ENTRIES, true); + private static final SectionConfig CR_COMMENTS_CONFIG + = new SectionConfig<>(Bundle.AnnotationsContentViewer_centralRepositoryEntry_title(), CR_COMMENTS_ENTRIES); /** * Creates an instance of AnnotationsContentViewer. @@ -312,10 +272,15 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data artifact.getDisplayName(), artifact.getArtifactID()), ex); } + boolean somethingWasRendered = false; if (artifact != null) { - renderArtifact(body, artifact, sourceFile); + somethingWasRendered = renderArtifact(body, artifact, sourceFile); } else { - renderContent(body, sourceFile, false); + somethingWasRendered = renderContent(body, sourceFile, false); + } + + if (!somethingWasRendered) { + appendMessage(body, Bundle.AnnotationsContentViewer_onEmpty()); } jTextPane1.setText(html.html()); @@ -329,23 +294,32 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data * @param bba The blackboard artifact to render. * @param sourceContent The content from which the blackboard artifact * comes. + * @return If any content was actually rendered. */ - private static void renderArtifact(Element parent, BlackboardArtifact bba, Content sourceContent) { - appendEntries(parent, ARTIFACT_TAG_CONFIG, getTags(bba), false); - + private static boolean renderArtifact(Element parent, BlackboardArtifact bba, Content sourceContent) { + boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(bba), false); + if (sourceContent instanceof AbstractFile && CentralRepository.isEnabled()) { AbstractFile sourceFile = (AbstractFile) sourceContent; List centralRepoComments = getCentralRepositoryData(bba, sourceFile); - appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, false); + boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, false); + contentRendered = contentRendered || crRendered; } if (BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == bba.getArtifactTypeID() || BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID()) { - appendEntries(parent, ARTIFACT_COMMENT_CONFIG, Arrays.asList(bba), false); + boolean filesetRendered = appendEntries(parent, ARTIFACT_COMMENT_CONFIG, Arrays.asList(bba), false); + contentRendered = contentRendered || filesetRendered; } Element sourceFileSection = appendSection(parent, Bundle.AnnotationsContentViewer_sourceFile_title()); - renderContent(sourceFileSection, sourceContent, true); + boolean sourceFileRendered = renderContent(sourceFileSection, sourceContent, true); + + if (!sourceFileRendered) { + parent.children().remove(sourceFileSection); + } + + return contentRendered || sourceFileRendered; } /** @@ -355,27 +329,32 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data * @param sourceContent The content for which annotations will be gathered. * @param isSubheader True if this section should be rendered as a * subheader as opposed to a top-level header. + * @return If any content was actually rendered. */ - private static void renderContent(Element parent, Content sourceContent, boolean isSubheader) { - appendEntries(parent, CONTENT_TAG_CONFIG, getTags(sourceContent), isSubheader); + private static boolean renderContent(Element parent, Content sourceContent, boolean isSubheader) { + boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(sourceContent), isSubheader); if (sourceContent instanceof AbstractFile) { AbstractFile sourceFile = (AbstractFile) sourceContent; if (CentralRepository.isEnabled()) { List centralRepoComments = getCentralRepositoryData(null, sourceFile); - appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, isSubheader); + boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, isSubheader); + contentRendered = contentRendered || crRendered; } - appendEntries(parent, HASHSET_CONFIG, + boolean hashsetRendered = appendEntries(parent, HASHSET_CONFIG, getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT), isSubheader); + contentRendered = contentRendered || hashsetRendered; - appendEntries(parent, INTERESTING_FILE_CONFIG, + boolean interestingFileRendered =appendEntries(parent, INTERESTING_FILE_CONFIG, getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT), isSubheader); + + contentRendered = contentRendered || interestingFileRendered; } - + return contentRendered; } /** @@ -536,19 +515,17 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data * @param items The items to display. * @param isSubsection Whether or not this should be displayed as a * subsection. If not displayed as a top-level section. + * @return If there was actual content rendered for this set of entries. */ - private static void appendEntries(Element parent, SectionConfig config, List items, + private static boolean appendEntries(Element parent, SectionConfig config, List items, boolean isSubsection) { - - Element sectionDiv = (isSubsection) ? appendSubsection(parent, config.getTitle()) : appendSection(parent, config.getTitle()); - if (items == null || items.isEmpty()) { - appendMessage(sectionDiv, config.getOnEmpty()); - } else if (config.isIsVerticalTable()) { - appendVerticalEntryTables(sectionDiv, items, config.getAttributes()); - } else { - appendEntryTable(sectionDiv, items, config.getAttributes()); + return false; } + + Element sectionDiv = (isSubsection) ? appendSubsection(parent, config.getTitle()) : appendSection(parent, config.getTitle()); + appendVerticalEntryTables(sectionDiv, items, config.getAttributes()); + return true; } /** @@ -586,34 +563,6 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return parent; } - /** - * Appends a table with column headers to the parent element. - * - * @param The item type. - * @param parent The element that will have this table appended to it. - * @param items The items to place as a row in this table. - * @param columns The columns for this table and the means to process each - * data item to retrieve a cell. - * - * @return The generated table element. - */ - private static Element appendEntryTable(Element parent, List items, List> columns) { - int columnNumber = columns.size(); - List columnHeaders = columns.stream().map(c -> c.getItemName()).collect(Collectors.toList()); - List> rows = items.stream() - .filter(r -> r != null) - .map(r -> { - return columns.stream() - .map(c -> c.retrieveValue(r)) - .collect(Collectors.toList()); - }) - .collect(Collectors.toList()); - - Element table = appendTable(parent, columnNumber, rows, columnHeaders); - table.attr("class", ENTRY_TABLE_CLASSNAME); - return table; - } - /** * Appends a generic table to the parent element. * From 057034e4fd40c6b25efc839971a6755a259a8d8d Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Wed, 13 May 2020 15:50:19 -0400 Subject: [PATCH 68/90] Interim commit - The viewer now displays Name, phone numbers and email addresses of contact from the artifact. --- .../contentviewers/ContactArtifactViewer.form | 8 +- .../contentviewers/ContactArtifactViewer.java | 193 ++++++++++++++++-- 2 files changed, 180 insertions(+), 21 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form index 58e8520202..b422d1c18e 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form @@ -46,7 +46,7 @@ - + @@ -57,6 +57,9 @@
        + + + @@ -78,6 +81,9 @@ + + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java index 33cb2258bc..b07b017479 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java @@ -19,9 +19,13 @@ package org.sleuthkit.autopsy.contentviewers; import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; +import javax.swing.Box; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -61,7 +65,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac setLayout(new java.awt.GridBagLayout()); - contactNameLabel.setFont(new java.awt.Font("Dialog", 2, 18)); // NOI18N + contactNameLabel.setFont(new java.awt.Font("Dialog", 3, 18)); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(contactNameLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.contactNameLabel.text")); // NOI18N javax.swing.GroupLayout namePanelLayout = new javax.swing.GroupLayout(namePanel); @@ -89,6 +93,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; add(namePanel, gridBagConstraints); + phonesLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(phonesLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.phonesLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; @@ -109,6 +114,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0); add(phoneNumbersPanel, gridBagConstraints); + emailsLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(emailsLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.emailsLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; @@ -131,21 +137,23 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac @Override public void setArtifact(BlackboardArtifact artifact) { - + // wipe the panel clean this.removeAll(); initComponents(); - + List phoneNumList = new ArrayList<>(); List emailList = new ArrayList<>(); List nameList = new ArrayList<>(); List otherList = new ArrayList<>(); - - + + + + //BlackboardAttribute bba = new BlackboardAttribute(); try { // RAMAN TBD: populate the display components from the artifact - for (BlackboardAttribute bba : artifact.getAttributes()) { + for (BlackboardAttribute bba : artifact.getAttributes()) { if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) { phoneNumList.add(bba); } else if (bba.getAttributeType().getTypeName().startsWith("TSK_EMAIL")) { @@ -157,20 +165,28 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac } } } catch (TskCoreException ex) { - logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); + logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); } + + // RAMAN TBD: test with multiple phones and emails + phoneNumList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE, "RAMAN", "+1 222 333 4444")); + phoneNumList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE, "RAMAN", "123456789012")); + + emailList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_HOME, "RAMAN", "home@gmail.com")); + emailList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_OFFICE, "RAMAN", "workemail@provider.com")); - setContactName(nameList); - - // TBD: set the phones - //this.phonesLabel.setVisible(true); - - // TBD: set the emails - - - // repaint - - this.revalidate(); + otherList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID, "RAMAN", "8:live:atpsy.sbarney")); + + + updateNamePanel(nameList); + + updatePhoneNumbersPanel(phoneNumList); + + updateEmailAddressesPanel(emailList); + + // TBD: update the other attributes panel + // repaint + this.revalidate(); } @Override @@ -183,18 +199,155 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac return artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID(); } - private void setContactName(List attributesList) { + private void updateNamePanel(List attributesList) { for (BlackboardAttribute bba : attributesList) { if (bba.getAttributeType().getTypeName().startsWith("TSK_NAME")) { contactNameLabel.setText(bba.getDisplayString()); - System.out.println("Setting contact name to: " + bba.getDisplayString()); break; } } contactNameLabel.revalidate(); } + + private void updatePhoneNumbersPanel(List phoneAttributesList) { + + if (phoneAttributesList.isEmpty()) { + this.phonesLabel.setVisible(false); + phoneNumbersPanel.setVisible(false); + return; + } + + GridBagLayout gridBagLayout = new GridBagLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridx = 0; + constraints.gridy = -1; + constraints.weighty = .0; + constraints.anchor = GridBagConstraints.LINE_START; + Dimension horizSpacerBlockDimension = new Dimension(12, 4); + + for (BlackboardAttribute bba : phoneAttributesList) { + constraints.weightx = 0; + constraints.gridy++; + constraints.gridx = 0; + + // Add a label for phone number type + javax.swing.JLabel phoneTypeLabel = new javax.swing.JLabel(); + + + + String attributeLabel = bba.getAttributeType().getDisplayName(); + phoneTypeLabel.setText(attributeLabel); + + // RAMAN TBD: set the size/font/style for label + //Font newLabelFont=new Font(phoneTypeLabel.getFont().getName(),Font.ITALIC+Font.BOLD,phoneTypeLabel.getFont().getSize()); + //phoneTypeLabel.setFont(newLabelFont); + + gridBagLayout.setConstraints(phoneTypeLabel, constraints); + phoneNumbersPanel.add(phoneTypeLabel); + + // Add horizontal space + constraints.gridx++; + Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); + gridBagLayout.setConstraints(spacer, constraints); + phoneNumbersPanel.add(spacer); + + // Add a label for the phone number + constraints.gridx++; + javax.swing.JLabel phoneNumberLabel = new javax.swing.JLabel(); + phoneNumberLabel.setText(bba.getValueString()); + + gridBagLayout.setConstraints(phoneNumberLabel, constraints); + phoneNumbersPanel.add(phoneNumberLabel); + } + + + //constraints.gridy++; + //constraints.gridx = 0; + //constraints.weighty = 1; + //Component vertGlue = createVerticalGlue(); + //this.phoneNumbersPanel.add(vertGlue); + //gridBagLayout.setConstraints(vertGlue, constraints); + + phoneNumbersPanel.setLayout(gridBagLayout); + + + phoneNumbersPanel.revalidate(); + } + + private void updateEmailAddressesPanel(List emailAddressAttributesList) { + + if (emailAddressAttributesList.isEmpty()) { + emailsLabel.setVisible(false); + this.emailsPanel.setVisible(false); + return; + } + + GridBagLayout gridBagLayout = new GridBagLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridx = 0; + constraints.gridy = -1; + constraints.weighty = .0; + constraints.anchor = GridBagConstraints.LINE_START; + + Dimension horizSpacerBlockDimension = new Dimension(12, 4); + + for (BlackboardAttribute bba : emailAddressAttributesList) { + constraints.weightx = 0; + constraints.gridy++; + constraints.gridx = 0; + + // Add a label for email address type + javax.swing.JLabel emailAddressTypeLabel = new javax.swing.JLabel(); + String attrLabel = bba.getAttributeType().getDisplayName(); + emailAddressTypeLabel.setText(attrLabel); + + // RAMAN TBD: set the size/font/style for label + + gridBagLayout.setConstraints(emailAddressTypeLabel, constraints); + emailsPanel.add(emailAddressTypeLabel); + + + + // Add horizontal space + constraints.gridx++; + Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); + gridBagLayout.setConstraints(spacer, constraints); + emailsPanel.add(spacer); + + // Add the phone number + constraints.gridx++; + javax.swing.JLabel emailAddressLabel = new javax.swing.JLabel(); + emailAddressLabel.setText(bba.getValueString()); + gridBagLayout.setConstraints(emailAddressLabel, constraints); + emailsPanel.add(emailAddressLabel); + } + + + //constraints.gridy++; + //constraints.gridx = 0; + //constraints.weighty = 1; + //Component vertGlue = createVerticalGlue(); + //emailsPanel.add(vertGlue); + //gridBagLayout.setConstraints(vertGlue, constraints); + + + emailsPanel.setLayout(gridBagLayout); + emailsPanel.revalidate(); + } + + + private String getAttributeLabel(BlackboardAttribute bba) { + // TBD if not found, should probably strip TSK_ and convert to camel case, + //return ATTR_LABELS_MAP.getOrDefault(bba.getAttributeType(), c); + + return bba.getAttributeType().getDisplayName(); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel contactNameLabel; private javax.swing.JLabel emailsLabel; From e57ab0f0424bebd8505ef3a97b7c905163ae8193 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 13 May 2020 15:56:44 -0400 Subject: [PATCH 69/90] updated annotation viewer comments --- .../autopsy/contentviewers/AnnotationsContentViewer.java | 2 +- .../autopsy/contentviewers/Bundle.properties-MERGED | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index f3689aebce..bf3c507a22 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -316,7 +316,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data boolean sourceFileRendered = renderContent(sourceFileSection, sourceContent, true); if (!sourceFileRendered) { - parent.children().remove(sourceFileSection); + sourceFileSection.remove(); } return contentRendered || sourceFileRendered; diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED index 893d2f705a..a0526646bb 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED @@ -15,21 +15,18 @@ # governing permissions and limitations under the License. # -AnnotationsContentViewer.centralRepositoryEntry.onEmpty=There is no comment data for the selected content in the Central Repository. AnnotationsContentViewer.centralRepositoryEntry.title=Central Repository Comments AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=Case: AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment: AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path: AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type: +AnnotationsContentViewer.fileHitEntry.artifactCommentTitle=Artifact Comment AnnotationsContentViewer.fileHitEntry.comment=Comment: AnnotationsContentViewer.fileHitEntry.hashSetHitTitle=Hash Set Hit Comments AnnotationsContentViewer.fileHitEntry.interestingFileHitTitle=Interesting File Hit Comments -AnnotationsContentViewer.fileHitEntry.onHashSetHitEmpty=There are no hash set hits for the selected content. -AnnotationsContentViewer.fileHitEntry.onInterestingFileHitEmpty=There are no interesting file hits for the selected content. AnnotationsContentViewer.fileHitEntry.setName=Set Name: +AnnotationsContentViewer.onEmpty=No annotations were found for this particular item. AnnotationsContentViewer.sourceFile.title=Source File -AnnotationsContentViewer.tagEntry.onArtifactEmpty=There are no tags for the selected artifact. -AnnotationsContentViewer.tagEntry.onContentEmpty=There are no tags for the selected content. AnnotationsContentViewer.tagEntry.title=Tags AnnotationsContentViewer.tagEntryDataLabel.comment=Comment: AnnotationsContentViewer.tagEntryDataLabel.tag=Tag: From 0b14b28785ddea581056e02dccc13ac0bf25b130 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 13 May 2020 17:09:30 -0400 Subject: [PATCH 70/90] Added methods to TagsManager to get the standard tag display strings --- .../services/TagNameDefinition.java | 27 +++++++++++++++++++ .../casemodule/services/TagsManager.java | 27 +++++++++++++++++++ .../datamodel/Bundle.properties-MERGED | 2 -- .../datamodel/DrawableTagsManager.java | 7 ++--- 4 files changed, 56 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java index 0c65f3c58d..b0c4da05e5 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java @@ -115,6 +115,33 @@ final class TagNameDefinition implements Comparable { return strList; } + /** + * Returns the bookmark tag display string. + * + * @return + */ + static String getBookmarkDisplayString() { + return Bundle.TagNameDefinition_predefTagNames_bookmark_text(); + } + + /** + * Returns the Follow Up tag display string. + * + * @return + */ + static String getFollowUpDisplayString() { + return Bundle.TagNameDefinition_predefTagNames_followUp_text(); + } + + /** + * Returns the Notable tag display string. + * + * @return + */ + static String getNotableDisplayString() { + return Bundle.TagNameDefinition_predefTagNames_notableItem_text(); + } + /** * Gets the display name for the tag name. * diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 49388d619e..aa7002faf4 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -165,6 +165,33 @@ public class TagsManager implements Closeable { return TagNameDefinition.getStandardTagNames(); } + /** + * Returns the bookmark tag display string. + * + * @return + */ + public static String getBookmarkDisplayString() { + return TagNameDefinition.getBookmarkDisplayString(); + } + + /** + * Returns the Follow Up tag display string. + * + * @return + */ + public static String getFollowUpDisplayString() { + return TagNameDefinition.getFollowUpDisplayString(); + } + + /** + * Returns the Notable tag display string. + * + * @return + */ + public static String getNotableDisplayString() { + return TagNameDefinition.getNotableDisplayString(); + } + /** * Constructs a per case Autopsy service that manages the addition of * content and artifact tags to the case database. diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Bundle.properties-MERGED b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Bundle.properties-MERGED index 6686b27994..b10e8bbb17 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Bundle.properties-MERGED +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Bundle.properties-MERGED @@ -13,6 +13,4 @@ DrawableAttribute.name=Name DrawableAttribute.path=Path DrawableAttribute.tags=Tags DrawableAttribute.width=Width -DrawableTagsManager.bookMark=Bookmark -DrawableTagsManager.followUp=Follow Up VideoFile.getMedia.progress=writing temporary file to disk diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java index ec06c6e343..abf2c02586 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java @@ -29,7 +29,6 @@ import javafx.scene.Node; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import org.apache.commons.lang3.concurrent.BasicThreadFactory; -import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.services.TagsManager; @@ -44,8 +43,6 @@ import org.sleuthkit.datamodel.TskCoreException; * Manages Tags, Tagging, and the relationship between Categories and Tags in * the autopsy Db. Delegates some work to the backing autopsy TagsManager. */ -@NbBundle.Messages({"DrawableTagsManager.followUp=Follow Up", - "DrawableTagsManager.bookMark=Bookmark"}) public final class DrawableTagsManager { private static final Logger logger = Logger.getLogger(DrawableTagsManager.class.getName()); @@ -78,8 +75,8 @@ public final class DrawableTagsManager { public DrawableTagsManager(ImageGalleryController controller) throws TskCoreException { this.autopsyTagsManager = controller.getCase().getServices().getTagsManager(); - followUpTagName = getTagName(Bundle.DrawableTagsManager_followUp()); - bookmarkTagName = getTagName(Bundle.DrawableTagsManager_bookMark()); + followUpTagName = getTagName(TagsManager.getFollowUpDisplayString()); + bookmarkTagName = getTagName(TagsManager.getBookmarkDisplayString()); this.controller = controller; compareByDisplayName = new Comparator() { From 3c242485fec3b151b86c1e1ffe776234d18f791c Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Wed, 13 May 2020 17:19:01 -0400 Subject: [PATCH 71/90] 6354 Formatting issues and splitting details into separate window --- .../autopsy/persona/Bundle.properties | 23 +- .../persona/PersonaDetailsTopComponent.form | 230 +++++++++++ .../persona/PersonaDetailsTopComponent.java | 228 +++++++++++ .../persona/PersonaSearchTopComponent.form | 178 +++++++++ .../persona/PersonaSearchTopComponent.java | 226 +++++++++++ .../autopsy/persona/PersonasTopComponent.form | 368 ------------------ .../autopsy/persona/PersonasTopComponent.java | 354 ----------------- 7 files changed, 874 insertions(+), 733 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.form create mode 100644 Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.java create mode 100644 Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.form create mode 100644 Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java delete mode 100644 Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form delete mode 100644 Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java diff --git a/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties b/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties index 8fdce69042..508c0d1370 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/persona/Bundle.properties @@ -1,14 +1,15 @@ CTL_OpenPersonas=Personas CTL_PersonasTopComponentAction=PersonasTopComponent CTL_PersonasTopComponent=Personas -PersonasTopComponent.searchField.text= -PersonasTopComponent.searchBtn.text=Search -PersonasTopComponent.searchNameRadio.text=Name -PersonasTopComponent.searchAccountRadio.text=Account -PersonasTopComponent.filterResultsTable.columnModel.title1=Name -PersonasTopComponent.filterResultsTable.columnModel.title0=ID -PersonasTopComponent.resultAccountsLbl.text=Accounts: -PersonasTopComponent.resultAliasesLbl.text=Aliases: -PersonasTopComponent.resultNameLbl.text=Name: -PersonasTopComponent.resultCasesLbl.text=Cases found in: -PersonasTopComponent.resultNameField.text=Johnathan Dough +PersonaDetailsTopComponent.resultNameLbl.text=Name: +PersonaDetailsTopComponent.resultCasesLbl.text=Cases found in: +PersonaDetailsTopComponent.resultAccountsLbl.text=Accounts: +PersonaDetailsTopComponent.resultAliasesLbl.text=Aliases: +PersonaDetailsTopComponent.resultNameField.text=Johnathan Dough +PersonaSearchTopComponent.searchAccountRadio.text=Account +PersonaSearchTopComponent.searchNameRadio.text=Name +PersonaSearchTopComponent.searchField.text= +PersonaSearchTopComponent.searchBtn.text=Search +PersonaSearchTopComponent.filterResultsTable.columnModel.title1=Name +PersonaSearchTopComponent.filterResultsTable.columnModel.title0=ID +PersonaSearchTopComponent.filterResultsTable.toolTipText= diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.form b/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.form new file mode 100644 index 0000000000..fbfd7ded76 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.form @@ -0,0 +1,230 @@ + + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + + + + + + + + + + +
        +
        +
        +
        +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.java new file mode 100644 index 0000000000..d26f3a3e71 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.java @@ -0,0 +1,228 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.persona; + +import org.netbeans.api.settings.ConvertAsProperties; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.windows.TopComponent; +import org.openide.util.NbBundle.Messages; + +/** + * Top component which displays something. + */ +@ConvertAsProperties( + dtd = "-//org.sleuthkit.autopsy.persona//PersonaDetails//EN", + autostore = false +) +@TopComponent.Description( + preferredID = "PersonaDetailsTopComponent", + //iconBase="SET/PATH/TO/ICON/HERE", + persistenceType = TopComponent.PERSISTENCE_ALWAYS +) +@TopComponent.Registration(mode = "geolocation", openAtStartup = false) +@ActionID(category = "Window", id = "org.sleuthkit.autopsy.persona.PersonaDetailsTopComponent") +@ActionReference(path = "Menu/Window" /*, position = 333 */) +@TopComponent.OpenActionRegistration( + displayName = "#CTL_PersonaDetailsAction", + preferredID = "PersonaDetailsTopComponent" +) +@Messages({ + "CTL_PersonaDetailsAction=PersonaDetails", + "CTL_PersonaDetailsTopComponent=PersonaDetails Window", + "HINT_PersonaDetailsTopComponent=This is a PersonaDetails window" +}) +public final class PersonaDetailsTopComponent extends TopComponent { + + public PersonaDetailsTopComponent() { + initComponents(); + setName(Bundle.CTL_PersonaDetailsTopComponent()); + setToolTipText(Bundle.HINT_PersonaDetailsTopComponent()); + + } + + /** + * 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. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + detailsPanel = new javax.swing.JPanel(); + resultNameLbl = new javax.swing.JLabel(); + resultNameField = new javax.swing.JTextField(); + resultAliasesLbl = new javax.swing.JLabel(); + resultAccountsLbl = new javax.swing.JLabel(); + accountsTablePane = new javax.swing.JScrollPane(); + accountsTable = new javax.swing.JTable(); + resultCasesLbl = new javax.swing.JLabel(); + casesListPane = new javax.swing.JScrollPane(); + casesList = new javax.swing.JList<>(); + aliasesListPane = new javax.swing.JScrollPane(); + aliasesList = new javax.swing.JList<>(); + + org.openide.awt.Mnemonics.setLocalizedText(resultNameLbl, org.openide.util.NbBundle.getMessage(PersonaDetailsTopComponent.class, "PersonaDetailsTopComponent.resultNameLbl.text")); // NOI18N + + resultNameField.setEditable(false); + resultNameField.setText(org.openide.util.NbBundle.getMessage(PersonaDetailsTopComponent.class, "PersonaDetailsTopComponent.resultNameField.text")); // NOI18N + resultNameField.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + resultNameFieldActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(resultAliasesLbl, org.openide.util.NbBundle.getMessage(PersonaDetailsTopComponent.class, "PersonaDetailsTopComponent.resultAliasesLbl.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(resultAccountsLbl, org.openide.util.NbBundle.getMessage(PersonaDetailsTopComponent.class, "PersonaDetailsTopComponent.resultAccountsLbl.text")); // NOI18N + + accountsTable.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + {"Email", "jdb@yahoo.com"}, + {"Phone", "865-555-5555"}, + {"Twitter", "@jd93.bread"}, + {null, null} + }, + new String [] { + "Type", "Data" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + false, false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + accountsTablePane.setViewportView(accountsTable); + + org.openide.awt.Mnemonics.setLocalizedText(resultCasesLbl, org.openide.util.NbBundle.getMessage(PersonaDetailsTopComponent.class, "PersonaDetailsTopComponent.resultCasesLbl.text")); // NOI18N + + casesList.setModel(new javax.swing.AbstractListModel() { + String[] strings = { "Investigation 13", "Scene 5" }; + public int getSize() { return strings.length; } + public String getElementAt(int i) { return strings[i]; } + }); + casesListPane.setViewportView(casesList); + + aliasesList.setModel(new javax.swing.AbstractListModel() { + String[] strings = { "J.D.", "Fred Smidge", "Ethan Roseman" }; + public int getSize() { return strings.length; } + public String getElementAt(int i) { return strings[i]; } + }); + aliasesListPane.setViewportView(aliasesList); + + javax.swing.GroupLayout detailsPanelLayout = new javax.swing.GroupLayout(detailsPanel); + detailsPanel.setLayout(detailsPanelLayout); + detailsPanelLayout.setHorizontalGroup( + detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, detailsPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(accountsTablePane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addComponent(aliasesListPane) + .addComponent(casesListPane) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, detailsPanelLayout.createSequentialGroup() + .addComponent(resultNameLbl) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(resultNameField, javax.swing.GroupLayout.DEFAULT_SIZE, 447, Short.MAX_VALUE)) + .addComponent(resultAliasesLbl, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(resultAccountsLbl, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(resultCasesLbl, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + detailsPanelLayout.setVerticalGroup( + detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(detailsPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(resultNameLbl) + .addComponent(resultNameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 18, 18) + .addComponent(resultAliasesLbl) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(aliasesListPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(resultAccountsLbl) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(accountsTablePane, javax.swing.GroupLayout.PREFERRED_SIZE, 153, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(resultCasesLbl) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(casesListPane, javax.swing.GroupLayout.DEFAULT_SIZE, 118, Short.MAX_VALUE) + .addContainerGap()) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 505, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(detailsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE))) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 555, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(detailsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE))) + ); + }// //GEN-END:initComponents + + private void resultNameFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resultNameFieldActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_resultNameFieldActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JTable accountsTable; + private javax.swing.JScrollPane accountsTablePane; + private javax.swing.JList aliasesList; + private javax.swing.JScrollPane aliasesListPane; + private javax.swing.JList casesList; + private javax.swing.JScrollPane casesListPane; + private javax.swing.JPanel detailsPanel; + private javax.swing.JLabel resultAccountsLbl; + private javax.swing.JLabel resultAliasesLbl; + private javax.swing.JLabel resultCasesLbl; + private javax.swing.JTextField resultNameField; + private javax.swing.JLabel resultNameLbl; + // End of variables declaration//GEN-END:variables + @Override + public void componentOpened() { + // TODO add custom code on component opening + } + + @Override + public void componentClosed() { + // TODO add custom code on component closing + } + + void writeProperties(java.util.Properties p) { + // better to version settings since initial version as advocated at + // http://wiki.apidesign.org/wiki/PropertyFiles + p.setProperty("version", "1.0"); + // TODO store your settings + } + + void readProperties(java.util.Properties p) { + String version = p.getProperty("version"); + // TODO read your settings according to their version + } +} diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.form b/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.form new file mode 100644 index 0000000000..ec91c8bb53 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.form @@ -0,0 +1,178 @@ + + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonaSearchTopComponent.filterResultsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonaSearchTopComponent.filterResultsTable.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + + + + + + + + + + + + + + + + + + + + + + + +
        diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java new file mode 100644 index 0000000000..126daa8870 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java @@ -0,0 +1,226 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.persona; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.table.DefaultTableModel; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle.Messages; +import org.openide.windows.Mode; +import org.openide.windows.RetainLocation; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; +import org.sleuthkit.autopsy.centralrepository.datamodel.Persona; + +/** + * Top component for the Personas tool + * + */ +@TopComponent.Description(preferredID = "PersonasTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER) +@TopComponent.Registration(mode = "personasearch", openAtStartup = false) +@RetainLocation("personasearch") +@SuppressWarnings("PMD.SingularField") +public final class PersonaSearchTopComponent extends TopComponent { + + @Messages({ + "PTopComponent_Name=Persona Search" + }) + public PersonaSearchTopComponent() { + initComponents(); + setName(Bundle.PTopComponent_Name()); + executeSearch(); + + searchBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + executeSearch(); + } + }); + } + + class PersonaFilterTableModel extends DefaultTableModel { + + PersonaFilterTableModel(Object[][] rows, String[] colNames) { + super(rows, colNames); + } + + @Override + public boolean isCellEditable(int row, int column) { + return false; + } + } + + void updateResultsTable(Collection results) { + Object[][] rows = new Object[results.size()][2]; + int i = 0; + for (Persona result : results) { + rows[i] = new String[]{String.valueOf(result.getId()), result.getName()}; + i++; + } + DefaultTableModel updatedTableModel = new PersonaFilterTableModel( + rows, + new String[]{"ID", "Name"} + ); + + filterResultsTable.setModel(updatedTableModel); + + // Formatting + filterResultsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + filterResultsTable.getColumnModel().getColumn(0).setMaxWidth(100); + filterResultsTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + } + + void executeSearch() { + Collection results = Collections.EMPTY_LIST; + try { + results = Persona.getPersonaByName(searchField.getText()); + } catch (CentralRepoException ex) { + Exceptions.printStackTrace(ex); + } + updateResultsTable(results); + } + + @Override + public void componentOpened() { + super.componentOpened(); + WindowManager.getDefault().setTopComponentFloating(this, true); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + searchButtonGroup = new javax.swing.ButtonGroup(); + searchPanel = new javax.swing.JPanel(); + searchField = new javax.swing.JTextField(); + searchNameRadio = new javax.swing.JRadioButton(); + searchAccountRadio = new javax.swing.JRadioButton(); + filterResultsPane = new javax.swing.JScrollPane(); + filterResultsTable = new javax.swing.JTable(); + searchBtn = new javax.swing.JButton(); + + setMinimumSize(new java.awt.Dimension(400, 400)); + + searchField.setText(org.openide.util.NbBundle.getMessage(PersonaSearchTopComponent.class, "PersonaSearchTopComponent.searchField.text")); // NOI18N + + searchButtonGroup.add(searchNameRadio); + searchNameRadio.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(searchNameRadio, org.openide.util.NbBundle.getMessage(PersonaSearchTopComponent.class, "PersonaSearchTopComponent.searchNameRadio.text")); // NOI18N + searchNameRadio.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + searchNameRadioActionPerformed(evt); + } + }); + + searchButtonGroup.add(searchAccountRadio); + org.openide.awt.Mnemonics.setLocalizedText(searchAccountRadio, org.openide.util.NbBundle.getMessage(PersonaSearchTopComponent.class, "PersonaSearchTopComponent.searchAccountRadio.text")); // NOI18N + + filterResultsTable.setToolTipText(org.openide.util.NbBundle.getMessage(PersonaSearchTopComponent.class, "PersonaSearchTopComponent.filterResultsTable.toolTipText")); // NOI18N + filterResultsTable.getTableHeader().setReorderingAllowed(false); + filterResultsPane.setViewportView(filterResultsTable); + if (filterResultsTable.getColumnModel().getColumnCount() > 0) { + filterResultsTable.getColumnModel().getColumn(0).setMaxWidth(25); + filterResultsTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonaSearchTopComponent.class, "PersonaSearchTopComponent.filterResultsTable.columnModel.title0")); // NOI18N + filterResultsTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonaSearchTopComponent.class, "PersonaSearchTopComponent.filterResultsTable.columnModel.title1")); // NOI18N + } + + org.openide.awt.Mnemonics.setLocalizedText(searchBtn, org.openide.util.NbBundle.getMessage(PersonaSearchTopComponent.class, "PersonaSearchTopComponent.searchBtn.text")); // NOI18N + + javax.swing.GroupLayout searchPanelLayout = new javax.swing.GroupLayout(searchPanel); + searchPanel.setLayout(searchPanelLayout); + searchPanelLayout.setHorizontalGroup( + searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(searchPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(filterResultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addComponent(searchField) + .addGroup(searchPanelLayout.createSequentialGroup() + .addComponent(searchNameRadio) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(searchAccountRadio) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 155, Short.MAX_VALUE) + .addComponent(searchBtn))) + .addContainerGap()) + ); + searchPanelLayout.setVerticalGroup( + searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(searchPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(searchField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(searchNameRadio) + .addComponent(searchAccountRadio) + .addComponent(searchBtn)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(filterResultsPane, javax.swing.GroupLayout.DEFAULT_SIZE, 320, Short.MAX_VALUE) + .addContainerGap()) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(searchPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(searchPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + private void searchNameRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchNameRadioActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_searchNameRadioActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane filterResultsPane; + private javax.swing.JTable filterResultsTable; + private javax.swing.JRadioButton searchAccountRadio; + private javax.swing.JButton searchBtn; + private javax.swing.ButtonGroup searchButtonGroup; + private javax.swing.JTextField searchField; + private javax.swing.JRadioButton searchNameRadio; + private javax.swing.JPanel searchPanel; + // End of variables declaration//GEN-END:variables + + @Override + public List availableModes(List modes) { + /* + * This looks like the right thing to do, but online discussions seems + * to indicate this method is effectively deprecated. A break point + * placed here was never hit. + */ + return modes.stream().filter(mode -> mode.getName().equals("personasearch")) + .collect(Collectors.toList()); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form deleted file mode 100644 index 846b80f5ab..0000000000 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.form +++ /dev/null @@ -1,368 +0,0 @@ - - - - -
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonasTopComponent.filterResultsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - - - - - - - <ResourceString bundle="org/sleuthkit/autopsy/persona/Bundle.properties" key="PersonasTopComponent.filterResultsTable.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        - - - - - - - - - - - - -
        -
        -
        -
        -
        -
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        -
        -
        -
        -
        -
        diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java deleted file mode 100644 index d22ad25f39..0000000000 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonasTopComponent.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2020 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.persona; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Collection; -import java.util.Collections; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.DefaultTableModel; -import javax.swing.table.TableModel; -import org.openide.util.Exceptions; -import org.openide.util.NbBundle.Messages; -import org.openide.windows.RetainLocation; -import org.openide.windows.TopComponent; -import org.openide.windows.WindowManager; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; -import org.sleuthkit.autopsy.centralrepository.datamodel.Persona; - -/** - * Top component for the Personas tool - * - */ -@TopComponent.Description(preferredID = "PersonasTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER) -@TopComponent.Registration(mode = "personas", openAtStartup = false) -@RetainLocation("personas") -@SuppressWarnings("PMD.SingularField") -public final class PersonasTopComponent extends TopComponent { - - @Messages({ - "PTopComponent_Name=Personas" - }) - public PersonasTopComponent() { - initComponents(); - setName(Bundle.PTopComponent_Name()); - executeSearch(); - - searchBtn.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - executeSearch(); - } - }); - } - - public class PersonaFilterTableModel extends DefaultTableModel { - PersonaFilterTableModel(Object[][] rows, String[] colNames) { - super(rows, colNames); - } - - public boolean isCellEditable(int row, int column) { - return false; - } - } - - void updateResultsTable(Collection results) { - Object[][] rows = new Object[results.size()][2]; - int i = 0; - for (Persona result : results) { - rows[i] = new String[]{String.valueOf(result.getId()), result.getName()}; - i++; - } - DefaultTableModel updatedTableModel = new PersonaFilterTableModel( - rows, - new String[]{"ID", "Name"} - ); - - filterResultsTable.setModel(updatedTableModel); - } - - void executeSearch() { - System.out.println("Search!"); - Collection results = Collections.EMPTY_LIST; - try { - results = Persona.getPersonaByName(searchField.getText()); - } catch (CentralRepoException ex) { - Exceptions.printStackTrace(ex); - } - updateResultsTable(results); - } - - @Override - public void componentOpened() { - super.componentOpened(); - WindowManager.getDefault().setTopComponentFloating(this, true); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - - searchButtonGroup = new javax.swing.ButtonGroup(); - splitPane = new javax.swing.JSplitPane(); - searchPanel = new javax.swing.JPanel(); - searchField = new javax.swing.JTextField(); - searchNameRadio = new javax.swing.JRadioButton(); - searchAccountRadio = new javax.swing.JRadioButton(); - filterResultsPane = new javax.swing.JScrollPane(); - filterResultsTable = new javax.swing.JTable(); - searchBtn = new javax.swing.JButton(); - detailsPanel = new javax.swing.JPanel(); - resultNameLbl = new javax.swing.JLabel(); - resultNameField = new javax.swing.JTextField(); - resultAliasesLbl = new javax.swing.JLabel(); - resultAccountsLbl = new javax.swing.JLabel(); - accountsTablePane = new javax.swing.JScrollPane(); - accountsTable = new javax.swing.JTable(); - resultCasesLbl = new javax.swing.JLabel(); - casesListPane = new javax.swing.JScrollPane(); - casesList = new javax.swing.JList<>(); - aliasesListPane = new javax.swing.JScrollPane(); - aliasesList = new javax.swing.JList<>(); - - setMinimumSize(new java.awt.Dimension(400, 400)); - - searchField.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchField.text")); // NOI18N - - searchButtonGroup.add(searchNameRadio); - searchNameRadio.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(searchNameRadio, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchNameRadio.text")); // NOI18N - searchNameRadio.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - searchNameRadioActionPerformed(evt); - } - }); - - searchButtonGroup.add(searchAccountRadio); - org.openide.awt.Mnemonics.setLocalizedText(searchAccountRadio, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchAccountRadio.text")); // NOI18N - - filterResultsTable.setModel(new javax.swing.table.DefaultTableModel( - new Object [][] { - {}, - {}, - {}, - {} - }, - new String [] { - - } - )); - filterResultsPane.setViewportView(filterResultsTable); - if (filterResultsTable.getColumnModel().getColumnCount() > 0) { - filterResultsTable.getColumnModel().getColumn(0).setMaxWidth(25); - filterResultsTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.filterResultsTable.columnModel.title0")); // NOI18N - filterResultsTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.filterResultsTable.columnModel.title1")); // NOI18N - } - - org.openide.awt.Mnemonics.setLocalizedText(searchBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchBtn.text")); // NOI18N - - javax.swing.GroupLayout searchPanelLayout = new javax.swing.GroupLayout(searchPanel); - searchPanel.setLayout(searchPanelLayout); - searchPanelLayout.setHorizontalGroup( - searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(searchPanelLayout.createSequentialGroup() - .addContainerGap() - .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(filterResultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addGroup(searchPanelLayout.createSequentialGroup() - .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(searchField) - .addGroup(searchPanelLayout.createSequentialGroup() - .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(searchPanelLayout.createSequentialGroup() - .addComponent(searchNameRadio) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(searchAccountRadio)) - .addComponent(searchBtn)) - .addGap(0, 25, Short.MAX_VALUE))) - .addContainerGap()))) - ); - searchPanelLayout.setVerticalGroup( - searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(searchPanelLayout.createSequentialGroup() - .addContainerGap() - .addComponent(searchField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(searchNameRadio) - .addComponent(searchAccountRadio)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(searchBtn) - .addGap(18, 18, 18) - .addComponent(filterResultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addContainerGap()) - ); - - splitPane.setLeftComponent(searchPanel); - - org.openide.awt.Mnemonics.setLocalizedText(resultNameLbl, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultNameLbl.text")); // NOI18N - - resultNameField.setEditable(false); - resultNameField.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultNameField.text")); // NOI18N - resultNameField.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - resultNameFieldActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(resultAliasesLbl, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultAliasesLbl.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(resultAccountsLbl, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultAccountsLbl.text")); // NOI18N - - accountsTable.setModel(new javax.swing.table.DefaultTableModel( - new Object [][] { - {"Email", "jdb@yahoo.com"}, - {"Phone", "865-555-5555"}, - {"Twitter", "@jd93.bread"}, - {null, null} - }, - new String [] { - "Type", "Data" - } - ) { - Class[] types = new Class [] { - java.lang.String.class, java.lang.String.class - }; - boolean[] canEdit = new boolean [] { - false, false - }; - - public Class getColumnClass(int columnIndex) { - return types [columnIndex]; - } - - public boolean isCellEditable(int rowIndex, int columnIndex) { - return canEdit [columnIndex]; - } - }); - accountsTablePane.setViewportView(accountsTable); - - org.openide.awt.Mnemonics.setLocalizedText(resultCasesLbl, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultCasesLbl.text")); // NOI18N - - casesList.setModel(new javax.swing.AbstractListModel() { - String[] strings = { "Investigation 13", "Scene 5" }; - public int getSize() { return strings.length; } - public String getElementAt(int i) { return strings[i]; } - }); - casesListPane.setViewportView(casesList); - - aliasesList.setModel(new javax.swing.AbstractListModel() { - String[] strings = { "J.D.", "Fred Smidge", "Ethan Roseman" }; - public int getSize() { return strings.length; } - public String getElementAt(int i) { return strings[i]; } - }); - aliasesListPane.setViewportView(aliasesList); - - javax.swing.GroupLayout detailsPanelLayout = new javax.swing.GroupLayout(detailsPanel); - detailsPanel.setLayout(detailsPanelLayout); - detailsPanelLayout.setHorizontalGroup( - detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, detailsPanelLayout.createSequentialGroup() - .addContainerGap() - .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(accountsTablePane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addComponent(aliasesListPane) - .addComponent(casesListPane) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, detailsPanelLayout.createSequentialGroup() - .addComponent(resultNameLbl) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(resultNameField, javax.swing.GroupLayout.DEFAULT_SIZE, 447, Short.MAX_VALUE)) - .addComponent(resultAliasesLbl, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(resultAccountsLbl, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(resultCasesLbl, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap()) - ); - detailsPanelLayout.setVerticalGroup( - detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(detailsPanelLayout.createSequentialGroup() - .addContainerGap() - .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(resultNameLbl) - .addComponent(resultNameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(18, 18, 18) - .addComponent(resultAliasesLbl) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(aliasesListPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(resultAccountsLbl) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(accountsTablePane, javax.swing.GroupLayout.PREFERRED_SIZE, 153, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(resultCasesLbl) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(casesListPane, javax.swing.GroupLayout.DEFAULT_SIZE, 118, Short.MAX_VALUE) - .addContainerGap()) - ); - - splitPane.setRightComponent(detailsPanel); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(splitPane) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(splitPane) - ); - }// //GEN-END:initComponents - - private void searchNameRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchNameRadioActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_searchNameRadioActionPerformed - - private void resultNameFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resultNameFieldActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_resultNameFieldActionPerformed - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JTable accountsTable; - private javax.swing.JScrollPane accountsTablePane; - private javax.swing.JList aliasesList; - private javax.swing.JScrollPane aliasesListPane; - private javax.swing.JList casesList; - private javax.swing.JScrollPane casesListPane; - private javax.swing.JPanel detailsPanel; - private javax.swing.JScrollPane filterResultsPane; - private javax.swing.JTable filterResultsTable; - private javax.swing.JLabel resultAccountsLbl; - private javax.swing.JLabel resultAliasesLbl; - private javax.swing.JLabel resultCasesLbl; - private javax.swing.JTextField resultNameField; - private javax.swing.JLabel resultNameLbl; - private javax.swing.JRadioButton searchAccountRadio; - private javax.swing.JButton searchBtn; - private javax.swing.ButtonGroup searchButtonGroup; - private javax.swing.JTextField searchField; - private javax.swing.JRadioButton searchNameRadio; - private javax.swing.JPanel searchPanel; - private javax.swing.JSplitPane splitPane; - // End of variables declaration//GEN-END:variables - -} From fe23a400f45da1d6880783f56ebbd4e2388ed31b Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Wed, 13 May 2020 17:23:32 -0400 Subject: [PATCH 72/90] 6354 Cleanup --- .../persona/PersonaDetailsTopComponent.java | 81 +++++++------------ .../persona/PersonaSearchTopComponent.java | 13 --- 2 files changed, 31 insertions(+), 63 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.java index d26f3a3e71..1177901493 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.java @@ -1,47 +1,43 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.sleuthkit.autopsy.persona; -import org.netbeans.api.settings.ConvertAsProperties; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; import org.openide.windows.TopComponent; import org.openide.util.NbBundle.Messages; +import org.openide.windows.RetainLocation; +import org.openide.windows.WindowManager; /** - * Top component which displays something. + * Top component for persona details */ -@ConvertAsProperties( - dtd = "-//org.sleuthkit.autopsy.persona//PersonaDetails//EN", - autostore = false -) -@TopComponent.Description( - preferredID = "PersonaDetailsTopComponent", - //iconBase="SET/PATH/TO/ICON/HERE", - persistenceType = TopComponent.PERSISTENCE_ALWAYS -) -@TopComponent.Registration(mode = "geolocation", openAtStartup = false) -@ActionID(category = "Window", id = "org.sleuthkit.autopsy.persona.PersonaDetailsTopComponent") -@ActionReference(path = "Menu/Window" /*, position = 333 */) -@TopComponent.OpenActionRegistration( - displayName = "#CTL_PersonaDetailsAction", - preferredID = "PersonaDetailsTopComponent" -) -@Messages({ - "CTL_PersonaDetailsAction=PersonaDetails", - "CTL_PersonaDetailsTopComponent=PersonaDetails Window", - "HINT_PersonaDetailsTopComponent=This is a PersonaDetails window" -}) +@TopComponent.Description(preferredID = "PersonasTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER) +@TopComponent.Registration(mode = "personadetails", openAtStartup = false) +@RetainLocation("personadetails") +@SuppressWarnings("PMD.SingularField") public final class PersonaDetailsTopComponent extends TopComponent { + @Messages({ + "PTopComponent_Name=Persona Details" + }) public PersonaDetailsTopComponent() { initComponents(); - setName(Bundle.CTL_PersonaDetailsTopComponent()); - setToolTipText(Bundle.HINT_PersonaDetailsTopComponent()); - + setName(Bundle.PTopComponent_Name()); } /** @@ -187,7 +183,7 @@ public final class PersonaDetailsTopComponent extends TopComponent { }// //GEN-END:initComponents private void resultNameFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resultNameFieldActionPerformed - // TODO add your handling code here: + }//GEN-LAST:event_resultNameFieldActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables @@ -204,25 +200,10 @@ public final class PersonaDetailsTopComponent extends TopComponent { private javax.swing.JTextField resultNameField; private javax.swing.JLabel resultNameLbl; // End of variables declaration//GEN-END:variables + @Override public void componentOpened() { - // TODO add custom code on component opening - } - - @Override - public void componentClosed() { - // TODO add custom code on component closing - } - - void writeProperties(java.util.Properties p) { - // better to version settings since initial version as advocated at - // http://wiki.apidesign.org/wiki/PropertyFiles - p.setProperty("version", "1.0"); - // TODO store your settings - } - - void readProperties(java.util.Properties p) { - String version = p.getProperty("version"); - // TODO read your settings according to their version + super.componentOpened(); + WindowManager.getDefault().setTopComponentFloating(this, true); } } diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java index 126daa8870..9d37d7797e 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java @@ -22,14 +22,11 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Collection; import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.table.DefaultTableModel; import org.openide.util.Exceptions; import org.openide.util.NbBundle.Messages; -import org.openide.windows.Mode; import org.openide.windows.RetainLocation; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; @@ -213,14 +210,4 @@ public final class PersonaSearchTopComponent extends TopComponent { private javax.swing.JPanel searchPanel; // End of variables declaration//GEN-END:variables - @Override - public List availableModes(List modes) { - /* - * This looks like the right thing to do, but online discussions seems - * to indicate this method is effectively deprecated. A break point - * placed here was never hit. - */ - return modes.stream().filter(mode -> mode.getName().equals("personasearch")) - .collect(Collectors.toList()); - } } From 838d873b8c48a4ea007db2628a9abf717b719b49 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Wed, 13 May 2020 17:28:57 -0400 Subject: [PATCH 73/90] Added a section to display Other attributes. --- .../autopsy/contentviewers/Bundle.properties | 1 + .../contentviewers/ContactArtifactViewer.form | 35 +++++- .../contentviewers/ContactArtifactViewer.java | 106 +++++++++++++++--- 3 files changed, 122 insertions(+), 20 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties index 8bec0c4b15..4f1041c642 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties @@ -959,3 +959,4 @@ DefaultArtifactContentViewer.selectAllMenuItem.text=Select All ContactArtifactViewer.contactNameLabel.text=Joanna Doe ContactArtifactViewer.phonesLabel.text=Phone ContactArtifactViewer.emailsLabel.text=Email +ContactArtifactViewer.othersLabel.text=Other diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form index b422d1c18e..e916c58b08 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form @@ -11,6 +11,7 @@ + @@ -18,7 +19,7 @@ - + @@ -66,14 +67,14 @@
        - + - + @@ -90,14 +91,38 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java index b07b017479..f581912173 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java @@ -62,6 +62,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac phoneNumbersPanel = new javax.swing.JPanel(); emailsLabel = new javax.swing.JLabel(); emailsPanel = new javax.swing.JPanel(); + othersLabel = new javax.swing.JLabel(); + otherAttrsPanel = new javax.swing.JPanel(); setLayout(new java.awt.GridBagLayout()); @@ -88,8 +90,9 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; - gridBagConstraints.gridwidth = 3; + gridBagConstraints.gridwidth = 4; gridBagConstraints.ipadx = 227; + gridBagConstraints.ipady = -7; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; add(namePanel, gridBagConstraints); @@ -98,16 +101,16 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 2; + gridBagConstraints.gridwidth = 3; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(12, 19, 0, 0); + gridBagConstraints.insets = new java.awt.Insets(18, 19, 0, 0); add(phonesLabel, gridBagConstraints); phoneNumbersPanel.setLayout(new java.awt.GridBagLayout()); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; - gridBagConstraints.gridwidth = 3; + gridBagConstraints.gridwidth = 4; gridBagConstraints.ipadx = 400; gridBagConstraints.ipady = 101; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; @@ -119,6 +122,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 3; + gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); add(emailsLabel, gridBagConstraints); @@ -127,12 +131,32 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 4; - gridBagConstraints.gridwidth = 3; + gridBagConstraints.gridwidth = 4; gridBagConstraints.ipadx = 400; gridBagConstraints.ipady = 106; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 0); add(emailsPanel, gridBagConstraints); + + othersLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(othersLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.othersLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 5; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(18, 19, 0, 0); + add(othersLabel, gridBagConstraints); + + otherAttrsPanel.setLayout(new java.awt.GridBagLayout()); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 6; + gridBagConstraints.gridwidth = 4; + gridBagConstraints.ipadx = 400; + gridBagConstraints.ipady = 100; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(6, 0, 29, 0); + add(otherAttrsPanel, gridBagConstraints); }// //GEN-END:initComponents @Override @@ -148,11 +172,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac List otherList = new ArrayList<>(); - - - //BlackboardAttribute bba = new BlackboardAttribute(); try { - // RAMAN TBD: populate the display components from the artifact + // Get all the attributes and group them by the panels they go in for (BlackboardAttribute bba : artifact.getAttributes()) { if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) { phoneNumList.add(bba); @@ -184,7 +205,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac updateEmailAddressesPanel(emailList); - // TBD: update the other attributes panel + updateOtherAttributesPanel(otherList); // repaint this.revalidate(); } @@ -339,13 +360,66 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac emailsPanel.revalidate(); } - - private String getAttributeLabel(BlackboardAttribute bba) { - // TBD if not found, should probably strip TSK_ and convert to camel case, - //return ATTR_LABELS_MAP.getOrDefault(bba.getAttributeType(), c); + private void updateOtherAttributesPanel(List otherAttributesList) { - return bba.getAttributeType().getDisplayName(); + if (otherAttributesList.isEmpty()) { + this.othersLabel.setVisible(false); + this.otherAttrsPanel.setVisible(false); + return; + } + + GridBagLayout gridBagLayout = new GridBagLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridx = 0; + constraints.gridy = -1; + constraints.weighty = .0; + constraints.anchor = GridBagConstraints.LINE_START; + + Dimension horizSpacerBlockDimension = new Dimension(12, 4); + + for (BlackboardAttribute bba : otherAttributesList) { + constraints.weightx = 0; + constraints.gridy++; + constraints.gridx = 0; + + // Add a label for attribute type + javax.swing.JLabel attrTypeLabel = new javax.swing.JLabel(); + String attrLabel = bba.getAttributeType().getDisplayName(); + attrTypeLabel.setText(attrLabel); + + // RAMAN TBD: set the size/font/style for label + + gridBagLayout.setConstraints(attrTypeLabel, constraints); + otherAttrsPanel.add(attrTypeLabel); + + // Add horizontal space + constraints.gridx++; + Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); + gridBagLayout.setConstraints(spacer, constraints); + otherAttrsPanel.add(spacer); + + // Add the attribute value + constraints.gridx++; + javax.swing.JLabel attrValueLabel = new javax.swing.JLabel(); + attrValueLabel.setText(bba.getValueString()); + gridBagLayout.setConstraints(attrValueLabel, constraints); + otherAttrsPanel.add(attrValueLabel); + } + + + //constraints.gridy++; + //constraints.gridx = 0; + //constraints.weighty = 1; + //Component vertGlue = createVerticalGlue(); + //emailsPanel.add(vertGlue); + //gridBagLayout.setConstraints(vertGlue, constraints); + + + otherAttrsPanel.setLayout(gridBagLayout); + otherAttrsPanel.revalidate(); } + // Variables declaration - do not modify//GEN-BEGIN:variables @@ -353,6 +427,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac private javax.swing.JLabel emailsLabel; private javax.swing.JPanel emailsPanel; private javax.swing.JPanel namePanel; + private javax.swing.JPanel otherAttrsPanel; + private javax.swing.JLabel othersLabel; private javax.swing.JPanel phoneNumbersPanel; private javax.swing.JLabel phonesLabel; // End of variables declaration//GEN-END:variables From 73d442f3ebd330fdb58b5d3116b739021dd20dc5 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Thu, 14 May 2020 08:15:03 -0400 Subject: [PATCH 74/90] Interim commit - Made a general method that can update all sections. --- .../contentviewers/ContactArtifactViewer.java | 345 +++++++++++------- 1 file changed, 205 insertions(+), 140 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java index f581912173..71d52f05c0 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import javax.swing.Box; +import javax.swing.JLabel; +import javax.swing.JPanel; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -201,11 +203,14 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac updateNamePanel(nameList); - updatePhoneNumbersPanel(phoneNumList); + updateSection(phoneNumList, this.phonesLabel, this.phoneNumbersPanel); - updateEmailAddressesPanel(emailList); + updateSection(emailList, this.emailsLabel, this.emailsPanel); - updateOtherAttributesPanel(otherList); + //updateOtherAttributesPanel(otherList); + + updateSection(otherList, this.othersLabel, this.otherAttrsPanel); + // repaint this.revalidate(); } @@ -231,140 +236,200 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac contactNameLabel.revalidate(); } - private void updatePhoneNumbersPanel(List phoneAttributesList) { - - if (phoneAttributesList.isEmpty()) { - this.phonesLabel.setVisible(false); - phoneNumbersPanel.setVisible(false); - return; - } - - GridBagLayout gridBagLayout = new GridBagLayout(); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.fill = GridBagConstraints.HORIZONTAL; - constraints.gridx = 0; - constraints.gridy = -1; - constraints.weighty = .0; - constraints.anchor = GridBagConstraints.LINE_START; - - Dimension horizSpacerBlockDimension = new Dimension(12, 4); - - for (BlackboardAttribute bba : phoneAttributesList) { - constraints.weightx = 0; - constraints.gridy++; - constraints.gridx = 0; - - // Add a label for phone number type - javax.swing.JLabel phoneTypeLabel = new javax.swing.JLabel(); - - - - String attributeLabel = bba.getAttributeType().getDisplayName(); - phoneTypeLabel.setText(attributeLabel); - - // RAMAN TBD: set the size/font/style for label - //Font newLabelFont=new Font(phoneTypeLabel.getFont().getName(),Font.ITALIC+Font.BOLD,phoneTypeLabel.getFont().getSize()); - //phoneTypeLabel.setFont(newLabelFont); - - gridBagLayout.setConstraints(phoneTypeLabel, constraints); - phoneNumbersPanel.add(phoneTypeLabel); - - // Add horizontal space - constraints.gridx++; - Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); - gridBagLayout.setConstraints(spacer, constraints); - phoneNumbersPanel.add(spacer); - - // Add a label for the phone number - constraints.gridx++; - javax.swing.JLabel phoneNumberLabel = new javax.swing.JLabel(); - phoneNumberLabel.setText(bba.getValueString()); - - gridBagLayout.setConstraints(phoneNumberLabel, constraints); - phoneNumbersPanel.add(phoneNumberLabel); - } - - - //constraints.gridy++; - //constraints.gridx = 0; - //constraints.weighty = 1; - //Component vertGlue = createVerticalGlue(); - //this.phoneNumbersPanel.add(vertGlue); - //gridBagLayout.setConstraints(vertGlue, constraints); - - phoneNumbersPanel.setLayout(gridBagLayout); - - - phoneNumbersPanel.revalidate(); - } +// private void updatePhoneNumbersPanel(List phoneAttributesList) { +// +// if (phoneAttributesList.isEmpty()) { +// this.phonesLabel.setVisible(false); +// phoneNumbersPanel.setVisible(false); +// return; +// } +// +// GridBagLayout gridBagLayout = new GridBagLayout(); +// GridBagConstraints constraints = new GridBagConstraints(); +// constraints.fill = GridBagConstraints.HORIZONTAL; +// constraints.gridx = 0; +// constraints.gridy = -1; +// constraints.weighty = .0; +// constraints.anchor = GridBagConstraints.LINE_START; +// +// Dimension horizSpacerBlockDimension = new Dimension(12, 4); +// +// for (BlackboardAttribute bba : phoneAttributesList) { +// constraints.weightx = 0; +// constraints.gridy++; +// constraints.gridx = 0; +// +// // Add a label for phone number type +// javax.swing.JLabel phoneTypeLabel = new javax.swing.JLabel(); +// +// +// +// String attributeLabel = bba.getAttributeType().getDisplayName(); +// phoneTypeLabel.setText(attributeLabel); +// +// // RAMAN TBD: set the size/font/style for label +// //Font newLabelFont=new Font(phoneTypeLabel.getFont().getName(),Font.ITALIC+Font.BOLD,phoneTypeLabel.getFont().getSize()); +// //phoneTypeLabel.setFont(newLabelFont); +// +// gridBagLayout.setConstraints(phoneTypeLabel, constraints); +// phoneNumbersPanel.add(phoneTypeLabel); +// +// // Add horizontal space +// constraints.gridx++; +// Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); +// gridBagLayout.setConstraints(spacer, constraints); +// phoneNumbersPanel.add(spacer); +// +// // Add a label for the phone number +// constraints.gridx++; +// javax.swing.JLabel phoneNumberLabel = new javax.swing.JLabel(); +// phoneNumberLabel.setText(bba.getValueString()); +// +// gridBagLayout.setConstraints(phoneNumberLabel, constraints); +// phoneNumbersPanel.add(phoneNumberLabel); +// } +// +// +// //constraints.gridy++; +// //constraints.gridx = 0; +// //constraints.weighty = 1; +// //Component vertGlue = createVerticalGlue(); +// //this.phoneNumbersPanel.add(vertGlue); +// //gridBagLayout.setConstraints(vertGlue, constraints); +// +// phoneNumbersPanel.setLayout(gridBagLayout); +// +// +// phoneNumbersPanel.revalidate(); +// } - private void updateEmailAddressesPanel(List emailAddressAttributesList) { - - if (emailAddressAttributesList.isEmpty()) { - emailsLabel.setVisible(false); - this.emailsPanel.setVisible(false); - return; - } - - GridBagLayout gridBagLayout = new GridBagLayout(); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.fill = GridBagConstraints.HORIZONTAL; - constraints.gridx = 0; - constraints.gridy = -1; - constraints.weighty = .0; - constraints.anchor = GridBagConstraints.LINE_START; - - Dimension horizSpacerBlockDimension = new Dimension(12, 4); - - for (BlackboardAttribute bba : emailAddressAttributesList) { - constraints.weightx = 0; - constraints.gridy++; - constraints.gridx = 0; - - // Add a label for email address type - javax.swing.JLabel emailAddressTypeLabel = new javax.swing.JLabel(); - String attrLabel = bba.getAttributeType().getDisplayName(); - emailAddressTypeLabel.setText(attrLabel); - - // RAMAN TBD: set the size/font/style for label - - gridBagLayout.setConstraints(emailAddressTypeLabel, constraints); - emailsPanel.add(emailAddressTypeLabel); - - - - // Add horizontal space - constraints.gridx++; - Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); - gridBagLayout.setConstraints(spacer, constraints); - emailsPanel.add(spacer); - - // Add the phone number - constraints.gridx++; - javax.swing.JLabel emailAddressLabel = new javax.swing.JLabel(); - emailAddressLabel.setText(bba.getValueString()); - gridBagLayout.setConstraints(emailAddressLabel, constraints); - emailsPanel.add(emailAddressLabel); - } - - - //constraints.gridy++; - //constraints.gridx = 0; - //constraints.weighty = 1; - //Component vertGlue = createVerticalGlue(); - //emailsPanel.add(vertGlue); - //gridBagLayout.setConstraints(vertGlue, constraints); - - - emailsPanel.setLayout(gridBagLayout); - emailsPanel.revalidate(); - } +// private void updateEmailAddressesPanel(List emailAddressAttributesList) { +// +// if (emailAddressAttributesList.isEmpty()) { +// emailsLabel.setVisible(false); +// this.emailsPanel.setVisible(false); +// return; +// } +// +// GridBagLayout gridBagLayout = new GridBagLayout(); +// GridBagConstraints constraints = new GridBagConstraints(); +// constraints.fill = GridBagConstraints.HORIZONTAL; +// constraints.gridx = 0; +// constraints.gridy = -1; +// constraints.weighty = .0; +// constraints.anchor = GridBagConstraints.LINE_START; +// +// Dimension horizSpacerBlockDimension = new Dimension(12, 4); +// +// for (BlackboardAttribute bba : emailAddressAttributesList) { +// constraints.weightx = 0; +// constraints.gridy++; +// constraints.gridx = 0; +// +// // Add a label for email address type +// javax.swing.JLabel emailAddressTypeLabel = new javax.swing.JLabel(); +// String attrLabel = bba.getAttributeType().getDisplayName(); +// emailAddressTypeLabel.setText(attrLabel); +// +// // RAMAN TBD: set the size/font/style for label +// +// gridBagLayout.setConstraints(emailAddressTypeLabel, constraints); +// emailsPanel.add(emailAddressTypeLabel); +// +// +// +// // Add horizontal space +// constraints.gridx++; +// Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); +// gridBagLayout.setConstraints(spacer, constraints); +// emailsPanel.add(spacer); +// +// // Add the phone number +// constraints.gridx++; +// javax.swing.JLabel emailAddressLabel = new javax.swing.JLabel(); +// emailAddressLabel.setText(bba.getValueString()); +// gridBagLayout.setConstraints(emailAddressLabel, constraints); +// emailsPanel.add(emailAddressLabel); +// } +// +// +// //constraints.gridy++; +// //constraints.gridx = 0; +// //constraints.weighty = 1; +// //Component vertGlue = createVerticalGlue(); +// //emailsPanel.add(vertGlue); +// //gridBagLayout.setConstraints(vertGlue, constraints); +// +// +// emailsPanel.setLayout(gridBagLayout); +// emailsPanel.revalidate(); +// } - private void updateOtherAttributesPanel(List otherAttributesList) { +// private void updateOtherAttributesPanel(List otherAttributesList) { +// +// if (otherAttributesList.isEmpty()) { +// this.othersLabel.setVisible(false); +// this.otherAttrsPanel.setVisible(false); +// return; +// } +// +// GridBagLayout gridBagLayout = new GridBagLayout(); +// GridBagConstraints constraints = new GridBagConstraints(); +// constraints.fill = GridBagConstraints.HORIZONTAL; +// constraints.gridx = 0; +// constraints.gridy = -1; +// constraints.weighty = .0; +// constraints.anchor = GridBagConstraints.LINE_START; +// +// Dimension horizSpacerBlockDimension = new Dimension(12, 4); +// +// for (BlackboardAttribute bba : otherAttributesList) { +// constraints.weightx = 0; +// constraints.gridy++; +// constraints.gridx = 0; +// +// // Add a label for attribute type +// javax.swing.JLabel attrTypeLabel = new javax.swing.JLabel(); +// String attrLabel = bba.getAttributeType().getDisplayName(); +// attrTypeLabel.setText(attrLabel); +// +// // RAMAN TBD: set the size/font/style for label +// +// gridBagLayout.setConstraints(attrTypeLabel, constraints); +// otherAttrsPanel.add(attrTypeLabel); +// +// // Add horizontal space +// constraints.gridx++; +// Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); +// gridBagLayout.setConstraints(spacer, constraints); +// otherAttrsPanel.add(spacer); +// +// // Add the attribute value +// constraints.gridx++; +// javax.swing.JLabel attrValueLabel = new javax.swing.JLabel(); +// attrValueLabel.setText(bba.getValueString()); +// gridBagLayout.setConstraints(attrValueLabel, constraints); +// otherAttrsPanel.add(attrValueLabel); +// } +// +// +// //constraints.gridy++; +// //constraints.gridx = 0; +// //constraints.weighty = 1; +// //Component vertGlue = createVerticalGlue(); +// //emailsPanel.add(vertGlue); +// //gridBagLayout.setConstraints(vertGlue, constraints); +// +// +// otherAttrsPanel.setLayout(gridBagLayout); +// otherAttrsPanel.revalidate(); +// } + + private void updateSection(List sectionAttributesList, JLabel sectionLabel, JPanel sectionPanel) { - if (otherAttributesList.isEmpty()) { - this.othersLabel.setVisible(false); - this.otherAttrsPanel.setVisible(false); + if (sectionAttributesList.isEmpty()) { + sectionLabel.setVisible(false); + sectionPanel.setVisible(false); return; } @@ -378,7 +443,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac Dimension horizSpacerBlockDimension = new Dimension(12, 4); - for (BlackboardAttribute bba : otherAttributesList) { + for (BlackboardAttribute bba : sectionAttributesList) { constraints.weightx = 0; constraints.gridy++; constraints.gridx = 0; @@ -391,20 +456,20 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac // RAMAN TBD: set the size/font/style for label gridBagLayout.setConstraints(attrTypeLabel, constraints); - otherAttrsPanel.add(attrTypeLabel); + sectionPanel.add(attrTypeLabel); // Add horizontal space constraints.gridx++; Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); gridBagLayout.setConstraints(spacer, constraints); - otherAttrsPanel.add(spacer); + sectionPanel.add(spacer); // Add the attribute value constraints.gridx++; javax.swing.JLabel attrValueLabel = new javax.swing.JLabel(); attrValueLabel.setText(bba.getValueString()); gridBagLayout.setConstraints(attrValueLabel, constraints); - otherAttrsPanel.add(attrValueLabel); + sectionPanel.add(attrValueLabel); } @@ -416,8 +481,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac //gridBagLayout.setConstraints(vertGlue, constraints); - otherAttrsPanel.setLayout(gridBagLayout); - otherAttrsPanel.revalidate(); + sectionPanel.setLayout(gridBagLayout); + sectionPanel.revalidate(); } From c6aaa0aad30a9fc032147b340d584b7a1d152998 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 14 May 2020 08:15:29 -0400 Subject: [PATCH 75/90] fixes for CR comments and only render if content --- .../AnnotationsContentViewer.java | 143 +++++++++++------- 1 file changed, 87 insertions(+), 56 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index bf3c507a22..6a15719fb9 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -29,6 +29,7 @@ import javax.swing.JLabel; import javax.swing.text.EditorKit; import javax.swing.text.html.HTMLEditorKit; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import static org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; @@ -38,8 +39,6 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException; -import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase; -import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeUtil; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; @@ -278,7 +277,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } else { somethingWasRendered = renderContent(body, sourceFile, false); } - + if (!somethingWasRendered) { appendMessage(body, Bundle.AnnotationsContentViewer_onEmpty()); } @@ -294,14 +293,14 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data * @param bba The blackboard artifact to render. * @param sourceContent The content from which the blackboard artifact * comes. - * @return If any content was actually rendered. + * + * @return If any content was actually rendered. */ private static boolean renderArtifact(Element parent, BlackboardArtifact bba, Content sourceContent) { boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(bba), false); - - if (sourceContent instanceof AbstractFile && CentralRepository.isEnabled()) { - AbstractFile sourceFile = (AbstractFile) sourceContent; - List centralRepoComments = getCentralRepositoryData(bba, sourceFile); + + if (CentralRepository.isEnabled()) { + List centralRepoComments = getCentralRepositoryData(bba); boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, false); contentRendered = contentRendered || crRendered; } @@ -314,11 +313,11 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data Element sourceFileSection = appendSection(parent, Bundle.AnnotationsContentViewer_sourceFile_title()); boolean sourceFileRendered = renderContent(sourceFileSection, sourceContent, true); - + if (!sourceFileRendered) { sourceFileSection.remove(); } - + return contentRendered || sourceFileRendered; } @@ -329,7 +328,8 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data * @param sourceContent The content for which annotations will be gathered. * @param isSubheader True if this section should be rendered as a * subheader as opposed to a top-level header. - * @return If any content was actually rendered. + * + * @return If any content was actually rendered. */ private static boolean renderContent(Element parent, Content sourceContent, boolean isSubheader) { boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(sourceContent), isSubheader); @@ -338,7 +338,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data AbstractFile sourceFile = (AbstractFile) sourceContent; if (CentralRepository.isEnabled()) { - List centralRepoComments = getCentralRepositoryData(null, sourceFile); + List centralRepoComments = getCentralRepositoryData(sourceFile); boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, isSubheader); contentRendered = contentRendered || crRendered; } @@ -346,13 +346,12 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data boolean hashsetRendered = appendEntries(parent, HASHSET_CONFIG, getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT), isSubheader); - contentRendered = contentRendered || hashsetRendered; - boolean interestingFileRendered =appendEntries(parent, INTERESTING_FILE_CONFIG, + boolean interestingFileRendered = appendEntries(parent, INTERESTING_FILE_CONFIG, getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT), isSubheader); - - contentRendered = contentRendered || interestingFileRendered; + + contentRendered = contentRendered || hashsetRendered || interestingFileRendered; } return contentRendered; } @@ -444,62 +443,93 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return attr.getValueString(); } + /** + * Gets the "Central Repository Comments" section with data for the + * blackboard artifact. + * + * @param artifact The selected artifact. + * + * @return The Correlation Attribute Instances associated with the artifact + * that have comments. + */ + private static List getCentralRepositoryData(BlackboardArtifact artifact) { + if (artifact == null) { + return new ArrayList<>(); + } + + List> lookupKeys = CorrelationAttributeUtil.makeCorrAttrsForCorrelation(artifact) + .stream() + .map(cai -> Pair.of(cai.getCorrelationType(), cai.getCorrelationValue())) + .collect(Collectors.toList()); + + return getCorrelationAttributeComments(lookupKeys); + } + /** * Gets the "Central Repository Comments" section with data. * - * @param artifact A selected artifact (can be null). * @param sourceFile A selected file, or a source file of the selected * artifact. * - * @return The Correlation Attribute Instances associated with the artifact - * and/or sourcefile. + * @return The Correlation Attribute Instances associated with the + * sourcefile that have comments. */ - private static List getCentralRepositoryData(BlackboardArtifact artifact, AbstractFile sourceFile) { - List toReturn = new ArrayList<>(); - - List instancesList = new ArrayList<>(); - if (artifact != null) { - instancesList.addAll(CorrelationAttributeUtil.makeCorrAttrsForCorrelation(artifact)); + private static List getCentralRepositoryData(AbstractFile sourceFile) { + if (sourceFile == null || StringUtils.isEmpty(sourceFile.getMd5Hash())) { + return new ArrayList<>(); } + String md5 = sourceFile.getMd5Hash(); + + List artifactTypes = null; try { - List artifactTypes = CentralRepository.getInstance().getDefinedCorrelationTypes(); - String md5 = sourceFile.getMd5Hash(); - if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) { - for (CorrelationAttributeInstance.Type attributeType : artifactTypes) { - if (attributeType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) { - CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCase()); - instancesList.add(new CorrelationAttributeInstance( - attributeType, - md5, - correlationCase, - CorrelationDataSource.fromTSKDataSource(correlationCase, sourceFile.getDataSource()), - sourceFile.getParentPath() + sourceFile.getName(), - "", - sourceFile.getKnown(), - sourceFile.getId())); - break; - } - } + artifactTypes = CentralRepository.getInstance().getDefinedCorrelationTypes(); + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, "Error connecting to the Central Repository database.", ex); // NON-NLS + } + + if (artifactTypes == null || artifactTypes.isEmpty()) { + return new ArrayList<>(); + } + + // get key lookups for a file attribute types and the md5 hash + List> lookupKeys = artifactTypes.stream() + .filter((attributeType) -> attributeType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) + .map((attributeType) -> Pair.of(attributeType, md5)) + .collect(Collectors.toList()); + + return getCorrelationAttributeComments(lookupKeys); + } + + /** + * Given a type and a value for that type, does a lookup in the Central + * Repository for matching values that have comments. + * + * @param lookupKeys The type and value to lookup. + * + * @return The found correlation attribute instances. + */ + private static List getCorrelationAttributeComments(List> lookupKeys) { + List instancesToRet = new ArrayList<>(); + + try { + // use lookup instances to find the actual correlation attributes for the items selected + for (Pair typeVal : lookupKeys) { + instancesToRet.addAll(CentralRepository.getInstance() + .getArtifactInstancesByTypeValue(typeVal.getKey(), typeVal.getValue()) + .stream() + // for each one found, if it has a comment, return + .filter((cai) -> StringUtils.isNotEmpty(cai.getComment())) + .collect(Collectors.toList())); } - for (CorrelationAttributeInstance instance : instancesList) { - List correlatedInstancesList - = CentralRepository.getInstance().getArtifactInstancesByTypeValue(instance.getCorrelationType(), instance.getCorrelationValue()); - for (CorrelationAttributeInstance correlatedInstance : correlatedInstancesList) { - if (StringUtils.isNotEmpty(correlatedInstance.getComment())) { - toReturn.add(correlatedInstance); - } - } - } - - } catch (CentralRepoException | TskCoreException ex) { + } catch (CentralRepoException ex) { logger.log(Level.SEVERE, "Error connecting to the Central Repository database.", ex); // NON-NLS } catch (CorrelationAttributeNormalizationException ex) { logger.log(Level.SEVERE, "Error normalizing instance from Central Repository database.", ex); // NON-NLS } - return toReturn; + return instancesToRet; } /** @@ -515,6 +545,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data * @param items The items to display. * @param isSubsection Whether or not this should be displayed as a * subsection. If not displayed as a top-level section. + * * @return If there was actual content rendered for this set of entries. */ private static boolean appendEntries(Element parent, SectionConfig config, List items, @@ -522,7 +553,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data if (items == null || items.isEmpty()) { return false; } - + Element sectionDiv = (isSubsection) ? appendSubsection(parent, config.getTitle()) : appendSection(parent, config.getTitle()); appendVerticalEntryTables(sectionDiv, items, config.getAttributes()); return true; From 233acdfbafd887a5d1e64b7e6c29724e1fecfb5e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 14 May 2020 08:24:13 -0400 Subject: [PATCH 76/90] addressing codacy remark --- .../autopsy/contentviewers/AnnotationsContentViewer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index 6a15719fb9..344589e5ce 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -479,8 +479,6 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return new ArrayList<>(); } - String md5 = sourceFile.getMd5Hash(); - List artifactTypes = null; try { artifactTypes = CentralRepository.getInstance().getDefinedCorrelationTypes(); @@ -491,6 +489,8 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data if (artifactTypes == null || artifactTypes.isEmpty()) { return new ArrayList<>(); } + + String md5 = sourceFile.getMd5Hash(); // get key lookups for a file attribute types and the md5 hash List> lookupKeys = artifactTypes.stream() From 42a077b3ac44a4e1a880f41d36266c8b9a5f4a17 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 14 May 2020 09:32:00 -0400 Subject: [PATCH 77/90] changed logic to always check for other notable tags on source and act accordingly --- .../eventlisteners/CaseEventListener.java | 188 ++++++++++-------- 1 file changed, 101 insertions(+), 87 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index 22642cab6c..507a9e8112 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -209,81 +209,84 @@ final class CaseEventListener implements PropertyChangeListener { } else if (curEventType == Case.Events.CONTENT_TAG_DELETED && event instanceof ContentTagDeletedEvent) { handleTagDeleted((ContentTagDeletedEvent) event); } else { - LOGGER.log(Level.WARNING, + LOGGER.log(Level.SEVERE, String.format("Received an event %s of type %s and was expecting either CONTENT_TAG_ADDED or CONTENT_TAG_DELETED.", event, curEventType)); } } - /** - * When a tag is added, handle whether or not to add/update the central - * repository correlation attribute instance for the file. A correlation - * attribute instance will be created / updated if the tag is notable. - * - * @param tagAddedEvent The event where a tag was added. - */ - private void handleTagAdded(ContentTagAddedEvent tagAddedEvent) { - final ContentTag tagAdded = tagAddedEvent.getAddedTag(); - - if (!isNotableTag(tagAdded)) { + private void handleTagDeleted(ContentTagDeletedEvent evt) { + // ensure tag deleted event has a valid content id + if (evt.getDeletedTagInfo() == null) { + LOGGER.log(Level.SEVERE, + String.format("ContentTagDeletedEvent %s did not have valid content to provide a content id.", evt)); return; } + + try { + // obtain content + Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(evt.getDeletedTagInfo().getContentID()); + if (content == null) { + LOGGER.log(Level.WARNING, + String.format("Unable to get content for item with content id: %d.", evt.getDeletedTagInfo().getContentID())); + return; + } + + // then handle the event + handleTagChange(content); + } catch (NoCurrentCaseException | TskCoreException ex) { + LOGGER.log(Level.WARNING, "Error updating non-file object."); + } + } + private void handleTagAdded(ContentTagAddedEvent evt) { + // ensure tag added event has a valid content id + if (evt.getAddedTag() == null || evt.getAddedTag().getContent() == null) { + LOGGER.log(Level.SEVERE, + String.format("ContentTagAddedEvent %s did not have valid content to provide a content id.", evt)); + return; + } + + // then handle the event + handleTagChange(evt.getAddedTag().getContent()); + } + + /** + * When a tag is added or deleted, check if there are other notable tags for the item. + * If there are, set known status as notable. If not set status as unknown. + * + * @param content The content for the tag that was added or deleted. + */ + private void handleTagChange(Content content) { AbstractFile af = null; try { - af = Case.getCurrentCaseThrows().getSleuthkitCase().getAbstractFileById(tagAdded.getContent().getId()); + af = Case.getCurrentCaseThrows().getSleuthkitCase().getAbstractFileById(content.getId()); } catch (NoCurrentCaseException | TskCoreException ex) { - LOGGER.log(Level.WARNING, "Error updating non-file object"); + LOGGER.log(Level.WARNING, "Error updating non-file object."); } if (af == null) { return; } - - setContentKnownStatus(af, TskData.FileKnown.BAD); - } - - /** - * For deleted tags, set the central repository correlation attribute - * instance file status to unknown if the tag that was deleted was the - * only tag on the file that confers notability. - * - * @param tagDeletedEvent The tag deleted event containing information - * about the tag that is being deleted. - */ - private void handleTagDeleted(ContentTagDeletedEvent tagDeletedEvent) { - if (!isNotableTagName(tagDeletedEvent.getDeletedTagInfo().getName())) { - // If the tag that got removed isn't on the list of central repo tags, do nothing - return; - } - - long contentID = tagDeletedEvent.getDeletedTagInfo().getContentID(); - + try { - // Get the remaining tags on the content object - Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(contentID); + // Get the tags on the content object TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager(); if (hasNotableTag(tagsManager.getContentTagsByContent(content))) { - // There's still at least one bad tag, so leave the known status as is - return; + // if there is a notable tag on the object, set content known status to bad + setContentKnownStatus(af, TskData.FileKnown.BAD); } - - // There are no more bad tags on the object - AbstractFile af = Case.getCurrentCaseThrows().getSleuthkitCase().getAbstractFileById(contentID); - if (af == null) { - LOGGER.log(Level.WARNING, "Error updating non-file object"); - return; + else { + // otherwise, set to unknown + setContentKnownStatus(af, TskData.FileKnown.UNKNOWN); } - - setContentKnownStatus(af, TskData.FileKnown.UNKNOWN); - } catch (TskCoreException | NoCurrentCaseException ex) { - LOGGER.log(Level.SEVERE, "Failed to find content", ex); - return; + LOGGER.log(Level.SEVERE, "Failed to obtain tags manager for case.", ex); } } + /** * Sets the known status for the correlation attribute instance for the * given abstract file. @@ -295,7 +298,6 @@ final class CaseEventListener implements PropertyChangeListener { */ private void setContentKnownStatus(AbstractFile af, TskData.FileKnown knownStatus) { final CorrelationAttributeInstance eamArtifact = CorrelationAttributeUtil.makeCorrAttrFromFile(af); - eamArtifact.setComment(""); if (eamArtifact != null) { // send update to Central Repository db @@ -336,43 +338,60 @@ final class CaseEventListener implements PropertyChangeListener { } } - /** - * When a tag is added, handle whether or not to add/update the central - * repository correlation attribute instance for the artifact. A - * correlation attribute instance will be created / updated if the tag - * is notable and the file is not known. - * - * @param tagAddedEvent The event where a tag was added. - */ - private void handleTagAdded(BlackBoardArtifactTagAddedEvent tagAddedEvent) { - final BlackboardArtifactTag tagAdded = tagAddedEvent.getAddedTag(); - - // The added tag isn't flagged as bad in central repo, so do nothing - if (!isNotableTag(tagAdded)) { + private void handleTagDeleted(BlackBoardArtifactTagDeletedEvent evt) { + // ensure tag deleted event has a valid content id + if (evt.getDeletedTagInfo() == null) { + LOGGER.log(Level.SEVERE, + String.format("ContentTagDeletedEvent %s did not have valid content to provide a content id.", evt)); return; } + + try { + Case openCase = Case.getCurrentCaseThrows(); + + // obtain content + Content content = openCase.getSleuthkitCase().getContentById(evt.getDeletedTagInfo().getContentID()); + if (content == null) { + LOGGER.log(Level.WARNING, + String.format("Unable to get content for item with content id: %d.", evt.getDeletedTagInfo().getContentID())); + return; + } + + // obtain blackboard artifact + BlackboardArtifact bbArtifact = openCase.getSleuthkitCase().getBlackboardArtifact(evt.getDeletedTagInfo().getArtifactID()); + if (bbArtifact == null) { + LOGGER.log(Level.WARNING, + String.format("Unable to get blackboard artifact for item with artifact id: %d.", evt.getDeletedTagInfo().getArtifactID())); + return; + } + + // then handle the event + handleTagChange(content, bbArtifact); + } catch (NoCurrentCaseException | TskCoreException ex) { + LOGGER.log(Level.WARNING, "Error updating non-file object."); + } + } - if (isKnownFile(tagAdded.getContent())) { + private void handleTagAdded(BlackBoardArtifactTagAddedEvent evt) { + // ensure tag added event has a valid content id + if (evt.getAddedTag() == null || evt.getAddedTag().getContent() == null) { + LOGGER.log(Level.SEVERE, + String.format("ContentTagAddedEvent %s did not have valid content to provide a content id.", evt)); return; } - - setArtifactKnownStatus(tagAdded.getArtifact(), TskData.FileKnown.BAD); + + // then handle the event + handleTagChange(evt.getAddedTag().getContent(), evt.getAddedTag().getArtifact()); } /** - * For deleted tags, set the central repository correlation attribute - * instance file status to unknown if the tag that was deleted was the - * only tag on the file that confers notability. + * When a tag is added or deleted, check if there are other notable tags for the item. + * If there are, set known status as notable. If not set status as unknown. * - * @param tagDeletedEvent The tag deleted event containing information - * about the tag that is begin deleted. + * @param content The content for the tag that was added or deleted. + * @param bbArtifact The artifact for the tag that was added or deleted. */ - private void handleTagDeleted(BlackBoardArtifactTagDeletedEvent tagDeletedEvent) { - if (!isNotableTagName(tagDeletedEvent.getDeletedTagInfo().getName())) { - // If the tag that got removed isn't on the list of central repo tags, do nothing - return; - } - + private void handleTagChange(Content content, BlackboardArtifact bbArtifact) { Case openCase; try { openCase = Case.getCurrentCaseThrows(); @@ -381,26 +400,21 @@ final class CaseEventListener implements PropertyChangeListener { return; } - long contentID = tagDeletedEvent.getDeletedTagInfo().getContentID(); - long artifactID = tagDeletedEvent.getDeletedTagInfo().getArtifactID(); - try { - // Get the remaining tags on the artifact - Content content = openCase.getSleuthkitCase().getContentById(contentID); if (isKnownFile(content)) { return; } - BlackboardArtifact bbArtifact = openCase.getSleuthkitCase().getBlackboardArtifact(artifactID); TagsManager tagsManager = openCase.getServices().getTagsManager(); List tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact); if (hasNotableTag(tags)) { - return; + setArtifactKnownStatus(bbArtifact, TskData.FileKnown.BAD); + } + else { + setArtifactKnownStatus(bbArtifact, TskData.FileKnown.UNKNOWN); } - - setArtifactKnownStatus(bbArtifact, TskData.FileKnown.UNKNOWN); } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Failed to find content", ex); + LOGGER.log(Level.SEVERE, "Failed to obtain tags manager for case.", ex); return; } } From 2d3dcc43e8f84bb49430f70f4005f099c78955ef Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 14 May 2020 09:55:23 -0400 Subject: [PATCH 78/90] defensive code --- .../centralrepository/eventlisteners/CaseEventListener.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index 507a9e8112..cbd136b31c 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -374,7 +374,7 @@ final class CaseEventListener implements PropertyChangeListener { private void handleTagAdded(BlackBoardArtifactTagAddedEvent evt) { // ensure tag added event has a valid content id - if (evt.getAddedTag() == null || evt.getAddedTag().getContent() == null) { + if (evt.getAddedTag() == null || evt.getAddedTag().getContent() == null || evt.getAddedTag().getArtifact() == null) { LOGGER.log(Level.SEVERE, String.format("ContentTagAddedEvent %s did not have valid content to provide a content id.", evt)); return; @@ -440,7 +440,6 @@ final class CaseEventListener implements PropertyChangeListener { private void setArtifactKnownStatus(BlackboardArtifact bbArtifact, TskData.FileKnown knownStatus) { List convertedArtifacts = CorrelationAttributeUtil.makeCorrAttrsForCorrelation(bbArtifact); for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) { - eamArtifact.setComment(""); try { dbManager.setAttributeInstanceKnownStatus(eamArtifact, knownStatus); } catch (CentralRepoException ex) { From 7c1d01bc058828c1a7d79ccf8feb75966ab75707 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 14 May 2020 09:57:00 -0400 Subject: [PATCH 79/90] formatting --- .../datamodel/RdbmsCentralRepo.java | 232 +++++++++--------- .../eventlisteners/CaseEventListener.java | 45 ++-- 2 files changed, 135 insertions(+), 142 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java index b5e044d6e9..42174a4c65 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java @@ -82,7 +82,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { private static final Cache, CentralRepoAccount> accountsCache = CacheBuilder.newBuilder() .expireAfterWrite(ACCOUNTS_CACHE_TIMEOUT, TimeUnit.MINUTES). build(); - + private boolean isCRTypeCacheInitialized; private static final Cache typeCache = CacheBuilder.newBuilder().build(); private static final Cache caseCacheByUUID = CacheBuilder.newBuilder() @@ -105,8 +105,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { static final int DEFAULT_BULK_THRESHHOLD = 1000; private static final int QUERY_STR_MAX_LEN = 1000; - - + /** * Connect to the DB and initialize it. * @@ -137,6 +136,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { * Get an ephemeral connection. */ protected abstract Connection getEphemeralConnection(); + /** * Add a new name/value pair in the db_info table. * @@ -223,7 +223,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { * Reset the contents of the caches associated with EamDb results. */ public final void clearCaches() { - synchronized(typeCache) { + synchronized (typeCache) { typeCache.invalidateAll(); isCRTypeCacheInitialized = false; } @@ -1017,27 +1017,26 @@ abstract class RdbmsCentralRepo implements CentralRepository { // @@@ We should cache the case and data source IDs in memory String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()); boolean artifactHasAnAccount = CentralRepoDbUtil.correlationAttribHasAnAccount(eamArtifact.getCorrelationType()); - + String sql; // _instance table for accounts have an additional account_id column if (artifactHasAnAccount) { - sql = "INSERT INTO " - + tableName - + "(case_id, data_source_id, value, file_path, known_status, comment, file_obj_id, account_id) " - + "VALUES (?, ?, ?, ?, ?, ?, ?, ?) " - + getConflictClause(); - } - else { - sql = "INSERT INTO " - + tableName - + "(case_id, data_source_id, value, file_path, known_status, comment, file_obj_id) " - + "VALUES (?, ?, ?, ?, ?, ?, ?) " - + getConflictClause(); + sql = "INSERT INTO " + + tableName + + "(case_id, data_source_id, value, file_path, known_status, comment, file_obj_id, account_id) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?) " + + getConflictClause(); + } else { + sql = "INSERT INTO " + + tableName + + "(case_id, data_source_id, value, file_path, known_status, comment, file_obj_id) " + + "VALUES (?, ?, ?, ?, ?, ?, ?) " + + getConflictClause(); } try (Connection conn = connect(); - PreparedStatement preparedStatement = conn.prepareStatement(sql);) { - + PreparedStatement preparedStatement = conn.prepareStatement(sql);) { + if (!eamArtifact.getCorrelationValue().isEmpty()) { preparedStatement.setInt(1, eamArtifact.getCorrelationCase().getID()); preparedStatement.setInt(2, eamArtifact.getCorrelationDataSource().getID()); @@ -1051,7 +1050,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { preparedStatement.setString(6, eamArtifact.getComment()); } preparedStatement.setLong(7, eamArtifact.getFileObjectId()); - + // set in the accountId only for artifacts that represent accounts if (artifactHasAnAccount) { if (eamArtifact.getAccountId() >= 0) { @@ -1066,21 +1065,21 @@ abstract class RdbmsCentralRepo implements CentralRepository { } catch (SQLException ex) { throw new CentralRepoException("Error inserting new artifact into artifacts table.", ex); // NON-NLS - } + } } - /** - * Gets the Central Repo account for the given account type and account ID. - * Create a new account first, if one doesn't exist - * - * @param accountType account type - * @param accountUniqueID unique account identifier - * - * @return A matching account, either existing or newly created. - * - * @throws TskCoreException exception thrown if a critical error occurs - * within TSK core - */ + /** + * Gets the Central Repo account for the given account type and account ID. + * Create a new account first, if one doesn't exist + * + * @param accountType account type + * @param accountUniqueID unique account identifier + * + * @return A matching account, either existing or newly created. + * + * @throws TskCoreException exception thrown if a critical error occurs + * within TSK core + */ @Override public CentralRepoAccount getOrCreateAccount(CentralRepoAccountType crAccountType, String accountUniqueID) throws CentralRepoException { // Get the account fom the accounts table @@ -1106,56 +1105,53 @@ abstract class RdbmsCentralRepo implements CentralRepository { return account; } - @Override public CentralRepoAccountType getAccountTypeByName(String accountTypeName) throws CentralRepoException { try { return accountTypesCache.get(accountTypeName, () -> getCRAccountTypeFromDb(accountTypeName)); } catch (CacheLoader.InvalidCacheLoadException | ExecutionException ex) { - throw new CentralRepoException("Error looking up CR account type in cache.", ex); - } + throw new CentralRepoException("Error looking up CR account type in cache.", ex); + } } - - @Override public Collection getAllAccountTypes() throws CentralRepoException { - - Collection accountTypes = new ArrayList<>(); - - String sql = "SELECT * FROM account_types"; - try ( Connection conn = connect(); - PreparedStatement preparedStatement = conn.prepareStatement(sql);) { - + Collection accountTypes = new ArrayList<>(); + + String sql = "SELECT * FROM account_types"; + try (Connection conn = connect(); + PreparedStatement preparedStatement = conn.prepareStatement(sql);) { + try (ResultSet resultSet = preparedStatement.executeQuery();) { while (resultSet.next()) { Account.Type acctType = new Account.Type(resultSet.getString("type_name"), resultSet.getString("display_name")); CentralRepoAccountType crAccountType = new CentralRepoAccountType(resultSet.getInt("id"), acctType, resultSet.getInt("correlation_type_id")); - + accountTypes.add(crAccountType); - } + } } } catch (SQLException ex) { throw new CentralRepoException("Error getting account types from central repository.", ex); // NON-NLS - } + } return accountTypes; } - + /** * Gets the CR account type for the specified type name. - * + * * @param accountTypeName account type name to look for + * * @return CR account type - * - * @throws CentralRepoException + * + * @throws CentralRepoException */ private CentralRepoAccountType getCRAccountTypeFromDb(String accountTypeName) throws CentralRepoException { String sql = "SELECT * FROM account_types WHERE type_name = ?"; - try ( Connection conn = connect(); - PreparedStatement preparedStatement = conn.prepareStatement(sql);) { + try (Connection conn = connect(); + PreparedStatement preparedStatement = conn.prepareStatement(sql);) { preparedStatement.setString(1, accountTypeName); try (ResultSet resultSet = preparedStatement.executeQuery();) { @@ -1170,24 +1166,27 @@ abstract class RdbmsCentralRepo implements CentralRepository { } } catch (SQLException ex) { throw new CentralRepoException("Error getting correlation type by id.", ex); // NON-NLS - } + } } - + /** - * Get the CR account with the given account type and the unique account identifier. - * Looks in the cache first. - * If not found in cache, reads from the database and saves in cache. - * - * Returns null if the account is not found in the cache and not in the database. - * - * @param crAccountType account type to look for + * Get the CR account with the given account type and the unique account + * identifier. Looks in the cache first. If not found in cache, reads from + * the database and saves in cache. + * + * Returns null if the account is not found in the cache and not in the + * database. + * + * @param crAccountType account type to look for * @param accountUniqueID unique account id - * @return CentralRepoAccount for the give type/id. May return null if not found. - * - * @throws CentralRepoException + * + * @return CentralRepoAccount for the give type/id. May return null if not + * found. + * + * @throws CentralRepoException */ private CentralRepoAccount getAccount(CentralRepoAccountType crAccountType, String accountUniqueID) throws CentralRepoException { - + CentralRepoAccount crAccount = accountsCache.getIfPresent(Pair.of(crAccountType, accountUniqueID)); if (crAccount == null) { crAccount = getCRAccountFromDb(crAccountType, accountUniqueID); @@ -1195,30 +1194,29 @@ abstract class RdbmsCentralRepo implements CentralRepository { accountsCache.put(Pair.of(crAccountType, accountUniqueID), crAccount); } } - + return crAccount; } - - + /** - * Get the Account with the given account type and account identifier, - * from the database. + * Get the Account with the given account type and account identifier, from + * the database. * - * @param accountType account type + * @param accountType account type * @param accountUniqueID unique account identifier * * @return Account, returns NULL is no matching account found * * @throws TskCoreException exception thrown if a critical error occurs - * within TSK core + * within TSK core */ private CentralRepoAccount getCRAccountFromDb(CentralRepoAccountType crAccountType, String accountUniqueID) throws CentralRepoException { CentralRepoAccount account = null; String sql = "SELECT * FROM accounts WHERE account_type_id = ? AND account_unique_identifier = ?"; - try ( Connection connection = connect(); - PreparedStatement preparedStatement = connection.prepareStatement(sql);) { + try (Connection connection = connect(); + PreparedStatement preparedStatement = connection.prepareStatement(sql);) { preparedStatement.setInt(1, crAccountType.getAccountTypeId()); preparedStatement.setString(2, accountUniqueID); @@ -1234,8 +1232,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { return account; } - - + private void checkAddArtifactInstanceNulls(CorrelationAttributeInstance eamArtifact) throws CentralRepoException { if (eamArtifact == null) { throw new CentralRepoException("CorrelationAttribute is null"); @@ -1576,7 +1573,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { synchronized (bulkArtifacts) { if (bulkArtifacts.get(CentralRepoDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType())) == null) { - bulkArtifacts.put(CentralRepoDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()), new ArrayList<>()); + bulkArtifacts.put(CentralRepoDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()), new ArrayList<>()); } bulkArtifacts.get(CentralRepoDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType())).add(eamArtifact); bulkArtifactsCount++; @@ -2001,11 +1998,10 @@ abstract class RdbmsCentralRepo implements CentralRepository { + "AND file_path=?"; String sqlUpdate - = "UPDATE " - + tableName - + " SET known_status=? WHERE id=?"; - - + = "UPDATE " + + tableName + + " SET known_status=? WHERE id=?"; + try { preparedQuery = conn.prepareStatement(sqlQuery); preparedQuery.setInt(1, eamArtifact.getCorrelationCase().getID()); @@ -2325,8 +2321,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { HashHitInfo found = new HashHitInfo(hashFound, "", ""); found.addComment(comment); return found; - } - else { + } else { return null; } } catch (SQLException ex) { @@ -2337,8 +2332,6 @@ abstract class RdbmsCentralRepo implements CentralRepository { CentralRepoDbUtil.closeConnection(conn); } } - - /** * Check if the given value is in a specific reference set @@ -2509,7 +2502,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { CentralRepoDbUtil.closeConnection(conn); } } - + /** * Process a SELECT query * @@ -2547,7 +2540,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { CentralRepoDbUtil.closeResultSet(resultSet); CentralRepoDbUtil.closeConnection(conn); } - } + } @Override public void executeInsertSQL(String insertClause) throws CentralRepoException { @@ -2590,7 +2583,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { throw new CentralRepoException(String.format("Error running SQL %s, exception = %s", selectSQL, ex.getMessage()), ex); } } - + @Override public CentralRepoOrganization newOrganization(CentralRepoOrganization eamOrg) throws CentralRepoException { if (eamOrg == null) { @@ -2730,15 +2723,16 @@ abstract class RdbmsCentralRepo implements CentralRepository { } /** - * Queries the examiner table for the given user name. - * Adds a row if the user is not found in the examiner table. + * Queries the examiner table for the given user name. Adds a row if the + * user is not found in the examiner table. * * @param examinerLoginName user name to look for. + * * @return CentralRepoExaminer for the given user name. + * * @throws CentralRepoException If there is an error in looking up or - * inserting the user in the examiners table. + * inserting the user in the examiners table. */ - @Override public CentralRepoExaminer getOrInsertExaminer(String examinerLoginName) throws CentralRepoException { @@ -2763,7 +2757,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { default: throw new CentralRepoException(String.format("Cannot add examiner to currently selected CR database platform %s", CentralRepoDbManager.getSavedDbChoice().getDbPlatform())); //NON-NLS } - statement.execute(insertSQL); + statement.execute(insertSQL); // Query the table again to get the row for the user try (ResultSet resultSet2 = statement.executeQuery(querySQL)) { @@ -2783,7 +2777,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { throw new CentralRepoException("Error getting examiner for name = " + examinerLoginName, ex); } } - + /** * Update an existing organization. * @@ -3178,7 +3172,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { typeId = newCorrelationTypeKnownId(newType); } - synchronized(typeCache) { + synchronized (typeCache) { typeCache.put(newType.getId(), newType); } return typeId; @@ -3395,7 +3389,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { preparedStatement.setInt(4, aType.isEnabled() ? 1 : 0); preparedStatement.setInt(5, aType.getId()); preparedStatement.executeUpdate(); - synchronized(typeCache) { + synchronized (typeCache) { typeCache.put(aType.getId(), aType); } } catch (SQLException ex) { @@ -3419,7 +3413,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { @Override public CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId) throws CentralRepoException { try { - synchronized(typeCache) { + synchronized (typeCache) { return typeCache.get(typeId, () -> getCorrelationTypeByIdFromCr(typeId)); } } catch (CacheLoader.InvalidCacheLoadException ignored) { @@ -3430,7 +3424,6 @@ abstract class RdbmsCentralRepo implements CentralRepository { } } - /** * Get the EamArtifact.Type that has the given Type.Id from the central repo * @@ -3469,24 +3462,25 @@ abstract class RdbmsCentralRepo implements CentralRepository { } /** - * Reads the correlation types from the database and loads them up in the cache. - * + * Reads the correlation types from the database and loads them up in the + * cache. + * * @throws CentralRepoException If there is an error. */ private void getCorrelationTypesFromCr() throws CentralRepoException { - + // clear out the cache - synchronized(typeCache) { + synchronized (typeCache) { typeCache.invalidateAll(); isCRTypeCacheInitialized = false; } - - String sql = "SELECT * FROM correlation_types"; - try ( Connection conn = connect(); - PreparedStatement preparedStatement = conn.prepareStatement(sql); - ResultSet resultSet = preparedStatement.executeQuery();) { - synchronized(typeCache) { + String sql = "SELECT * FROM correlation_types"; + try (Connection conn = connect(); + PreparedStatement preparedStatement = conn.prepareStatement(sql); + ResultSet resultSet = preparedStatement.executeQuery();) { + + synchronized (typeCache) { while (resultSet.next()) { CorrelationAttributeInstance.Type aType = getCorrelationTypeFromResultSet(resultSet); typeCache.put(aType.getId(), aType); @@ -3495,9 +3489,9 @@ abstract class RdbmsCentralRepo implements CentralRepository { } } catch (SQLException ex) { throw new CentralRepoException("Error getting correlation types.", ex); // NON-NLS - } + } } - + /** * Convert a ResultSet to a EamCase object * @@ -3655,13 +3649,13 @@ abstract class RdbmsCentralRepo implements CentralRepository { case POSTGRESQL: return "INSERT " + sql + " ON CONFLICT DO NOTHING"; //NON-NLS case SQLITE: - return "INSERT OR IGNORE " + sql; - + return "INSERT OR IGNORE " + sql; + default: throw new CentralRepoException("Unknown Central Repo DB platform" + CentralRepoDbManager.getSavedDbChoice().getDbPlatform()); } } - + /** * Determine if a specific column already exists in a specific table * @@ -3774,7 +3768,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { */ if (dbSchemaVersion.compareTo(new CaseDbSchemaVersionNumber(1, 2)) < 0) { final String addIntegerColumnTemplate = "ALTER TABLE %s ADD COLUMN %s INTEGER;"; //NON-NLS - + final String addSsidTableTemplate = RdbmsCentralRepoFactory.getCreateArtifactInstancesTableTemplate(selectedPlatform); final String addCaseIdIndexTemplate = RdbmsCentralRepoFactory.getAddCaseIdIndexTemplate(); final String addDataSourceIdIndexTemplate = RdbmsCentralRepoFactory.getAddDataSourceIdIndexTemplate(); @@ -3794,7 +3788,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { default: throw new CentralRepoException("Currently selected database platform \"" + selectedPlatform.name() + "\" can not be upgraded.", Bundle.AbstractSqlEamDb_cannotUpgrage_message(selectedPlatform.name())); } - + final String dataSourcesTableName = "data_sources"; final String dataSourceObjectIdColumnName = "datasource_obj_id"; if (!doesColumnExist(conn, dataSourcesTableName, dataSourceObjectIdColumnName)) { @@ -3959,7 +3953,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { // Upgrade to 1.4 (new CentralRepoDbUpgrader13To14()).upgradeSchema(dbSchemaVersion, conn); - + // Upgrade to 1.5 (new CentralRepoDbUpgrader14To15()).upgradeSchema(dbSchemaVersion, conn); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index cbd136b31c..44e19ca11c 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -90,7 +90,7 @@ final class CaseEventListener implements PropertyChangeListener { if (!(evt instanceof AutopsyEvent) || (((AutopsyEvent) evt).getSourceType() != AutopsyEvent.SourceType.LOCAL)) { return; } - + CentralRepository dbManager; try { dbManager = CentralRepository.getInstance(); @@ -222,16 +222,16 @@ final class CaseEventListener implements PropertyChangeListener { String.format("ContentTagDeletedEvent %s did not have valid content to provide a content id.", evt)); return; } - + try { // obtain content Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(evt.getDeletedTagInfo().getContentID()); if (content == null) { LOGGER.log(Level.WARNING, - String.format("Unable to get content for item with content id: %d.", evt.getDeletedTagInfo().getContentID())); + String.format("Unable to get content for item with content id: %d.", evt.getDeletedTagInfo().getContentID())); return; } - + // then handle the event handleTagChange(content); } catch (NoCurrentCaseException | TskCoreException ex) { @@ -246,14 +246,15 @@ final class CaseEventListener implements PropertyChangeListener { String.format("ContentTagAddedEvent %s did not have valid content to provide a content id.", evt)); return; } - + // then handle the event handleTagChange(evt.getAddedTag().getContent()); } /** - * When a tag is added or deleted, check if there are other notable tags for the item. - * If there are, set known status as notable. If not set status as unknown. + * When a tag is added or deleted, check if there are other notable tags + * for the item. If there are, set known status as notable. If not set + * status as unknown. * * @param content The content for the tag that was added or deleted. */ @@ -268,7 +269,7 @@ final class CaseEventListener implements PropertyChangeListener { if (af == null) { return; } - + try { // Get the tags on the content object TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager(); @@ -276,8 +277,7 @@ final class CaseEventListener implements PropertyChangeListener { if (hasNotableTag(tagsManager.getContentTagsByContent(content))) { // if there is a notable tag on the object, set content known status to bad setContentKnownStatus(af, TskData.FileKnown.BAD); - } - else { + } else { // otherwise, set to unknown setContentKnownStatus(af, TskData.FileKnown.UNKNOWN); } @@ -286,7 +286,6 @@ final class CaseEventListener implements PropertyChangeListener { } } - /** * Sets the known status for the correlation attribute instance for the * given abstract file. @@ -345,26 +344,26 @@ final class CaseEventListener implements PropertyChangeListener { String.format("ContentTagDeletedEvent %s did not have valid content to provide a content id.", evt)); return; } - + try { Case openCase = Case.getCurrentCaseThrows(); - + // obtain content Content content = openCase.getSleuthkitCase().getContentById(evt.getDeletedTagInfo().getContentID()); if (content == null) { LOGGER.log(Level.WARNING, - String.format("Unable to get content for item with content id: %d.", evt.getDeletedTagInfo().getContentID())); + String.format("Unable to get content for item with content id: %d.", evt.getDeletedTagInfo().getContentID())); return; } - + // obtain blackboard artifact BlackboardArtifact bbArtifact = openCase.getSleuthkitCase().getBlackboardArtifact(evt.getDeletedTagInfo().getArtifactID()); if (bbArtifact == null) { LOGGER.log(Level.WARNING, - String.format("Unable to get blackboard artifact for item with artifact id: %d.", evt.getDeletedTagInfo().getArtifactID())); + String.format("Unable to get blackboard artifact for item with artifact id: %d.", evt.getDeletedTagInfo().getArtifactID())); return; } - + // then handle the event handleTagChange(content, bbArtifact); } catch (NoCurrentCaseException | TskCoreException ex) { @@ -379,16 +378,17 @@ final class CaseEventListener implements PropertyChangeListener { String.format("ContentTagAddedEvent %s did not have valid content to provide a content id.", evt)); return; } - + // then handle the event handleTagChange(evt.getAddedTag().getContent(), evt.getAddedTag().getArtifact()); } /** - * When a tag is added or deleted, check if there are other notable tags for the item. - * If there are, set known status as notable. If not set status as unknown. + * When a tag is added or deleted, check if there are other notable tags + * for the item. If there are, set known status as notable. If not set + * status as unknown. * - * @param content The content for the tag that was added or deleted. + * @param content The content for the tag that was added or deleted. * @param bbArtifact The artifact for the tag that was added or deleted. */ private void handleTagChange(Content content, BlackboardArtifact bbArtifact) { @@ -409,8 +409,7 @@ final class CaseEventListener implements PropertyChangeListener { List tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact); if (hasNotableTag(tags)) { setArtifactKnownStatus(bbArtifact, TskData.FileKnown.BAD); - } - else { + } else { setArtifactKnownStatus(bbArtifact, TskData.FileKnown.UNKNOWN); } } catch (TskCoreException ex) { From 147d7535d17fbd4c6261a16b70b7fd71db18fea2 Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Thu, 14 May 2020 10:41:52 -0400 Subject: [PATCH 80/90] 6354 Fixing errors + Codacy --- .../autopsy/persona/PersonaDetailsTopComponent.java | 4 ++-- .../autopsy/persona/PersonaSearchTopComponent.java | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.java index 1177901493..fdc0af6e0d 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonaDetailsTopComponent.java @@ -33,11 +33,11 @@ import org.openide.windows.WindowManager; public final class PersonaDetailsTopComponent extends TopComponent { @Messages({ - "PTopComponent_Name=Persona Details" + "PDTopComponent_Name=Persona Details" }) public PersonaDetailsTopComponent() { initComponents(); - setName(Bundle.PTopComponent_Name()); + setName(Bundle.PDTopComponent_Name()); } /** diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java index 9d37d7797e..128c0b04b5 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java @@ -44,11 +44,11 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.Persona; public final class PersonaSearchTopComponent extends TopComponent { @Messages({ - "PTopComponent_Name=Persona Search" + "PSTopComponent_Name=Persona Search" }) public PersonaSearchTopComponent() { initComponents(); - setName(Bundle.PTopComponent_Name()); + setName(Bundle.PSTopComponent_Name()); executeSearch(); searchBtn.addActionListener(new ActionListener() { @@ -58,8 +58,12 @@ public final class PersonaSearchTopComponent extends TopComponent { } }); } - + + /** + * Table model for the persona search results + */ class PersonaFilterTableModel extends DefaultTableModel { + private static final long serialVersionUID = 1L; PersonaFilterTableModel(Object[][] rows, String[] colNames) { super(rows, colNames); From 5c14e4d99bb2fc4775e08779df40b7228ba54ffb Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Thu, 14 May 2020 16:56:24 -0400 Subject: [PATCH 81/90] Interim commit - Fixed the spacing & indentation. --- .../contentviewers/ContactArtifactViewer.form | 46 +++++-- .../contentviewers/ContactArtifactViewer.java | 118 ++++++++---------- 2 files changed, 91 insertions(+), 73 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form index e916c58b08..63150e57fc 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -29,7 +29,7 @@ - + @@ -67,14 +67,14 @@ - + - + @@ -98,7 +98,7 @@ - + @@ -115,18 +115,48 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java index 71d52f05c0..d1dd1e6ff9 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java @@ -19,13 +19,11 @@ package org.sleuthkit.autopsy.contentviewers; import java.awt.Component; -import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; -import javax.swing.Box; import javax.swing.JLabel; import javax.swing.JPanel; import org.sleuthkit.autopsy.coreutils.Logger; @@ -66,6 +64,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac emailsPanel = new javax.swing.JPanel(); othersLabel = new javax.swing.JLabel(); otherAttrsPanel = new javax.swing.JPanel(); + filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767)); + filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0)); setLayout(new java.awt.GridBagLayout()); @@ -79,7 +79,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac .addGroup(namePanelLayout.createSequentialGroup() .addContainerGap() .addComponent(contactNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 161, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(233, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); namePanelLayout.setVerticalGroup( namePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -93,8 +93,6 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.gridwidth = 4; - gridBagConstraints.ipadx = 227; - gridBagConstraints.ipady = -7; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; add(namePanel, gridBagConstraints); @@ -105,7 +103,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints.gridy = 1; gridBagConstraints.gridwidth = 3; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(18, 19, 0, 0); + gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); add(phonesLabel, gridBagConstraints); phoneNumbersPanel.setLayout(new java.awt.GridBagLayout()); @@ -113,10 +111,9 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.gridwidth = 4; - gridBagConstraints.ipadx = 400; - gridBagConstraints.ipady = 101; + gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0); + gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); add(phoneNumbersPanel, gridBagConstraints); emailsLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N @@ -134,10 +131,9 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 4; gridBagConstraints.gridwidth = 4; - gridBagConstraints.ipadx = 400; - gridBagConstraints.ipady = 106; + gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 0); + gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); add(emailsPanel, gridBagConstraints); othersLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N @@ -146,7 +142,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 5; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(18, 19, 0, 0); + gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); add(othersLabel, gridBagConstraints); otherAttrsPanel.setLayout(new java.awt.GridBagLayout()); @@ -154,11 +150,25 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 6; gridBagConstraints.gridwidth = 4; - gridBagConstraints.ipadx = 400; - gridBagConstraints.ipady = 100; + gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(6, 0, 29, 0); + gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); add(otherAttrsPanel, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 7; + gridBagConstraints.gridwidth = 4; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weighty = 1.0; + add(filler1, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 4; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridheight = 8; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.ipadx = 2; + gridBagConstraints.weightx = 1.0; + add(filler2, gridBagConstraints); }// //GEN-END:initComponents @Override @@ -173,7 +183,6 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac List nameList = new ArrayList<>(); List otherList = new ArrayList<>(); - try { // Get all the attributes and group them by the panels they go in for (BlackboardAttribute bba : artifact.getAttributes()) { @@ -194,13 +203,12 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac // RAMAN TBD: test with multiple phones and emails phoneNumList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE, "RAMAN", "+1 222 333 4444")); phoneNumList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE, "RAMAN", "123456789012")); - + emailList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_HOME, "RAMAN", "home@gmail.com")); emailList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_OFFICE, "RAMAN", "workemail@provider.com")); - + otherList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID, "RAMAN", "8:live:atpsy.sbarney")); - - + updateNamePanel(nameList); updateSection(phoneNumList, this.phonesLabel, this.phoneNumbersPanel); @@ -208,9 +216,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac updateSection(emailList, this.emailsLabel, this.emailsPanel); //updateOtherAttributesPanel(otherList); - updateSection(otherList, this.othersLabel, this.otherAttrsPanel); - + // repaint this.revalidate(); } @@ -232,10 +239,10 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac break; } } - + contactNameLabel.revalidate(); } - + // private void updatePhoneNumbersPanel(List phoneAttributesList) { // // if (phoneAttributesList.isEmpty()) { @@ -302,7 +309,6 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac // // phoneNumbersPanel.revalidate(); // } - // private void updateEmailAddressesPanel(List emailAddressAttributesList) { // // if (emailAddressAttributesList.isEmpty()) { @@ -364,7 +370,6 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac // emailsPanel.setLayout(gridBagLayout); // emailsPanel.revalidate(); // } - // private void updateOtherAttributesPanel(List otherAttributesList) { // // if (otherAttributesList.isEmpty()) { @@ -424,73 +429,56 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac // otherAttrsPanel.setLayout(gridBagLayout); // otherAttrsPanel.revalidate(); // } - - private void updateSection(List sectionAttributesList, JLabel sectionLabel, JPanel sectionPanel) { - + private void updateSection(List sectionAttributesList, JLabel sectionLabel, JPanel sectionPanel) { + if (sectionAttributesList.isEmpty()) { sectionLabel.setVisible(false); sectionPanel.setVisible(false); return; } - + GridBagLayout gridBagLayout = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); - constraints.fill = GridBagConstraints.HORIZONTAL; - constraints.gridx = 0; - constraints.gridy = -1; - constraints.weighty = .0; - constraints.anchor = GridBagConstraints.LINE_START; - - Dimension horizSpacerBlockDimension = new Dimension(12, 4); - + constraints.anchor = GridBagConstraints.FIRST_LINE_START; + constraints.gridy = 0; + constraints.insets = new java.awt.Insets(4, 12, 0, 0); for (BlackboardAttribute bba : sectionAttributesList) { + constraints.fill = GridBagConstraints.NONE; constraints.weightx = 0; - constraints.gridy++; - constraints.gridx = 0; - + constraints.gridx = 0; + // Add a label for attribute type javax.swing.JLabel attrTypeLabel = new javax.swing.JLabel(); String attrLabel = bba.getAttributeType().getDisplayName(); attrTypeLabel.setText(attrLabel); - + // RAMAN TBD: set the size/font/style for label - gridBagLayout.setConstraints(attrTypeLabel, constraints); sectionPanel.add(attrTypeLabel); - - // Add horizontal space - constraints.gridx++; - Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); - gridBagLayout.setConstraints(spacer, constraints); - sectionPanel.add(spacer); - + // Add the attribute value - constraints.gridx++; + constraints.gridx++; javax.swing.JLabel attrValueLabel = new javax.swing.JLabel(); attrValueLabel.setText(bba.getValueString()); gridBagLayout.setConstraints(attrValueLabel, constraints); sectionPanel.add(attrValueLabel); + + constraints.gridx++; + constraints.weightx = 1.0; + constraints.fill = GridBagConstraints.HORIZONTAL; + sectionPanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0))); + constraints.gridy++; } - - - //constraints.gridy++; - //constraints.gridx = 0; - //constraints.weighty = 1; - //Component vertGlue = createVerticalGlue(); - //emailsPanel.add(vertGlue); - //gridBagLayout.setConstraints(vertGlue, constraints); - - sectionPanel.setLayout(gridBagLayout); sectionPanel.revalidate(); } - - - + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel contactNameLabel; private javax.swing.JLabel emailsLabel; private javax.swing.JPanel emailsPanel; + private javax.swing.Box.Filler filler1; + private javax.swing.Box.Filler filler2; private javax.swing.JPanel namePanel; private javax.swing.JPanel otherAttrsPanel; private javax.swing.JLabel othersLabel; From 3c517371a0be3d575627426d4ad988c76932b432 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 15 May 2020 07:40:29 -0400 Subject: [PATCH 82/90] only non-blank comments for fileset hits --- .../AnnotationsContentViewer.java | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index 344589e5ce..2298a155f3 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -32,6 +32,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.Pair; import static org.openide.util.NbBundle.Messages; +import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.autopsy.coreutils.Logger; import org.openide.nodes.Node; import org.openide.util.lookup.ServiceProvider; @@ -305,8 +306,11 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data contentRendered = contentRendered || crRendered; } - if (BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == bba.getArtifactTypeID() - || BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID()) { + // if artifact is a hashset hit or interesting file and has a non-blank comment + if ((ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == bba.getArtifactTypeID() + || ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID()) + && (hasTskComment(bba))) { + boolean filesetRendered = appendEntries(parent, ARTIFACT_COMMENT_CONFIG, Arrays.asList(bba), false); contentRendered = contentRendered || filesetRendered; } @@ -344,11 +348,11 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data } boolean hashsetRendered = appendEntries(parent, HASHSET_CONFIG, - getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT), + getFileSetHits(sourceFile, ARTIFACT_TYPE.TSK_HASHSET_HIT), isSubheader); boolean interestingFileRendered = appendEntries(parent, INTERESTING_FILE_CONFIG, - getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT), + getFileSetHits(sourceFile, ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT), isSubheader); contentRendered = contentRendered || hashsetRendered || interestingFileRendered; @@ -396,17 +400,19 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data /** * Retrieves the blackboard artifacts for a source file matching a certain - * type. + * type that have a non-blank TSK_COMMENT. * * @param sourceFile The source file for which to fetch artifacts. * @param type The type of blackboard artifact to fetch. * * @return The artifacts found matching this type. */ - private static List getFileSetHits(AbstractFile sourceFile, BlackboardArtifact.ARTIFACT_TYPE type) { + private static List getFileSetHits(AbstractFile sourceFile, ARTIFACT_TYPE type) { try { SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - return tskCase.getBlackboardArtifacts(type, sourceFile.getId()); + return tskCase.getBlackboardArtifacts(type, sourceFile.getId()).stream() + .filter((bba) -> hasTskComment(bba)) + .collect(Collectors.toList()); } catch (NoCurrentCaseException ex) { logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS } catch (TskCoreException ex) { @@ -415,6 +421,17 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data return new ArrayList<>(); } + /** + * Returns true if the artifact contains a non-blank TSK_COMMENT attribute. + * + * @param artifact The artifact to check. + * + * @return True if it has a non-blank TSK_COMMENT. + */ + private static boolean hasTskComment(BlackboardArtifact artifact) { + return StringUtils.isNotBlank(tryGetAttribute(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT)); + } + /** * Attempts to retrieve the attribute of a particular type from a blackboard * artifact. @@ -489,7 +506,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data if (artifactTypes == null || artifactTypes.isEmpty()) { return new ArrayList<>(); } - + String md5 = sourceFile.getMd5Hash(); // get key lookups for a file attribute types and the md5 hash @@ -519,7 +536,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data .getArtifactInstancesByTypeValue(typeVal.getKey(), typeVal.getValue()) .stream() // for each one found, if it has a comment, return - .filter((cai) -> StringUtils.isNotEmpty(cai.getComment())) + .filter((cai) -> StringUtils.isNotBlank(cai.getComment())) .collect(Collectors.toList())); } From a0018cab57b52f7f61117305cd5e42277a3e071c Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Fri, 15 May 2020 09:32:13 -0400 Subject: [PATCH 83/90] Added a vertical scrollbar to the panel returned. Sundry cleanup and commenting. --- .../contentviewers/ContactArtifactViewer.java | 221 +++--------------- 1 file changed, 32 insertions(+), 189 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java index d1dd1e6ff9..ad4f08a16b 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.logging.Level; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JScrollPane; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -184,7 +185,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac List otherList = new ArrayList<>(); try { - // Get all the attributes and group them by the panels they go in + // Get all the attributes and group them by the section panels they go in for (BlackboardAttribute bba : artifact.getAttributes()) { if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) { phoneNumList.add(bba); @@ -224,14 +225,27 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac @Override public Component getComponent() { - return this; + // Slap a vertical scrollbar on the panel. + return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); } + /** + * Check if the given artifact is supported by this viewer. + * + * This viewer supports TSK_CONTACT artifacts. + * @param artifact artifact to check. + * @return True if the artifact is supported, false otherwise. + */ @Override public boolean isSupported(BlackboardArtifact artifact) { return artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID(); } + /** + * Updates the contact name in the view. + * + * @param attributesList + */ private void updateNamePanel(List attributesList) { for (BlackboardAttribute bba : attributesList) { if (bba.getAttributeType().getTypeName().startsWith("TSK_NAME")) { @@ -243,200 +257,23 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac contactNameLabel.revalidate(); } -// private void updatePhoneNumbersPanel(List phoneAttributesList) { -// -// if (phoneAttributesList.isEmpty()) { -// this.phonesLabel.setVisible(false); -// phoneNumbersPanel.setVisible(false); -// return; -// } -// -// GridBagLayout gridBagLayout = new GridBagLayout(); -// GridBagConstraints constraints = new GridBagConstraints(); -// constraints.fill = GridBagConstraints.HORIZONTAL; -// constraints.gridx = 0; -// constraints.gridy = -1; -// constraints.weighty = .0; -// constraints.anchor = GridBagConstraints.LINE_START; -// -// Dimension horizSpacerBlockDimension = new Dimension(12, 4); -// -// for (BlackboardAttribute bba : phoneAttributesList) { -// constraints.weightx = 0; -// constraints.gridy++; -// constraints.gridx = 0; -// -// // Add a label for phone number type -// javax.swing.JLabel phoneTypeLabel = new javax.swing.JLabel(); -// -// -// -// String attributeLabel = bba.getAttributeType().getDisplayName(); -// phoneTypeLabel.setText(attributeLabel); -// -// // RAMAN TBD: set the size/font/style for label -// //Font newLabelFont=new Font(phoneTypeLabel.getFont().getName(),Font.ITALIC+Font.BOLD,phoneTypeLabel.getFont().getSize()); -// //phoneTypeLabel.setFont(newLabelFont); -// -// gridBagLayout.setConstraints(phoneTypeLabel, constraints); -// phoneNumbersPanel.add(phoneTypeLabel); -// -// // Add horizontal space -// constraints.gridx++; -// Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); -// gridBagLayout.setConstraints(spacer, constraints); -// phoneNumbersPanel.add(spacer); -// -// // Add a label for the phone number -// constraints.gridx++; -// javax.swing.JLabel phoneNumberLabel = new javax.swing.JLabel(); -// phoneNumberLabel.setText(bba.getValueString()); -// -// gridBagLayout.setConstraints(phoneNumberLabel, constraints); -// phoneNumbersPanel.add(phoneNumberLabel); -// } -// -// -// //constraints.gridy++; -// //constraints.gridx = 0; -// //constraints.weighty = 1; -// //Component vertGlue = createVerticalGlue(); -// //this.phoneNumbersPanel.add(vertGlue); -// //gridBagLayout.setConstraints(vertGlue, constraints); -// -// phoneNumbersPanel.setLayout(gridBagLayout); -// -// -// phoneNumbersPanel.revalidate(); -// } -// private void updateEmailAddressesPanel(List emailAddressAttributesList) { -// -// if (emailAddressAttributesList.isEmpty()) { -// emailsLabel.setVisible(false); -// this.emailsPanel.setVisible(false); -// return; -// } -// -// GridBagLayout gridBagLayout = new GridBagLayout(); -// GridBagConstraints constraints = new GridBagConstraints(); -// constraints.fill = GridBagConstraints.HORIZONTAL; -// constraints.gridx = 0; -// constraints.gridy = -1; -// constraints.weighty = .0; -// constraints.anchor = GridBagConstraints.LINE_START; -// -// Dimension horizSpacerBlockDimension = new Dimension(12, 4); -// -// for (BlackboardAttribute bba : emailAddressAttributesList) { -// constraints.weightx = 0; -// constraints.gridy++; -// constraints.gridx = 0; -// -// // Add a label for email address type -// javax.swing.JLabel emailAddressTypeLabel = new javax.swing.JLabel(); -// String attrLabel = bba.getAttributeType().getDisplayName(); -// emailAddressTypeLabel.setText(attrLabel); -// -// // RAMAN TBD: set the size/font/style for label -// -// gridBagLayout.setConstraints(emailAddressTypeLabel, constraints); -// emailsPanel.add(emailAddressTypeLabel); -// -// -// -// // Add horizontal space -// constraints.gridx++; -// Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); -// gridBagLayout.setConstraints(spacer, constraints); -// emailsPanel.add(spacer); -// -// // Add the phone number -// constraints.gridx++; -// javax.swing.JLabel emailAddressLabel = new javax.swing.JLabel(); -// emailAddressLabel.setText(bba.getValueString()); -// gridBagLayout.setConstraints(emailAddressLabel, constraints); -// emailsPanel.add(emailAddressLabel); -// } -// -// -// //constraints.gridy++; -// //constraints.gridx = 0; -// //constraints.weighty = 1; -// //Component vertGlue = createVerticalGlue(); -// //emailsPanel.add(vertGlue); -// //gridBagLayout.setConstraints(vertGlue, constraints); -// -// -// emailsPanel.setLayout(gridBagLayout); -// emailsPanel.revalidate(); -// } -// private void updateOtherAttributesPanel(List otherAttributesList) { -// -// if (otherAttributesList.isEmpty()) { -// this.othersLabel.setVisible(false); -// this.otherAttrsPanel.setVisible(false); -// return; -// } -// -// GridBagLayout gridBagLayout = new GridBagLayout(); -// GridBagConstraints constraints = new GridBagConstraints(); -// constraints.fill = GridBagConstraints.HORIZONTAL; -// constraints.gridx = 0; -// constraints.gridy = -1; -// constraints.weighty = .0; -// constraints.anchor = GridBagConstraints.LINE_START; -// -// Dimension horizSpacerBlockDimension = new Dimension(12, 4); -// -// for (BlackboardAttribute bba : otherAttributesList) { -// constraints.weightx = 0; -// constraints.gridy++; -// constraints.gridx = 0; -// -// // Add a label for attribute type -// javax.swing.JLabel attrTypeLabel = new javax.swing.JLabel(); -// String attrLabel = bba.getAttributeType().getDisplayName(); -// attrTypeLabel.setText(attrLabel); -// -// // RAMAN TBD: set the size/font/style for label -// -// gridBagLayout.setConstraints(attrTypeLabel, constraints); -// otherAttrsPanel.add(attrTypeLabel); -// -// // Add horizontal space -// constraints.gridx++; -// Box.Filler spacer = new Box.Filler(horizSpacerBlockDimension, horizSpacerBlockDimension, horizSpacerBlockDimension); -// gridBagLayout.setConstraints(spacer, constraints); -// otherAttrsPanel.add(spacer); -// -// // Add the attribute value -// constraints.gridx++; -// javax.swing.JLabel attrValueLabel = new javax.swing.JLabel(); -// attrValueLabel.setText(bba.getValueString()); -// gridBagLayout.setConstraints(attrValueLabel, constraints); -// otherAttrsPanel.add(attrValueLabel); -// } -// -// -// //constraints.gridy++; -// //constraints.gridx = 0; -// //constraints.weighty = 1; -// //Component vertGlue = createVerticalGlue(); -// //emailsPanel.add(vertGlue); -// //gridBagLayout.setConstraints(vertGlue, constraints); -// -// -// otherAttrsPanel.setLayout(gridBagLayout); -// otherAttrsPanel.revalidate(); -// } + /** + * Updates the view by displaying the given list of attributes in the given section panel. + * + * @param sectionAttributesList list of attributes to display. + * @param sectionLabel section name label. + * @param sectionPanel section panel to display the attributes in. + */ private void updateSection(List sectionAttributesList, JLabel sectionLabel, JPanel sectionPanel) { + // If there are no attributes for tis section, hide the section panel and the section label if (sectionAttributesList.isEmpty()) { sectionLabel.setVisible(false); sectionPanel.setVisible(false); return; } + // create a gridbag layout to show each attribute on one line GridBagLayout gridBagLayout = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); constraints.anchor = GridBagConstraints.FIRST_LINE_START; @@ -445,6 +282,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac for (BlackboardAttribute bba : sectionAttributesList) { constraints.fill = GridBagConstraints.NONE; constraints.weightx = 0; + constraints.gridx = 0; // Add a label for attribute type @@ -452,7 +290,10 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac String attrLabel = bba.getAttributeType().getDisplayName(); attrTypeLabel.setText(attrLabel); - // RAMAN TBD: set the size/font/style for label + // make type label bold + //Font newLabelFont=new Font(attrTypeLabel.getFont().getName(),Font.BOLD,attrTypeLabel.getFont().getSize()); + //attrTypeLabel.setFont(newLabelFont); + gridBagLayout.setConstraints(attrTypeLabel, constraints); sectionPanel.add(attrTypeLabel); @@ -463,10 +304,12 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagLayout.setConstraints(attrValueLabel, constraints); sectionPanel.add(attrValueLabel); + // add a filler to take up rest of the space constraints.gridx++; constraints.weightx = 1.0; constraints.fill = GridBagConstraints.HORIZONTAL; sectionPanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0))); + constraints.gridy++; } sectionPanel.setLayout(gridBagLayout); From adf2c5ccb65f28233931d98502d1d9dab0d1fbdd Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 15 May 2020 09:46:52 -0400 Subject: [PATCH 84/90] remove method generic parameters --- .../autopsy/contentviewers/AnnotationsContentViewer.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index 2298a155f3..a12675994e 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -554,7 +554,6 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data * will be formatted as a table in the format specified in the * SectionConfig. * - * @param The item type. * @param parent The parent element for which the entries will be * attached. * @param config The display configuration for this entry type (i.e. @@ -579,7 +578,6 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data /** * Appends a table where items are displayed in rows of key-value pairs. * - * @param * @param parent The parent to append the table. * @param items The items to process into a series of tables. * @param rowHeaders The keys and the means to process items in order to get From 9dd0eb0109c2b9c39c3750d78065a6dcd2a92dfd Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Fri, 15 May 2020 10:50:06 -0400 Subject: [PATCH 85/90] 6354 PR comments --- .../autopsy/persona/PersonaSearchTopComponent.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java b/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java index 128c0b04b5..7cf22279db 100644 --- a/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/persona/PersonaSearchTopComponent.java @@ -62,7 +62,7 @@ public final class PersonaSearchTopComponent extends TopComponent { /** * Table model for the persona search results */ - class PersonaFilterTableModel extends DefaultTableModel { + final class PersonaFilterTableModel extends DefaultTableModel { private static final long serialVersionUID = 1L; PersonaFilterTableModel(Object[][] rows, String[] colNames) { @@ -75,7 +75,7 @@ public final class PersonaSearchTopComponent extends TopComponent { } } - void updateResultsTable(Collection results) { + private void updateResultsTable(Collection results) { Object[][] rows = new Object[results.size()][2]; int i = 0; for (Persona result : results) { @@ -95,7 +95,7 @@ public final class PersonaSearchTopComponent extends TopComponent { filterResultsTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); } - void executeSearch() { + private void executeSearch() { Collection results = Collections.EMPTY_LIST; try { results = Persona.getPersonaByName(searchField.getText()); From 955c1efe27949f67e1d0534fc9c1c075b7fb33f9 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Fri, 15 May 2020 11:48:44 -0400 Subject: [PATCH 86/90] Applied FONT recommendations to ensure cross platform working. --- .../contentviewers/ContactArtifactViewer.form | 24 ++++++++++++------- .../contentviewers/ContactArtifactViewer.java | 13 +++++----- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form index 63150e57fc..9511554652 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form @@ -46,8 +46,10 @@ - - + + + + @@ -58,8 +60,10 @@ - - + + + + @@ -82,8 +86,10 @@ - - + + + + @@ -106,8 +112,10 @@ - - + + + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java index ad4f08a16b..03b70b5718 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java @@ -70,7 +70,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac setLayout(new java.awt.GridBagLayout()); - contactNameLabel.setFont(new java.awt.Font("Dialog", 3, 18)); // NOI18N + contactNameLabel.setFont(contactNameLabel.getFont().deriveFont((contactNameLabel.getFont().getStyle() | java.awt.Font.ITALIC) | java.awt.Font.BOLD, contactNameLabel.getFont().getSize()+6)); org.openide.awt.Mnemonics.setLocalizedText(contactNameLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.contactNameLabel.text")); // NOI18N javax.swing.GroupLayout namePanelLayout = new javax.swing.GroupLayout(namePanel); @@ -97,7 +97,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; add(namePanel, gridBagConstraints); - phonesLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N + phonesLabel.setFont(phonesLabel.getFont().deriveFont(phonesLabel.getFont().getStyle() | java.awt.Font.BOLD, phonesLabel.getFont().getSize()+2)); org.openide.awt.Mnemonics.setLocalizedText(phonesLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.phonesLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; @@ -117,7 +117,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); add(phoneNumbersPanel, gridBagConstraints); - emailsLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N + emailsLabel.setFont(emailsLabel.getFont().deriveFont(emailsLabel.getFont().getStyle() | java.awt.Font.BOLD, emailsLabel.getFont().getSize()+2)); org.openide.awt.Mnemonics.setLocalizedText(emailsLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.emailsLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; @@ -137,7 +137,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); add(emailsPanel, gridBagConstraints); - othersLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N + othersLabel.setFont(othersLabel.getFont().deriveFont(othersLabel.getFont().getStyle() | java.awt.Font.BOLD, othersLabel.getFont().getSize()+2)); org.openide.awt.Mnemonics.setLocalizedText(othersLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.othersLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; @@ -290,9 +290,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac String attrLabel = bba.getAttributeType().getDisplayName(); attrTypeLabel.setText(attrLabel); - // make type label bold - //Font newLabelFont=new Font(attrTypeLabel.getFont().getName(),Font.BOLD,attrTypeLabel.getFont().getSize()); - //attrTypeLabel.setFont(newLabelFont); + // make type label bold - uncomment if needed. + //attrTypeLabel.setFont(attrTypeLabel.getFont().deriveFont(Font.BOLD, attrTypeLabel.getFont().getSize() )); gridBagLayout.setConstraints(attrTypeLabel, constraints); sectionPanel.add(attrTypeLabel); From e50ca1d34c09fa8166179b9a11eb5c71869ca979 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Fri, 15 May 2020 11:56:41 -0400 Subject: [PATCH 87/90] Removed test code. --- .../contentviewers/ContactArtifactViewer.java | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java index 03b70b5718..603a8f04f5 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,7 +41,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac private static final long serialVersionUID = 1L; /** - * Creates new form ContactArtifactViewer + * Creates new form for ContactArtifactViewer */ public ContactArtifactViewer() { initComponents(); @@ -201,22 +201,12 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); } - // RAMAN TBD: test with multiple phones and emails - phoneNumList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE, "RAMAN", "+1 222 333 4444")); - phoneNumList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE, "RAMAN", "123456789012")); - - emailList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_HOME, "RAMAN", "home@gmail.com")); - emailList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_OFFICE, "RAMAN", "workemail@provider.com")); - - otherList.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID, "RAMAN", "8:live:atpsy.sbarney")); - + // update name section updateNamePanel(nameList); - + + // update contact attributes sections updateSection(phoneNumList, this.phonesLabel, this.phoneNumbersPanel); - updateSection(emailList, this.emailsLabel, this.emailsPanel); - - //updateOtherAttributesPanel(otherList); updateSection(otherList, this.othersLabel, this.otherAttrsPanel); // repaint @@ -230,9 +220,9 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac } /** - * Check if the given artifact is supported by this viewer. - * + * Checks if the given artifact is supported by this viewer. * This viewer supports TSK_CONTACT artifacts. + * * @param artifact artifact to check. * @return True if the artifact is supported, false otherwise. */ From 8eb716587c35b04085bc7293c7c974a646b83e6c Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Fri, 15 May 2020 12:31:35 -0400 Subject: [PATCH 88/90] Increase name label width. --- .../sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form | 2 +- .../sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form index 9511554652..30a06c53a5 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form @@ -28,7 +28,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java index 603a8f04f5..922948fae4 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java @@ -79,7 +79,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac namePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(namePanelLayout.createSequentialGroup() .addContainerGap() - .addComponent(contactNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 161, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(contactNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 240, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); namePanelLayout.setVerticalGroup( From 1ea70b7dab165182a533a0c8054aca2f59b07bf5 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 15 May 2020 14:53:29 -0400 Subject: [PATCH 89/90] logging updates --- .../eventlisteners/CaseEventListener.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index 44e19ca11c..e201f6b642 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -218,8 +218,7 @@ final class CaseEventListener implements PropertyChangeListener { private void handleTagDeleted(ContentTagDeletedEvent evt) { // ensure tag deleted event has a valid content id if (evt.getDeletedTagInfo() == null) { - LOGGER.log(Level.SEVERE, - String.format("ContentTagDeletedEvent %s did not have valid content to provide a content id.", evt)); + LOGGER.log(Level.SEVERE, "ContentTagDeletedEvent did not have valid content to provide a content id."); return; } @@ -235,15 +234,15 @@ final class CaseEventListener implements PropertyChangeListener { // then handle the event handleTagChange(content); } catch (NoCurrentCaseException | TskCoreException ex) { - LOGGER.log(Level.WARNING, "Error updating non-file object."); + Long contentID = (evt != null && evt.getDeletedTagInfo() != null) ? evt.getDeletedTagInfo().getContentID() : null; + LOGGER.log(Level.WARNING, "Error updating non-file object: " + contentID, ex); } } private void handleTagAdded(ContentTagAddedEvent evt) { // ensure tag added event has a valid content id if (evt.getAddedTag() == null || evt.getAddedTag().getContent() == null) { - LOGGER.log(Level.SEVERE, - String.format("ContentTagAddedEvent %s did not have valid content to provide a content id.", evt)); + LOGGER.log(Level.SEVERE, "ContentTagAddedEvent did not have valid content to provide a content id."); return; } @@ -263,7 +262,8 @@ final class CaseEventListener implements PropertyChangeListener { try { af = Case.getCurrentCaseThrows().getSleuthkitCase().getAbstractFileById(content.getId()); } catch (NoCurrentCaseException | TskCoreException ex) { - LOGGER.log(Level.WARNING, "Error updating non-file object."); + Long contentID = (content != null) ? content.getId() : null; + LOGGER.log(Level.WARNING, "Error updating non-file object: " + contentID, ex); } if (af == null) { @@ -340,8 +340,7 @@ final class CaseEventListener implements PropertyChangeListener { private void handleTagDeleted(BlackBoardArtifactTagDeletedEvent evt) { // ensure tag deleted event has a valid content id if (evt.getDeletedTagInfo() == null) { - LOGGER.log(Level.SEVERE, - String.format("ContentTagDeletedEvent %s did not have valid content to provide a content id.", evt)); + LOGGER.log(Level.SEVERE, "BlackBoardArtifactTagDeletedEvent did not have valid content to provide a content id."); return; } @@ -367,15 +366,14 @@ final class CaseEventListener implements PropertyChangeListener { // then handle the event handleTagChange(content, bbArtifact); } catch (NoCurrentCaseException | TskCoreException ex) { - LOGGER.log(Level.WARNING, "Error updating non-file object."); + LOGGER.log(Level.WARNING, "Error updating non-file object.", ex); } } private void handleTagAdded(BlackBoardArtifactTagAddedEvent evt) { // ensure tag added event has a valid content id if (evt.getAddedTag() == null || evt.getAddedTag().getContent() == null || evt.getAddedTag().getArtifact() == null) { - LOGGER.log(Level.SEVERE, - String.format("ContentTagAddedEvent %s did not have valid content to provide a content id.", evt)); + LOGGER.log(Level.SEVERE, "BlackBoardArtifactTagAddedEvent did not have valid content to provide a content id."); return; } From a37080c9b260368a4fc8f45ba7965b921768823e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 18 May 2020 08:42:37 -0400 Subject: [PATCH 90/90] logging update --- .../centralrepository/eventlisteners/CaseEventListener.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index e201f6b642..94a22492c1 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -234,8 +234,7 @@ final class CaseEventListener implements PropertyChangeListener { // then handle the event handleTagChange(content); } catch (NoCurrentCaseException | TskCoreException ex) { - Long contentID = (evt != null && evt.getDeletedTagInfo() != null) ? evt.getDeletedTagInfo().getContentID() : null; - LOGGER.log(Level.WARNING, "Error updating non-file object: " + contentID, ex); + LOGGER.log(Level.WARNING, "Error updating non-file object: " + evt.getDeletedTagInfo().getContentID(), ex); } }