From ad5ef4965d32a51db0a9410bd3d70cdcfddbfe52 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Tue, 16 Feb 2016 15:22:27 -0500 Subject: [PATCH 01/77] Allowed custom logical file set names --- .../autopsy/casemodule/Bundle.properties | 2 + .../casemodule/LocalFilesDSProcessor.java | 4 +- .../autopsy/casemodule/LocalFilesPanel.form | 56 ++++++++++++++---- .../autopsy/casemodule/LocalFilesPanel.java | 58 +++++++++++++++---- 4 files changed, 95 insertions(+), 25 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 165f2d788a..f7437cbbf5 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -254,3 +254,5 @@ CloseCaseWhileIngesting.Warning.title=Warning\: This will close the current case CasePropertiesForm.imagesTable.columnModel.title1=Remove CasePropertiesForm.imagesTable.columnModel.title0=Path +LocalFilesPanel.jTextField1.text= +LocalFilesPanel.jLabel1.text=File Set Name diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java index 6d5c028cbb..9ff2e8ea5b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java @@ -46,6 +46,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { private String deviceId; private List localFilePaths; private boolean setDataSourceOptionsCalled; + private String fileSetName; /** * Constructs a local/logical files and/or directories data source processor @@ -120,8 +121,9 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { if (!setDataSourceOptionsCalled) { deviceId = UUID.randomUUID().toString(); localFilePaths = Arrays.asList(configPanel.getContentPaths().split(LocalFilesPanel.FILES_SEP)); + fileSetName = configPanel.getFileSetName(); } - run(deviceId, "", localFilePaths, progressMonitor, callback); + run(deviceId, fileSetName, localFilePaths, progressMonitor, callback); } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form index eb9d6182bb..facf7954f5 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form @@ -47,12 +47,14 @@ - - - - - + + + + + + + @@ -60,27 +62,40 @@ - - - + + + + + + + + + + + + + + + - - - + + - + + + @@ -151,5 +166,22 @@ + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java index eae470e0b4..55d0e028ed 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java @@ -156,12 +156,18 @@ class LocalFilesPanel extends JPanel { pcs.removePropertyChangeListener(pcl); } + + public String getFileSetName() { + return jTextField1.getText(); + } + @Override public String toString() { return NbBundle.getMessage(this.getClass(), "LocalFilesDSProcessor.toString.text"); } + /** * 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 @@ -180,6 +186,8 @@ class LocalFilesPanel extends JPanel { jScrollPane2 = new javax.swing.JScrollPane(); selectedPaths = new javax.swing.JTextArea(); errorLabel = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jLabel1 = new javax.swing.JLabel(); localFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonText")); // NOI18N localFileChooser.setApproveButtonToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonToolTipText")); // NOI18N @@ -218,37 +226,57 @@ class LocalFilesPanel extends JPanel { errorLabel.setForeground(new java.awt.Color(255, 0, 0)); org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.errorLabel.text")); // NOI18N + jTextField1.setText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.jTextField1.text")); // NOI18N + jTextField1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jTextField1ActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.jLabel1.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(infoLabel) - .addGap(0, 0, Short.MAX_VALUE)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 353, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(infoLabel) + .addGap(0, 0, Short.MAX_VALUE))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(selectButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(clearButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGap(2, 2, 2)) .addGroup(layout.createSequentialGroup() - .addComponent(errorLabel) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(errorLabel) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jTextField1))) + .addGap(65, 65, 65)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(infoLabel) - .addGap(5, 5, 5) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(selectButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(clearButton))) + .addGap(36, 36, 36) + .addComponent(clearButton)) + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(errorLabel)) + .addComponent(errorLabel) + .addContainerGap()) ); }// //GEN-END:initComponents @@ -291,13 +319,19 @@ class LocalFilesPanel extends JPanel { }//GEN-LAST:event_clearButtonActionPerformed + private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField1ActionPerformed + + }//GEN-LAST:event_jTextField1ActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton clearButton; private javax.swing.JLabel errorLabel; private javax.swing.JLabel infoLabel; + private javax.swing.JLabel jLabel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JTextArea jTextArea1; + private javax.swing.JTextField jTextField1; private javax.swing.JFileChooser localFileChooser; private javax.swing.JButton selectButton; private javax.swing.JTextArea selectedPaths; From 59d630284addf8bc12ade44b8f1d7a05d07c5af1 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Wed, 17 Feb 2016 09:58:31 -0500 Subject: [PATCH 02/77] Worked on fixing up UI --- .../autopsy/casemodule/Bundle.properties | 4 +- .../autopsy/casemodule/LocalFilesPanel.form | 54 +++++++++--------- .../autopsy/casemodule/LocalFilesPanel.java | 56 ++++++++++--------- 3 files changed, 58 insertions(+), 56 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index f7437cbbf5..0a6b19c9a9 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -254,5 +254,5 @@ CloseCaseWhileIngesting.Warning.title=Warning\: This will close the current case CasePropertiesForm.imagesTable.columnModel.title1=Remove CasePropertiesForm.imagesTable.columnModel.title0=Path -LocalFilesPanel.jTextField1.text= -LocalFilesPanel.jLabel1.text=File Set Name +LocalFilesPanel.jButton1.text=Change +LocalFilesPanel.fileSetNameLabel.text=File Set Name diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form index facf7954f5..2bb23cbae1 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form @@ -47,11 +47,18 @@ - + - + + + + + + + + @@ -63,29 +70,17 @@ - - - - - - - - - + + - - - - - - + @@ -94,6 +89,11 @@ + + + + + @@ -166,22 +166,22 @@ - + - + + + + + + + + - + - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java index 55d0e028ed..c47a740920 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java @@ -47,6 +47,7 @@ class LocalFilesPanel extends JPanel { private static LocalFilesPanel instance; public static final String FILES_SEP = ","; private static final Logger logger = Logger.getLogger(LocalFilesPanel.class.getName()); + private String displayName; /** * Creates new form LocalFilesPanel @@ -67,6 +68,7 @@ class LocalFilesPanel extends JPanel { localFileChooser.setMultiSelectionEnabled(true); errorLabel.setVisible(false); selectedPaths.setText(""); + this.fileSetNameLabel.setText("Display Name: Default"); } //@Override @@ -158,7 +160,7 @@ class LocalFilesPanel extends JPanel { } public String getFileSetName() { - return jTextField1.getText(); + return this.displayName; } @@ -186,8 +188,8 @@ class LocalFilesPanel extends JPanel { jScrollPane2 = new javax.swing.JScrollPane(); selectedPaths = new javax.swing.JTextArea(); errorLabel = new javax.swing.JLabel(); - jTextField1 = new javax.swing.JTextField(); - jLabel1 = new javax.swing.JLabel(); + fileSetNameLabel = new javax.swing.JLabel(); + jButton1 = new javax.swing.JButton(); localFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonText")); // NOI18N localFileChooser.setApproveButtonToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonToolTipText")); // NOI18N @@ -226,24 +228,29 @@ class LocalFilesPanel extends JPanel { errorLabel.setForeground(new java.awt.Color(255, 0, 0)); org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.errorLabel.text")); // NOI18N - jTextField1.setText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.jTextField1.text")); // NOI18N - jTextField1.addActionListener(new java.awt.event.ActionListener() { + org.openide.awt.Mnemonics.setLocalizedText(fileSetNameLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.fileSetNameLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - jTextField1ActionPerformed(evt); + jButton1ActionPerformed(evt); } }); - org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.jLabel1.text")); // NOI18N - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() - .addComponent(infoLabel) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(infoLabel) + .addGroup(layout.createSequentialGroup() + .addComponent(fileSetNameLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1))) .addGap(0, 0, Short.MAX_VALUE))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) @@ -251,30 +258,25 @@ class LocalFilesPanel extends JPanel { .addComponent(clearButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGap(2, 2, 2)) .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(errorLabel) - .addGroup(layout.createSequentialGroup() - .addComponent(jLabel1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jTextField1))) - .addGap(65, 65, 65)) + .addComponent(errorLabel) + .addContainerGap(361, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel1) - .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(infoLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createSequentialGroup() .addComponent(selectButton) .addGap(36, 36, 36) .addComponent(clearButton)) .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(fileSetNameLabel) + .addComponent(jButton1)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(errorLabel) .addContainerGap()) ); @@ -319,19 +321,19 @@ class LocalFilesPanel extends JPanel { }//GEN-LAST:event_clearButtonActionPerformed - private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField1ActionPerformed - - }//GEN-LAST:event_jTextField1ActionPerformed + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_jButton1ActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton clearButton; private javax.swing.JLabel errorLabel; + private javax.swing.JLabel fileSetNameLabel; private javax.swing.JLabel infoLabel; - private javax.swing.JLabel jLabel1; + private javax.swing.JButton jButton1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JTextArea jTextArea1; - private javax.swing.JTextField jTextField1; private javax.swing.JFileChooser localFileChooser; private javax.swing.JButton selectButton; private javax.swing.JTextArea selectedPaths; From fb1bffe53bfa619eb088c8772ff9375e46d811c1 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Wed, 17 Feb 2016 12:32:05 -0500 Subject: [PATCH 03/77] Updated UI --- .../autopsy/casemodule/Bundle.properties | 3 +- .../autopsy/casemodule/LocalFilesPanel.form | 48 +++++++-------- .../autopsy/casemodule/LocalFilesPanel.java | 61 ++++++++++--------- .../modules/filetypeid/Bundle.properties | 3 + 4 files changed, 60 insertions(+), 55 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 0a6b19c9a9..c05cb6ba50 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -254,5 +254,6 @@ CloseCaseWhileIngesting.Warning.title=Warning\: This will close the current case CasePropertiesForm.imagesTable.columnModel.title1=Remove CasePropertiesForm.imagesTable.columnModel.title0=Path +LocalFilesPanel.fileSetNameLabel.text=Display Name: Default LocalFilesPanel.jButton1.text=Change -LocalFilesPanel.fileSetNameLabel.text=File Set Name +LocalFilesPanel.displayNameField.text=Display Name: Default diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form index 2bb23cbae1..e3dfdd8111 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form @@ -48,31 +48,26 @@ + + + + - - - - - - - - - + + + + - - - - @@ -88,14 +83,14 @@ - - - - + + + + - + - + @@ -166,13 +161,6 @@ - - - - - - - @@ -183,5 +171,13 @@ + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java index c47a740920..134864cfd3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.casemodule; +import java.awt.Dialog; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.File; @@ -32,6 +33,10 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import java.util.logging.Level; +import javax.swing.JOptionPane; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; import org.sleuthkit.autopsy.casemodule.Case.CaseType; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PathValidator; @@ -47,7 +52,7 @@ class LocalFilesPanel extends JPanel { private static LocalFilesPanel instance; public static final String FILES_SEP = ","; private static final Logger logger = Logger.getLogger(LocalFilesPanel.class.getName()); - private String displayName; + private String displayName = ""; /** * Creates new form LocalFilesPanel @@ -68,7 +73,7 @@ class LocalFilesPanel extends JPanel { localFileChooser.setMultiSelectionEnabled(true); errorLabel.setVisible(false); selectedPaths.setText(""); - this.fileSetNameLabel.setText("Display Name: Default"); + this.displayNameField.setText("Display Name: Default"); } //@Override @@ -158,18 +163,16 @@ class LocalFilesPanel extends JPanel { pcs.removePropertyChangeListener(pcl); } - + public String getFileSetName() { return this.displayName; } - @Override public String toString() { return NbBundle.getMessage(this.getClass(), "LocalFilesDSProcessor.toString.text"); } - /** * 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 @@ -188,8 +191,8 @@ class LocalFilesPanel extends JPanel { jScrollPane2 = new javax.swing.JScrollPane(); selectedPaths = new javax.swing.JTextArea(); errorLabel = new javax.swing.JLabel(); - fileSetNameLabel = new javax.swing.JLabel(); jButton1 = new javax.swing.JButton(); + displayNameField = new javax.swing.JTextField(); localFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonText")); // NOI18N localFileChooser.setApproveButtonToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonToolTipText")); // NOI18N @@ -228,8 +231,6 @@ class LocalFilesPanel extends JPanel { errorLabel.setForeground(new java.awt.Color(255, 0, 0)); org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.errorLabel.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(fileSetNameLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.fileSetNameLabel.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.jButton1.text")); // NOI18N jButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -237,29 +238,29 @@ class LocalFilesPanel extends JPanel { } }); + displayNameField.setEditable(false); + displayNameField.setText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.displayNameField.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() + .addComponent(errorLabel) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(infoLabel) - .addGroup(layout.createSequentialGroup() - .addComponent(fileSetNameLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jButton1))) - .addGap(0, 0, Short.MAX_VALUE))) + .addComponent(infoLabel) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 378, Short.MAX_VALUE) + .addComponent(displayNameField)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(selectButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(clearButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(clearButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jButton1, javax.swing.GroupLayout.Alignment.TRAILING)) .addGap(2, 2, 2)) - .addGroup(layout.createSequentialGroup() - .addComponent(errorLabel) - .addContainerGap(361, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -272,13 +273,13 @@ class LocalFilesPanel extends JPanel { .addGap(36, 36, 36) .addComponent(clearButton)) .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(fileSetNameLabel) - .addComponent(jButton1)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 17, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jButton1, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(displayNameField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(errorLabel) - .addContainerGap()) + .addGap(7, 7, 7)) ); }// //GEN-END:initComponents @@ -322,13 +323,17 @@ class LocalFilesPanel extends JPanel { }//GEN-LAST:event_clearButtonActionPerformed private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed - // TODO add your handling code here: + String displayName = JOptionPane.showInputDialog("New Display Name: "); + if(displayName != null && !displayName.equals("")) { + this.displayName = displayName; + this.displayNameField.setText("Display Name: " + this.displayName); + } }//GEN-LAST:event_jButton1ActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton clearButton; + private javax.swing.JTextField displayNameField; private javax.swing.JLabel errorLabel; - private javax.swing.JLabel fileSetNameLabel; private javax.swing.JLabel infoLabel; private javax.swing.JButton jButton1; private javax.swing.JScrollPane jScrollPane1; diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties index bf6adc0de3..5009818bd0 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties @@ -50,3 +50,6 @@ FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy can automatically detect many FileTypeIdGlobalSettingsPanel.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector. FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector. FileTypeIdGlobalSettingsPanel.offsetRelativeToLabel.text=Offset is relative to +DisplayNameDialogFrame.jLabel1.text=jLabel1 +DisplayNamePanel.jLabel1.text=New Display Name: +DisplayNamePanel.jTextField1.text= From 6ba8cd8cb1b50e2d3aba0c9b6e73dd7111e69a53 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Wed, 17 Feb 2016 13:21:29 -0500 Subject: [PATCH 04/77] Final ui updates --- .../autopsy/casemodule/Bundle.properties | 3 +- .../autopsy/casemodule/LocalFilesPanel.form | 36 ++++++++++-------- .../autopsy/casemodule/LocalFilesPanel.java | 38 ++++++++++--------- 3 files changed, 42 insertions(+), 35 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index c05cb6ba50..64ced36212 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -254,6 +254,7 @@ CloseCaseWhileIngesting.Warning.title=Warning\: This will close the current case CasePropertiesForm.imagesTable.columnModel.title1=Remove CasePropertiesForm.imagesTable.columnModel.title0=Path +LocalFilesPanel.jButton1.text=Change LocalFilesPanel.fileSetNameLabel.text=Display Name: Default LocalFilesPanel.jButton1.text=Change -LocalFilesPanel.displayNameField.text=Display Name: Default +LocalFilesPanel.displayNameLabel.text=Display Name: Default diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form index e3dfdd8111..9470b481b7 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form @@ -47,27 +47,32 @@ - - - - - - + - - + + + + + + + + + + + + @@ -83,12 +88,12 @@ - - - - + + + + - + @@ -171,11 +176,10 @@ - + - - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java index 134864cfd3..164eadd0cb 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java @@ -73,7 +73,7 @@ class LocalFilesPanel extends JPanel { localFileChooser.setMultiSelectionEnabled(true); errorLabel.setVisible(false); selectedPaths.setText(""); - this.displayNameField.setText("Display Name: Default"); + this.displayNameLabel.setText("Display Name: Default"); } //@Override @@ -192,7 +192,7 @@ class LocalFilesPanel extends JPanel { selectedPaths = new javax.swing.JTextArea(); errorLabel = new javax.swing.JLabel(); jButton1 = new javax.swing.JButton(); - displayNameField = new javax.swing.JTextField(); + displayNameLabel = new javax.swing.JLabel(); localFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonText")); // NOI18N localFileChooser.setApproveButtonToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonToolTipText")); // NOI18N @@ -238,29 +238,31 @@ class LocalFilesPanel extends JPanel { } }); - displayNameField.setEditable(false); - displayNameField.setText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.displayNameField.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(displayNameLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.displayNameLabel.text")); // NOI18N javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(errorLabel) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(infoLabel) .addGap(0, 0, Short.MAX_VALUE)) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 378, Short.MAX_VALUE) - .addComponent(displayNameField)) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 389, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(selectButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(clearButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jButton1, javax.swing.GroupLayout.Alignment.TRAILING)) + .addComponent(clearButton, javax.swing.GroupLayout.DEFAULT_SIZE, 69, Short.MAX_VALUE)) .addGap(2, 2, 2)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(errorLabel) + .addGroup(layout.createSequentialGroup() + .addComponent(displayNameLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -273,11 +275,11 @@ class LocalFilesPanel extends JPanel { .addGap(36, 36, 36) .addComponent(clearButton)) .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 17, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jButton1, javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(displayNameField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(displayNameLabel)) + .addGap(13, 13, 13) .addComponent(errorLabel) .addGap(7, 7, 7)) ); @@ -326,13 +328,13 @@ class LocalFilesPanel extends JPanel { String displayName = JOptionPane.showInputDialog("New Display Name: "); if(displayName != null && !displayName.equals("")) { this.displayName = displayName; - this.displayNameField.setText("Display Name: " + this.displayName); + this.displayNameLabel.setText("Display Name: " + this.displayName); } }//GEN-LAST:event_jButton1ActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton clearButton; - private javax.swing.JTextField displayNameField; + private javax.swing.JLabel displayNameLabel; private javax.swing.JLabel errorLabel; private javax.swing.JLabel infoLabel; private javax.swing.JButton jButton1; From 0ecfb51d2db0baedfe18d0da451ca264ec23ba1b Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Thu, 25 Feb 2016 12:41:45 -0500 Subject: [PATCH 05/77] Fixed formatting --- Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java index 164eadd0cb..b4741d13f5 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java @@ -326,7 +326,7 @@ class LocalFilesPanel extends JPanel { private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed String displayName = JOptionPane.showInputDialog("New Display Name: "); - if(displayName != null && !displayName.equals("")) { + if (displayName != null && !displayName.equals("")) { this.displayName = displayName; this.displayNameLabel.setText("Display Name: " + this.displayName); } From b4f0000b9b974fd3e69ccbfbf2b7a50f1ff42398 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Wed, 2 Mar 2016 10:38:45 -0500 Subject: [PATCH 06/77] Updated for new Artifacts constructor --- .../autopsy/datamodel/ExtractedContent.java | 24 ++++--------- .../autopsy/ingest/ModuleDataEvent.java | 2 +- .../datamodel/eventtype/MiscTypes.java | 18 +++++----- .../datamodel/eventtype/TypeUtils.java | 35 ------------------- .../datamodel/eventtype/WebTypes.java | 10 +++--- 5 files changed, 21 insertions(+), 68 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/TypeUtils.java diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java index 146c4c72e5..8a9b31936f 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java @@ -210,29 +210,17 @@ public class ExtractedContent implements AutopsyVisitableItem { // these are shown in other parts of the UI tree doNotShow.add(new BlackboardArtifact.Type( - BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getTypeID(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getLabel(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getDisplayName())); + BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO)); doNotShow.add(new BlackboardArtifact.Type( - BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getLabel(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getDisplayName())); + BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG)); doNotShow.add(new BlackboardArtifact.Type( - BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getLabel(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName())); + BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT)); doNotShow.add(new BlackboardArtifact.Type( - BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getLabel(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName())); + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT)); doNotShow.add(new BlackboardArtifact.Type( - BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getLabel(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getDisplayName())); + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT)); doNotShow.add(new BlackboardArtifact.Type( - BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getLabel(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getDisplayName())); + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT)); } private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { diff --git a/Core/src/org/sleuthkit/autopsy/ingest/ModuleDataEvent.java b/Core/src/org/sleuthkit/autopsy/ingest/ModuleDataEvent.java index 7c58171d59..d78169e251 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/ModuleDataEvent.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/ModuleDataEvent.java @@ -58,7 +58,7 @@ public class ModuleDataEvent extends ChangeEvent { */ public ModuleDataEvent(String moduleName, ARTIFACT_TYPE artifactType) { super(artifactType); - this.blackboardArtifactType = new BlackboardArtifact.Type(artifactType.getTypeID(), artifactType.getLabel(), artifactType.getDisplayName()); + this.blackboardArtifactType = new BlackboardArtifact.Type(artifactType); this.moduleName = moduleName; } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/MiscTypes.java b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/MiscTypes.java index 3d73982bf5..ce7f009ceb 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/MiscTypes.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/MiscTypes.java @@ -42,7 +42,7 @@ import org.sleuthkit.datamodel.TskCoreException; public enum MiscTypes implements EventType, ArtifactEventType { MESSAGE(NbBundle.getMessage(MiscTypes.class, "MiscTypes.message.name"), "message.png", // NON-NLS - TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_MESSAGE), + new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_MESSAGE), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE)), artf -> { @@ -56,7 +56,7 @@ public enum MiscTypes implements EventType, ArtifactEventType { }, new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT))), GPS_ROUTE(NbBundle.getMessage(MiscTypes.class, "MiscTypes.GPSRoutes.name"), "gps-search.png", // NON-NLS - TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_GPS_ROUTE), + new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_GPS_ROUTE), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)), @@ -68,7 +68,7 @@ public enum MiscTypes implements EventType, ArtifactEventType { return String.format("from %1$s %2$s to %3$s %4$s", stringValueOf(latStart), stringValueOf(longStart), stringValueOf(latEnd), stringValueOf(longEnd)); // NON-NLS }), GPS_TRACKPOINT(NbBundle.getMessage(MiscTypes.class, "MiscTypes.GPSTrackpoint.name"), "gps-trackpoint.png", // NON-NLS - TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_GPS_TRACKPOINT), + new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_GPS_TRACKPOINT), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)), artf -> { @@ -78,13 +78,13 @@ public enum MiscTypes implements EventType, ArtifactEventType { }, EMPTY_EXTRACTOR), CALL_LOG(NbBundle.getMessage(MiscTypes.class, "MiscTypes.Calls.name"), "calllog.png", // NON-NLS - TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_CALLLOG), + new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_CALLLOG), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DIRECTION))), EMAIL(NbBundle.getMessage(MiscTypes.class, "MiscTypes.Email.name"), "mail-icon-16.png", // NON-NLS - TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_EMAIL_MSG), + new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_EMAIL_MSG), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_SENT), artf -> { final BlackboardAttribute emailFrom = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_FROM)); @@ -94,7 +94,7 @@ public enum MiscTypes implements EventType, ArtifactEventType { new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SUBJECT)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN))), RECENT_DOCUMENTS(NbBundle.getMessage(MiscTypes.class, "MiscTypes.recentDocuments.name"), "recent_docs.png", // NON-NLS - TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_RECENT_OBJECT), + new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_RECENT_OBJECT), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)).andThen( (String t) -> (StringUtils.substringBeforeLast(StringUtils.substringBeforeLast(t, "\\"), "\\"))), @@ -117,13 +117,13 @@ public enum MiscTypes implements EventType, ArtifactEventType { } }, INSTALLED_PROGRAM(NbBundle.getMessage(MiscTypes.class, "MiscTypes.installedPrograms.name"), "programs.png", // NON-NLS - TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_INSTALLED_PROG), + new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_INSTALLED_PROG), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)), EMPTY_EXTRACTOR, EMPTY_EXTRACTOR), EXIF(NbBundle.getMessage(MiscTypes.class, "MiscTypes.exif.name"), "camera-icon-16.png", // NON-NLS - TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_METADATA_EXIF), + new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_METADATA_EXIF), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL)), @@ -139,7 +139,7 @@ public enum MiscTypes implements EventType, ArtifactEventType { return "error loading file name"; }), DEVICES_ATTACHED(NbBundle.getMessage(MiscTypes.class, "MiscTypes.devicesAttached.name"), "usb_devices.png", // NON-NLS - TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED), + new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED), new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)), new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL)), diff --git a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/TypeUtils.java b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/TypeUtils.java deleted file mode 100644 index 889511f037..0000000000 --- a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/TypeUtils.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2016 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.timeline.datamodel.eventtype; - -import org.sleuthkit.datamodel.BlackboardArtifact; - -/** - * - */ -class TypeUtils { - -//TODO: this will be unncessary once their is BlackboardArtifact.Type constructr that takes a BlackboardArtifact.ARTIFACT_TYPE - static BlackboardArtifact.Type fromEnum(BlackboardArtifact.ARTIFACT_TYPE type) { - return new BlackboardArtifact.Type(type.getTypeID(), type.getLabel(), type.getDisplayName()); - } - - private TypeUtils() { - } -} diff --git a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/WebTypes.java b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/WebTypes.java index 2bb3b92ef4..33cbe4836c 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/WebTypes.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/eventtype/WebTypes.java @@ -37,7 +37,7 @@ public enum WebTypes implements EventType, ArtifactEventType { WEB_DOWNLOADS(NbBundle.getMessage(WebTypes.class, "WebTypes.webDownloads.name"), "downloads.png", // NON-NLS - TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD), + new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD), new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED), TopPrivateDomainExtractor.getInstance(), new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH)), @@ -61,7 +61,7 @@ public enum WebTypes implements EventType, ArtifactEventType { //TODO: review description separators WEB_COOKIE(NbBundle.getMessage(WebTypes.class, "WebTypes.webCookies.name"), "cookies.png", // NON-NLS - TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE), + new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE), new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME), TopPrivateDomainExtractor.getInstance(), new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME)), @@ -69,7 +69,7 @@ public enum WebTypes implements EventType, ArtifactEventType { //TODO: review description separators WEB_BOOKMARK(NbBundle.getMessage(WebTypes.class, "WebTypes.webBookmarks.name"), "bookmarks.png", // NON-NLS - TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK), + new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK), new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED), TopPrivateDomainExtractor.getInstance(), new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)), @@ -77,7 +77,7 @@ public enum WebTypes implements EventType, ArtifactEventType { //TODO: review description separators WEB_HISTORY(NbBundle.getMessage(WebTypes.class, "WebTypes.webHistory.name"), "history.png", // NON-NLS - TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY), + new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY), new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED), TopPrivateDomainExtractor.getInstance(), new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)), @@ -85,7 +85,7 @@ public enum WebTypes implements EventType, ArtifactEventType { //TODO: review description separators WEB_SEARCH(NbBundle.getMessage(WebTypes.class, "WebTypes.webSearch.name"), "searchquery.png", // NON-NLS - TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY), + new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY), new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED), new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT)), TopPrivateDomainExtractor.getInstance(), From f333c66d01b655fd972f3dcc7b653f3775f3f60b Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Thu, 3 Mar 2016 16:21:26 -0500 Subject: [PATCH 07/77] Serialization of user defined file types --- .../autopsy/modules/filetypeid/FileType.java | 96 ++++++++++--------- .../UserDefinedFileTypesManager.java | 35 +++++-- .../UserDefinedFileTypesSettings.java | 32 +++++++ 3 files changed, 113 insertions(+), 50 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesSettings.java diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java index 4f7f0bd043..432b4934e0 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.filetypeid; +import java.io.Serializable; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Objects; @@ -31,8 +32,9 @@ import org.sleuthkit.datamodel.TskCoreException; *

* Thread-safe (immutable). */ -class FileType { +class FileType implements Serializable { + private static final long serialVersionUID = 1L; private final String mimeType; private final Signature signature; private final String interestingFilesSetName; @@ -104,19 +106,20 @@ class FileType { String getFilesSetName() { return interestingFilesSetName; } - + @Override public String toString() { return this.mimeType; } - + @Override public boolean equals(Object other) { - if(other != null && other instanceof FileType) { + if (other != null && other instanceof FileType) { FileType that = (FileType) other; - if(this.getMimeType().equals(that.getMimeType()) && this.getSignature().equals(that.getSignature())) + if (this.getMimeType().equals(that.getMimeType()) && this.getSignature().equals(that.getSignature())) { return true; - } + } + } return false; } @@ -134,14 +137,16 @@ class FileType { *

* Thread-safe (immutable). */ - static class Signature { - + static class Signature implements Serializable { + + private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(Signature.class.getName()); /** * The way the signature byte sequence should be interpreted. */ enum Type { + RAW, ASCII }; @@ -156,8 +161,8 @@ class FileType { * * @param signatureBytes The signature bytes. * @param offset The offset of the signature bytes. - * @param type The type of data in the byte array. Impacts - * how it is displayed to the user in the UI. + * @param type The type of data in the byte array. Impacts how + * it is displayed to the user in the UI. */ Signature(final byte[] signatureBytes, long offset, Type type) { this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); @@ -165,13 +170,13 @@ class FileType { this.type = type; this.isRelativeToStart = true; } - + /** - * Creates a file signature consisting of an ASCII string at a - * specific offset within a file. + * Creates a file signature consisting of an ASCII string at a specific + * offset within a file. * * @param signatureString The ASCII string - * @param offset The offset of the signature bytes. + * @param offset The offset of the signature bytes. */ Signature(String signatureString, long offset) { this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII); @@ -179,12 +184,12 @@ class FileType { this.type = Type.ASCII; this.isRelativeToStart = true; } - + /** * Creates a file signature consisting of a sequence of bytes at a - * specific offset within a file. If bytes correspond to an ASCII - * string, use one of the other constructors so that the string is - * displayed to the user instead of the raw bytes. + * specific offset within a file. If bytes correspond to an ASCII + * string, use one of the other constructors so that the string is + * displayed to the user instead of the raw bytes. * * @param signatureBytes The signature bytes. * @param offset The offset of the signature bytes. @@ -195,16 +200,17 @@ class FileType { this.type = Type.RAW; this.isRelativeToStart = true; } - + /** * Creates a file signature consisting of a sequence of bytes at a * specific offset within a file. * - * @param signatureBytes The signature bytes. - * @param offset The offset of the signature bytes. - * @param type The type of data in the byte array. Impacts - * how it is displayed to the user in the UI. - * @param isRelativeToStart Determines whether this signature is relative to start. + * @param signatureBytes The signature bytes. + * @param offset The offset of the signature bytes. + * @param type The type of data in the byte array. Impacts + * how it is displayed to the user in the UI. + * @param isRelativeToStart Determines whether this signature is + * relative to start. */ Signature(final byte[] signatureBytes, long offset, Type type, boolean isRelativeToStart) { this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); @@ -212,14 +218,15 @@ class FileType { this.type = type; this.isRelativeToStart = isRelativeToStart; } - + /** - * Creates a file signature consisting of an ASCII string at a - * specific offset within a file. + * Creates a file signature consisting of an ASCII string at a specific + * offset within a file. * - * @param signatureString The ASCII string - * @param offset The offset of the signature bytes. - * @param isRelativeToStart Determines whether this signature is relative to start. + * @param signatureString The ASCII string + * @param offset The offset of the signature bytes. + * @param isRelativeToStart Determines whether this signature is + * relative to start. */ Signature(String signatureString, long offset, boolean isRelativeToStart) { this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII); @@ -227,16 +234,17 @@ class FileType { this.type = Type.ASCII; this.isRelativeToStart = isRelativeToStart; } - + /** * Creates a file signature consisting of a sequence of bytes at a - * specific offset within a file. If bytes correspond to an ASCII - * string, use one of the other constructors so that the string is - * displayed to the user instead of the raw bytes. + * specific offset within a file. If bytes correspond to an ASCII + * string, use one of the other constructors so that the string is + * displayed to the user instead of the raw bytes. * - * @param signatureBytes The signature bytes. - * @param offset The offset of the signature bytes. - * @param isRelativeToStart Determines whether this signature is relative to start. + * @param signatureBytes The signature bytes. + * @param offset The offset of the signature bytes. + * @param isRelativeToStart Determines whether this signature is + * relative to start. */ Signature(final byte[] signatureBytes, long offset, boolean isRelativeToStart) { this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length); @@ -271,7 +279,7 @@ class FileType { Type getType() { return type; } - + boolean isRelativeToStart() { return isRelativeToStart; } @@ -285,12 +293,13 @@ class FileType { * @return True or false. */ boolean containedIn(final AbstractFile file) { - if(offset >= file.getSize()) { + if (offset >= file.getSize()) { return false; // File is too small, offset lies outside file. } long actualOffset = offset; - if(!isRelativeToStart) + if (!isRelativeToStart) { actualOffset = file.getSize() - 1 - offset; + } if (file.getSize() < (actualOffset + signatureBytes.length)) { return false; /// too small, can't contain this signature } @@ -308,15 +317,16 @@ class FileType { return false; } } - + @Override public boolean equals(Object other) { if (other != null && other instanceof Signature) { Signature that = (Signature) other; - if(Arrays.equals(this.getSignatureBytes(), that.getSignatureBytes()) + if (Arrays.equals(this.getSignatureBytes(), that.getSignatureBytes()) && this.getOffset() == that.getOffset() - && this.getType().equals(that.getType())) + && this.getType().equals(that.getType())) { return true; + } } return false; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java index 8f2dbaabca..a6d0a1e992 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java @@ -19,7 +19,9 @@ package org.sleuthkit.autopsy.modules.filetypeid; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.file.Path; @@ -27,6 +29,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; +import javax.persistence.PersistenceException; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -34,10 +37,13 @@ import org.w3c.dom.NodeList; import javax.xml.bind.DatatypeConverter; import javax.xml.transform.TransformerException; import org.openide.util.NbBundle; +import org.openide.util.io.NbObjectInputStream; +import org.openide.util.io.NbObjectOutputStream; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.XMLUtil; import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature; +import org.sleuthkit.datamodel.TskCoreException; import org.w3c.dom.Node; import org.xml.sax.SAXException; @@ -60,6 +66,7 @@ final class UserDefinedFileTypesManager { private static final Logger logger = Logger.getLogger(UserDefinedFileTypesManager.class.getName()); private static final String USER_DEFINED_TYPE_DEFINITIONS_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS + private static final String USER_DEFINED_TYPE_SERIALIZATION_FILE = "UserFileTypeDefinitions.settings"; private static final String FILE_TYPES_TAG_NAME = "FileTypes"; //NON-NLS private static final String FILE_TYPE_TAG_NAME = "FileType"; //NON-NLS private static final String MIME_TYPE_TAG_NAME = "MimeType"; //NON-NLS @@ -323,14 +330,16 @@ final class UserDefinedFileTypesManager { * @throws TransformerException */ private static void writeFileTypes(List fileTypes, String filePath) throws ParserConfigurationException, IOException, FileNotFoundException, UnsupportedEncodingException, TransformerException { - Document doc = XMLUtil.createDocument(); - Element fileTypesElem = doc.createElement(FILE_TYPES_TAG_NAME); - doc.appendChild(fileTypesElem); - for (FileType fileType : fileTypes) { - Element fileTypeElem = XmlWriter.createFileTypeElement(fileType, doc); - fileTypesElem.appendChild(fileTypeElem); + try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)))) { + UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes); + out.writeObject(settings); + File xmlFile = new File(filePath); + if (xmlFile.exists()) { + xmlFile.delete(); + } + } catch (IOException ex) { + throw new PersistenceException(String.format("Failed to write settings to %s", getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)), ex); } - XMLUtil.saveDocument(doc, ENCODING_FOR_XML_FILE, filePath); } /** @@ -457,6 +466,18 @@ final class UserDefinedFileTypesManager { fileTypes.add(fileType); } } + } else { + File serializedDefs = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)); + if (serializedDefs.exists()) { + try { + try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) { + UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject(); + return filesSetsSettings.getUserDefinedFileTypes(); + } + } catch (IOException | ClassNotFoundException ex) { + throw new PersistenceException(String.format("Failed to read settings from %s", getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)), ex); + } + } } return fileTypes; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesSettings.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesSettings.java new file mode 100755 index 0000000000..e2a3e8e348 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesSettings.java @@ -0,0 +1,32 @@ +/* + * 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.modules.filetypeid; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author oliver + */ +class UserDefinedFileTypesSettings implements Serializable { + private static final long serialVersionUID = 1L; + private List userDefinedFileTypes; + + UserDefinedFileTypesSettings(List userDefinedFileTypes) { + this.userDefinedFileTypes = userDefinedFileTypes; + } + + /** + * @return the userDefinedFileTypes + */ + public List getUserDefinedFileTypes() { + return userDefinedFileTypes; + } + + +} From c0f15976cac04c4cc5b646e289d1729e29642e66 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Fri, 4 Mar 2016 09:12:03 -0500 Subject: [PATCH 08/77] Finished serialization of file types --- .../UserDefinedFileTypesManager.java | 132 ++++-------------- 1 file changed, 31 insertions(+), 101 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java index a6d0a1e992..6f1a4c322c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java @@ -255,8 +255,13 @@ final class UserDefinedFileTypesManager { try { String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE); File file = new File(filePath); + File serialized = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)); if (file.exists() && file.canRead()) { - for (FileType fileType : XmlReader.readFileTypes(filePath)) { + for (FileType fileType : DefinitionsReader.readFileTypes(filePath)) { + addUserDefinedFileType(fileType); + } + } else if (serialized.exists()) { + for (FileType fileType : DefinitionsReader.readFileTypesSerialized(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE))) { addUserDefinedFileType(fileType); } } @@ -291,7 +296,7 @@ final class UserDefinedFileTypesManager { synchronized void setUserDefinedFileTypes(List newFileTypes) throws UserDefinedFileTypesException { try { String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE); - XmlWriter.writeFileTypes(newFileTypes, filePath); + DefinitionsWriter.writeFileTypes(newFileTypes, filePath); } catch (ParserConfigurationException | FileNotFoundException | UnsupportedEncodingException | TransformerException ex) { throwUserDefinedFileTypesException(ex, "UserDefinedFileTypesManager.saveFileTypes.errorMessage"); } catch (IOException ex) { @@ -315,7 +320,7 @@ final class UserDefinedFileTypesManager { * Provides a mechanism for writing a set of file type definitions to an XML * file. */ - private static class XmlWriter { + private static class DefinitionsWriter { /** * Writes a set of file type definitions to an XML file. @@ -343,89 +348,10 @@ final class UserDefinedFileTypesManager { } /** - * Creates an XML representation of a file type. - * - * @param fileType The file type object. - * @param doc The WC3 DOM object to use to create the XML. - * - * @return An XML element. - */ - private static Element createFileTypeElement(FileType fileType, Document doc) { - Element fileTypeElem = doc.createElement(FILE_TYPE_TAG_NAME); - XmlWriter.addMimeTypeElement(fileType, fileTypeElem, doc); - XmlWriter.addSignatureElement(fileType, fileTypeElem, doc); - XmlWriter.addInterestingFilesSetElement(fileType, fileTypeElem, doc); - XmlWriter.addAlertAttribute(fileType, fileTypeElem); - return fileTypeElem; - } - - /** - * Add a MIME type child element to a file type XML element. - * - * @param fileType The file type to use as a content source. - * @param fileTypeElem The parent file type element. - * @param doc The WC3 DOM object to use to create the XML. - */ - private static void addMimeTypeElement(FileType fileType, Element fileTypeElem, Document doc) { - Element typeNameElem = doc.createElement(MIME_TYPE_TAG_NAME); - typeNameElem.setTextContent(fileType.getMimeType()); - fileTypeElem.appendChild(typeNameElem); - } - - /** - * Add a signature child element to a file type XML element. - * - * @param fileType The file type to use as a content source. - * @param fileTypeElem The parent file type element. - * @param doc The WC3 DOM object to use to create the XML. - */ - private static void addSignatureElement(FileType fileType, Element fileTypeElem, Document doc) { - Signature signature = fileType.getSignature(); - Element signatureElem = doc.createElement(SIGNATURE_TAG_NAME); - - Element bytesElem = doc.createElement(BYTES_TAG_NAME); - bytesElem.setTextContent(DatatypeConverter.printHexBinary(signature.getSignatureBytes())); - signatureElem.appendChild(bytesElem); - - Element offsetElem = doc.createElement(OFFSET_TAG_NAME); - offsetElem.setTextContent(DatatypeConverter.printLong(signature.getOffset())); - offsetElem.setAttribute(RELATIVE_ATTRIBUTE, String.valueOf(signature.isRelativeToStart())); - signatureElem.appendChild(offsetElem); - - signatureElem.setAttribute(SIGNATURE_TYPE_ATTRIBUTE, signature.getType().toString()); - fileTypeElem.appendChild(signatureElem); - } - - /** - * Add an interesting files set element to a file type XML element. - * - * @param fileType The file type to use as a content source. - * @param fileTypeElem The parent file type element. - * @param doc The WC3 DOM object to use to create the XML. - */ - private static void addInterestingFilesSetElement(FileType fileType, Element fileTypeElem, Document doc) { - if (!fileType.getFilesSetName().isEmpty()) { - Element filesSetElem = doc.createElement(INTERESTING_FILES_SET_TAG_NAME); - filesSetElem.setTextContent(fileType.getFilesSetName()); - fileTypeElem.appendChild(filesSetElem); - } - } - - /** - * Add an alert attribute to a file type XML element. - * - * @param fileType The file type to use as a content source. - * @param fileTypeElem The parent file type element. - */ - private static void addAlertAttribute(FileType fileType, Element fileTypeElem) { - fileTypeElem.setAttribute(ALERT_ATTRIBUTE, Boolean.toString(fileType.alertOnMatch())); - } - - /** - * Private constructor suppresses creation of instanmces of this utility + * Private constructor suppresses creation of instances of this utility * class. */ - private XmlWriter() { + private DefinitionsWriter() { } } @@ -434,7 +360,7 @@ final class UserDefinedFileTypesManager { * Provides a mechanism for reading a set of file type definitions from an * XML file. */ - private static class XmlReader { + private static class DefinitionsReader { /** * Reads a set of file type definitions from an XML file. @@ -462,21 +388,25 @@ final class UserDefinedFileTypesManager { NodeList fileTypeElems = fileTypesElem.getElementsByTagName(FILE_TYPE_TAG_NAME); for (int i = 0; i < fileTypeElems.getLength(); ++i) { Element fileTypeElem = (Element) fileTypeElems.item(i); - FileType fileType = XmlReader.parseFileType(fileTypeElem); + FileType fileType = DefinitionsReader.parseFileType(fileTypeElem); fileTypes.add(fileType); } } - } else { - File serializedDefs = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)); - if (serializedDefs.exists()) { - try { - try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) { - UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject(); - return filesSetsSettings.getUserDefinedFileTypes(); - } - } catch (IOException | ClassNotFoundException ex) { - throw new PersistenceException(String.format("Failed to read settings from %s", getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)), ex); + } + return fileTypes; + } + + private static List readFileTypesSerialized(String filePath) throws IOException, ParserConfigurationException, SAXException { + List fileTypes = new ArrayList<>(); + File serializedDefs = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)); + if (serializedDefs.exists()) { + try { + try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) { + UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject(); + return filesSetsSettings.getUserDefinedFileTypes(); } + } catch (IOException | ClassNotFoundException ex) { + throw new PersistenceException(String.format("Failed to read settings from %s", getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)), ex); } } return fileTypes; @@ -493,10 +423,10 @@ final class UserDefinedFileTypesManager { * @throws NumberFormatException */ private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException { - String mimeType = XmlReader.parseMimeType(fileTypeElem); - Signature signature = XmlReader.parseSignature(fileTypeElem); - String filesSetName = XmlReader.parseInterestingFilesSet(fileTypeElem); - boolean alert = XmlReader.parseAlert(fileTypeElem); + String mimeType = DefinitionsReader.parseMimeType(fileTypeElem); + Signature signature = DefinitionsReader.parseSignature(fileTypeElem); + String filesSetName = DefinitionsReader.parseInterestingFilesSet(fileTypeElem); + boolean alert = DefinitionsReader.parseAlert(fileTypeElem); return new FileType(mimeType, signature, filesSetName, alert); } @@ -594,7 +524,7 @@ final class UserDefinedFileTypesManager { * Private constructor suppresses creation of instanmces of this utility * class. */ - private XmlReader() { + private DefinitionsReader() { } } From c6a7ac050c3c9860985fb54a26c63ad9fb503fcd Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Fri, 4 Mar 2016 09:14:56 -0500 Subject: [PATCH 09/77] Updated documentation, exceptions thrown. --- .../filetypeid/UserDefinedFileTypesManager.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java index 6f1a4c322c..15beafa567 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java @@ -369,7 +369,7 @@ final class UserDefinedFileTypesManager { * * @return A collection of file types read from the XML file. */ - private static List readFileTypes(String filePath) throws IOException, ParserConfigurationException, SAXException { + private static List readFileTypes(String filePath) throws IOException, SAXException { List fileTypes = new ArrayList<>(); /* * RC: Commenting out the loadDocument overload that validates @@ -395,8 +395,15 @@ final class UserDefinedFileTypesManager { } return fileTypes; } - - private static List readFileTypesSerialized(String filePath) throws IOException, ParserConfigurationException, SAXException { + + /** + * Reads the file types + * + * @param filePath the file path where the file types are to be read + * @return the file types + * @throws ParserConfigurationException If the file cannot be read + */ + private static List readFileTypesSerialized(String filePath) throws ParserConfigurationException { List fileTypes = new ArrayList<>(); File serializedDefs = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)); if (serializedDefs.exists()) { From 458cde365e558c9c06ca88de45645748aa2fc72d Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Tue, 8 Mar 2016 10:47:02 -0500 Subject: [PATCH 10/77] Started progress --- .../autopsy/filesearch/MimeTypePanel.form | 60 ++++++++++++++++ .../autopsy/filesearch/MimeTypePanel.java | 68 +++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100755 Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form create mode 100755 Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form new file mode 100755 index 0000000000..eb170ef6ab --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form @@ -0,0 +1,60 @@ + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java new file mode 100755 index 0000000000..ff9146151f --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java @@ -0,0 +1,68 @@ +/* + * 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.filesearch; + +/** + * + * @author oliver + */ +public class MimeTypePanel extends javax.swing.JPanel { + + /** + * Creates new form MimeTypePanel + */ + public MimeTypePanel() { + initComponents(); + customInit(); + } + + void customInit() { + + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + jList1 = new javax.swing.JList(); + + jList1.setModel(new javax.swing.AbstractListModel() { + String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }; + public int getSize() { return strings.length; } + public Object getElementAt(int i) { return strings[i]; } + }); + jScrollPane1.setViewportView(jList1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JList jList1; + private javax.swing.JScrollPane jScrollPane1; + // End of variables declaration//GEN-END:variables +} From 8ea0b075eaf1fdad06f76cc139bffcc05b049e80 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Tue, 8 Mar 2016 11:01:37 -0500 Subject: [PATCH 11/77] Started process of populating JList with mime types --- .../autopsy/filesearch/MimeTypePanel.form | 13 +++--- .../autopsy/filesearch/MimeTypePanel.java | 44 ++++++++++++++++--- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form index eb170ef6ab..75185d623b 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form @@ -43,16 +43,13 @@ - - - - - - - - + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java index ff9146151f..455154b162 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java @@ -5,6 +5,15 @@ */ package org.sleuthkit.autopsy.filesearch; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import javax.swing.JList; +import org.apache.tika.mime.MediaType; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; + /** * * @author oliver @@ -16,11 +25,34 @@ public class MimeTypePanel extends javax.swing.JPanel { */ public MimeTypePanel() { initComponents(); - customInit(); } - void customInit() { - + String[] getMimeTypeArray() { + Set fileTypesCollated = new HashSet<>(); + for (MediaType mediaType : mediaTypes) { + fileTypesCollated.add(mediaType.toString()); + } + + FileTypeDetector fileTypeDetector; + try { + fileTypeDetector = new FileTypeDetector(); + List userDefinedFileTypes = fileTypeDetector.getUserDefinedTypes(); + fileTypesCollated.addAll(userDefinedFileTypes); + + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + logger.log(Level.SEVERE, "Unable to get user defined file types", ex); + } + + List toSort = new ArrayList<>(fileTypesCollated); + toSort.sort((String string1, String string2) -> { + int result = String.CASE_INSENSITIVE_ORDER.compare(string1, string2); + if (result == 0) { + result = string1.compareTo(string2); + } + return result; + }); + String [] mimeTypeArray = new String[toSort.size()]; + return toSort.toArray(mimeTypeArray); } /** @@ -33,10 +65,10 @@ public class MimeTypePanel extends javax.swing.JPanel { private void initComponents() { jScrollPane1 = new javax.swing.JScrollPane(); - jList1 = new javax.swing.JList(); + jList1 = new javax.swing.JList(); jList1.setModel(new javax.swing.AbstractListModel() { - String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }; + String[] strings = getMimeTypeArray(); public int getSize() { return strings.length; } public Object getElementAt(int i) { return strings[i]; } }); @@ -62,7 +94,7 @@ public class MimeTypePanel extends javax.swing.JPanel { // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JList jList1; + private javax.swing.JList jList1; private javax.swing.JScrollPane jScrollPane1; // End of variables declaration//GEN-END:variables } From 61bd11606119cce3f57c19679f174a1b29db1366 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Tue, 8 Mar 2016 13:06:31 -0500 Subject: [PATCH 12/77] UI updates, working towards making it work --- .../autopsy/filesearch/Bundle.properties | 1 + .../autopsy/filesearch/FileSearchDialog.java | 2 +- .../autopsy/filesearch/FileSearchPanel.form | 5 +++ .../autopsy/filesearch/FileSearchPanel.java | 3 ++ .../autopsy/filesearch/MimeTypeFilter.java | 44 +++++++++++++++++++ .../autopsy/filesearch/MimeTypePanel.form | 33 ++++++++++---- .../autopsy/filesearch/MimeTypePanel.java | 42 +++++++++++++----- 7 files changed, 111 insertions(+), 19 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties index 99c61a24ca..1b9c03b9c0 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties @@ -54,3 +54,4 @@ SearchNode.getName.text=Search Result SizeSearchPanel.sizeCompareComboBox.equalTo=equal to SizeSearchPanel.sizeCompareComboBox.greaterThan=greater than SizeSearchPanel.sizeCompareComboBox.lessThan=less than +MimeTypePanel.jLabel1.text=Mime Type diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchDialog.java b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchDialog.java index 66cca80df1..e8d76990b1 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchDialog.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchDialog.java @@ -46,7 +46,7 @@ class FileSearchDialog extends javax.swing.JDialog { NbBundle.getMessage(FileSearchDialog.class, "FileSearchDialog.frame.msg"), true); initComponents(); - setResizable(false); + setResizable(true); Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); double w = getSize().getWidth(); double h = getSize().getHeight(); diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.form index 7c2a63a271..3cb4dc8f4e 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.form +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.form @@ -1,6 +1,11 @@
+ + + + + diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java index a8ee427c24..903e62e6bc 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java @@ -101,6 +101,7 @@ class FileSearchPanel extends javax.swing.JPanel { this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.metadata"), metadataFilters)); this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.knownStatus"), new KnownStatusSearchFilter())); + this.filterAreas.add(new FilterArea("Test mime", new MimeTypeFilter())); for (FilterArea fa : this.filterAreas) { fa.setMaximumSize(new Dimension(Integer.MAX_VALUE, fa.getMinimumSize().height)); @@ -273,6 +274,8 @@ class FileSearchPanel extends javax.swing.JPanel { // //GEN-BEGIN:initComponents private void initComponents() { + setPreferredSize(new java.awt.Dimension(300, 450)); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java new file mode 100755 index 0000000000..061b3baed9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java @@ -0,0 +1,44 @@ +/* + * 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.filesearch; + +import java.awt.event.ActionListener; + +/** + * + * @author oliver + */ +class MimeTypeFilter extends AbstractFileSearchFilter { + + public MimeTypeFilter(MimeTypePanel component) { + super(component); + } + public MimeTypeFilter() { + this(new MimeTypePanel()); + } + + @Override + public boolean isEnabled() { + return !this.getComponent().getMimeTypesSelected().isEmpty(); + } + + @Override + public String getPredicate() throws FilterValidationException { + String predicate = ""; + for(String mimeType : this.getComponent().getMimeTypesSelected()) { + predicate += "mime_type = '" + mimeType + "' OR "; + } + if(predicate.length() > 3) { + predicate = predicate.substring(0, predicate.length() - 3); + } + return predicate; + } + + @Override + public void addActionListener(ActionListener l) { + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form index 75185d623b..bb33d80711 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form @@ -16,19 +16,26 @@ - - - - + + + + + + + + + + - - - - + + + + + @@ -46,6 +53,9 @@ + + + @@ -53,5 +63,12 @@ + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java index 455154b162..3f0f5c5e04 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java @@ -5,14 +5,17 @@ */ package org.sleuthkit.autopsy.filesearch; +import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.SortedSet; import java.util.logging.Level; -import javax.swing.JList; -import org.apache.tika.mime.MediaType; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; +import org.apache.tika.mime.MediaType; +import org.apache.tika.mime.MimeTypes; +import org.sleuthkit.autopsy.coreutils.Logger; /** * @@ -20,14 +23,18 @@ import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; */ public class MimeTypePanel extends javax.swing.JPanel { + private static final SortedSet mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes(); + private static final Logger logger = Logger.getLogger(MimeTypePanel.class.getName()); + private static final long serialVersionUID = 1L; + /** * Creates new form MimeTypePanel */ public MimeTypePanel() { initComponents(); } - - String[] getMimeTypeArray() { + + private String[] getMimeTypeArray() { Set fileTypesCollated = new HashSet<>(); for (MediaType mediaType : mediaTypes) { fileTypesCollated.add(mediaType.toString()); @@ -51,9 +58,14 @@ public class MimeTypePanel extends javax.swing.JPanel { } return result; }); - String [] mimeTypeArray = new String[toSort.size()]; + String[] mimeTypeArray = new String[toSort.size()]; return toSort.toArray(mimeTypeArray); } + + List getMimeTypesSelected() { + return this.jList1.getSelectedValuesList(); + } + /** * This method is called from within the constructor to initialize the form. @@ -66,34 +78,44 @@ public class MimeTypePanel extends javax.swing.JPanel { jScrollPane1 = new javax.swing.JScrollPane(); jList1 = new javax.swing.JList(); + jLabel1 = new javax.swing.JLabel(); jList1.setModel(new javax.swing.AbstractListModel() { String[] strings = getMimeTypeArray(); public int getSize() { return strings.length; } public Object getElementAt(int i) { return strings[i]; } }); + jList1.setMinimumSize(new java.awt.Dimension(0, 200)); jScrollPane1.setViewportView(jList1); + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(MimeTypePanel.class, "MimeTypePanel.jLabel1.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 90, Short.MAX_VALUE) + .addContainerGap()) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; private javax.swing.JList jList1; private javax.swing.JScrollPane jScrollPane1; // End of variables declaration//GEN-END:variables From 8fe18f00af063e87528ebeb62911a0030d839d9c Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Tue, 8 Mar 2016 15:41:09 -0500 Subject: [PATCH 13/77] UI updates --- .../sleuthkit/autopsy/filesearch/MimeTypePanel.form | 10 +++++++++- .../sleuthkit/autopsy/filesearch/MimeTypePanel.java | 5 ++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form index bb33d80711..5709ecb8b7 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form @@ -1,6 +1,14 @@
+ + + + + + + + @@ -34,7 +42,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java index 3f0f5c5e04..b1eacda29a 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java @@ -80,6 +80,9 @@ public class MimeTypePanel extends javax.swing.JPanel { jList1 = new javax.swing.JList(); jLabel1 = new javax.swing.JLabel(); + setMinimumSize(new java.awt.Dimension(100, 100)); + setPreferredSize(new java.awt.Dimension(100, 100)); + jList1.setModel(new javax.swing.AbstractListModel() { String[] strings = getMimeTypeArray(); public int getSize() { return strings.length; } @@ -108,7 +111,7 @@ public class MimeTypePanel extends javax.swing.JPanel { .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 90, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 121, Short.MAX_VALUE) .addContainerGap()) ); }// //GEN-END:initComponents From dad7a70417738651751c4810eef083cf1afa2c20 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Wed, 9 Mar 2016 10:42:17 -0500 Subject: [PATCH 14/77] UI updates --- .../autopsy/filesearch/Bundle.properties | 1 + .../autopsy/filesearch/FileSearchDialog.java | 2 +- .../autopsy/filesearch/MimeTypeFilter.java | 3 +- .../autopsy/filesearch/MimeTypePanel.form | 24 ++++++++-------- .../autopsy/filesearch/MimeTypePanel.java | 28 ++++++++++--------- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties index 1b9c03b9c0..de4e16ae5c 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties @@ -54,4 +54,5 @@ SearchNode.getName.text=Search Result SizeSearchPanel.sizeCompareComboBox.equalTo=equal to SizeSearchPanel.sizeCompareComboBox.greaterThan=greater than SizeSearchPanel.sizeCompareComboBox.lessThan=less than +MimeTypePanel.jCheckBox1.text=MIME Type MimeTypePanel.jLabel1.text=Mime Type diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchDialog.java b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchDialog.java index e8d76990b1..66cca80df1 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchDialog.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchDialog.java @@ -46,7 +46,7 @@ class FileSearchDialog extends javax.swing.JDialog { NbBundle.getMessage(FileSearchDialog.class, "FileSearchDialog.frame.msg"), true); initComponents(); - setResizable(true); + setResizable(false); Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); double w = getSize().getWidth(); double h = getSize().getHeight(); diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java index 061b3baed9..a6978109a5 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java @@ -22,7 +22,8 @@ class MimeTypeFilter extends AbstractFileSearchFilter { @Override public boolean isEnabled() { - return !this.getComponent().getMimeTypesSelected().isEmpty(); + return this.getComponent().isSelected() && + !this.getComponent().getMimeTypesSelected().isEmpty(); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form index 5709ecb8b7..89d0d39d8b 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form @@ -3,7 +3,7 @@ - + @@ -26,23 +26,21 @@ - - - - - - - + + + + + - - - + + + @@ -71,10 +69,10 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java index b1eacda29a..58ba69f75e 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java @@ -61,11 +61,14 @@ public class MimeTypePanel extends javax.swing.JPanel { String[] mimeTypeArray = new String[toSort.size()]; return toSort.toArray(mimeTypeArray); } - + List getMimeTypesSelected() { return this.jList1.getSelectedValuesList(); } - + + boolean isSelected() { + return this.jCheckBox1.isSelected(); + } /** * This method is called from within the constructor to initialize the form. @@ -78,9 +81,9 @@ public class MimeTypePanel extends javax.swing.JPanel { jScrollPane1 = new javax.swing.JScrollPane(); jList1 = new javax.swing.JList(); - jLabel1 = new javax.swing.JLabel(); + jCheckBox1 = new javax.swing.JCheckBox(); - setMinimumSize(new java.awt.Dimension(100, 100)); + setMinimumSize(new java.awt.Dimension(150, 150)); setPreferredSize(new java.awt.Dimension(100, 100)); jList1.setModel(new javax.swing.AbstractListModel() { @@ -91,7 +94,7 @@ public class MimeTypePanel extends javax.swing.JPanel { jList1.setMinimumSize(new java.awt.Dimension(0, 200)); jScrollPane1.setViewportView(jList1); - org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(MimeTypePanel.class, "MimeTypePanel.jLabel1.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, org.openide.util.NbBundle.getMessage(MimeTypePanel.class, "MimeTypePanel.jCheckBox1.text")); // NOI18N javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); @@ -99,26 +102,25 @@ public class MimeTypePanel extends javax.swing.JPanel { layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(jLabel1) - .addGap(0, 0, Short.MAX_VALUE)) - .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 180, Short.MAX_VALUE) .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addComponent(jCheckBox1) + .addGap(0, 0, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(jLabel1) + .addComponent(jCheckBox1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 121, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 164, Short.MAX_VALUE) .addContainerGap()) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel jLabel1; + private javax.swing.JCheckBox jCheckBox1; private javax.swing.JList jList1; private javax.swing.JScrollPane jScrollPane1; // End of variables declaration//GEN-END:variables From 71326792fe6aa3a81ac2629855f3be6ea4f59956 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Wed, 9 Mar 2016 12:29:19 -0500 Subject: [PATCH 15/77] Disabled cancel button in reports panel on completion --- .../autopsy/report/ReportGenerationPanel.java | 13 ++++++++++ .../autopsy/report/ReportProgressPanel.java | 26 +++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerationPanel.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerationPanel.java index debc77e343..568b25b30e 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerationPanel.java @@ -20,8 +20,11 @@ package org.sleuthkit.autopsy.report; import java.awt.*; import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import javax.swing.Box; import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus; @@ -49,6 +52,7 @@ class ReportGenerationPanel extends javax.swing.JPanel { c.gridy = 0; c.weightx = 1.0; glue = Box.createVerticalGlue(); + } /** @@ -78,6 +82,14 @@ class ReportGenerationPanel extends javax.swing.JPanel { // 80 px per progressPanel. reportPanel.setPreferredSize(new Dimension(600, 1 * 80)); reportPanel.repaint(); + progressPanel.addPropertyChangeListener((PropertyChangeEvent evt) -> { + String propName = evt.getPropertyName(); + if (propName.equals(ReportProgressPanel.Events.COMPLETED.toString())) { + SwingUtilities.invokeLater(() -> { + cancelButton.setEnabled(false); + }); + } + }); return progressPanel; } @@ -238,4 +250,5 @@ class ReportGenerationPanel extends javax.swing.JPanel { private javax.swing.JLabel titleLabel; private javax.swing.JSeparator titleSeparator; // End of variables declaration//GEN-END:variables + } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java b/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java index e51a62de0e..10e2e27613 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java @@ -23,6 +23,8 @@ import org.openide.util.NbBundle; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; import java.io.File; import java.io.IOException; import java.util.logging.Level; @@ -31,6 +33,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; public class ReportProgressPanel extends javax.swing.JPanel { private static final Logger logger = Logger.getLogger(ReportProgressPanel.class.getName()); + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); private ReportStatus STATUS; // Enum to represent if a report is waiting, @@ -44,6 +47,12 @@ public class ReportProgressPanel extends javax.swing.JPanel { ERROR } + public enum Events { + + COMPLETED, + NOT_COMPLETED + } + /** * Creates new form ReportProgressPanel */ @@ -109,6 +118,16 @@ public class ReportProgressPanel extends javax.swing.JPanel { } } + @Override + public void addPropertyChangeListener(PropertyChangeListener listener) { + this.pcs.addPropertyChangeListener(listener); + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener listener) { + this.pcs.removePropertyChangeListener(listener); + } + /** * Return a shortened version of the given path. */ @@ -251,10 +270,11 @@ public class ReportProgressPanel extends javax.swing.JPanel { public void run() { // make sure we disable an indeterminate reportProgressBar.setIndeterminate(false); - + if (STATUS != ReportStatus.CANCELED) { switch (reportStatus) { case COMPLETE: { + ReportStatus oldValue = STATUS; STATUS = ReportStatus.COMPLETE; processingLabel.setForeground(Color.BLACK); processingLabel.setText( @@ -264,10 +284,11 @@ public class ReportProgressPanel extends javax.swing.JPanel { // set reportProgressBar color as green. reportProgressBar.setForeground(new Color(50, 205, 50)); reportProgressBar.setString("Complete"); //NON-NLS - + pcs.firePropertyChange(Events.COMPLETED.toString(), oldValue, STATUS); break; } case ERROR: { + ReportStatus oldValue = STATUS; STATUS = ReportStatus.ERROR; processingLabel.setForeground(new Color(178, 34, 34)); processingLabel.setText( @@ -277,6 +298,7 @@ public class ReportProgressPanel extends javax.swing.JPanel { // set reportProgressBar color as red. reportProgressBar.setForeground(new Color(178, 34, 34)); reportProgressBar.setString("Error"); //NON-NLS + pcs.firePropertyChange(Events.COMPLETED.toString(), oldValue, STATUS); break; } // add finer grained result codes here. From ded047203a07f2ecb6703daa22fd8c625b0e9450 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Wed, 9 Mar 2016 12:35:17 -0500 Subject: [PATCH 16/77] Deleted unnecessary enum --- Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java b/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java index 10e2e27613..7d4189157f 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java @@ -49,8 +49,7 @@ public class ReportProgressPanel extends javax.swing.JPanel { public enum Events { - COMPLETED, - NOT_COMPLETED + COMPLETED } /** From 39b289df72595b0d372bfba454c0653820472636 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Thu, 10 Mar 2016 15:13:07 -0500 Subject: [PATCH 17/77] Updated serialization to match new protocol --- .../UserDefinedFileTypesManager.java | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java index 15beafa567..c24354a345 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java @@ -256,12 +256,12 @@ final class UserDefinedFileTypesManager { String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE); File file = new File(filePath); File serialized = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)); - if (file.exists() && file.canRead()) { - for (FileType fileType : DefinitionsReader.readFileTypes(filePath)) { + if (serialized.exists()) { + for (FileType fileType : DefinitionsReader.readFileTypesSerialized()) { addUserDefinedFileType(fileType); } - } else if (serialized.exists()) { - for (FileType fileType : DefinitionsReader.readFileTypesSerialized(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE))) { + } else if (file.exists() && file.canRead()) { + for (FileType fileType : DefinitionsReader.readFileTypes(filePath)) { addUserDefinedFileType(fileType); } } @@ -294,14 +294,8 @@ final class UserDefinedFileTypesManager { * types. */ synchronized void setUserDefinedFileTypes(List newFileTypes) throws UserDefinedFileTypesException { - try { - String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE); - DefinitionsWriter.writeFileTypes(newFileTypes, filePath); - } catch (ParserConfigurationException | FileNotFoundException | UnsupportedEncodingException | TransformerException ex) { - throwUserDefinedFileTypesException(ex, "UserDefinedFileTypesManager.saveFileTypes.errorMessage"); - } catch (IOException ex) { - throwUserDefinedFileTypesException(ex, "UserDefinedFileTypesManager.saveFileTypes.errorMessage"); - } + String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE); + DefinitionsWriter.writeFileTypes(newFileTypes, filePath); } /** @@ -334,16 +328,12 @@ final class UserDefinedFileTypesManager { * @throws UnsupportedEncodingException * @throws TransformerException */ - private static void writeFileTypes(List fileTypes, String filePath) throws ParserConfigurationException, IOException, FileNotFoundException, UnsupportedEncodingException, TransformerException { - try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)))) { + private static void writeFileTypes(List fileTypes, String filePath) throws UserDefinedFileTypesException { + try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) { UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes); out.writeObject(settings); - File xmlFile = new File(filePath); - if (xmlFile.exists()) { - xmlFile.delete(); - } } catch (IOException ex) { - throw new PersistenceException(String.format("Failed to write settings to %s", getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)), ex); + throw new UserDefinedFileTypesException(String.format("Failed to write settings to %s", getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)), ex); } } @@ -369,7 +359,7 @@ final class UserDefinedFileTypesManager { * * @return A collection of file types read from the XML file. */ - private static List readFileTypes(String filePath) throws IOException, SAXException { + private static List readFileTypes(String filePath) throws IOException, SAXException, ParserConfigurationException { List fileTypes = new ArrayList<>(); /* * RC: Commenting out the loadDocument overload that validates @@ -395,15 +385,17 @@ final class UserDefinedFileTypesManager { } return fileTypes; } - + /** * Reads the file types - * + * * @param filePath the file path where the file types are to be read + * * @return the file types + * * @throws ParserConfigurationException If the file cannot be read */ - private static List readFileTypesSerialized(String filePath) throws ParserConfigurationException { + private static List readFileTypesSerialized() throws UserDefinedFileTypesException { List fileTypes = new ArrayList<>(); File serializedDefs = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)); if (serializedDefs.exists()) { @@ -413,7 +405,7 @@ final class UserDefinedFileTypesManager { return filesSetsSettings.getUserDefinedFileTypes(); } } catch (IOException | ClassNotFoundException ex) { - throw new PersistenceException(String.format("Failed to read settings from %s", getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)), ex); + throw new UserDefinedFileTypesException("Couldn't read serialized settings.", ex); } } return fileTypes; From a64cf78cab90d273aaf1de9a722f3350b244b006 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Thu, 10 Mar 2016 16:08:48 -0500 Subject: [PATCH 18/77] Update UserDefinedFileTypesSettings.java --- .../UserDefinedFileTypesSettings.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesSettings.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesSettings.java index e2a3e8e348..1f299c9d07 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesSettings.java @@ -1,7 +1,20 @@ /* - * 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 2011-2016 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.modules.filetypeid; From eded293a078bae7df26371872f1975187f50a079 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 15 Mar 2016 11:57:14 -0400 Subject: [PATCH 19/77] Treating JLnkParser errors as warnings --- .../sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java index f97603974e..c4c80a9420 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java @@ -98,7 +98,7 @@ class RecentDocumentsByLnk extends Extract { boolean unalloc = recentFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC) || recentFile.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC); if (unalloc == false) { - logger.log(Level.SEVERE, "Error lnk parsing the file to get recent files" + recentFile, e); //NON-NLS + logger.log(Level.WARNING, "Error lnk parsing the file to get recent files {0}", recentFile); //NON-NLS this.addErrorMessage( NbBundle.getMessage(this.getClass(), "RecentDocumentsByLnk.getRecDoc.errParsingFile", this.getName(), recentFile.getName())); From 0a933b26925280c2bf752a24cc61b6945b0bb6b7 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Wed, 16 Mar 2016 10:47:00 -0400 Subject: [PATCH 20/77] Removed error message --- .../sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java index c4c80a9420..bb200551fb 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java @@ -99,9 +99,6 @@ class RecentDocumentsByLnk extends Extract { || recentFile.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC); if (unalloc == false) { logger.log(Level.WARNING, "Error lnk parsing the file to get recent files {0}", recentFile); //NON-NLS - this.addErrorMessage( - NbBundle.getMessage(this.getClass(), "RecentDocumentsByLnk.getRecDoc.errParsingFile", - this.getName(), recentFile.getName())); } continue; } From fd90ec8276d17caa51958d67358e558631b6cea4 Mon Sep 17 00:00:00 2001 From: jmillman Date: Wed, 16 Mar 2016 16:40:41 -0400 Subject: [PATCH 21/77] use data_source_obj_id to grab new files instead of add hoc methods for images and virtualdirectories --- .../imagegallery/ImageGalleryController.java | 38 +------------------ 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index 246fb00154..897667e846 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.imagegallery; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -29,7 +28,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Level; -import java.util.stream.Collectors; import javafx.application.Platform; import javafx.beans.Observable; import javafx.beans.property.ReadOnlyBooleanProperty; @@ -81,12 +79,9 @@ import org.sleuthkit.autopsy.imagegallery.gui.Toolbar; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.FileSystem; -import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; -import org.sleuthkit.datamodel.VirtualDirectory; /** * Connects different parts of ImageGallery together and is hub for flow of @@ -916,37 +911,8 @@ public final class ImageGalleryController implements Executor { @Override List getFiles() throws TskCoreException { - if (dataSource instanceof Image) { - List fileSystems = ((Image) dataSource).getFileSystems(); - if (fileSystems.isEmpty()) { - /* - * no filesystems, don't bother with the initial population, - * just sort things out on file_done events - */ - progressHandle.finish(); - return Collections.emptyList(); - } - //use this clause to only grab files from the newly added filesystems. - String fsQuery = fileSystems.stream() - .map(fileSystem -> String.valueOf(fileSystem.getId())) - .collect(Collectors.joining(" OR fs_obj_id = ", "(fs_obj_id = ", ") ")); //NON-NLS - - return tskCase.findAllFilesWhere(fsQuery + " AND " + DRAWABLE_QUERY); //NON-NLS - } else if (dataSource instanceof VirtualDirectory) { - /* - * fs_obj_id is set only for file system files, so we will match - * the VirtualDirectory's name in the parent path. - * - * TODO: A future database schema could probably make this - * cleaner. If we had a datasource_id column in the files table - * we could just match agains that. - */ - return tskCase.findAllFilesWhere(" parent_path LIKE '/" + dataSource.getName() + "/%' AND " + DRAWABLE_QUERY); //NON-NLS - } else { - String msg = "Uknown datasource type: " + dataSource.getClass().getName(); - LOGGER.log(Level.SEVERE, msg); - throw new IllegalArgumentException(msg); - } + long datasourceID = dataSource.getDataSource().getId(); + return tskCase.findAllFilesWhere("data_source_obj_id = " + datasourceID + " AND " + DRAWABLE_QUERY); } @Override From a499e55c537bfd6a5fd5612f28378bf3840571ba Mon Sep 17 00:00:00 2001 From: jmillman Date: Thu, 17 Mar 2016 17:21:41 -0400 Subject: [PATCH 22/77] updated timeline filter display names --- .../org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java | 2 +- Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java | 2 +- Core/src/org/sleuthkit/autopsy/timeline/filters/TypeFilter.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java index 79f705bab0..838144fadd 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java @@ -16,7 +16,7 @@ import org.openide.util.NbBundle; public class HashHitsFilter extends UnionFilter { @Override - @NbBundle.Messages("hashHitsFilter.displayName.text=Only Hash Set Hits") + @NbBundle.Messages("hashHitsFilter.displayName.text=Hash Sets") public String getDisplayName() { return Bundle.hashHitsFilter_displayName_text(); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java index 44d71793fe..6d90482157 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java @@ -17,7 +17,7 @@ import org.sleuthkit.datamodel.TagName; public class TagsFilter extends UnionFilter { @Override - @NbBundle.Messages("tagsFilter.displayName.text=Only Events Tagged") + @NbBundle.Messages("tagsFilter.displayName.text=Tags") public String getDisplayName() { return Bundle.tagsFilter_displayName_text(); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/TypeFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/TypeFilter.java index 362580094c..85a299e5fc 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/TypeFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/TypeFilter.java @@ -72,7 +72,7 @@ public class TypeFilter extends UnionFilter { } @Override - @NbBundle.Messages("TypeFilter.displayName.text=Event Type Filter") + @NbBundle.Messages("TypeFilter.displayName.text=Event Type") public String getDisplayName() { return (eventType == RootEventType.getInstance()) ? Bundle.TypeFilter_displayName_text() From cd486f44ed13e71ea26e69379869dededd3c3ba0 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Fri, 18 Mar 2016 13:01:17 -0400 Subject: [PATCH 23/77] Fixed property map for blackboard artifact node --- .../autopsy/datamodel/BlackboardArtifactNode.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 7101b3c023..fa934b113f 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -286,16 +286,17 @@ public class BlackboardArtifactNode extends DisplayableItemNode { * are put * @param artifact to extract properties from */ - @SuppressWarnings("deprecation") // TODO: Remove this when TSK_TAGGED_ARTIFACT rows are removed in a database upgrade. + @SuppressWarnings("deprecation") private void fillPropertyMap(Map map, BlackboardArtifact artifact) { try { for (BlackboardAttribute attribute : artifact.getAttributes()) { - final int attributeTypeID = attribute.getAttributeTypeID(); + final int attributeTypeID = attribute.getAttributeType().getTypeID(); //skip some internal attributes that user shouldn't see if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID() || attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID() || attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID() || attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) { + continue; } else if (attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID() || attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID() || attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID() @@ -304,7 +305,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode { || attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID() || attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID() || attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID()) { - map.put(attribute.getAttributeTypeDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated)); + map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString()); } else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID() && attributeTypeID == ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()) { /* @@ -318,9 +319,9 @@ public class BlackboardArtifactNode extends DisplayableItemNode { if (value.length() > 512) { value = value.substring(0, 512); } - map.put(attribute.getAttributeTypeDisplayName(), value); + map.put(attribute.getAttributeType().getDisplayName(), value); } else { - map.put(attribute.getAttributeTypeDisplayName(), attribute.getDisplayString()); + map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString()); } } } catch (TskException ex) { From 6c8b005e7db800d3d2b375af1c834571c7f3d1bb Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 18 Mar 2016 14:14:14 -0400 Subject: [PATCH 24/77] Fix incorrect dialog title bug injected in testing/RegressionTest --- .../src/org/sleuthkit/autopsy/testing/RegressionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java index bb53ec0974..1f081e06bd 100755 --- a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java +++ b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java @@ -234,7 +234,7 @@ public class RegressionTest extends TestCase { for (String database : databases) { JButtonOperator importButtonOperator = new JButtonOperator(hashMainDialogOperator, "Import"); importButtonOperator.pushNoBlock(); - JDialog addDatabaseDialog = JDialogOperator.waitJDialog("Global Keyword Search Settings", false, false); + JDialog addDatabaseDialog = JDialogOperator.waitJDialog("Import Hash Database", false, false); JDialogOperator addDatabaseDialogOperator = new JDialogOperator(addDatabaseDialog); JButtonOperator browseButtonOperator = new JButtonOperator(addDatabaseDialogOperator, "Open...", 0); browseButtonOperator.pushNoBlock(); From ff7ce09e164505ca30da068734061970053f6cef Mon Sep 17 00:00:00 2001 From: jmillman Date: Fri, 18 Mar 2016 14:15:31 -0400 Subject: [PATCH 25/77] keep track of db staleness using properties file keep track of db staleness using properties file rather than relying on SleuthKitCase.getLastObjectID() or TimeLineController.getCaseLastArtifactID() --- .../autopsy/timeline/OpenTimelineAction.java | 20 ++- .../timeline/PerCaseTimelineProperties.java | 144 ++++++++++++++++++ .../autopsy/timeline/TimeLineController.java | 128 +++++++++------- .../autopsy/timeline/db/EventDB.java | 89 +---------- .../autopsy/timeline/db/EventsRepository.java | 53 +------ .../autopsy/timeline/ui/StatusBar.java | 5 +- .../timeline/ui/VisualizationPanel.java | 8 +- 7 files changed, 248 insertions(+), 199 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/timeline/PerCaseTimelineProperties.java diff --git a/Core/src/org/sleuthkit/autopsy/timeline/OpenTimelineAction.java b/Core/src/org/sleuthkit/autopsy/timeline/OpenTimelineAction.java index 78b21bd9e8..73d58e49ac 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/OpenTimelineAction.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/OpenTimelineAction.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.timeline; +import java.io.IOException; import java.util.logging.Level; import javax.swing.JOptionPane; import org.openide.awt.ActionID; @@ -31,6 +32,7 @@ import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.core.Installer; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.ThreadConfined; @ActionID(category = "Tools", id = "org.sleuthkit.autopsy.timeline.Timeline") @@ -74,14 +76,18 @@ public class OpenTimelineAction extends CallableSystemAction { return; } - if (timeLineController == null) { - timeLineController = new TimeLineController(currentCase); - } else if (timeLineController.getAutopsyCase() != currentCase) { - timeLineController.closeTimeLine(); - timeLineController = new TimeLineController(currentCase); + try { + if (timeLineController == null) { + timeLineController = new TimeLineController(currentCase); + } else if (timeLineController.getAutopsyCase() != currentCase) { + timeLineController.closeTimeLine(); + timeLineController = new TimeLineController(currentCase); + } + timeLineController.openTimeLine(); + } catch (IOException iOException) { + MessageNotifyUtil.Notify.error("Timeline", "Failed to initialize timeline settings."); + LOGGER.log(Level.SEVERE, "Failed to initialize per case timeline settings."); } - - timeLineController.openTimeLine(); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/timeline/PerCaseTimelineProperties.java b/Core/src/org/sleuthkit/autopsy/timeline/PerCaseTimelineProperties.java new file mode 100644 index 0000000000..faeb4e3dac --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/timeline/PerCaseTimelineProperties.java @@ -0,0 +1,144 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2016 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.timeline; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; +import org.apache.commons.lang3.StringUtils; +import org.sleuthkit.autopsy.casemodule.Case; + +/** + * Provides access to per-case timeline properties/settings. + */ +class PerCaseTimelineProperties { + + public static final String STALE_KEY = "stale"; //NON-NLS + public static final String WAS_INGEST_RUNNING_KEY = "was_ingest_running"; // NON-NLS + + private final Case theCase; + private final Path propertiesPath; + + PerCaseTimelineProperties(Case c) { + this.theCase = c; + propertiesPath = Paths.get(theCase.getModuleDirectory(), "Timeline", "timeline.properties"); //NON-NLS + } + + public synchronized boolean isDbStale() throws IOException { + String stale = getConfigSetting(STALE_KEY); + return StringUtils.isBlank(stale) ? true : Boolean.valueOf(stale); + } + + public synchronized void setDbStale(Boolean stale) throws IOException { + setConfigSetting(STALE_KEY, stale.toString()); + } + + public synchronized boolean wasIngestRunning() throws IOException { + String stale = getConfigSetting(WAS_INGEST_RUNNING_KEY); + return StringUtils.isBlank(stale) ? true : Boolean.valueOf(stale); + } + + public synchronized void setIngestRunning(Boolean stale) throws IOException { + setConfigSetting(WAS_INGEST_RUNNING_KEY, stale.toString()); + } + + /** + * Makes a new config file of the specified name. Do not include the + * extension. + * + * @param moduleName - The name of the config file to make + * + * @return True if successfully created, false if already exists or an error + * is thrown. + */ + private synchronized Path getPropertiesPath() throws IOException { + + if (!Files.exists(propertiesPath)) { + Path parent = propertiesPath.getParent(); + Files.createDirectories(parent); + Files.createFile(propertiesPath); + } + return propertiesPath; + } + + /** + * Returns the given properties file's setting as specific by settingName. + * + * @param moduleName - The name of the config file to read from. + * @param settingName - The setting name to retrieve. + * + * @return - the value associated with the setting. + * + * @throws IOException + */ + private synchronized String getConfigSetting(String settingName) throws IOException { + return getProperties().getProperty(settingName); + } + + /** + * Sets the given properties file to the given settings. + * + * @param moduleName - The name of the module to be written to. + * @param settingName - The name of the setting to be modified. + * @param settingVal - the value to set the setting to. + */ + private synchronized void setConfigSetting(String settingName, String settingVal) throws IOException { + Path propertiesFile = getPropertiesPath(); + Properties props = getProperties(propertiesFile); + props.setProperty(settingName, settingVal); + + try (OutputStream fos = Files.newOutputStream(propertiesFile)) { + props.store(fos, ""); //NON-NLS + } + } + + /** + * Returns the properties as specified by moduleName. + * + * @param moduleName + * @param propertiesFile the value of propertiesFile + * + * @throws IOException + * @return the java.util.Properties + */ + private synchronized Properties getProperties() throws IOException { + return getProperties(getPropertiesPath()); + } + + /** + * Returns the properties as specified by moduleName. + * + * @param moduleName + * + * @return Properties file as specified by moduleName. + * + * @throws IOException + */ + private synchronized Properties getProperties(final Path propertiesFile) throws IOException { + try (InputStream inputStream = Files.newInputStream(propertiesFile)) { + Properties props = new Properties(); + props.load(inputStream); + return props; + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index a33bdb50d1..abfa02a5f3 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.timeline; import java.awt.HeadlessException; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.io.IOException; import java.sql.ResultSet; import java.sql.SQLException; import java.time.ZoneId; @@ -33,7 +34,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Level; import javafx.application.Platform; -import javafx.beans.InvalidationListener; import javafx.beans.Observable; import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.ReadOnlyBooleanWrapper; @@ -49,7 +49,6 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.concurrent.Task; import javafx.concurrent.Worker; -import javafx.scene.control.Dialog; import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.Immutable; import javax.swing.SwingUtilities; @@ -139,9 +138,6 @@ public class TimeLineController { private final ReadOnlyStringWrapper status = new ReadOnlyStringWrapper(); - @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - private Dialog currentDialog; - /** * status is a string that will be displayed in the status bar as a kind of * user hint/information when it is not empty @@ -156,6 +152,7 @@ public class TimeLineController { status.set(string); } private final Case autoCase; + private final PerCaseTimelineProperties perCaseTimelineProperties; @ThreadConfined(type = ThreadConfined.ThreadType.JFX) private final ObservableList quickHideMaskFilters = FXCollections.observableArrayList(); @@ -241,14 +238,8 @@ public class TimeLineController { return selectedTimeRange.getReadOnlyProperty(); } - public ReadOnlyBooleanProperty getNewEventsFlag() { - return newEventsFlag.getReadOnlyProperty(); - } - - private final ReadOnlyBooleanWrapper needsHistogramRebuild = new ReadOnlyBooleanWrapper(false); - - public ReadOnlyBooleanProperty getNeedsHistogramRebuild() { - return needsHistogramRebuild.getReadOnlyProperty(); + public ReadOnlyBooleanProperty eventsDBStaleProperty() { + return eventsDBStale.getReadOnlyProperty(); } synchronized public ReadOnlyBooleanProperty getCanAdvance() { @@ -258,28 +249,26 @@ public class TimeLineController { synchronized public ReadOnlyBooleanProperty getCanRetreat() { return historyManager.getCanRetreat(); } - private final ReadOnlyBooleanWrapper newEventsFlag = new ReadOnlyBooleanWrapper(false); + private final ReadOnlyBooleanWrapper eventsDBStale = new ReadOnlyBooleanWrapper(false); private final PromptDialogManager promptDialogManager = new PromptDialogManager(this); - public TimeLineController(Case autoCase) { + public TimeLineController(Case autoCase) throws IOException { this.autoCase = autoCase; - + this.perCaseTimelineProperties = new PerCaseTimelineProperties(autoCase); + eventsDBStale.set(perCaseTimelineProperties.isDbStale()); + eventsRepository = new EventsRepository(autoCase, currentParams.getReadOnlyProperty()); /* * as the history manager's current state changes, modify the tags * filter to be in sync, and expose that as propery from * TimeLineController. Do we need to do this with datasource or hash hit * filters? */ - historyManager.currentState().addListener(new InvalidationListener() { - public void invalidated(Observable observable) { - ZoomParams historyManagerParams = historyManager.getCurrentState(); - eventsRepository.syncTagsFilter(historyManagerParams.getFilter().getTagsFilter()); - currentParams.set(historyManagerParams); - } + historyManager.currentState().addListener((Observable observable) -> { + ZoomParams historyManagerParams = historyManager.getCurrentState(); + eventsRepository.syncTagsFilter(historyManagerParams.getFilter().getTagsFilter()); + currentParams.set(historyManagerParams); }); - - eventsRepository = new EventsRepository(autoCase, currentParams.getReadOnlyProperty()); filteredEvents = eventsRepository.getEventsModel(); InitialZoomState = new ZoomParams(filteredEvents.getSpanningInterval(), @@ -316,19 +305,22 @@ public class TimeLineController { void rebuildRepo() { SwingUtilities.invokeLater(this::closeTimelineWindow); final CancellationProgressTask rebuildRepository = eventsRepository.rebuildRepository(); + boolean ingestRunning = IngestManager.getInstance().isIngestRunning(); rebuildRepository.stateProperty().addListener((stateProperty, oldState, newSate) -> { //this will be on JFX thread - if (newSate == Worker.State.SUCCEEDED) { - //TODO: this looks hacky. what is going on? should this be an event? - needsHistogramRebuild.set(true); - needsHistogramRebuild.set(false); - SwingUtilities.invokeLater(TimeLineController.this::showWindow); - - //TODO: should this be an event? - newEventsFlag.set(false); - historyManager.reset(filteredEvents.zoomParametersProperty().get()); - TimeLineController.this.showFullRange(); + setIngestRunning(ingestRunning); + switch (newSate) { + case SUCCEEDED: + setEventsDBStale(false); + SwingUtilities.invokeLater(TimeLineController.this::showWindow); + historyManager.reset(filteredEvents.zoomParametersProperty().get()); + TimeLineController.this.showFullRange(); + break; + case FAILED: + case CANCELLED: + setEventsDBStale(true); + break; } }); promptDialogManager.showProgressDialog(rebuildRepository); @@ -409,7 +401,7 @@ public class TimeLineController { /* * if the repo was not rebuilt at minimum rebuild the tags which * may have been updated without our knowing it, since we - * can't/aren't checking them. This should at elast be quick. + * can't/aren't checking them. This should at least be quick. * //TODO: can we check the tags to see if we need to do this? */ if (checkAndPromptForRebuild() == false) { @@ -425,7 +417,7 @@ public class TimeLineController { @ThreadConfined(type = ThreadConfined.ThreadType.JFX) private boolean checkAndPromptForRebuild() { //if the repo is empty just (r)ebuild it with out asking, they can always cancel part way through; - if (eventsRepository.getLastObjID() == -1) { + if (eventsRepository.countAllEvents() == 0) { rebuildRepo(); return true; } @@ -451,22 +443,21 @@ public class TimeLineController { private ArrayList getRebuildReasons() { ArrayList rebuildReasons = new ArrayList<>(); //if ingest was running during last rebuild, prompt to rebuild - if (eventsRepository.getWasIngestRunning()) { - rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_ingestWasRunning()); - } - final SleuthkitCase sleuthkitCase = autoCase.getSleuthkitCase(); try { - //if the last artifact and object ids don't match between skc and tldb, prompt to rebuild - if (sleuthkitCase.getLastObjectId() != eventsRepository.getLastObjID() - || getCaseLastArtifactID(sleuthkitCase) != eventsRepository.getLastArtfactID()) { - rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_outOfDate()); + if (perCaseTimelineProperties.wasIngestRunning()) { + rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_ingestWasRunning()); } - } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Error determing last object id from sleutkit case. We will assume the timeline is out of date.", ex); // NON-NLS + + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "Error determing the state of the timeline db. We will assume the it is out of date.", ex); // NON-NLS MessageNotifyUtil.Notify.error(Bundle.TimeLineController_errorTitle(), Bundle.TimeLineController_outOfDate_errorMessage()); rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_outOfDateError()); } + //if the events db is stale, prompt to rebuild + if (isEventsDBStale()) { + rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_outOfDate()); + } // if the TLDB schema has been upgraded since last time TL ran, prompt for rebuild if (eventsRepository.hasNewColumns() == false) { rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_incompleteOldSchema()); @@ -752,6 +743,38 @@ public class TimeLineController { } } + /** + * is the events db out of date + * + * @return true if the events db is out of date , false otherwise + */ + public boolean isEventsDBStale() { + return eventsDBStale.get(); + } + + /** + * + * @param stale the value of stale + */ + private void setEventsDBStale(final Boolean stale) { + eventsDBStale.set(stale); + try { + perCaseTimelineProperties.setDbStale(stale); + } catch (IOException ex) { + MessageNotifyUtil.Notify.error("Timeline", "Failed to mark the timeline db as " + (stale ? "" : "not ") + "stale. Some results may be out of date or missing."); + LOGGER.log(Level.SEVERE, "Error marking the timeline db as stale.", ex); + } + } + + private void setIngestRunning(boolean ingestRunning) { + try { + perCaseTimelineProperties.setIngestRunning(ingestRunning); + } catch (IOException ex) { + MessageNotifyUtil.Notify.error("Timeline", "Failed to mark the timeline db as populated while ingest was" + (ingestRunning ? "" : "not ") + "running. Some results may be out of date or missing."); + LOGGER.log(Level.SEVERE, "Error marking the ingest state while the timeline db was populated.", ex); + } + } + private class AutopsyIngestModuleListener implements PropertyChangeListener { @Override @@ -773,15 +796,14 @@ public class TimeLineController { switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) { case CONTENT_CHANGED: - case DATA_ADDED: break; + case DATA_ADDED: case FILE_DONE: - Platform.runLater(() -> { - newEventsFlag.set(true); - }); + Platform.runLater(() -> setEventsDBStale(true)); break; } } + } @Immutable @@ -824,7 +846,11 @@ public class TimeLineController { }); break; case DATA_SOURCE_ADDED: - SwingUtilities.invokeLater(TimeLineController.this::confirmOutOfDateRebuildIfWindowOpen); + Platform.runLater(() -> { + setEventsDBStale(true); + SwingUtilities.invokeLater(TimeLineController.this::confirmOutOfDateRebuildIfWindowOpen); + }); + break; case CURRENT_CASE: diff --git a/Core/src/org/sleuthkit/autopsy/timeline/db/EventDB.java b/Core/src/org/sleuthkit/autopsy/timeline/db/EventDB.java index e708fe0b99..ed0357d6fa 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/db/EventDB.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/db/EventDB.java @@ -84,28 +84,6 @@ import org.sqlite.SQLiteJDBCLoader; */ public class EventDB { - /** - * - * enum to represent keys stored in db_info table - */ - private enum DBInfoKey { - - LAST_ARTIFACT_ID("last_artifact_id"), // NON-NLS - LAST_OBJECT_ID("last_object_id"), // NON-NLS - WAS_INGEST_RUNNING("was_ingest_running"); // NON-NLS - - private final String keyName; - - private DBInfoKey(String keyName) { - this.keyName = keyName; - } - - @Override - public String toString() { - return keyName; - } - } - private static final org.sleuthkit.autopsy.coreutils.Logger LOGGER = Logger.getLogger(EventDB.class.getName()); static { @@ -142,14 +120,12 @@ public class EventDB { private final String dbPath; - private PreparedStatement getDBInfoStmt; private PreparedStatement getEventByIDStmt; private PreparedStatement getMaxTimeStmt; private PreparedStatement getMinTimeStmt; private PreparedStatement getDataSourceIDsStmt; private PreparedStatement getHashSetNamesStmt; private PreparedStatement insertRowStmt; - private PreparedStatement recordDBInfoStmt; private PreparedStatement insertHashSetStmt; private PreparedStatement insertHashHitStmt; private PreparedStatement insertTagStmt; @@ -394,14 +370,6 @@ public class EventDB { return resultIDs; } - long getLastArtfactID() { - return getDBInfo(DBInfoKey.LAST_ARTIFACT_ID, -1); - } - - long getLastObjID() { - return getDBInfo(DBInfoKey.LAST_OBJECT_ID, -1); - } - /** * this relies on the fact that no tskObj has ID 0 but 0 is the default * value for the datasource_id column in the events table. @@ -489,10 +457,6 @@ public class EventDB { return -1l; } - boolean getWasIngestRunning() { - return getDBInfo(DBInfoKey.WAS_INGEST_RUNNING, 0) != 0; - } - /** * create the table and indices if they don't already exist * @@ -614,8 +578,6 @@ public class EventDB { getMaxTimeStmt = prepareStatement("SELECT Max(time) AS max FROM events"); // NON-NLS getMinTimeStmt = prepareStatement("SELECT Min(time) AS min FROM events"); // NON-NLS getEventByIDStmt = prepareStatement("SELECT * FROM events WHERE event_id = ?"); // NON-NLS - recordDBInfoStmt = prepareStatement("INSERT OR REPLACE INTO db_info (key, value) values (?, ?)"); // NON-NLS - getDBInfoStmt = prepareStatement("SELECT value FROM db_info WHERE key = ?"); // NON-NLS insertHashSetStmt = prepareStatement("INSERT OR IGNORE INTO hash_sets (hash_set_name) values (?)"); //NON-NLS selectHashSetStmt = prepareStatement("SELECT hash_set_id FROM hash_sets WHERE hash_set_name = ?"); //NON-NLS insertHashHitStmt = prepareStatement("INSERT OR IGNORE INTO hash_set_hits (hash_set_id, event_id) values (?,?)"); //NON-NLS @@ -938,18 +900,6 @@ public class EventDB { return eventIDs; } - void recordLastArtifactID(long lastArtfID) { - recordDBInfo(DBInfoKey.LAST_ARTIFACT_ID, lastArtfID); - } - - void recordLastObjID(Long lastObjID) { - recordDBInfo(DBInfoKey.LAST_OBJECT_ID, lastObjID); - } - - void recordWasIngestRunning(boolean wasIngestRunning) { - recordDBInfo(DBInfoKey.WAS_INGEST_RUNNING, (wasIngestRunning ? 1 : 0)); - } - void rollBackTransaction(EventTransaction trans) { trans.rollback(); } @@ -983,8 +933,7 @@ public class EventDB { try { LOGGER.log(Level.INFO, String.format("sqlite-jdbc version %s loaded in %s mode", // NON-NLS - SQLiteJDBCLoader.getVersion(), SQLiteJDBCLoader.isNativeMode() - ? "native" : "pure-java")); // NON-NLS + SQLiteJDBCLoader.getVersion(), SQLiteJDBCLoader.isNativeMode() ? "native" : "pure-java")); // NON-NLS } catch (Exception exception) { LOGGER.log(Level.SEVERE, "Failed to determine if sqlite-jdbc is loaded in native or pure-java mode.", exception); //NON-NLS } @@ -1220,28 +1169,6 @@ public class EventDB { return useSubTypes ? "sub_type" : "base_type"; //NON-NLS } - private long getDBInfo(DBInfoKey key, long defaultValue) { - DBLock.lock(); - try { - getDBInfoStmt.setString(1, key.toString()); - - try (ResultSet rs = getDBInfoStmt.executeQuery()) { - long result = defaultValue; - while (rs.next()) { - result = rs.getLong("value"); // NON-NLS - } - return result; - } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "failed to read key: " + key + " from db_info", ex); // NON-NLS - } finally { - DBLock.unlock(); - } - } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "failed to set key: " + key + " on getDBInfoStmt ", ex); // NON-NLS - } - - return defaultValue; - } private PreparedStatement prepareStatement(String queryString) throws SQLException { PreparedStatement prepareStatement = con.prepareStatement(queryString); @@ -1249,20 +1176,6 @@ public class EventDB { return prepareStatement; } - private void recordDBInfo(DBInfoKey key, long value) { - DBLock.lock(); - try { - recordDBInfoStmt.setString(1, key.toString()); - recordDBInfoStmt.setLong(2, value); - recordDBInfoStmt.executeUpdate(); - } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "failed to set dbinfo key: " + key + " value: " + value, ex); // NON-NLS - } finally { - DBLock.unlock(); - - } - } - /** * inner class that can reference access database connection */ diff --git a/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java b/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java index 6946ded64d..c8554cfdc3 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java @@ -54,9 +54,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; -import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.timeline.CancellationProgressTask; -import org.sleuthkit.autopsy.timeline.TimeLineController; import org.sleuthkit.autopsy.timeline.datamodel.EventStripe; import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel; import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent; @@ -168,7 +166,7 @@ public class EventsRepository { */ public Long getMaxTime() { return maxCache.getUnchecked("max"); // NON-NLS -// return eventDB.getMaxTime(); + } /** @@ -176,32 +174,9 @@ public class EventsRepository { */ public Long getMinTime() { return minCache.getUnchecked("min"); // NON-NLS -// return eventDB.getMinTime(); + } - private void recordLastArtifactID(long lastArtfID) { - eventDB.recordLastArtifactID(lastArtfID); - } - - private void recordWasIngestRunning(Boolean wasIngestRunning) { - eventDB.recordWasIngestRunning(wasIngestRunning); - } - - private void recordLastObjID(Long lastObjID) { - eventDB.recordLastObjID(lastObjID); - } - - public boolean getWasIngestRunning() { - return eventDB.getWasIngestRunning(); - } - - public Long getLastObjID() { - return eventDB.getLastObjID(); - } - - public long getLastArtfactID() { - return eventDB.getLastArtfactID(); - } public TimeLineEvent getEventById(Long eventID) { return idToEventCache.getUnchecked(eventID); @@ -227,6 +202,10 @@ public class EventsRepository { return eventCountsCache.getUnchecked(params); } + synchronized public int countAllEvents() { + return eventDB.countAllEvents(); + } + private void invalidateCaches() { minCache.invalidateAll(); maxCache.invalidateAll(); @@ -331,17 +310,7 @@ public class EventsRepository { } } - /** - * - * @param lastObjId the value of lastObjId - * @param lastArtfID the value of lastArtfID - * @param injestRunning the value of injestRunning - */ - public void recordDBPopulationState(final long lastObjId, final long lastArtfID, final Boolean injestRunning) { - recordLastObjID(lastObjId); - recordLastArtifactID(lastArtfID); - recordWasIngestRunning(injestRunning); - } + public boolean areFiltersEquivalent(RootFilter f1, RootFilter f2) { return SQLHelper.getSQLWhere(f1).equals(SQLHelper.getSQLWhere(f2)); @@ -470,11 +439,6 @@ public class EventsRepository { protected Void call() throws Exception { EventDB.EventTransaction trans = null; - //save paramaters for recording later - long lastObjId = skCase.getLastObjectId(); - long lastArtfID = TimeLineController.getCaseLastArtifactID(skCase); - boolean injestRunning = IngestManager.getInstance().isIngestRunning(); - if (dbPopulationMode == DBPopulationMode.FULL) { //drop old db, and add back MAC and artifact events LOGGER.log(Level.INFO, "Beginning population of timeline db."); // NON-NLS @@ -513,9 +477,6 @@ public class EventsRepository { Platform.runLater(() -> cancellable.set(false)); restartProgressHandle(Bundle.progressWindow_msg_commitingDb(), "", -1D, 1, false); eventDB.commitTransaction(trans); - if (isCancelRequested() == false) { - recordDBPopulationState(lastObjId, lastArtfID, injestRunning); - } eventDB.analyze(); populateFilterData(skCase); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/StatusBar.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/StatusBar.java index 3ff0222beb..eb1ba3091a 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/StatusBar.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/StatusBar.java @@ -74,8 +74,8 @@ public class StatusBar extends ToolBar { taskLabel.setVisible(false); HBox.setHgrow(spacer, Priority.ALWAYS); - refreshLabel.visibleProperty().bind(this.controller.getNewEventsFlag()); - refreshLabel.managedProperty().bind(this.controller.getNewEventsFlag()); + refreshLabel.visibleProperty().bind(this.controller.eventsDBStaleProperty()); + refreshLabel.managedProperty().bind(this.controller.eventsDBStaleProperty()); taskLabel.textProperty().bind(this.controller.taskTitleProperty()); messageLabel.textProperty().bind(this.controller.taskMessageProperty()); progressBar.progressProperty().bind(this.controller.taskProgressProperty()); @@ -83,6 +83,5 @@ public class StatusBar extends ToolBar { statusLabel.textProperty().bind(this.controller.getStatusProperty()); statusLabel.visibleProperty().bind(statusLabel.textProperty().isNotEmpty()); - } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/VisualizationPanel.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/VisualizationPanel.java index eb3cf09768..2f56b78f79 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/VisualizationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/VisualizationPanel.java @@ -347,9 +347,9 @@ final public class VisualizationPanel extends BorderPane { refreshTimeUI(); //populate the viz //this should use an event(EventBus) , not this weird observable pattern - controller.getNeedsHistogramRebuild().addListener((observable, oldValue, newValue) -> { - if (newValue) { - refreshHistorgram(); + controller.eventsDBStaleProperty().addListener(staleProperty -> { + if (controller.isEventsDBStale()) { + Platform.runLater(VisualizationPanel.this::refreshHistorgram); } }); refreshHistorgram(); @@ -569,7 +569,7 @@ final public class VisualizationPanel extends BorderPane { titledPane.setText(Bundle.NoEventsDialog_titledPane_text()); noEventsDialogLabel.setText(NbBundle.getMessage(NoEventsDialog.class, "VisualizationPanel.noEventsDialogLabel.text")); // NON-NLS - + dismissButton.setOnAction(actionEvent -> closeCallback.run()); ActionUtils.configureButton(new ZoomToEvents(controller), zoomButton); From eb425bbfd9b93f99790a97455e5038a30e84580a Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Fri, 18 Mar 2016 15:03:54 -0400 Subject: [PATCH 26/77] Added content to ArtifactData to optimize getting time, source file. --- .../autopsy/report/ReportGenerator.java | 524 +++++++++--------- 1 file changed, 272 insertions(+), 252 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index e0d201f4af..6bdaf6a065 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -51,12 +51,15 @@ import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.SwingWorker; import org.openide.filesystems.FileUtil; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -79,20 +82,20 @@ import org.sleuthkit.datamodel.BlackboardAttribute.Type; * objects displayed using a dialog box. */ class ReportGenerator { - + private static final Logger logger = Logger.getLogger(ReportGenerator.class.getName()); - + private Case currentCase = Case.getCurrentCase(); private SleuthkitCase skCase = currentCase.getSleuthkitCase(); - + private Map tableProgress; private Map generalProgress; private Map fileProgress; private Map> columnHeaderMap; - + private String reportPath; private ReportGenerationPanel panel = new ReportGenerationPanel(); - + static final String REPORTS_DIR = "Reports"; //NON-NLS private List errorList; @@ -114,14 +117,14 @@ class ReportGenerator { return; } } - + ReportGenerator(Map tableModuleStates, Map generalModuleStates, Map fileListModuleStates) { // Create the root reports directory path of the form: /Reports/ / DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss"); Date date = new Date(); String dateNoTime = dateFormat.format(date); this.reportPath = currentCase.getReportDirectory() + File.separator + currentCase.getName() + " " + dateNoTime + File.separator; - + this.errorList = new ArrayList(); // Create the root reports directory. @@ -166,7 +169,7 @@ class ReportGenerator { } } } - + if (null != generalModuleStates) { for (Entry entry : generalModuleStates.entrySet()) { if (entry.getValue()) { @@ -180,7 +183,7 @@ class ReportGenerator { } } } - + if (null != fileListModuleStates) { for (Entry entry : fileListModuleStates.entrySet()) { if (entry.getValue()) { @@ -206,21 +209,21 @@ class ReportGenerator { dialog.setTitle(NbBundle.getMessage(this.getClass(), "ReportGenerator.displayProgress.title.text")); dialog.add(this.panel); dialog.pack(); - + panel.addCloseAction(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { dialog.dispose(); } }); - + dialog.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { panel.close(); } }); - + Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); int w = dialog.getSize().width; int h = dialog.getSize().height; @@ -276,7 +279,7 @@ class ReportGenerator { * SwingWorker to run GeneralReportModules. */ private class GeneralReportsWorker extends SwingWorker { - + @Override protected Integer doInBackground() throws Exception { for (Entry entry : generalProgress.entrySet()) { @@ -287,7 +290,7 @@ class ReportGenerator { } return 0; } - + @Override protected void done() { try { @@ -305,24 +308,24 @@ class ReportGenerator { errorList.clear(); } } - + } /** * SwingWorker to run FileReportModules. */ private class FileReportsWorker extends SwingWorker { - + private List enabledInfo = Arrays.asList(FileReportDataTypes.values()); private List fileModules = new ArrayList<>(); - + FileReportsWorker(List enabled) { enabledInfo = enabled; for (Entry entry : fileProgress.entrySet()) { fileModules.add(entry.getKey()); } } - + @Override protected Integer doInBackground() throws Exception { for (FileReportModule module : fileModules) { @@ -333,7 +336,7 @@ class ReportGenerator { NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.queryingDb.text")); } } - + List files = getFiles(); int numFiles = files.size(); for (FileReportModule module : fileModules) { @@ -342,7 +345,7 @@ class ReportGenerator { fileProgress.get(module).setIndeterminate(false); fileProgress.get(module).setMaximumProgress(numFiles); } - + int i = 0; // Add files to report. for (AbstractFile file : files) { @@ -361,7 +364,7 @@ class ReportGenerator { module.addRow(file, enabledInfo); progress.increment(); } - + if ((i % 100) == 0) { progress.updateStatusLabel( NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processingFile.text", @@ -370,13 +373,13 @@ class ReportGenerator { } i++; } - + for (FileReportModule module : fileModules) { module.endTable(); module.endReport(); fileProgress.get(module).complete(ReportStatus.COMPLETE); } - + return 0; } @@ -400,7 +403,7 @@ class ReportGenerator { return Collections.emptyList(); } } - + @Override protected void done() { try { @@ -425,13 +428,13 @@ class ReportGenerator { * content tags, and blackboard artifact tags. */ private class TableReportsWorker extends SwingWorker { - + private List tableModules = new ArrayList<>(); private List artifactTypes = new ArrayList<>(); private HashSet tagNamesFilter = new HashSet<>(); - + private List images = new ArrayList<>(); - + TableReportsWorker(Map artifactTypeSelections, Map tagNameSelections) { // Get the report modules selected by the user. for (Entry entry : tableProgress.entrySet()) { @@ -454,7 +457,7 @@ class ReportGenerator { } } } - + @Override protected Integer doInBackground() throws Exception { // Start the progress indicators for each active TableReportModule. @@ -483,7 +486,7 @@ class ReportGenerator { tableProgress.get(module).complete(ReportStatus.COMPLETE); module.endReport(); } - + return 0; } @@ -505,7 +508,7 @@ class ReportGenerator { if (tableModules.isEmpty()) { return; } - + for (TableReportModule module : tableModules) { tableProgress.get(module).updateStatusLabel( NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processing", @@ -520,9 +523,9 @@ class ReportGenerator { writeHashsetHits(tableModules, comment.toString(), tagNamesFilter); continue; } - + List artifactList = getFilteredArtifacts(type, tagNamesFilter); - + if (artifactList.isEmpty()) { continue; } @@ -555,7 +558,7 @@ class ReportGenerator { for (Column currColumn : columns) { columnHeaderNames.add(currColumn.getColumnHeader()); } - + for (TableReportModule module : tableModules) { module.startDataType(type.getDisplayName(), comment.toString()); module.startTable(columnHeaderNames); @@ -570,7 +573,7 @@ class ReportGenerator { if (rowData.isEmpty()) { continue; } - + module.addRow(rowData); } } @@ -621,7 +624,7 @@ class ReportGenerator { NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.timeCreated"), NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.size"), NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.hash"))); - + StringBuilder comment = new StringBuilder(); if (!tagNamesFilter.isEmpty()) { comment.append( @@ -644,14 +647,14 @@ class ReportGenerator { if (passesTagNamesFilter(tag.getName().getDisplayName()) == false) { continue; } - + String fileName; try { fileName = tag.getContent().getUniquePath(); } catch (TskCoreException ex) { fileName = tag.getContent().getName(); } - + ArrayList rowData = new ArrayList<>(Arrays.asList(tag.getName().getDisplayName(), fileName, tag.getComment())); for (TableReportModule module : tableModules) { // @@@ This casting is a tricky little workaround to allow the HTML report module to slip in a content hyperlink. @@ -674,7 +677,7 @@ class ReportGenerator { module.endDataType(); } } - + @Override protected void done() { try { @@ -703,7 +706,7 @@ class ReportGenerator { if (tableModules.isEmpty()) { return; } - + List tags; try { tags = Case.getCurrentCase().getServices().getTagsManager().getAllBlackboardArtifactTags(); @@ -738,7 +741,7 @@ class ReportGenerator { if (passesTagNamesFilter(tag.getName().getDisplayName()) == false) { continue; } - + List row; for (TableReportModule module : tableModules) { row = new ArrayList<>(Arrays.asList(tag.getArtifact().getArtifactTypeName(), tag.getName().getDisplayName(), tag.getComment(), tag.getContent().getName())); @@ -767,7 +770,7 @@ class ReportGenerator { private boolean passesTagNamesFilter(String tagName) { return tagNamesFilter.isEmpty() || tagNamesFilter.contains(tagName); } - + void removeCancelledTableReportModules() { Iterator iter = tableModules.iterator(); while (iter.hasNext()) { @@ -785,7 +788,7 @@ class ReportGenerator { for (TableReportModule module : tableModules) { tableProgress.get(module).updateStatusLabel( NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.createdThumb.text")); - + if (module instanceof ReportHTML) { ReportHTML htmlModule = (ReportHTML) module; htmlModule.startDataType( @@ -796,9 +799,9 @@ class ReportGenerator { emptyHeaders.add(""); } htmlModule.startTable(emptyHeaders); - + htmlModule.addThumbnailRows(images); - + htmlModule.endTable(); htmlModule.endDataType(); } @@ -821,7 +824,7 @@ class ReportGenerator { logger.log(Level.WARNING, "Error while getting content from a blackboard artifact to report on.", ex); //NON-NLS return; } - + if (file != null) { checkIfFileIsImage(file); } @@ -848,13 +851,13 @@ class ReportGenerator { * @param file */ private void checkIfFileIsImage(AbstractFile file) { - + if (file.isDir() || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) { return; } - + if (ImageUtils.thumbnailSupported(file)) { images.add(file); } @@ -866,7 +869,7 @@ class ReportGenerator { if (null == tagsNamesFilter || tagsNamesFilter.isEmpty()) { return false; } - + HashSet filteredTagNames = new HashSet<>(tagNames); filteredTagNames.retainAll(tagsNamesFilter); return filteredTagNames.isEmpty(); @@ -958,7 +961,7 @@ class ReportGenerator { logger.log(Level.SEVERE, "Failed to query keyword lists: ", ex); //NON-NLS return; } - + if (currentCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) { orderByClause = "ORDER BY convert_to(att3.value_text, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS + "convert_to(att1.value_text, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS @@ -984,7 +987,7 @@ class ReportGenerator { try (CaseDbQuery dbQuery = skCase.executeQuery(keywordsQuery)) { ResultSet resultSet = dbQuery.getResultSet(); - + String currentKeyword = ""; String currentList = ""; while (resultSet.next()) { @@ -1006,13 +1009,13 @@ class ReportGenerator { continue; } String tagsList = makeCommaSeparatedList(uniqueTagNames); - + Long objId = resultSet.getLong("obj_id"); //NON-NLS String keyword = resultSet.getString("keyword"); //NON-NLS String preview = resultSet.getString("preview"); //NON-NLS String list = resultSet.getString("list"); //NON-NLS String uniquePath = ""; - + try { AbstractFile f = skCase.getAbstractFileById(objId); if (f != null) { @@ -1059,7 +1062,7 @@ class ReportGenerator { module.startTable(columnHeaderNames); } } - + String previewreplace = EscapeUtil.escapeHtml(preview); for (TableReportModule module : tableModules) { module.addRow(Arrays.asList(new String[]{previewreplace.replaceAll(" { - + private BlackboardArtifact artifact; private List attributes; private HashSet tags; private List rowData = null; - + private Content content; + ArtifactData(BlackboardArtifact artifact, List attrs, HashSet tags) { this.artifact = artifact; this.attributes = attrs; this.tags = tags; + try { + this.content = Case.getCurrentCase().getSleuthkitCase().getContentById(artifact.getObjectID()); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Could not get content from database"); + } } - + public BlackboardArtifact getArtifact() { return artifact; } - + public List getAttributes() { return attributes; } - + public HashSet getTags() { return tags; } - + public long getArtifactID() { return artifact.getArtifactID(); } - + public long getObjectID() { return artifact.getObjectID(); } + /** + * @return the content + */ + public Content getContent() { + return content; + } + /** * Compares ArtifactData objects by the first attribute they have in * common in their List. Should only be used on two @@ -1878,11 +1893,11 @@ class ReportGenerator { * @throws TskCoreException */ private List getOrderedRowDataAsStrings() throws TskCoreException { - + List orderedRowData = new ArrayList<>(); if (ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID() == getArtifact().getArtifactTypeID()) { - AbstractFile file = skCase.getAbstractFileById(getObjectID()); - if (file != null) { + if (content != null && content instanceof AbstractFile) { + AbstractFile file = (AbstractFile) content; orderedRowData.add(file.getName()); orderedRowData.add(file.getNameExtension()); String mimeType = file.getMIMEType(); @@ -1900,7 +1915,7 @@ class ReportGenerator { orderedRowData.add(null); } orderedRowData.add(makeCommaSeparatedList(getTags())); - + } else if (ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == getArtifact().getArtifactTypeID()) { String[] attributeDataArray = new String[3]; // Array is used so that the order of the attributes is @@ -1913,26 +1928,27 @@ class ReportGenerator { } else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))) { String pathToShow = attr.getDisplayString(); if (pathToShow.isEmpty()) { - pathToShow = getFileUniquePath(getObjectID()); + pathToShow = getFileUniquePath(getContent()); } attributeDataArray[2] = pathToShow; } } orderedRowData.addAll(Arrays.asList(attributeDataArray)); orderedRowData.add(makeCommaSeparatedList(getTags())); - + } else { if (ReportGenerator.this.columnHeaderMap.containsKey(this.artifact.getArtifactTypeID())) { - + for (Column currColumn : ReportGenerator.this.columnHeaderMap.get(this.artifact.getArtifactTypeID())) { String cellData = currColumn.getCellData(this); orderedRowData.add(cellData); } } } - + return orderedRowData; } + } /** @@ -1947,7 +1963,7 @@ class ReportGenerator { @SuppressWarnings("deprecation") private HashSet getUniqueTagNames(long artifactId) throws TskCoreException { HashSet uniqueTagNames = new HashSet<>(); - + String query = "SELECT display_name, artifact_id FROM tag_names AS tn, blackboard_artifact_tags AS bat " + //NON-NLS "WHERE tn.tag_name_id = bat.tag_name_id AND bat.artifact_id = " + artifactId; //NON-NLS @@ -1959,22 +1975,22 @@ class ReportGenerator { } catch (TskCoreException | SQLException ex) { throw new TskCoreException("Error getting tag names for artifact: ", ex); } - + return uniqueTagNames; - + } - + private interface Column { - + String getColumnHeader(); - + String getCellData(ArtifactData artData); - + Set removeTypeFromSet(Set types); } - + private class AttributeColumn implements Column { - + private String columnHeader; private BlackboardAttribute.Type attributeType; @@ -1988,102 +2004,106 @@ class ReportGenerator { this.columnHeader = Objects.requireNonNull(columnHeader); this.attributeType = attributeType; } - + @Override public String getColumnHeader() { return this.columnHeader; } - + @Override public String getCellData(ArtifactData artData) { List attributes = artData.getAttributes(); for (BlackboardAttribute attribute : attributes) { if (attribute.getAttributeType().equals(this.attributeType)) { - return attribute.getDisplayString(); + if (attribute.getAttributeType().getValueType() != BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) { + return attribute.getDisplayString(); + } else { + return ContentUtils.getStringTime(attribute.getValueLong(), artData.getContent()); + } } } return ""; } - + @Override public Set removeTypeFromSet(Set types) { types.remove(this.attributeType); return types; } } - + private class SourceFileColumn implements Column { - + private String columnHeader; - + SourceFileColumn(String columnHeader) { this.columnHeader = columnHeader; } - + @Override public String getColumnHeader() { return this.columnHeader; } - + @Override public String getCellData(ArtifactData artData) { - return getFileUniquePath(artData.getObjectID()); + return getFileUniquePath(artData.getContent()); /*else if (this.columnHeader.equals(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"))) { return makeCommaSeparatedList(artData.getTags()); } return "";*/ } - + @Override public Set removeTypeFromSet(Set types) { // This column doesn't have a type, so nothing to remove return types; } } - + private class TaggedResultsColumn implements Column { - + private String columnHeader; - + TaggedResultsColumn(String columnHeader) { this.columnHeader = columnHeader; } - + @Override public String getColumnHeader() { return this.columnHeader; } - + @Override public String getCellData(ArtifactData artData) { return makeCommaSeparatedList(artData.getTags()); } - + @Override public Set removeTypeFromSet(Set types) { // This column doesn't have a type, so nothing to remove return types; } } - + private class HeaderOnlyColumn implements Column { - + private String columnHeader; - + HeaderOnlyColumn(String columnHeader) { this.columnHeader = columnHeader; } - + @Override public String getColumnHeader() { return columnHeader; } - + @Override public String getCellData(ArtifactData artData) { throw new UnsupportedOperationException("Cannot get cell data of unspecified column"); } - + @Override public Set removeTypeFromSet(Set types) { // This column doesn't have a type, so nothing to remove From 08b34657604bf9c0bb9a6eaa2971904e89564a77 Mon Sep 17 00:00:00 2001 From: jmillman Date: Fri, 18 Mar 2016 14:22:32 -0400 Subject: [PATCH 27/77] cleanup; remove dead code --- .../autopsy/timeline/OpenTimelineAction.java | 2 +- .../autopsy/timeline/TimeLineController.java | 58 +++++-------------- 2 files changed, 14 insertions(+), 46 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/OpenTimelineAction.java b/Core/src/org/sleuthkit/autopsy/timeline/OpenTimelineAction.java index 73d58e49ac..2fed7f5c6a 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/OpenTimelineAction.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/OpenTimelineAction.java @@ -80,7 +80,7 @@ public class OpenTimelineAction extends CallableSystemAction { if (timeLineController == null) { timeLineController = new TimeLineController(currentCase); } else if (timeLineController.getAutopsyCase() != currentCase) { - timeLineController.closeTimeLine(); + timeLineController.shutDownTimeLine(); timeLineController = new TimeLineController(currentCase); } timeLineController.openTimeLine(); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index abfa02a5f3..b5ca76f38c 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014-2015 Basis Technology Corp. + * Copyright 2014-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,8 +22,6 @@ import java.awt.HeadlessException; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; -import java.sql.ResultSet; -import java.sql.SQLException; import java.time.ZoneId; import java.util.ArrayList; import java.util.Collection; @@ -82,9 +80,6 @@ import org.sleuthkit.autopsy.timeline.utils.IntervalUtils; import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD; import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel; import org.sleuthkit.autopsy.timeline.zooming.ZoomParams; -import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; -import org.sleuthkit.datamodel.TskCoreException; /** * Controller in the MVC design along with model = {@link FilteredEventsModel} @@ -155,10 +150,10 @@ public class TimeLineController { private final PerCaseTimelineProperties perCaseTimelineProperties; @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - private final ObservableList quickHideMaskFilters = FXCollections.observableArrayList(); + private final ObservableList quickHideFilters = FXCollections.observableArrayList(); public ObservableList getQuickHideFilters() { - return quickHideMaskFilters; + return quickHideFilters; } /** @@ -216,13 +211,12 @@ public class TimeLineController { @GuardedBy("this") private final ReadOnlyObjectWrapper currentParams = new ReadOnlyObjectWrapper<>(); - //all members should be access with the intrinsict lock of this object held //selected events (ie shown in the result viewer) @GuardedBy("this") private final ObservableList selectedEventIDs = FXCollections.synchronizedObservableList(FXCollections.observableArrayList()); /** - * @return an unmodifiable list of the selected event ids + * @return a list of the selected event ids */ synchronized public ObservableList getSelectedEventIDs() { return selectedEventIDs; @@ -249,7 +243,7 @@ public class TimeLineController { synchronized public ReadOnlyBooleanProperty getCanRetreat() { return historyManager.getCanRetreat(); } - private final ReadOnlyBooleanWrapper eventsDBStale = new ReadOnlyBooleanWrapper(false); + private final ReadOnlyBooleanWrapper eventsDBStale = new ReadOnlyBooleanWrapper(true); private final PromptDialogManager promptDialogManager = new PromptDialogManager(this); @@ -362,7 +356,7 @@ public class TimeLineController { } @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - public void closeTimeLine() { + public void shutDownTimeLine() { if (mainFrame != null) { listeningToAutopsy = false; IngestManager.getInstance().removeIngestModuleEventListener(ingestModuleListener); @@ -432,7 +426,6 @@ public class TimeLineController { return false; } - @SuppressWarnings("deprecation") // TODO (EUR-733): Do not use SleuthkitCase.getLastObjectId @ThreadConfined(type = ThreadConfined.ThreadType.ANY) @NbBundle.Messages({"TimeLineController.errorTitle=Timeline error.", "TimeLineController.outOfDate.errorMessage=Error determing if the timeline is out of date. We will assume it should be updated. See the logs for more details.", @@ -442,8 +435,9 @@ public class TimeLineController { "TimeLineController.rebuildReasons.incompleteOldSchema=The Timeline events database was previously populated without incomplete information: Some features may be unavailable or non-functional unless you update the events database."}) private ArrayList getRebuildReasons() { ArrayList rebuildReasons = new ArrayList<>(); - //if ingest was running during last rebuild, prompt to rebuild + try { + //if ingest was running during last rebuild, prompt to rebuild if (perCaseTimelineProperties.wasIngestRunning()) { rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_ingestWasRunning()); } @@ -465,21 +459,6 @@ public class TimeLineController { return rebuildReasons; } - public static long getCaseLastArtifactID(final SleuthkitCase sleuthkitCase) { - //TODO: push this into sleuthkitCase - long caseLastArtfId = -1; - String query = "select Max(artifact_id) as max_id from blackboard_artifacts"; // NON-NLS //NOI18N - try (CaseDbQuery dbQuery = sleuthkitCase.executeQuery(query)) { - ResultSet resultSet = dbQuery.getResultSet(); - while (resultSet.next()) { - caseLastArtfId = resultSet.getLong("max_id"); // NON-NLS //NOI18N - } - } catch (TskCoreException | SQLException ex) { - LOGGER.log(Level.SEVERE, "Error getting last artifact id: ", ex); // NON-NLS //NOI18N - } - return caseLastArtfId; - } - /** * request a time range the same length as the given period and centered * around the middle of the currently selected range @@ -803,7 +782,6 @@ public class TimeLineController { break; } } - } @Immutable @@ -826,36 +804,26 @@ public class TimeLineController { public void propertyChange(PropertyChangeEvent evt) { switch (Case.Events.valueOf(evt.getPropertyName())) { case BLACKBOARD_ARTIFACT_TAG_ADDED: - executor.submit(() -> { - filteredEvents.handleArtifactTagAdded((BlackBoardArtifactTagAddedEvent) evt); - }); + executor.submit(() -> filteredEvents.handleArtifactTagAdded((BlackBoardArtifactTagAddedEvent) evt)); break; case BLACKBOARD_ARTIFACT_TAG_DELETED: - executor.submit(() -> { - filteredEvents.handleArtifactTagDeleted((BlackBoardArtifactTagDeletedEvent) evt); - }); + executor.submit(() -> filteredEvents.handleArtifactTagDeleted((BlackBoardArtifactTagDeletedEvent) evt)); break; case CONTENT_TAG_ADDED: - executor.submit(() -> { - filteredEvents.handleContentTagAdded((ContentTagAddedEvent) evt); - }); + executor.submit(() -> filteredEvents.handleContentTagAdded((ContentTagAddedEvent) evt)); break; case CONTENT_TAG_DELETED: - executor.submit(() -> { - filteredEvents.handleContentTagDeleted((ContentTagDeletedEvent) evt); - }); + executor.submit(() -> filteredEvents.handleContentTagDeleted((ContentTagDeletedEvent) evt)); break; case DATA_SOURCE_ADDED: Platform.runLater(() -> { setEventsDBStale(true); SwingUtilities.invokeLater(TimeLineController.this::confirmOutOfDateRebuildIfWindowOpen); }); - break; - case CURRENT_CASE: OpenTimelineAction.invalidateController(); - SwingUtilities.invokeLater(TimeLineController.this::closeTimeLine); + SwingUtilities.invokeLater(TimeLineController.this::shutDownTimeLine); break; } } From fa0fc5f396d55552081aba50e28c624049802ef4 Mon Sep 17 00:00:00 2001 From: jmillman Date: Fri, 18 Mar 2016 15:43:59 -0400 Subject: [PATCH 28/77] cleanup and comments PerCaseTimelineProperties --- .../timeline/PerCaseTimelineProperties.java | 135 +++++++++++------- .../autopsy/timeline/TimeLineController.java | 2 +- 2 files changed, 85 insertions(+), 52 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/PerCaseTimelineProperties.java b/Core/src/org/sleuthkit/autopsy/timeline/PerCaseTimelineProperties.java index faeb4e3dac..6861dac340 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/PerCaseTimelineProperties.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/PerCaseTimelineProperties.java @@ -24,52 +24,86 @@ import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Objects; import java.util.Properties; import org.apache.commons.lang3.StringUtils; import org.sleuthkit.autopsy.casemodule.Case; /** - * Provides access to per-case timeline properties/settings. + * Provides access to per-case timeline properties (key-value store). */ class PerCaseTimelineProperties { - public static final String STALE_KEY = "stale"; //NON-NLS - public static final String WAS_INGEST_RUNNING_KEY = "was_ingest_running"; // NON-NLS + private static final String STALE_KEY = "stale"; //NON-NLS + private static final String WAS_INGEST_RUNNING_KEY = "was_ingest_running"; // NON-NLS - private final Case theCase; + private final Case autoCase; private final Path propertiesPath; PerCaseTimelineProperties(Case c) { - this.theCase = c; - propertiesPath = Paths.get(theCase.getModuleDirectory(), "Timeline", "timeline.properties"); //NON-NLS - } - - public synchronized boolean isDbStale() throws IOException { - String stale = getConfigSetting(STALE_KEY); - return StringUtils.isBlank(stale) ? true : Boolean.valueOf(stale); - } - - public synchronized void setDbStale(Boolean stale) throws IOException { - setConfigSetting(STALE_KEY, stale.toString()); - } - - public synchronized boolean wasIngestRunning() throws IOException { - String stale = getConfigSetting(WAS_INGEST_RUNNING_KEY); - return StringUtils.isBlank(stale) ? true : Boolean.valueOf(stale); - } - - public synchronized void setIngestRunning(Boolean stale) throws IOException { - setConfigSetting(WAS_INGEST_RUNNING_KEY, stale.toString()); + Objects.requireNonNull(c, "Case must not be null"); + this.autoCase = c; + propertiesPath = Paths.get(autoCase.getModuleDirectory(), "Timeline", "timeline.properties"); //NON-NLS } /** - * Makes a new config file of the specified name. Do not include the - * extension. + * Is the DB stale, i.e. does it need to be updated because new datasources + * (eg) have been added to the case. * - * @param moduleName - The name of the config file to make + * @return true if the db is stale * - * @return True if successfully created, false if already exists or an error - * is thrown. + * @throws IOException if there is a problem reading the state from disk + */ + public synchronized boolean isDBStale() throws IOException { + + String stale = getProperty(STALE_KEY); + return StringUtils.isBlank(stale) ? true : Boolean.valueOf(stale); + + } + + /** + * record the state of the events db as stale(true) or not stale(false). + * + * @param stale the new state of the event db. true for stale, false for not + * stale. + * + * @throws IOException if there was a problem writing the state to disk. + */ + public synchronized void setDbStale(Boolean stale) throws IOException { + setProperty(STALE_KEY, stale.toString()); + } + + /** + * Was ingest running the last time the database was updated? + * + * @return true if ingest was running the last time the db was updated + * + * @throws IOException if there was a problem reading from disk + */ + public synchronized boolean wasIngestRunning() throws IOException { + String stale = getProperty(WAS_INGEST_RUNNING_KEY); + return StringUtils.isBlank(stale) ? true : Boolean.valueOf(stale); + } + + /** + * record whether ingest was running during the last time the database was + * updated + * + * @param ingestRunning true if ingest was running + * + * @throws IOException if there was a problem writing to disk + */ + public synchronized void setIngestRunning(Boolean ingestRunning) throws IOException { + setProperty(WAS_INGEST_RUNNING_KEY, ingestRunning.toString()); + } + + /** + * Get a {@link Path} to the properties file. If the file does not exist, it + * will be created. + * + * @return the Path to the properties file. + * + * @throws IOException if there was a problem creating the properties file */ private synchronized Path getPropertiesPath() throws IOException { @@ -82,30 +116,30 @@ class PerCaseTimelineProperties { } /** - * Returns the given properties file's setting as specific by settingName. + * Returns the property with the given key. * - * @param moduleName - The name of the config file to read from. - * @param settingName - The setting name to retrieve. + * @param propertyKey - The property key to get the value for. * - * @return - the value associated with the setting. + * @return - the value associated with the property. * - * @throws IOException + * @throws IOException if there was a problem reading the property from disk */ - private synchronized String getConfigSetting(String settingName) throws IOException { - return getProperties().getProperty(settingName); + private synchronized String getProperty(String propertyKey) throws IOException { + return getProperties().getProperty(propertyKey); } /** - * Sets the given properties file to the given settings. + * Sets the given property to the given value. * - * @param moduleName - The name of the module to be written to. - * @param settingName - The name of the setting to be modified. - * @param settingVal - the value to set the setting to. + * @param propertyKey - The key of the property to be modified. + * @param propertyValue - the value to set the property to. + * + * @throws IOException if there was a problem writing the property to disk */ - private synchronized void setConfigSetting(String settingName, String settingVal) throws IOException { + private synchronized void setProperty(String propertyKey, String propertyValue) throws IOException { Path propertiesFile = getPropertiesPath(); Properties props = getProperties(propertiesFile); - props.setProperty(settingName, settingVal); + props.setProperty(propertyKey, propertyValue); try (OutputStream fos = Files.newOutputStream(propertiesFile)) { props.store(fos, ""); //NON-NLS @@ -113,26 +147,25 @@ class PerCaseTimelineProperties { } /** - * Returns the properties as specified by moduleName. + * Get a {@link Properties} object used to store the timeline properties. * - * @param moduleName - * @param propertiesFile the value of propertiesFile + * @return a properties object * - * @throws IOException - * @return the java.util.Properties + * @throws IOException if there was a problem reading the .properties file */ private synchronized Properties getProperties() throws IOException { return getProperties(getPropertiesPath()); } /** - * Returns the properties as specified by moduleName. + * Gets a {@link Properties} object populated form the given .properties + * file. * - * @param moduleName + * @param propertiesFile a path to the .properties file to load * - * @return Properties file as specified by moduleName. + * @return a properties object * - * @throws IOException + * @throws IOException if there was a problem reading the .properties file */ private synchronized Properties getProperties(final Path propertiesFile) throws IOException { try (InputStream inputStream = Files.newInputStream(propertiesFile)) { diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index b5ca76f38c..ee581fbd7d 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -250,7 +250,7 @@ public class TimeLineController { public TimeLineController(Case autoCase) throws IOException { this.autoCase = autoCase; this.perCaseTimelineProperties = new PerCaseTimelineProperties(autoCase); - eventsDBStale.set(perCaseTimelineProperties.isDbStale()); + eventsDBStale.set(perCaseTimelineProperties.isDBStale()); eventsRepository = new EventsRepository(autoCase, currentParams.getReadOnlyProperty()); /* * as the history manager's current state changes, modify the tags From ec430b951d7d4930f56090940ece58224c96a8cf Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Fri, 18 Mar 2016 16:07:49 -0400 Subject: [PATCH 29/77] Bugfixes to report generator --- .../autopsy/report/ReportGenerator.java | 488 +++++++++--------- 1 file changed, 244 insertions(+), 244 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 6bdaf6a065..ab13271eb9 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -82,20 +82,20 @@ import org.sleuthkit.datamodel.BlackboardAttribute.Type; * objects displayed using a dialog box. */ class ReportGenerator { - + private static final Logger logger = Logger.getLogger(ReportGenerator.class.getName()); - + private Case currentCase = Case.getCurrentCase(); private SleuthkitCase skCase = currentCase.getSleuthkitCase(); - + private Map tableProgress; private Map generalProgress; private Map fileProgress; private Map> columnHeaderMap; - + private String reportPath; private ReportGenerationPanel panel = new ReportGenerationPanel(); - + static final String REPORTS_DIR = "Reports"; //NON-NLS private List errorList; @@ -117,14 +117,14 @@ class ReportGenerator { return; } } - + ReportGenerator(Map tableModuleStates, Map generalModuleStates, Map fileListModuleStates) { // Create the root reports directory path of the form: /Reports/ / DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss"); Date date = new Date(); String dateNoTime = dateFormat.format(date); this.reportPath = currentCase.getReportDirectory() + File.separator + currentCase.getName() + " " + dateNoTime + File.separator; - + this.errorList = new ArrayList(); // Create the root reports directory. @@ -169,7 +169,7 @@ class ReportGenerator { } } } - + if (null != generalModuleStates) { for (Entry entry : generalModuleStates.entrySet()) { if (entry.getValue()) { @@ -183,7 +183,7 @@ class ReportGenerator { } } } - + if (null != fileListModuleStates) { for (Entry entry : fileListModuleStates.entrySet()) { if (entry.getValue()) { @@ -209,21 +209,21 @@ class ReportGenerator { dialog.setTitle(NbBundle.getMessage(this.getClass(), "ReportGenerator.displayProgress.title.text")); dialog.add(this.panel); dialog.pack(); - + panel.addCloseAction(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { dialog.dispose(); } }); - + dialog.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { panel.close(); } }); - + Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); int w = dialog.getSize().width; int h = dialog.getSize().height; @@ -279,7 +279,7 @@ class ReportGenerator { * SwingWorker to run GeneralReportModules. */ private class GeneralReportsWorker extends SwingWorker { - + @Override protected Integer doInBackground() throws Exception { for (Entry entry : generalProgress.entrySet()) { @@ -290,7 +290,7 @@ class ReportGenerator { } return 0; } - + @Override protected void done() { try { @@ -308,24 +308,24 @@ class ReportGenerator { errorList.clear(); } } - + } /** * SwingWorker to run FileReportModules. */ private class FileReportsWorker extends SwingWorker { - + private List enabledInfo = Arrays.asList(FileReportDataTypes.values()); private List fileModules = new ArrayList<>(); - + FileReportsWorker(List enabled) { enabledInfo = enabled; for (Entry entry : fileProgress.entrySet()) { fileModules.add(entry.getKey()); } } - + @Override protected Integer doInBackground() throws Exception { for (FileReportModule module : fileModules) { @@ -336,7 +336,7 @@ class ReportGenerator { NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.queryingDb.text")); } } - + List files = getFiles(); int numFiles = files.size(); for (FileReportModule module : fileModules) { @@ -345,7 +345,7 @@ class ReportGenerator { fileProgress.get(module).setIndeterminate(false); fileProgress.get(module).setMaximumProgress(numFiles); } - + int i = 0; // Add files to report. for (AbstractFile file : files) { @@ -364,7 +364,7 @@ class ReportGenerator { module.addRow(file, enabledInfo); progress.increment(); } - + if ((i % 100) == 0) { progress.updateStatusLabel( NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processingFile.text", @@ -373,13 +373,13 @@ class ReportGenerator { } i++; } - + for (FileReportModule module : fileModules) { module.endTable(); module.endReport(); fileProgress.get(module).complete(ReportStatus.COMPLETE); } - + return 0; } @@ -403,7 +403,7 @@ class ReportGenerator { return Collections.emptyList(); } } - + @Override protected void done() { try { @@ -428,13 +428,13 @@ class ReportGenerator { * content tags, and blackboard artifact tags. */ private class TableReportsWorker extends SwingWorker { - + private List tableModules = new ArrayList<>(); private List artifactTypes = new ArrayList<>(); private HashSet tagNamesFilter = new HashSet<>(); - + private List images = new ArrayList<>(); - + TableReportsWorker(Map artifactTypeSelections, Map tagNameSelections) { // Get the report modules selected by the user. for (Entry entry : tableProgress.entrySet()) { @@ -457,7 +457,7 @@ class ReportGenerator { } } } - + @Override protected Integer doInBackground() throws Exception { // Start the progress indicators for each active TableReportModule. @@ -486,7 +486,7 @@ class ReportGenerator { tableProgress.get(module).complete(ReportStatus.COMPLETE); module.endReport(); } - + return 0; } @@ -508,7 +508,7 @@ class ReportGenerator { if (tableModules.isEmpty()) { return; } - + for (TableReportModule module : tableModules) { tableProgress.get(module).updateStatusLabel( NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processing", @@ -523,9 +523,9 @@ class ReportGenerator { writeHashsetHits(tableModules, comment.toString(), tagNamesFilter); continue; } - + List artifactList = getFilteredArtifacts(type, tagNamesFilter); - + if (artifactList.isEmpty()) { continue; } @@ -558,7 +558,7 @@ class ReportGenerator { for (Column currColumn : columns) { columnHeaderNames.add(currColumn.getColumnHeader()); } - + for (TableReportModule module : tableModules) { module.startDataType(type.getDisplayName(), comment.toString()); module.startTable(columnHeaderNames); @@ -573,7 +573,7 @@ class ReportGenerator { if (rowData.isEmpty()) { continue; } - + module.addRow(rowData); } } @@ -624,7 +624,7 @@ class ReportGenerator { NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.timeCreated"), NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.size"), NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.hash"))); - + StringBuilder comment = new StringBuilder(); if (!tagNamesFilter.isEmpty()) { comment.append( @@ -647,14 +647,14 @@ class ReportGenerator { if (passesTagNamesFilter(tag.getName().getDisplayName()) == false) { continue; } - + String fileName; try { fileName = tag.getContent().getUniquePath(); } catch (TskCoreException ex) { fileName = tag.getContent().getName(); } - + ArrayList rowData = new ArrayList<>(Arrays.asList(tag.getName().getDisplayName(), fileName, tag.getComment())); for (TableReportModule module : tableModules) { // @@@ This casting is a tricky little workaround to allow the HTML report module to slip in a content hyperlink. @@ -677,7 +677,7 @@ class ReportGenerator { module.endDataType(); } } - + @Override protected void done() { try { @@ -706,7 +706,7 @@ class ReportGenerator { if (tableModules.isEmpty()) { return; } - + List tags; try { tags = Case.getCurrentCase().getServices().getTagsManager().getAllBlackboardArtifactTags(); @@ -741,7 +741,7 @@ class ReportGenerator { if (passesTagNamesFilter(tag.getName().getDisplayName()) == false) { continue; } - + List row; for (TableReportModule module : tableModules) { row = new ArrayList<>(Arrays.asList(tag.getArtifact().getArtifactTypeName(), tag.getName().getDisplayName(), tag.getComment(), tag.getContent().getName())); @@ -770,7 +770,7 @@ class ReportGenerator { private boolean passesTagNamesFilter(String tagName) { return tagNamesFilter.isEmpty() || tagNamesFilter.contains(tagName); } - + void removeCancelledTableReportModules() { Iterator iter = tableModules.iterator(); while (iter.hasNext()) { @@ -788,7 +788,7 @@ class ReportGenerator { for (TableReportModule module : tableModules) { tableProgress.get(module).updateStatusLabel( NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.createdThumb.text")); - + if (module instanceof ReportHTML) { ReportHTML htmlModule = (ReportHTML) module; htmlModule.startDataType( @@ -799,9 +799,9 @@ class ReportGenerator { emptyHeaders.add(""); } htmlModule.startTable(emptyHeaders); - + htmlModule.addThumbnailRows(images); - + htmlModule.endTable(); htmlModule.endDataType(); } @@ -824,7 +824,7 @@ class ReportGenerator { logger.log(Level.WARNING, "Error while getting content from a blackboard artifact to report on.", ex); //NON-NLS return; } - + if (file != null) { checkIfFileIsImage(file); } @@ -851,13 +851,13 @@ class ReportGenerator { * @param file */ private void checkIfFileIsImage(AbstractFile file) { - + if (file.isDir() || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) { return; } - + if (ImageUtils.thumbnailSupported(file)) { images.add(file); } @@ -869,7 +869,7 @@ class ReportGenerator { if (null == tagsNamesFilter || tagsNamesFilter.isEmpty()) { return false; } - + HashSet filteredTagNames = new HashSet<>(tagNames); filteredTagNames.retainAll(tagsNamesFilter); return filteredTagNames.isEmpty(); @@ -961,7 +961,7 @@ class ReportGenerator { logger.log(Level.SEVERE, "Failed to query keyword lists: ", ex); //NON-NLS return; } - + if (currentCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) { orderByClause = "ORDER BY convert_to(att3.value_text, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS + "convert_to(att1.value_text, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS @@ -987,7 +987,7 @@ class ReportGenerator { try (CaseDbQuery dbQuery = skCase.executeQuery(keywordsQuery)) { ResultSet resultSet = dbQuery.getResultSet(); - + String currentKeyword = ""; String currentList = ""; while (resultSet.next()) { @@ -1009,13 +1009,13 @@ class ReportGenerator { continue; } String tagsList = makeCommaSeparatedList(uniqueTagNames); - + Long objId = resultSet.getLong("obj_id"); //NON-NLS String keyword = resultSet.getString("keyword"); //NON-NLS String preview = resultSet.getString("preview"); //NON-NLS String list = resultSet.getString("list"); //NON-NLS String uniquePath = ""; - + try { AbstractFile f = skCase.getAbstractFileById(objId); if (f != null) { @@ -1062,7 +1062,7 @@ class ReportGenerator { module.startTable(columnHeaderNames); } } - + String previewreplace = EscapeUtil.escapeHtml(preview); for (TableReportModule module : tableModules) { module.addRow(Arrays.asList(new String[]{previewreplace.replaceAll(" { - + private BlackboardArtifact artifact; private List attributes; private HashSet tags; private List rowData = null; private Content content; - + ArtifactData(BlackboardArtifact artifact, List attrs, HashSet tags) { this.artifact = artifact; this.attributes = attrs; @@ -1799,23 +1799,23 @@ class ReportGenerator { logger.log(Level.SEVERE, "Could not get content from database"); } } - + public BlackboardArtifact getArtifact() { return artifact; } - + public List getAttributes() { return attributes; } - + public HashSet getTags() { return tags; } - + public long getArtifactID() { return artifact.getArtifactID(); } - + public long getObjectID() { return artifact.getObjectID(); } @@ -1893,7 +1893,7 @@ class ReportGenerator { * @throws TskCoreException */ private List getOrderedRowDataAsStrings() throws TskCoreException { - + List orderedRowData = new ArrayList<>(); if (ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID() == getArtifact().getArtifactTypeID()) { if (content != null && content instanceof AbstractFile) { @@ -1915,7 +1915,7 @@ class ReportGenerator { orderedRowData.add(null); } orderedRowData.add(makeCommaSeparatedList(getTags())); - + } else if (ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == getArtifact().getArtifactTypeID()) { String[] attributeDataArray = new String[3]; // Array is used so that the order of the attributes is @@ -1935,20 +1935,20 @@ class ReportGenerator { } orderedRowData.addAll(Arrays.asList(attributeDataArray)); orderedRowData.add(makeCommaSeparatedList(getTags())); - + } else { if (ReportGenerator.this.columnHeaderMap.containsKey(this.artifact.getArtifactTypeID())) { - + for (Column currColumn : ReportGenerator.this.columnHeaderMap.get(this.artifact.getArtifactTypeID())) { String cellData = currColumn.getCellData(this); orderedRowData.add(cellData); } } } - + return orderedRowData; } - + } /** @@ -1963,7 +1963,7 @@ class ReportGenerator { @SuppressWarnings("deprecation") private HashSet getUniqueTagNames(long artifactId) throws TskCoreException { HashSet uniqueTagNames = new HashSet<>(); - + String query = "SELECT display_name, artifact_id FROM tag_names AS tn, blackboard_artifact_tags AS bat " + //NON-NLS "WHERE tn.tag_name_id = bat.tag_name_id AND bat.artifact_id = " + artifactId; //NON-NLS @@ -1975,22 +1975,22 @@ class ReportGenerator { } catch (TskCoreException | SQLException ex) { throw new TskCoreException("Error getting tag names for artifact: ", ex); } - + return uniqueTagNames; - + } - + private interface Column { - + String getColumnHeader(); - + String getCellData(ArtifactData artData); - + Set removeTypeFromSet(Set types); } - + private class AttributeColumn implements Column { - + private String columnHeader; private BlackboardAttribute.Type attributeType; @@ -2004,12 +2004,12 @@ class ReportGenerator { this.columnHeader = Objects.requireNonNull(columnHeader); this.attributeType = attributeType; } - + @Override public String getColumnHeader() { return this.columnHeader; } - + @Override public String getCellData(ArtifactData artData) { List attributes = artData.getAttributes(); @@ -2024,27 +2024,27 @@ class ReportGenerator { } return ""; } - + @Override public Set removeTypeFromSet(Set types) { types.remove(this.attributeType); return types; } } - + private class SourceFileColumn implements Column { - + private String columnHeader; - + SourceFileColumn(String columnHeader) { this.columnHeader = columnHeader; } - + @Override public String getColumnHeader() { return this.columnHeader; } - + @Override public String getCellData(ArtifactData artData) { return getFileUniquePath(artData.getContent()); @@ -2053,57 +2053,57 @@ class ReportGenerator { } return "";*/ } - + @Override public Set removeTypeFromSet(Set types) { // This column doesn't have a type, so nothing to remove return types; } } - + private class TaggedResultsColumn implements Column { - + private String columnHeader; - + TaggedResultsColumn(String columnHeader) { this.columnHeader = columnHeader; } - + @Override public String getColumnHeader() { return this.columnHeader; } - + @Override public String getCellData(ArtifactData artData) { return makeCommaSeparatedList(artData.getTags()); } - + @Override public Set removeTypeFromSet(Set types) { // This column doesn't have a type, so nothing to remove return types; } } - + private class HeaderOnlyColumn implements Column { - + private String columnHeader; - + HeaderOnlyColumn(String columnHeader) { this.columnHeader = columnHeader; } - + @Override public String getColumnHeader() { return columnHeader; } - + @Override public String getCellData(ArtifactData artData) { throw new UnsupportedOperationException("Cannot get cell data of unspecified column"); } - + @Override public Set removeTypeFromSet(Set types) { // This column doesn't have a type, so nothing to remove From a27c09220fc82f8845060e0a8c76e8a4c4760fe5 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Fri, 18 Mar 2016 16:15:47 -0400 Subject: [PATCH 30/77] Fixed fill property map to show correct time type. --- .../autopsy/datamodel/BlackboardArtifactNode.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index fa934b113f..afeacb9a46 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -297,15 +297,8 @@ public class BlackboardArtifactNode extends DisplayableItemNode { || attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID() || attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) { continue; - } else if (attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID() - || attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID() - || attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID() - || attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED.getTypeID() - || attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_RCVD.getTypeID() - || attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID() - || attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID() - || attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID()) { - map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString()); + } else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) { + map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated)); } else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID() && attributeTypeID == ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()) { /* From 1e6673bbeefe2f076bafbe705e922596c9d364fa Mon Sep 17 00:00:00 2001 From: jmillman Date: Fri, 18 Mar 2016 16:25:27 -0400 Subject: [PATCH 31/77] cleanup and internationalize OpenTimelineAction --- .../autopsy/timeline/Bundle.properties | 4 +- .../autopsy/timeline/OpenTimelineAction.java | 50 +++++++++---------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/Bundle.properties b/Core/src/org/sleuthkit/autopsy/timeline/Bundle.properties index 9f2e0c950c..131934652e 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/Bundle.properties @@ -1,4 +1,4 @@ -CTL_MakeTimeline="Timeline" +CTL_MakeTimeline=Timeline CTL_TimeLineTopComponentAction=TimeLineTopComponent CTL_TimeLineTopComponent=Timeline Window HINT_TimeLineTopComponent=This is a Timeline window @@ -24,7 +24,5 @@ TimelinePanel.jButton7.text=3d TimelinePanel.jButton2.text=1m TimelinePanel.jButton3.text=3m TimelinePanel.jButton4.text=2w -OpenTimelineAction.title=Timeline -OpenTimeLineAction.msgdlg.text=Could not create timeline, there are no data sources. ProgressWindow.progressHeader.text=\ diff --git a/Core/src/org/sleuthkit/autopsy/timeline/OpenTimelineAction.java b/Core/src/org/sleuthkit/autopsy/timeline/OpenTimelineAction.java index 2fed7f5c6a..b766394926 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/OpenTimelineAction.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/OpenTimelineAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2013-16 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.timeline; import java.io.IOException; import java.util.logging.Level; -import javax.swing.JOptionPane; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionReferences; @@ -28,7 +27,6 @@ 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.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.core.Installer; import org.sleuthkit.autopsy.coreutils.Logger; @@ -60,39 +58,39 @@ public class OpenTimelineAction extends CallableSystemAction { return Case.isCaseOpen() && fxInited;// && Case.getCurrentCase().hasData(); } + @NbBundle.Messages({ + "OpenTimelineAction.settingsErrorMessage=Failed to initialize timeline settings.", + "OpenTimeLineAction.msgdlg.text=Could not create timeline, there are no data sources."}) @Override @ThreadConfined(type = ThreadConfined.ThreadType.AWT) public void performAction() { - //check case - if (!Case.isCaseOpen()) { - return; - } - final Case currentCase = Case.getCurrentCase(); - - if (currentCase.hasData() == false) { - JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - NbBundle.getMessage(this.getClass(), "OpenTimeLineAction.msgdlg.text")); - LOGGER.log(Level.INFO, "Could not create timeline, there are no data sources.");// NON-NLS - return; - } - try { - if (timeLineController == null) { - timeLineController = new TimeLineController(currentCase); - } else if (timeLineController.getAutopsyCase() != currentCase) { - timeLineController.shutDownTimeLine(); - timeLineController = new TimeLineController(currentCase); + Case currentCase = Case.getCurrentCase(); + if (currentCase.hasData() == false) { + MessageNotifyUtil.Message.info(Bundle.OpenTimeLineAction_msgdlg_text()); + LOGGER.log(Level.INFO, "Could not create timeline, there are no data sources.");// NON-NLS + return; } - timeLineController.openTimeLine(); - } catch (IOException iOException) { - MessageNotifyUtil.Notify.error("Timeline", "Failed to initialize timeline settings."); - LOGGER.log(Level.SEVERE, "Failed to initialize per case timeline settings."); + try { + if (timeLineController == null) { + timeLineController = new TimeLineController(currentCase); + } else if (timeLineController.getAutopsyCase() != currentCase) { + timeLineController.shutDownTimeLine(); + timeLineController = new TimeLineController(currentCase); + } + timeLineController.openTimeLine(); + } catch (IOException iOException) { + MessageNotifyUtil.Message.error(Bundle.OpenTimelineAction_settingsErrorMessage()); + LOGGER.log(Level.SEVERE, "Failed to initialize per case timeline settings.", iOException); + } + } catch (IllegalStateException e) { + //there is no case... Do nothing. } } @Override public String getName() { - return NbBundle.getMessage(TimeLineTopComponent.class, "OpenTimelineAction.title"); + return NbBundle.getMessage(OpenTimelineAction.class, "CTL_MakeTimeline"); } @Override From 43e3461ace4af7f03bf9773146a29ea924f6e40c Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Fri, 18 Mar 2016 16:34:57 -0400 Subject: [PATCH 32/77] Update ReportGenerator.java --- Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 6bdaf6a065..f2597a9701 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -51,7 +51,6 @@ import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.SwingWorker; import org.openide.filesystems.FileUtil; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.core.UserPreferences; From 581a12816fe92115c765a4bffb2142c1b5b78e37 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Fri, 18 Mar 2016 16:39:04 -0400 Subject: [PATCH 33/77] Added consistency to getContent vs this.content --- Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index f2f8d1b8e9..fed97afb85 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -1927,7 +1927,7 @@ class ReportGenerator { } else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))) { String pathToShow = attr.getDisplayString(); if (pathToShow.isEmpty()) { - pathToShow = getFileUniquePath(getContent()); + pathToShow = getFileUniquePath(content); } attributeDataArray[2] = pathToShow; } From ea212341fcc37add4a1818920d5fc74acc4b23c1 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Mon, 21 Mar 2016 13:57:57 -0400 Subject: [PATCH 34/77] Added better error message --- Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index fed97afb85..6929666658 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -684,7 +684,7 @@ class ReportGenerator { } catch (InterruptedException | ExecutionException ex) { MessageNotifyUtil.Notify.show( NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorTitle"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getLocalizedMessage(), + NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getCause().getLocalizedMessage(), MessageNotifyUtil.MessageType.ERROR); logger.log(Level.SEVERE, "failed to generate reports", ex); //NON-NLS } // catch and ignore if we were cancelled From 3c298c5967eedbce6c67e66350f5132f00e779a6 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Mon, 21 Mar 2016 14:27:46 -0400 Subject: [PATCH 35/77] Fixed error message display in table reports worker --- Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 6929666658..69e2839e6e 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -684,9 +684,10 @@ class ReportGenerator { } catch (InterruptedException | ExecutionException ex) { MessageNotifyUtil.Notify.show( NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorTitle"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getCause().getLocalizedMessage(), + NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getLocalizedMessage(), MessageNotifyUtil.MessageType.ERROR); logger.log(Level.SEVERE, "failed to generate reports", ex); //NON-NLS + logger.log(Level.SEVERE, "failed to generate reports", ex.getCause()); //NON-NLS } // catch and ignore if we were cancelled catch (java.util.concurrent.CancellationException ex) { } finally { From 68e4f094a3b939c05844b15b7382fd9b1344ff41 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Mon, 21 Mar 2016 15:07:26 -0400 Subject: [PATCH 36/77] Switched error messages --- Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 69e2839e6e..38a5931427 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -686,8 +686,8 @@ class ReportGenerator { NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorTitle"), NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getLocalizedMessage(), MessageNotifyUtil.MessageType.ERROR); - logger.log(Level.SEVERE, "failed to generate reports", ex); //NON-NLS logger.log(Level.SEVERE, "failed to generate reports", ex.getCause()); //NON-NLS + logger.log(Level.SEVERE, "failed to generate reports", ex); //NON-NLS } // catch and ignore if we were cancelled catch (java.util.concurrent.CancellationException ex) { } finally { From ca044a8cb9412f08a8c382a805cdf441b36c07cd Mon Sep 17 00:00:00 2001 From: jmillman Date: Mon, 21 Mar 2016 15:01:10 -0400 Subject: [PATCH 37/77] refactor FileTypeDetector so that detect() and getFileType() have consistent behavior except for adding the results to the case db. --- .../modules/filetypeid/FileTypeDetector.java | 97 +++++++++++-------- 1 file changed, 59 insertions(+), 38 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index e6e8269ac9..b25dda2a35 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -139,42 +139,14 @@ public class FileTypeDetector { * * @param file The file. * - * @return A MIME type name. + * @return A MIME type name. If file type could not be detected or results + * were uncertain, octet-stream is returned. * * @throws TskCoreException if detection is required and there is a problem * writing the result to the case database. */ - @SuppressWarnings("deprecation") public String getFileType(AbstractFile file) throws TskCoreException { - String mimeType = file.getMIMEType(); - if (null != mimeType) { - return mimeType; - } - - mimeType = detect(file); - Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType); - - /* - * Add the file type attribute to the general info artifact. Note that - * no property change is fired for this blackboard posting because - * general info artifacts are different from other artifacts, e.g., they - * are not displayed in the results tree. - * - * SPECIAL NOTE: Adding a file type attribute to the general info - * artifact is meant to be replaced by the use of the MIME type field of - * the AbstractFile class (tsk_files.mime_type in the case database). - * The attribute is still added here to support backward compatibility, - * but it introduces a check-then-act race condition that can lead to - * duplicate attributes. Various mitigation strategies were considered. - * It was decided to go with the policy that this method would not be - * called outside of ingest (see note in method docs), at least until - * such time as the attribute is no longer created. - */ - BlackboardArtifact getInfoArt = file.getGenInfoArtifact(); - BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType); - getInfoArt.addAttribute(batt); - - return mimeType; + return detect(file, true); } /** @@ -189,6 +161,29 @@ public class FileTypeDetector { * @throws TskCoreException */ public String detect(AbstractFile file) throws TskCoreException { + return detect(file, false); + } + + /** + * Detects the MIME type of a file. The result is posted to the blackboard + * only if the postToBlackBoard parameter is true. + * + * @param file The file to test. + * @param postToBlackBoard Whether the MIME type should be posted to the + * blackboard. + * + * @return A MIME type name. If file type could not be detected or results + * were uncertain, octet-stream is returned. + * + * @throws TskCoreException + */ + private String detect(AbstractFile file, boolean postToBlackBoard) throws TskCoreException { + String mimeType = file.getMIMEType(); + + if (null != mimeType) { + return mimeType; + } + /* * Mark non-regular files (refer to TskData.TSK_FS_META_TYPE_ENUM), * zero-sized files, unallocated space, and unused blocks (refer to @@ -204,7 +199,7 @@ public class FileTypeDetector { /* * Give precedence to user-defined types. */ - String mimeType = detectUserDefinedType(file); + mimeType = detectUserDefinedType(file, postToBlackBoard); if (null == mimeType) { /* * The file does not match a user-defined type. Send the initial @@ -237,25 +232,51 @@ public class FileTypeDetector { mimeType = MimeTypes.OCTET_STREAM; } } + Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType); + + /* + * Add the file type attribute to the general info artifact. Note that + * no property change is fired for this blackboard posting because + * general info artifacts are different from other artifacts, e.g., they + * are not displayed in the results tree. + * + * SPECIAL NOTE: Adding a file type attribute to the general info + * artifact is meant to be replaced by the use of the MIME type field of + * the AbstractFile class (tsk_files.mime_type in the case database). + * The attribute is still added here to support backward compatibility, + * but it introduces a check-then-act race condition that can lead to + * duplicate attributes. Various mitigation strategies were considered. + * It was decided to go with the policy that this method would not be + * called outside of ingest (see note in method docs), at least until + * such time as the attribute is no longer created. + */ + if (postToBlackBoard) { + BlackboardArtifact getInfoArt = file.getGenInfoArtifact(); + @SuppressWarnings("deprecation") //we are maintaining the file type attribute on the gen info artifact for backward compatibility + BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType); + getInfoArt.addAttribute(batt); + } return mimeType; } /** * Determines whether or not the a file matches a user-defined or Autopsy - * predefined file type. If a match is found and the file type definition - * calls for an alert on a match, an interesting file hit artifact is posted - * to the blackboard. + * predefined file type. If postToBlackBoard is true, and a match is found, + * and the file type definition calls for an alert on a match, an + * interesting file hit artifact is posted to the blackboard. * - * @param file The file to test. + * @param file The file to test. + * @param postToBlackBoard Whether an interesting file hit could be posted + * to the blackboard. * * @return The file type name string or null, if no match is detected. * * @throws TskCoreException */ - private String detectUserDefinedType(AbstractFile file) throws TskCoreException { + private String detectUserDefinedType(AbstractFile file, boolean postToBlackBoard) throws TskCoreException { for (FileType fileType : userDefinedFileTypes) { if (fileType.matches(file)) { - if (fileType.alertOnMatch()) { + if (postToBlackBoard && fileType.alertOnMatch()) { /* * Create an interesting file hit artifact. */ From 94947d154c54e6749698f2b495410cf567f15e43 Mon Sep 17 00:00:00 2001 From: jmillman Date: Mon, 21 Mar 2016 15:34:39 -0400 Subject: [PATCH 38/77] document TskCoreException --- .../autopsy/modules/filetypeid/FileTypeDetector.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index b25dda2a35..89a3832996 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -158,7 +158,8 @@ public class FileTypeDetector { * @return A MIME type name. If file type could not be detected or results * were uncertain, octet-stream is returned. * - * @throws TskCoreException + * @throws TskCoreException If there is a problem writing the result to the + * case database. */ public String detect(AbstractFile file) throws TskCoreException { return detect(file, false); @@ -175,7 +176,8 @@ public class FileTypeDetector { * @return A MIME type name. If file type could not be detected or results * were uncertain, octet-stream is returned. * - * @throws TskCoreException + * @throws TskCoreException If there is a problem writing the result to the + * case database. */ private String detect(AbstractFile file, boolean postToBlackBoard) throws TskCoreException { String mimeType = file.getMIMEType(); From 419f2409a858c1fac80fa26374f1db001df4f4ba Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Mon, 21 Mar 2016 17:25:02 -0400 Subject: [PATCH 39/77] Replace deprecated SleuthkitCase method call in ExternalResultsReporter --- .../ExternalResultsImporter.java | 58 +++++++------------ 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/externalresults/ExternalResultsImporter.java b/Core/src/org/sleuthkit/autopsy/externalresults/ExternalResultsImporter.java index f2f7f39797..9deeb0e841 100644 --- a/Core/src/org/sleuthkit/autopsy/externalresults/ExternalResultsImporter.java +++ b/Core/src/org/sleuthkit/autopsy/externalresults/ExternalResultsImporter.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,7 +26,6 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.logging.Level; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.Blackboard; @@ -34,7 +33,6 @@ import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.coreutils.ErrorInfo; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.ingest.IngestModule; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; @@ -69,11 +67,12 @@ public final class ExternalResultsImporter { * Import results generated by a process external to Autopsy into Autopsy. * * @param results A standard representation of results data (e.g., - * artifacts, derived files, reports)from the data source. + * artifacts, derived files, reports)from the data source. * * @return A collection of error messages, possibly empty. The error - * messages are already logged but are provided to allow the caller to - * provide additional user feedback via the Autopsy user interface. + * messages are already logged but are provided to allow the caller + * to provide additional user feedback via the Autopsy user + * interface. */ public List importResults(ExternalResults results) { blackboard = Case.getCurrentCase().getServices().getBlackboard(); @@ -133,7 +132,7 @@ public final class ExternalResultsImporter { for (ExternalResults.Artifact artifactData : results.getArtifacts()) { try { // Add the artifact to the case database. - int artifactTypeId = caseDb.getArtifactTypeID(artifactData.getType()); + int artifactTypeId = caseDb.getArtifactType(artifactData.getType()).getTypeID(); if (artifactTypeId == -1) { artifactTypeId = caseDb.addBlackboardArtifactType(artifactData.getType(), artifactData.getType()).getTypeID(); } @@ -147,20 +146,20 @@ public final class ExternalResultsImporter { BlackboardAttribute.Type attributeType = caseDb.getAttributeType(attributeData.getType()); if (attributeType == null) { switch (attributeData.getValueType()) { - case "text": //NON-NLS - attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("String"), attributeData.getType()); //NON-NLS - break; - case "int32": //NON-NLS - attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("Integer"), attributeData.getType()); //NON-NLS - break; - case "int64": //NON-NLS - attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("Long"), attributeData.getType()); //NON-NLS - break; - case "double": //NON-NLS - attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("Double"), attributeData.getType()); //NON-NLS - break; - case "datetime": //NON-NLS - attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("DateTime"), attributeData.getType()); //NON-NLS + case "text": //NON-NLS + attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("String"), attributeData.getType()); //NON-NLS + break; + case "int32": //NON-NLS + attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("Integer"), attributeData.getType()); //NON-NLS + break; + case "int64": //NON-NLS + attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("Long"), attributeData.getType()); //NON-NLS + break; + case "double": //NON-NLS + attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("Double"), attributeData.getType()); //NON-NLS + break; + case "datetime": //NON-NLS + attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("DateTime"), attributeData.getType()); //NON-NLS } } @@ -216,13 +215,7 @@ public final class ExternalResultsImporter { ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage); this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage)); } - } catch (TskCoreException ex) { - String errorMessage = NbBundle.getMessage(this.getClass(), - "ExternalResultsImporter.importArtifacts.errMsg2.text", - artifactData.getType(), artifactData.getSourceFilePath()); - ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage, ex); - this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage, ex)); - } catch (TskDataException ex) { + } catch (TskCoreException | TskDataException ex) { String errorMessage = NbBundle.getMessage(this.getClass(), "ExternalResultsImporter.importArtifacts.errMsg2.text", artifactData.getType(), artifactData.getSourceFilePath()); @@ -299,15 +292,6 @@ public final class ExternalResultsImporter { return relativePath; } -// private static boolean isStandardArtifactType(int artifactTypeId) { -// for (BlackboardArtifact.ARTIFACT_TYPE art : BlackboardArtifact.ARTIFACT_TYPE.values()) { -// if (art.getTypeID() == artifactTypeId) { -// return true; -// } -// } -// return false; -// } -// private void recordError(String errorMessage) { ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage); this.errors.add(new ErrorInfo(this.getClass().getName(), errorMessage)); From f9277249cf31c05d54d2aefb1897ea74d0e0d1d8 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Mon, 21 Mar 2016 17:27:58 -0400 Subject: [PATCH 40/77] Cleanup/document report gen panels, disable cancel button when already cancelled --- .../autopsy/report/Bundle.properties | 6 +- .../autopsy/report/Bundle_ja.properties | 476 +++++++++--------- .../autopsy/report/ReportGenerationPanel.form | 105 +--- .../autopsy/report/ReportGenerationPanel.java | 139 +++-- .../autopsy/report/ReportProgressPanel.form | 26 +- .../autopsy/report/ReportProgressPanel.java | 370 ++++++-------- 6 files changed, 493 insertions(+), 629 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties index d535c310f4..8bafc2aa3a 100644 --- a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties @@ -14,9 +14,6 @@ ArtifactSelectionDialog.selectAllButton.text=Select All ReportGenerationPanel.closeButton.text=Close ReportProgressPanel.reportLabel.text=reportLabel ReportProgressPanel.pathLabel.text=pathLabel -ReportProgressPanel.separationLabel.text=- -ReportProgressPanel.processingLabel.text=processingLabel -ReportGenerationPanel.titleLabel.text=Report Generation Progress ReportVisualPanel2.taggedResultsRadioButton.text=Tagged Results ReportVisualPanel2.allResultsRadioButton.text=All Results ReportWizardFileOptionsVisualPanel.selectAllButton.text=Select All @@ -206,10 +203,8 @@ ReportProgressPanel.initPathLabel.noFile=No report file ReportProgressPanel.start.cancelButton.text=Cancel ReportProgressPanel.start.progress.text=Starting report... ReportProgressPanel.complete.processLbl.text=Complete -ReportProgressPanel.complete.processLb2.text=Completed with error ReportProgressPanel.complete.cancelButton.text=Complete ReportProgressPanel.cancel.cancelButton.toolTipText=Canceled -ReportProgressPanel.cancel.procLbl.text=Canceled ReportVisualPanel1.getName.text=Select and Configure Report Modules ReportVisualPanel2.getName.text=Configure Artifact Reports ReportWizardAction.actionName.text=Generate Report @@ -249,3 +244,4 @@ ReportKML.latLongStartPoint={0};{1};;{2} (Start)\n ReportKML.latLongEndPoint={0};{1};;{2} (End)\n ReportGenerationPanel.cancelButton.actionCommand=Cancel ReportGenerationPanel.cancelButton.text=Cancel +ReportProgressPanel.separationLabel.text=: diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties index bc76fbb82f..aae60084fb 100644 --- a/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties @@ -1,247 +1,243 @@ -OpenIDE-Module-Name=\u30EC\u30DD\u30FC\u30C8 -CTL_ReportWizardAction=\u30EC\u30DD\u30FC\u30C8\u3092\u5B9F\u884C -ArtifactSelectionDialog.titleLabel.text=\u3069\u306E\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u306B\u3064\u3044\u3066\u30EC\u30DD\u30FC\u30C8\u3059\u308B\u304B\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044\uFF1A +OpenIDE-Module-Name=\u30ec\u30dd\u30fc\u30c8 +CTL_ReportWizardAction=\u30ec\u30dd\u30fc\u30c8\u3092\u5b9f\u884c +ArtifactSelectionDialog.titleLabel.text=\u3069\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306b\u3064\u3044\u3066\u30ec\u30dd\u30fc\u30c8\u3059\u308b\u304b\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\uff1a ArtifactSelectionDialog.okButton.text=OK -ReportVisualPanel1.reportModulesLabel.text=\u30EC\u30DD\u30FC\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\uFF1A -DefaultReportConfigurationPanel.infoLabel.text=\u3053\u306E\u30EC\u30DD\u30FC\u30C8\u306F\u6B21\u306E\u30B9\u30AF\u30EA\u30FC\u30F3\u3067\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002 -ReportVisualPanel2.dataLabel.text=\u3069\u306E\u30C7\u30FC\u30BF\u306B\u3064\u3044\u3066\u30EC\u30DD\u30FC\u30C8\u3059\u308B\u304B\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044\uFF1A -ReportVisualPanel2.deselectAllButton.text=\u5168\u3066\u9078\u629E\u89E3\u9664 -ReportVisualPanel2.selectAllButton.text=\u5168\u3066\u9078\u629E -ReportVisualPanel2.advancedButton.text=\u30C7\u30FC\u30BF\u30BF\u30A4\u30D7 -ArtifactSelectionDialog.deselectAllButton.text=\u5168\u3066\u9078\u629E\u89E3\u9664 -ArtifactSelectionDialog.selectAllButton.text=\u5168\u3066\u9078\u629E -ReportGenerationPanel.closeButton.text=\u9589\u3058\u308B -ReportProgressPanel.reportLabel.text=\u30EC\u30DD\u30FC\u30C8\u30E9\u30D9\u30EB -ReportProgressPanel.pathLabel.text=\u30D1\u30B9\u30E9\u30D9\u30EB -ReportProgressPanel.separationLabel.text=- -ReportProgressPanel.processingLabel.text=\u30D7\u30ED\u30BB\u30B7\u30F3\u30B0\u30E9\u30D9\u30EB -ReportGenerationPanel.titleLabel.text=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u30D7\u30ED\u30B0\u30EC\u30B9 -ReportVisualPanel2.taggedResultsRadioButton.text=\u30BF\u30B0\u3055\u308C\u305F\u7D50\u679C -ReportVisualPanel2.allResultsRadioButton.text=\u5168\u3066\u306E\u7D50\u679C -ReportWizardFileOptionsVisualPanel.selectAllButton.text=\u5168\u3066\u9078\u629E -ReportWizardFileOptionsVisualPanel.deselectAllButton.text=\u5168\u3066\u9078\u629E\u89E3\u9664 -ReportWizardFileOptionsVisualPanel.jLabel1.text=\u30D5\u30A1\u30A4\u30EB\u30EC\u30DD\u30FC\u30C8\u306B\u542B\u3081\u308B\u30A2\u30A4\u30C6\u30E0\u3092\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044\uFF1A -ArtifactSelectionDialog.dlgTitle.text=\u30A2\u30C9\u30D0\u30F3\u30B9\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u9078\u629E -FileReportDataTypes.filename.text=\u540D\u524D -FileReportDataTypes.fileExt.text=\u30D5\u30A1\u30A4\u30EB\u62E1\u5F35\u5B50 -FileReportDataTypes.fileType.text=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7 -FileReportDataTypes.isDel.text=\u306F\u524A\u9664\u3055\u308C\u307E\u3057\u305F -FileReportDataTypes.aTime.text=\u6700\u5F8C\u306E\u30A2\u30AF\u30BB\u30B9 -FileReportDataTypes.crTime.text=\u4F5C\u6210\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB -FileReportDataTypes.mTime.text=\u6700\u5F8C\u306E\u4FEE\u6B63 -FileReportDataTypes.size.text=\u30B5\u30A4\u30BA -FileReportDataTypes.address.text=\u30A2\u30C9\u30EC\u30B9 -FileReportDataTypes.hash.text=\u30CF\u30C3\u30B7\u30E5\u5024 -FileReportDataTypes.knownStatus.text=\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9 -FileReportDataTypes.perms.text=\u30D1\u30FC\u30DF\u30C3\u30B7\u30E7\u30F3 -FileReportDataTypes.path.text=\u30D5\u30EB\u30D1\u30B9 -FileReportText.getName.text=\u30D5\u30A1\u30A4\u30EB - \u30C6\u30AD\u30B9\u30C8 -FileReportText.getDesc.text=\u30B1\u30FC\u30B9\u306E\u500B\u5225\u30D5\u30A1\u30A4\u30EB\u306B\u3064\u3044\u3066\u306E\u60C5\u5831\u3092\u6301\u3064\u3001\u30BF\u30D6\u533A\u5207\u308A\u30C6\u30AD\u30B9\u30C8\u30D5\u30A1\u30A4\u30EB\u3002 -ReportBodyFile.progress.querying=\u30D5\u30A1\u30A4\u30EB\u306E\u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u4E2D\u2026 -ReportBodyFile.ingestWarning.text=\u8B66\u544A\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B5\u30FC\u30D3\u30B9\u304C\u5B8C\u4E86\u3059\u308B\u524D\u306B\u30EC\u30DD\u30FC\u30C8\u304C\u5B9F\u884C\u3055\u308C\u307E\u3057\u305F\uFF01 -ReportBodyFile.progress.loading=\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u307F\u8FBC\u307F\u4E2D\u2026 -ReportBodyFile.progress.processing={0}\u3092\u51E6\u7406\u4E2D\u2026 -ReportBodyFile.getName.text=TSK\u30DC\u30C7\u30A3\u30D5\u30A1\u30A4\u30EB -ReportBodyFile.getDesc.text=\u5404\u30D5\u30A1\u30A4\u30EB\u306EMAC\u30BF\u30A4\u30E0\u3092\u542B\u3080\u3001\u30DC\u30C7\u30A3\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F\u30EC\u30DD\u30FC\u30C8\u3002\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30D3\u30E5\u30FC\u306B\u3053\u306E\u5F62\u5F0F\u3092\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002 +ReportVisualPanel1.reportModulesLabel.text=\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\uff1a +DefaultReportConfigurationPanel.infoLabel.text=\u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306f\u6b21\u306e\u30b9\u30af\u30ea\u30fc\u30f3\u3067\u8a2d\u5b9a\u3055\u308c\u307e\u3059\u3002 +ReportVisualPanel2.dataLabel.text=\u3069\u306e\u30c7\u30fc\u30bf\u306b\u3064\u3044\u3066\u30ec\u30dd\u30fc\u30c8\u3059\u308b\u304b\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\uff1a +ReportVisualPanel2.deselectAllButton.text=\u5168\u3066\u9078\u629e\u89e3\u9664 +ReportVisualPanel2.selectAllButton.text=\u5168\u3066\u9078\u629e +ReportVisualPanel2.advancedButton.text=\u30c7\u30fc\u30bf\u30bf\u30a4\u30d7 +ArtifactSelectionDialog.deselectAllButton.text=\u5168\u3066\u9078\u629e\u89e3\u9664 +ArtifactSelectionDialog.selectAllButton.text=\u5168\u3066\u9078\u629e +ReportGenerationPanel.closeButton.text=\u9589\u3058\u308b +ReportProgressPanel.reportLabel.text=\u30ec\u30dd\u30fc\u30c8\u30e9\u30d9\u30eb +ReportProgressPanel.pathLabel.text=\u30d1\u30b9\u30e9\u30d9\u30eb +ReportVisualPanel2.taggedResultsRadioButton.text=\u30bf\u30b0\u3055\u308c\u305f\u7d50\u679c +ReportVisualPanel2.allResultsRadioButton.text=\u5168\u3066\u306e\u7d50\u679c +ReportWizardFileOptionsVisualPanel.selectAllButton.text=\u5168\u3066\u9078\u629e +ReportWizardFileOptionsVisualPanel.deselectAllButton.text=\u5168\u3066\u9078\u629e\u89e3\u9664 +ReportWizardFileOptionsVisualPanel.jLabel1.text=\u30d5\u30a1\u30a4\u30eb\u30ec\u30dd\u30fc\u30c8\u306b\u542b\u3081\u308b\u30a2\u30a4\u30c6\u30e0\u3092\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\uff1a +ArtifactSelectionDialog.dlgTitle.text=\u30a2\u30c9\u30d0\u30f3\u30b9\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u9078\u629e +FileReportDataTypes.filename.text=\u540d\u524d +FileReportDataTypes.fileExt.text=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50 +FileReportDataTypes.fileType.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7 +FileReportDataTypes.isDel.text=\u306f\u524a\u9664\u3055\u308c\u307e\u3057\u305f +FileReportDataTypes.aTime.text=\u6700\u5f8c\u306e\u30a2\u30af\u30bb\u30b9 +FileReportDataTypes.crTime.text=\u4f5c\u6210\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb +FileReportDataTypes.mTime.text=\u6700\u5f8c\u306e\u4fee\u6b63 +FileReportDataTypes.size.text=\u30b5\u30a4\u30ba +FileReportDataTypes.address.text=\u30a2\u30c9\u30ec\u30b9 +FileReportDataTypes.hash.text=\u30cf\u30c3\u30b7\u30e5\u5024 +FileReportDataTypes.knownStatus.text=\u65e2\u77e5\u30b9\u30c6\u30fc\u30bf\u30b9 +FileReportDataTypes.perms.text=\u30d1\u30fc\u30df\u30c3\u30b7\u30e7\u30f3 +FileReportDataTypes.path.text=\u30d5\u30eb\u30d1\u30b9 +FileReportText.getName.text=\u30d5\u30a1\u30a4\u30eb - \u30c6\u30ad\u30b9\u30c8 +FileReportText.getDesc.text=\u30b1\u30fc\u30b9\u306e\u500b\u5225\u30d5\u30a1\u30a4\u30eb\u306b\u3064\u3044\u3066\u306e\u60c5\u5831\u3092\u6301\u3064\u3001\u30bf\u30d6\u533a\u5207\u308a\u30c6\u30ad\u30b9\u30c8\u30d5\u30a1\u30a4\u30eb\u3002 +ReportBodyFile.progress.querying=\u30d5\u30a1\u30a4\u30eb\u306e\u30af\u30a8\u30ea\u3092\u5b9f\u884c\u4e2d\u2026 +ReportBodyFile.ingestWarning.text=\u8b66\u544a\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b5\u30fc\u30d3\u30b9\u304c\u5b8c\u4e86\u3059\u308b\u524d\u306b\u30ec\u30dd\u30fc\u30c8\u304c\u5b9f\u884c\u3055\u308c\u307e\u3057\u305f\uff01 +ReportBodyFile.progress.loading=\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u2026 +ReportBodyFile.progress.processing={0}\u3092\u51e6\u7406\u4e2d\u2026 +ReportBodyFile.getName.text=TSK\u30dc\u30c7\u30a3\u30d5\u30a1\u30a4\u30eb +ReportBodyFile.getDesc.text=\u5404\u30d5\u30a1\u30a4\u30eb\u306eMAC\u30bf\u30a4\u30e0\u3092\u542b\u3080\u3001\u30dc\u30c7\u30a3\u30d5\u30a1\u30a4\u30eb\u5f62\u5f0f\u30ec\u30dd\u30fc\u30c8\u3002\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30d3\u30e5\u30fc\u306b\u3053\u306e\u5f62\u5f0f\u3092\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002 ReportBodyFile.getFilePath.text=BodyFile.txt -ReportBranding.defaultReportTitle.text=Autopsy\u30D5\u30A9\u30EC\u30F3\u30B8\u30C3\u30AF\u30EC\u30DD\u30FC\u30C8 -ReportBranding.defaultReportFooter.text=Autopsy\u30AA\u30FC\u30D7\u30F3\u30BD\u30FC\u30B9\u30FB\u30C7\u30B8\u30BF\u30EB\u30FB\u30D5\u30A9\u30EC\u30F3\u30B8\u30C3\u30AF\u30FB\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u306B\u3088\u308A\u63D0\u4F9B - www.sleuthkit.org -ReportExcel.numAartifacts.text=\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u6570\uFF1A -ReportExcel.getName.text=\u7D50\u679C - Excel -ReportExcel.getDesc.text=\u7D50\u679C\u306B\u95A2\u3059\u308B\u30EC\u30DD\u30FC\u30C8\u3002Excel(XLS)\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u3067\u30A2\u30A4\u30C6\u30E0\u306E\u30BF\u30B0\u4ED8\u3051\u304C\u3055\u308C\u3066\u3044\u307E\u3059\u3002 -ReportExcel.sheetName.text=\u30B5\u30DE\u30EA\u30FC -ReportExcel.cellVal.summary=\u30B5\u30DE\u30EA\u30FC -ReportExcel.cellVal.caseName=\u30B1\u30FC\u30B9\u540D\uFF1A -ReportExcel.cellVal.caseNum=\u30B1\u30FC\u30B9\u756A\u53F7\uFF1A -ReportExcel.cellVal.examiner=\u8ABF\u67FB\u62C5\u5F53\u8005\uFF1A -ReportExcel.cellVal.numImages=\u30A4\u30E1\u30FC\u30B8\u6570\uFF1A -ReportGenerationPanel.confDlg.sureToClose.msg=\u3053\u306E\u30C0\u30A4\u30A2\u30ED\u30B0\u3092\u672C\u5F53\u306B\u9589\u3058\u307E\u3059\u304B\uFF1F\n\u5168\u3066\u306E\u30EC\u30DD\u30FC\u30C8\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3059\u3002 -ReportGenerationPanel.confDlg.title.closing=\u9589\u3058\u3066\u3044\u307E\u3059 -ReportGenerator.displayProgress.title.text=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u30D7\u30ED\u30B0\u30EC\u30B9\u2026 -ReportGenerator.progress.queryingDb.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u4E2D\u2026 -ReportGenerator.progress.processingFile.text={0}\u3092\u51E6\u7406\u4E2D -ReportGenerator.artifactTable.taggedResults.text=\u6B21\u306E\u4E2D\u306E\u4E00\u3064\u3067\u30BF\u30B0\u3055\u308C\u305F\u7D50\u679C\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\uFF1A -ReportGenerator.progress.processing={0}\u3092\u51E6\u7406\u4E2D\u2026 -ReportGenerator.msgShow.skippingArtType.title=\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u30BF\u30A4\u30D7{0}\u3092\u30EC\u30DD\u30FC\u30C8\u3067\u30B9\u30AD\u30C3\u30D7\u3057\u3066\u3044\u307E\u3059 -ReportGenerator.msgShow.skippingArtType.msg=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u3059\u308B\u306E\u306B\u4E0D\u660E\u306A\u30B3\u30E9\u30E0 -ReportGenerator.msgShow.skippingArtRow.title=\u30BF\u30A4\u30D7{0}\u306E\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u884C\u3092\u30EC\u30DD\u30FC\u30C8\u3067\u30B9\u30AD\u30C3\u30D7\u3057\u3066\u3044\u307E\u3059 -ReportGenerator.msgShow.skippingArtRow.msg=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u3059\u308B\u306E\u306B\u4E0D\u660E\u306A\u30B3\u30E9\u30E0 -ReportGenerator.makeContTagTab.taggedFiles.msg=\u306E\u4E2D\u306E\u4E00\u3064\u3067\u30BF\u30B0\u3055\u308C\u305F\u7D50\u679C\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\uFF1A -ReportGenerator.makeBbArtTagTab.taggedRes.msg=\u3053\u306E\u30EC\u30DD\u30FC\u30C8\u306B\u306F\u6B21\u3067\u30BF\u30B0\u3055\u308C\u305F\u7D50\u679C\u3057\u304B\u542B\u307E\u308C\u307E\u305B\u3093\uFF1A -ReportGenerator.tagTable.header.resultType=\u7D50\u679C\u30BF\u30A4\u30D7 -ReportGenerator.tagTable.header.tag=\u30BF\u30B0 -ReportGenerator.tagTable.header.comment=\u30B3\u30E1\u30F3\u30C8 -ReportGenerator.tagTable.header.srcFile=\u30BD\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB -ReportGenerator.progress.createdThumb.text=\u30B5\u30E0\u30CD\u30A4\u30EB\u3092\u4F5C\u6210\u4E2D\u2026 -ReportGenerator.thumbnailTable.name=\u30B5\u30E0\u30CD\u30A4\u30EB -ReportGenerator.thumbnailTable.desc=\u30BF\u30B0\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u3084\u7D50\u679C\u306B\u95A2\u9023\u3059\u308B\u30A4\u30E1\u30FC\u30B8\u306E\u30B5\u30E0\u30CD\u30A4\u30EB\u304C\u542B\u307E\u308C\u307E\u3059\u3002 -ReportGenerator.writeKwHits.userSrchs=\u30E6\u30FC\u30B6\u691C\u7D22 -ReportGenerator.progress.processingList={0} ({1})\u3092\u51E6\u7406\u4E2D\u2026 +ReportBranding.defaultReportTitle.text=Autopsy\u30d5\u30a9\u30ec\u30f3\u30b8\u30c3\u30af\u30ec\u30dd\u30fc\u30c8 +ReportBranding.defaultReportFooter.text=Autopsy\u30aa\u30fc\u30d7\u30f3\u30bd\u30fc\u30b9\u30fb\u30c7\u30b8\u30bf\u30eb\u30fb\u30d5\u30a9\u30ec\u30f3\u30b8\u30c3\u30af\u30fb\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u306b\u3088\u308a\u63d0\u4f9b - www.sleuthkit.org +ReportExcel.numAartifacts.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u6570\uff1a +ReportExcel.getName.text=\u7d50\u679c - Excel +ReportExcel.getDesc.text=\u7d50\u679c\u306b\u95a2\u3059\u308b\u30ec\u30dd\u30fc\u30c8\u3002Excel(XLS)\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3067\u30a2\u30a4\u30c6\u30e0\u306e\u30bf\u30b0\u4ed8\u3051\u304c\u3055\u308c\u3066\u3044\u307e\u3059\u3002 +ReportExcel.sheetName.text=\u30b5\u30de\u30ea\u30fc +ReportExcel.cellVal.summary=\u30b5\u30de\u30ea\u30fc +ReportExcel.cellVal.caseName=\u30b1\u30fc\u30b9\u540d\uff1a +ReportExcel.cellVal.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a +ReportExcel.cellVal.examiner=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a +ReportExcel.cellVal.numImages=\u30a4\u30e1\u30fc\u30b8\u6570\uff1a +ReportGenerationPanel.confDlg.sureToClose.msg=\u3053\u306e\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u672c\u5f53\u306b\u9589\u3058\u307e\u3059\u304b\uff1f\n\u5168\u3066\u306e\u30ec\u30dd\u30fc\u30c8\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3059\u3002 +ReportGenerationPanel.confDlg.title.closing=\u9589\u3058\u3066\u3044\u307e\u3059 +ReportGenerator.displayProgress.title.text=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u30d7\u30ed\u30b0\u30ec\u30b9\u2026 +ReportGenerator.progress.queryingDb.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30af\u30a8\u30ea\u3092\u5b9f\u884c\u4e2d\u2026 +ReportGenerator.progress.processingFile.text={0}\u3092\u51e6\u7406\u4e2d +ReportGenerator.artifactTable.taggedResults.text=\u6b21\u306e\u4e2d\u306e\u4e00\u3064\u3067\u30bf\u30b0\u3055\u308c\u305f\u7d50\u679c\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\uff1a +ReportGenerator.progress.processing={0}\u3092\u51e6\u7406\u4e2d\u2026 +ReportGenerator.msgShow.skippingArtType.title=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30bf\u30a4\u30d7{0}\u3092\u30ec\u30dd\u30fc\u30c8\u3067\u30b9\u30ad\u30c3\u30d7\u3057\u3066\u3044\u307e\u3059 +ReportGenerator.msgShow.skippingArtType.msg=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u3059\u308b\u306e\u306b\u4e0d\u660e\u306a\u30b3\u30e9\u30e0 +ReportGenerator.msgShow.skippingArtRow.title=\u30bf\u30a4\u30d7{0}\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u884c\u3092\u30ec\u30dd\u30fc\u30c8\u3067\u30b9\u30ad\u30c3\u30d7\u3057\u3066\u3044\u307e\u3059 +ReportGenerator.msgShow.skippingArtRow.msg=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u3059\u308b\u306e\u306b\u4e0d\u660e\u306a\u30b3\u30e9\u30e0 +ReportGenerator.makeContTagTab.taggedFiles.msg=\u306e\u4e2d\u306e\u4e00\u3064\u3067\u30bf\u30b0\u3055\u308c\u305f\u7d50\u679c\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\uff1a +ReportGenerator.makeBbArtTagTab.taggedRes.msg=\u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306b\u306f\u6b21\u3067\u30bf\u30b0\u3055\u308c\u305f\u7d50\u679c\u3057\u304b\u542b\u307e\u308c\u307e\u305b\u3093\uff1a +ReportGenerator.tagTable.header.resultType=\u7d50\u679c\u30bf\u30a4\u30d7 +ReportGenerator.tagTable.header.tag=\u30bf\u30b0 +ReportGenerator.tagTable.header.comment=\u30b3\u30e1\u30f3\u30c8 +ReportGenerator.tagTable.header.srcFile=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb +ReportGenerator.progress.createdThumb.text=\u30b5\u30e0\u30cd\u30a4\u30eb\u3092\u4f5c\u6210\u4e2d\u2026 +ReportGenerator.thumbnailTable.name=\u30b5\u30e0\u30cd\u30a4\u30eb +ReportGenerator.thumbnailTable.desc=\u30bf\u30b0\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u3084\u7d50\u679c\u306b\u95a2\u9023\u3059\u308b\u30a4\u30e1\u30fc\u30b8\u306e\u30b5\u30e0\u30cd\u30a4\u30eb\u304c\u542b\u307e\u308c\u307e\u3059\u3002 +ReportGenerator.writeKwHits.userSrchs=\u30e6\u30fc\u30b6\u691c\u7d22 +ReportGenerator.progress.processingList={0} ({1})\u3092\u51e6\u7406\u4e2d\u2026 ReportGenerator.artTableColHdr.url=URL -ReportGenerator.artTableColHdr.title=\u30BF\u30A4\u30C8\u30EB -ReportGenerator.artTableColHdr.dateCreated=\u4F5C\u6210\u65E5\u4ED8 -ReportGenerator.artTableColHdr.program=\u30D7\u30ED\u30B0\u30E9\u30E0 -ReportGenerator.artTableColHdr.srcFile=\u30BD\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB -ReportGenerator.artTableColHdr.dateTime=\u65E5\u4ED8\uFF0F\u6642\u523B -ReportGenerator.artTableColHdr.name=\u540D\u524D -ReportGenerator.artTableColHdr.value=\u30D0\u30EA\u30E5\u30FC -ReportGenerator.artTableColHdr.dateAccessed=\u30A2\u30AF\u30BB\u30B9\u65E5\u4ED8 -ReportGenerator.artTableColHdr.referrer=\u30EA\u30D5\u30A1\u30E9 -ReportGenerator.artTableColHdr.dest=\u30C7\u30B9\u30C6\u30A3\u30CD\u30FC\u30B7\u30E7\u30F3 -ReportGenerator.artTableColHdr.sourceUrl=\u30BD\u30FC\u30B9URL -ReportGenerator.artTableColHdr.path=\u30D1\u30B9 -ReportGenerator.artTableColHdr.progName=\u30D7\u30ED\u30B0\u30E9\u30E0\u540D -ReportGenerator.artTableColHdr.instDateTime=\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u65E5\u4ED8\uFF0F\u6642\u523B -ReportGenerator.artTableColHdr.preview=\u30D7\u30EC\u30D3\u30E5\u30FC -ReportGenerator.artTableColHdr.file=\u30D5\u30A1\u30A4\u30EB -ReportGenerator.artTableColHdr.size=\u30B5\u30A4\u30BA -ReportGenerator.artTableColHdr.deviceId=\u6A5F\u5668ID -ReportGenerator.artTableColHdr.text=\u30C6\u30AD\u30B9\u30C8 -ReportGenerator.artTableColHdr.domain=\u30C9\u30E1\u30A4\u30F3 -ReportGenerator.artTableColHdr.devManufacturer=\u6A5F\u5668\u30E1\u30FC\u30AB\u30FC -ReportGenerator.artTableColHdr.devModel=\u6A5F\u5668\u30E2\u30C7\u30EB -ReportGenerator.artTableColHdr.personName=\u4EBA\u540D -ReportGenerator.artTableColHdr.phoneNumber=\u96FB\u8A71\u756A\u53F7 -ReportGenerator.artTableColHdr.phoneNumHome=\u96FB\u8A71\u756A\u53F7\uFF08\u81EA\u5B85\uFF09 -ReportGenerator.artTableColHdr.phoneNumOffice=\u96FB\u8A71\u756A\u53F7\uFF08\u4F1A\u793E\uFF09 -ReportGenerator.artTableColHdr.phoneNumMobile=\u96FB\u8A71\u756A\u53F7\uFF08\u643A\u5E2F\uFF09 +ReportGenerator.artTableColHdr.title=\u30bf\u30a4\u30c8\u30eb +ReportGenerator.artTableColHdr.dateCreated=\u4f5c\u6210\u65e5\u4ed8 +ReportGenerator.artTableColHdr.program=\u30d7\u30ed\u30b0\u30e9\u30e0 +ReportGenerator.artTableColHdr.srcFile=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb +ReportGenerator.artTableColHdr.dateTime=\u65e5\u4ed8\uff0f\u6642\u523b +ReportGenerator.artTableColHdr.name=\u540d\u524d +ReportGenerator.artTableColHdr.value=\u30d0\u30ea\u30e5\u30fc +ReportGenerator.artTableColHdr.dateAccessed=\u30a2\u30af\u30bb\u30b9\u65e5\u4ed8 +ReportGenerator.artTableColHdr.referrer=\u30ea\u30d5\u30a1\u30e9 +ReportGenerator.artTableColHdr.dest=\u30c7\u30b9\u30c6\u30a3\u30cd\u30fc\u30b7\u30e7\u30f3 +ReportGenerator.artTableColHdr.sourceUrl=\u30bd\u30fc\u30b9URL +ReportGenerator.artTableColHdr.path=\u30d1\u30b9 +ReportGenerator.artTableColHdr.progName=\u30d7\u30ed\u30b0\u30e9\u30e0\u540d +ReportGenerator.artTableColHdr.instDateTime=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65e5\u4ed8\uff0f\u6642\u523b +ReportGenerator.artTableColHdr.preview=\u30d7\u30ec\u30d3\u30e5\u30fc +ReportGenerator.artTableColHdr.file=\u30d5\u30a1\u30a4\u30eb +ReportGenerator.artTableColHdr.size=\u30b5\u30a4\u30ba +ReportGenerator.artTableColHdr.deviceId=\u6a5f\u5668ID +ReportGenerator.artTableColHdr.text=\u30c6\u30ad\u30b9\u30c8 +ReportGenerator.artTableColHdr.domain=\u30c9\u30e1\u30a4\u30f3 +ReportGenerator.artTableColHdr.devManufacturer=\u6a5f\u5668\u30e1\u30fc\u30ab\u30fc +ReportGenerator.artTableColHdr.devModel=\u6a5f\u5668\u30e2\u30c7\u30eb +ReportGenerator.artTableColHdr.personName=\u4eba\u540d +ReportGenerator.artTableColHdr.phoneNumber=\u96fb\u8a71\u756a\u53f7 +ReportGenerator.artTableColHdr.phoneNumHome=\u96fb\u8a71\u756a\u53f7\uff08\u81ea\u5b85\uff09 +ReportGenerator.artTableColHdr.phoneNumOffice=\u96fb\u8a71\u756a\u53f7\uff08\u4f1a\u793e\uff09 +ReportGenerator.artTableColHdr.phoneNumMobile=\u96fb\u8a71\u756a\u53f7\uff08\u643a\u5e2f\uff09 ReportGenerator.artTableColHdr.email=Email -ReportGenerator.artTableColHdr.msgType=\u30E1\u30C3\u30BB\u30FC\u30B8\u30BF\u30A4\u30D7 -ReportGenerator.artTableColHdr.latitude=\u7DEF\u5EA6 -ReportGenerator.artTableColHdr.longitude=\u7D4C\u5EA6 -ReportGenerator.artTableColHdr.dateTaken=\u64AE\u5F71\u65E5\u4ED8 -ReportGenerator.artTableColHdr.subject=\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8 -ReportGenerator.artTableColHdr.calendarEntryType=\u30AB\u30EC\u30F3\u30C0\u30FC\u30A8\u30F3\u30C8\u30EA\u30BF\u30A4\u30D7 -ReportGenerator.artTableColHdr.description=\u8AAC\u660E -ReportGenerator.artTableColHdr.startDateTime=\u958B\u59CB\u65E5\u4ED8\uFF0F\u6642\u523B -ReportGenerator.artTableColHdr.shortCut=\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8 -ReportGenerator.artTableColHdr.endDateTime=\u4FEE\u4E86\u65E5\u4ED8\uFF0F\u6642\u523B -ReportGenerator.artTableColHdr.location=\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3 -ReportGenerator.artTableColHdr.deviceName=\u6A5F\u5668\u540D -ReportGenerator.artTableColHdr.deviceAddress=\u6A5F\u5668\u30A2\u30C9\u30EC\u30B9 -ReportGenerator.artTableColHdr.altitude=\u6A19\u9AD8 -ReportGenerator.artTableColHdr.locationAddress=\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3\u30A2\u30C9\u30EC\u30B9 -ReportGenerator.artTableColHdr.category=\u30AB\u30C6\u30B4\u30EA\u30FC -ReportGenerator.artTableColHdr.userId=\u30E6\u30FC\u30B6ID -ReportGenerator.artTableColHdr.password=\u30D1\u30B9\u30EF\u30FC\u30C9 -ReportGenerator.artTableColHdr.replytoAddress=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9 -ReportGenerator.artTableColHdr.mailServer=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0 -ReportGenerator.artTableColHdr.tags=\u30BF\u30B0 -ReportHTML.addThumbRows.dataType.title=\u30BF\u30B0\u4ED8\u3051\u3055\u308C\u305F\u30A4\u30E1\u30FC\u30B8 - {0} -ReportHTML.addThumbRows.dataType.msg=\u30A4\u30E1\u30FC\u30B8\u3092\u542B\u3080\u30BF\u30B0\u4ED8\u3051\u3055\u308C\u305F\u7D50\u679C\u304A\u3088\u3073\u30B3\u30F3\u30C6\u30F3\u30C4\u3002 -ReportHTML.thumbLink.tags=\u30BF\u30B0\uFF1A -ReportHTML.getName.text=\u7D50\u679C - HTML -ReportHTML.getDesc.text=HTML\u5F62\u5F0F\u306E\u7D50\u679C\u304A\u3088\u3073\u30BF\u30B0\u4ED8\u3051\u3055\u308C\u305F\u30A2\u30A4\u30C6\u30E0\u306E\u30EC\u30DD\u30FC\u30C8 -ReportHTML.writeIndex.title=\u30B1\u30FC\u30B9{0}\u306EAutopsy\u30EC\u30DD\u30FC\u30C8 -ReportHTML.writeNav.title=\u30EC\u30DD\u30FC\u30C8\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3 -ReportHTML.writeNav.h1=\u30EC\u30DD\u30FC\u30C8\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3 -ReportHTML.writeNav.summary=\u30B1\u30FC\u30B9\u30B5\u30DE\u30EA\u30FC -ReportHTML.writeSum.title=\u30B1\u30FC\u30B9\u30B5\u30DE\u30EA\u30FC -ReportHTML.writeSum.caseName=\u30B1\u30FC\u30B9\uFF1A -ReportHTML.writeSum.caseNum=\u30B1\u30FC\u30B9\u756A\u53F7\uFF1A -ReportHTML.writeSum.examiner=\u8ABF\u67FB\u62C5\u5F53\u8005\uFF1A -ReportHTML.writeSum.numImages=\u30A4\u30E1\u30FC\u30B8\u6570\uFF1A -ReportHTML.writeSum.path=\u30D1\u30B9\uFF1A -ReportProgressPanel.start.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB -ReportProgressPanel.complete.processLbl.text=\u5B8C\u4E86 -ReportProgressPanel.complete.cancelButton.text=\u5B8C\u4E86 -ReportProgressPanel.cancel.cancelButton.toolTipText=\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F -ReportWizardAction.actionName.text=\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210 -ReportWizardAction.reportWiz.title=\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210 -ReportWizardAction.toolBarButton.text=\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210 -ReportWizardPanel1.nextButton.text=\u6B21 > -ReportWizardPanel2.nextButton.text=\u6B21 > -ReportGenerator.artTableColHdr.direction=\u65B9\u5411 -ReportGenerator.artTableColHdr.fromEmail=\u9001\u4FE1\u5143E\u30E1\u30FC\u30EB -ReportGenerator.artTableColHdr.toEmail=\u9001\u4FE1\u5148E\u30E1\u30FC\u30EB -ReportGenerator.artTableColHdr.fromPhoneNum=\u767A\u4FE1\u8005\u96FB\u8A71\u756A\u53F7 -ReportGenerator.artTableColHdr.toPhoneNum=\u7740\u4FE1\u8005\u96FB\u8A71\u756A\u53F7 -ReportGenerator.artTableColHdr.appName=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u540D -ReportGenerator.artTableColHdr.appPath=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30D1\u30B9 -ReportHTML.writeIndex.noFrames.msg=\u4F7F\u7528\u3057\u3066\u3044\u308B\u30D6\u30E9\u30A6\u30B6\u306F\u5F0A\u793E\u306E\u30D5\u30EC\u30FC\u30E0\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3068\u306E\u4E92\u63DB\u6027\u304C\u3042\u308A\u307E\u305B\u3093\u3002 -ReportHTML.writeIndex.noFrames.seeNav=\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u30EA\u30F3\u30AF\u306F\u4E0B\u8A18\u306E\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u30DA\u30FC\u30B8\u3092\u3054\u89A7\u4E0B\u3055\u3044 -ReportHTML.writeIndex.seeSum=\u307E\u305F\u3001\u30B1\u30FC\u30B9\u30B5\u30DE\u30EA\u30FC\u306F\u4E0B\u8A18\u306E\u30B5\u30DE\u30EA\u30FC\u30DA\u30FC\u30B8\u3092\u3054\u89A7\u4E0B\u3055\u3044\u3002 -ReportHTML.writeSum.warningMsg=\u8B66\u544A\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B5\u30FC\u30D3\u30B9\u304C\u5B8C\u4E86\u3059\u308B\u524D\u306B\u30EC\u30DD\u30FC\u30C8\u304C\u5B9F\u884C\u3055\u308C\u307E\u3057\u305F\uFF01 -ReportHTML.writeSum.noExaminer=\u8ABF\u67FB\u62C5\u5F53\u8005\u7121\u3057 -ReportHTML.writeSum.imageInfoHeading=

\u30A4\u30E1\u30FC\u30B8\u60C5\u5831\uFF1A

-ReportHTML.writeSum.timezone=\u30BF\u30A4\u30E0\u30BE\u30FC\u30F3\uFF1A -ReportProgressPanel.progress.queuing=\u30AD\u30E5\u30FC\u30A4\u30F3\u30B0\u2026 -ReportProgressPanel.initPathLabel.noFile=\u30EC\u30DD\u30FC\u30C8\u30D5\u30A1\u30A4\u30EB\u7121\u3057 -ReportProgressPanel.start.progress.text=\u30EC\u30DD\u30FC\u30C8\u958B\u59CB\u4E2D\u2026 -ReportProgressPanel.cancel.procLbl.text=\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F -ReportVisualPanel1.getName.text=\u30EC\u30DD\u30FC\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u9078\u629E\u304A\u3088\u3073\u8A2D\u5B9A -ReportVisualPanel2.getName.text=\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u30EC\u30DD\u30FC\u30C8\u3092\u8A2D\u5B9A -ReportWizardFileOptionsPanel.finishButton.text=\u7D42\u4E86 -ReportWizardFileOptionsVisualPanel.getName.text=\u30D5\u30A1\u30A4\u30EB\u30EC\u30DD\u30FC\u30C8\u3092\u8A2D\u5B9A -ReportWizardPanel1.finishButton.text=\u7D42\u4E86 -ReportWizardPanel2.finishButton.text=\u7D42\u4E86 -ReportHTML.writeSum.reportGenOn.text={0}\u306BHTML\u30EC\u30DD\u30FC\u30C8\u306F\u751F\u6210\u3055\u308C\u307E\u3057\u305F -ReportHTML.writeSum.noCaseNum=\u30B1\u30FC\u30B9\u756A\u53F7\u304C\u3042\u308A\u307E\u305B\u3093 -ReportGenerator.errors.reportErrorTitle=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F -ReportGenerator.errors.reportErrorText=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\uFF1A -ReportKML.getDesc.text=\u95A2\u9023\u30D5\u30A1\u30A4\u30EB\u306E\u5EA7\u6A19\u3092\u542B\u3080KML\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u306E\u30EC\u30DD\u30FC\u30C8\u3002\u3053\u306E\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u306FGoogle Earth\u30D3\u30E5\u30FC\u306B\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002 +ReportGenerator.artTableColHdr.msgType=\u30e1\u30c3\u30bb\u30fc\u30b8\u30bf\u30a4\u30d7 +ReportGenerator.artTableColHdr.latitude=\u7def\u5ea6 +ReportGenerator.artTableColHdr.longitude=\u7d4c\u5ea6 +ReportGenerator.artTableColHdr.dateTaken=\u64ae\u5f71\u65e5\u4ed8 +ReportGenerator.artTableColHdr.subject=\u30b5\u30d6\u30b8\u30a7\u30af\u30c8 +ReportGenerator.artTableColHdr.calendarEntryType=\u30ab\u30ec\u30f3\u30c0\u30fc\u30a8\u30f3\u30c8\u30ea\u30bf\u30a4\u30d7 +ReportGenerator.artTableColHdr.description=\u8aac\u660e +ReportGenerator.artTableColHdr.startDateTime=\u958b\u59cb\u65e5\u4ed8\uff0f\u6642\u523b +ReportGenerator.artTableColHdr.shortCut=\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8 +ReportGenerator.artTableColHdr.endDateTime=\u4fee\u4e86\u65e5\u4ed8\uff0f\u6642\u523b +ReportGenerator.artTableColHdr.location=\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3 +ReportGenerator.artTableColHdr.deviceName=\u6a5f\u5668\u540d +ReportGenerator.artTableColHdr.deviceAddress=\u6a5f\u5668\u30a2\u30c9\u30ec\u30b9 +ReportGenerator.artTableColHdr.altitude=\u6a19\u9ad8 +ReportGenerator.artTableColHdr.locationAddress=\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u30a2\u30c9\u30ec\u30b9 +ReportGenerator.artTableColHdr.category=\u30ab\u30c6\u30b4\u30ea\u30fc +ReportGenerator.artTableColHdr.userId=\u30e6\u30fc\u30b6ID +ReportGenerator.artTableColHdr.password=\u30d1\u30b9\u30ef\u30fc\u30c9 +ReportGenerator.artTableColHdr.replytoAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9 +ReportGenerator.artTableColHdr.mailServer=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0 +ReportGenerator.artTableColHdr.tags=\u30bf\u30b0 +ReportHTML.addThumbRows.dataType.title=\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30a4\u30e1\u30fc\u30b8 - {0} +ReportHTML.addThumbRows.dataType.msg=\u30a4\u30e1\u30fc\u30b8\u3092\u542b\u3080\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u7d50\u679c\u304a\u3088\u3073\u30b3\u30f3\u30c6\u30f3\u30c4\u3002 +ReportHTML.thumbLink.tags=\u30bf\u30b0\uff1a +ReportHTML.getName.text=\u7d50\u679c - HTML +ReportHTML.getDesc.text=HTML\u5f62\u5f0f\u306e\u7d50\u679c\u304a\u3088\u3073\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30a2\u30a4\u30c6\u30e0\u306e\u30ec\u30dd\u30fc\u30c8 +ReportHTML.writeIndex.title=\u30b1\u30fc\u30b9{0}\u306eAutopsy\u30ec\u30dd\u30fc\u30c8 +ReportHTML.writeNav.title=\u30ec\u30dd\u30fc\u30c8\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3 +ReportHTML.writeNav.h1=\u30ec\u30dd\u30fc\u30c8\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3 +ReportHTML.writeNav.summary=\u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc +ReportHTML.writeSum.title=\u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc +ReportHTML.writeSum.caseName=\u30b1\u30fc\u30b9\uff1a +ReportHTML.writeSum.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a +ReportHTML.writeSum.examiner=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a +ReportHTML.writeSum.numImages=\u30a4\u30e1\u30fc\u30b8\u6570\uff1a +ReportHTML.writeSum.path=\u30d1\u30b9\uff1a +ReportProgressPanel.start.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +ReportProgressPanel.complete.processLbl.text=\u5b8c\u4e86 +ReportProgressPanel.complete.cancelButton.text=\u5b8c\u4e86 +ReportProgressPanel.cancel.cancelButton.toolTipText=\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f +ReportWizardAction.actionName.text=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210 +ReportWizardAction.reportWiz.title=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210 +ReportWizardAction.toolBarButton.text=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210 +ReportWizardPanel1.nextButton.text=\u6b21 > +ReportWizardPanel2.nextButton.text=\u6b21 > +ReportGenerator.artTableColHdr.direction=\u65b9\u5411 +ReportGenerator.artTableColHdr.fromEmail=\u9001\u4fe1\u5143E\u30e1\u30fc\u30eb +ReportGenerator.artTableColHdr.toEmail=\u9001\u4fe1\u5148E\u30e1\u30fc\u30eb +ReportGenerator.artTableColHdr.fromPhoneNum=\u767a\u4fe1\u8005\u96fb\u8a71\u756a\u53f7 +ReportGenerator.artTableColHdr.toPhoneNum=\u7740\u4fe1\u8005\u96fb\u8a71\u756a\u53f7 +ReportGenerator.artTableColHdr.appName=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u540d +ReportGenerator.artTableColHdr.appPath=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30d1\u30b9 +ReportHTML.writeIndex.noFrames.msg=\u4f7f\u7528\u3057\u3066\u3044\u308b\u30d6\u30e9\u30a6\u30b6\u306f\u5f0a\u793e\u306e\u30d5\u30ec\u30fc\u30e0\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3068\u306e\u4e92\u63db\u6027\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +ReportHTML.writeIndex.noFrames.seeNav=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30ea\u30f3\u30af\u306f\u4e0b\u8a18\u306e\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3\u30da\u30fc\u30b8
\u3092\u3054\u89a7\u4e0b\u3055\u3044 +ReportHTML.writeIndex.seeSum=\u307e\u305f\u3001\u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc\u306f\u4e0b\u8a18\u306e\u30b5\u30de\u30ea\u30fc\u30da\u30fc\u30b8\u3092\u3054\u89a7\u4e0b\u3055\u3044\u3002 +ReportHTML.writeSum.warningMsg=\u8b66\u544a\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b5\u30fc\u30d3\u30b9\u304c\u5b8c\u4e86\u3059\u308b\u524d\u306b\u30ec\u30dd\u30fc\u30c8\u304c\u5b9f\u884c\u3055\u308c\u307e\u3057\u305f\uff01 +ReportHTML.writeSum.noExaminer=\u8abf\u67fb\u62c5\u5f53\u8005\u7121\u3057 +ReportHTML.writeSum.imageInfoHeading=

\u30a4\u30e1\u30fc\u30b8\u60c5\u5831\uff1a

+ReportHTML.writeSum.timezone=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\uff1a +ReportProgressPanel.progress.queuing=\u30ad\u30e5\u30fc\u30a4\u30f3\u30b0\u2026 +ReportProgressPanel.initPathLabel.noFile=\u30ec\u30dd\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u7121\u3057 +ReportProgressPanel.start.progress.text=\u30ec\u30dd\u30fc\u30c8\u958b\u59cb\u4e2d\u2026 +ReportVisualPanel1.getName.text=\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u9078\u629e\u304a\u3088\u3073\u8a2d\u5b9a +ReportVisualPanel2.getName.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30ec\u30dd\u30fc\u30c8\u3092\u8a2d\u5b9a +ReportWizardFileOptionsPanel.finishButton.text=\u7d42\u4e86 +ReportWizardFileOptionsVisualPanel.getName.text=\u30d5\u30a1\u30a4\u30eb\u30ec\u30dd\u30fc\u30c8\u3092\u8a2d\u5b9a +ReportWizardPanel1.finishButton.text=\u7d42\u4e86 +ReportWizardPanel2.finishButton.text=\u7d42\u4e86 +ReportHTML.writeSum.reportGenOn.text={0}\u306bHTML\u30ec\u30dd\u30fc\u30c8\u306f\u751f\u6210\u3055\u308c\u307e\u3057\u305f +ReportHTML.writeSum.noCaseNum=\u30b1\u30fc\u30b9\u756a\u53f7\u304c\u3042\u308a\u307e\u305b\u3093 +ReportGenerator.errors.reportErrorTitle=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +ReportGenerator.errors.reportErrorText=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a +ReportKML.getDesc.text=\u95a2\u9023\u30d5\u30a1\u30a4\u30eb\u306e\u5ea7\u6a19\u3092\u542b\u3080KML\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u306e\u30ec\u30dd\u30fc\u30c8\u3002\u3053\u306e\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u306fGoogle Earth\u30d3\u30e5\u30fc\u306b\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002 ReportKML.getName.text=Google Earth/KML -ReportKML.progress.loading=\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u307F\u8FBC\u307F\u4E2D\u2026 -ReportKML.progress.querying=\u30D5\u30A1\u30A4\u30EB\u306E\u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u4E2D\u2026 -ReportBodyFile.generateReport.srcModuleName.text=TSK\u30DC\u30C7\u30A3\u30D5\u30A1\u30A4\u30EB -ReportExcel.endReport.srcModuleName.text=Excel\u30EC\u30DD\u30FC\u30C8 -ReportGenerator.artTableColHdr.extension.text=\u62E1\u5F35\u5B50 -ReportGenerator.artTableColHdr.mimeType.text=MIME\u30BF\u30A4\u30D7 -ReportHTML.writeIndex.srcModuleName.text=HTML\u30EC\u30DD\u30FC\u30C8 -ReportKML.genReport.srcModuleName.text=KML\u30EC\u30DD\u30FC\u30C8 -ReportGenerator.artTableColHdr.associatedArtifact=\u95A2\u4FC2\u3059\u308B\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8 -ReportGenerator.artTableColHdr.count=\u30AB\u30A6\u30F3\u30C8 -ReportGenerator.artTableColHdr.devMake=\u6A5F\u5668\u578B\u540D -ReportGenerator.artTableColHdr.latitudeEnd=\u5230\u7740\u7DEF\u5EA6 -ReportGenerator.artTableColHdr.latitudeStart=\u51FA\u767A\u7DEF\u5EA6 -ReportGenerator.artTableColHdr.localPath=\u30ED\u30FC\u30AB\u30EB\u30D1\u30B9 -ReportGenerator.artTableColHdr.longitudeEnd=\u5230\u7740\u7D4C\u5EA6 -ReportGenerator.artTableColHdr.longitudeStart=\u51FA\u767A\u7D4C\u5EA6 -ReportGenerator.artTableColHdr.osInstallDate.text=\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u65E5\u4ED8 -ReportGenerator.artTableColHdr.osName.text=\u30AA\u30DA\u30EC\u30FC\u30C6\u30A3\u30F3\u30B0\u30B7\u30B9\u30C6\u30E0\u540D -ReportGenerator.artTableColHdr.processorArchitecture.text=\u30D7\u30ED\u30BB\u30C3\u30B5\u30A2\u30FC\u30AD\u30C6\u30AF\u30C1\u30E3 -ReportGenerator.artTableColHdr.readStatus=\u8AAD\u307F\u53D6\u308A\u4E2D\u30B9\u30C6\u30FC\u30BF\u30B9 -ReportGenerator.artTableColHdr.remotePath=\u30EA\u30E2\u30FC\u30C8\u30D1\u30B9 -ReportGenerator.artTableColHdr.tskDateTimeRcvd=\u53D7\u4FE1\u65E5 -ReportGenerator.artTableColHdr.tskDateTimeSent=\u9001\u4FE1\u65E5 +ReportKML.progress.loading=\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u2026 +ReportKML.progress.querying=\u30d5\u30a1\u30a4\u30eb\u306e\u30af\u30a8\u30ea\u3092\u5b9f\u884c\u4e2d\u2026 +ReportBodyFile.generateReport.srcModuleName.text=TSK\u30dc\u30c7\u30a3\u30d5\u30a1\u30a4\u30eb +ReportExcel.endReport.srcModuleName.text=Excel\u30ec\u30dd\u30fc\u30c8 +ReportGenerator.artTableColHdr.extension.text=\u62e1\u5f35\u5b50 +ReportGenerator.artTableColHdr.mimeType.text=MIME\u30bf\u30a4\u30d7 +ReportHTML.writeIndex.srcModuleName.text=HTML\u30ec\u30dd\u30fc\u30c8 +ReportKML.genReport.srcModuleName.text=KML\u30ec\u30dd\u30fc\u30c8 +ReportGenerator.artTableColHdr.associatedArtifact=\u95a2\u4fc2\u3059\u308b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8 +ReportGenerator.artTableColHdr.count=\u30ab\u30a6\u30f3\u30c8 +ReportGenerator.artTableColHdr.devMake=\u6a5f\u5668\u578b\u540d +ReportGenerator.artTableColHdr.latitudeEnd=\u5230\u7740\u7def\u5ea6 +ReportGenerator.artTableColHdr.latitudeStart=\u51fa\u767a\u7def\u5ea6 +ReportGenerator.artTableColHdr.localPath=\u30ed\u30fc\u30ab\u30eb\u30d1\u30b9 +ReportGenerator.artTableColHdr.longitudeEnd=\u5230\u7740\u7d4c\u5ea6 +ReportGenerator.artTableColHdr.longitudeStart=\u51fa\u767a\u7d4c\u5ea6 +ReportGenerator.artTableColHdr.osInstallDate.text=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65e5\u4ed8 +ReportGenerator.artTableColHdr.osName.text=\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u540d +ReportGenerator.artTableColHdr.processorArchitecture.text=\u30d7\u30ed\u30bb\u30c3\u30b5\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3 +ReportGenerator.artTableColHdr.readStatus=\u8aad\u307f\u53d6\u308a\u4e2d\u30b9\u30c6\u30fc\u30bf\u30b9 +ReportGenerator.artTableColHdr.remotePath=\u30ea\u30e2\u30fc\u30c8\u30d1\u30b9 +ReportGenerator.artTableColHdr.tskDateTimeRcvd=\u53d7\u4fe1\u65e5 +ReportGenerator.artTableColHdr.tskDateTimeSent=\u9001\u4fe1\u65e5 ReportGenerator.artTableColHdr.tskEmailBcc=E-Mail BCC ReportGenerator.artTableColHdr.tskEmailCc=E-Mail CC -ReportGenerator.artTableColHdr.tskEmailFrom=E-Mail\u9001\u4FE1\u5143 -ReportGenerator.artTableColHdr.tskEmailTo=E-Mail\u9001\u4FE1\u5148 -ReportGenerator.artTableColHdr.tskGpsRouteCategory=\u30AB\u30C6\u30B4\u30EA -ReportGenerator.artTableColHdr.tskInterestingFilesCategory=\u30EB\u30FC\u30EB -ReportGenerator.artTableColHdr.tskMsgId=\u30E1\u30C3\u30BB\u30FC\u30B8ID -ReportGenerator.artTableColHdr.tskPath=\u30D1\u30B9 -ReportGenerator.artTableColHdr.tskSetName=\u30BB\u30C3\u30C8\u540D -ReportGenerator.artTableColHdr.tskSubject=\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8 -ReportGenerator.artTableColHdr.urlDomainDecoded=URL\u30C9\u30E1\u30A4\u30F3 -ReportGenerator.artTableColHdr.userName=\u30E6\u30FC\u30B6\u540D -ReportGenerator.errList.coreExceptionWhileGenRptRow=\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u30EC\u30DD\u30FC\u30C8\u7528\u30ED\u30FC\u30C7\u30FC\u30BF\u306E\u751F\u6210\u4E2D\u306B\u30B3\u30A2\u30A8\u30AF\u30BB\u30D7\u30B7\u30E7\u30F3\uFF08\u4F8B\u5916\uFF09\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F -ReportGenerator.errList.errGetContentFromBBArtifact=Blackboard\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u304B\u3089\u30EC\u30DD\u30FC\u30C8\u7528\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u3092\u53D6\u5F97\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -ReportGenerator.errList.failedGetAbstractFileByID=ID\u306B\u57FA\u3065\u304D\u30A2\u30D6\u30B9\u30C8\u30E9\u30AF\u30C8\u30D5\u30A1\u30A4\u30EB\u3092\u53D6\u5F97\u3059\u308B\u306E\u3092\u5931\u6557\u3057\u307E\u3057\u305F -ReportGenerator.errList.failedGetBBArtifacts=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u4E2D\u306BBlackboard\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -ReportGenerator.errList.failedGetBBArtifactTags=Blackboard\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u30BF\u30B0\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -ReportGenerator.errList.failedGetBBAttribs=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u4E2D\u306BBlackboard\u5C5E\u6027\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -ReportGenerator.errList.failedGetContentTags=\u30B3\u30F3\u30C6\u30F3\u30C4\u30BF\u30B0\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -ReportGenerator.errList.failedMakeRptFolder=\u30EC\u30DD\u30FC\u30C8\u30D5\u30A9\u30EB\u30C0\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u304C\u3067\u304D\u306A\u3044\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 -ReportGenerator.errList.failedQueryHashsetHits=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u30D2\u30C3\u30C8\u3092\u30AF\u30A8\u30EA\u3059\u308B\u306E\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -ReportGenerator.errList.failedQueryHashsetLists=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u30EA\u30B9\u30C8\u3092\u30AF\u30A8\u30EA\u3059\u308B\u306E\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -ReportGenerator.errList.failedQueryKWLists=\u30AD\u30FC\u30EF\u30FC\u30C9\u30EA\u30B9\u30C8\u3092\u30AF\u30A8\u30EA\u3059\u308B\u306E\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -ReportGenerator.errList.failedQueryKWs=\u30AD\u30FC\u30EF\u30FC\u30C9\u3092\u30AF\u30A8\u30EA\u3059\u308B\u306E\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -ReportGenerator.htmlOutput.header.comment=\u30B3\u30E1\u30F3\u30C8 -ReportGenerator.htmlOutput.header.file=\u30D5\u30A1\u30A4\u30EB -ReportGenerator.htmlOutput.header.hash=\u30CF\u30C3\u30B7\u30E5 -ReportGenerator.htmlOutput.header.size=\u30B5\u30A4\u30BA\uFF08\u30D0\u30A4\u30C8\uFF09 -ReportGenerator.htmlOutput.header.tag=\u30BF\u30B0 -ReportGenerator.htmlOutput.header.timeAccessed=\u30A2\u30AF\u30BB\u30B9\u65E5\u6642 -ReportGenerator.htmlOutput.header.timeChanged=\u5909\u66F4\u65E5\u6642 -ReportGenerator.htmlOutput.header.timeCreated=\u4F5C\u6210\u65E5\u6642 -ReportGenerator.htmlOutput.header.timeModified=\u4FEE\u6B63\u65E5\u6642 -ReportGenerator.notifyErr.errsDuringRptGen=\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u4E2D\u306E\u30A8\u30E9\u30FC\uFF1A -ReportGenerator.errList.failedGetAbstractFileFromID=ID\u306B\u57FA\u3065\u304D\u30A2\u30D6\u30B9\u30C8\u30E9\u30AF\u30C8\u30D5\u30A1\u30A4\u30EB\u3092\u53D6\u5F97\u3059\u308B\u306E\u3092\u5931\u6557\u3057\u307E\u3057\u305F -ReportKML.getFilePath.text=\u30EC\u30DD\u30FC\u30C8KML.kml -ReportVisualPanel1.invalidModuleWarning=\u7121\u52B9\u306A\u30EC\u30DD\u30FC\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB({0})\u306B\u906D\u9047\u3057\u307E\u3057\u305F -ReportGenerationPanel.confDlg.cancelReport.msg=\u672C\u5F53\u306B\u30EC\u30DD\u30FC\u30C8\u3092\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3059\u304B\uFF1F -ReportProgressPanel.complete.processLb2.text=\u5B8C\u4E86\u3057\u307E\u3057\u305F\u304C\u3001\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F -ReportGenerationPanel.cancelButton.actionCommand=\u30AD\u30E3\u30F3\u30BB\u30EB -ReportGenerationPanel.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB \ No newline at end of file +ReportGenerator.artTableColHdr.tskEmailFrom=E-Mail\u9001\u4fe1\u5143 +ReportGenerator.artTableColHdr.tskEmailTo=E-Mail\u9001\u4fe1\u5148 +ReportGenerator.artTableColHdr.tskGpsRouteCategory=\u30ab\u30c6\u30b4\u30ea +ReportGenerator.artTableColHdr.tskInterestingFilesCategory=\u30eb\u30fc\u30eb +ReportGenerator.artTableColHdr.tskMsgId=\u30e1\u30c3\u30bb\u30fc\u30b8ID +ReportGenerator.artTableColHdr.tskPath=\u30d1\u30b9 +ReportGenerator.artTableColHdr.tskSetName=\u30bb\u30c3\u30c8\u540d +ReportGenerator.artTableColHdr.tskSubject=\u30b5\u30d6\u30b8\u30a7\u30af\u30c8 +ReportGenerator.artTableColHdr.urlDomainDecoded=URL\u30c9\u30e1\u30a4\u30f3 +ReportGenerator.artTableColHdr.userName=\u30e6\u30fc\u30b6\u540d +ReportGenerator.errList.coreExceptionWhileGenRptRow=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30ec\u30dd\u30fc\u30c8\u7528\u30ed\u30fc\u30c7\u30fc\u30bf\u306e\u751f\u6210\u4e2d\u306b\u30b3\u30a2\u30a8\u30af\u30bb\u30d7\u30b7\u30e7\u30f3\uff08\u4f8b\u5916\uff09\u304c\u691c\u51fa\u3055\u308c\u307e\u3057\u305f +ReportGenerator.errList.errGetContentFromBBArtifact=Blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u304b\u3089\u30ec\u30dd\u30fc\u30c8\u7528\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +ReportGenerator.errList.failedGetAbstractFileByID=ID\u306b\u57fa\u3065\u304d\u30a2\u30d6\u30b9\u30c8\u30e9\u30af\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3059\u308b\u306e\u3092\u5931\u6557\u3057\u307e\u3057\u305f +ReportGenerator.errList.failedGetBBArtifacts=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306bBlackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +ReportGenerator.errList.failedGetBBArtifactTags=Blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30bf\u30b0\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +ReportGenerator.errList.failedGetBBAttribs=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306bBlackboard\u5c5e\u6027\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +ReportGenerator.errList.failedGetContentTags=\u30b3\u30f3\u30c6\u30f3\u30c4\u30bf\u30b0\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +ReportGenerator.errList.failedMakeRptFolder=\u30ec\u30dd\u30fc\u30c8\u30d5\u30a9\u30eb\u30c0\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u304c\u3067\u304d\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 +ReportGenerator.errList.failedQueryHashsetHits=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30d2\u30c3\u30c8\u3092\u30af\u30a8\u30ea\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +ReportGenerator.errList.failedQueryHashsetLists=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30ea\u30b9\u30c8\u3092\u30af\u30a8\u30ea\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +ReportGenerator.errList.failedQueryKWLists=\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u3092\u30af\u30a8\u30ea\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +ReportGenerator.errList.failedQueryKWs=\u30ad\u30fc\u30ef\u30fc\u30c9\u3092\u30af\u30a8\u30ea\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +ReportGenerator.htmlOutput.header.comment=\u30b3\u30e1\u30f3\u30c8 +ReportGenerator.htmlOutput.header.file=\u30d5\u30a1\u30a4\u30eb +ReportGenerator.htmlOutput.header.hash=\u30cf\u30c3\u30b7\u30e5 +ReportGenerator.htmlOutput.header.size=\u30b5\u30a4\u30ba\uff08\u30d0\u30a4\u30c8\uff09 +ReportGenerator.htmlOutput.header.tag=\u30bf\u30b0 +ReportGenerator.htmlOutput.header.timeAccessed=\u30a2\u30af\u30bb\u30b9\u65e5\u6642 +ReportGenerator.htmlOutput.header.timeChanged=\u5909\u66f4\u65e5\u6642 +ReportGenerator.htmlOutput.header.timeCreated=\u4f5c\u6210\u65e5\u6642 +ReportGenerator.htmlOutput.header.timeModified=\u4fee\u6b63\u65e5\u6642 +ReportGenerator.notifyErr.errsDuringRptGen=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306e\u30a8\u30e9\u30fc\uff1a +ReportGenerator.errList.failedGetAbstractFileFromID=ID\u306b\u57fa\u3065\u304d\u30a2\u30d6\u30b9\u30c8\u30e9\u30af\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3059\u308b\u306e\u3092\u5931\u6557\u3057\u307e\u3057\u305f +ReportKML.getFilePath.text=\u30ec\u30dd\u30fc\u30c8KML.kml +ReportVisualPanel1.invalidModuleWarning=\u7121\u52b9\u306a\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb({0})\u306b\u906d\u9047\u3057\u307e\u3057\u305f +ReportGenerationPanel.confDlg.cancelReport.msg=\u672c\u5f53\u306b\u30ec\u30dd\u30fc\u30c8\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3059\u304b\uff1f +ReportGenerationPanel.cancelButton.actionCommand=\u30ad\u30e3\u30f3\u30bb\u30eb +ReportGenerationPanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +ReportProgressPanel.separationLabel.text=- diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerationPanel.form b/Core/src/org/sleuthkit/autopsy/report/ReportGenerationPanel.form index f7da786aa4..86a4cbe37d 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerationPanel.form +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerationPanel.form @@ -26,22 +26,16 @@ - - - - - - - - - - + + + + @@ -51,19 +45,13 @@ - - - - - - - + - + @@ -102,77 +90,30 @@
- + - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerationPanel.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerationPanel.java index 568b25b30e..0064b14f69 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerationPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.report; import java.awt.*; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import javax.swing.Box; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; @@ -29,62 +28,71 @@ import javax.swing.SwingUtilities; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus; +/** + * A panel that displays a panel used by a report generation module to show + * progress. It provides OK and Cancel buttons. + */ class ReportGenerationPanel extends javax.swing.JPanel { - private GridBagConstraints c; - ReportProgressPanel progressPanel; - private Component glue; + private static final long serialVersionUID = 1L; + private final GridBagConstraints constraints; + private final Component glue; private ActionListener actionListener; + ReportProgressPanel progressPanel; /** - * Creates new form ReportGenerationPanel + * Constructs a panel that displays a panel used by a report generation + * module to show progress. It provides OK and Cancel buttons. */ - public ReportGenerationPanel() { + ReportGenerationPanel() { initComponents(); - customInit(); - } - - private void customInit() { reportPanel.setLayout(new GridBagLayout()); - c = new GridBagConstraints(); - c.fill = GridBagConstraints.BOTH; - c.gridx = 0; - c.gridy = 0; - c.weightx = 1.0; + constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.BOTH; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.weightx = 1.0; glue = Box.createVerticalGlue(); - } /** - * Add a ReportProgressPanel to this panel with the given report name and - * path. + * Adds a panel used by a report generation module to show progress to this + * panel. * - * @param reportName report name - * @param reportPath report path + * @param reportName The report name. + * @param reportPath The report file path * - * @return ReportProgressPanel progress panel to update + * @return The report generation progress panel. */ - public ReportProgressPanel addReport(String reportName, String reportPath) { - // Remove the glue + ReportProgressPanel addReport(String reportName, String reportPath) { + /* + * Remove the "glue." + */ reportPanel.remove(glue); progressPanel = new ReportProgressPanel(reportName, reportPath); - c.weighty = 0.0; - c.anchor = GridBagConstraints.NORTH; - reportPanel.add(progressPanel, c); - c.gridy++; + constraints.weighty = 0.0; + constraints.anchor = GridBagConstraints.NORTH; + reportPanel.add(progressPanel, constraints); + constraints.gridy++; - // Add the glue back to the bottom - c.weighty = 1.0; - c.anchor = GridBagConstraints.PAGE_END; - reportPanel.add(glue, c); + /* + * Add the "glue" back to the bottom of the panel. + */ + constraints.weighty = 1.0; + constraints.anchor = GridBagConstraints.PAGE_END; + reportPanel.add(glue, constraints); - // 80 px per progressPanel. + /* + * Use 80 pixels per progress panel. This is a leftover from when this + * panel used to show multiple report progress panels. + */ reportPanel.setPreferredSize(new Dimension(600, 1 * 80)); reportPanel.repaint(); progressPanel.addPropertyChangeListener((PropertyChangeEvent evt) -> { String propName = evt.getPropertyName(); - if (propName.equals(ReportProgressPanel.Events.COMPLETED.toString())) { + if (propName.equals(ReportProgressPanel.ReportStatus.COMPLETE.toString()) + || propName.equals(ReportProgressPanel.ReportStatus.CANCELED.toString())) { SwingUtilities.invokeLater(() -> { cancelButton.setEnabled(false); }); @@ -94,7 +102,7 @@ class ReportGenerationPanel extends javax.swing.JPanel { } /** - * Close this panel and it's dialog if all reports are done. + * Closes this panel and its dialog if all reports are done. */ void close() { boolean closeable = true; @@ -117,6 +125,15 @@ class ReportGenerationPanel extends javax.swing.JPanel { } } + /** + * Adds a close action listener to this panel. + * + * @param listener The listener to add. + */ + void addCloseAction(ActionListener listener) { + this.actionListener = listener; + } + /** * 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 @@ -128,11 +145,7 @@ class ReportGenerationPanel extends javax.swing.JPanel { closeButton = new javax.swing.JButton(); cancelButton = new javax.swing.JButton(); - reportScrollPane = new javax.swing.JScrollPane(); reportPanel = new javax.swing.JPanel(); - titleLabel = new javax.swing.JLabel(); - titleSeparator = new javax.swing.JSeparator(); - optionSeparator = new javax.swing.JSeparator(); setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11)); setPreferredSize(new java.awt.Dimension(700, 400)); @@ -154,10 +167,6 @@ class ReportGenerationPanel extends javax.swing.JPanel { } }); - reportScrollPane.setBorder(javax.swing.BorderFactory.createLineBorder(java.awt.SystemColor.activeCaptionBorder)); - reportScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - reportScrollPane.setFont(reportScrollPane.getFont().deriveFont(reportScrollPane.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - reportPanel.setFont(reportPanel.getFont().deriveFont(reportPanel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); reportPanel.setPreferredSize(new java.awt.Dimension(600, 400)); @@ -165,53 +174,33 @@ class ReportGenerationPanel extends javax.swing.JPanel { reportPanel.setLayout(reportPanelLayout); reportPanelLayout.setHorizontalGroup( reportPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 661, Short.MAX_VALUE) + .addGap(0, 0, Short.MAX_VALUE) ); reportPanelLayout.setVerticalGroup( reportPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 400, Short.MAX_VALUE) + .addGap(0, 344, Short.MAX_VALUE) ); - reportScrollPane.setViewportView(reportPanel); - - titleLabel.setFont(titleLabel.getFont().deriveFont(titleLabel.getFont().getStyle() | java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(titleLabel, org.openide.util.NbBundle.getMessage(ReportGenerationPanel.class, "ReportGenerationPanel.titleLabel.text")); // NOI18N - - titleSeparator.setForeground(new java.awt.Color(0, 0, 0)); - - optionSeparator.setForeground(new java.awt.Color(0, 0, 0)); - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(optionSeparator) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(reportScrollPane) - .addComponent(titleSeparator, javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addComponent(titleLabel) - .addGap(0, 522, Short.MAX_VALUE)) - .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGap(0, 546, Short.MAX_VALUE) .addComponent(cancelButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(closeButton))) + .addComponent(closeButton)) + .addComponent(reportPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 680, Short.MAX_VALUE)) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(titleLabel) - .addGap(0, 0, 0) - .addComponent(titleSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(18, 18, 18) - .addComponent(reportScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 290, Short.MAX_VALUE) - .addGap(18, 18, 18) - .addComponent(optionSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(reportPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 344, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(closeButton) @@ -237,18 +226,10 @@ class ReportGenerationPanel extends javax.swing.JPanel { } }//GEN-LAST:event_cancelButtonActionPerformed - void addCloseAction(ActionListener l) { - this.actionListener = l; - } - // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton cancelButton; private javax.swing.JButton closeButton; - private javax.swing.JSeparator optionSeparator; private javax.swing.JPanel reportPanel; - private javax.swing.JScrollPane reportScrollPane; - private javax.swing.JLabel titleLabel; - private javax.swing.JSeparator titleSeparator; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.form b/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.form index b490520e46..8291726f99 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.form +++ b/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.form @@ -29,10 +29,9 @@ - - + @@ -49,17 +48,15 @@ - + - + - + - - - + @@ -96,18 +93,7 @@ -
-
- - - - - - - - - - + diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java b/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java index 7d4189157f..a1c560f076 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.report; import org.openide.util.NbBundle; - import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; @@ -30,14 +29,22 @@ import java.io.IOException; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; +/** + * A panel used by a report generation module to show progress. + */ public class ReportProgressPanel extends javax.swing.JPanel { + private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(ReportProgressPanel.class.getName()); + private static final Color GREEN = new Color(50, 205, 50); + private static final Color RED = new Color(178, 34, 34); private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); - private ReportStatus STATUS; + private ReportStatus status; - // Enum to represent if a report is waiting, - // running, done, or has been canceled + /** + * Used by a report generation module to communicate report generation + * status to this panel and its listeners. + */ public enum ReportStatus { QUEUING, @@ -47,269 +54,235 @@ public class ReportProgressPanel extends javax.swing.JPanel { ERROR } - public enum Events { - - COMPLETED - } - /** - * Creates new form ReportProgressPanel + * Constructs a panel used by report generation module to show progress. + * + * @param reportName The name of the report being generated. + * @param reportPath The path to the report file. */ public ReportProgressPanel(String reportName, String reportPath) { initComponents(); - customInit(reportName, reportPath); - } - - private void customInit(String reportName, String reportPath) { reportProgressBar.setIndeterminate(true); reportProgressBar.setMaximum(100); - reportLabel.setText(reportName); - processingLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.progress.queuing")); - STATUS = ReportStatus.QUEUING; - - if (reportPath != null) { + status = ReportStatus.QUEUING; + if (null != reportPath) { pathLabel.setText("" + shortenPath(reportPath) + ""); //NON-NLS pathLabel.setToolTipText(reportPath); - - // Add the "link" effect to the pathLabel - final String linkPath = reportPath; + String linkPath = reportPath; pathLabel.addMouseListener(new MouseListener() { @Override - public void mouseClicked(MouseEvent e) { + public void mouseClicked(MouseEvent mouseEvent) { } @Override - public void mousePressed(MouseEvent e) { + public void mousePressed(MouseEvent mouseEvent) { } @Override - public void mouseReleased(MouseEvent e) { + public void mouseReleased(MouseEvent mouseEvent) { File file = new File(linkPath); try { Desktop.getDesktop().open(file); - } catch (IOException ex) { - } catch (IllegalArgumentException ex) { + } catch (IOException ioex) { + logger.log(Level.SEVERE, "Error opening report file", ioex); + } catch (IllegalArgumentException iaEx) { + logger.log(Level.SEVERE, "Error opening report file", iaEx); try { - // try to open the parent path if the file doens't exist Desktop.getDesktop().open(file.getParentFile()); - } catch (IOException ex1) { + } catch (IOException ioEx2) { + logger.log(Level.SEVERE, "Error opening report file parent", ioEx2); } } } @Override - public void mouseEntered(MouseEvent e) { + public void mouseEntered(MouseEvent e3) { pathLabel.setForeground(Color.DARK_GRAY); setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } @Override - public void mouseExited(MouseEvent e) { + public void mouseExited(MouseEvent e4) { pathLabel.setForeground(Color.BLACK); setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } - }); } else { pathLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.initPathLabel.noFile")); } } + /** + * Adds a property change listener to this panel. + * + * @param listener The listener to be added. + */ @Override public void addPropertyChangeListener(PropertyChangeListener listener) { this.pcs.addPropertyChangeListener(listener); } + /** + * Removes a property change listener from this panel. + * + * @param listener The listener to be removed. + */ @Override public void removePropertyChangeListener(PropertyChangeListener listener) { this.pcs.removePropertyChangeListener(listener); } /** - * Return a shortened version of the given path. - */ - private String shortenPath(String path) { - if (path.length() > 100) { - path = path.substring(0, 10 + path.substring(10).indexOf(File.separator) + 1) + "..." - + path.substring((path.length() - 70) + path.substring(path.length() - 70).indexOf(File.separator)); - } - return path; - } - - /** - * Return the current ReportStatus of this report. + * Gets the current status of the generation of the report. * - * @return ReportStatus status of this report + * @return The report generation status as a ReportStatus enum. */ public ReportStatus getStatus() { - return STATUS; + return status; } /** - * Start the JProgressBar for this report. - * - * Enables the cancelButton, updates the processingLabel, and changes this - * report's ReportStatus. + * Starts the progress bar component of this panel. */ public void start() { - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - processingLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.start.progress.text")); - STATUS = ReportStatus.RUNNING; - } + EventQueue.invokeLater(() -> { + status = ReportStatus.RUNNING; }); } /** - * Set the maximum progress for this report's JProgressBar. + * Sets the maximum value of the progress bar component of this panel. * - * @param max maximum progress for JProgressBar + * @param max The maximum value. */ - public void setMaximumProgress(final int max) { - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - if (STATUS != ReportStatus.CANCELED) { - reportProgressBar.setMaximum(max); - } + public void setMaximumProgress(int max) { + EventQueue.invokeLater(() -> { + if (status != ReportStatus.CANCELED) { + reportProgressBar.setMaximum(max); } }); } /** - * Increment the JProgressBar for this report by one unit. + * Increments the current value of the progress bar component of this panel + * by one unit. */ public void increment() { - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - if (STATUS != ReportStatus.CANCELED) { - reportProgressBar.setValue(reportProgressBar.getValue() + 1); - } + EventQueue.invokeLater(() -> { + if (status != ReportStatus.CANCELED) { + reportProgressBar.setValue(reportProgressBar.getValue() + 1); } }); } /** - * Set the value of the JProgressBar for this report. + * Sets the current value of the progress bar component of this panel. * - * @param value value to be set at + * @param value The value to be set. */ - public void setProgress(final int value) { - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - if (STATUS != ReportStatus.CANCELED) { - reportProgressBar.setValue(value); - } + public void setProgress(int value) { + EventQueue.invokeLater(() -> { + if (status != ReportStatus.CANCELED) { + reportProgressBar.setValue(value); } }); } /** - * Changes the status of the JProgressBar to be determinate or + * Changes the the progress bar component of this panel to be determinate or * indeterminate. * - * @param indeterminate sets the JProgressBar to be indeterminate if true, - * determinate otherwise + * @param indeterminate True if the progress bar should be set to + * indeterminate. */ - public void setIndeterminate(final boolean indeterminate) { - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - if (STATUS != ReportStatus.CANCELED) { - reportProgressBar.setIndeterminate(indeterminate); - } + public void setIndeterminate(boolean indeterminate) { + EventQueue.invokeLater(() -> { + if (status != ReportStatus.CANCELED) { + reportProgressBar.setIndeterminate(indeterminate); } }); } /** - * Change the text of this report's status label. The text given will be the - * full text used. e.g. updateStatusLabel("Now processing files...") sets - * the label to "Now processing files..." + * Makes the components of this panel indicate the final status of + * generation of the report. * - * @param status String to use as status - */ - public void updateStatusLabel(final String status) { - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - if (STATUS != ReportStatus.CANCELED) { - processingLabel.setText(status); - } - } - }); - } - - /** - * Declare the report completed. This will fill the JProgressBar, update the - * cancelButton to completed, and disallow any cancellation of this report. - * - * @deprecated Use {@link #complete(ReportStatus)} - */ - @Deprecated - public void complete() { - complete(ReportStatus.COMPLETE); - } - - /** - * Declare the report completed ands sets if completed successfully or with - * errors. This will fill the JProgressBar, update the cancelButton to - * completed, and disallow any cancellation of this report. - * - * @param reportStatus set to appropriate ResultStatus enum. + * @param reportStatus The final status, must be COMPLETE or ERROR. */ public void complete(ReportStatus reportStatus) { - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - // make sure we disable an indeterminate - reportProgressBar.setIndeterminate(false); - - if (STATUS != ReportStatus.CANCELED) { - switch (reportStatus) { - case COMPLETE: { - ReportStatus oldValue = STATUS; - STATUS = ReportStatus.COMPLETE; - processingLabel.setForeground(Color.BLACK); - processingLabel.setText( - NbBundle.getMessage(this.getClass(), "ReportProgressPanel.complete.processLbl.text")); - reportProgressBar.setValue(reportProgressBar.getMaximum()); - reportProgressBar.setStringPainted(true); - // set reportProgressBar color as green. - reportProgressBar.setForeground(new Color(50, 205, 50)); - reportProgressBar.setString("Complete"); //NON-NLS - pcs.firePropertyChange(Events.COMPLETED.toString(), oldValue, STATUS); - break; - } - case ERROR: { - ReportStatus oldValue = STATUS; - STATUS = ReportStatus.ERROR; - processingLabel.setForeground(new Color(178, 34, 34)); - processingLabel.setText( - NbBundle.getMessage(this.getClass(), "ReportProgressPanel.complete.processLb2.text")); - reportProgressBar.setValue(reportProgressBar.getMaximum()); - reportProgressBar.setStringPainted(true); - // set reportProgressBar color as red. - reportProgressBar.setForeground(new Color(178, 34, 34)); - reportProgressBar.setString("Error"); //NON-NLS - pcs.firePropertyChange(Events.COMPLETED.toString(), oldValue, STATUS); - break; - } - // add finer grained result codes here. - default: { - logger.log(Level.SEVERE, "Invalid ReportStatus code {0}", reportStatus); //NON-NLS - break; - } + EventQueue.invokeLater(() -> { + reportProgressBar.setIndeterminate(false); + if (status != ReportStatus.CANCELED) { + switch (reportStatus) { + case COMPLETE: { + ReportStatus oldValue = status; + status = ReportStatus.COMPLETE; + reportProgressBar.setValue(reportProgressBar.getMaximum()); + reportProgressBar.setStringPainted(true); + reportProgressBar.setForeground(GREEN); + reportProgressBar.setString("Complete"); //NON-NLS + pcs.firePropertyChange(ReportStatus.COMPLETE.toString(), oldValue, status); + break; + } + case ERROR: { + ReportStatus oldValue = status; + status = ReportStatus.ERROR; + reportProgressBar.setValue(reportProgressBar.getMaximum()); + reportProgressBar.setStringPainted(true); + reportProgressBar.setForeground(RED); + reportProgressBar.setString("Error"); //NON-NLS + pcs.firePropertyChange(ReportStatus.COMPLETE.toString(), oldValue, status); + break; + } + default: { + break; } } } }); - // Do something with the button to change the icon and make not clickable + } + + /** + * Makes the components of this panel indicate generation of the report was + * cancelled. + */ + void cancel() { + switch (status) { + case COMPLETE: + break; + case CANCELED: + break; + case ERROR: + break; + default: + ReportStatus oldValue = status; + status = ReportStatus.CANCELED; + reportProgressBar.setIndeterminate(false); + reportProgressBar.setValue(0); + reportProgressBar.setStringPainted(true); + reportProgressBar.setForeground(RED); // Red + reportProgressBar.setString("Cancelled"); //NON-NLS + pcs.firePropertyChange(ReportStatus.CANCELED.toString(), oldValue, status); + break; + } + } + + /** + * Gets a shortened version of a file path. + * + * @param path The path to shorten. + * + * @return The shortened path. + */ + private String shortenPath(String path) { + if (path.length() > 100) { + return path.substring(0, 10 + path.substring(10).indexOf(File.separator) + 1) + "..." + + path.substring((path.length() - 70) + path.substring(path.length() - 70).indexOf(File.separator)); + } else { + return path; + } } /** @@ -324,7 +297,6 @@ public class ReportProgressPanel extends javax.swing.JPanel { reportProgressBar = new javax.swing.JProgressBar(); reportLabel = new javax.swing.JLabel(); pathLabel = new javax.swing.JLabel(); - processingLabel = new javax.swing.JLabel(); separationLabel = new javax.swing.JLabel(); setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11)); @@ -337,9 +309,7 @@ public class ReportProgressPanel extends javax.swing.JPanel { pathLabel.setFont(pathLabel.getFont().deriveFont(pathLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.pathLabel.text")); // NOI18N - - processingLabel.setFont(processingLabel.getFont().deriveFont((processingLabel.getFont().getStyle() | java.awt.Font.ITALIC) & ~java.awt.Font.BOLD, 10)); - org.openide.awt.Mnemonics.setLocalizedText(processingLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.processingLabel.text")); // NOI18N + pathLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP); separationLabel.setFont(separationLabel.getFont().deriveFont(separationLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); org.openide.awt.Mnemonics.setLocalizedText(separationLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.separationLabel.text")); // NOI18N @@ -351,10 +321,9 @@ public class ReportProgressPanel extends javax.swing.JPanel { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(processingLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(reportProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGap(58, 58, 58)) + .addGap(0, 0, 0)) .addGroup(layout.createSequentialGroup() .addComponent(reportLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -371,45 +340,40 @@ public class ReportProgressPanel extends javax.swing.JPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(reportLabel) - .addComponent(pathLabel) + .addComponent(pathLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(separationLabel)) - .addGap(0, 0, 0) - .addComponent(processingLabel) - .addContainerGap(20, Short.MAX_VALUE)) + .addGap(33, 33, 33)) ); }// //GEN-END:initComponents - /** - * Cancels the current report, based on it's status. If the report is - * complete or has already been completed, nothing happens. - */ - void cancel() { - switch (STATUS) { - case COMPLETE: - break; - case CANCELED: - break; - case ERROR: - break; - default: - STATUS = ReportStatus.CANCELED; - reportProgressBar.setIndeterminate(false); - reportProgressBar.setValue(0); - reportProgressBar.setStringPainted(true); - // set reportProgressBar color as red. - reportProgressBar.setForeground(new Color(178, 34, 34)); - reportProgressBar.setString("Cancelled"); //NON-NLS - processingLabel.setForeground(new Color(178, 34, 34)); - processingLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.cancel.procLbl.text")); - break; - } - } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel pathLabel; - private javax.swing.JLabel processingLabel; private javax.swing.JLabel reportLabel; private javax.swing.JProgressBar reportProgressBar; private javax.swing.JLabel separationLabel; // End of variables declaration//GEN-END:variables + + /** + * Does nothing, the status label it used to update no longer exists. + * + * @param status String to use as status + * + * @deprecated + */ + @Deprecated + public void updateStatusLabel(final String status) { + } + + /** + * Makes the components of this panel indicate the generation of the report + * is completed. + * + * @deprecated Use {@link #complete(ReportStatus)} + */ + @Deprecated + public void complete() { + complete(ReportStatus.COMPLETE); + } + } From e6a2334bf560d040391c2e7f460b83c0f5b690b9 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Tue, 22 Mar 2016 09:56:06 -0400 Subject: [PATCH 41/77] Redesigned ui to have standard gaps for file search. --- .../autopsy/filesearch/DateSearchPanel.form | 2 +- .../autopsy/filesearch/DateSearchPanel.java | 2 +- .../autopsy/filesearch/FileSearchPanel.java | 2 +- .../autopsy/filesearch/FilterArea.java | 22 ++++++++++--------- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.form index 0418d2eec7..1a9a1dd9f3 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.form +++ b/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.form @@ -134,7 +134,7 @@ - +
diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.java index 91a63186ed..baa4e63bcc 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.java @@ -276,7 +276,7 @@ class DateSearchPanel extends javax.swing.JPanel { .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel3) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(0, 0, 0)) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java index 903e62e6bc..5b169e9717 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java @@ -97,11 +97,11 @@ class FileSearchPanel extends javax.swing.JPanel { List metadataFilters = new ArrayList(); metadataFilters.add(new SizeSearchFilter()); + metadataFilters.add(new MimeTypeFilter()); metadataFilters.add(new DateSearchFilter()); this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.metadata"), metadataFilters)); this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.knownStatus"), new KnownStatusSearchFilter())); - this.filterAreas.add(new FilterArea("Test mime", new MimeTypeFilter())); for (FilterArea fa : this.filterAreas) { fa.setMaximumSize(new Dimension(Integer.MAX_VALUE, fa.getMinimumSize().height)); diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FilterArea.java b/Core/src/org/sleuthkit/autopsy/filesearch/FilterArea.java index 6c9329ca11..430fb47e5e 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FilterArea.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FilterArea.java @@ -92,20 +92,22 @@ class FilterArea extends JPanel { filtersPanel = new JPanel(); filtersPanel.setAlignmentX(Component.LEFT_ALIGNMENT); - BoxLayout filtersPanelLayout = new BoxLayout(filtersPanel, BoxLayout.Y_AXIS); - filtersPanel.setLayout(filtersPanelLayout); + BoxLayout filtersPanelLayout = new BoxLayout(this, BoxLayout.Y_AXIS); + this.setLayout(filtersPanelLayout); - for (FileSearchFilter f : filters) { + for (int i = 0; i < filters.size(); i++) { + FileSearchFilter f = filters.get(i); JComponent filterComponent = f.getComponent(); filterComponent.setAlignmentX(Component.LEFT_ALIGNMENT); - filterComponent.setBorder(new EmptyBorder(0, 0, 20, 0)); - filtersPanel.add(filterComponent); + if (i != filters.size() - 1) { + filterComponent.setBorder(new EmptyBorder(0, 0, 15, 0)); + } + else { + filterComponent.setBorder(new EmptyBorder(0, 0, 18, 0)); + } + this.add(filterComponent); } - - this.add(filtersPanel); - - BoxLayout layout = new BoxLayout(this, BoxLayout.Y_AXIS); - this.setLayout(layout); + this.setAlignmentX(Component.LEFT_ALIGNMENT); } private void refresh() { From 743cfc6fee9f3935878e3155644617df4a3375f6 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Tue, 22 Mar 2016 10:51:38 -0400 Subject: [PATCH 42/77] Fixed ui reset for file set name, added new icon logic to directory tree. --- .../org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java | 1 + Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java | 2 ++ .../org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java index 1112ffcb48..513ede01cd 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java @@ -129,6 +129,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { fileSetName = configPanel.getFileSetName(); } run(deviceId, fileSetName, localFilePaths, progressMonitor, callback); + this.reset(); } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java index b4741d13f5..cea0aecdac 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java @@ -144,6 +144,8 @@ class LocalFilesPanel extends JPanel { selectedPaths.setText(""); enableNext = false; errorLabel.setVisible(false); + displayName = ""; + this.displayNameLabel.setText("Display Name: Default"); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java index 16bb0b591d..f908251d28 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java @@ -55,7 +55,7 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode Date: Mon, 21 Mar 2016 15:10:32 -0400 Subject: [PATCH 43/77] use fileTypeDetector.detect use fileTypeDetector.detect --- .../corecomponents/MediaViewVideoPanel.java | 43 ++- .../corecomponents/ThumbnailViewChildren.java | 10 +- .../autopsy/coreutils/ImageUtils.java | 268 +++++++++--------- .../autopsy/coreutils/VideoUtils.java | 17 +- .../sleuthkit/autopsy/datamodel/FileNode.java | 71 ++--- .../autopsy/report/ReportGenerator.java | 36 +-- .../autopsy/imagegallery/FileTypeUtils.java | 50 +--- .../imagegallery/ImageGalleryController.java | 24 +- .../imagegallery/ImageGalleryModule.java | 4 +- .../autopsy/imagegallery/ThumbnailCache.java | 17 +- .../actions/CategorizeAction.java | 4 +- .../actions/CategorizeGroupAction.java | 3 +- .../imagegallery/datamodel/DrawableDB.java | 24 +- .../imagegallery/datamodel/DrawableFile.java | 7 +- .../datamodel/grouping/GroupManager.java | 3 +- .../gui/drawableviews/DrawableUIBase.java | 3 +- 16 files changed, 285 insertions(+), 299 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java index a3dc773abb..7ff9fcb411 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java @@ -21,14 +21,14 @@ package org.sleuthkit.autopsy.corecomponents; import java.awt.Dimension; import java.util.Arrays; import java.util.List; -import static java.util.Objects.nonNull; import java.util.Set; -import java.util.SortedSet; import java.util.TreeSet; import java.util.logging.Level; import javax.swing.JPanel; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.TskCoreException; /** * Video viewer part of the Media View layered pane. Uses different engines @@ -131,19 +131,38 @@ public abstract class MediaViewVideoPanel extends JPanel implements FrameCapture @Override public boolean isSupported(AbstractFile file) { - /* - * TODO (AUT-2042): Is this the logic we want? - */ String extension = file.getNameExtension(); + //TODO: is this what we want, to require both extension and mimetype support? if (AUDIO_EXTENSIONS.contains("." + extension) || getExtensionsList().contains("." + extension)) { - SortedSet mimeTypes = new TreeSet<>(getMimeTypes()); - String mimeType = file.getMIMEType(); - if (nonNull(mimeType)) { - return mimeTypes.contains(mimeType); - } else { - return getExtensionsList().contains("." + extension); - } + return true;//getExtensionsList().contains("." + extension); + } + + try { + String mimeType = new FileTypeDetector().detect(file); + return getMimeTypes().contains(mimeType); + } catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) { + logger.log(Level.WARNING, "Failed to look up mimetype for " + file.getName() + ".", ex); } return false; + +// String extension = file.getNameExtension(); +// //TODO: is this what we want, to require both extension and mimetype support? +// if (AUDIO_EXTENSIONS.contains("." + extension) || getExtensionsList().contains("." + extension)) { +// SortedSet mimeTypes = new TreeSet<>(getMimeTypes()); +// try { +// String mimeType = new FileTypeDetector().getFileType(file); +// if (nonNull(mimeType)) { +// return mimeTypes.contains(mimeType); +// } +// } catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) { +// logger.log(Level.WARNING, "Failed to look up mimetype for " + file.getName() + " using FileTypeDetector. Fallingback on AbstractFile.isMimeType", ex); +// if (!mimeTypes.isEmpty() && file.isMimeType(mimeTypes) == AbstractFile.MimeMatchEnum.TRUE) { +// return true; +// } +// } +// +// return getExtensionsList().contains("." + extension); +// } +// return false; } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java index e7a39f62ce..c84e8bc5ef 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java @@ -27,7 +27,7 @@ import org.openide.nodes.Node; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.AbstractFile; /** * Complementary class to ThumbnailViewNode. Children node factory. Wraps around @@ -132,11 +132,11 @@ class ThumbnailViewChildren extends Children.Keys { return new Node[]{pageNode}; } - public static boolean isSupported(Node node) { + static boolean isSupported(Node node) { if (node != null) { - Content content = node.getLookup().lookup(Content.class); - if (content != null) { - return ImageUtils.thumbnailSupported(content); + AbstractFile file = node.getLookup().lookup(AbstractFile.class); + if (file != null) { + return ImageUtils.isImageThumbnailSupported(file); } } return false; diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java index f6e87d22e5..94a5185f68 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java @@ -21,7 +21,6 @@ */ package org.sleuthkit.autopsy.coreutils; -import com.google.common.collect.ImmutableSortedSet; import com.google.common.io.Files; import java.awt.Image; import java.awt.image.BufferedImage; @@ -32,10 +31,10 @@ import java.io.InputStream; import java.nio.file.Paths; import java.text.MessageFormat; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Objects; import static java.util.Objects.nonNull; import java.util.SortedSet; import java.util.TreeSet; @@ -78,7 +77,7 @@ public class ImageUtils { /** * save thumbnails to disk as this format */ - private static final String FORMAT = "png"; //NON-NLS //NOI18N + private static final String FORMAT = "png"; //NON-NLS public static final int ICON_SIZE_SMALL = 50; public static final int ICON_SIZE_MEDIUM = 100; @@ -86,12 +85,11 @@ public class ImageUtils { private static final BufferedImage DEFAULT_THUMBNAIL; - private static final String IMAGE_GIF_MIME = "image/gif"; //NOI18N NON-NLS - private static final SortedSet GIF_MIME_SET = ImmutableSortedSet.copyOf(new String[]{IMAGE_GIF_MIME}); + private static final String GIF_EXTENSION = "gif"; + private static final String IMAGE_GIF_MIME = "image/gif"; //NON-NLS private static final List SUPPORTED_IMAGE_EXTENSIONS; private static final SortedSet SUPPORTED_IMAGE_MIME_TYPES; - private static final List CONDITIONAL_MIME_TYPES = Arrays.asList("audio/x-aiff", "application/octet-stream"); //NOI18N NON-NLS private static final boolean openCVLoaded; @@ -119,14 +117,13 @@ public class ImageUtils { openCVLoadedTemp = true; } catch (UnsatisfiedLinkError e) { openCVLoadedTemp = false; - LOGGER.log(Level.SEVERE, "OpenCV Native code library failed to load", e); //NOI18N NON-NLS + LOGGER.log(Level.SEVERE, "OpenCV Native code library failed to load", e); //NON-NLS //TODO: show warning bubble } openCVLoaded = openCVLoadedTemp; SUPPORTED_IMAGE_EXTENSIONS = Arrays.asList(ImageIO.getReaderFileSuffixes()); - SUPPORTED_IMAGE_MIME_TYPES = new TreeSet<>(Arrays.asList(ImageIO.getReaderMIMETypes())); /* * special cases and variants that we support, but don't get registered @@ -137,8 +134,8 @@ public class ImageUtils { "image/x-ms-bmp", //NON-NLS "image/x-portable-graymap", //NON-NLS "image/x-portable-bitmap", //NON-NLS - "application/x-123")); //TODO: is this correct? -jm //NOI18N NON-NLS - SUPPORTED_IMAGE_MIME_TYPES.removeIf("application/octet-stream"::equals); //NOI18N NON-NLS + "application/x-123")); //TODO: is this correct? -jm //NON-NLS + SUPPORTED_IMAGE_MIME_TYPES.removeIf("application/octet-stream"::equals); //NON-NLS } /** @@ -149,9 +146,9 @@ public class ImageUtils { /** * thread that saves generated thumbnails to disk in the background */ - private static final Executor imageSaver - = Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder() - .namingPattern("icon saver-%d").build()); //NOI18N NON-NLS + private static final Executor imageSaver = + Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder() + .namingPattern("thumbnail-saver-%d").build()); //NON-NLS public static List getSupportedImageExtensions() { return Collections.unmodifiableList(SUPPORTED_IMAGE_EXTENSIONS); @@ -161,19 +158,6 @@ public class ImageUtils { return Collections.unmodifiableSortedSet(SUPPORTED_IMAGE_MIME_TYPES); } - /** - * Get the default thumbnail, which is the icon for a file. Used when we can - * not generate content based thumbnail. - * - * @return - * - * @deprecated use {@link #getDefaultThumbnail() } instead. - */ - @Deprecated - public static Image getDefaultIcon() { - return getDefaultThumbnail(); - } - /** * Get the default thumbnail, which is the icon for a file. Used when we can * not generate content based thumbnail. @@ -184,31 +168,6 @@ public class ImageUtils { return DEFAULT_THUMBNAIL; } - /** - * Can a thumbnail be generated for the content? - * - * Although this method accepts Content, it always returns false for objects - * that are not instances of AbstractFile. - * - * @param content A content object to test for thumbnail support. - * - * @return true if a thumbnail can be generated for the given content. - */ - public static boolean thumbnailSupported(Content content) { - - if (content.getSize() == 0) { - return false; - } - if (!(content instanceof AbstractFile)) { - return false; - } - AbstractFile file = (AbstractFile) content; - - return VideoUtils.isVideoThumbnailSupported(file) - || isImageThumbnailSupported(file); - - } - /** * is the file an image that we can read and generate a thumbnail for * @@ -218,8 +177,7 @@ public class ImageUtils { * for. */ public static boolean isImageThumbnailSupported(AbstractFile file) { - return isMediaThumbnailSupported(file, SUPPORTED_IMAGE_MIME_TYPES, SUPPORTED_IMAGE_EXTENSIONS, CONDITIONAL_MIME_TYPES) - || hasImageFileHeader(file); + return hasImageFileHeader(file) || isMediaThumbnailSupported(file, SUPPORTED_IMAGE_MIME_TYPES, SUPPORTED_IMAGE_EXTENSIONS); } /** @@ -231,16 +189,11 @@ public class ImageUtils { * @return True or false */ public static boolean isGIF(AbstractFile file) { - String mimeType = file.getMIMEType(); - if (nonNull(mimeType)) { - return IMAGE_GIF_MIME.equalsIgnoreCase(mimeType); - } else { - return "gif".equalsIgnoreCase(file.getNameExtension()); //NOI18N - } + return isMediaThumbnailSupported(file, Arrays.asList(IMAGE_GIF_MIME), Arrays.asList(GIF_EXTENSION)); } /** - * Check if a file is "supported" by checking its mimetype and extension + * Check if a file is "supported" by checking its extension and/or MIME type * * //TODO: this should move to a better place. Should ImageUtils and * VideoUtils both implement/extend some base interface/abstract class. That @@ -252,24 +205,26 @@ public class ImageUtils { * @param supportedExtension a set of extensions a file could have to be * supported if the mime lookup fails or is * inconclusive - * @param conditionalMimes a set of mimetypes that a file could have to be - * supoprted if it also has a supported extension * * @return true if a thumbnail can be generated for the given file based on * the given lists of supported mimetype and extensions */ - static boolean isMediaThumbnailSupported(AbstractFile file, final SortedSet supportedMimeTypes, final List supportedExtension, List conditionalMimes) { - if (file.getSize() == 0) { + static boolean isMediaThumbnailSupported(AbstractFile file, final Collection supportedMimeTypes, final List supportedExtension) { + if (false == file.isFile() || file.getSize() <= 0) { return false; } - String mimeType = file.getMIMEType(); + String extension = file.getNameExtension(); - if (nonNull(mimeType)) { - return supportedMimeTypes.contains(mimeType) - || (conditionalMimes.contains(mimeType.toLowerCase()) - && supportedExtension.contains(extension)); + + if (StringUtils.isNotBlank(extension) && supportedExtension.contains(extension)) { + return true; } else { - return StringUtils.isNotBlank(extension) && supportedExtension.contains(extension); + try { + return supportedMimeTypes.contains(getFileTypeDetector().detect(file)); + } catch (FileTypeDetectorInitException | TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Error determining MIME type of " + getContentPathSafe(file), ex); + return false; + } } } @@ -288,25 +243,6 @@ public class ImageUtils { return fileTypeDetector; } - /** - * Get a thumbnail of a specified size for the given image. Generates the - * thumbnail if it is not already cached. - * - * @param content - * @param iconSize - * - * @return a thumbnail for the given image or a default one if there was a - * problem making a thumbnail. - * - * @deprecated use {@link #getThumbnail(org.sleuthkit.datamodel.Content, int) - * } instead. - */ - @Nonnull - @Deprecated - public static BufferedImage getIcon(Content content, int iconSize) { - return getThumbnail(content, iconSize); - } - /** * Get a thumbnail of a specified size for the given image. Generates the * thumbnail if it is not already cached. @@ -334,27 +270,6 @@ public class ImageUtils { } } - /** - * Get a thumbnail of a specified size for the given image. Generates the - * thumbnail if it is not already cached. - * - * @param content - * @param iconSize - * - * @return File object for cached image. Is guaranteed to exist, as long as - * there was not an error generating or saving the thumbnail. - * - * @deprecated use {@link #getCachedThumbnailFile(org.sleuthkit.datamodel.Content, int) - * } instead. - * - */ - @Nullable - @Deprecated - public static File getIconFile(Content content, int iconSize) { - return getCachedThumbnailFile(content, iconSize); - - } - /** * * Get a thumbnail of a specified size for the given image. Generates the @@ -372,22 +287,6 @@ public class ImageUtils { return getCachedThumbnailLocation(content.getId()); } - /** - * Get a file object for where the cached icon should exist. The returned - * file may not exist. - * - * @param id - * - * @return - * - * @deprecated use {@link #getCachedThumbnailLocation(long) } instead - */ - @Deprecated - - public static File getFile(long id) { - return getCachedThumbnailLocation(id); - } - /** * Get a file object for where the cached thumbnail should exist. The * returned file may not exist. @@ -409,18 +308,6 @@ public class ImageUtils { } - /** - * Do a direct check to see if the given file has an image file header. - * NOTE: Currently only jpeg and png are supported. - * - * @param file - * - * @return true if the given file has one of the supported image headers. - */ - public static boolean hasImageFileHeader(AbstractFile file) { - return isJpegFileHeader(file) || isPngFileHeader(file); - } - /** * Check if the given file is a jpeg based on header. * @@ -912,4 +799,109 @@ public class ImageUtils { return contentName; } } + + /** + * Get the default thumbnail, which is the icon for a file. Used when we can + * not generate content based thumbnail. + * + * @return + * + * @deprecated use {@link #getDefaultThumbnail() } instead. + */ + @Deprecated + public static Image getDefaultIcon() { + return getDefaultThumbnail(); + } + + /** + * Get a file object for where the cached icon should exist. The returned + * file may not exist. + * + * @param id + * + * @return + * + * @deprecated use {@link #getCachedThumbnailLocation(long) } instead + */ + @Deprecated + + public static File getFile(long id) { + return getCachedThumbnailLocation(id); + } + + /** + * Get a thumbnail of a specified size for the given image. Generates the + * thumbnail if it is not already cached. + * + * @param content + * @param iconSize + * + * @return a thumbnail for the given image or a default one if there was a + * problem making a thumbnail. + * + * @deprecated use {@link #getThumbnail(org.sleuthkit.datamodel.Content, int) + * } instead. + */ + @Nonnull + @Deprecated + public static BufferedImage getIcon(Content content, int iconSize) { + return getThumbnail(content, iconSize); + } + + /** + * Get a thumbnail of a specified size for the given image. Generates the + * thumbnail if it is not already cached. + * + * @param content + * @param iconSize + * + * @return File object for cached image. Is guaranteed to exist, as long as + * there was not an error generating or saving the thumbnail. + * + * @deprecated use {@link #getCachedThumbnailFile(org.sleuthkit.datamodel.Content, int) + * } instead. + * + */ + @Nullable + @Deprecated + public static File getIconFile(Content content, int iconSize) { + return getCachedThumbnailFile(content, iconSize); + + } + + /** + * Do a direct check to see if the given file has an image file header. + * NOTE: Currently only jpeg and png are supported. + * + * @param file + * + * @return true if the given file has one of the supported image headers. + */ + @Deprecated + public static boolean hasImageFileHeader(AbstractFile file) { + return isJpegFileHeader(file) || isPngFileHeader(file); + } + + /** + * Can a thumbnail be generated for the content? + * + * Although this method accepts Content, it always returns false for objects + * that are not instances of AbstractFile. + * + * @param content A content object to test for thumbnail support. + * + * @return true if a thumbnail can be generated for the given content. + */ + @Deprecated + public static boolean thumbnailSupported(Content content) { + + if (!(content instanceof AbstractFile)) { + return false; + } + AbstractFile file = (AbstractFile) content; + + return VideoUtils.isVideoThumbnailSupported(file) + || isImageThumbnailSupported(file); + } + } diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/VideoUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/VideoUtils.java index 58c61e955b..42c3e076c5 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/VideoUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/VideoUtils.java @@ -60,10 +60,17 @@ public class VideoUtils { "flm", "tmv", "4xm"); //NON-NLS private static final SortedSet SUPPORTED_VIDEO_MIME_TYPES = new TreeSet<>( - Arrays.asList("application/x-shockwave-flash", "video/x-m4v", "video/x-flv", "video/quicktime", "video/avi", "video/msvideo", "video/x-msvideo", //NON-NLS - "video/mp4", "video/x-ms-wmv", "video/mpeg", "video/asf")); //NON-NLS - - private static final List CONDITIONAL_MIME_TYPES = Arrays.asList("application/octet-stream"); //NON-NLS + Arrays.asList("application/x-shockwave-flash", + "video/x-m4v", + "video/x-flv", + "video/quicktime", + "video/avi", + "video/msvideo", + "video/x-msvideo", //NON-NLS + "video/mp4", + "video/x-ms-wmv", + "video/mpeg", + "video/asf")); //NON-NLS public static List getSupportedVideoExtensions() { return SUPPORTED_VIDEO_EXTENSIONS; @@ -89,7 +96,7 @@ public class VideoUtils { } public static boolean isVideoThumbnailSupported(AbstractFile file) { - return isMediaThumbnailSupported(file, SUPPORTED_VIDEO_MIME_TYPES, SUPPORTED_VIDEO_EXTENSIONS, CONDITIONAL_MIME_TYPES); + return isMediaThumbnailSupported(file, SUPPORTED_VIDEO_MIME_TYPES, SUPPORTED_VIDEO_EXTENSIONS); } @NbBundle.Messages({"# {0} - file name", diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java index d740149ffe..8b54e5a7b6 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.datamodel; import java.util.ArrayList; import java.util.List; import javax.swing.Action; +import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.actions.AddContentTagAction; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; @@ -110,70 +111,52 @@ public class FileNode extends AbstractFsContentNode { // file based off it's extension static String getIconForFileType(AbstractFile file) { // Get the name, extension - String name = file.getName(); - int dotIndex = name.lastIndexOf("."); - if (dotIndex == -1) { - return "org/sleuthkit/autopsy/images/file-icon.png"; //NON-NLS - } - String ext = name.substring(dotIndex).toLowerCase(); + String ext = file.getNameExtension(); - // Images - for (String s : FileTypeExtensions.getImageExtensions()) { - if (ImageUtils.thumbnailSupported(file) || ext.equals(s)) { - return "org/sleuthkit/autopsy/images/image-file.png"; //NON-NLS - } + if (StringUtils.isBlank(ext)) { + return "org/sleuthkit/autopsy/images/file-icon.png"; //NON-NLS + } else { + ext = "." + ext; + } + + if (ImageUtils.isImageThumbnailSupported(file) + || FileTypeExtensions.getImageExtensions().contains(ext)) { + return "org/sleuthkit/autopsy/images/image-file.png"; //NON-NLS } // Videos - for (String s : FileTypeExtensions.getVideoExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/video-file.png"; //NON-NLS - } + if (FileTypeExtensions.getVideoExtensions().contains(ext)) { + return "org/sleuthkit/autopsy/images/video-file.png"; //NON-NLS } // Audio Files - for (String s : FileTypeExtensions.getAudioExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/audio-file.png"; //NON-NLS - } + if (FileTypeExtensions.getAudioExtensions().contains(ext)) { + return "org/sleuthkit/autopsy/images/audio-file.png"; //NON-NLS } // Documents - for (String s : FileTypeExtensions.getDocumentExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/doc-file.png"; //NON-NLS - } + if (FileTypeExtensions.getDocumentExtensions().contains(ext)) { + return "org/sleuthkit/autopsy/images/doc-file.png"; //NON-NLS } // Executables / System Files - for (String s : FileTypeExtensions.getExecutableExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/exe-file.png"; //NON-NLS - } + if (FileTypeExtensions.getExecutableExtensions().contains(ext)) { + return "org/sleuthkit/autopsy/images/exe-file.png"; //NON-NLS } // Text Files - for (String s : FileTypeExtensions.getTextExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/text-file.png"; //NON-NLS - } + if (FileTypeExtensions.getTextExtensions().contains(ext)) { + return "org/sleuthkit/autopsy/images/text-file.png"; //NON-NLS } // Web Files - for (String s : FileTypeExtensions.getWebExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/web-file.png"; //NON-NLS - } + if (FileTypeExtensions.getWebExtensions().contains(ext)) { + return "org/sleuthkit/autopsy/images/web-file.png"; //NON-NLS } // PDFs - for (String s : FileTypeExtensions.getPDFExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/pdf-file.png"; //NON-NLS - } + if (FileTypeExtensions.getPDFExtensions().contains(ext)) { + return "org/sleuthkit/autopsy/images/pdf-file.png"; //NON-NLS } // Archives - for (String s : FileTypeExtensions.getArchiveExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/archive-file.png"; //NON-NLS - } + if (FileTypeExtensions.getArchiveExtensions().contains(ext)) { + return "org/sleuthkit/autopsy/images/archive-file.png"; //NON-NLS } // Else return the default return "org/sleuthkit/autopsy/images/file-icon.png"; //NON-NLS - } @Override diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 38a5931427..8286c4d429 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -34,7 +34,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -53,7 +52,6 @@ import javax.swing.SwingWorker; import org.openide.filesystems.FileUtil; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; @@ -66,13 +64,13 @@ import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; +import org.sleuthkit.datamodel.BlackboardAttribute.Type; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; -import org.sleuthkit.datamodel.BlackboardAttribute.Type; /** * Instances of this class use GeneralReportModules, TableReportModules and @@ -530,8 +528,8 @@ class ReportGenerator { } /* - Gets all of the attribute types of this artifact type by adding - all of the types to a set + * Gets all of the attribute types of this artifact type by + * adding all of the types to a set */ Set attrTypeSet = new TreeSet<>((Type o1, Type o2) -> o1.getDisplayName().compareTo(o2.getDisplayName())); for (ArtifactData data : artifactList) { @@ -858,7 +856,7 @@ class ReportGenerator { return; } - if (ImageUtils.thumbnailSupported(file)) { + if (ImageUtils.isImageThumbnailSupported(file)) { images.add(file); } } @@ -929,8 +927,8 @@ class ReportGenerator { } else { orderByClause = "ORDER BY list ASC"; //NON-NLS } - String keywordListQuery - = "SELECT att.value_text AS list " + //NON-NLS + String keywordListQuery = + "SELECT att.value_text AS list " + //NON-NLS "FROM blackboard_attributes AS att, blackboard_artifacts AS art " + //NON-NLS "WHERE att.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " " + //NON-NLS "AND art.artifact_type_id = " + ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + " " + //NON-NLS @@ -972,8 +970,8 @@ class ReportGenerator { orderByClause = "ORDER BY list ASC, keyword ASC, parent_path ASC, name ASC, preview ASC"; //NON-NLS } // Query for keywords, grouped by list - String keywordsQuery - = "SELECT art.artifact_id, art.obj_id, att1.value_text AS keyword, att2.value_text AS preview, att3.value_text AS list, f.name AS name, f.parent_path AS parent_path " + //NON-NLS + String keywordsQuery = + "SELECT art.artifact_id, art.obj_id, att1.value_text AS keyword, att2.value_text AS preview, att3.value_text AS list, f.name AS name, f.parent_path AS parent_path " + //NON-NLS "FROM blackboard_artifacts AS art, blackboard_attributes AS att1, blackboard_attributes AS att2, blackboard_attributes AS att3, tsk_files AS f " + //NON-NLS "WHERE (att1.artifact_id = art.artifact_id) " + //NON-NLS "AND (att2.artifact_id = art.artifact_id) " + //NON-NLS @@ -1093,8 +1091,8 @@ class ReportGenerator { } else { orderByClause = "ORDER BY att.value_text ASC"; //NON-NLS } - String hashsetsQuery - = "SELECT att.value_text AS list " + //NON-NLS + String hashsetsQuery = + "SELECT att.value_text AS list " + //NON-NLS "FROM blackboard_attributes AS att, blackboard_artifacts AS art " + //NON-NLS "WHERE att.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " " + //NON-NLS "AND art.artifact_type_id = " + ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() + " " + //NON-NLS @@ -1130,8 +1128,8 @@ class ReportGenerator { } else { orderByClause = "ORDER BY att.value_text ASC, f.parent_path ASC, f.name ASC, size ASC"; //NON-NLS } - String hashsetHitsQuery - = "SELECT art.artifact_id, art.obj_id, att.value_text AS setname, f.name AS name, f.size AS size, f.parent_path AS parent_path " + //NON-NLS + String hashsetHitsQuery = + "SELECT art.artifact_id, art.obj_id, att.value_text AS setname, f.name AS name, f.size AS size, f.parent_path AS parent_path " + //NON-NLS "FROM blackboard_artifacts AS art, blackboard_attributes AS att, tsk_files AS f " + //NON-NLS "WHERE (att.artifact_id = art.artifact_id) " + //NON-NLS "AND (f.obj_id = art.obj_id) " + //NON-NLS @@ -2048,10 +2046,12 @@ class ReportGenerator { @Override public String getCellData(ArtifactData artData) { return getFileUniquePath(artData.getContent()); - /*else if (this.columnHeader.equals(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"))) { - return makeCommaSeparatedList(artData.getTags()); - } - return "";*/ + /* + * else if + * (this.columnHeader.equals(NbBundle.getMessage(this.getClass(), + * "ReportGenerator.artTableColHdr.tags"))) { return + * makeCommaSeparatedList(artData.getTags()); } return ""; + */ } @Override diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java index 764a4fa4d1..9af389ad94 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java @@ -23,13 +23,11 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import static java.util.Objects.isNull; -import java.util.Optional; import java.util.Set; -import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.imageio.ImageIO; -import org.sleuthkit.autopsy.coreutils.ImageUtils; +import org.apache.commons.lang3.StringUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; @@ -149,13 +147,9 @@ public enum FileTypeUtils { return Collections.unmodifiableSet(supportedExtensions); } - static synchronized FileTypeDetector getFileTypeDetector() { + static synchronized FileTypeDetector getFileTypeDetector() throws FileTypeDetector.FileTypeDetectorInitException { if (isNull(FILE_TYPE_DETECTOR)) { - try { - FILE_TYPE_DETECTOR = new FileTypeDetector(); - } catch (FileTypeDetector.FileTypeDetectorInitException ex) { - LOGGER.log(Level.SEVERE, "Failed to initialize File Type Detector, will fall back on extensions in some situations.", ex); //NON-NLS - } + FILE_TYPE_DETECTOR = new FileTypeDetector(); } return FILE_TYPE_DETECTOR; } @@ -169,24 +163,16 @@ public enum FileTypeUtils { * * @return true if this file is supported or false if not */ - public static boolean isDrawable(AbstractFile file) throws TskCoreException { - return hasDrawableMimeType(file).orElseGet(() -> { - return FileTypeUtils.supportedExtensions.contains(file.getNameExtension().toLowerCase()) - || ImageUtils.isJpegFileHeader(file) - || ImageUtils.isPngFileHeader(file); - }); + public static boolean isDrawable(AbstractFile file) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { + return hasDrawableMIMEType(file); } - public static boolean isGIF(AbstractFile file) { - return ImageUtils.isGIF(file); - } - - public static Optional getMimeType(AbstractFile file) throws TskCoreException { - return Optional.ofNullable(file.getMIMEType()); + public static String getMimeType(AbstractFile file) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { + return getFileTypeDetector().getFileType(file); } static boolean isDrawableMimeType(String mimeType) { - if (isNull(mimeType)) { + if (StringUtils.isBlank(mimeType)) { return false; } else { String mimeTypeLower = mimeType.toLowerCase(); @@ -205,8 +191,10 @@ public enum FileTypeUtils { * type. False if a non image/video mimetype. empty Optional if a * mimetype could not be detected. */ - static Optional hasDrawableMimeType(AbstractFile file) throws TskCoreException { - return getMimeType(file).map(FileTypeUtils::isDrawableMimeType); + static boolean hasDrawableMIMEType(AbstractFile file) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { + String mimeType = getMimeType(file).toLowerCase(); + return isDrawableMimeType(mimeType) || (mimeType.equals("audio/x-aiff") && "tiff".equalsIgnoreCase(file.getNameExtension())); + } /** @@ -218,16 +206,8 @@ public enum FileTypeUtils { * application/x-shockwave-flash, etc) or, if no mimetype is * available, a video extension. */ - public static boolean isVideoFile(AbstractFile file) { - try { - return getMimeType(file) - .map(String::toLowerCase) - .map(mimeType - -> mimeType.startsWith("video/") - || videoMimeTypes.contains(mimeType)) - .orElseGet(() -> FileTypeUtils.videoExtensions.contains(file.getNameExtension())); - } catch (TskCoreException ex) { - return FileTypeUtils.videoExtensions.contains(file.getNameExtension()); - } + public static boolean hasVideoMIMEType(AbstractFile file) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { + String mimeType = getMimeType(file).toLowerCase(); + return mimeType.startsWith("video/") || videoMimeTypes.contains(mimeType); } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index 897667e846..0a1474926c 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -22,7 +22,6 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -77,6 +76,7 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewState; import org.sleuthkit.autopsy.imagegallery.gui.NoGroupsDialog; import org.sleuthkit.autopsy.imagegallery.gui.Toolbar; import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.SleuthkitCase; @@ -443,7 +443,7 @@ public final class ImageGalleryController implements Executor { } @Nullable - synchronized public DrawableFile getFileFromId(Long fileID) throws TskCoreException { + synchronized public DrawableFile getFileFromId(Long fileID) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { if (Objects.isNull(db)) { LOGGER.log(Level.WARNING, "Could not get file from id, no DB set. The case is probably closed."); //NON-NLS return null; @@ -848,23 +848,15 @@ public final class ImageGalleryController implements Executor { if (known) { taskDB.removeFile(f.getId(), tr); //remove known files } else { - Optional mimeType = FileTypeUtils.getMimeType(f); - if (mimeType.isPresent()) { - //mime type - if (FileTypeUtils.isDrawableMimeType(mimeType.get())) { //supported mimetype => analyzed + + try { + if (FileTypeUtils.hasDrawableMIMEType(f)) { //supported mimetype => analyzed taskDB.updateFile(DrawableFile.create(f, true, false), tr); } else { //unsupported mimtype => analyzed but shouldn't include taskDB.removeFile(f.getId(), tr); } - } else { - //no mime tyoe - if (FileTypeUtils.isDrawable(f)) { - //no mime type but supported => add as not analyzed - taskDB.insertFile(DrawableFile.create(f, false, false), tr); - } else { - //no mime type, not supported => remove ( should never get here) - taskDB.removeFile(f.getId(), tr); - } + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + throw new RuntimeException(ex); } } } @@ -968,7 +960,7 @@ public final class ImageGalleryController implements Executor { //this file would have gotten scooped up in initial grab, but actually we don't need it queueDBWorkerTask(new RemoveFileTask(file, db)); } - } catch (TskCoreException ex) { + } catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) { //TODO: What to do here? LOGGER.log(Level.WARNING, "Unable to determine if file is drawable and not known. Not making any changes to DB", ex); //NON-NLS throw new RuntimeException(ex); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java index 770df56132..a5f13c1d9a 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java @@ -22,11 +22,11 @@ import java.nio.file.Path; import java.nio.file.Paths; import org.apache.commons.lang3.StringUtils; import static org.apache.commons.lang3.StringUtils.isNotBlank; - import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; @@ -105,7 +105,7 @@ public class ImageGalleryModule { * @return true if the given {@link AbstractFile} is "drawable" and not * 'known', else false */ - public static boolean isDrawableAndNotKnown(AbstractFile abstractFile) throws TskCoreException { + public static boolean isDrawableAndNotKnown(AbstractFile abstractFile) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { return (abstractFile.getKnown() != TskData.FileKnown.KNOWN) && FileTypeUtils.isDrawable(abstractFile); } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java index dfd60e5d13..2463d9dc59 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java @@ -44,6 +44,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.gui.Toolbar; import org.sleuthkit.autopsy.imagegallery.utils.TaskUtils; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.TskCoreException; @@ -97,7 +98,7 @@ public enum ThumbnailCache { * could not be generated */ @Nullable - public Image get(DrawableFile file) { + public Image get(AbstractFile file) { try { return cache.get(file.getId(), () -> load(file)); } catch (UncheckedExecutionException | CacheLoader.InvalidCacheLoadException | ExecutionException ex) { @@ -109,7 +110,7 @@ public enum ThumbnailCache { @Nullable public Image get(Long fileID) { try { - return get(ImageGalleryController.getDefault().getFileFromId(fileID)); + return get(ImageGalleryController.getDefault().getSleuthKitCase().getAbstractFileById(fileID)); } catch (TskCoreException ex) { LOGGER.log(Level.WARNING, "Failed to load thumbnail for file: " + fileID, ex.getCause()); //NON-NLS return null; @@ -124,12 +125,12 @@ public enum ThumbnailCache { * * @return an (possibly empty) optional containing a thumbnail */ - private Image load(DrawableFile file) { + private Image load(AbstractFile file) { - if (FileTypeUtils.isGIF(file.getAbstractFile())) { + if (ImageUtils.isGIF(file)) { //directly read gif to preserve potential animation, //NOTE: not saved to disk! - return new Image(new BufferedInputStream(new ReadContentInputStream(file.getAbstractFile())), MAX_THUMBNAIL_SIZE, MAX_THUMBNAIL_SIZE, true, true); + return new Image(new BufferedInputStream(new ReadContentInputStream(file)), MAX_THUMBNAIL_SIZE, MAX_THUMBNAIL_SIZE, true, true); } BufferedImage thumbnail = getCacheFile(file).map(cachFile -> { @@ -149,7 +150,7 @@ public enum ThumbnailCache { } return null; }).orElseGet(() -> { - return ImageUtils.getThumbnail(file.getAbstractFile(), MAX_THUMBNAIL_SIZE); + return ImageUtils.getThumbnail(file, MAX_THUMBNAIL_SIZE); }); WritableImage jfxthumbnail; @@ -171,9 +172,9 @@ public enum ThumbnailCache { * @return a Optional containing a File to store the cached icon in or an * empty optional if there was a problem. */ - private static Optional getCacheFile(DrawableFile file) { + private static Optional getCacheFile(AbstractFile file) { try { - return Optional.of(ImageUtils.getCachedThumbnailFile(file.getAbstractFile(), MAX_THUMBNAIL_SIZE)); + return Optional.of(ImageUtils.getCachedThumbnailFile(file, MAX_THUMBNAIL_SIZE)); } catch (Exception e) { LOGGER.log(Level.WARNING, "Failed to create cache file.{0}", e.getLocalizedMessage()); //NON-NLS diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java index b91b857e60..152f0dab25 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java @@ -45,6 +45,7 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableTagsManager; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TagName; @@ -84,7 +85,6 @@ public class CategorizeAction extends Action { return new CategoryMenu(controller); } - final void addCatToFiles(Set ids) { Logger.getAnonymousLogger().log(Level.INFO, "categorizing{0} as {1}", new Object[]{ids.toString(), cat.getDisplayName()}); //NON-NLS controller.queueDBWorkerTask(new CategorizeTask(ids, cat, createUndo)); @@ -167,7 +167,7 @@ public class CategorizeAction extends Action { tagsManager.addContentTag(file, tagName, ""); } } - } catch (TskCoreException ex) { + } catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) { LOGGER.log(Level.SEVERE, "Error categorizing result", ex); //NON-NLS JOptionPane.showMessageDialog(null, Bundle.CategorizeTask_errorUnable_msg(fileID), diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java index cc2ede2ce5..35dc0a9158 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java @@ -39,6 +39,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryPreferences; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.TskCoreException; /** @@ -66,7 +67,7 @@ public class CategorizeGroupAction extends CategorizeAction { if (false == Category.ZERO.equals(category) && newCat.equals(category) == false) { catCountMap.merge(category, 1L, Long::sum); } - } catch (TskCoreException ex) { + } catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) { LOGGER.log(Level.SEVERE, "Failed to categorize files.", ex); } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index bf46596ed5..e2b2d0db80 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -34,7 +34,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import static java.util.Objects.isNull; import static java.util.Objects.nonNull; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -55,6 +54,7 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupKey; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupSortBy; import static org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupSortBy.GROUP_BY_VALUE; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -979,7 +979,7 @@ public final class DrawableDB { * @throws TskCoreException if unable to get a file from the currently open * {@link SleuthkitCase} */ - private DrawableFile getFileFromID(Long id, boolean analyzed) throws TskCoreException { + private DrawableFile getFileFromID(Long id, boolean analyzed) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { try { AbstractFile f = tskCase.getAbstractFileById(id); return DrawableFile.create(f, analyzed, isVideoFile(f)); @@ -997,7 +997,7 @@ public final class DrawableDB { * @throws TskCoreException if unable to get a file from the currently open * {@link SleuthkitCase} */ - public DrawableFile getFileFromID(Long id) throws TskCoreException { + public DrawableFile getFileFromID(Long id) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { try { AbstractFile f = tskCase.getAbstractFileById(id); return DrawableFile.create(f, @@ -1174,10 +1174,18 @@ public final class DrawableDB { * @return returns true if this file is a video as determined by {@link ImageGalleryModule#isVideoFile(org.sleuthkit.datamodel.AbstractFile) * } but caches the result. returns false if passed a null AbstractFile */ - public boolean isVideoFile(AbstractFile f) { - return isNull(f) ? false - : videoFileMap.computeIfAbsent(f.getId(), id -> FileTypeUtils.isVideoFile(f)); + public boolean isVideoFile(AbstractFile f) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { + if (null == f) { + return false; + } else { + Boolean isVideo = videoFileMap.get(f.getId()); + if (null == isVideo) { + isVideo = FileTypeUtils.hasVideoMIMEType(f); + videoFileMap.put(f.getId(), isVideo); + } + return isVideo; + } } /** @@ -1242,8 +1250,8 @@ public final class DrawableDB { String fileIdsList = "(" + StringUtils.join(fileIDs, ",") + " )"; //count the fileids that are in the given list and don't have a non-zero category assigned to them. - String name - = "SELECT COUNT(obj_id) FROM tsk_files where obj_id IN " + fileIdsList //NON-NLS + String name = + "SELECT COUNT(obj_id) FROM tsk_files where obj_id IN " + fileIdsList //NON-NLS + " AND obj_id NOT IN (SELECT obj_id FROM content_tags WHERE content_tags.tag_name_id IN " + catTagNameIDs + ")"; //NON-NLS try (SleuthkitCase.CaseDbQuery executeQuery = controller.getSleuthKitCase().executeQuery(name); ResultSet resultSet = executeQuery.getResultSet();) { diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java index 678069db9d..7a74188c5a 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java @@ -41,6 +41,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.FileTypeUtils; import org.sleuthkit.autopsy.imagegallery.ThumbnailCache; import org.sleuthkit.autopsy.imagegallery.utils.TaskUtils; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; @@ -59,8 +60,8 @@ public abstract class DrawableFile { private static final Logger LOGGER = Logger.getLogger(DrawableFile.class.getName()); - public static DrawableFile create(AbstractFile abstractFileById, boolean analyzed) { - return create(abstractFileById, analyzed, FileTypeUtils.isVideoFile(abstractFileById)); + public static DrawableFile create(AbstractFile abstractFileById, boolean analyzed) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { + return create(abstractFileById, analyzed, FileTypeUtils.hasVideoMIMEType(abstractFileById)); } /** @@ -72,7 +73,7 @@ public abstract class DrawableFile { : new ImageFile(abstractFileById, analyzed); } - public static DrawableFile create(Long id, boolean analyzed) throws TskCoreException, IllegalStateException { + public static DrawableFile create(Long id, boolean analyzed) throws TskCoreException, IllegalStateException, FileTypeDetector.FileTypeDetectorInitException { return create(Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(id), analyzed); } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java index b52702728a..0c31b3c299 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java @@ -78,6 +78,7 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableTagsManager; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.SleuthkitCase; @@ -199,7 +200,7 @@ public class GroupManager { } else { Logger.getLogger(GroupManager.class.getName()).log(Level.WARNING, "Failed to load file with id: {0} from database. There is no database assigned.", fileID); //NON-NLS } - } catch (TskCoreException ex) { + } catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) { Logger.getLogger(GroupManager.class.getName()).log(Level.SEVERE, "failed to load file with id: " + fileID + " from database", ex); //NON-NLS } return Collections.emptySet(); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableUIBase.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableUIBase.java index da8120f632..9069ebf5a3 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableUIBase.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableUIBase.java @@ -46,6 +46,7 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.actions.OpenExternalViewerAction; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.TskCoreException; /** @@ -101,7 +102,7 @@ abstract public class DrawableUIBase extends AnchorPane implements DrawableView } else { try { fileOpt = Optional.ofNullable(getController().getFileFromId(fileIDOpt.get())); - } catch (TskCoreException ex) { + } catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) { Logger.getAnonymousLogger().log(Level.WARNING, "failed to get DrawableFile for obj_id" + fileIDOpt.get(), ex); //NON-NLS fileOpt = Optional.empty(); } From 4b542f6d492e88add56945812a34e724adce984b Mon Sep 17 00:00:00 2001 From: jmillman Date: Tue, 22 Mar 2016 11:24:04 -0400 Subject: [PATCH 44/77] improve ImageUtils.isGIF and cleanup minor cleanup in ImageUtils --- .../DataContentViewerMedia.java | 4 - .../corecomponents/MediaViewVideoPanel.java | 42 ++++------ .../corecomponents/ThumbnailViewChildren.java | 8 +- .../autopsy/coreutils/ImageUtils.java | 84 ++++++++++--------- .../autopsy/coreutils/VideoUtils.java | 2 +- .../autopsy/imagegallery/FileTypeUtils.java | 37 ++++++-- .../imagegallery/ImageGalleryController.java | 2 +- .../autopsy/imagegallery/ThumbnailCache.java | 17 ++-- .../actions/CategorizeAction.java | 3 +- .../actions/CategorizeGroupAction.java | 3 +- .../imagegallery/datamodel/DrawableDB.java | 4 +- .../imagegallery/datamodel/DrawableFile.java | 5 +- .../gui/drawableviews/DrawableUIBase.java | 3 +- 13 files changed, 108 insertions(+), 106 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index 9c1efe9b21..b8e03d51d6 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -22,8 +22,6 @@ import java.awt.CardLayout; import java.awt.Component; import java.awt.Dimension; import java.util.List; -import java.util.SortedSet; -import java.util.TreeSet; import java.util.logging.Level; import org.openide.nodes.Node; import org.openide.util.NbBundle; @@ -47,7 +45,6 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo //UI private final MediaViewVideoPanel videoPanel; private final boolean videoPanelInited; - private final SortedSet videoExtensions; // get them from the panel private final MediaViewImagePanel imagePanel; private final boolean imagePanelInited; @@ -64,7 +61,6 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo // get the right panel for our platform videoPanel = MediaViewVideoPanel.createVideoPanel(); videoPanelInited = videoPanel.isInited(); - videoExtensions = new TreeSet<>(videoPanel.getExtensionsList()); imagePanel = new MediaViewImagePanel(); imagePanelInited = imagePanel.isInited(); diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java index 7ff9fcb411..3bf297b036 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java @@ -21,7 +21,9 @@ package org.sleuthkit.autopsy.corecomponents; import java.awt.Dimension; import java.util.Arrays; import java.util.List; +import static java.util.Objects.nonNull; import java.util.Set; +import java.util.SortedSet; import java.util.TreeSet; import java.util.logging.Level; import javax.swing.JPanel; @@ -134,35 +136,21 @@ public abstract class MediaViewVideoPanel extends JPanel implements FrameCapture String extension = file.getNameExtension(); //TODO: is this what we want, to require both extension and mimetype support? if (AUDIO_EXTENSIONS.contains("." + extension) || getExtensionsList().contains("." + extension)) { - return true;//getExtensionsList().contains("." + extension); - } + SortedSet mimeTypes = new TreeSet<>(getMimeTypes()); + try { + String mimeType = new FileTypeDetector().detect(file); + if (nonNull(mimeType)) { + return mimeTypes.contains(mimeType); + } + } catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) { + logger.log(Level.WARNING, "Failed to look up mimetype for " + file.getName() + " using FileTypeDetector. Fallingback on AbstractFile.isMimeType", ex); + if (!mimeTypes.isEmpty() && file.isMimeType(mimeTypes) == AbstractFile.MimeMatchEnum.TRUE) { + return true; + } + } - try { - String mimeType = new FileTypeDetector().detect(file); - return getMimeTypes().contains(mimeType); - } catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) { - logger.log(Level.WARNING, "Failed to look up mimetype for " + file.getName() + ".", ex); + return getExtensionsList().contains("." + extension); } return false; - -// String extension = file.getNameExtension(); -// //TODO: is this what we want, to require both extension and mimetype support? -// if (AUDIO_EXTENSIONS.contains("." + extension) || getExtensionsList().contains("." + extension)) { -// SortedSet mimeTypes = new TreeSet<>(getMimeTypes()); -// try { -// String mimeType = new FileTypeDetector().getFileType(file); -// if (nonNull(mimeType)) { -// return mimeTypes.contains(mimeType); -// } -// } catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) { -// logger.log(Level.WARNING, "Failed to look up mimetype for " + file.getName() + " using FileTypeDetector. Fallingback on AbstractFile.isMimeType", ex); -// if (!mimeTypes.isEmpty() && file.isMimeType(mimeTypes) == AbstractFile.MimeMatchEnum.TRUE) { -// return true; -// } -// } -// -// return getExtensionsList().contains("." + extension); -// } -// return false; } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java index c84e8bc5ef..bb16323625 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java @@ -27,7 +27,7 @@ import org.openide.nodes.Node; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Content; /** * Complementary class to ThumbnailViewNode. Children node factory. Wraps around @@ -134,9 +134,9 @@ class ThumbnailViewChildren extends Children.Keys { static boolean isSupported(Node node) { if (node != null) { - AbstractFile file = node.getLookup().lookup(AbstractFile.class); - if (file != null) { - return ImageUtils.isImageThumbnailSupported(file); + Content content = node.getLookup().lookup(Content.class); + if (content != null) { + return ImageUtils.thumbnailSupported(content); } } return false; diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java index 94a5185f68..a4876ec64f 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java @@ -85,8 +85,8 @@ public class ImageUtils { private static final BufferedImage DEFAULT_THUMBNAIL; - private static final String GIF_EXTENSION = "gif"; - private static final String IMAGE_GIF_MIME = "image/gif"; //NON-NLS + private static final List GIF_EXTENSION_LIST = Arrays.asList("gif"); + private static final SortedSet GIF_MIME_SET = ImmutableSortedSet.copyOf(new String[]{"image/gif"}); private static final List SUPPORTED_IMAGE_EXTENSIONS; private static final SortedSet SUPPORTED_IMAGE_MIME_TYPES; @@ -168,6 +168,27 @@ public class ImageUtils { return DEFAULT_THUMBNAIL; } + /** + * Can a thumbnail be generated for the content? + * + * Although this method accepts Content, it always returns false for objects + * that are not instances of AbstractFile. + * + * @param content A content object to test for thumbnail support. + * + * @return true if a thumbnail can be generated for the given content. + */ + public static boolean thumbnailSupported(Content content) { + + if (!(content instanceof AbstractFile)) { + return false; + } + AbstractFile file = (AbstractFile) content; + + return VideoUtils.isVideoThumbnailSupported(file) + || isImageThumbnailSupported(file); + } + /** * is the file an image that we can read and generate a thumbnail for * @@ -177,7 +198,7 @@ public class ImageUtils { * for. */ public static boolean isImageThumbnailSupported(AbstractFile file) { - return hasImageFileHeader(file) || isMediaThumbnailSupported(file, SUPPORTED_IMAGE_MIME_TYPES, SUPPORTED_IMAGE_EXTENSIONS); + return isMediaThumbnailSupported(file, "image/", SUPPORTED_IMAGE_MIME_TYPES, SUPPORTED_IMAGE_EXTENSIONS) || hasImageFileHeader(file); } /** @@ -189,7 +210,7 @@ public class ImageUtils { * @return True or false */ public static boolean isGIF(AbstractFile file) { - return isMediaThumbnailSupported(file, Arrays.asList(IMAGE_GIF_MIME), Arrays.asList(GIF_EXTENSION)); + return isMediaThumbnailSupported(file, null, GIF_MIME_SET, GIF_EXTENSION_LIST); } /** @@ -209,7 +230,7 @@ public class ImageUtils { * @return true if a thumbnail can be generated for the given file based on * the given lists of supported mimetype and extensions */ - static boolean isMediaThumbnailSupported(AbstractFile file, final Collection supportedMimeTypes, final List supportedExtension) { + static boolean isMediaThumbnailSupported(AbstractFile file, String mimeTypePrefix, final Collection supportedMimeTypes, final List supportedExtension) { if (false == file.isFile() || file.getSize() <= 0) { return false; } @@ -220,7 +241,11 @@ public class ImageUtils { return true; } else { try { - return supportedMimeTypes.contains(getFileTypeDetector().detect(file)); + String mimeType = getFileTypeDetector().detect(file); + if (StringUtils.isNotBlank(mimeTypePrefix) && mimeTypePrefix.startsWith(mimeTypePrefix)) { + return true; + } + return supportedMimeTypes.contains(mimeType); } catch (FileTypeDetectorInitException | TskCoreException ex) { LOGGER.log(Level.SEVERE, "Error determining MIME type of " + getContentPathSafe(file), ex); return false; @@ -308,6 +333,18 @@ public class ImageUtils { } + /** + * Do a direct check to see if the given file has an image file header. + * NOTE: Currently only jpeg and png are supported. + * + * @param file + * + * @return true if the given file has one of the supported image headers. + */ + public static boolean hasImageFileHeader(AbstractFile file) { + return isJpegFileHeader(file) || isPngFileHeader(file); + } + /** * Check if the given file is a jpeg based on header. * @@ -869,39 +906,4 @@ public class ImageUtils { } - /** - * Do a direct check to see if the given file has an image file header. - * NOTE: Currently only jpeg and png are supported. - * - * @param file - * - * @return true if the given file has one of the supported image headers. - */ - @Deprecated - public static boolean hasImageFileHeader(AbstractFile file) { - return isJpegFileHeader(file) || isPngFileHeader(file); - } - - /** - * Can a thumbnail be generated for the content? - * - * Although this method accepts Content, it always returns false for objects - * that are not instances of AbstractFile. - * - * @param content A content object to test for thumbnail support. - * - * @return true if a thumbnail can be generated for the given content. - */ - @Deprecated - public static boolean thumbnailSupported(Content content) { - - if (!(content instanceof AbstractFile)) { - return false; - } - AbstractFile file = (AbstractFile) content; - - return VideoUtils.isVideoThumbnailSupported(file) - || isImageThumbnailSupported(file); - } - } diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/VideoUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/VideoUtils.java index 42c3e076c5..a48a109a7e 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/VideoUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/VideoUtils.java @@ -96,7 +96,7 @@ public class VideoUtils { } public static boolean isVideoThumbnailSupported(AbstractFile file) { - return isMediaThumbnailSupported(file, SUPPORTED_VIDEO_MIME_TYPES, SUPPORTED_VIDEO_EXTENSIONS); + return isMediaThumbnailSupported(file, "video/", SUPPORTED_VIDEO_MIME_TYPES, SUPPORTED_VIDEO_EXTENSIONS); } @NbBundle.Messages({"# {0} - file name", diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java index 9af389ad94..5e646247e6 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.HashSet; import static java.util.Objects.isNull; import java.util.Set; +import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.imageio.ImageIO; @@ -31,6 +32,7 @@ import org.apache.commons.lang3.StringUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskCoreException; /** @@ -167,10 +169,6 @@ public enum FileTypeUtils { return hasDrawableMIMEType(file); } - public static String getMimeType(AbstractFile file) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { - return getFileTypeDetector().getFileType(file); - } - static boolean isDrawableMimeType(String mimeType) { if (StringUtils.isBlank(mimeType)) { return false; @@ -192,7 +190,7 @@ public enum FileTypeUtils { * mimetype could not be detected. */ static boolean hasDrawableMIMEType(AbstractFile file) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { - String mimeType = getMimeType(file).toLowerCase(); + String mimeType = getFileTypeDetector().detect(file).toLowerCase(); return isDrawableMimeType(mimeType) || (mimeType.equals("audio/x-aiff") && "tiff".equalsIgnoreCase(file.getNameExtension())); } @@ -206,8 +204,31 @@ public enum FileTypeUtils { * application/x-shockwave-flash, etc) or, if no mimetype is * available, a video extension. */ - public static boolean hasVideoMIMEType(AbstractFile file) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { - String mimeType = getMimeType(file).toLowerCase(); - return mimeType.startsWith("video/") || videoMimeTypes.contains(mimeType); + public static boolean hasVideoMIMEType(AbstractFile file) { + try { + String mimeType = getFileTypeDetector().detect(file).toLowerCase(); + return mimeType.startsWith("video/") || videoMimeTypes.contains(mimeType); + } catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Error determining MIME type of " + getContentPathSafe(file), ex); + return false; + } + } + + /** + * Get the unique path for the content, or if that fails, just return the + * name. + * + * @param content + * + * @return + */ + static String getContentPathSafe(Content content) { + try { + return content.getUniquePath(); + } catch (TskCoreException tskCoreException) { + String contentName = content.getName(); + LOGGER.log(Level.SEVERE, "Failed to get unique path for " + contentName, tskCoreException); //NOI18N NON-NLS + return contentName; + } } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index 0a1474926c..d1c28eb695 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -443,7 +443,7 @@ public final class ImageGalleryController implements Executor { } @Nullable - synchronized public DrawableFile getFileFromId(Long fileID) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { + synchronized public DrawableFile getFileFromId(Long fileID) throws TskCoreException{ if (Objects.isNull(db)) { LOGGER.log(Level.WARNING, "Could not get file from id, no DB set. The case is probably closed."); //NON-NLS return null; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java index 2463d9dc59..78b260e731 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java @@ -44,7 +44,6 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.gui.Toolbar; import org.sleuthkit.autopsy.imagegallery.utils.TaskUtils; -import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.TskCoreException; @@ -98,7 +97,7 @@ public enum ThumbnailCache { * could not be generated */ @Nullable - public Image get(AbstractFile file) { + public Image get(DrawableFile file) { try { return cache.get(file.getId(), () -> load(file)); } catch (UncheckedExecutionException | CacheLoader.InvalidCacheLoadException | ExecutionException ex) { @@ -110,7 +109,7 @@ public enum ThumbnailCache { @Nullable public Image get(Long fileID) { try { - return get(ImageGalleryController.getDefault().getSleuthKitCase().getAbstractFileById(fileID)); + return get(ImageGalleryController.getDefault().getFileFromId(fileID)); } catch (TskCoreException ex) { LOGGER.log(Level.WARNING, "Failed to load thumbnail for file: " + fileID, ex.getCause()); //NON-NLS return null; @@ -125,12 +124,12 @@ public enum ThumbnailCache { * * @return an (possibly empty) optional containing a thumbnail */ - private Image load(AbstractFile file) { + private Image load(DrawableFile file) { - if (ImageUtils.isGIF(file)) { + if (ImageUtils.isGIF(file.getAbstractFile())) { //directly read gif to preserve potential animation, //NOTE: not saved to disk! - return new Image(new BufferedInputStream(new ReadContentInputStream(file)), MAX_THUMBNAIL_SIZE, MAX_THUMBNAIL_SIZE, true, true); + return new Image(new BufferedInputStream(new ReadContentInputStream(file.getAbstractFile())), MAX_THUMBNAIL_SIZE, MAX_THUMBNAIL_SIZE, true, true); } BufferedImage thumbnail = getCacheFile(file).map(cachFile -> { @@ -150,7 +149,7 @@ public enum ThumbnailCache { } return null; }).orElseGet(() -> { - return ImageUtils.getThumbnail(file, MAX_THUMBNAIL_SIZE); + return ImageUtils.getThumbnail(file.getAbstractFile(), MAX_THUMBNAIL_SIZE); }); WritableImage jfxthumbnail; @@ -172,9 +171,9 @@ public enum ThumbnailCache { * @return a Optional containing a File to store the cached icon in or an * empty optional if there was a problem. */ - private static Optional getCacheFile(AbstractFile file) { + private static Optional getCacheFile(DrawableFile file) { try { - return Optional.of(ImageUtils.getCachedThumbnailFile(file, MAX_THUMBNAIL_SIZE)); + return Optional.of(ImageUtils.getCachedThumbnailFile(file.getAbstractFile(), MAX_THUMBNAIL_SIZE)); } catch (Exception e) { LOGGER.log(Level.WARNING, "Failed to create cache file.{0}", e.getLocalizedMessage()); //NON-NLS diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java index 152f0dab25..341f0ba8b4 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java @@ -45,7 +45,6 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableTagsManager; -import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TagName; @@ -167,7 +166,7 @@ public class CategorizeAction extends Action { tagsManager.addContentTag(file, tagName, ""); } } - } catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) { + } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Error categorizing result", ex); //NON-NLS JOptionPane.showMessageDialog(null, Bundle.CategorizeTask_errorUnable_msg(fileID), diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java index 35dc0a9158..973954bf82 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java @@ -39,7 +39,6 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryPreferences; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; -import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.TskCoreException; /** @@ -67,7 +66,7 @@ public class CategorizeGroupAction extends CategorizeAction { if (false == Category.ZERO.equals(category) && newCat.equals(category) == false) { catCountMap.merge(category, 1L, Long::sum); } - } catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) { + } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Failed to categorize files.", ex); } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index e2b2d0db80..e61c8f34a3 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -997,7 +997,7 @@ public final class DrawableDB { * @throws TskCoreException if unable to get a file from the currently open * {@link SleuthkitCase} */ - public DrawableFile getFileFromID(Long id) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { + public DrawableFile getFileFromID(Long id) throws TskCoreException{ try { AbstractFile f = tskCase.getAbstractFileById(id); return DrawableFile.create(f, @@ -1174,7 +1174,7 @@ public final class DrawableDB { * @return returns true if this file is a video as determined by {@link ImageGalleryModule#isVideoFile(org.sleuthkit.datamodel.AbstractFile) * } but caches the result. returns false if passed a null AbstractFile */ - public boolean isVideoFile(AbstractFile f) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { + public boolean isVideoFile(AbstractFile f) { if (null == f) { return false; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java index 7a74188c5a..fba445de64 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java @@ -41,7 +41,6 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.FileTypeUtils; import org.sleuthkit.autopsy.imagegallery.ThumbnailCache; import org.sleuthkit.autopsy.imagegallery.utils.TaskUtils; -import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; @@ -60,7 +59,7 @@ public abstract class DrawableFile { private static final Logger LOGGER = Logger.getLogger(DrawableFile.class.getName()); - public static DrawableFile create(AbstractFile abstractFileById, boolean analyzed) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { + public static DrawableFile create(AbstractFile abstractFileById, boolean analyzed) throws TskCoreException { return create(abstractFileById, analyzed, FileTypeUtils.hasVideoMIMEType(abstractFileById)); } @@ -73,7 +72,7 @@ public abstract class DrawableFile { : new ImageFile(abstractFileById, analyzed); } - public static DrawableFile create(Long id, boolean analyzed) throws TskCoreException, IllegalStateException, FileTypeDetector.FileTypeDetectorInitException { + public static DrawableFile create(Long id, boolean analyzed) throws TskCoreException, IllegalStateException { return create(Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(id), analyzed); } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableUIBase.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableUIBase.java index 9069ebf5a3..da8120f632 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableUIBase.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableUIBase.java @@ -46,7 +46,6 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.actions.OpenExternalViewerAction; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; -import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.TskCoreException; /** @@ -102,7 +101,7 @@ abstract public class DrawableUIBase extends AnchorPane implements DrawableView } else { try { fileOpt = Optional.ofNullable(getController().getFileFromId(fileIDOpt.get())); - } catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) { + } catch (TskCoreException ex) { Logger.getAnonymousLogger().log(Level.WARNING, "failed to get DrawableFile for obj_id" + fileIDOpt.get(), ex); //NON-NLS fileOpt = Optional.empty(); } From 7877113aa81b6561b2cb6697dd9e0f771498c5f6 Mon Sep 17 00:00:00 2001 From: jmillman Date: Tue, 22 Mar 2016 14:13:44 -0400 Subject: [PATCH 45/77] comment why old bahavior is desired in MediaViewVideoPanel rever ReportGenerator, CategorizeAction, and CategorizeGroupAction since all changes where white space and formatting --- .../corecomponents/MediaViewVideoPanel.java | 17 ++- .../autopsy/coreutils/ImageUtils.java | 111 ++++++++++-------- .../autopsy/report/ReportGenerator.java | 36 +++--- .../actions/CategorizeAction.java | 3 +- .../actions/CategorizeGroupAction.java | 2 +- 5 files changed, 96 insertions(+), 73 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java index 3bf297b036..b9ad634ff5 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java @@ -134,7 +134,22 @@ public abstract class MediaViewVideoPanel extends JPanel implements FrameCapture @Override public boolean isSupported(AbstractFile file) { String extension = file.getNameExtension(); - //TODO: is this what we want, to require both extension and mimetype support? + /** + * Although it seems too restrictive, requiring both a supported + * extension and a supported MIME type prevents two undesirable + * behaviors: + * + * 1) Until AUT-1766 and AUT-1801 are fixed, we incorrectly identify all + * iff files as audio/aiff. This means that if this panel went with the + * looser 'mime type OR extension' criteria we use for images, then this + * panel would attempt (and fail) to display all iff files, even non + * audio ones. + * + * 2) The looser criteria means we are less confident about the files we + * are potentialy sending to GStreamer on 32bit jvms. We are less + * comfortable with the error handling for GStreamer, and don't want to + * send it files which might cause it trouble. + */ if (AUDIO_EXTENSIONS.contains("." + extension) || getExtensionsList().contains("." + extension)) { SortedSet mimeTypes = new TreeSet<>(getMimeTypes()); try { diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java index a4876ec64f..475c365451 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java @@ -21,6 +21,7 @@ */ package org.sleuthkit.autopsy.coreutils; +import com.google.common.collect.ImmutableSortedSet; import com.google.common.io.Files; import java.awt.Image; import java.awt.image.BufferedImage; @@ -97,9 +98,9 @@ public class ImageUtils { ImageIO.scanForPlugins(); BufferedImage tempImage; try { - tempImage = ImageIO.read(ImageUtils.class.getResourceAsStream("/org/sleuthkit/autopsy/images/file-icon.png"));//NON-NLS //NOI18N + tempImage = ImageIO.read(ImageUtils.class.getResourceAsStream("/org/sleuthkit/autopsy/images/file-icon.png"));//NON-NLS } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "Failed to load default icon.", ex); //NOI18N NON-NLS + LOGGER.log(Level.SEVERE, "Failed to load default icon.", ex); //NON-NLS tempImage = null; } DEFAULT_THUMBNAIL = tempImage; @@ -108,10 +109,10 @@ public class ImageUtils { boolean openCVLoadedTemp; try { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); - if (System.getProperty("os.arch").equals("amd64") || System.getProperty("os.arch").equals("x86_64")) { //NOI18N NON-NLS - System.loadLibrary("opencv_ffmpeg248_64"); //NOI18N NON-NLS + if (System.getProperty("os.arch").equals("amd64") || System.getProperty("os.arch").equals("x86_64")) { //NON-NLS + System.loadLibrary("opencv_ffmpeg248_64"); //NON-NLS } else { - System.loadLibrary("opencv_ffmpeg248"); //NOI18N NON-NLS + System.loadLibrary("opencv_ffmpeg248"); //NON-NLS } openCVLoadedTemp = true; @@ -160,7 +161,7 @@ public class ImageUtils { /** * Get the default thumbnail, which is the icon for a file. Used when we can - * not generate content based thumbnail. + * not generate a content based thumbnail. * * @return the default thumbnail */ @@ -190,45 +191,48 @@ public class ImageUtils { } /** - * is the file an image that we can read and generate a thumbnail for + * Is the file an image that we can read and generate a thumbnail for? * - * @param file + * @param file the AbstractFile to test * * @return true if the file is an image we can read and generate thumbnail * for. */ public static boolean isImageThumbnailSupported(AbstractFile file) { - return isMediaThumbnailSupported(file, "image/", SUPPORTED_IMAGE_MIME_TYPES, SUPPORTED_IMAGE_EXTENSIONS) || hasImageFileHeader(file); + return isMediaThumbnailSupported(file, "image/", SUPPORTED_IMAGE_MIME_TYPES, SUPPORTED_IMAGE_EXTENSIONS) || hasImageFileHeader(file);//NON-NLS } /** - * Checks the MIME type of a file to determine whether it is a GIF. If the - * MIME type is not known, checks for a "gif" extension. + * Checks the MIME type and/or extension of a file to determine whether it + * is a GIF. * - * @param file The file to be checked. + * @param file the AbstractFile to test * - * @return True or false + * @return true if the file is a gif */ public static boolean isGIF(AbstractFile file) { return isMediaThumbnailSupported(file, null, GIF_MIME_SET, GIF_EXTENSION_LIST); } /** - * Check if a file is "supported" by checking its extension and/or MIME type + * Check if making a thumbnail for the given file is supported by checking + * its extension and/or MIME type against the supplied collections. * * //TODO: this should move to a better place. Should ImageUtils and * VideoUtils both implement/extend some base interface/abstract class. That * would be the natural place to put this. * - * @param file - * @param supportedMimeTypes a set of mimetypes that the could have to be - * supported - * @param supportedExtension a set of extensions a file could have to be - * supported if the mime lookup fails or is - * inconclusive + * @param file the AbstractFile to test + * @param mimeTypePrefix a MIME 'top-level type name' such as "image/", + * including the "/". In addition to the list of + * supported MIME types, any type that starts with + * this prefix will be regarded as supported + * @param supportedMimeTypes a collection of mimetypes that are supported + * @param supportedExtension a collection of extensions that are supported * * @return true if a thumbnail can be generated for the given file based on - * the given lists of supported mimetype and extensions + * the given MIME type prefix and lists of supported MIME types and + * extensions */ static boolean isMediaThumbnailSupported(AbstractFile file, String mimeTypePrefix, final Collection supportedMimeTypes, final List supportedExtension) { if (false == file.isFile() || file.getSize() <= 0) { @@ -247,18 +251,21 @@ public class ImageUtils { } return supportedMimeTypes.contains(mimeType); } catch (FileTypeDetectorInitException | TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Error determining MIME type of " + getContentPathSafe(file), ex); + LOGGER.log(Level.SEVERE, "Error determining MIME type of " + getContentPathSafe(file), ex);//NON-NLS return false; } } } /** - * returns a lazily instatiated FileTypeDetector + * //TODO: AUT-2057 this FileTypeDetector needs to be recreated when the + * user adds new user defined file types. + * + * get a FileTypeDetector * * @return a FileTypeDetector * - * @throws FileTypeDetectorInitException if a initializing the + * @throws FileTypeDetectorInitException if initializing the * FileTypeDetector failed. */ synchronized private static FileTypeDetector getFileTypeDetector() throws FileTypeDetector.FileTypeDetectorInitException { @@ -272,8 +279,8 @@ public class ImageUtils { * Get a thumbnail of a specified size for the given image. Generates the * thumbnail if it is not already cached. * - * @param content - * @param iconSize + * @param content the content to generate a thumbnail for + * @param iconSize the size (one side of a square) in pixels to generate * * @return a thumbnail for the given image or a default one if there was a * problem making a thumbnail. @@ -300,8 +307,8 @@ public class ImageUtils { * Get a thumbnail of a specified size for the given image. Generates the * thumbnail if it is not already cached. * - * @param content - * @param iconSize + * @param content the content to generate a thumbnail for + * @param iconSize the size (one side of a square) in pixels to generate * * @return File object for cached image. Is guaranteed to exist, as long as * there was not an error generating or saving the thumbnail. @@ -313,10 +320,10 @@ public class ImageUtils { } /** - * Get a file object for where the cached thumbnail should exist. The - * returned file may not exist. + * Get the location of the cached thumbnail for a file with the given fileID + * as a java {@link File}. The returned File may not exist on disk yet. * - * @param fileID + * @param fileID the fileID to get the cached thumbnail location for * * @return a File object representing the location of the cached thumbnail. * This file may not actually exist(yet). Returns null if there was @@ -325,19 +332,18 @@ public class ImageUtils { private static File getCachedThumbnailLocation(long fileID) { try { String cacheDirectory = Case.getCurrentCase().getCacheDirectory(); - return Paths.get(cacheDirectory, "thumbnails", fileID + ".png").toFile(); //NOI18N NON-NLS + return Paths.get(cacheDirectory, "thumbnails", fileID + ".png").toFile(); //NON-NLS } catch (IllegalStateException e) { LOGGER.log(Level.WARNING, "Could not get cached thumbnail location. No case is open."); //NON-NLS return null; } - } /** * Do a direct check to see if the given file has an image file header. * NOTE: Currently only jpeg and png are supported. * - * @param file + * @param file the AbstractFile to check * * @return true if the given file has one of the supported image headers. */ @@ -348,7 +354,7 @@ public class ImageUtils { /** * Check if the given file is a jpeg based on header. * - * @param file + * @param file the AbstractFile to check * * @return true if jpeg file, false otherwise */ @@ -373,7 +379,7 @@ public class ImageUtils { /** * Check if the given file is a png based on header. * - * @param file + * @param file the AbstractFile to check * * @return true if png file, false otherwise */ @@ -405,7 +411,7 @@ public class ImageUtils { if (bytesRead != buffLength) { //ignore if can't read the first few bytes, not an image - throw new TskCoreException("Could not read " + buffLength + " bytes from " + file.getName()); //NOI18N + throw new TskCoreException("Could not read " + buffLength + " bytes from " + file.getName());//NON-NLS } return fileHeaderBuffer; } @@ -422,7 +428,7 @@ public class ImageUtils { */ static public int getImageWidth(AbstractFile file) throws IOException { return getImageProperty(file, - "ImageIO could not determine width of {0}: ", //NOI18N NON-NLS + "ImageIO could not determine width of {0}: ", //NON-NLS imageReader -> imageReader.getWidth(0) ); } @@ -439,7 +445,7 @@ public class ImageUtils { */ static public int getImageHeight(AbstractFile file) throws IOException { return getImageProperty(file, - "ImageIO could not determine height of {0}: ", //NOI18N NON-NLS + "ImageIO could not determine height of {0}: ", //NON-NLS imageReader -> imageReader.getHeight(0) ); } @@ -536,7 +542,7 @@ public class ImageUtils { */ static private class GetThumbnailTask extends ReadImageTaskBase { - private static final String FAILED_TO_READ_IMAGE_FOR_THUMBNAIL_GENERATION = "Failed to read {0} for thumbnail generation."; //NOI18N NON-NLS + private static final String FAILED_TO_READ_IMAGE_FOR_THUMBNAIL_GENERATION = "Failed to read {0} for thumbnail generation."; //NON-NLS private final int iconSize; private final File cacheFile; @@ -570,7 +576,7 @@ public class ImageUtils { return SwingFXUtils.toFXImage(cachedThumbnail, null); } } catch (Exception ex) { - LOGGER.log(Level.WARNING, "ImageIO had a problem reading the cached thumbnail for {0}: " + ex.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS + LOGGER.log(Level.WARNING, "ImageIO had a problem reading the cached thumbnail for {0}: " + ex.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS cacheFile.delete(); //since we can't read the file we might as well delete it. } } @@ -590,7 +596,7 @@ public class ImageUtils { if (defaultOnFailure) { thumbnail = DEFAULT_THUMBNAIL; } else { - throw new IIOException("Failed to generate a thumbnail for " + getContentPathSafe(file)); + throw new IIOException("Failed to generate a thumbnail for " + getContentPathSafe(file));//NON-NLS } } @@ -610,7 +616,7 @@ public class ImageUtils { thumbnail = ScalrWrapper.resizeFast(bufferedImage, iconSize); } catch (IllegalArgumentException | OutOfMemoryError e) { // if resizing does not work due to extreme aspect ratio or oom, crop the image instead. - LOGGER.log(Level.WARNING, "Cropping {0}, because it could not be scaled: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS + LOGGER.log(Level.WARNING, "Cropping {0}, because it could not be scaled: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS final int height = bufferedImage.getHeight(); final int width = bufferedImage.getWidth(); @@ -620,11 +626,11 @@ public class ImageUtils { try { thumbnail = ScalrWrapper.cropImage(bufferedImage, cropWidth, cropHeight); } catch (Exception cropException) { - LOGGER.log(Level.WARNING, "Could not crop {0}: " + cropException.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS + LOGGER.log(Level.WARNING, "Could not crop {0}: " + cropException.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS } } } catch (Exception e) { - LOGGER.log(Level.WARNING, "Could not scale {0}: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS + LOGGER.log(Level.WARNING, "Could not scale {0}: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS throw e; } } @@ -657,19 +663,20 @@ public class ImageUtils { } ImageIO.write(thumbnail, FORMAT, cacheFile); } catch (IllegalArgumentException | IOException ex) { - LOGGER.log(Level.WARNING, "Could not write thumbnail for {0}: " + ex.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N NON-NLS + LOGGER.log(Level.WARNING, "Could not write thumbnail for {0}: " + ex.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS } }); } } /** - * Create a new {@link Task} that will read the fileinto memory as an + * Create a new {@link Task} that will read the file into memory as an * {@link javafx.scene.image.Image} * * Note: the returned task is suitable for running in a background thread, * but is not started automatically. Clients are responsible for running the - * task, monitoring its progress, and using its result. + * task, monitoring its progress, and using its result(including testing for + * null). * * @param file the file to read as an Image * @@ -703,7 +710,7 @@ public class ImageUtils { */ static private abstract class ReadImageTaskBase extends Task implements IIOReadProgressListener { - private static final String IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT = "ImageIO could not read {0}. It may be unsupported or corrupt"; //NOI18N NON-NLS + private static final String IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT = "ImageIO could not read {0}. It may be unsupported or corrupt"; //NON-NLS final AbstractFile file; // private ImageReader reader; @@ -739,7 +746,7 @@ public class ImageUtils { try { bufferedImage = imageReader.read(0, param); //should always be same bufferedImage object } catch (IOException iOException) { - LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + iOException.toString(), ImageUtils.getContentPathSafe(file)); //NOI18N + LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + iOException.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS } finally { imageReader.removeIIOReadProgressListener(ReadImageTaskBase.this); } @@ -825,14 +832,14 @@ public class ImageUtils { * * @param content * - * @return + * @return the unique path for the content, or if that fails, just the name. */ static String getContentPathSafe(Content content) { try { return content.getUniquePath(); } catch (TskCoreException tskCoreException) { String contentName = content.getName(); - LOGGER.log(Level.SEVERE, "Failed to get unique path for " + contentName, tskCoreException); //NOI18N NON-NLS + LOGGER.log(Level.SEVERE, "Failed to get unique path for " + contentName, tskCoreException); //NON-NLS return contentName; } } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 8286c4d429..38a5931427 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -52,6 +53,7 @@ import javax.swing.SwingWorker; import org.openide.filesystems.FileUtil; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; @@ -64,13 +66,13 @@ import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; -import org.sleuthkit.datamodel.BlackboardAttribute.Type; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; +import org.sleuthkit.datamodel.BlackboardAttribute.Type; /** * Instances of this class use GeneralReportModules, TableReportModules and @@ -528,8 +530,8 @@ class ReportGenerator { } /* - * Gets all of the attribute types of this artifact type by - * adding all of the types to a set + Gets all of the attribute types of this artifact type by adding + all of the types to a set */ Set attrTypeSet = new TreeSet<>((Type o1, Type o2) -> o1.getDisplayName().compareTo(o2.getDisplayName())); for (ArtifactData data : artifactList) { @@ -856,7 +858,7 @@ class ReportGenerator { return; } - if (ImageUtils.isImageThumbnailSupported(file)) { + if (ImageUtils.thumbnailSupported(file)) { images.add(file); } } @@ -927,8 +929,8 @@ class ReportGenerator { } else { orderByClause = "ORDER BY list ASC"; //NON-NLS } - String keywordListQuery = - "SELECT att.value_text AS list " + //NON-NLS + String keywordListQuery + = "SELECT att.value_text AS list " + //NON-NLS "FROM blackboard_attributes AS att, blackboard_artifacts AS art " + //NON-NLS "WHERE att.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " " + //NON-NLS "AND art.artifact_type_id = " + ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + " " + //NON-NLS @@ -970,8 +972,8 @@ class ReportGenerator { orderByClause = "ORDER BY list ASC, keyword ASC, parent_path ASC, name ASC, preview ASC"; //NON-NLS } // Query for keywords, grouped by list - String keywordsQuery = - "SELECT art.artifact_id, art.obj_id, att1.value_text AS keyword, att2.value_text AS preview, att3.value_text AS list, f.name AS name, f.parent_path AS parent_path " + //NON-NLS + String keywordsQuery + = "SELECT art.artifact_id, art.obj_id, att1.value_text AS keyword, att2.value_text AS preview, att3.value_text AS list, f.name AS name, f.parent_path AS parent_path " + //NON-NLS "FROM blackboard_artifacts AS art, blackboard_attributes AS att1, blackboard_attributes AS att2, blackboard_attributes AS att3, tsk_files AS f " + //NON-NLS "WHERE (att1.artifact_id = art.artifact_id) " + //NON-NLS "AND (att2.artifact_id = art.artifact_id) " + //NON-NLS @@ -1091,8 +1093,8 @@ class ReportGenerator { } else { orderByClause = "ORDER BY att.value_text ASC"; //NON-NLS } - String hashsetsQuery = - "SELECT att.value_text AS list " + //NON-NLS + String hashsetsQuery + = "SELECT att.value_text AS list " + //NON-NLS "FROM blackboard_attributes AS att, blackboard_artifacts AS art " + //NON-NLS "WHERE att.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " " + //NON-NLS "AND art.artifact_type_id = " + ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() + " " + //NON-NLS @@ -1128,8 +1130,8 @@ class ReportGenerator { } else { orderByClause = "ORDER BY att.value_text ASC, f.parent_path ASC, f.name ASC, size ASC"; //NON-NLS } - String hashsetHitsQuery = - "SELECT art.artifact_id, art.obj_id, att.value_text AS setname, f.name AS name, f.size AS size, f.parent_path AS parent_path " + //NON-NLS + String hashsetHitsQuery + = "SELECT art.artifact_id, art.obj_id, att.value_text AS setname, f.name AS name, f.size AS size, f.parent_path AS parent_path " + //NON-NLS "FROM blackboard_artifacts AS art, blackboard_attributes AS att, tsk_files AS f " + //NON-NLS "WHERE (att.artifact_id = art.artifact_id) " + //NON-NLS "AND (f.obj_id = art.obj_id) " + //NON-NLS @@ -2046,12 +2048,10 @@ class ReportGenerator { @Override public String getCellData(ArtifactData artData) { return getFileUniquePath(artData.getContent()); - /* - * else if - * (this.columnHeader.equals(NbBundle.getMessage(this.getClass(), - * "ReportGenerator.artTableColHdr.tags"))) { return - * makeCommaSeparatedList(artData.getTags()); } return ""; - */ + /*else if (this.columnHeader.equals(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"))) { + return makeCommaSeparatedList(artData.getTags()); + } + return "";*/ } @Override diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java index 341f0ba8b4..b91b857e60 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java @@ -84,6 +84,7 @@ public class CategorizeAction extends Action { return new CategoryMenu(controller); } + final void addCatToFiles(Set ids) { Logger.getAnonymousLogger().log(Level.INFO, "categorizing{0} as {1}", new Object[]{ids.toString(), cat.getDisplayName()}); //NON-NLS controller.queueDBWorkerTask(new CategorizeTask(ids, cat, createUndo)); @@ -166,7 +167,7 @@ public class CategorizeAction extends Action { tagsManager.addContentTag(file, tagName, ""); } } - } catch (TskCoreException ex) { + } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Error categorizing result", ex); //NON-NLS JOptionPane.showMessageDialog(null, Bundle.CategorizeTask_errorUnable_msg(fileID), diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java index 973954bf82..cc2ede2ce5 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java @@ -66,7 +66,7 @@ public class CategorizeGroupAction extends CategorizeAction { if (false == Category.ZERO.equals(category) && newCat.equals(category) == false) { catCountMap.merge(category, 1L, Long::sum); } - } catch (TskCoreException ex) { + } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Failed to categorize files.", ex); } } From 60ee20c9efbe51943fb16bf10d083b42a62c296e Mon Sep 17 00:00:00 2001 From: jmillman Date: Tue, 22 Mar 2016 15:09:18 -0400 Subject: [PATCH 46/77] improve error handling in ImageGallery --- .../autopsy/imagegallery/FileTypeUtils.java | 9 ++++++++- .../imagegallery/ImageGalleryController.java | 7 ++++--- .../imagegallery/datamodel/DrawableDB.java | 19 +++++-------------- .../imagegallery/datamodel/DrawableFile.java | 2 +- .../datamodel/grouping/GroupManager.java | 3 +-- 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java index 5e646247e6..e5822569c8 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java @@ -150,6 +150,10 @@ public enum FileTypeUtils { } static synchronized FileTypeDetector getFileTypeDetector() throws FileTypeDetector.FileTypeDetectorInitException { + /* + * TODO: EUR-740 recreate FileTypeDetector when the user creates new + * user defined file types + */ if (isNull(FILE_TYPE_DETECTOR)) { FILE_TYPE_DETECTOR = new FileTypeDetector(); } @@ -181,6 +185,10 @@ public enum FileTypeUtils { } /** + * + * TODO: EUR-740 recreate FileTypeDetector when the user creates new user + * defined file types + * * does the given file have drawable/supported mime type * * @param file @@ -192,7 +200,6 @@ public enum FileTypeUtils { static boolean hasDrawableMIMEType(AbstractFile file) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { String mimeType = getFileTypeDetector().detect(file).toLowerCase(); return isDrawableMimeType(mimeType) || (mimeType.equals("audio/x-aiff") && "tiff".equalsIgnoreCase(file.getNameExtension())); - } /** diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index d1c28eb695..9794232b57 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -443,7 +443,7 @@ public final class ImageGalleryController implements Executor { } @Nullable - synchronized public DrawableFile getFileFromId(Long fileID) throws TskCoreException{ + synchronized public DrawableFile getFileFromId(Long fileID) throws TskCoreException { if (Objects.isNull(db)) { LOGGER.log(Level.WARNING, "Could not get file from id, no DB set. The case is probably closed."); //NON-NLS return null; @@ -962,8 +962,9 @@ public final class ImageGalleryController implements Executor { } } catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) { //TODO: What to do here? - LOGGER.log(Level.WARNING, "Unable to determine if file is drawable and not known. Not making any changes to DB", ex); //NON-NLS - throw new RuntimeException(ex); + LOGGER.log(Level.SEVERE, "Unable to determine if file is drawable and not known. Not making any changes to DB", ex); //NON-NLS + MessageNotifyUtil.Notify.error("Image Gallery Error", + "Unable to determine if file is drawable and not known. Not making any changes to DB. See the logs for details."); } } } else { //TODO: keep track of what we missed for later diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index e61c8f34a3..e7d9dc0a8d 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -34,6 +34,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import static java.util.Objects.isNull; import static java.util.Objects.nonNull; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -54,7 +55,6 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupKey; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupSortBy; import static org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupSortBy.GROUP_BY_VALUE; -import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -979,7 +979,7 @@ public final class DrawableDB { * @throws TskCoreException if unable to get a file from the currently open * {@link SleuthkitCase} */ - private DrawableFile getFileFromID(Long id, boolean analyzed) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException { + private DrawableFile getFileFromID(Long id, boolean analyzed) throws TskCoreException { try { AbstractFile f = tskCase.getAbstractFileById(id); return DrawableFile.create(f, analyzed, isVideoFile(f)); @@ -997,7 +997,7 @@ public final class DrawableDB { * @throws TskCoreException if unable to get a file from the currently open * {@link SleuthkitCase} */ - public DrawableFile getFileFromID(Long id) throws TskCoreException{ + public DrawableFile getFileFromID(Long id) throws TskCoreException { try { AbstractFile f = tskCase.getAbstractFileById(id); return DrawableFile.create(f, @@ -1175,17 +1175,8 @@ public final class DrawableDB { * } but caches the result. returns false if passed a null AbstractFile */ public boolean isVideoFile(AbstractFile f) { - - if (null == f) { - return false; - } else { - Boolean isVideo = videoFileMap.get(f.getId()); - if (null == isVideo) { - isVideo = FileTypeUtils.hasVideoMIMEType(f); - videoFileMap.put(f.getId(), isVideo); - } - return isVideo; - } + return isNull(f) ? false + : videoFileMap.computeIfAbsent(f.getId(), id -> FileTypeUtils.hasVideoMIMEType(f)); } /** diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java index fba445de64..2f86c47ad6 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java @@ -59,7 +59,7 @@ public abstract class DrawableFile { private static final Logger LOGGER = Logger.getLogger(DrawableFile.class.getName()); - public static DrawableFile create(AbstractFile abstractFileById, boolean analyzed) throws TskCoreException { + public static DrawableFile create(AbstractFile abstractFileById, boolean analyzed) { return create(abstractFileById, analyzed, FileTypeUtils.hasVideoMIMEType(abstractFileById)); } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java index 0c31b3c299..b52702728a 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java @@ -78,7 +78,6 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableTagsManager; -import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.SleuthkitCase; @@ -200,7 +199,7 @@ public class GroupManager { } else { Logger.getLogger(GroupManager.class.getName()).log(Level.WARNING, "Failed to load file with id: {0} from database. There is no database assigned.", fileID); //NON-NLS } - } catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) { + } catch (TskCoreException ex) { Logger.getLogger(GroupManager.class.getName()).log(Level.SEVERE, "failed to load file with id: " + fileID + " from database", ex); //NON-NLS } return Collections.emptySet(); From 341fbf836c53e6a37a414f227a7925ea13117aa7 Mon Sep 17 00:00:00 2001 From: jmillman Date: Tue, 22 Mar 2016 15:23:04 -0400 Subject: [PATCH 47/77] fix bug in isMediaThumbnailSupported --- Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java index 475c365451..057c39cade 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java @@ -246,7 +246,7 @@ public class ImageUtils { } else { try { String mimeType = getFileTypeDetector().detect(file); - if (StringUtils.isNotBlank(mimeTypePrefix) && mimeTypePrefix.startsWith(mimeTypePrefix)) { + if (StringUtils.isNotBlank(mimeTypePrefix) && mimeType.startsWith(mimeTypePrefix)) { return true; } return supportedMimeTypes.contains(mimeType); From bca44773844056b0ada99ed0280ced203ba5b46d Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 22 Mar 2016 23:41:18 -0400 Subject: [PATCH 48/77] Map drives only on windows. Caused exceptions on OS X --- .../org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java b/Core/src/org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java index 9ba40b7a08..e9ce8a7d95 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java @@ -263,6 +263,11 @@ public class UNCPathUtilities { */ synchronized private Map getMappedDrives() { Map driveMap = new HashMap<>(); + + if (PlatformUtil.isWindowsOS() == false) { + return driveMap; + } + File mappedDrive = Paths.get(System.getenv(TEMP_FOLDER), nameString + MAPPED_DRIVES).toFile(); try { Files.deleteIfExists(mappedDrive.toPath()); From ab50b39d6c94159905258d886e6e389ae15b21f1 Mon Sep 17 00:00:00 2001 From: jmillman Date: Wed, 23 Mar 2016 10:49:47 -0400 Subject: [PATCH 49/77] fix gstreamer buffering --- .../src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java index 9c3036db6c..8f69f82386 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/GstVideoPanel.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.corecomponents; +import com.google.common.io.Files; import java.awt.Dimension; import java.awt.Image; import java.awt.image.BufferedImage; @@ -680,6 +681,7 @@ public class GstVideoPanel extends MediaViewVideoPanel { progressLabel.setText(NbBundle.getMessage(this.getClass(), "GstVideoPanel.progress.buffering")); progress.start(100); try { + Files.createParentDirs(tempFile); return ContentUtils.writeToFile(sourceFile, tempFile, progress, this, true); } catch (IOException ex) { logger.log(Level.WARNING, "Error buffering file", ex); //NON-NLS From 3d2143cd1dbc2c3fcac7d7d0aabd988431a370d8 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Wed, 23 Mar 2016 11:47:00 -0400 Subject: [PATCH 50/77] Updated ui for logical file set names, edited implementation details. --- .../sleuthkit/autopsy/casemodule/Bundle.properties | 5 +---- .../autopsy/casemodule/LocalFilesDSProcessor.java | 11 +++-------- .../sleuthkit/autopsy/casemodule/LocalFilesPanel.form | 2 +- .../sleuthkit/autopsy/casemodule/LocalFilesPanel.java | 6 +++--- .../autopsy/modules/filetypeid/Bundle.properties | 3 --- 5 files changed, 8 insertions(+), 19 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 64ced36212..d05018d379 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -252,9 +252,6 @@ SingleUserCaseConverter.CanNotOpenDatabase=Unable to open database CloseCaseWhileIngesting.Warning=Ingest is running. Are you sure you want to close the case? CloseCaseWhileIngesting.Warning.title=Warning\: This will close the current case CasePropertiesForm.imagesTable.columnModel.title1=Remove - CasePropertiesForm.imagesTable.columnModel.title0=Path LocalFilesPanel.jButton1.text=Change -LocalFilesPanel.fileSetNameLabel.text=Display Name: Default -LocalFilesPanel.jButton1.text=Change -LocalFilesPanel.displayNameLabel.text=Display Name: Default +LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java index 513ede01cd..1a19ded518 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java @@ -43,10 +43,8 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { * TODO: Remove the setDataSourceOptionsCalled flag and the settings fields * when the deprecated method setDataSourceOptions is removed. */ - private String deviceId; private List localFilePaths; private boolean setDataSourceOptionsCalled; - private String fileSetName; /** * Constructs a local/logical files and/or directories data source processor @@ -124,12 +122,9 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { @Override public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { if (!setDataSourceOptionsCalled) { - deviceId = UUID.randomUUID().toString(); localFilePaths = Arrays.asList(configPanel.getContentPaths().split(LocalFilesPanel.FILES_SEP)); - fileSetName = configPanel.getFileSetName(); } - run(deviceId, fileSetName, localFilePaths, progressMonitor, callback); - this.reset(); + run(UUID.randomUUID().toString(), configPanel.getFileSetName(), localFilePaths, progressMonitor, callback); } /** @@ -165,7 +160,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { * is a "best effort" cancellation, with no guarantees that the case * database will be unchanged. If cancellation succeeded, the list of new * data sources returned by the background task will be empty. - * + * * TODO (AUT-1907): Implement cancellation by deleting rows added to the * case database. */ @@ -197,7 +192,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { */ @Deprecated public void setDataSourceOptions(String paths) { - this.localFilePaths = Arrays.asList(configPanel.getContentPaths().split(LocalFilesPanel.FILES_SEP)); + this.localFilePaths = Arrays.asList(paths.split(LocalFilesPanel.FILES_SEP)); setDataSourceOptionsCalled = true; } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form index 9470b481b7..4a502d97bf 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form @@ -67,7 +67,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java index cea0aecdac..99ba5ec231 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java @@ -73,7 +73,7 @@ class LocalFilesPanel extends JPanel { localFileChooser.setMultiSelectionEnabled(true); errorLabel.setVisible(false); selectedPaths.setText(""); - this.displayNameLabel.setText("Display Name: Default"); + this.displayNameLabel.setText(NbBundle.getMessage(this.getClass(), "LocalFilesPanel.displayNameLabel.text")); } //@Override @@ -145,7 +145,7 @@ class LocalFilesPanel extends JPanel { enableNext = false; errorLabel.setVisible(false); displayName = ""; - this.displayNameLabel.setText("Display Name: Default"); + this.displayNameLabel.setText(NbBundle.getMessage(this.getClass(), "LocalFilesPanel.displayNameLabel.text")); } @Override @@ -262,7 +262,7 @@ class LocalFilesPanel extends JPanel { .addComponent(errorLabel) .addGroup(layout.createSequentialGroup() .addComponent(displayNameLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jButton1))) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties index 6816c358c8..db618b0865 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties @@ -49,6 +49,3 @@ FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy can automatically detect many FileTypeIdGlobalSettingsPanel.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector. FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector. FileTypeIdGlobalSettingsPanel.offsetRelativeToLabel.text=Offset is relative to -DisplayNameDialogFrame.jLabel1.text=jLabel1 -DisplayNamePanel.jLabel1.text=New Display Name: -DisplayNamePanel.jTextField1.text= From 77c68361b73539cc92c8d681e9a50ef334564391 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Wed, 23 Mar 2016 11:55:04 -0400 Subject: [PATCH 51/77] Added comments to increase clarity. --- .../org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java | 1 + .../org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java index 1a19ded518..c7825b6458 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java @@ -192,6 +192,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { */ @Deprecated public void setDataSourceOptions(String paths) { + //LocalFilesPanel.FILES_SEP is currently "," this.localFilePaths = Arrays.asList(paths.split(LocalFilesPanel.FILES_SEP)); setDataSourceOptionsCalled = true; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties index db618b0865..ccc1bd0aff 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties @@ -48,4 +48,4 @@ FileTypeIdGlobalSettingsPanel.jLabel2.text=Custom MIME Types: FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy can automatically detect many file types. Add your custom file types here. FileTypeIdGlobalSettingsPanel.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector. FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector. -FileTypeIdGlobalSettingsPanel.offsetRelativeToLabel.text=Offset is relative to +FileTypeIdGlobalSettingsPanel.offsetRelativeToLabel.text=Offset is relative to From fa8b4217b2fec843a9925cdce4712af310c8a2f1 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 23 Mar 2016 13:25:41 -0400 Subject: [PATCH 52/77] Make nee filetypeid/FileTypeDetector.detect set MIME type correctly for special files --- .../modules/filetypeid/FileTypeDetector.java | 124 +++++++++++------- 1 file changed, 79 insertions(+), 45 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index e6e8269ac9..ec7fa1dfb7 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -139,42 +139,14 @@ public class FileTypeDetector { * * @param file The file. * - * @return A MIME type name. + * @return A MIME type name. If file type could not be detected or results + * were uncertain, octet-stream is returned. * * @throws TskCoreException if detection is required and there is a problem * writing the result to the case database. */ - @SuppressWarnings("deprecation") public String getFileType(AbstractFile file) throws TskCoreException { - String mimeType = file.getMIMEType(); - if (null != mimeType) { - return mimeType; - } - - mimeType = detect(file); - Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType); - - /* - * Add the file type attribute to the general info artifact. Note that - * no property change is fired for this blackboard posting because - * general info artifacts are different from other artifacts, e.g., they - * are not displayed in the results tree. - * - * SPECIAL NOTE: Adding a file type attribute to the general info - * artifact is meant to be replaced by the use of the MIME type field of - * the AbstractFile class (tsk_files.mime_type in the case database). - * The attribute is still added here to support backward compatibility, - * but it introduces a check-then-act race condition that can lead to - * duplicate attributes. Various mitigation strategies were considered. - * It was decided to go with the policy that this method would not be - * called outside of ingest (see note in method docs), at least until - * such time as the attribute is no longer created. - */ - BlackboardArtifact getInfoArt = file.getGenInfoArtifact(); - BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType); - getInfoArt.addAttribute(batt); - - return mimeType; + return detect(file, true); } /** @@ -186,9 +158,36 @@ public class FileTypeDetector { * @return A MIME type name. If file type could not be detected or results * were uncertain, octet-stream is returned. * - * @throws TskCoreException + * @throws TskCoreException If there is a problem writing the result to the + * case database. */ public String detect(AbstractFile file) throws TskCoreException { + return detect(file, false); + } + + /** + * Detects the MIME type of a file. The result is posted to the blackboard + * only if the postToBlackBoard parameter is true. + * + * @param file The file to test. + * @param postToBlackBoard Whether the MIME type should be posted to the + * blackboard. + * + * @return A MIME type name. If file type could not be detected or results + * were uncertain, octet-stream is returned. + * + * @throws TskCoreException If there is a problem writing the result to the + * case database. + */ + private String detect(AbstractFile file, boolean postToBlackBoard) throws TskCoreException { + /* + * Check to see if the file has already been typed. + */ + String mimeType = file.getMIMEType(); + if (null != mimeType) { + return mimeType; + } + /* * Mark non-regular files (refer to TskData.TSK_FS_META_TYPE_ENUM), * zero-sized files, unallocated space, and unused blocks (refer to @@ -198,18 +197,21 @@ public class FileTypeDetector { || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) { - return MimeTypes.OCTET_STREAM; + mimeType = MimeTypes.OCTET_STREAM; } /* - * Give precedence to user-defined types. + * If the file is a regular file, give precedence to user-defined types. + */ + if (null == mimeType) { + mimeType = detectUserDefinedType(file, postToBlackBoard); + } + + /* + * If the file does not match a user-defined type, send the initial + * bytes to Tika. */ - String mimeType = detectUserDefinedType(file); if (null == mimeType) { - /* - * The file does not match a user-defined type. Send the initial - * bytes to Tika. - */ try { byte buf[]; int len = file.read(buffer, 0, BUFFER_SIZE); @@ -237,25 +239,57 @@ public class FileTypeDetector { mimeType = MimeTypes.OCTET_STREAM; } } + + /* + * Add the file type to the case database. + */ + file.setMIMEType(mimeType); + Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType); + + /* + * If posting to the blackboard, add the file type attribute to the + * general info artifact. A property change is not fired for this + * posting because general info artifacts are different from other + * artifacts, e.g., they are not displayed in the results tree. + * + * SPECIAL NOTE: This deprecated attribute is added here to support + * backward compatibility, but there is a check-then-act race condition + * that can lead to duplicate attributes. Various mitigation strategies + * were considered. It was decided to go with the policy that this + * method will not be called outside of ingest, at least until such time + * as the attribute is no longer created. Of course, this is not a + * perfect solution. It's not really enforceable and does not handle the + * unlikely case of multiple processes typing the same file for a + * multi-user case. + */ + if (postToBlackBoard) { + BlackboardArtifact getInfoArt = file.getGenInfoArtifact(); + @SuppressWarnings("deprecation") + BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType); + getInfoArt.addAttribute(batt); + } + return mimeType; } /** * Determines whether or not the a file matches a user-defined or Autopsy - * predefined file type. If a match is found and the file type definition - * calls for an alert on a match, an interesting file hit artifact is posted - * to the blackboard. + * predefined file type. If postToBlackBoard is true, and a match is found, + * and the file type definition calls for an alert on a match, an + * interesting file hit artifact is posted to the blackboard. * - * @param file The file to test. + * @param file The file to test. + * @param postToBlackBoard Whether an interesting file hit could be posted + * to the blackboard. * * @return The file type name string or null, if no match is detected. * * @throws TskCoreException */ - private String detectUserDefinedType(AbstractFile file) throws TskCoreException { + private String detectUserDefinedType(AbstractFile file, boolean postToBlackBoard) throws TskCoreException { for (FileType fileType : userDefinedFileTypes) { if (fileType.matches(file)) { - if (fileType.alertOnMatch()) { + if (postToBlackBoard && fileType.alertOnMatch()) { /* * Create an interesting file hit artifact. */ From 49ee29ffcaf4c090ff4e856d427049c2e953c0d4 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Wed, 23 Mar 2016 13:58:38 -0400 Subject: [PATCH 53/77] Fixed ui look for file search. --- .../autopsy/filesearch/Bundle.properties | 8 +- .../autopsy/filesearch/Bundle_ja.properties | 99 ++++++++------- .../autopsy/filesearch/DateSearchPanel.form | 119 ++++++++++-------- .../autopsy/filesearch/DateSearchPanel.java | 100 ++++++++------- .../autopsy/filesearch/FileSearchPanel.form | 41 +++++- .../autopsy/filesearch/FileSearchPanel.java | 47 +++---- .../filesearch/KnownStatusSearchPanel.form | 27 ++-- .../filesearch/KnownStatusSearchPanel.java | 23 ++-- .../autopsy/filesearch/MimeTypePanel.form | 32 +++-- .../autopsy/filesearch/MimeTypePanel.java | 23 +++- .../autopsy/filesearch/NameSearchPanel.form | 24 ++-- .../autopsy/filesearch/NameSearchPanel.java | 19 +-- 12 files changed, 334 insertions(+), 228 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties index de4e16ae5c..d946e2f9c2 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties @@ -18,7 +18,7 @@ DateSearchPanel.jLabel1.text=to DateSearchPanel.dateFromTextField.text= DateSearchPanel.dateFromButtonCalendar.text= NameSearchPanel.nameCheckBox.text=Name: -NameSearchPanel.noteNameLabel.text=*Note: Name match is case insensitive and matches
any part of the file name. Regular expressions are
not currently supported. +NameSearchPanel.noteNameLabel.text=*Note: Name match is case insensitive and matches any part of the file name. Regular expressions are not currently supported. NameSearchPanel.searchTextField.text= SizeSearchPanel.sizeCheckBox.text=Size: NameSearchPanel.cutMenuItem.text=Cut @@ -40,7 +40,6 @@ FileSearchPanel.custComp.label.text=Search for files that match the following cr FileSearchPanel.filterTitle.name=Name FileSearchPanel.filterTitle.metadata=Metadata FileSearchPanel.filterTitle.knownStatus=Known Status -FileSearchPanel.searchButton.text=Search FileSearchPanel.search.results.title=File Search Results {0} FileSearchPanel.search.results.pathText=Filename Search Results\: FileSearchPanel.search.results.msg=File Search\: {0} matches found @@ -54,5 +53,6 @@ SearchNode.getName.text=Search Result SizeSearchPanel.sizeCompareComboBox.equalTo=equal to SizeSearchPanel.sizeCompareComboBox.greaterThan=greater than SizeSearchPanel.sizeCompareComboBox.lessThan=less than -MimeTypePanel.jCheckBox1.text=MIME Type -MimeTypePanel.jLabel1.text=Mime Type +MimeTypePanel.jCheckBox1.text=MIME Type: +MimeTypePanel.jLabel1.text=*Note: Multiple MIME types can be selected +FileSearchPanel.searchButton.text=Search diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle_ja.properties index 891bf77b29..401f521568 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle_ja.properties @@ -1,51 +1,50 @@ -OpenIDE-Module-Name=\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 -KnownStatusSearchPanel.knownCheckBox.text=\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9\uFF1A -KnownStatusSearchPanel.knownBadOptionCheckBox.text=\u65E2\u77E5\u306E\u60AA\u8CEA -KnownStatusSearchPanel.knownOptionCheckBox.text=\u65E2\u77E5\uFF08NSRL\u307E\u305F\u306F\u305D\u306E\u4ED6\uFF09 -KnownStatusSearchPanel.unknownOptionCheckBox.text=\u4E0D\u660E -DateSearchFilter.noneSelectedMsg.text=\u6700\u4F4E\u4E00\u3064\u306E\u30C7\u30FC\u30BF\u30BF\u30A4\u30D7\u3092\u9078\u629E\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF01 -DateSearchPanel.dateCheckBox.text=\u65E5\u4ED8\uFF1A -DateSearchPanel.jLabel4.text=\u30BF\u30A4\u30E0\u30BE\u30FC\u30F3\uFF1A -DateSearchPanel.jLabel3.text=*\u65E5\u4ED8\u306E\u5F62\u5F0F\u306Fmm/dd/yyyy -DateSearchPanel.jLabel2.text=*\u7A7A\u767D\u306E\u9805\u76EE\u306F\u300C\u5236\u9650\u306A\u3057\u300D\u3068\u3044\u3046\u610F\u5473\u3067\u3059 -DateSearchPanel.createdCheckBox.text=\u4F5C\u6210\u6E08\u307F -DateSearchPanel.accessedCheckBox.text=\u30A2\u30AF\u30BB\u30B9\u6E08\u307F -DateSearchPanel.changedCheckBox.text=\u5909\u66F4\u6E08\u307F -DateSearchPanel.modifiedCheckBox.text=\u4FEE\u6B63\u6E08\u307F +OpenIDE-Module-Name=\u30d5\u30a1\u30a4\u30eb\u691c\u7d22 +KnownStatusSearchPanel.knownCheckBox.text=\u65e2\u77e5\u30b9\u30c6\u30fc\u30bf\u30b9\uff1a +KnownStatusSearchPanel.knownBadOptionCheckBox.text=\u65e2\u77e5\u306e\u60aa\u8cea +KnownStatusSearchPanel.knownOptionCheckBox.text=\u65e2\u77e5\uff08NSRL\u307e\u305f\u306f\u305d\u306e\u4ed6\uff09 +KnownStatusSearchPanel.unknownOptionCheckBox.text=\u4e0d\u660e +DateSearchFilter.noneSelectedMsg.text=\u6700\u4f4e\u4e00\u3064\u306e\u30c7\u30fc\u30bf\u30bf\u30a4\u30d7\u3092\u9078\u629e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\uff01 +DateSearchPanel.dateCheckBox.text=\u65e5\u4ed8\uff1a +DateSearchPanel.jLabel4.text=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\uff1a +DateSearchPanel.jLabel3.text=*\u65e5\u4ed8\u306e\u5f62\u5f0f\u306fmm/dd/yyyy +DateSearchPanel.jLabel2.text=*\u7a7a\u767d\u306e\u9805\u76ee\u306f\u300c\u5236\u9650\u306a\u3057\u300d\u3068\u3044\u3046\u610f\u5473\u3067\u3059 +DateSearchPanel.createdCheckBox.text=\u4f5c\u6210\u6e08\u307f +DateSearchPanel.accessedCheckBox.text=\u30a2\u30af\u30bb\u30b9\u6e08\u307f +DateSearchPanel.changedCheckBox.text=\u5909\u66f4\u6e08\u307f +DateSearchPanel.modifiedCheckBox.text=\u4fee\u6b63\u6e08\u307f DateSearchPanel.jLabel1.text=to -NameSearchPanel.nameCheckBox.text=\u540D\u524D\uFF1A -NameSearchPanel.noteNameLabel.text=*\u6CE8\u610F\uFF1A\u540D\u524D\u30DE\u30C3\u30C1\u306F\u5927\u6587\u5B57\u3068\u5C0F\u6587\u5B57\u3092\u533A\u5225\u3057\u307E\u3059\u3002\u307E\u305F\u3001
\u30D5\u30A1\u30A4\u30EB\u540D\u306E\u3044\u304B\u306A\u308B\u90E8\u5206\u3082\u30DE\u30C3\u30C1\u3057\u307E\u3059\u3002\u6B63\u898F\u8868\u73FE\u306F
\u73FE\u5728\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002 -SizeSearchPanel.sizeCheckBox.text=\u30B5\u30A4\u30BA\uFF1A -NameSearchPanel.cutMenuItem.text=\u30AB\u30C3\u30C8 -NameSearchPanel.copyMenuItem.text=\u30B3\u30D4\u30FC -NameSearchPanel.pasteMenuItem.text=\u8CBC\u308A\u4ED8\u3051 -NameSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E -SizeSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E -SizeSearchPanel.pasteMenuItem.text=\u8CBC\u308A\u4ED8\u3051 -SizeSearchPanel.copyMenuItem.text=\u30B3\u30D4\u30FC -SizeSearchPanel.cutMenuItem.text=\u30AB\u30C3\u30C8 -DateSearchPanel.cutMenuItem.text=\u30AB\u30C3\u30C8 -DateSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E -DateSearchPanel.pasteMenuItem.text=\u8CBC\u308A\u4ED8\u3051 -DateSearchPanel.copyMenuItem.text=\u30B3\u30D4\u30FC -FileSearchAction.getName.text=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 -FileSearchDialog.frame.title=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 -FileSearchDialog.frame.msg=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 -FileSearchPanel.custComp.label.text=\u6B21\u306E\u6761\u4EF6\u306B\u4E00\u81F4\u3059\u308B\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\uFF1A -FileSearchPanel.filterTitle.name=\u540D\u524D -FileSearchPanel.filterTitle.metadata=\u30E1\u30BF\u30C7\u30FC\u30BF -FileSearchPanel.filterTitle.knownStatus=\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9 -FileSearchPanel.searchButton.text=\u691C\u7D22 -FileSearchPanel.search.results.title=\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\u7D50\u679C{0} -FileSearchPanel.search.results.pathText=\u30D5\u30A1\u30A4\u30EB\u540D\u691C\u7D22\u7D50\u679C\uFF1A -FileSearchPanel.search.results.msg=\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\uFF1A{0}\u500B\u306E\u30DE\u30C3\u30C1\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F -FileSearchPanel.search.results.details=\u591A\u304F\u306E\u30DE\u30C3\u30C1\u304C\u3042\u308B\u5834\u5408\u3001\u4E00\u90E8\u306E\u51E6\u7406\u306E\u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u306B\u5F71\u97FF\u3092\u4E0E\u3048\u308B\u304B\u3082\u3057\u308C\u307E\u305B\u3093 -FileSearchPanel.search.exception.noFilterSelected.msg=\u6700\u4F4E\uFF11\u500B\u306E\u30D5\u30A3\u30EB\u30BF\u30FC\u3092\u9078\u629E\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 -FileSearchPanel.search.validationErr.msg=\u30D0\u30EA\u30C7\u30FC\u30B7\u30E7\u30F3\u30A8\u30E9\u30FC\uFF1A{0} -FileSearchPanel.emptyWhereClause.text=\u7121\u52B9\u306A\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3059\u3002\u8868\u793A\u3059\u308B\u3082\u306E\u304C\u3042\u308A\u307E\u305B\u3093\u3002 -KnownStatusSearchFilter.noneSelectedMsg.text=\u6700\u4F4E\uFF11\u500B\u306E\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9\u3092\u9078\u629E\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF01 -NameSearchFilter.emptyNameMsg.text=\u540D\u524D\u691C\u7D22\u306B\u4F55\u304B\u8A18\u5165\u3057\u306A\u3051\u308C\u3070\u3044\u3051\u307E\u305B\u3093\u3002 -SearchNode.getName.text=\u691C\u7D22\u7D50\u679C -SizeSearchPanel.sizeCompareComboBox.equalTo=\u4E0B\u8A18\u3068\u7B49\u3057\u3044 -SizeSearchPanel.sizeCompareComboBox.greaterThan=\u4E0B\u8A18\u3088\u308A\u5927\u304D\u3044 -SizeSearchPanel.sizeCompareComboBox.lessThan=\u4E0B\u8A18\u3088\u308A\u5C0F\u3055\u3044 +NameSearchPanel.nameCheckBox.text=\u540d\u524d\uff1a +NameSearchPanel.noteNameLabel.text=*\u6ce8\u610f\uff1a\u540d\u524d\u30de\u30c3\u30c1\u306f\u5927\u6587\u5b57\u3068\u5c0f\u6587\u5b57\u3092\u533a\u5225\u3057\u307e\u3059\u3002\u307e\u305f\u3001
\u30d5\u30a1\u30a4\u30eb\u540d\u306e\u3044\u304b\u306a\u308b\u90e8\u5206\u3082\u30de\u30c3\u30c1\u3057\u307e\u3059\u3002\u6b63\u898f\u8868\u73fe\u306f
\u73fe\u5728\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 +SizeSearchPanel.sizeCheckBox.text=\u30b5\u30a4\u30ba\uff1a +NameSearchPanel.cutMenuItem.text=\u30ab\u30c3\u30c8 +NameSearchPanel.copyMenuItem.text=\u30b3\u30d4\u30fc +NameSearchPanel.pasteMenuItem.text=\u8cbc\u308a\u4ed8\u3051 +NameSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e +SizeSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e +SizeSearchPanel.pasteMenuItem.text=\u8cbc\u308a\u4ed8\u3051 +SizeSearchPanel.copyMenuItem.text=\u30b3\u30d4\u30fc +SizeSearchPanel.cutMenuItem.text=\u30ab\u30c3\u30c8 +DateSearchPanel.cutMenuItem.text=\u30ab\u30c3\u30c8 +DateSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e +DateSearchPanel.pasteMenuItem.text=\u8cbc\u308a\u4ed8\u3051 +DateSearchPanel.copyMenuItem.text=\u30b3\u30d4\u30fc +FileSearchAction.getName.text=\u5c5e\u6027\u306b\u3088\u308b\u30d5\u30a1\u30a4\u30eb\u691c\u7d22 +FileSearchDialog.frame.title=\u5c5e\u6027\u306b\u3088\u308b\u30d5\u30a1\u30a4\u30eb\u691c\u7d22 +FileSearchDialog.frame.msg=\u5c5e\u6027\u306b\u3088\u308b\u30d5\u30a1\u30a4\u30eb\u691c\u7d22 +FileSearchPanel.custComp.label.text=\u6b21\u306e\u6761\u4ef6\u306b\u4e00\u81f4\u3059\u308b\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22\uff1a +FileSearchPanel.filterTitle.name=\u540d\u524d +FileSearchPanel.filterTitle.metadata=\u30e1\u30bf\u30c7\u30fc\u30bf +FileSearchPanel.filterTitle.knownStatus=\u65e2\u77e5\u30b9\u30c6\u30fc\u30bf\u30b9 +FileSearchPanel.search.results.title=\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u7d50\u679c{0} +FileSearchPanel.search.results.pathText=\u30d5\u30a1\u30a4\u30eb\u540d\u691c\u7d22\u7d50\u679c\uff1a +FileSearchPanel.search.results.msg=\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\uff1a{0}\u500b\u306e\u30de\u30c3\u30c1\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f +FileSearchPanel.search.results.details=\u591a\u304f\u306e\u30de\u30c3\u30c1\u304c\u3042\u308b\u5834\u5408\u3001\u4e00\u90e8\u306e\u51e6\u7406\u306e\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u306b\u5f71\u97ff\u3092\u4e0e\u3048\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093 +FileSearchPanel.search.exception.noFilterSelected.msg=\u6700\u4f4e\uff11\u500b\u306e\u30d5\u30a3\u30eb\u30bf\u30fc\u3092\u9078\u629e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 +FileSearchPanel.search.validationErr.msg=\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc\uff1a{0} +FileSearchPanel.emptyWhereClause.text=\u7121\u52b9\u306a\u30aa\u30d7\u30b7\u30e7\u30f3\u3067\u3059\u3002\u8868\u793a\u3059\u308b\u3082\u306e\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +KnownStatusSearchFilter.noneSelectedMsg.text=\u6700\u4f4e\uff11\u500b\u306e\u65e2\u77e5\u30b9\u30c6\u30fc\u30bf\u30b9\u3092\u9078\u629e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\uff01 +NameSearchFilter.emptyNameMsg.text=\u540d\u524d\u691c\u7d22\u306b\u4f55\u304b\u8a18\u5165\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093\u3002 +SearchNode.getName.text=\u691c\u7d22\u7d50\u679c +SizeSearchPanel.sizeCompareComboBox.equalTo=\u4e0b\u8a18\u3068\u7b49\u3057\u3044 +SizeSearchPanel.sizeCompareComboBox.greaterThan=\u4e0b\u8a18\u3088\u308a\u5927\u304d\u3044 +SizeSearchPanel.sizeCompareComboBox.lessThan=\u4e0b\u8a18\u3088\u308a\u5c0f\u3055\u3044 diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.form index 1a9a1dd9f3..4b253ff1e6 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.form +++ b/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.form @@ -55,85 +55,92 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - + + + + + + + + + + + + + + + - - - - - + + + + + + + + - - - - + + + + + + + - - - - + + + + + + + + + + + + + + + - - - - - - - + + + + + + - - - - - - - - - @@ -188,6 +195,9 @@ + + + @@ -208,6 +218,9 @@ + + + diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.java index baa4e63bcc..b2bb6d295c 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/DateSearchPanel.java @@ -74,7 +74,6 @@ class DateSearchPanel extends javax.swing.JPanel { copyMenuItem.addActionListener(actList); pasteMenuItem.addActionListener(actList); selectAllMenuItem.addActionListener(actList); - } JCheckBox getAccessedCheckBox() { @@ -172,6 +171,7 @@ class DateSearchPanel extends javax.swing.JPanel { dateCheckBox.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.dateCheckBox.text")); // NOI18N + jLabel3.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N jLabel3.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.jLabel3.text")); // NOI18N dateFromTextField.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.dateFromTextField.text")); // NOI18N @@ -181,6 +181,7 @@ class DateSearchPanel extends javax.swing.JPanel { } }); + jLabel2.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N jLabel2.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.jLabel2.text")); // NOI18N modifiedCheckBox.setSelected(true); @@ -214,68 +215,73 @@ class DateSearchPanel extends javax.swing.JPanel { layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(dateCheckBox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(dateFromTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, 0) - .addComponent(dateFromButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jLabel1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(dateToTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, 0) - .addComponent(dateToButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(layout.createSequentialGroup() - .addGap(21, 21, 21) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(changedCheckBox) - .addComponent(modifiedCheckBox)) + .addComponent(dateCheckBox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(dateFromTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(dateFromButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(accessedCheckBox) - .addComponent(createdCheckBox))) + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(dateToTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(dateToButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jLabel3))) + .addContainerGap(26, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jLabel4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 193, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(layout.createSequentialGroup() - .addGap(21, 21, 21) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel3) - .addComponent(jLabel2))))) + .addComponent(modifiedCheckBox) + .addGap(6, 6, 6) + .addComponent(accessedCheckBox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(createdCheckBox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(changedCheckBox))) + .addGap(33, 33, 33)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(dateCheckBox) - .addComponent(dateFromTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(dateToButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel1) - .addComponent(dateToTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(dateFromButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(4, 4, 4) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(dateCheckBox) + .addComponent(dateFromTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 18, 18)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(dateToButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(dateToTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(dateFromButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel3) + .addComponent(jLabel2)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel4) .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(layout.createSequentialGroup() - .addComponent(modifiedCheckBox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(changedCheckBox)) - .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(modifiedCheckBox, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(accessedCheckBox) - .addGap(23, 23, 23)) - .addComponent(createdCheckBox)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jLabel2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jLabel3) + .addComponent(createdCheckBox) + .addComponent(changedCheckBox))) .addGap(0, 0, 0)) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.form index 3cb4dc8f4e..dbb90bea12 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.form +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.form @@ -3,7 +3,7 @@
- + @@ -21,13 +21,48 @@ - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java index 5b169e9717..e796589d22 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java @@ -60,8 +60,7 @@ import org.sleuthkit.datamodel.TskCoreException; */ class FileSearchPanel extends javax.swing.JPanel { - private List filterAreas = new ArrayList(); - private JButton searchButton; + private final List filterAreas = new ArrayList<>(); private static int resultWindowCount = 0; //keep track of result windows so they get unique names private static final String EMPTY_WHERE_CLAUSE = NbBundle.getMessage(DateSearchFilter.class, "FileSearchPanel.emptyWhereClause.text"); @@ -79,14 +78,6 @@ class FileSearchPanel extends javax.swing.JPanel { */ private void customizeComponents() { - this.setLayout(new BorderLayout()); - - JPanel filterPanel = new JPanel(); - filterPanel.setLayout(new BoxLayout(filterPanel, BoxLayout.Y_AXIS)); - filterPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); - - this.add(filterPanel, BorderLayout.CENTER); - JLabel label = new JLabel(NbBundle.getMessage(this.getClass(), "FileSearchPanel.custComp.label.text")); label.setAlignmentX(Component.LEFT_ALIGNMENT); label.setBorder(new EmptyBorder(0, 0, 10, 0)); @@ -95,7 +86,7 @@ class FileSearchPanel extends javax.swing.JPanel { // Create and add filter areas this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.name"), new NameSearchFilter())); - List metadataFilters = new ArrayList(); + List metadataFilters = new ArrayList<>(); metadataFilters.add(new SizeSearchFilter()); metadataFilters.add(new MimeTypeFilter()); metadataFilters.add(new DateSearchFilter()); @@ -109,11 +100,6 @@ class FileSearchPanel extends javax.swing.JPanel { filterPanel.add(fa); } - // Create and add search button - this.searchButton = new JButton(NbBundle.getMessage(this.getClass(), "FileSearchPanel.searchButton.text")); - this.searchButton.setAlignmentX(Component.LEFT_ALIGNMENT); - filterPanel.add(searchButton); - addListenerToAll(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -235,7 +221,7 @@ class FileSearchPanel extends javax.swing.JPanel { } private Collection getFilters() { - Collection filters = new ArrayList(); + Collection filters = new ArrayList<>(); for (FilterArea fa : this.filterAreas) { filters.addAll(fa.getFilters()); @@ -245,7 +231,7 @@ class FileSearchPanel extends javax.swing.JPanel { } private Collection getEnabledFilters() { - Collection enabledFilters = new ArrayList(); + Collection enabledFilters = new ArrayList<>(); for (FileSearchFilter f : this.getFilters()) { if (f.isEnabled()) { @@ -274,19 +260,38 @@ class FileSearchPanel extends javax.swing.JPanel { // //GEN-BEGIN:initComponents private void initComponents() { - setPreferredSize(new java.awt.Dimension(300, 450)); + filterPanel = new javax.swing.JPanel(); + searchButton = new javax.swing.JButton(); + + setPreferredSize(new java.awt.Dimension(300, 300)); + + filterPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10)); + filterPanel.setPreferredSize(new java.awt.Dimension(300, 400)); + filterPanel.setLayout(new javax.swing.BoxLayout(filterPanel, javax.swing.BoxLayout.Y_AXIS)); + + searchButton.setText(org.openide.util.NbBundle.getMessage(FileSearchPanel.class, "FileSearchPanel.searchButton.text")); // NOI18N javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 300, Short.MAX_VALUE) + .addComponent(filterPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(searchButton) + .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 376, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(filterPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(0, 0, 0) + .addComponent(searchButton) + .addContainerGap()) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel filterPanel; + private javax.swing.JButton searchButton; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/KnownStatusSearchPanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/KnownStatusSearchPanel.form index 3237a70996..3de5bd4680 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/KnownStatusSearchPanel.form +++ b/Core/src/org/sleuthkit/autopsy/filesearch/KnownStatusSearchPanel.form @@ -16,14 +16,19 @@ - - - + - - - + + + + + + + + + + @@ -32,11 +37,11 @@ - - - - - + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/KnownStatusSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/KnownStatusSearchPanel.java index c2866caacd..9a564fcdbc 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/KnownStatusSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/KnownStatusSearchPanel.java @@ -89,24 +89,27 @@ class KnownStatusSearchPanel extends javax.swing.JPanel { this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(knownCheckBox) .addGroup(layout.createSequentialGroup() - .addGap(21, 21, 21) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(knownBadOptionCheckBox) - .addComponent(unknownOptionCheckBox) - .addComponent(knownOptionCheckBox))) + .addComponent(knownCheckBox) + .addGroup(layout.createSequentialGroup() + .addGap(21, 21, 21) + .addComponent(unknownOptionCheckBox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(knownOptionCheckBox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(knownBadOptionCheckBox))) + .addContainerGap(28, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(knownCheckBox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(unknownOptionCheckBox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(knownOptionCheckBox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(knownBadOptionCheckBox)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(unknownOptionCheckBox) + .addComponent(knownOptionCheckBox) + .addComponent(knownBadOptionCheckBox))) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form index 89d0d39d8b..7fc017726e 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form @@ -24,15 +24,21 @@ - - - - - + + + + + + + + + + + @@ -40,8 +46,10 @@ - - + + + + @@ -76,5 +84,15 @@
+ + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java index 58ba69f75e..6fe2e60f40 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java @@ -82,6 +82,7 @@ public class MimeTypePanel extends javax.swing.JPanel { jScrollPane1 = new javax.swing.JScrollPane(); jList1 = new javax.swing.JList(); jCheckBox1 = new javax.swing.JCheckBox(); + jLabel1 = new javax.swing.JLabel(); setMinimumSize(new java.awt.Dimension(150, 150)); setPreferredSize(new java.awt.Dimension(100, 100)); @@ -96,31 +97,41 @@ public class MimeTypePanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, org.openide.util.NbBundle.getMessage(MimeTypePanel.class, "MimeTypePanel.jCheckBox1.text")); // NOI18N + jLabel1.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(MimeTypePanel.class, "MimeTypePanel.jLabel1.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 180, Short.MAX_VALUE) - .addContainerGap()) .addGroup(layout.createSequentialGroup() .addComponent(jCheckBox1) .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 246, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE))) + .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(jCheckBox1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 164, Short.MAX_VALUE) - .addContainerGap()) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 106, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel1) + .addGap(0, 0, 0)) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JCheckBox jCheckBox1; + private javax.swing.JLabel jLabel1; private javax.swing.JList jList1; private javax.swing.JScrollPane jScrollPane1; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchPanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchPanel.form index e28dd6d357..7b5e61f5e1 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchPanel.form +++ b/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchPanel.form @@ -55,18 +55,16 @@ - - + + + - - + - - - - + + @@ -79,6 +77,7 @@ + @@ -121,6 +120,15 @@ + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchPanel.java index 7f59ec3e3b..dc68c320de 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchPanel.java @@ -121,21 +121,23 @@ class NameSearchPanel extends javax.swing.JPanel { noteNameLabel.setFont(noteNameLabel.getFont().deriveFont(noteNameLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 10)); noteNameLabel.setText(org.openide.util.NbBundle.getMessage(NameSearchPanel.class, "NameSearchPanel.noteNameLabel.text")); // NOI18N + noteNameLabel.setMaximumSize(new java.awt.Dimension(250, 30)); + noteNameLabel.setMinimumSize(new java.awt.Dimension(250, 30)); + noteNameLabel.setPreferredSize(new java.awt.Dimension(250, 30)); 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(nameCheckBox) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addGroup(layout.createSequentialGroup() - .addGap(12, 12, 12) - .addComponent(noteNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap()) + .addGap(0, 0, 0) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(noteNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 296, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(layout.createSequentialGroup() + .addComponent(nameCheckBox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(searchTextField)))) + .addComponent(searchTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 247, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGap(0, 0, 0)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -144,7 +146,8 @@ class NameSearchPanel extends javax.swing.JPanel { .addComponent(nameCheckBox) .addComponent(searchTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(noteNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(noteNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) ); }// //GEN-END:initComponents From e8058f264404648298bf1c2f8fb9f220b5dc78d8 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 23 Mar 2016 14:52:35 -0400 Subject: [PATCH 54/77] Update NEWS.txt for release 4.1.0 --- NEWS.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/NEWS.txt b/NEWS.txt index 53c2d3fb0c..2922552cf5 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,3 +1,14 @@ +---------------- VERSION 4.1.0 -------------- +Improvements: +- VMWare virtual machine files (vmdk) and Microsoft Virtual Hard Drives (vhd) can be added as data sources. +- New core ingest module detects vmdk and vhd files embedded in other data sources and adds them as data sources. +- Custom (user-defined) blackboard artifact and attribute types displayed in UI and included reports. +- File size and MIME type conditions can be specified for interesting files rules. +- File size and MIME type conditions can be specified for file search by attributes. +- Local/GMT time preference is used in reports. +- User has option to choose display name for logical/local file set data sources. +- Assorted bug fixes and minor enhancements. + ---------------- VERSION 4.0.0 -------------- Improvements: - Collaboration supported by optional multi-user cases with centralized data and services From ce814b1f46f3d41939f491c0e2b40e27a06e02c8 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 23 Mar 2016 22:50:33 -0400 Subject: [PATCH 55/77] remove beep because it caused a crash on OS X --- .../autopsy/casemodule/AddImageWizardIngestConfigPanel.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index 6e1d353e22..6291ff7521 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -35,6 +35,7 @@ import org.openide.util.HelpCtx; import org.sleuthkit.datamodel.Content; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestManager; @@ -271,7 +272,10 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel Date: Thu, 24 Mar 2016 08:39:53 -0400 Subject: [PATCH 56/77] Fix logic for conditional case db add/post in modules/filetypeid/FileTypeDetector --- .../modules/filetypeid/FileTypeDetector.java | 70 +++++++++++-------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index ec7fa1dfb7..bc78a95e2d 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -133,7 +133,7 @@ public class FileTypeDetector { * Gets the MIME type of a file, detecting it if it is not already known. If * detection is necessary, the result is added to the case database. * - * IMPORTANT: This method should not be called except by ingest modules; all + * IMPORTANT: This method should only be called by ingest modules. All * other clients should call AbstractFile.getMIMEType, and may call * FileTypeDetector.detect, if AbstractFile.getMIMEType returns null. * @@ -166,12 +166,14 @@ public class FileTypeDetector { } /** - * Detects the MIME type of a file. The result is posted to the blackboard - * only if the postToBlackBoard parameter is true. + * Detects the MIME type of a file. The result is saved to the case database + * only if the add to case dastabase flag is set. * - * @param file The file to test. - * @param postToBlackBoard Whether the MIME type should be posted to the - * blackboard. + * @param file The file to test. + * @param addToCaseDb Whether the MIME type should be added to the case + * database. This flag is part of a partial workaround + * for a check-then-act-race condition (see notes in + * comments for details). * * @return A MIME type name. If file type could not be detected or results * were uncertain, octet-stream is returned. @@ -179,9 +181,10 @@ public class FileTypeDetector { * @throws TskCoreException If there is a problem writing the result to the * case database. */ - private String detect(AbstractFile file, boolean postToBlackBoard) throws TskCoreException { + private String detect(AbstractFile file, boolean addToCaseDb) throws TskCoreException { /* - * Check to see if the file has already been typed. + * Check to see if the file has already been typed. This is the "check" + * part of a check-then-act race condition (see note below). */ String mimeType = file.getMIMEType(); if (null != mimeType) { @@ -204,7 +207,7 @@ public class FileTypeDetector { * If the file is a regular file, give precedence to user-defined types. */ if (null == mimeType) { - mimeType = detectUserDefinedType(file, postToBlackBoard); + mimeType = detectUserDefinedType(file, addToCaseDb); } /* @@ -241,34 +244,41 @@ public class FileTypeDetector { } /* - * Add the file type to the case database. - */ - file.setMIMEType(mimeType); - Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType); - - /* - * If posting to the blackboard, add the file type attribute to the - * general info artifact. A property change is not fired for this - * posting because general info artifacts are different from other - * artifacts, e.g., they are not displayed in the results tree. + * If adding the result to the case database, do so now. * - * SPECIAL NOTE: This deprecated attribute is added here to support - * backward compatibility, but there is a check-then-act race condition - * that can lead to duplicate attributes. Various mitigation strategies - * were considered. It was decided to go with the policy that this - * method will not be called outside of ingest, at least until such time - * as the attribute is no longer created. Of course, this is not a - * perfect solution. It's not really enforceable and does not handle the - * unlikely case of multiple processes typing the same file for a - * multi-user case. + * NOTE: This condtional is a way to deal with the check-then-act race + * condition created by the gap between querying the MIME type and + * recording it. It is not really a problem for the mime_type column of + * the tsk_files table, but it can lead to duplicate blackboard posts, + * and the posts are required to maintain backward compatibility. + * Various mitigation strategies were considered. It was decided to go + * with the policy that only ingest modules are allowed to add file + * types to the case database, at least until such time as file types + * are no longer posted to the blackboard. Of course, this is not a + * perfect solution. It's not really enforceable for community + * contributed plug ins and it does not handle the unlikely but possible + * scenario of multiple processes typing the same file for a multi-user + * case. */ - if (postToBlackBoard) { + if (addToCaseDb) { + /* + * Add the MIME type to the files table in the case database. + */ + Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType); + file.setMIMEType(mimeType); + + /* + * Post to the blackboard, adding the file type attribute to the + * general info artifact. A property change is not fired for this + * posting because general info artifacts are different from other + * artifacts, e.g., they are not displayed in the results tree. + */ BlackboardArtifact getInfoArt = file.getGenInfoArtifact(); @SuppressWarnings("deprecation") BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType); getInfoArt.addAttribute(batt); } - + return mimeType; } From a6e5adbc733ad0a45800f9b9d64a99462ece82bf Mon Sep 17 00:00:00 2001 From: jmillman Date: Mon, 21 Mar 2016 13:24:47 -0400 Subject: [PATCH 57/77] disable subfilters if parent filter is unselected --- .../autopsy/timeline/filters/AbstractFilter.java | 6 +++--- .../autopsy/timeline/filters/CompoundFilter.java | 4 ++++ .../timeline/filters/DataSourcesFilter.java | 4 ++-- .../autopsy/timeline/filters/Filter.java | 2 +- .../autopsy/timeline/filters/HashHitsFilter.java | 2 +- .../autopsy/timeline/filters/RootFilter.java | 16 +++++++++++++++- .../autopsy/timeline/filters/TagsFilter.java | 2 +- .../ui/filtering/FilterCheckBoxCellFactory.java | 5 ++--- 8 files changed, 29 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/AbstractFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/AbstractFilter.java index c5871454d8..798f8aeb9c 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/AbstractFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/AbstractFilter.java @@ -38,7 +38,7 @@ public abstract class AbstractFilter implements Filter { } @Override - public SimpleBooleanProperty getDisabledProperty() { + public SimpleBooleanProperty disabledProperty() { return disabled; } @@ -67,11 +67,11 @@ public abstract class AbstractFilter implements Filter { return "[" + (isSelected() ? "x" : " ") + "]"; // NON-NLS } - public final boolean isActive() { + public boolean isActive() { return activeProperty.get(); } - public final BooleanBinding activeProperty() { + public BooleanBinding activeProperty() { return activeProperty; } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/CompoundFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/CompoundFilter.java index bf4c6a1b07..6f8f656bcf 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/CompoundFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/CompoundFilter.java @@ -67,6 +67,10 @@ public abstract class CompoundFilter extends Abstr } }); this.subFilters.setAll(subFilters); + + this.activeProperty().addListener(activeProperty1 -> { + getSubFilters().forEach(subFilter -> subFilter.setDisabled(isActive() == false)); + }); } private void addSubFilterListeners(List newSubfilters) { diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/DataSourcesFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/DataSourcesFilter.java index 06198052af..a1d348b8b8 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/DataSourcesFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/DataSourcesFilter.java @@ -29,7 +29,7 @@ import org.openide.util.NbBundle; public class DataSourcesFilter extends UnionFilter { public DataSourcesFilter() { - getDisabledProperty().bind(Bindings.size(getSubFilters()).lessThanOrEqualTo(1)); + disabledProperty().bind(Bindings.size(getSubFilters()).lessThanOrEqualTo(1)); setSelected(false); } @@ -69,7 +69,7 @@ public class DataSourcesFilter extends UnionFilter { .map(DataSourceFilter::getDataSourceID) .filter(t -> t == dataSourceFilter.getDataSourceID()) .findAny().isPresent() == false) { - dataSourceFilter.getDisabledProperty().bind(getDisabledProperty()); + dataSourceFilter.disabledProperty().bind(disabledProperty()); getSubFilters().add(dataSourceFilter); getSubFilters().sort(Comparator.comparing(DataSourceFilter::getDisplayName)); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/Filter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/Filter.java index dc44c8912b..9ea652355f 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/Filter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/Filter.java @@ -77,7 +77,7 @@ public interface Filter { */ void setDisabled(Boolean act); - SimpleBooleanProperty getDisabledProperty(); + SimpleBooleanProperty disabledProperty(); boolean isDisabled(); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java index 838144fadd..18d2b43bc9 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java @@ -22,7 +22,7 @@ public class HashHitsFilter extends UnionFilter { } public HashHitsFilter() { - getDisabledProperty().bind(Bindings.size(getSubFilters()).lessThan(1)); + disabledProperty().bind(Bindings.size(getSubFilters()).lessThan(1)); setSelected(false); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/RootFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/RootFilter.java index 9034810ed7..2b31978d7b 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/RootFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/RootFilter.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.timeline.filters; import java.util.Set; import java.util.stream.Collectors; +import javafx.beans.binding.BooleanBinding; import javafx.collections.FXCollections; /** @@ -70,7 +71,7 @@ public class RootFilter extends IntersectionFilter { public RootFilter copyOf() { Set annonymousSubFilters = getSubFilters().stream() .filter(subFilter -> - !(subFilter.equals(knownFilter) + !(subFilter.equals(knownFilter) || subFilter.equals(tagsFilter) || subFilter.equals(hashFilter) || subFilter.equals(typeFilter) @@ -108,4 +109,17 @@ public class RootFilter extends IntersectionFilter { } return areSubFiltersEqual(this, (CompoundFilter) obj); } + + public boolean isActive() { + return true; + } + + public BooleanBinding activeProperty() { + return new BooleanBinding() { + @Override + protected boolean computeValue() { + return true; + } + }; + } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java index 6d90482157..f2c0e79152 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java @@ -23,7 +23,7 @@ public class TagsFilter extends UnionFilter { } public TagsFilter() { - getDisabledProperty().bind(Bindings.size(getSubFilters()).lessThan(1)); + disabledProperty().bind(Bindings.size(getSubFilters()).lessThan(1)); setSelected(false); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/FilterCheckBoxCellFactory.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/FilterCheckBoxCellFactory.java index 535289c6aa..2b432b525f 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/FilterCheckBoxCellFactory.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/FilterCheckBoxCellFactory.java @@ -41,13 +41,12 @@ class FilterCheckBoxCellFactory extends AbstractFXCell } if (item == null) { - cell.setText(null); cell.setGraphic(null); } else { - cell.setText(item.getDisplayName()); + checkBox.setText(item.getDisplayName()); selectedProperty = item.selectedProperty(); checkBox.selectedProperty().bindBidirectional(selectedProperty); - disabledProperty = item.getDisabledProperty(); + disabledProperty = item.disabledProperty(); checkBox.disableProperty().bindBidirectional(disabledProperty); cell.setGraphic(checkBox); } From 2a7c0e33ce848f515f1f1f3ecae1fbaa48dd0064 Mon Sep 17 00:00:00 2001 From: jmillman Date: Wed, 23 Mar 2016 16:29:53 -0400 Subject: [PATCH 58/77] stop disabling filters when there is only one possible value because it conflicted with disabling them if no children are selected --- .../sleuthkit/autopsy/timeline/filters/CompoundFilter.java | 5 ++++- .../autopsy/timeline/filters/DataSourcesFilter.java | 3 --- .../sleuthkit/autopsy/timeline/filters/HashHitsFilter.java | 2 -- .../org/sleuthkit/autopsy/timeline/filters/TagsFilter.java | 3 --- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/CompoundFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/CompoundFilter.java index 6f8f656bcf..eacb17d642 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/CompoundFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/CompoundFilter.java @@ -68,7 +68,10 @@ public abstract class CompoundFilter extends Abstr }); this.subFilters.setAll(subFilters); - this.activeProperty().addListener(activeProperty1 -> { + this.selectedProperty().addListener(activeProperty1 -> { + getSubFilters().forEach(subFilter -> subFilter.setDisabled(isActive() == false)); + }); + this.disabledProperty().addListener(activeProperty1 -> { getSubFilters().forEach(subFilter -> subFilter.setDisabled(isActive() == false)); }); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/DataSourcesFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/DataSourcesFilter.java index a1d348b8b8..3b33ddbe0c 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/DataSourcesFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/DataSourcesFilter.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.timeline.filters; import java.util.Comparator; import java.util.stream.Collectors; -import javafx.beans.binding.Bindings; import org.openide.util.NbBundle; /** @@ -29,7 +28,6 @@ import org.openide.util.NbBundle; public class DataSourcesFilter extends UnionFilter { public DataSourcesFilter() { - disabledProperty().bind(Bindings.size(getSubFilters()).lessThanOrEqualTo(1)); setSelected(false); } @@ -69,7 +67,6 @@ public class DataSourcesFilter extends UnionFilter { .map(DataSourceFilter::getDataSourceID) .filter(t -> t == dataSourceFilter.getDataSourceID()) .findAny().isPresent() == false) { - dataSourceFilter.disabledProperty().bind(disabledProperty()); getSubFilters().add(dataSourceFilter); getSubFilters().sort(Comparator.comparing(DataSourceFilter::getDisplayName)); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java index 18d2b43bc9..ad2c04baa0 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java @@ -7,7 +7,6 @@ package org.sleuthkit.autopsy.timeline.filters; import java.util.Comparator; import java.util.stream.Collectors; -import javafx.beans.binding.Bindings; import org.openide.util.NbBundle; /** @@ -22,7 +21,6 @@ public class HashHitsFilter extends UnionFilter { } public HashHitsFilter() { - disabledProperty().bind(Bindings.size(getSubFilters()).lessThan(1)); setSelected(false); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java index f2c0e79152..2e3fec6693 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java @@ -7,7 +7,6 @@ package org.sleuthkit.autopsy.timeline.filters; import java.util.Comparator; import java.util.stream.Collectors; -import javafx.beans.binding.Bindings; import org.openide.util.NbBundle; import org.sleuthkit.datamodel.TagName; @@ -23,7 +22,6 @@ public class TagsFilter extends UnionFilter { } public TagsFilter() { - disabledProperty().bind(Bindings.size(getSubFilters()).lessThan(1)); setSelected(false); } @@ -89,5 +87,4 @@ public class TagsFilter extends UnionFilter { getSubFilters().sort(Comparator.comparing(TagNameFilter::getDisplayName)); } - } From 2e36dcb0408c8c9644e48e687747242639d4b9e8 Mon Sep 17 00:00:00 2001 From: jmillman Date: Thu, 24 Mar 2016 13:32:41 -0400 Subject: [PATCH 59/77] support subfilter disabling and [parent filter diabling based on nunber of subfilters. --- .../autopsy/timeline/filters/AbstractFilter.java | 7 ++++--- .../autopsy/timeline/filters/CompoundFilter.java | 4 ++-- .../autopsy/timeline/filters/DataSourcesFilter.java | 8 ++++++++ .../org/sleuthkit/autopsy/timeline/filters/Filter.java | 3 ++- .../autopsy/timeline/filters/HashHitsFilter.java | 7 +++++++ .../sleuthkit/autopsy/timeline/filters/TagsFilter.java | 6 ++++++ .../timeline/ui/filtering/FilterCheckBoxCellFactory.java | 7 ++++--- 7 files changed, 33 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/AbstractFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/AbstractFilter.java index 798f8aeb9c..c51b3a82ed 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/AbstractFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/AbstractFilter.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.timeline.filters; import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanBinding; import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.value.ObservableBooleanValue; /** * Base implementation of a {@link Filter}. Implements active property. @@ -38,7 +39,7 @@ public abstract class AbstractFilter implements Filter { } @Override - public SimpleBooleanProperty disabledProperty() { + public ObservableBooleanValue disabledProperty() { return disabled; } @@ -67,11 +68,11 @@ public abstract class AbstractFilter implements Filter { return "[" + (isSelected() ? "x" : " ") + "]"; // NON-NLS } - public boolean isActive() { + public boolean isActive() { return activeProperty.get(); } - public BooleanBinding activeProperty() { + public BooleanBinding activeProperty() { return activeProperty; } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/CompoundFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/CompoundFilter.java index eacb17d642..dff26b1e61 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/CompoundFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/CompoundFilter.java @@ -68,10 +68,10 @@ public abstract class CompoundFilter extends Abstr }); this.subFilters.setAll(subFilters); - this.selectedProperty().addListener(activeProperty1 -> { + this.selectedProperty().addListener(activeProperty -> { getSubFilters().forEach(subFilter -> subFilter.setDisabled(isActive() == false)); }); - this.disabledProperty().addListener(activeProperty1 -> { + this.disabledProperty().addListener(activeProperty -> { getSubFilters().forEach(subFilter -> subFilter.setDisabled(isActive() == false)); }); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/DataSourcesFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/DataSourcesFilter.java index 3b33ddbe0c..02318310f1 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/DataSourcesFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/DataSourcesFilter.java @@ -20,6 +20,8 @@ package org.sleuthkit.autopsy.timeline.filters; import java.util.Comparator; import java.util.stream.Collectors; +import javafx.beans.binding.Bindings; +import javafx.beans.value.ObservableBooleanValue; import org.openide.util.NbBundle; /** @@ -97,4 +99,10 @@ public class DataSourcesFilter extends UnionFilter { public int hashCode() { return 9; } + + @Override + public ObservableBooleanValue disabledProperty() { + return Bindings.or(super.disabledProperty(), Bindings.size(getSubFilters()).lessThanOrEqualTo(1)); + } + } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/Filter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/Filter.java index 9ea652355f..435998a183 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/Filter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/Filter.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.timeline.filters; import javafx.beans.binding.BooleanBinding; import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.value.ObservableBooleanValue; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -77,7 +78,7 @@ public interface Filter { */ void setDisabled(Boolean act); - SimpleBooleanProperty disabledProperty(); + ObservableBooleanValue disabledProperty(); boolean isDisabled(); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java index ad2c04baa0..b7a13184f7 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/HashHitsFilter.java @@ -7,6 +7,8 @@ package org.sleuthkit.autopsy.timeline.filters; import java.util.Comparator; import java.util.stream.Collectors; +import javafx.beans.binding.Bindings; +import javafx.beans.value.ObservableBooleanValue; import org.openide.util.NbBundle; /** @@ -79,4 +81,9 @@ public class HashHitsFilter extends UnionFilter { getSubFilters().sort(Comparator.comparing(HashSetFilter::getDisplayName)); } } + + @Override + public ObservableBooleanValue disabledProperty() { + return Bindings.or(super.disabledProperty(), Bindings.isEmpty(getSubFilters())); + } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java b/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java index 2e3fec6693..1ab69a3909 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/filters/TagsFilter.java @@ -7,6 +7,8 @@ package org.sleuthkit.autopsy.timeline.filters; import java.util.Comparator; import java.util.stream.Collectors; +import javafx.beans.binding.Bindings; +import javafx.beans.value.ObservableBooleanValue; import org.openide.util.NbBundle; import org.sleuthkit.datamodel.TagName; @@ -87,4 +89,8 @@ public class TagsFilter extends UnionFilter { getSubFilters().sort(Comparator.comparing(TagNameFilter::getDisplayName)); } + @Override + public ObservableBooleanValue disabledProperty() { + return Bindings.or(super.disabledProperty(), Bindings.isEmpty(getSubFilters())); + } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/FilterCheckBoxCellFactory.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/FilterCheckBoxCellFactory.java index 2b432b525f..689bb47702 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/FilterCheckBoxCellFactory.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/FilterCheckBoxCellFactory.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.timeline.ui.filtering; import java.util.function.Supplier; import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.value.ObservableBooleanValue; import javafx.scene.control.CheckBox; import javafx.scene.control.IndexedCell; import org.sleuthkit.autopsy.timeline.filters.AbstractFilter; @@ -29,7 +30,7 @@ class FilterCheckBoxCellFactory extends AbstractFXCell private final CheckBox checkBox = new CheckBox(); private SimpleBooleanProperty selectedProperty; - private SimpleBooleanProperty disabledProperty; + private ObservableBooleanValue disabledProperty; @Override protected void configureCell(IndexedCell cell, X item, boolean empty, Supplier supplier) { @@ -37,7 +38,7 @@ class FilterCheckBoxCellFactory extends AbstractFXCell checkBox.selectedProperty().unbindBidirectional(selectedProperty); } if (disabledProperty != null) { - checkBox.disableProperty().unbindBidirectional(disabledProperty); + checkBox.disableProperty().unbind();//disabledProperty); } if (item == null) { @@ -47,7 +48,7 @@ class FilterCheckBoxCellFactory extends AbstractFXCell selectedProperty = item.selectedProperty(); checkBox.selectedProperty().bindBidirectional(selectedProperty); disabledProperty = item.disabledProperty(); - checkBox.disableProperty().bindBidirectional(disabledProperty); + checkBox.disableProperty().bind(disabledProperty); cell.setGraphic(checkBox); } } From 8c0680c1c5ce45f3de9fe7aa09a0a8e43b6c512f Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Thu, 24 Mar 2016 13:36:10 -0400 Subject: [PATCH 60/77] Got rid of raw types warning in MImeTyepPanel, updated docs. --- Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java | 3 +-- Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form | 2 +- Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java index a6978109a5..b119566299 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java @@ -8,8 +8,7 @@ package org.sleuthkit.autopsy.filesearch; import java.awt.event.ActionListener; /** - * - * @author oliver + * Filter by mime type used in filter areas of file search by attribute. */ class MimeTypeFilter extends AbstractFileSearchFilter { diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form index 7fc017726e..9221d39633 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form @@ -65,7 +65,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java index 6fe2e60f40..8a90761946 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java @@ -87,10 +87,10 @@ public class MimeTypePanel extends javax.swing.JPanel { setMinimumSize(new java.awt.Dimension(150, 150)); setPreferredSize(new java.awt.Dimension(100, 100)); - jList1.setModel(new javax.swing.AbstractListModel() { + jList1.setModel(new javax.swing.AbstractListModel() { String[] strings = getMimeTypeArray(); public int getSize() { return strings.length; } - public Object getElementAt(int i) { return strings[i]; } + public String getElementAt(int i) { return strings[i]; } }); jList1.setMinimumSize(new java.awt.Dimension(0, 200)); jScrollPane1.setViewportView(jList1); From e81868916a507dd537ada173c77637e5162151b7 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 24 Mar 2016 13:44:19 -0400 Subject: [PATCH 61/77] Do not call non-publicAbstractFile.setMIMEType in modules/filetypeid/FileTypeDetector --- .../modules/filetypeid/FileTypeDetector.java | 1 - .../autopsy/report/Bundle.properties | 6 ++- .../autopsy/report/Bundle_ja.properties | 9 ++-- .../autopsy/report/ReportProgressPanel.form | 17 +++++-- .../autopsy/report/ReportProgressPanel.java | 47 +++++++++++++------ 5 files changed, 55 insertions(+), 25 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index bc78a95e2d..0546a01f01 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -265,7 +265,6 @@ public class FileTypeDetector { * Add the MIME type to the files table in the case database. */ Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType); - file.setMIMEType(mimeType); /* * Post to the blackboard, adding the file type attribute to the diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties index 8bafc2aa3a..0be3a1924f 100644 --- a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties @@ -14,6 +14,9 @@ ArtifactSelectionDialog.selectAllButton.text=Select All ReportGenerationPanel.closeButton.text=Close ReportProgressPanel.reportLabel.text=reportLabel ReportProgressPanel.pathLabel.text=pathLabel +ReportProgressPanel.separationLabel.text=: +ReportProgressPanel.statusMessageLabel.text=processingLabel +ReportGenerationPanel.titleLabel.text=Report Generation Progress ReportVisualPanel2.taggedResultsRadioButton.text=Tagged Results ReportVisualPanel2.allResultsRadioButton.text=All Results ReportWizardFileOptionsVisualPanel.selectAllButton.text=Select All @@ -203,8 +206,10 @@ ReportProgressPanel.initPathLabel.noFile=No report file ReportProgressPanel.start.cancelButton.text=Cancel ReportProgressPanel.start.progress.text=Starting report... ReportProgressPanel.complete.processLbl.text=Complete +ReportProgressPanel.complete.processLb2.text=Completed with error ReportProgressPanel.complete.cancelButton.text=Complete ReportProgressPanel.cancel.cancelButton.toolTipText=Canceled +ReportProgressPanel.cancel.procLbl.text=Canceled ReportVisualPanel1.getName.text=Select and Configure Report Modules ReportVisualPanel2.getName.text=Configure Artifact Reports ReportWizardAction.actionName.text=Generate Report @@ -244,4 +249,3 @@ ReportKML.latLongStartPoint={0};{1};;{2} (Start)\n ReportKML.latLongEndPoint={0};{1};;{2} (End)\n ReportGenerationPanel.cancelButton.actionCommand=Cancel ReportGenerationPanel.cancelButton.text=Cancel -ReportProgressPanel.separationLabel.text=: diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties index aae60084fb..6ff657b68a 100644 --- a/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties @@ -13,6 +13,9 @@ ArtifactSelectionDialog.selectAllButton.text=\u5168\u3066\u9078\u629e ReportGenerationPanel.closeButton.text=\u9589\u3058\u308b ReportProgressPanel.reportLabel.text=\u30ec\u30dd\u30fc\u30c8\u30e9\u30d9\u30eb ReportProgressPanel.pathLabel.text=\u30d1\u30b9\u30e9\u30d9\u30eb +ReportProgressPanel.separationLabel.text=: +ReportProgressPanel.statusMessageLabel.text=\u30d7\u30ed\u30bb\u30b7\u30f3\u30b0\u30e9\u30d9\u30eb +ReportGenerationPanel.titleLabel.text=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u30d7\u30ed\u30b0\u30ec\u30b9 ReportVisualPanel2.taggedResultsRadioButton.text=\u30bf\u30b0\u3055\u308c\u305f\u7d50\u679c ReportVisualPanel2.allResultsRadioButton.text=\u5168\u3066\u306e\u7d50\u679c ReportWizardFileOptionsVisualPanel.selectAllButton.text=\u5168\u3066\u9078\u629e @@ -165,6 +168,7 @@ ReportHTML.writeSum.timezone=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\uff1a ReportProgressPanel.progress.queuing=\u30ad\u30e5\u30fc\u30a4\u30f3\u30b0\u2026 ReportProgressPanel.initPathLabel.noFile=\u30ec\u30dd\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u7121\u3057 ReportProgressPanel.start.progress.text=\u30ec\u30dd\u30fc\u30c8\u958b\u59cb\u4e2d\u2026 +ReportProgressPanel.cancel.procLbl.text=\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f ReportVisualPanel1.getName.text=\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u9078\u629e\u304a\u3088\u3073\u8a2d\u5b9a ReportVisualPanel2.getName.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30ec\u30dd\u30fc\u30c8\u3092\u8a2d\u5b9a ReportWizardFileOptionsPanel.finishButton.text=\u7d42\u4e86 @@ -230,7 +234,6 @@ ReportGenerator.htmlOutput.header.hash=\u30cf\u30c3\u30b7\u30e5 ReportGenerator.htmlOutput.header.size=\u30b5\u30a4\u30ba\uff08\u30d0\u30a4\u30c8\uff09 ReportGenerator.htmlOutput.header.tag=\u30bf\u30b0 ReportGenerator.htmlOutput.header.timeAccessed=\u30a2\u30af\u30bb\u30b9\u65e5\u6642 -ReportGenerator.htmlOutput.header.timeChanged=\u5909\u66f4\u65e5\u6642 ReportGenerator.htmlOutput.header.timeCreated=\u4f5c\u6210\u65e5\u6642 ReportGenerator.htmlOutput.header.timeModified=\u4fee\u6b63\u65e5\u6642 ReportGenerator.notifyErr.errsDuringRptGen=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306e\u30a8\u30e9\u30fc\uff1a @@ -238,6 +241,6 @@ ReportGenerator.errList.failedGetAbstractFileFromID=ID\u306b\u57fa\u3065\u304d\u ReportKML.getFilePath.text=\u30ec\u30dd\u30fc\u30c8KML.kml ReportVisualPanel1.invalidModuleWarning=\u7121\u52b9\u306a\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb({0})\u306b\u906d\u9047\u3057\u307e\u3057\u305f ReportGenerationPanel.confDlg.cancelReport.msg=\u672c\u5f53\u306b\u30ec\u30dd\u30fc\u30c8\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3059\u304b\uff1f +ReportProgressPanel.complete.processLb2.text=\u5b8c\u4e86\u3057\u307e\u3057\u305f\u304c\u3001\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f ReportGenerationPanel.cancelButton.actionCommand=\u30ad\u30e3\u30f3\u30bb\u30eb -ReportGenerationPanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb -ReportProgressPanel.separationLabel.text=- +ReportGenerationPanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.form b/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.form index 8291726f99..597dd89df4 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.form +++ b/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.form @@ -29,10 +29,8 @@ - - - - + + @@ -56,7 +54,9 @@ - + + + @@ -108,5 +108,12 @@ + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java b/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java index a1c560f076..59a7cb38b1 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportProgressPanel.java @@ -65,6 +65,7 @@ public class ReportProgressPanel extends javax.swing.JPanel { reportProgressBar.setIndeterminate(true); reportProgressBar.setMaximum(100); reportLabel.setText(reportName); + statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.progress.queuing")); status = ReportStatus.QUEUING; if (null != reportPath) { pathLabel.setText("" + shortenPath(reportPath) + ""); //NON-NLS @@ -148,6 +149,7 @@ public class ReportProgressPanel extends javax.swing.JPanel { */ public void start() { EventQueue.invokeLater(() -> { + statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.start.progress.text")); status = ReportStatus.RUNNING; }); } @@ -205,6 +207,21 @@ public class ReportProgressPanel extends javax.swing.JPanel { }); } + /** + * Changes the status message label component of this panel to show a given + * processing status message. For example, updateStatusLabel("Now processing + * files...") sets the label text to "Now processing files..." + * + * @param statusMessage String to use as label text. + */ + public void updateStatusLabel(String statusMessage) { + EventQueue.invokeLater(() -> { + if (status != ReportStatus.CANCELED) { + statusMessageLabel.setText(statusMessage); + } + }); + } + /** * Makes the components of this panel indicate the final status of * generation of the report. @@ -219,6 +236,8 @@ public class ReportProgressPanel extends javax.swing.JPanel { case COMPLETE: { ReportStatus oldValue = status; status = ReportStatus.COMPLETE; + statusMessageLabel.setForeground(Color.BLACK); + statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.complete.processLbl.text")); reportProgressBar.setValue(reportProgressBar.getMaximum()); reportProgressBar.setStringPainted(true); reportProgressBar.setForeground(GREEN); @@ -229,6 +248,8 @@ public class ReportProgressPanel extends javax.swing.JPanel { case ERROR: { ReportStatus oldValue = status; status = ReportStatus.ERROR; + statusMessageLabel.setForeground(RED); + statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.complete.processLb2.text")); reportProgressBar.setValue(reportProgressBar.getMaximum()); reportProgressBar.setStringPainted(true); reportProgressBar.setForeground(RED); @@ -265,6 +286,8 @@ public class ReportProgressPanel extends javax.swing.JPanel { reportProgressBar.setForeground(RED); // Red reportProgressBar.setString("Cancelled"); //NON-NLS pcs.firePropertyChange(ReportStatus.CANCELED.toString(), oldValue, status); + statusMessageLabel.setForeground(RED); + statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.cancel.procLbl.text")); break; } } @@ -298,6 +321,7 @@ public class ReportProgressPanel extends javax.swing.JPanel { reportLabel = new javax.swing.JLabel(); pathLabel = new javax.swing.JLabel(); separationLabel = new javax.swing.JLabel(); + statusMessageLabel = new javax.swing.JLabel(); setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11)); setMinimumSize(new java.awt.Dimension(486, 68)); @@ -314,6 +338,8 @@ public class ReportProgressPanel extends javax.swing.JPanel { separationLabel.setFont(separationLabel.getFont().deriveFont(separationLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); org.openide.awt.Mnemonics.setLocalizedText(separationLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.separationLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(statusMessageLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.statusMessageLabel.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -321,9 +347,8 @@ public class ReportProgressPanel extends javax.swing.JPanel { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(reportProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGap(0, 0, 0)) + .addComponent(statusMessageLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(reportProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(reportLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -342,7 +367,9 @@ public class ReportProgressPanel extends javax.swing.JPanel { .addComponent(reportLabel) .addComponent(pathLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(separationLabel)) - .addGap(33, 33, 33)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(statusMessageLabel) + .addGap(13, 13, 13)) ); }// //GEN-END:initComponents @@ -352,19 +379,9 @@ public class ReportProgressPanel extends javax.swing.JPanel { private javax.swing.JLabel reportLabel; private javax.swing.JProgressBar reportProgressBar; private javax.swing.JLabel separationLabel; + private javax.swing.JLabel statusMessageLabel; // End of variables declaration//GEN-END:variables - /** - * Does nothing, the status label it used to update no longer exists. - * - * @param status String to use as status - * - * @deprecated - */ - @Deprecated - public void updateStatusLabel(final String status) { - } - /** * Makes the components of this panel indicate the generation of the report * is completed. From 72a96d600274cd5ad9f0c405370e84e7c99de570 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Thu, 24 Mar 2016 15:15:23 -0400 Subject: [PATCH 62/77] Made tagged results data work for all reports. --- .../sleuthkit/autopsy/report/ReportGenerator.java | 12 ++++++++++++ .../src/org/sleuthkit/autopsy/report/ReportHTML.java | 9 --------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 38a5931427..1f49588837 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -655,6 +655,18 @@ class ReportGenerator { } ArrayList rowData = new ArrayList<>(Arrays.asList(tag.getName().getDisplayName(), fileName, tag.getComment())); + Content content = tag.getContent(); + if (content instanceof AbstractFile) { + AbstractFile file = (AbstractFile) content; + + // Add metadata about the file to HTML output + rowData.add(file.getMtimeAsDate()); + rowData.add(file.getCtimeAsDate()); + rowData.add(file.getAtimeAsDate()); + rowData.add(file.getCrtimeAsDate()); + rowData.add(Long.toString(file.getSize())); + rowData.add(file.getMd5Hash()); + } for (TableReportModule module : tableModules) { // @@@ This casting is a tricky little workaround to allow the HTML report module to slip in a content hyperlink. if (module instanceof ReportHTML) { diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index 196f770ca7..eeca1efe56 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -560,15 +560,6 @@ class ReportHTML implements TableReportModule { return; } AbstractFile file = (AbstractFile) content; - - // Add metadata about the file to HTML output - row.add(file.getMtimeAsDate()); - row.add(file.getCtimeAsDate()); - row.add(file.getAtimeAsDate()); - row.add(file.getCrtimeAsDate()); - row.add(Long.toString(file.getSize())); - row.add(file.getMd5Hash()); - // Add the hyperlink to the row. A column header for it was created in startTable(). StringBuilder localFileLink = new StringBuilder(); // Don't make a local copy of the file if it is a directory or unallocated space. From 843fefac2546908bbab92da60a72eb95979496d9 Mon Sep 17 00:00:00 2001 From: jmillman Date: Thu, 24 Mar 2016 15:46:01 -0400 Subject: [PATCH 63/77] prevent progressdialog from blocking input to the main timeline window --- .../autopsy/timeline/PromptDialogManager.java | 2 + .../autopsy/timeline/TimeLineController.java | 40 ++++++++----------- .../autopsy/timeline/db/EventsRepository.java | 20 +++++----- 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/PromptDialogManager.java b/Core/src/org/sleuthkit/autopsy/timeline/PromptDialogManager.java index 131b8db003..6f58bade53 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/PromptDialogManager.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/PromptDialogManager.java @@ -88,6 +88,7 @@ public class PromptDialogManager { @ThreadConfined(type = ThreadConfined.ThreadType.JFX) public void showProgressDialog(CancellationProgressTask task) { currentDialog = new ProgressDialog(task); + currentDialog.initModality(Modality.NONE); currentDialog.headerTextProperty().bind(task.titleProperty()); setDialogIcons(currentDialog); currentDialog.setTitle(Bundle.PromptDialogManager_progressDialog_title()); @@ -98,6 +99,7 @@ public class PromptDialogManager { //co-ordinate task cancelation and dialog hiding. task.setOnCancelled(cancelled -> currentDialog.close()); task.setOnSucceeded(succeeded -> currentDialog.close()); + task.setOnFailed(failed -> currentDialog.close()); dialogPane.getButtonTypes().setAll(ButtonType.CANCEL); final Node cancelButton = dialogPane.lookupButton(ButtonType.CANCEL); cancelButton.disableProperty().bind(task.cancellableProperty().not()); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index ee581fbd7d..4a925800bf 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -30,6 +30,8 @@ import java.util.TimeZone; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.function.Consumer; +import java.util.function.Function; import java.util.logging.Level; import javafx.application.Platform; import javafx.beans.Observable; @@ -288,26 +290,17 @@ public class TimeLineController { advance(filteredEvents.zoomParametersProperty().get().withTimeRange(boundingEventsInterval)); } - /** - * rebuld the repo. - * - * @return False if the repo was not rebuilt because because the user - * aborted after prompt about ingest running. True if the repo was - * rebuilt. - */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - void rebuildRepo() { + private void rebuildRepoHelper(Function, CancellationProgressTask> repoBuilder) { SwingUtilities.invokeLater(this::closeTimelineWindow); - final CancellationProgressTask rebuildRepository = eventsRepository.rebuildRepository(); boolean ingestRunning = IngestManager.getInstance().isIngestRunning(); - rebuildRepository.stateProperty().addListener((stateProperty, oldState, newSate) -> { - //this will be on JFX thread + final CancellationProgressTask rebuildRepository = repoBuilder.apply(newSate -> { setIngestRunning(ingestRunning); + //this will be on JFX thread switch (newSate) { case SUCCEEDED: setEventsDBStale(false); SwingUtilities.invokeLater(TimeLineController.this::showWindow); - historyManager.reset(filteredEvents.zoomParametersProperty().get()); TimeLineController.this.showFullRange(); break; @@ -318,7 +311,18 @@ public class TimeLineController { } }); promptDialogManager.showProgressDialog(rebuildRepository); + } + /** + * rebuld the repo. + * + * @return False if the repo was not rebuilt because because the user + * aborted after prompt about ingest running. True if the repo was + * rebuilt. + */ + @ThreadConfined(type = ThreadConfined.ThreadType.JFX) + void rebuildRepo() { + rebuildRepoHelper(eventsRepository::rebuildRepository); } /** @@ -329,17 +333,7 @@ public class TimeLineController { */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) void rebuildTagsTable() { - - SwingUtilities.invokeLater(this::closeTimelineWindow); - CancellationProgressTask rebuildTags = eventsRepository.rebuildTags(); - rebuildTags.stateProperty().addListener((stateProperty, oldState, newSate) -> { - //this will be on JFX thread - if (newSate == Worker.State.SUCCEEDED) { - SwingUtilities.invokeLater(TimeLineController.this::showWindow); - showFullRange(); - } - }); - promptDialogManager.showProgressDialog(rebuildTags); + rebuildRepoHelper(eventsRepository::rebuildTags); } @ThreadConfined(type = ThreadConfined.ThreadType.AWT) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java b/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java index c8554cfdc3..bc490faed4 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java @@ -35,6 +35,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; import java.util.logging.Level; import java.util.stream.Collectors; import javafx.application.Platform; @@ -44,6 +45,7 @@ import javafx.beans.property.ReadOnlyObjectProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.ObservableMap; +import javafx.concurrent.Worker; import javax.swing.JOptionPane; import org.apache.commons.lang3.StringUtils; import org.joda.time.Interval; @@ -177,7 +179,6 @@ public class EventsRepository { } - public TimeLineEvent getEventById(Long eventID) { return idToEventCache.getUnchecked(eventID); } @@ -310,8 +311,6 @@ public class EventsRepository { } } - - public boolean areFiltersEquivalent(RootFilter f1, RootFilter f2) { return SQLHelper.getSQLWhere(f1).equals(SQLHelper.getSQLWhere(f2)); } @@ -322,13 +321,13 @@ public class EventsRepository { } @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - public CancellationProgressTask rebuildRepository() { - return rebuildRepository(DBPopulationMode.FULL); + public CancellationProgressTask rebuildRepository(Consumer onStateChange) { + return rebuildRepository(DBPopulationMode.FULL, onStateChange); } @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - public CancellationProgressTask rebuildTags() { - return rebuildRepository(DBPopulationMode.TAGS_ONLY); + public CancellationProgressTask rebuildTags(Consumer onStateChange) { + return rebuildRepository(DBPopulationMode.TAGS_ONLY, onStateChange); } /** @@ -336,12 +335,12 @@ public class EventsRepository { * @param mode the value of mode */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - private CancellationProgressTask rebuildRepository(final DBPopulationMode mode) { + private CancellationProgressTask rebuildRepository(final DBPopulationMode mode, Consumer onStateChange) { LOGGER.log(Level.INFO, "(re)starting {0} db population task", mode); //NON-NLS if (dbWorker != null) { dbWorker.cancel(); } - dbWorker = new DBPopulationWorker(mode); + dbWorker = new DBPopulationWorker(mode, onStateChange); workerExecutor.execute(dbWorker); return dbWorker; } @@ -406,10 +405,11 @@ public class EventsRepository { } } - DBPopulationWorker(DBPopulationMode mode) { + DBPopulationWorker(DBPopulationMode mode, Consumer onStateChange) { skCase = autoCase.getSleuthkitCase(); tagsManager = autoCase.getServices().getTagsManager(); this.dbPopulationMode = mode; + this.stateProperty().addListener(observable -> onStateChange.accept(getState())); } void restartProgressHandle(String title, String message, Double workDone, double total, Boolean cancellable) { From 767a169d77a2a90cd6ea3006636f47c6612e90d4 Mon Sep 17 00:00:00 2001 From: jmillman Date: Thu, 24 Mar 2016 15:56:14 -0400 Subject: [PATCH 64/77] cleanup PromptDialogManager, EventsRepository and TimeLineController --- .../autopsy/timeline/PromptDialogManager.java | 32 +++++++++--------- .../autopsy/timeline/TimeLineController.java | 15 +++++---- .../autopsy/timeline/db/EventsRepository.java | 33 +++++++++++++++++-- 3 files changed, 56 insertions(+), 24 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/PromptDialogManager.java b/Core/src/org/sleuthkit/autopsy/timeline/PromptDialogManager.java index 6f58bade53..893ff1dec4 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/PromptDialogManager.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/PromptDialogManager.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2015-16 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -61,9 +61,9 @@ public class PromptDialogManager { static { Image x = null; try { - x = new Image(new URL("nbresloc:/org/netbeans/core/startup/frame.gif").openStream()); //NOI18N + x = new Image(new URL("nbresloc:/org/netbeans/core/startup/frame.gif").openStream()); //NON-NLS } catch (IOException ex) { - LOGGER.log(Level.WARNING, "Failed to load branded icon for progress dialog.", ex); //NOI18N NON-NLS + LOGGER.log(Level.WARNING, "Failed to load branded icon for progress dialog.", ex); //NON-NLS } LOGO = x; } @@ -75,6 +75,12 @@ public class PromptDialogManager { this.controller = controller; } + /** + * bring the currently managed dialog (if there is one) to the front + * + * @return true if a dialog was brought to the front, or false of there is + * no currently managed open dialog + */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) boolean bringCurrentDialogToFront() { if (currentDialog != null && currentDialog.isShowing()) { @@ -86,12 +92,12 @@ public class PromptDialogManager { @NbBundle.Messages({"PromptDialogManager.progressDialog.title=Populating Timeline Data"}) @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - public void showProgressDialog(CancellationProgressTask task) { + void showProgressDialog(CancellationProgressTask task) { currentDialog = new ProgressDialog(task); currentDialog.initModality(Modality.NONE); - currentDialog.headerTextProperty().bind(task.titleProperty()); - setDialogIcons(currentDialog); currentDialog.setTitle(Bundle.PromptDialogManager_progressDialog_title()); + setDialogIcons(currentDialog); + currentDialog.headerTextProperty().bind(task.titleProperty()); DialogPane dialogPane = currentDialog.getDialogPane(); dialogPane.setPrefSize(400, 200); //override autosizing which fails for some reason @@ -100,6 +106,7 @@ public class PromptDialogManager { task.setOnCancelled(cancelled -> currentDialog.close()); task.setOnSucceeded(succeeded -> currentDialog.close()); task.setOnFailed(failed -> currentDialog.close()); + dialogPane.getButtonTypes().setAll(ButtonType.CANCEL); final Node cancelButton = dialogPane.lookupButton(ButtonType.CANCEL); cancelButton.disableProperty().bind(task.cancellableProperty().not()); @@ -117,14 +124,7 @@ public class PromptDialogManager { @ThreadConfined(type = ThreadConfined.ThreadType.JFX) static private void setDialogIcons(Dialog dialog) { - Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow(); - stage.getIcons().setAll(LOGO); - } - - @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - static private void setDialogTitle(Dialog dialog) { - Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow(); - stage.setTitle(Bundle.Timeline_confirmation_dialogs_title()); + ((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().setAll(LOGO); } /** @@ -141,7 +141,7 @@ public class PromptDialogManager { currentDialog.initModality(Modality.APPLICATION_MODAL); currentDialog.setHeaderText(Bundle.PromptDialogManager_confirmDuringIngest_headerText()); setDialogIcons(currentDialog); - setDialogTitle(currentDialog); + currentDialog.setTitle(Bundle.Timeline_confirmation_dialogs_title()); return currentDialog.showAndWait().map(SHOW_TIMELINE::equals).orElse(false); } @@ -154,7 +154,7 @@ public class PromptDialogManager { currentDialog.initModality(Modality.APPLICATION_MODAL); currentDialog.setHeaderText(Bundle.PromptDialogManager_rebuildPrompt_headerText()); setDialogIcons(currentDialog); - setDialogTitle(currentDialog); + currentDialog.setTitle(Bundle.Timeline_confirmation_dialogs_title()); DialogPane dialogPane = currentDialog.getDialogPane(); ListView listView = new ListView<>(FXCollections.observableArrayList(rebuildReasons)); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index 4a925800bf..c77ba8ee75 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -290,6 +290,14 @@ public class TimeLineController { advance(filteredEvents.zoomParametersProperty().get().withTimeRange(boundingEventsInterval)); } + /** + * rebuild the repo using the given repo builder (expected to be a member + * reference to {@link EventsRepository#rebuildRepository(java.util.function.Consumer) + * } or {@link EventsRepository#rebuildTags(java.util.function.Consumer) }) + * and display the ui when it is done. + * + * @param repoBuilder + */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) private void rebuildRepoHelper(Function, CancellationProgressTask> repoBuilder) { SwingUtilities.invokeLater(this::closeTimelineWindow); @@ -314,11 +322,7 @@ public class TimeLineController { } /** - * rebuld the repo. - * - * @return False if the repo was not rebuilt because because the user - * aborted after prompt about ingest running. True if the repo was - * rebuilt. + * rebuld the entire repo. */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) void rebuildRepo() { @@ -329,7 +333,6 @@ public class TimeLineController { * Since tags might have changed while TimeLine wasn't listening, drop the * tags table and rebuild it by querying for all the tags and inserting them * in to the TimeLine DB. - * */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) void rebuildTagsTable() { diff --git a/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java b/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java index bc490faed4..0583b0c175 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/db/EventsRepository.java @@ -320,19 +320,48 @@ public class EventsRepository { return dbWorker.isRunning(); } + /** + * + * rebuild the entire repo. + * + * @param onStateChange called when he background task changes state. + * Clients can use this to handle failure, or cleanup + * operations for example. + * + * @return the task that will rebuild the repo in a background thread. The + * task has already been started. + */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) public CancellationProgressTask rebuildRepository(Consumer onStateChange) { return rebuildRepository(DBPopulationMode.FULL, onStateChange); } + /** + * + * drop and rebuild the tags in the repo. + * + * @param onStateChange called when he background task changes state. + * Clients can use this to handle failure, or cleanup + * operations for example. + * + * @return the task that will rebuild the repo in a background thread. The + * task has already been started. + */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) public CancellationProgressTask rebuildTags(Consumer onStateChange) { return rebuildRepository(DBPopulationMode.TAGS_ONLY, onStateChange); } /** + * rebuild the repo. * - * @param mode the value of mode + * @param mode the rebuild mode to use. + * @param onStateChange called when he background task changes state. + * Clients can use this to handle failure, or cleanup + * operations for example. + * + * @return the task that will rebuild the repo in a background thread. The + * task has already been started. */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) private CancellationProgressTask rebuildRepository(final DBPopulationMode mode, Consumer onStateChange) { @@ -409,7 +438,7 @@ public class EventsRepository { skCase = autoCase.getSleuthkitCase(); tagsManager = autoCase.getServices().getTagsManager(); this.dbPopulationMode = mode; - this.stateProperty().addListener(observable -> onStateChange.accept(getState())); + this.stateProperty().addListener(stateObservable -> onStateChange.accept(getState())); } void restartProgressHandle(String title, String message, Double workDone, double total, Boolean cancellable) { From 1807570dec80fc56a6a33e625c5dc606ca768fcc Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Fri, 25 Mar 2016 10:54:29 -0400 Subject: [PATCH 65/77] Got rid of save button in file extension mismatch. --- .../modules/fileextmismatch/Bundle.properties | 1 - .../fileextmismatch/Bundle_ja.properties | 1 - .../FileExtMismatchSettingsPanel.form | 27 ++---------- .../FileExtMismatchSettingsPanel.java | 44 +++---------------- 4 files changed, 10 insertions(+), 63 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties index c85ead90b1..1b8dd3acc7 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties @@ -43,7 +43,6 @@ FileExtMismatchSettingsPanel.mimeRemoveErrLabel.text=\ FileExtMismatchSettingsPanel.extRemoveErrLabel.text=\ FileExtMismatchSettingsPanel.mimeErrLabel.text=\ FileExtMismatchSettingsPanel.removeTypeButton.text=Remove Selected Type -FileExtMismatchSettingsPanel.saveButton.text=Save Configuration FileExtMismatchSettingsPanel.jLabel1.text=File Types: FileExtMismatchSettingsPanel.userExtTextField.text= FileExtMismatchSettingsPanel.addExtButton.text=Add Extension diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle_ja.properties index 82aa0220c3..9679198eaf 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle_ja.properties @@ -38,7 +38,6 @@ FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text=\u62e1\u5f35\u5b50\u30 FileExtMismatchSettingsPanel.addTypeButton.text=\u30bf\u30a4\u30d7\u3092\u8ffd\u52a0 FileExtMismatchSettingsPanel.extHeaderLabel.text=\u8a31\u53ef\u3059\u308b\u62e1\u5f35\u5b50\uff1a FileExtMismatchSettingsPanel.removeTypeButton.text=\u9078\u629e\u3057\u305f\u30bf\u30a4\u30d7\u3092\u524a\u9664 -FileExtMismatchSettingsPanel.saveButton.text=\u8a2d\u5b9a\u3092\u4fdd\u5b58 FileExtMismatchSettingsPanel.jLabel1.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\uff1a FileExtMismatchSettingsPanel.addExtButton.text=\u62e1\u5f35\u5b50\u3092\u8ffd\u52a0 FileExtMismatchSettingsPanel.removeExtButton.text=\u9078\u629e\u3057\u305f\u62e1\u5f35\u5b50\u3092\u524a\u9664 diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.form index 397f707b31..3b5f5d7758 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.form @@ -46,13 +46,10 @@ - + - - - - + @@ -63,9 +60,7 @@ - - - + @@ -74,20 +69,6 @@
- - - - - - - - - - - - - - @@ -146,7 +127,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java index 1de79557bc..56883ef119 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java @@ -69,7 +69,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel customizeComponents(); } - @NbBundle.Messages({"FileExtMismatchSettingsPanel.Title=Global File Extension Mismatch Identification Settings"}) + @NbBundle.Messages({"FileExtMismatchSettingsPanel.Title=Global File Extension Mismatch Identification Settings"}) private void customizeComponents() { setName(Bundle.FileExtMismatchSettingsPanel_Title()); @@ -143,7 +143,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel jScrollPane1 = new javax.swing.JScrollPane(); jPanel1 = new javax.swing.JPanel(); - saveButton = new javax.swing.JButton(); jSplitPane1 = new javax.swing.JSplitPane(); mimePanel = new javax.swing.JPanel(); jLabel1 = new javax.swing.JLabel(); @@ -167,15 +166,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel jPanel1.setPreferredSize(new java.awt.Dimension(687, 450)); - saveButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/fileextmismatch/save16.png"))); // NOI18N NON-NLS - saveButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.saveButton.text")); // NOI18N - saveButton.setEnabled(false); - saveButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - saveButtonActionPerformed(evt); - } - }); - jSplitPane1.setDividerLocation(430); jLabel1.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.jLabel1.text")); // NOI18N @@ -247,7 +237,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel .addComponent(removeTypeButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(mimeRemoveErrLabel) - .addContainerGap(47, Short.MAX_VALUE)) + .addContainerGap(83, Short.MAX_VALUE)) ); jSplitPane1.setLeftComponent(mimePanel); @@ -336,21 +326,17 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 667, Short.MAX_VALUE) + .addComponent(jSplitPane1) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(saveButton, javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(saveMsgLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addComponent(saveMsgLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap()) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() - .addComponent(jSplitPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(saveButton) + .addComponent(jSplitPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 466, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(saveMsgLabel) .addContainerGap()) @@ -416,10 +402,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel setIsModified(); }//GEN-LAST:event_addExtButtonActionPerformed - private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed - store(); - }//GEN-LAST:event_saveButtonActionPerformed - private void addTypeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addTypeButtonActionPerformed String newMime = userTypeTextField.getText(); if (newMime.isEmpty()) { @@ -555,7 +537,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel extErrorLabel.setText(" "); saveMsgLabel.setText(NbBundle.getMessage(this.getClass(), "FileExtMismatchConfigPanel.store.msg")); - saveButton.setEnabled(false); } else { //error JOptionPane.showMessageDialog(this, @@ -582,7 +563,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel } private void setIsModified() { - saveButton.setEnabled(true); saveMsgLabel.setText(" "); } @@ -592,18 +572,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel } public void ok() { - // if data is unsaved - if (saveButton.isEnabled()) { - int choice = JOptionPane.showConfirmDialog(this, - NbBundle.getMessage(this.getClass(), - "FileExtMismatchConfigPanel.ok.confDlg.msg"), - NbBundle.getMessage(this.getClass(), - "FileExtMismatchConfigPanel.confDlg.title"), - JOptionPane.YES_NO_OPTION); - if (choice == JOptionPane.YES_OPTION) { - store(); - } - } + store(); clearErrLabels(); load(); // The next time this panel is opened, we want it to be fresh } @@ -631,7 +600,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel private javax.swing.JTable mimeTable; private javax.swing.JButton removeExtButton; private javax.swing.JButton removeTypeButton; - private javax.swing.JButton saveButton; private javax.swing.JLabel saveMsgLabel; private javax.swing.JTextField userExtTextField; private javax.swing.JTextField userTypeTextField; From 50977ca21941b2fcb0171ce486855a06413e728b Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Sun, 27 Mar 2016 13:12:42 -0400 Subject: [PATCH 66/77] Update datamodel/ArtifactStringContent for BlackboardAttribute.getContext deprecation --- .../org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java index db8607cd93..fa59de87c1 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2013 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -50,6 +50,7 @@ public class ArtifactStringContent implements StringContent { } @Override + @SuppressWarnings("deprecation") public String getString() { if (stringContent.isEmpty()) { try { From 4cb80c2dc2d50867387f0e62988c41aa386e0324 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Sun, 27 Mar 2016 14:04:11 -0400 Subject: [PATCH 67/77] Clean up some of the doxygen warnings for class javadocs --- .../actions/GetTagNameAndCommentDialog.java | 10 ++++---- .../sleuthkit/autopsy/casemodule/Case.java | 14 +++++------ .../casemodule/LocalDiskDSProcessor.java | 4 ++-- .../casemodule/OpenRecentCasePanel.java | 18 --------------- .../casemodule/services/FileManager.java | 4 +++- .../corecomponents/DataContentViewerHex.java | 4 ++-- .../MultiUserSettingsPanel.java | 22 ++++++++++++++---- .../sleuthkit/autopsy/coreutils/ExecUtil.java | 8 +------ .../autopsy/coreutils/ImageUtils.java | 11 +++++---- .../autopsy/coreutils/JLnkParser.java | 16 ++++++------- .../autopsy/coreutils/UNCPathUtilities.java | 23 +++++++++++-------- .../ExternalResultsXMLParser.java | 3 ++- ...taSourceIngestModuleProcessTerminator.java | 5 +--- .../ingest/DataSourceIngestPipeline.java | 8 +------ .../FileIngestModuleProcessTerminator.java | 5 +--- .../autopsy/ingest/IngestMessage.java | 7 +----- .../autopsy/ingest/IngestModuleFactory.java | 2 +- .../ingest/IngestModuleFactoryAdapter.java | 2 +- .../ingest/events/ContentChangedEvent.java | 6 ++--- 19 files changed, 74 insertions(+), 98 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java index 5f69fc8a7f..eb4dbbab6b 100644 --- a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java +++ b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,6 +40,7 @@ import org.sleuthkit.datamodel.TskCoreException; public class GetTagNameAndCommentDialog extends JDialog { + private static final long serialVersionUID = 1L; private static final String NO_TAG_NAMES_MESSAGE = NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.noTags"); private final HashMap tagNames = new HashMap<>(); @@ -47,8 +48,8 @@ public class GetTagNameAndCommentDialog extends JDialog { public static class TagNameAndComment { - private TagName tagName; - private String comment; + private final TagName tagName; + private final String comment; private TagNameAndComment(TagName tagName, String comment) { this.tagName = tagName; @@ -67,8 +68,7 @@ public class GetTagNameAndCommentDialog extends JDialog { /** * Show the Tag Name and Comment Dialog and return the TagNameAndContent * chosen by the user. The dialog will be centered with the main autopsy - * window as its owner. To set another window as the owner use {@link #doDialog(java.awt.Window) - * } + * window as its owner. * * @return a TagNameAndComment instance containing the TagName selected by * the user and the entered comment, or null if the user canceled diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 6615cde7e6..29567cbf5f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2015 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -714,16 +714,14 @@ public class Case implements SleuthkitCase.ErrorObserver { } /** - * Adds the image to the current case after it has been added to the DB. + * Adds an image to the current case after it has been added to the DB. * Sends out event and reopens windows if needed. * - * @param imgPaths the paths of the image that being added - * @param imgId the ID of the image that being added - * @param timeZone the timeZone of the image where it's added + * @param imgPath The path of the image file. + * @param imgId The ID of the image. + * @param timeZone The time zone of the image. * - * @deprecated As of release 4.0, replaced by {@link #notifyAddingDataSource(java.util.UUID) and - * {@link #notifyDataSourceAdded(org.sleuthkit.datamodel.Content, java.util.UUID) and - * {@link #notifyFailedAddingDataSource(java.util.UUID)} + * @deprecated As of release 4.0 */ @Deprecated public Image addImage(String imgPath, long imgId, String timeZone) throws CaseActionException { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java index c699eb740d..977c7ef6b0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java @@ -190,9 +190,9 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { * Sets the configuration of the data source processor without using the * configuration panel. * - * @param imagePath Path to the image file. + * @param drivePath Path to the local drive. * @param timeZone The time zone to use when processing dates - * and times for the image, obtained from + * and times for the local drive, obtained from * java.util.TimeZone.getID. * @param ignoreFatOrphanFiles Whether to parse orphans if the image has a * FAT filesystem. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/OpenRecentCasePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/OpenRecentCasePanel.java index 07706cc798..f7035effbb 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/OpenRecentCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/OpenRecentCasePanel.java @@ -156,9 +156,6 @@ class OpenRecentCasePanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; - /** - * @inheritDoc - */ @Override public int getRowCount() { int count = 0; @@ -170,17 +167,11 @@ class OpenRecentCasePanel extends javax.swing.JPanel { return count; } - /** - * @inheritDoc - */ @Override public int getColumnCount() { return 2; } - /** - * @inheritDoc - */ @Override public String getColumnName(int column) { String colName = null; @@ -197,9 +188,6 @@ class OpenRecentCasePanel extends javax.swing.JPanel { return colName; } - /** - * @inheritDoc - */ @Override public Object getValueAt(int rowIndex, int columnIndex) { Object ret = null; @@ -217,17 +205,11 @@ class OpenRecentCasePanel extends javax.swing.JPanel { return ret; } - /** - * @inheritDoc - */ @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return false; } - /** - * @inheritDoc - */ @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java index 4d540fa5cb..5b958cd5a7 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2012 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * * Copyright 2012 42six Solutions. * Contact: aebadirad 42six com @@ -512,6 +512,7 @@ public class FileManager implements Closeable { * Helper (internal) method to recursively add contents of a folder. Node * passed in can be a file or directory. Children of directories are added. * + * @param trans A case database transaction. * @param parentVd Dir that is the parent of localFile * @param localFile File/Dir that we are adding * @param addProgressUpdater notifier to receive progress notifications on @@ -569,6 +570,7 @@ public class FileManager implements Closeable { * @param parentFile parent file object container (such as virtual * directory, another local file, or fscontent File), * @param localFile File that we are adding + * @param trans A case database transaction. * * @return newly created local file object added to the database * diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java index 512cf6393c..917eaf404b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2013 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -385,7 +385,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont /** * Sets the DataView (The tabbed panel) by offset * - * @param page Page to display (1-based counting) + * @param offset Page to display (1-based counting) */ private void setDataViewByOffset(long offset) { if (this.dataSource == null) { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java index 8b4af64dc3..6ebaa4293f 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java @@ -1,7 +1,20 @@ /* - * 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 2013-2016 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.corecomponents; @@ -467,7 +480,8 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { /** * Enables/disables the multi-user settings, based upon input provided * - * @param enabled true means enable, false means disable + * @param textFields The text fields to enable/disable. + * @param enabled True means enable, false means disable. */ private static void enableMultiUserComponents(Collection textFields, boolean enabled) { for (JTextField textField : textFields) { diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java index b0a04d0d56..0507e55cd6 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -96,9 +96,6 @@ public final class ExecUtil { this.startTimeInSeconds = (new Date().getTime()) / 1000; } - /** - * @inheritDoc - */ @Override public boolean shouldTerminateProcess() { long currentTimeInSeconds = (new Date().getTime()) / 1000; @@ -120,9 +117,6 @@ public final class ExecUtil { */ public static int execute(ProcessBuilder processBuilder) throws SecurityException, IOException { return ExecUtil.execute(processBuilder, 30, TimeUnit.DAYS, new ProcessTerminator() { - /** - * @inheritDoc - */ @Override public boolean shouldTerminateProcess() { return false; diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java index 057c39cade..f4f1e99ab3 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java @@ -147,8 +147,8 @@ public class ImageUtils { /** * thread that saves generated thumbnails to disk in the background */ - private static final Executor imageSaver = - Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder() + private static final Executor imageSaver + = Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder() .namingPattern("thumbnail-saver-%d").build()); //NON-NLS public static List getSupportedImageExtensions() { @@ -467,7 +467,7 @@ public class ImageUtils { /** * Private template method designed to be used as the implementation of * public methods that pull particular (usually meta-)data out of a image - * file. ./** + * file. * * @param the type of the property to be retrieved. * @param file the file to extract the data from @@ -528,8 +528,9 @@ public class ImageUtils { * but is not started automatically. Clients are responsible for running the * task, monitoring its progress, and using its result. * - * @param file the file to create a thumbnail for - * @param iconSize the size of the thumbnail + * @param file The file to create a thumbnail for. + * @param iconSize The size of the thumbnail. + * @param defaultOnFailure Whether or not to default on failure. * * @return a new Task that returns a thumbnail as its result. */ diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/JLnkParser.java b/Core/src/org/sleuthkit/autopsy/coreutils/JLnkParser.java index 7cef330e6e..f371bee622 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/JLnkParser.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/JLnkParser.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,14 +25,12 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; -import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.LnkEnums.CommonCLSIDS; import org.sleuthkit.autopsy.coreutils.LnkEnums.DriveType; import org.sleuthkit.autopsy.coreutils.LnkEnums.NetworkProviderType; /** - * - * @author dfickling Parse lnk files using documentation from + * Parse lnk files using documentation from: * http://msdn.microsoft.com/en-us/library/dd871305(v=prot.13).aspx * http://msdn.microsoft.com/en-us/library/windows/desktop/cc144090(v=vs.85).aspx#unknown_74413 * http://blog.0x01000000.org/2010/08/10/lnk-parsing-youre-doing-it-wrong-i/ @@ -67,12 +65,12 @@ public class JLnkParser { int showCommand = bb.getInt(); short hotkey = bb.getShort(); bb.get(new byte[10]); // reserved (???) - List linkTargetIdList = new ArrayList(); + List linkTargetIdList = new ArrayList<>(); if ((linkFlags & LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) == LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) { int idListSize = bb.getShort(); int bytesRead = 0; - List linkTargetIdListBytes = new ArrayList(); + List linkTargetIdListBytes = new ArrayList<>(); while (true) { short itemIdSize = bb.getShort(); if (itemIdSize == 0) { @@ -82,7 +80,7 @@ public class JLnkParser { byte[] theArray = new byte[itemIdSize - 2]; bb.get(theArray); // an idlist data object linkTargetIdListBytes.add(theArray); - bytesRead = bytesRead + itemIdSize; + bytesRead += itemIdSize; } linkTargetIdList = parseLinkTargetIdList(linkTargetIdListBytes); } @@ -272,7 +270,7 @@ public class JLnkParser { } private List parseLinkTargetIdList(List idList) { - List ret = new ArrayList(); + List ret = new ArrayList<>(); if (!idList.isEmpty()) { CommonCLSIDS clsid = CommonCLSIDS.valueOf(Arrays.copyOfRange(idList.remove(0), 2, 18)); switch (clsid) { @@ -295,7 +293,7 @@ public class JLnkParser { } private List parsePathElements(List idList) { - List ret = new ArrayList(); + List ret = new ArrayList<>(); for (byte[] pathElement : idList) { ByteBuffer bb = ByteBuffer.wrap(pathElement); bb.order(ByteOrder.LITTLE_ENDIAN); diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java b/Core/src/org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java index e9ce8a7d95..2d16c51cbb 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -60,7 +60,8 @@ public class UNCPathUtilities { /** * This method converts a passed in path to UNC if it is not already UNC. * The UNC path will end up in one of the following two forms: - * \\hostname\somefolder\otherfolder or \\IP_ADDRESS\somefolder\otherfolder + * "\\hostname\somefolder\otherfolder" or + * "\\IP_ADDRESS\somefolder\otherfolder" * * This is accomplished by checking the mapped drives list the operating * system maintains and substituting where required. If the drive of the @@ -167,9 +168,10 @@ public class UNCPathUtilities { /** * Takes a UNC path that may have an IP address in it and converts it to * hostname, if it can resolve the hostname. Given - * \\10.11.12.13\some\folder, the result will be \\TEDS_COMPUTER\some\folder - * if the IP address 10.11.12.13 belongs to a machine with the hostname - * TEDS_COMPUTER and the local machine is able to resolve the hostname. + * "\\10.11.12.13\some\folder", the result will be + * "\\TEDS_COMPUTER\some\folder" if the IP address 10.11.12.13 belongs to a + * machine with the hostname TEDS_COMPUTER and the local machine is able to + * resolve the hostname. * * @param inputPath the path to convert to a hostname UNC path * @@ -186,9 +188,10 @@ public class UNCPathUtilities { /** * Takes a UNC path that may have an IP address in it and converts it to * hostname, if it can resolve the hostname. Given - * \\10.11.12.13\some\folder, the result will be \\TEDS_COMPUTER\some\folder - * if the IP address 10.11.12.13 belongs to a machine with the hostname - * TEDS_COMPUTER and the local machine is able to resolve the hostname. + * "\\10.11.12.13\some\folder", the result will be + * "\\TEDS_COMPUTER\some\folder" if the IP address 10.11.12.13 belongs to a + * machine with the hostname TEDS_COMPUTER and the local machine is able to + * resolve the hostname. * * @param inputPath a String of the path to convert to a hostname UNC path * @@ -263,11 +266,11 @@ public class UNCPathUtilities { */ synchronized private Map getMappedDrives() { Map driveMap = new HashMap<>(); - + if (PlatformUtil.isWindowsOS() == false) { return driveMap; } - + File mappedDrive = Paths.get(System.getenv(TEMP_FOLDER), nameString + MAPPED_DRIVES).toFile(); try { Files.deleteIfExists(mappedDrive.toPath()); diff --git a/Core/src/org/sleuthkit/autopsy/externalresults/ExternalResultsXMLParser.java b/Core/src/org/sleuthkit/autopsy/externalresults/ExternalResultsXMLParser.java index 8443e6b71a..0c33e87ca7 100644 --- a/Core/src/org/sleuthkit/autopsy/externalresults/ExternalResultsXMLParser.java +++ b/Core/src/org/sleuthkit/autopsy/externalresults/ExternalResultsXMLParser.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -117,6 +117,7 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser { /** * Constructor. * + * @param dataSource The data source for the results. * @param resultsFilePath Full path of the results file to be parsed. */ public ExternalResultsXMLParser(Content dataSource, String resultsFilePath) { diff --git a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestModuleProcessTerminator.java b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestModuleProcessTerminator.java index 59b5af0730..eacb918d92 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestModuleProcessTerminator.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestModuleProcessTerminator.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -69,9 +69,6 @@ public final class DataSourceIngestModuleProcessTerminator implements ProcessTer } } - /** - * @inheritDoc - */ @Override public boolean shouldTerminateProcess() { diff --git a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java index 4c27c201d5..363af546de 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014-2015 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -195,17 +195,11 @@ final class DataSourceIngestPipeline { return this.processingStartTime; } - /** - * @inheritDoc - */ @Override public void startUp(IngestJobContext context) throws IngestModuleException { this.module.startUp(context); } - /** - * @inheritDoc - */ @Override public IngestModule.ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) { this.processingStartTime = new Date(); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/FileIngestModuleProcessTerminator.java b/Core/src/org/sleuthkit/autopsy/ingest/FileIngestModuleProcessTerminator.java index 7f0ac84240..ad06ff65fd 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/FileIngestModuleProcessTerminator.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/FileIngestModuleProcessTerminator.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -68,9 +68,6 @@ public final class FileIngestModuleProcessTerminator implements ProcessTerminato } } - /** - * @inheritDoc - */ @Override public boolean shouldTerminateProcess() { diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestMessage.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestMessage.java index bdde998aad..5819a2f424 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestMessage.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestMessage.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -168,12 +168,9 @@ public class IngestMessage { return hash; } - //factory methods /** * Create a message of specified type * - * @param ID ID of the message, unique in the context of module - * that generated it * @param messageType message type * @param source originating module * @param subject message subject to be displayed @@ -210,8 +207,6 @@ public class IngestMessage { /** * Create error message * - * @param ID ID of the message, unique in the context of module - * that generated it * @param source originating module * @param subject message subject to be displayed * @param detailsHtml html formatted detailed message (without leading and diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactory.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactory.java index de99a445ab..470d728558 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactory.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 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/ingest/IngestModuleFactoryAdapter.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactoryAdapter.java index 2c4831bb01..14beecd05d 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactoryAdapter.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactoryAdapter.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 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/ingest/events/ContentChangedEvent.java b/Core/src/org/sleuthkit/autopsy/ingest/events/ContentChangedEvent.java index 7370d90586..0f7dcdc0dc 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/events/ContentChangedEvent.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/events/ContentChangedEvent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -45,8 +45,8 @@ public final class ContentChangedEvent extends AutopsyEvent implements Serializa * Constructs a event to be published when new content is added to a case or * there is a change a recorded attribute of existing content. * - * @param contentEvent A ModuleContentEvent object containing the data - * associated with the content addition or change. + * @param eventData A ModuleContentEvent object containing the data + * associated with the content addition or change. */ public ContentChangedEvent(ModuleContentEvent eventData) { /** From 2179987dadf256f5bd5d436b42305653c2a553c6 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Sun, 27 Mar 2016 16:05:46 -0400 Subject: [PATCH 68/77] Change build.type to RELEASE fro 4.1.0 --- nbproject/project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nbproject/project.properties b/nbproject/project.properties index 8d6bea269f..82d17bcb95 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -7,7 +7,7 @@ app.name=${branding.token} app.version=4.1.0 ### build.type must be one of: DEVELOPMENT, RELEASE #build.type=RELEASE -build.type=DEVELOPMENT +build.type=RELEASE project.org.sleuthkit.autopsy.imagegallery=ImageGallery update_versions=false From 6d4c8a9c45583280cac60b0518d94f8fc70942bc Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Sun, 27 Mar 2016 16:07:40 -0400 Subject: [PATCH 69/77] Add missing versioning values for CoreLibs and ScalpelCarver NBMs --- CoreLibs/manifest.mf | 1 + ScalpelCarver/manifest.mf | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CoreLibs/manifest.mf b/CoreLibs/manifest.mf index bba0e51547..d62dccceb4 100644 --- a/CoreLibs/manifest.mf +++ b/CoreLibs/manifest.mf @@ -1,5 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.corelibs/3 +OpenIDE-Module-Implementation-Version: 3 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/corelibs/Bundle.properties OpenIDE-Module-Specification-Version: 1.1 AutoUpdate-Show-In-Client: true diff --git a/ScalpelCarver/manifest.mf b/ScalpelCarver/manifest.mf index 8fb11a1cc4..53be511223 100644 --- a/ScalpelCarver/manifest.mf +++ b/ScalpelCarver/manifest.mf @@ -1,4 +1,5 @@ Manifest-Version: 1.0 -OpenIDE-Module: org.sleuthkit.autopsy.scalpel +OpenIDE-Module: org.sleuthkit.autopsy.scalpel/1 +OpenIDE-Module-Implementation-Version: 1 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/scalpel/Bundle.properties OpenIDE-Module-Specification-Version: 1.0 From 3c7c30c0329bb6ecb02283c675ef2b9d68c194b5 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Sun, 27 Mar 2016 16:23:33 -0400 Subject: [PATCH 70/77] Update NBM versioning for release 4.1.0 --- Core/manifest.mf | 2 +- Core/nbproject/project.properties | 2 +- Core/nbproject/project.xml | 2 +- CoreLibs/manifest.mf | 2 +- ImageGallery/manifest.mf | 4 ++-- ImageGallery/nbproject/project.properties | 2 +- ImageGallery/nbproject/project.xml | 8 ++++---- KeywordSearch/manifest.mf | 2 +- KeywordSearch/nbproject/project.xml | 4 ++-- RecentActivity/manifest.mf | 2 +- RecentActivity/nbproject/project.xml | 4 ++-- ScalpelCarver/manifest.mf | 2 +- ScalpelCarver/nbproject/project.xml | 4 ++-- Testing/manifest.mf | 2 +- Testing/nbproject/project.xml | 8 ++++---- thunderbirdparser/manifest.mf | 2 +- thunderbirdparser/nbproject/project.xml | 8 ++++---- 17 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Core/manifest.mf b/Core/manifest.mf index cc13c3055d..fef8f5793b 100644 --- a/Core/manifest.mf +++ b/Core/manifest.mf @@ -2,7 +2,7 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.core/10 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml -OpenIDE-Module-Implementation-Version: 15 +OpenIDE-Module-Implementation-Version: 16 OpenIDE-Module-Requires: org.openide.windows.WindowManager AutoUpdate-Show-In-Client: true AutoUpdate-Essential-Module: true diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties index add7b7b717..f52a185822 100644 --- a/Core/nbproject/project.properties +++ b/Core/nbproject/project.properties @@ -21,5 +21,5 @@ nbm.homepage=http://www.sleuthkit.org/ nbm.module.author=Brian Carrier nbm.needs.restart=true source.reference.metadata-extractor-2.8.1.jar=release/modules/ext/metadata-extractor-2.8.1-src.zip!/Source/ -spec.version.base=10.4 +spec.version.base=10.5 diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index a2ddc46460..3f1e5f172d 100644 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -177,7 +177,7 @@ 3 - 1.0 + 1.1 diff --git a/CoreLibs/manifest.mf b/CoreLibs/manifest.mf index d62dccceb4..e2386f67ce 100644 --- a/CoreLibs/manifest.mf +++ b/CoreLibs/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.corelibs/3 -OpenIDE-Module-Implementation-Version: 3 +OpenIDE-Module-Implementation-Version: 4 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/corelibs/Bundle.properties OpenIDE-Module-Specification-Version: 1.1 AutoUpdate-Show-In-Client: true diff --git a/ImageGallery/manifest.mf b/ImageGallery/manifest.mf index 25b0a0656d..79c24ee687 100644 --- a/ImageGallery/manifest.mf +++ b/ImageGallery/manifest.mf @@ -1,5 +1,5 @@ Manifest-Version: 1.0 -OpenIDE-Module: org.sleuthkit.autopsy.imagegallery/1 -OpenIDE-Module-Implementation-Version: 1 +OpenIDE-Module: org.sleuthkit.autopsy.imagegallery/2 +OpenIDE-Module-Implementation-Version: 2 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/imagegallery/Bundle.properties diff --git a/ImageGallery/nbproject/project.properties b/ImageGallery/nbproject/project.properties index f61ae8d42a..e400c96aab 100644 --- a/ImageGallery/nbproject/project.properties +++ b/ImageGallery/nbproject/project.properties @@ -5,4 +5,4 @@ license.file=LICENSE-2.0.txt nbm.homepage=http://www.sleuthkit.org/ nbm.needs.restart=true project.license=imagegallery -spec.version.base=1.0 +spec.version.base=2.0 diff --git a/ImageGallery/nbproject/project.xml b/ImageGallery/nbproject/project.xml index 2a28ce3deb..5af1b0c374 100644 --- a/ImageGallery/nbproject/project.xml +++ b/ImageGallery/nbproject/project.xml @@ -102,8 +102,8 @@ - 10 - 10.0.11 + 11 + 11.0 @@ -111,8 +111,8 @@ - 3 - 1.1 + 11 + 11.0 diff --git a/KeywordSearch/manifest.mf b/KeywordSearch/manifest.mf index df31f51f32..8d28239264 100644 --- a/KeywordSearch/manifest.mf +++ b/KeywordSearch/manifest.mf @@ -1,7 +1,7 @@ Manifest-Version: 1.0 AutoUpdate-Show-In-Client: true OpenIDE-Module: org.sleuthkit.autopsy.keywordsearch/6 -OpenIDE-Module-Implementation-Version: 15 +OpenIDE-Module-Implementation-Version: 16 OpenIDE-Module-Install: org/sleuthkit/autopsy/keywordsearch/Installer.class OpenIDE-Module-Layer: org/sleuthkit/autopsy/keywordsearch/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/keywordsearch/Bundle.properties diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml index 43b6b9f390..038ceb3b9d 100644 --- a/KeywordSearch/nbproject/project.xml +++ b/KeywordSearch/nbproject/project.xml @@ -94,8 +94,8 @@ - 10 - 10.0 + 11 + 11.0 diff --git a/RecentActivity/manifest.mf b/RecentActivity/manifest.mf index 8b8da4b3b6..3121c6b8ca 100644 --- a/RecentActivity/manifest.mf +++ b/RecentActivity/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.recentactivity/6 -OpenIDE-Module-Implementation-Version: 14 +OpenIDE-Module-Implementation-Version: 15 OpenIDE-Module-Layer: org/sleuthkit/autopsy/recentactivity/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/recentactivity/Bundle.properties OpenIDE-Module-Requires: diff --git a/RecentActivity/nbproject/project.xml b/RecentActivity/nbproject/project.xml index bf7bb93662..1c36b3b394 100644 --- a/RecentActivity/nbproject/project.xml +++ b/RecentActivity/nbproject/project.xml @@ -51,8 +51,8 @@ - 10 - 10.0 + 11 + 11.0 diff --git a/ScalpelCarver/manifest.mf b/ScalpelCarver/manifest.mf index 53be511223..97d1291613 100644 --- a/ScalpelCarver/manifest.mf +++ b/ScalpelCarver/manifest.mf @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.scalpel/1 -OpenIDE-Module-Implementation-Version: 1 +OpenIDE-Module-Implementation-Version: 2 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/scalpel/Bundle.properties OpenIDE-Module-Specification-Version: 1.0 diff --git a/ScalpelCarver/nbproject/project.xml b/ScalpelCarver/nbproject/project.xml index 866c390d45..0affc73b48 100644 --- a/ScalpelCarver/nbproject/project.xml +++ b/ScalpelCarver/nbproject/project.xml @@ -27,8 +27,8 @@ - 10 - 10.0 + 11 + 11.0 diff --git a/Testing/manifest.mf b/Testing/manifest.mf index 7f246db06f..51d75b7ab6 100644 --- a/Testing/manifest.mf +++ b/Testing/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 AutoUpdate-Show-In-Client: false OpenIDE-Module: org.sleuthkit.autopsy.testing/3 -OpenIDE-Module-Implementation-Version: 8 +OpenIDE-Module-Implementation-Version: 9 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/testing/Bundle.properties diff --git a/Testing/nbproject/project.xml b/Testing/nbproject/project.xml index eac0450c0a..758995d590 100644 --- a/Testing/nbproject/project.xml +++ b/Testing/nbproject/project.xml @@ -11,8 +11,8 @@ - 10 - 10.0 + 11 + 11.0 @@ -20,8 +20,8 @@ - 6 - 6.0 + 11 + 6.3 diff --git a/thunderbirdparser/manifest.mf b/thunderbirdparser/manifest.mf index 3e793b1cb0..74d710d518 100644 --- a/thunderbirdparser/manifest.mf +++ b/thunderbirdparser/manifest.mf @@ -1,7 +1,7 @@ Manifest-Version: 1.0 AutoUpdate-Show-In-Client: true OpenIDE-Module: org.sleuthkit.autopsy.thunderbirdparser/4 -OpenIDE-Module-Implementation-Version: 15 +OpenIDE-Module-Implementation-Version: 16 OpenIDE-Module-Layer: org/sleuthkit/autopsy/thunderbirdparser/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/thunderbirdparser/Bundle.properties diff --git a/thunderbirdparser/nbproject/project.xml b/thunderbirdparser/nbproject/project.xml index d28caa4d6f..0c7fdca193 100644 --- a/thunderbirdparser/nbproject/project.xml +++ b/thunderbirdparser/nbproject/project.xml @@ -27,8 +27,8 @@ - 10 - 10.0 + 11 + 11.0 @@ -36,8 +36,8 @@ - 6 - 6.0 + 11 + 6.3 From 8cf3702d4bf1e90e04d6173ace46623e642bc34f Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Sun, 27 Mar 2016 16:39:29 -0400 Subject: [PATCH 71/77] Update inter-NBM dependencies for suite NBMs for release 4.1.0 --- ImageGallery/nbproject/project.xml | 8 ++++---- KeywordSearch/nbproject/project.xml | 4 ++-- RecentActivity/nbproject/project.xml | 4 ++-- Testing/nbproject/project.xml | 6 +++--- thunderbirdparser/nbproject/project.xml | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ImageGallery/nbproject/project.xml b/ImageGallery/nbproject/project.xml index 5af1b0c374..bff28c8d43 100644 --- a/ImageGallery/nbproject/project.xml +++ b/ImageGallery/nbproject/project.xml @@ -102,8 +102,8 @@ - 11 - 11.0 + 10 + 10.5 @@ -111,8 +111,8 @@ - 11 - 11.0 + 3 + 1.1 diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml index 038ceb3b9d..a0c6d6ff4b 100644 --- a/KeywordSearch/nbproject/project.xml +++ b/KeywordSearch/nbproject/project.xml @@ -94,8 +94,8 @@ - 11 - 11.0 + 10 + 10.5 diff --git a/RecentActivity/nbproject/project.xml b/RecentActivity/nbproject/project.xml index 1c36b3b394..28d1cc24f7 100644 --- a/RecentActivity/nbproject/project.xml +++ b/RecentActivity/nbproject/project.xml @@ -51,8 +51,8 @@ - 11 - 11.0 + 10 + 10.5 diff --git a/Testing/nbproject/project.xml b/Testing/nbproject/project.xml index 758995d590..8d39122411 100644 --- a/Testing/nbproject/project.xml +++ b/Testing/nbproject/project.xml @@ -11,8 +11,8 @@ - 11 - 11.0 + 10 + 10.5 @@ -20,7 +20,7 @@ - 11 + 6 6.3 diff --git a/thunderbirdparser/nbproject/project.xml b/thunderbirdparser/nbproject/project.xml index 0c7fdca193..5d0dc34ef4 100644 --- a/thunderbirdparser/nbproject/project.xml +++ b/thunderbirdparser/nbproject/project.xml @@ -27,8 +27,8 @@ - 11 - 11.0 + 10 + 10.5 @@ -36,7 +36,7 @@ - 11 + 6 6.3 From 271bdd961b15e04754ef0921a693fc079272503d Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Sun, 27 Mar 2016 20:34:00 -0400 Subject: [PATCH 72/77] Set build.type back to DEVELOPMENT post release 4.1.0 --- nbproject/project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nbproject/project.properties b/nbproject/project.properties index 82d17bcb95..8d6bea269f 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -7,7 +7,7 @@ app.name=${branding.token} app.version=4.1.0 ### build.type must be one of: DEVELOPMENT, RELEASE #build.type=RELEASE -build.type=RELEASE +build.type=DEVELOPMENT project.org.sleuthkit.autopsy.imagegallery=ImageGallery update_versions=false From 6a1dcc0ee6103f2e3a7eec368f547a4b69ee75bc Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Mon, 28 Mar 2016 16:20:44 -0400 Subject: [PATCH 73/77] Fixed semantics issues in UserDefinedFileTypesManager --- .../UserDefinedFileTypesManager.java | 145 +++++++++--------- 1 file changed, 74 insertions(+), 71 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java index c24354a345..ee712a8d81 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java @@ -5,7 +5,7 @@ * 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 not use this xmlFile except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 @@ -48,25 +48,25 @@ import org.w3c.dom.Node; import org.xml.sax.SAXException; /** - * Manages user-defined file types characterized by MIME type, signature, and + * Manages user-defined xmlFile types characterized by MIME type, signature, and * optional membership in an interesting files set. *

* Note that this class exposes a very simple get/set API that operates on the - * user-defined file types as a complete set - there is no concept of adding, - * editing or deleting file types singly. This works because this class is not - * exposed outside of this ingest module package and is ONLY used in a very - * specific paradigm. In this paradigm, there is a single modal writer of file - * types in the form of a global settings panel that disables itself when ingest - * is running so that multiple readers in the form of file ingest modules get a - * consistent set of file type definitions. + * user-defined xmlFile types as a complete set - there is no concept of adding, + * editing or deleting xmlFile types singly. This works because this class is + * not exposed outside of this ingest module package and is ONLY used in a very + * specific paradigm. In this paradigm, there is a single modal writer of + * xmlFile types in the form of a global settings panel that disables itself + * when ingest is running so that multiple readers in the form of xmlFile ingest + * modules get a consistent set of xmlFile type definitions. *

* Thread-safe. */ final class UserDefinedFileTypesManager { private static final Logger logger = Logger.getLogger(UserDefinedFileTypesManager.class.getName()); - private static final String USER_DEFINED_TYPE_DEFINITIONS_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS - private static final String USER_DEFINED_TYPE_SERIALIZATION_FILE = "UserFileTypeDefinitions.settings"; + private static final String USER_DEFINED_TYPES_XML_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS + private static final String USER_DEFINED_TYPES_SERIALIZATION_FILE = "UserFileTypeDefinitions.settings"; private static final String FILE_TYPES_TAG_NAME = "FileTypes"; //NON-NLS private static final String FILE_TYPE_TAG_NAME = "FileType"; //NON-NLS private static final String MIME_TYPE_TAG_NAME = "MimeType"; //NON-NLS @@ -81,28 +81,28 @@ final class UserDefinedFileTypesManager { private static UserDefinedFileTypesManager instance; /** - * File types to be persisted to the user-defined file type definitions file - * are stored in this mapping of MIME types to file types. Access to this - * map is guarded by the intrinsic lock of the user-defined file types - * manager for thread-safety. + * File types to be persisted to the user-defined xmlFile type definitions + * xmlFile are stored in this mapping of MIME types to xmlFile types. Access + * to this map is guarded by the intrinsic lock of the user-defined xmlFile + * types manager for thread-safety. */ private final List userDefinedFileTypes = new ArrayList<>(); /** - * The combined set of user-defined file types and file types predefined by - * Autopsy are stored in this mapping of MIME types to file types. This is - * the current working set of file types. Access to this map is guarded by - * the intrinsic lock of the user-defined file types manager for - * thread-safety. + * The combined set of user-defined xmlFile types and xmlFile types + * predefined by Autopsy are stored in this mapping of MIME types to xmlFile + * types. This is the current working set of xmlFile types. Access to this + * map is guarded by the intrinsic lock of the user-defined xmlFile types + * manager for thread-safety. */ private final List fileTypes = new ArrayList<>(); /** - * Gets the singleton manager of user-defined file types characterized by + * Gets the singleton manager of user-defined xmlFile types characterized by * MIME type, signature, and optional membership in an interesting files * set. * - * @return The user-defined file types manager singleton. + * @return The user-defined xmlFile types manager singleton. */ synchronized static UserDefinedFileTypesManager getInstance() { if (instance == null) { @@ -112,16 +112,16 @@ final class UserDefinedFileTypesManager { } /** - * Creates a manager of user-defined file types characterized by MIME type, - * signature, and optional membership in an interesting files set. + * Creates a manager of user-defined xmlFile types characterized by MIME + * type, signature, and optional membership in an interesting files set. */ private UserDefinedFileTypesManager() { } /** - * Gets both the predefined and the user-defined file types. + * Gets both the predefined and the user-defined xmlFile types. * - * @return A mapping of file type names to file types, possibly empty. + * @return A mapping of xmlFile type names to xmlFile types, possibly empty. * * @throws * org.sleuthkit.autopsy.modules.filetypeid.UserDefinedFileTypesManager.UserDefinedFileTypesException @@ -139,9 +139,9 @@ final class UserDefinedFileTypesManager { } /** - * Gets the user-defined file types. + * Gets the user-defined xmlFile types. * - * @return A mapping of file type names to file types, possibly empty. + * @return A mapping of xmlFile type names to xmlFile types, possibly empty. * * @throws * org.sleuthkit.autopsy.modules.filetypeid.UserDefinedFileTypesManager.UserDefinedFileTypesException @@ -159,7 +159,7 @@ final class UserDefinedFileTypesManager { } /** - * Loads the MIME type to file type mappings with predefined and + * Loads the MIME type to xmlFile type mappings with predefined and * user-defined types. * * @throws @@ -177,8 +177,8 @@ final class UserDefinedFileTypesManager { } /** - * Adds the predefined file types to the in-memory mappings of MIME types to - * file types. + * Adds the predefined xmlFile types to the in-memory mappings of MIME types + * to xmlFile types. * * @throws * org.sleuthkit.autopsy.modules.filetypeid.UserDefinedFileTypesManager.UserDefinedFileTypesException @@ -253,16 +253,18 @@ final class UserDefinedFileTypesManager { */ private void loadUserDefinedFileTypes() throws UserDefinedFileTypesException { try { - String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE); - File file = new File(filePath); - File serialized = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)); + File serialized = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE)); if (serialized.exists()) { for (FileType fileType : DefinitionsReader.readFileTypesSerialized()) { addUserDefinedFileType(fileType); } - } else if (file.exists() && file.canRead()) { - for (FileType fileType : DefinitionsReader.readFileTypes(filePath)) { - addUserDefinedFileType(fileType); + } else { + String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_XML_FILE); + File xmlFile = new File(filePath); + if (xmlFile.exists()) { + for (FileType fileType : DefinitionsReader.readFileTypes(filePath)) { + addUserDefinedFileType(fileType); + } } } @@ -277,10 +279,10 @@ final class UserDefinedFileTypesManager { } /** - * Adds a user-defined file type to the in-memory mappings of MIME types to - * file types. + * Adds a user-defined xmlFile type to the in-memory mappings of MIME types + * to xmlFile types. * - * @param fileType The file type to add. + * @param fileType The xmlFile type to add. */ private void addUserDefinedFileType(FileType fileType) { userDefinedFileTypes.add(fileType); @@ -288,22 +290,22 @@ final class UserDefinedFileTypesManager { } /** - * Sets the user-defined file types. + * Sets the user-defined xmlFile types. * - * @param newFileTypes A mapping of file type names to user-defined file - * types. + * @param newFileTypes A mapping of xmlFile type names to user-defined + * xmlFile types. */ synchronized void setUserDefinedFileTypes(List newFileTypes) throws UserDefinedFileTypesException { - String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE); + String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_XML_FILE); DefinitionsWriter.writeFileTypes(newFileTypes, filePath); } /** - * Gets the absolute path of a file type definitions file. + * Gets the absolute path of a xmlFile type definitions xmlFile. * - * @param fileName The name of the file. + * @param fileName The name of the xmlFile. * - * @return The absolute path to the file. + * @return The absolute path to the xmlFile. */ private static String getFileTypeDefinitionsFilePath(String fileName) { Path filePath = Paths.get(PlatformUtil.getUserConfigDirectory(), fileName); @@ -311,16 +313,16 @@ final class UserDefinedFileTypesManager { } /** - * Provides a mechanism for writing a set of file type definitions to an XML - * file. + * Provides a mechanism for writing a set of xmlFile type definitions to an + * XML xmlFile. */ private static class DefinitionsWriter { /** - * Writes a set of file type definitions to an XML file. + * Writes a set of xmlFile type definitions to an XML xmlFile. * - * @param fileTypes A collection of file types. - * @param filePath The path to the destination file. + * @param fileTypes A collection of xmlFile types. + * @param filePath The path to the destination xmlFile. * * @throws ParserConfigurationException * @throws IOException @@ -333,7 +335,7 @@ final class UserDefinedFileTypesManager { UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes); out.writeObject(settings); } catch (IOException ex) { - throw new UserDefinedFileTypesException(String.format("Failed to write settings to %s", getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)), ex); + throw new UserDefinedFileTypesException(String.format("Failed to write settings to %s", getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE)), ex); } } @@ -347,17 +349,17 @@ final class UserDefinedFileTypesManager { } /** - * Provides a mechanism for reading a set of file type definitions from an - * XML file. + * Provides a mechanism for reading a set of xmlFile type definitions from + * an XML xmlFile. */ private static class DefinitionsReader { /** - * Reads a set of file type definitions from an XML file. + * Reads a set of xmlFile type definitions from an XML xmlFile. * - * @param filePath The path to the XML file. + * @param filePath The path to the XML xmlFile. * - * @return A collection of file types read from the XML file. + * @return A collection of xmlFile types read from the XML xmlFile. */ private static List readFileTypes(String filePath) throws IOException, SAXException, ParserConfigurationException { List fileTypes = new ArrayList<>(); @@ -387,17 +389,18 @@ final class UserDefinedFileTypesManager { } /** - * Reads the file types + * Reads the xmlFile types * - * @param filePath the file path where the file types are to be read + * @param filePath the xmlFile path where the xmlFile types are to be + * read * - * @return the file types + * @return the xmlFile types * - * @throws ParserConfigurationException If the file cannot be read + * @throws ParserConfigurationException If the xmlFile cannot be read */ private static List readFileTypesSerialized() throws UserDefinedFileTypesException { List fileTypes = new ArrayList<>(); - File serializedDefs = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_SERIALIZATION_FILE)); + File serializedDefs = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE)); if (serializedDefs.exists()) { try { try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) { @@ -412,11 +415,11 @@ final class UserDefinedFileTypesManager { } /** - * Gets a file type definition from a file type XML element. + * Gets a xmlFile type definition from a xmlFile type XML element. * * @param fileTypeElem The XML element. * - * @return A file type object. + * @return A xmlFile type object. * * @throws IllegalArgumentException * @throws NumberFormatException @@ -430,7 +433,7 @@ final class UserDefinedFileTypesManager { } /** - * Gets the MIME type from a file type XML element. + * Gets the MIME type from a xmlFile type XML element. * * @param fileTypeElem The element * @@ -441,7 +444,7 @@ final class UserDefinedFileTypesManager { } /** - * Gets the signature from a file type XML element. + * Gets the signature from a xmlFile type XML element. * * @param fileTypeElem The XML element. * @@ -473,7 +476,7 @@ final class UserDefinedFileTypesManager { } /** - * Gets the interesting files set name from a file type XML element. + * Gets the interesting files set name from a xmlFile type XML element. * * @param fileTypeElem The XML element. * @@ -490,7 +493,7 @@ final class UserDefinedFileTypesManager { } /** - * Gets the alert attribute from a file type XML element. + * Gets the alert attribute from a xmlFile type XML element. * * @param fileTypeElem The XML element. * @@ -533,7 +536,7 @@ final class UserDefinedFileTypesManager { * uniform exception type, and throws the wrapper exception. * * @param ex The exception to wrap. - * @param messageKey A key into the bundle file that maps to the desired + * @param messageKey A key into the bundle xmlFile that maps to the desired * message. * * @throws @@ -548,7 +551,7 @@ final class UserDefinedFileTypesManager { /** * Used to translate more implementation-details-specific exceptions (which * are logged by this class) into more generic exceptions for propagation to - * clients of the user-defined file types manager. + * clients of the user-defined xmlFile types manager. */ static class UserDefinedFileTypesException extends Exception { From 6aac65730cd66f1d51bfdab3206748b42f8168b5 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Tue, 29 Mar 2016 09:08:04 -0400 Subject: [PATCH 74/77] Fixed xmlFile in comments. --- .../UserDefinedFileTypesManager.java | 139 +++++++++--------- 1 file changed, 67 insertions(+), 72 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java index ee712a8d81..d93d53da23 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java @@ -5,7 +5,7 @@ * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this xmlFile except in compliance with 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 @@ -48,17 +48,17 @@ import org.w3c.dom.Node; import org.xml.sax.SAXException; /** - * Manages user-defined xmlFile types characterized by MIME type, signature, and + * Manages user-defined file types characterized by MIME type, signature, and * optional membership in an interesting files set. *

* Note that this class exposes a very simple get/set API that operates on the - * user-defined xmlFile types as a complete set - there is no concept of adding, - * editing or deleting xmlFile types singly. This works because this class is - * not exposed outside of this ingest module package and is ONLY used in a very - * specific paradigm. In this paradigm, there is a single modal writer of - * xmlFile types in the form of a global settings panel that disables itself - * when ingest is running so that multiple readers in the form of xmlFile ingest - * modules get a consistent set of xmlFile type definitions. + * user-defined file types as a complete set - there is no concept of adding, + * editing or deleting file types singly. This works because this class is not + * exposed outside of this ingest module package and is ONLY used in a very + * specific paradigm. In this paradigm, there is a single modal writer of file + * types in the form of a global settings panel that disables itself when ingest + * is running so that multiple readers in the form of file ingest modules get a + * consistent set of file type definitions. *

* Thread-safe. */ @@ -81,28 +81,28 @@ final class UserDefinedFileTypesManager { private static UserDefinedFileTypesManager instance; /** - * File types to be persisted to the user-defined xmlFile type definitions - * xmlFile are stored in this mapping of MIME types to xmlFile types. Access - * to this map is guarded by the intrinsic lock of the user-defined xmlFile - * types manager for thread-safety. + * File types to be persisted to the user-defined file type definitions file + * are stored in this mapping of MIME types to file types. Access to this + * map is guarded by the intrinsic lock of the user-defined file types + * manager for thread-safety. */ private final List userDefinedFileTypes = new ArrayList<>(); /** - * The combined set of user-defined xmlFile types and xmlFile types - * predefined by Autopsy are stored in this mapping of MIME types to xmlFile - * types. This is the current working set of xmlFile types. Access to this - * map is guarded by the intrinsic lock of the user-defined xmlFile types - * manager for thread-safety. + * The combined set of user-defined file types and file types predefined by + * Autopsy are stored in this mapping of MIME types to file types. This is + * the current working set of file types. Access to this map is guarded by + * the intrinsic lock of the user-defined file types manager for + * thread-safety. */ private final List fileTypes = new ArrayList<>(); /** - * Gets the singleton manager of user-defined xmlFile types characterized by + * Gets the singleton manager of user-defined file types characterized by * MIME type, signature, and optional membership in an interesting files * set. * - * @return The user-defined xmlFile types manager singleton. + * @return The user-defined file types manager singleton. */ synchronized static UserDefinedFileTypesManager getInstance() { if (instance == null) { @@ -112,16 +112,16 @@ final class UserDefinedFileTypesManager { } /** - * Creates a manager of user-defined xmlFile types characterized by MIME - * type, signature, and optional membership in an interesting files set. + * Creates a manager of user-defined file types characterized by MIME type, + * signature, and optional membership in an interesting files set. */ private UserDefinedFileTypesManager() { } /** - * Gets both the predefined and the user-defined xmlFile types. + * Gets both the predefined and the user-defined file types. * - * @return A mapping of xmlFile type names to xmlFile types, possibly empty. + * @return A mapping of file type names to file types, possibly empty. * * @throws * org.sleuthkit.autopsy.modules.filetypeid.UserDefinedFileTypesManager.UserDefinedFileTypesException @@ -139,9 +139,9 @@ final class UserDefinedFileTypesManager { } /** - * Gets the user-defined xmlFile types. + * Gets the user-defined file types. * - * @return A mapping of xmlFile type names to xmlFile types, possibly empty. + * @return A mapping of file type names to file types, possibly empty. * * @throws * org.sleuthkit.autopsy.modules.filetypeid.UserDefinedFileTypesManager.UserDefinedFileTypesException @@ -159,7 +159,7 @@ final class UserDefinedFileTypesManager { } /** - * Loads the MIME type to xmlFile type mappings with predefined and + * Loads the MIME type to file type mappings with predefined and * user-defined types. * * @throws @@ -177,8 +177,8 @@ final class UserDefinedFileTypesManager { } /** - * Adds the predefined xmlFile types to the in-memory mappings of MIME types - * to xmlFile types. + * Adds the predefined file types to the in-memory mappings of MIME types to + * file types. * * @throws * org.sleuthkit.autopsy.modules.filetypeid.UserDefinedFileTypesManager.UserDefinedFileTypesException @@ -279,10 +279,10 @@ final class UserDefinedFileTypesManager { } /** - * Adds a user-defined xmlFile type to the in-memory mappings of MIME types - * to xmlFile types. + * Adds a user-defined file type to the in-memory mappings of MIME types to + * file types. * - * @param fileType The xmlFile type to add. + * @param fileType The file type to add. */ private void addUserDefinedFileType(FileType fileType) { userDefinedFileTypes.add(fileType); @@ -290,10 +290,10 @@ final class UserDefinedFileTypesManager { } /** - * Sets the user-defined xmlFile types. + * Sets the user-defined file types. * - * @param newFileTypes A mapping of xmlFile type names to user-defined - * xmlFile types. + * @param newFileTypes A mapping of file type names to user-defined file + * types. */ synchronized void setUserDefinedFileTypes(List newFileTypes) throws UserDefinedFileTypesException { String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_XML_FILE); @@ -301,11 +301,11 @@ final class UserDefinedFileTypesManager { } /** - * Gets the absolute path of a xmlFile type definitions xmlFile. + * Gets the absolute path of a file type definitions file. * - * @param fileName The name of the xmlFile. + * @param fileName The name of the file. * - * @return The absolute path to the xmlFile. + * @return The absolute path to the file. */ private static String getFileTypeDefinitionsFilePath(String fileName) { Path filePath = Paths.get(PlatformUtil.getUserConfigDirectory(), fileName); @@ -313,16 +313,16 @@ final class UserDefinedFileTypesManager { } /** - * Provides a mechanism for writing a set of xmlFile type definitions to an - * XML xmlFile. + * Provides a mechanism for writing a set of file type definitions to an XML + * file. */ private static class DefinitionsWriter { /** - * Writes a set of xmlFile type definitions to an XML xmlFile. + * Writes a set of file type definitions to an XML file. * - * @param fileTypes A collection of xmlFile types. - * @param filePath The path to the destination xmlFile. + * @param fileTypes A collection of file types. + * @param filePath The path to the destination file. * * @throws ParserConfigurationException * @throws IOException @@ -335,7 +335,7 @@ final class UserDefinedFileTypesManager { UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes); out.writeObject(settings); } catch (IOException ex) { - throw new UserDefinedFileTypesException(String.format("Failed to write settings to %s", getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE)), ex); + throw new UserDefinedFileTypesException(String.format("Failed to write settings to %s", filePath), ex); } } @@ -349,17 +349,17 @@ final class UserDefinedFileTypesManager { } /** - * Provides a mechanism for reading a set of xmlFile type definitions from - * an XML xmlFile. + * Provides a mechanism for reading a set of file type definitions from an + * XML file. */ private static class DefinitionsReader { /** - * Reads a set of xmlFile type definitions from an XML xmlFile. + * Reads a set of file type definitions from an XML file. * - * @param filePath The path to the XML xmlFile. + * @param filePath The path to the XML file. * - * @return A collection of xmlFile types read from the XML xmlFile. + * @return A collection of file types read from the XML file. */ private static List readFileTypes(String filePath) throws IOException, SAXException, ParserConfigurationException { List fileTypes = new ArrayList<>(); @@ -389,37 +389,32 @@ final class UserDefinedFileTypesManager { } /** - * Reads the xmlFile types + * Reads the file types * - * @param filePath the xmlFile path where the xmlFile types are to be - * read + * @param filePath the file path where the file types are to be read * - * @return the xmlFile types + * @return the file types * - * @throws ParserConfigurationException If the xmlFile cannot be read + * @throws ParserConfigurationException If the file cannot be read */ private static List readFileTypesSerialized() throws UserDefinedFileTypesException { - List fileTypes = new ArrayList<>(); File serializedDefs = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE)); - if (serializedDefs.exists()) { - try { - try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) { - UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject(); - return filesSetsSettings.getUserDefinedFileTypes(); - } - } catch (IOException | ClassNotFoundException ex) { - throw new UserDefinedFileTypesException("Couldn't read serialized settings.", ex); + try { + try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) { + UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject(); + return filesSetsSettings.getUserDefinedFileTypes(); } + } catch (IOException | ClassNotFoundException ex) { + throw new UserDefinedFileTypesException("Couldn't read serialized settings.", ex); } - return fileTypes; } /** - * Gets a xmlFile type definition from a xmlFile type XML element. + * Gets a file type definition from a file type XML element. * * @param fileTypeElem The XML element. * - * @return A xmlFile type object. + * @return A file type object. * * @throws IllegalArgumentException * @throws NumberFormatException @@ -433,7 +428,7 @@ final class UserDefinedFileTypesManager { } /** - * Gets the MIME type from a xmlFile type XML element. + * Gets the MIME type from a file type XML element. * * @param fileTypeElem The element * @@ -444,7 +439,7 @@ final class UserDefinedFileTypesManager { } /** - * Gets the signature from a xmlFile type XML element. + * Gets the signature from a file type XML element. * * @param fileTypeElem The XML element. * @@ -476,7 +471,7 @@ final class UserDefinedFileTypesManager { } /** - * Gets the interesting files set name from a xmlFile type XML element. + * Gets the interesting files set name from a file type XML element. * * @param fileTypeElem The XML element. * @@ -493,7 +488,7 @@ final class UserDefinedFileTypesManager { } /** - * Gets the alert attribute from a xmlFile type XML element. + * Gets the alert attribute from a file type XML element. * * @param fileTypeElem The XML element. * @@ -536,7 +531,7 @@ final class UserDefinedFileTypesManager { * uniform exception type, and throws the wrapper exception. * * @param ex The exception to wrap. - * @param messageKey A key into the bundle xmlFile that maps to the desired + * @param messageKey A key into the bundle file that maps to the desired * message. * * @throws @@ -551,7 +546,7 @@ final class UserDefinedFileTypesManager { /** * Used to translate more implementation-details-specific exceptions (which * are logged by this class) into more generic exceptions for propagation to - * clients of the user-defined xmlFile types manager. + * clients of the user-defined file types manager. */ static class UserDefinedFileTypesException extends Exception { From 5fcd643b3900517894c99debd2322ad15683a820 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Tue, 29 Mar 2016 10:12:01 -0400 Subject: [PATCH 75/77] Semantics updates to userdefined types save managers. --- .../UserDefinedFileTypesManager.java | 105 ++++++++---------- .../UserDefinedFileTypesSettings.java | 12 +- 2 files changed, 51 insertions(+), 66 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java index d93d53da23..125293e2f9 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java @@ -255,14 +255,14 @@ final class UserDefinedFileTypesManager { try { File serialized = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE)); if (serialized.exists()) { - for (FileType fileType : DefinitionsReader.readFileTypesSerialized()) { + for (FileType fileType : readFileTypesSerialized()) { addUserDefinedFileType(fileType); } } else { String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_XML_FILE); File xmlFile = new File(filePath); if (xmlFile.exists()) { - for (FileType fileType : DefinitionsReader.readFileTypes(filePath)) { + for (FileType fileType : XMLDefinitionsReader.readFileTypes(filePath)) { addUserDefinedFileType(fileType); } } @@ -297,7 +297,7 @@ final class UserDefinedFileTypesManager { */ synchronized void setUserDefinedFileTypes(List newFileTypes) throws UserDefinedFileTypesException { String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_XML_FILE); - DefinitionsWriter.writeFileTypes(newFileTypes, filePath); + writeFileTypes(newFileTypes, filePath); } /** @@ -313,46 +313,52 @@ final class UserDefinedFileTypesManager { } /** - * Provides a mechanism for writing a set of file type definitions to an XML - * file. + * Writes a set of file types to a file. + * + * @param fileTypes A collection of file types. + * @param filePath The path to the destination file. + * + * @throws ParserConfigurationException + * @throws IOException + * @throws FileNotFoundException + * @throws UnsupportedEncodingException + * @throws TransformerException */ - private static class DefinitionsWriter { + private static void writeFileTypes(List fileTypes, String filePath) throws UserDefinedFileTypesException { + try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) { + UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes); + out.writeObject(settings); + } catch (IOException ex) { + throw new UserDefinedFileTypesException(String.format("Failed to write settings to %s", filePath), ex); + } + } - /** - * Writes a set of file type definitions to an XML file. - * - * @param fileTypes A collection of file types. - * @param filePath The path to the destination file. - * - * @throws ParserConfigurationException - * @throws IOException - * @throws FileNotFoundException - * @throws UnsupportedEncodingException - * @throws TransformerException - */ - private static void writeFileTypes(List fileTypes, String filePath) throws UserDefinedFileTypesException { - try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) { - UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes); - out.writeObject(settings); - } catch (IOException ex) { - throw new UserDefinedFileTypesException(String.format("Failed to write settings to %s", filePath), ex); + /** + * Reads the file types + * + * @param filePath the file path where the file types are to be read + * + * @return the file types + * + * @throws ParserConfigurationException If the file cannot be read + */ + private static List readFileTypesSerialized() throws UserDefinedFileTypesException { + File serializedDefs = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE)); + try { + try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) { + UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject(); + return filesSetsSettings.getUserDefinedFileTypes(); } + } catch (IOException | ClassNotFoundException ex) { + throw new UserDefinedFileTypesException("Couldn't read serialized settings.", ex); } - - /** - * Private constructor suppresses creation of instances of this utility - * class. - */ - private DefinitionsWriter() { - } - } /** * Provides a mechanism for reading a set of file type definitions from an * XML file. */ - private static class DefinitionsReader { + private static class XMLDefinitionsReader { /** * Reads a set of file type definitions from an XML file. @@ -380,7 +386,7 @@ final class UserDefinedFileTypesManager { NodeList fileTypeElems = fileTypesElem.getElementsByTagName(FILE_TYPE_TAG_NAME); for (int i = 0; i < fileTypeElems.getLength(); ++i) { Element fileTypeElem = (Element) fileTypeElems.item(i); - FileType fileType = DefinitionsReader.parseFileType(fileTypeElem); + FileType fileType = XMLDefinitionsReader.parseFileType(fileTypeElem); fileTypes.add(fileType); } } @@ -388,27 +394,6 @@ final class UserDefinedFileTypesManager { return fileTypes; } - /** - * Reads the file types - * - * @param filePath the file path where the file types are to be read - * - * @return the file types - * - * @throws ParserConfigurationException If the file cannot be read - */ - private static List readFileTypesSerialized() throws UserDefinedFileTypesException { - File serializedDefs = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE)); - try { - try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) { - UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject(); - return filesSetsSettings.getUserDefinedFileTypes(); - } - } catch (IOException | ClassNotFoundException ex) { - throw new UserDefinedFileTypesException("Couldn't read serialized settings.", ex); - } - } - /** * Gets a file type definition from a file type XML element. * @@ -420,10 +405,10 @@ final class UserDefinedFileTypesManager { * @throws NumberFormatException */ private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException { - String mimeType = DefinitionsReader.parseMimeType(fileTypeElem); - Signature signature = DefinitionsReader.parseSignature(fileTypeElem); - String filesSetName = DefinitionsReader.parseInterestingFilesSet(fileTypeElem); - boolean alert = DefinitionsReader.parseAlert(fileTypeElem); + String mimeType = XMLDefinitionsReader.parseMimeType(fileTypeElem); + Signature signature = XMLDefinitionsReader.parseSignature(fileTypeElem); + String filesSetName = XMLDefinitionsReader.parseInterestingFilesSet(fileTypeElem); + boolean alert = XMLDefinitionsReader.parseAlert(fileTypeElem); return new FileType(mimeType, signature, filesSetName, alert); } @@ -521,7 +506,7 @@ final class UserDefinedFileTypesManager { * Private constructor suppresses creation of instanmces of this utility * class. */ - private DefinitionsReader() { + private XMLDefinitionsReader() { } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesSettings.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesSettings.java index 1f299c9d07..1b69d1dcc4 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesSettings.java @@ -19,27 +19,27 @@ package org.sleuthkit.autopsy.modules.filetypeid; import java.io.Serializable; -import java.util.ArrayList; import java.util.List; /** - * - * @author oliver + * Settings object for user defined file types */ class UserDefinedFileTypesSettings implements Serializable { + private static final long serialVersionUID = 1L; private List userDefinedFileTypes; - + UserDefinedFileTypesSettings(List userDefinedFileTypes) { this.userDefinedFileTypes = userDefinedFileTypes; } /** + * Gets the list of file types contained within the settings + * * @return the userDefinedFileTypes */ public List getUserDefinedFileTypes() { return userDefinedFileTypes; } - - + } From 1c3dba29fb4e84a54d00566c531b8f6266789924 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Wed, 30 Mar 2016 09:02:06 -0400 Subject: [PATCH 76/77] Fixed save of user defined file types definitions. --- .../autopsy/modules/filetypeid/UserDefinedFileTypesManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java index 125293e2f9..6ae8404c13 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java @@ -296,7 +296,7 @@ final class UserDefinedFileTypesManager { * types. */ synchronized void setUserDefinedFileTypes(List newFileTypes) throws UserDefinedFileTypesException { - String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_XML_FILE); + String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE); writeFileTypes(newFileTypes, filePath); } From f43e250381da0a20fa3c74039a1a8eb6b1c78325 Mon Sep 17 00:00:00 2001 From: jmillman Date: Thu, 31 Mar 2016 13:42:24 -0400 Subject: [PATCH 77/77] cleanup and internationalize ThumbnailViewNode --- .../autopsy/corecomponents/ThumbnailViewNode.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java index 5ac5b95c67..1d58764315 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java @@ -26,10 +26,12 @@ import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.SwingWorker; import javax.swing.Timer; +import org.apache.commons.lang3.StringUtils; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; import org.openide.nodes.FilterNode; import org.openide.nodes.Node; +import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.Content; @@ -58,14 +60,12 @@ class ThumbnailViewNode extends FilterNode { @Override public String getDisplayName() { - if (super.getDisplayName().length() > 15) { - return super.getDisplayName().substring(0, 15).concat("..."); - } else { - return super.getDisplayName(); - } + return StringUtils.abbreviate(super.getDisplayName(), 18); } @Override + @NbBundle.Messages({"# {0} - file name", + "ThumbnailViewNode.progressHandle.text=Generating thumbnail for {0}"}) public Image getIcon(int type) { Image icon = null; @@ -82,7 +82,7 @@ class ThumbnailViewNode extends FilterNode { } if (swingWorker == null || swingWorker.isDone()) { swingWorker = new SwingWorker() { - final private ProgressHandle progressHandle = ProgressHandleFactory.createHandle("generating thumbnail for video file " + content.getName()); + final private ProgressHandle progressHandle = ProgressHandleFactory.createHandle(Bundle.ThumbnailViewNode_progressHandle_text(content.getName())); @Override protected Image doInBackground() throws Exception { @@ -97,7 +97,7 @@ class ThumbnailViewNode extends FilterNode { iconCache = new SoftReference<>(super.get()); fireIconChange(); } catch (InterruptedException | ExecutionException ex) { - Logger.getLogger(ThumbnailViewNode.class.getName()).log(Level.SEVERE, "Error getting thumbnail icon", ex); //NON-NLS + Logger.getLogger(ThumbnailViewNode.class.getName()).log(Level.SEVERE, "Error getting thumbnail icon for " + content.getName(), ex); //NON-NLS } finally { progressHandle.finish(); if (timer != null) {