diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml
index 3f1e5f172d..216a8e0f82 100644
--- a/Core/nbproject/project.xml
+++ b/Core/nbproject/project.xml
@@ -15,6 +15,22 @@
1.28.1
+
+ org.netbeans.api.progress.compat8
+
+
+
+ 1.46.1
+
+
+
+ org.netbeans.api.progress.nb
+
+
+
+ 1.46.1
+
+
org.netbeans.core
@@ -123,6 +139,22 @@
7.62.1
+
+ org.openide.filesystems.compat8
+
+
+
+ 9.7.1
+
+
+
+ org.openide.filesystems.nb
+
+
+
+ 9.7.1
+
+
org.openide.modules
@@ -163,6 +195,14 @@
8.15.1
+
+ org.openide.util.ui
+
+
+
+ 9.4.1
+
+
org.openide.windows
diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java
index 2111f3a554..28ce44b3c7 100755
--- a/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java
@@ -1,15 +1,15 @@
/*
* Autopsy Forensic Browser
- *
- * Copyright 2013-2015 Basis Technology Corp.
+ *
+ * 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.
@@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.actions;
import java.util.Collection;
+import java.util.HashSet;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
@@ -26,8 +27,8 @@ import org.openide.util.NbBundle;
import org.openide.util.Utilities;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
-import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.BlackboardArtifact;
+import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException;
/**
@@ -38,7 +39,6 @@ public class AddBlackboardArtifactTagAction extends AddTagAction {
// This class is a singleton to support multi-selection of nodes, since
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
// node in the array returns a reference to the same action object from Node.getActions(boolean).
-
private static AddBlackboardArtifactTagAction instance;
public static synchronized AddBlackboardArtifactTagAction getInstance() {
@@ -63,7 +63,14 @@ public class AddBlackboardArtifactTagAction extends AddTagAction {
@Override
protected void addTag(TagName tagName, String comment) {
- final Collection extends BlackboardArtifact> selectedArtifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
+ /*
+ * The documentation for Lookup.lookupAll() explicitly says that the
+ * collection it returns may contain duplicates. Within this invocation
+ * of addTag(), we don't want to tag the same BlackboardArtifact more
+ * than once, so we dedupe the BlackboardArtifacts by stuffing them into
+ * a HashSet.
+ */
+ final Collection selectedArtifacts = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
new Thread(() -> {
for (BlackboardArtifact artifact : selectedArtifacts) {
diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java
index d504600446..e32f9df902 100755
--- a/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java
@@ -1,15 +1,15 @@
/*
* Autopsy Forensic Browser
- *
- * Copyright 2013-2015 Basis Technology Corp.
+ *
+ * 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.
@@ -19,13 +19,13 @@
package org.sleuthkit.autopsy.actions;
import java.util.Collection;
+import java.util.HashSet;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
import org.sleuthkit.autopsy.casemodule.Case;
-import org.sleuthkit.autopsy.casemodule.services.TagsManager;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
@@ -40,7 +40,6 @@ public class AddContentTagAction extends AddTagAction {
// This class is a singleton to support multi-selection of nodes, since
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
// node in the array returns a reference to the same action object from Node.getActions(boolean).
-
private static AddContentTagAction instance;
public static synchronized AddContentTagAction getInstance() {
@@ -63,7 +62,13 @@ public class AddContentTagAction extends AddTagAction {
@Override
protected void addTag(TagName tagName, String comment) {
- final Collection extends AbstractFile> selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class);
+ /*
+ * The documentation for Lookup.lookupAll() explicitly says that the
+ * collection it returns may contain duplicates. Within this invocation
+ * of addTag(), we don't want to tag the same AbstractFile more than
+ * once, so we dedupe the AbstractFiles by stuffing them into a HashSet.
+ */
+ final Collection selectedFiles = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
new Thread(() -> {
for (AbstractFile file : selectedFiles) {
diff --git a/Core/src/org/sleuthkit/autopsy/actions/ExitAction.java b/Core/src/org/sleuthkit/autopsy/actions/ExitAction.java
new file mode 100755
index 0000000000..15cacf490d
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/actions/ExitAction.java
@@ -0,0 +1,51 @@
+/*
+ * 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.actions;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.logging.Level;
+import org.openide.LifecycleManager;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.autopsy.coreutils.Logger;
+
+@ActionRegistration(displayName = "Exit", iconInMenu = true)
+@ActionReference(path = "Menu/Case", position = 1000, separatorBefore = 999)
+@ActionID(id = "org.sleuthkit.autopsy.casemodule.ExitAction", category = "Case")
+
+final public class ExitAction implements ActionListener {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ try {
+ Case currentCase = Case.getCurrentCase();
+ if (currentCase != null) {
+ currentCase.closeCase();
+ }
+ } catch (Exception ex) {
+ Logger.getLogger(ExitAction.class.getName()).log(Level.SEVERE, "Had a problem closing the case.", ex); //NON-NLS
+ } finally {
+ LifecycleManager.getDefault().exit();
+ }
+ }
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/actions/OpenOutputFolderAction.java b/Core/src/org/sleuthkit/autopsy/actions/OpenOutputFolderAction.java
index be492578a0..e5d922af2d 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/OpenOutputFolderAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/OpenOutputFolderAction.java
@@ -39,7 +39,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
*/
@ActionRegistration(
displayName = "#CTL_OpenOutputFolder", iconInMenu = true)
-@ActionReference(path = "Menu/Help", position = 1850)
+@ActionReference(path = "Menu/Tools", position = 1850, separatorBefore = 1849)
@ActionID(id = "org.sleuthkit.autopsy.actions.OpenOutputFolderAction", category = "Help")
public final class OpenOutputFolderAction extends CallableSystemAction {
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
index 474b7f6ace..f0a42c0fd6 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
@@ -4,7 +4,7 @@ CTL_CaseCloseAct=Close Case
CTL_CaseNewAction=New Case...
CTL_CasePropertiesAction=Case Properties...
CTL_OpenAction=Open Case...
-Menu/File/OpenRecentCase=Open Recent Case
+Menu/Case/OpenRecentCase=Open Recent Case
CTL_CaseDeleteAction=Delete Case
OpenIDE-Module-Name=Case
NewCaseVisualPanel1.jLabel1.text_1=Enter New Case Information:
@@ -18,13 +18,8 @@ NewCaseVisualPanel1.caseDirTextField.text_1=
CasePropertiesForm.caseDirLabel.text=Case Directory:
CasePropertiesForm.crDateLabel.text=Created Date:
CasePropertiesForm.caseNameLabel.text=Case Name:
-CasePropertiesForm.crDateTextField.text=
CasePropertiesForm.caseNameTextField.text=
-CasePropertiesForm.updateCaseNameButton.text=Update
-CasePropertiesForm.casePropLabel.text=Case Information
-CasePropertiesForm.genInfoLabel.text=General Information
-CasePropertiesForm.imgInfoLabel.text=Images Information
-CasePropertiesForm.OKButton.text=OK
+CasePropertiesForm.updateCaseNameButton.text=Update Name
CasePropertiesForm.deleteCaseButton.text=Delete Case
CueBannerPanel.autopsyLogo.text=
CueBannerPanel.createNewLabel.text=Create New Case
@@ -38,8 +33,6 @@ OpenRecentCasePanel.cancelButton.text=Cancel
OpenRecentCasePanel.jLabel1.text=Recent Cases
CasePropertiesForm.caseNumberLabel.text=Case Number:
CasePropertiesForm.examinerLabel.text=Examiner:
-CasePropertiesForm.caseNumberTextField.text=
-CasePropertiesForm.examinerTextField.text=
NewCaseVisualPanel2.caseNumberTextField.text=
NewCaseVisualPanel2.examinerLabel.text=Examiner:
NewCaseVisualPanel2.caseNumberLabel.text=Case Number:
@@ -231,9 +224,7 @@ NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-user
NewCaseVisualPanel1.singleUserCaseRadioButton.text=Single-user
NewCaseVisualPanel1.caseTypeLabel.text=Case Type:
CasePropertiesForm.lbDbType.text=Case Type:
-CasePropertiesForm.tbDbType.text=
CasePropertiesForm.lbDbName.text=Database Name:
-CasePropertiesForm.tbDbName.text=
SingleUserCaseConverter.BadDatabaseFileName=Database file does not exist!
SingleUserCaseConverter.AlreadyMultiUser=Case is already multi-user!
SingleUserCaseConverter.NonUniqueDatabaseName=Database name not unique.
@@ -245,3 +236,10 @@ CasePropertiesForm.imagesTable.columnModel.title1=Remove
CasePropertiesForm.imagesTable.columnModel.title0=Path
LocalFilesPanel.jButton1.text=Change
LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default
+CaseInformationPanel.jPanel1.TabConstraints.tabTitle=tab1
+CasePropertiesForm.caseNumberField.text=
+CasePropertiesForm.examinerField.text=
+CasePropertiesForm.crDateField.text=
+CasePropertiesForm.caseDirField.text=
+CasePropertiesForm.caseTypeField.text=
+CasePropertiesForm.dbNameField.text=
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties
index 4a60a9a404..b033efa9ca 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties
@@ -4,7 +4,7 @@ CTL_CaseCloseAct=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b
CTL_CaseNewAction=\u65b0\u898f\u30b1\u30fc\u30b9...
CTL_CasePropertiesAction=\u30b1\u30fc\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3...
CTL_OpenAction=\u30b1\u30fc\u30b9\u3092\u958b\u304f...
-Menu/File/OpenRecentCase=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f
+Menu/Case/OpenRecentCase=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f
CTL_CaseDeleteAction=\u30b1\u30fc\u30b9\u3092\u524a\u9664
OpenIDE-Module-Name=\u30b1\u30fc\u30b9
NewCaseVisualPanel1.jLabel1.text_1=\u65b0\u898f\u30b1\u30fc\u30b9\u60c5\u5831\u3092\u5165\u529b\uff1a
@@ -16,10 +16,6 @@ CasePropertiesForm.caseDirLabel.text=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\
CasePropertiesForm.crDateLabel.text=\u4f5c\u6210\u65e5\uff1a
CasePropertiesForm.caseNameLabel.text=\u30b1\u30fc\u30b9\u540d\uff1a
CasePropertiesForm.updateCaseNameButton.text=\u66f4\u65b0
-CasePropertiesForm.casePropLabel.text=\u30b1\u30fc\u30b9\u60c5\u5831
-CasePropertiesForm.genInfoLabel.text=\u4e00\u822c\u60c5\u5831
-CasePropertiesForm.imgInfoLabel.text=\u30a4\u30e1\u30fc\u30b8\u60c5\u5831
-CasePropertiesForm.OKButton.text=OK
CasePropertiesForm.deleteCaseButton.text=\u30b1\u30fc\u30b9\u3092\u524a\u9664
CueBannerPanel.createNewLabel.text=\u65b0\u898f\u30b1\u30fc\u30b9\u3092\u4f5c\u6210
CueBannerPanel.openLabel.text=\u65e2\u5b58\u30b1\u30fc\u30b9\u3092\u958b\u304f
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
index 1cd1f9313a..75defea2f3 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
@@ -75,7 +75,7 @@ import org.sleuthkit.autopsy.events.AutopsyEventException;
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
import org.sleuthkit.autopsy.ingest.IngestJob;
import org.sleuthkit.autopsy.ingest.IngestManager;
-import org.sleuthkit.autopsy.ingest.RunIngestAction;
+import org.sleuthkit.autopsy.timeline.OpenTimelineAction;
import org.sleuthkit.datamodel.BlackboardArtifactTag;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentTag;
@@ -1519,27 +1519,20 @@ public class Case implements SleuthkitCase.ErrorObserver {
if (RuntimeProperties.coreComponentsAreActive()) {
// enable these menus
- CallableSystemAction.get(AddImageAction.class).setEnabled(true);
- CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
- CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true);
- CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu
- CallableSystemAction.get(RunIngestAction.class).setEnabled(true);
-
- if (toChangeTo.hasData()) {
- // open all top components
- SwingUtilities.invokeLater(() -> {
- CoreComponentControl.openCoreWindows();
- });
- } else {
- // close all top components
- SwingUtilities.invokeLater(() -> {
- CoreComponentControl.closeCoreWindows();
- });
- }
- }
-
- if (RuntimeProperties.coreComponentsAreActive()) {
SwingUtilities.invokeLater(() -> {
+ CallableSystemAction.get(AddImageAction.class).setEnabled(true);
+ CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
+ CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true);
+ CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu
+ CallableSystemAction.get(OpenTimelineAction.class).setEnabled(true);
+
+ if (toChangeTo.hasData()) {
+ // open all top components
+ CoreComponentControl.openCoreWindows();
+ } else {
+ // close all top components
+ CoreComponentControl.closeCoreWindows();
+ }
updateMainWindowTitle(currentCase.getName());
});
} else {
@@ -1550,9 +1543,9 @@ public class Case implements SleuthkitCase.ErrorObserver {
}
} else { // case is closed
- if (RuntimeProperties.coreComponentsAreActive()) {
+ SwingUtilities.invokeLater(() -> {
+ if (RuntimeProperties.coreComponentsAreActive()) {
- SwingUtilities.invokeLater(() -> {
// close all top components first
CoreComponentControl.closeCoreWindows();
@@ -1561,16 +1554,11 @@ public class Case implements SleuthkitCase.ErrorObserver {
CallableSystemAction.get(CaseCloseAction.class).setEnabled(false); // Case Close menu
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false); // Case Properties menu
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false); // Delete Case menu
- CallableSystemAction.get(RunIngestAction.class).setEnabled(false);
- });
- }
+ CallableSystemAction.get(OpenTimelineAction.class).setEnabled(false);
+ }
- //clear pending notifications
- SwingUtilities.invokeLater(() -> {
+ //clear pending notifications
MessageNotifyUtil.Notify.clear();
- });
-
- SwingUtilities.invokeLater(() -> {
Frame f = WindowManager.getDefault().getMainWindow();
f.setTitle(Case.getAppName()); // set the window name to just application name
});
@@ -1666,7 +1654,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
* Deletes reports from the case.
*
* @param reports Collection of Report to be deleted from the case.
- * @param deleteFromDisk No longer supported - ignored.
+ * @param deleteFromDisk No longer supported - ignored.
*
* @throws TskCoreException
* @deprecated Use deleteReports(Collection extends Report> reports)
@@ -1676,5 +1664,5 @@ public class Case implements SleuthkitCase.ErrorObserver {
public void deleteReports(Collection extends Report> reports, boolean deleteFromDisk) throws TskCoreException {
deleteReports(reports);
}
-
-}
+
+}
\ No newline at end of file
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.form
new file mode 100755
index 0000000000..755d1dca70
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.form
@@ -0,0 +1,63 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java
new file mode 100755
index 0000000000..2e7711d8de
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java
@@ -0,0 +1,90 @@
+/*
+ * 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.casemodule;
+
+import java.util.Map;
+import org.openide.util.NbBundle.Messages;
+
+/**
+ *
+ * @author oliver
+ */
+public class CaseInformationPanel extends javax.swing.JPanel {
+
+ /**
+ * Creates new form CaseInformationPanel
+ */
+ public CaseInformationPanel() {
+ initComponents();
+ customizeComponents();
+ }
+
+ @Messages({"CaseInformationPanel.caseDetails.header=Case Details"})
+ private void customizeComponents() {
+ try {
+ Case currentCase = Case.getCurrentCase();
+ String crDate = currentCase.getCreatedDate();
+ String caseDir = currentCase.getCaseDirectory();
+
+ // put the image paths information into hashmap
+ Map imgPaths = Case.getImagePaths(currentCase.getSleuthkitCase());
+ CasePropertiesForm cpf = new CasePropertiesForm(currentCase, crDate, caseDir, imgPaths);
+ cpf.setSize(cpf.getPreferredSize());
+ this.tabbedPane.addTab(Bundle.CaseInformationPanel_caseDetails_header(), cpf);
+ } catch (CaseMetadata.CaseMetadataException ex) {
+ //TOLOG
+ }
+ }
+
+
+ /**
+ * 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() {
+
+ jPanel1 = new javax.swing.JPanel();
+ tabbedPane = new javax.swing.JTabbedPane();
+
+ tabbedPane.setPreferredSize(new java.awt.Dimension(420, 200));
+
+ javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+ jPanel1.setLayout(jPanel1Layout);
+ jPanel1Layout.setHorizontalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(tabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ );
+ jPanel1Layout.setVerticalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
+ .addComponent(tabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 228, Short.MAX_VALUE)
+ .addGap(0, 0, 0))
+ );
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(0, 0, 0)
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGap(0, 0, 0))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ );
+ }// //GEN-END:initComponents
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JTabbedPane tabbedPane;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java
index 5cae020845..b54d342a44 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java
@@ -20,9 +20,6 @@ package org.sleuthkit.autopsy.casemodule;
import java.awt.Dimension;
import java.awt.Toolkit;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.Map;
import java.util.logging.Level;
import javax.swing.Action;
import javax.swing.JDialog;
@@ -61,32 +58,16 @@ final class CasePropertiesAction extends CallableSystemAction {
// create the popUp window for it
String title = NbBundle.getMessage(this.getClass(), "CasePropertiesAction.window.title");
final JFrame frame = new JFrame(title);
- popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
-
- // get the information that needed
- Case currentCase = Case.getCurrentCase();
- String crDate = currentCase.getCreatedDate();
- String caseDir = currentCase.getCaseDirectory();
-
- // put the image paths information into hashmap
- Map imgPaths = Case.getImagePaths(currentCase.getSleuthkitCase());
+ popUpWindow = new JDialog(frame, title, false); // to make the popUp Window to be modal
// create the case properties form
- CasePropertiesForm cpf = new CasePropertiesForm(currentCase, crDate, caseDir, imgPaths);
-
- // add the command to close the window to the button on the Case Properties form / panel
- cpf.setOKButtonActionListener(new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- popUpWindow.dispose();
- }
- });
+ CaseInformationPanel caseInformationPanel = new CaseInformationPanel();
// add the case properties form / panel to the popup window
- popUpWindow.add(cpf);
+ popUpWindow.add(caseInformationPanel);
+ popUpWindow.setResizable(true);
popUpWindow.pack();
- popUpWindow.setResizable(false);
+
// set the location of the popUp Window on the center of the screen
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.form b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.form
index 14b675bc54..9ceccdad62 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.form
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.form
@@ -33,437 +33,307 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java
index 537cd0f3d2..80605bc8c1 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java
@@ -17,36 +17,33 @@
* limitations under the License.
*/
-/*
+ /*
* CasePropertiesForm.java
*
* Created on Mar 14, 2011, 1:48:20 PM
*/
package org.sleuthkit.autopsy.casemodule;
-import java.nio.file.Paths;
-import java.awt.event.ActionListener;
import java.io.File;
import java.util.Map;
import java.util.logging.Level;
-import org.openide.util.NbBundle;
-import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
-import javax.swing.table.DefaultTableModel;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
+import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
+import org.sleuthkit.autopsy.coreutils.Logger;
/**
* The form where user can change / update the properties of the current case
* metadata.
*/
class CasePropertiesForm extends javax.swing.JPanel {
-
+
private static final long serialVersionUID = 1L;
-
+
private Case current = null;
private static JPanel caller; // panel for error
@@ -55,15 +52,15 @@ class CasePropertiesForm extends javax.swing.JPanel {
private String shrinkPath(String path, int targetLength) {
if (path.length() > targetLength) {
String fill = "...";
-
+
int partsLength = targetLength - fill.length();
-
+
String front = path.substring(0, partsLength / 4);
int frontSep = front.lastIndexOf(File.separatorChar);
if (frontSep != -1) {
front = front.substring(0, frontSep + 1);
}
-
+
String back = path.substring(partsLength * 3 / 4);
int backSep = back.indexOf(File.separatorChar);
if (backSep != -1) {
@@ -81,52 +78,35 @@ class CasePropertiesForm extends javax.swing.JPanel {
CasePropertiesForm(Case currentCase, String crDate, String caseDir, Map imgPaths) throws CaseMetadata.CaseMetadataException {
initComponents();
caseNameTextField.setText(currentCase.getName());
- caseNumberTextField.setText(currentCase.getNumber());
- examinerTextField.setText(currentCase.getExaminer());
- crDateTextField.setText(crDate);
- caseDirTextArea.setText(caseDir);
+ String caseNumber = currentCase.getNumber();
+ if (!caseNumber.equals("")) {
+ caseNumberField.setText(caseNumber);
+ } else {
+ caseNumberField.setText("N/A");
+ }
+ String examiner = currentCase.getExaminer();
+ if (!examiner.equals("")) {
+ examinerField.setText(examiner);
+ } else {
+ examinerField.setText("N/A");
+ }
+ crDateField.setText(crDate);
+ caseDirField.setText(caseDir);
current = currentCase;
-
+
CaseMetadata caseMetadata = currentCase.getCaseMetadata();
if (caseMetadata.getCaseType() == Case.CaseType.SINGLE_USER_CASE) {
- tbDbName.setText(caseMetadata.getCaseDatabasePath());
+ dbNameField.setText(caseMetadata.getCaseDatabasePath());
} else {
- tbDbName.setText(caseMetadata.getCaseDatabaseName());
+ dbNameField.setText(caseMetadata.getCaseDatabaseName());
}
Case.CaseType caseType = caseMetadata.getCaseType();
- tbDbType.setText(caseType.getLocalizedDisplayName());
+ caseTypeField.setText(caseType.getLocalizedDisplayName());
if (caseType == Case.CaseType.SINGLE_USER_CASE) {
deleteCaseButton.setEnabled(true);
} else {
deleteCaseButton.setEnabled(false);
}
-
- int totalImages = imgPaths.size();
-
- // create the headers and add all the rows
- // Header names are internationalized via the generated code, do not overwrite.
- String[] headers = {imagesTable.getColumnName(0),
- imagesTable.getColumnName(1)};
- String[][] rows = new String[totalImages][];
-
- int i = 0;
- for (long key : imgPaths.keySet()) {
- String path = imgPaths.get(key);
- String shortenPath = shrinkPath(path, 70);
- rows[i] = new String[]{shortenPath};
- i++;
- }
-
- // create the table inside with the imgPaths information
- DefaultTableModel model = new DefaultTableModel(rows, headers) {
- @Override
- // make the cells in the FileContentTable "read only"
- public boolean isCellEditable(int row, int column) {
- return false;
- //return column == lastColumn; // make the last column (Remove button), only the editable
- }
- };
- imagesTable.setModel(model);
}
/**
@@ -149,38 +129,28 @@ class CasePropertiesForm extends javax.swing.JPanel {
jScrollPane1 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea();
- casePropLabel = new javax.swing.JLabel();
+ jPanel1 = new javax.swing.JPanel();
caseNameLabel = new javax.swing.JLabel();
crDateLabel = new javax.swing.JLabel();
caseDirLabel = new javax.swing.JLabel();
- crDateTextField = new javax.swing.JTextField();
caseNameTextField = new javax.swing.JTextField();
updateCaseNameButton = new javax.swing.JButton();
- genInfoLabel = new javax.swing.JLabel();
- imgInfoLabel = new javax.swing.JLabel();
- OKButton = new javax.swing.JButton();
- imagesTableScrollPane = new javax.swing.JScrollPane();
- imagesTable = new javax.swing.JTable();
- jScrollPane2 = new javax.swing.JScrollPane();
- caseDirTextArea = new javax.swing.JTextArea();
deleteCaseButton = new javax.swing.JButton();
caseNumberLabel = new javax.swing.JLabel();
examinerLabel = new javax.swing.JLabel();
- caseNumberTextField = new javax.swing.JTextField();
- examinerTextField = new javax.swing.JTextField();
lbDbType = new javax.swing.JLabel();
- tbDbType = new javax.swing.JTextField();
lbDbName = new javax.swing.JLabel();
- tbDbName = new javax.swing.JTextField();
+ caseNumberField = new javax.swing.JLabel();
+ examinerField = new javax.swing.JLabel();
+ crDateField = new javax.swing.JLabel();
+ caseDirField = new javax.swing.JLabel();
+ dbNameField = new javax.swing.JLabel();
+ caseTypeField = new javax.swing.JLabel();
jTextArea1.setColumns(20);
jTextArea1.setRows(5);
jScrollPane1.setViewportView(jTextArea1);
- casePropLabel.setFont(casePropLabel.getFont().deriveFont(casePropLabel.getFont().getStyle() | java.awt.Font.BOLD, 24));
- casePropLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
- casePropLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.casePropLabel.text")); // NOI18N
-
caseNameLabel.setFont(caseNameLabel.getFont().deriveFont(caseNameLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
caseNameLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNameLabel.text")); // NOI18N
@@ -190,12 +160,13 @@ class CasePropertiesForm extends javax.swing.JPanel {
caseDirLabel.setFont(caseDirLabel.getFont().deriveFont(caseDirLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
caseDirLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseDirLabel.text")); // NOI18N
- crDateTextField.setEditable(false);
- crDateTextField.setFont(crDateTextField.getFont().deriveFont(crDateTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
- crDateTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.crDateTextField.text")); // NOI18N
-
caseNameTextField.setFont(caseNameTextField.getFont().deriveFont(caseNameTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
caseNameTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNameTextField.text")); // NOI18N
+ caseNameTextField.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ caseNameTextFieldActionPerformed(evt);
+ }
+ });
updateCaseNameButton.setFont(updateCaseNameButton.getFont().deriveFont(updateCaseNameButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
updateCaseNameButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.updateCaseNameButton.text")); // NOI18N
@@ -205,53 +176,6 @@ class CasePropertiesForm extends javax.swing.JPanel {
}
});
- genInfoLabel.setFont(genInfoLabel.getFont().deriveFont(genInfoLabel.getFont().getStyle() | java.awt.Font.BOLD, 14));
- genInfoLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.genInfoLabel.text")); // NOI18N
-
- imgInfoLabel.setFont(imgInfoLabel.getFont().deriveFont(imgInfoLabel.getFont().getStyle() | java.awt.Font.BOLD, 14));
- imgInfoLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.imgInfoLabel.text")); // NOI18N
-
- OKButton.setFont(OKButton.getFont().deriveFont(OKButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
- OKButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.OKButton.text")); // NOI18N
-
- imagesTableScrollPane.setFont(imagesTableScrollPane.getFont().deriveFont(imagesTableScrollPane.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
-
- imagesTable.setFont(imagesTable.getFont().deriveFont(imagesTable.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
- imagesTable.setModel(new javax.swing.table.DefaultTableModel(
- new Object [][] {
-
- },
- new String [] {
- "Path", "Remove"
- }
- ) {
- boolean[] canEdit = new boolean [] {
- false, true
- };
-
- public boolean isCellEditable(int rowIndex, int columnIndex) {
- return canEdit [columnIndex];
- }
- });
- imagesTable.setShowHorizontalLines(false);
- imagesTable.setShowVerticalLines(false);
- imagesTable.getTableHeader().setReorderingAllowed(false);
- imagesTable.setUpdateSelectionOnSort(false);
- imagesTableScrollPane.setViewportView(imagesTable);
- if (imagesTable.getColumnModel().getColumnCount() > 0) {
- imagesTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.imagesTable.columnModel.title0")); // NOI18N
- imagesTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.imagesTable.columnModel.title1")); // NOI18N
- }
-
- jScrollPane2.setFont(jScrollPane2.getFont().deriveFont(jScrollPane2.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
-
- caseDirTextArea.setEditable(false);
- caseDirTextArea.setBackground(new java.awt.Color(240, 240, 240));
- caseDirTextArea.setColumns(20);
- caseDirTextArea.setRows(1);
- caseDirTextArea.setRequestFocusEnabled(false);
- jScrollPane2.setViewportView(caseDirTextArea);
-
deleteCaseButton.setFont(deleteCaseButton.getFont().deriveFont(deleteCaseButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
deleteCaseButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.deleteCaseButton.text")); // NOI18N
deleteCaseButton.addActionListener(new java.awt.event.ActionListener() {
@@ -266,117 +190,119 @@ class CasePropertiesForm extends javax.swing.JPanel {
examinerLabel.setFont(examinerLabel.getFont().deriveFont(examinerLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
examinerLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.examinerLabel.text")); // NOI18N
- caseNumberTextField.setEditable(false);
- caseNumberTextField.setFont(caseNumberTextField.getFont().deriveFont(caseNumberTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
- caseNumberTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNumberTextField.text")); // NOI18N
-
- examinerTextField.setEditable(false);
- examinerTextField.setFont(examinerTextField.getFont().deriveFont(examinerTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
- examinerTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.examinerTextField.text")); // NOI18N
-
lbDbType.setFont(lbDbType.getFont().deriveFont(lbDbType.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
lbDbType.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.lbDbType.text")); // NOI18N
- tbDbType.setEditable(false);
- tbDbType.setFont(tbDbType.getFont().deriveFont(tbDbType.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
- tbDbType.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.tbDbType.text")); // NOI18N
-
lbDbName.setFont(lbDbName.getFont().deriveFont(lbDbName.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
lbDbName.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.lbDbName.text")); // NOI18N
- tbDbName.setEditable(false);
- tbDbName.setFont(tbDbName.getFont().deriveFont(tbDbName.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
- tbDbName.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.tbDbName.text")); // NOI18N
+ caseNumberField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNumberField.text")); // NOI18N
+
+ examinerField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.examinerField.text")); // NOI18N
+
+ crDateField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.crDateField.text")); // NOI18N
+
+ caseDirField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseDirField.text")); // NOI18N
+ caseDirField.setMinimumSize(new java.awt.Dimension(25, 14));
+
+ dbNameField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.dbNameField.text")); // NOI18N
+ dbNameField.setMinimumSize(new java.awt.Dimension(25, 14));
+
+ caseTypeField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseTypeField.text")); // NOI18N
+ caseTypeField.setMaximumSize(new java.awt.Dimension(1, 0));
+
+ javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+ jPanel1.setLayout(jPanel1Layout);
+ jPanel1Layout.setHorizontalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(lbDbName)
+ .addComponent(lbDbType)
+ .addComponent(caseDirLabel))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(caseDirField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(caseTypeField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(dbNameField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(crDateLabel)
+ .addComponent(examinerLabel)
+ .addComponent(caseNumberLabel))
+ .addGap(18, 18, 18)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(examinerField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(caseNumberField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addComponent(caseNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 243, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(updateCaseNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, 104, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(crDateField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
+ .addGap(0, 0, Short.MAX_VALUE)
+ .addComponent(deleteCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 106, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addContainerGap())
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(caseNameLabel)
+ .addContainerGap(392, Short.MAX_VALUE)))
+ );
+ jPanel1Layout.setVerticalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(caseNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(updateCaseNameButton))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addComponent(caseNumberField, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(examinerField, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(examinerLabel))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(crDateField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(crDateLabel, javax.swing.GroupLayout.Alignment.TRAILING))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(caseDirLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(caseDirField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(caseTypeField, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(lbDbType))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(lbDbName)
+ .addComponent(dbNameField, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addComponent(caseNumberLabel))
+ .addGap(10, 10, 10)
+ .addComponent(deleteCaseButton)
+ .addContainerGap())
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(caseNameLabel)
+ .addContainerGap(173, Short.MAX_VALUE)))
+ );
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addContainerGap()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(casePropLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 440, Short.MAX_VALUE)
- .addComponent(imagesTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 440, Short.MAX_VALUE)
- .addGroup(layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(caseNameLabel)
- .addComponent(caseNumberLabel)
- .addComponent(examinerLabel)
- .addComponent(caseDirLabel)
- .addComponent(crDateLabel)
- .addComponent(lbDbType))
- .addGap(18, 18, 18)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(caseNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 245, Short.MAX_VALUE)
- .addComponent(caseNumberTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 245, Short.MAX_VALUE)
- .addComponent(examinerTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 245, Short.MAX_VALUE)
- .addComponent(crDateTextField)
- .addComponent(jScrollPane2)
- .addComponent(tbDbType)
- .addComponent(tbDbName))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(deleteCaseButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(updateCaseNameButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
- .addGroup(layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(genInfoLabel)
- .addComponent(imgInfoLabel)
- .addGroup(layout.createSequentialGroup()
- .addGap(181, 181, 181)
- .addComponent(OKButton, javax.swing.GroupLayout.PREFERRED_SIZE, 78, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addComponent(lbDbName))
- .addGap(0, 0, Short.MAX_VALUE)))
- .addContainerGap())
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addContainerGap()
- .addComponent(casePropLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(18, 18, 18)
- .addComponent(genInfoLabel)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(caseNameLabel)
- .addComponent(caseNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(updateCaseNameButton))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(caseNumberLabel)
- .addComponent(caseNumberTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(examinerLabel)
- .addComponent(examinerTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(crDateLabel)
- .addComponent(crDateTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(caseDirLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(tbDbType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(lbDbType))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(lbDbName)
- .addComponent(tbDbName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addGap(18, 18, 18)
- .addComponent(imgInfoLabel))
- .addGroup(layout.createSequentialGroup()
- .addGap(9, 9, 9)
- .addComponent(deleteCaseButton)))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(imagesTableScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 170, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(OKButton)
- .addContainerGap())
+ .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
);
}// //GEN-END:initComponents
@@ -399,38 +325,36 @@ class CasePropertiesForm extends javax.swing.JPanel {
NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.msgDlg.empty.title"),
JOptionPane.ERROR_MESSAGE);
+ } else // check if case Name contain one of this following symbol:
+ // \ / : * ? " < > |
+ if (newCaseName.contains("\\") || newCaseName.contains("/") || newCaseName.contains(":")
+ || newCaseName.contains("*") || newCaseName.contains("?") || newCaseName.contains("\"")
+ || newCaseName.contains("<") || newCaseName.contains(">") || newCaseName.contains("|")) {
+ String errorMsg = NbBundle
+ .getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.msg");
+ JOptionPane.showMessageDialog(caller, errorMsg,
+ NbBundle.getMessage(this.getClass(),
+ "CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.title"),
+ JOptionPane.ERROR_MESSAGE);
} else {
- // check if case Name contain one of this following symbol:
- // \ / : * ? " < > |
- if (newCaseName.contains("\\") || newCaseName.contains("/") || newCaseName.contains(":")
- || newCaseName.contains("*") || newCaseName.contains("?") || newCaseName.contains("\"")
- || newCaseName.contains("<") || newCaseName.contains(">") || newCaseName.contains("|")) {
- String errorMsg = NbBundle
- .getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.msg");
- JOptionPane.showMessageDialog(caller, errorMsg,
- NbBundle.getMessage(this.getClass(),
- "CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.title"),
- JOptionPane.ERROR_MESSAGE);
- } else {
- // ask for the confirmation first
- String confMsg = NbBundle
- .getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.confMsg.msg", oldCaseName,
- newCaseName);
- NotifyDescriptor d = new NotifyDescriptor.Confirmation(confMsg,
- NbBundle.getMessage(this.getClass(),
- "CasePropertiesForm.updateCaseName.confMsg.title"),
- NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
- d.setValue(NotifyDescriptor.NO_OPTION);
-
- Object res = DialogDisplayer.getDefault().notify(d);
- if (res != null && res == DialogDescriptor.YES_OPTION) {
- // if user select "Yes"
- String oldPath = current.getCaseMetadata().getFilePath().toString();
- try {
- current.updateCaseName(oldCaseName, oldPath, newCaseName, oldPath);
- } catch (Exception ex) {
- Logger.getLogger(CasePropertiesForm.class.getName()).log(Level.WARNING, "Error: problem updating case name.", ex); //NON-NLS
- }
+ // ask for the confirmation first
+ String confMsg = NbBundle
+ .getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.confMsg.msg", oldCaseName,
+ newCaseName);
+ NotifyDescriptor d = new NotifyDescriptor.Confirmation(confMsg,
+ NbBundle.getMessage(this.getClass(),
+ "CasePropertiesForm.updateCaseName.confMsg.title"),
+ NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
+ d.setValue(NotifyDescriptor.NO_OPTION);
+
+ Object res = DialogDisplayer.getDefault().notify(d);
+ if (res != null && res == DialogDescriptor.YES_OPTION) {
+ // if user select "Yes"
+ String oldPath = current.getCaseMetadata().getFilePath().toString();
+ try {
+ current.updateCaseName(oldCaseName, oldPath, newCaseName, oldPath);
+ } catch (Exception ex) {
+ Logger.getLogger(CasePropertiesForm.class.getName()).log(Level.WARNING, "Error: problem updating case name.", ex); //NON-NLS
}
}
}
@@ -441,40 +365,30 @@ class CasePropertiesForm extends javax.swing.JPanel {
CallableSystemAction.get(CaseDeleteAction.class).actionPerformed(evt);
}//GEN-LAST:event_deleteCaseButtonActionPerformed
- /**
- * Sets the listener for the OK button
- *
- * @param e The action listener
- */
- public void setOKButtonActionListener(ActionListener e) {
- OKButton.addActionListener(e);
- }
+ private void caseNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_caseNameTextFieldActionPerformed
+ // TODO add your handling code here:
+ }//GEN-LAST:event_caseNameTextFieldActionPerformed
+
// Variables declaration - do not modify//GEN-BEGIN:variables
- private javax.swing.JButton OKButton;
+ private javax.swing.JLabel caseDirField;
private javax.swing.JLabel caseDirLabel;
- private javax.swing.JTextArea caseDirTextArea;
private javax.swing.JLabel caseNameLabel;
private javax.swing.JTextField caseNameTextField;
+ private javax.swing.JLabel caseNumberField;
private javax.swing.JLabel caseNumberLabel;
- private javax.swing.JTextField caseNumberTextField;
- private javax.swing.JLabel casePropLabel;
+ private javax.swing.JLabel caseTypeField;
+ private javax.swing.JLabel crDateField;
private javax.swing.JLabel crDateLabel;
- private javax.swing.JTextField crDateTextField;
+ private javax.swing.JLabel dbNameField;
private javax.swing.JButton deleteCaseButton;
+ private javax.swing.JLabel examinerField;
private javax.swing.JLabel examinerLabel;
- private javax.swing.JTextField examinerTextField;
- private javax.swing.JLabel genInfoLabel;
- private javax.swing.JTable imagesTable;
- private javax.swing.JScrollPane imagesTableScrollPane;
- private javax.swing.JLabel imgInfoLabel;
+ private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
- private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea jTextArea1;
private javax.swing.JLabel lbDbName;
private javax.swing.JLabel lbDbType;
- private javax.swing.JTextField tbDbName;
- private javax.swing.JTextField tbDbType;
private javax.swing.JButton updateCaseNameButton;
// End of variables declaration//GEN-END:variables
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java
index d5064e3b4e..70b10b0f0e 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java
@@ -25,17 +25,30 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
+import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskDataException;
/**
- * Represents the blackboard, a place where artifacts and their attributes are
- * posted.
+ * A representation of the blackboard, a place where artifacts and their
+ * attributes are posted.
*
* NOTE: This API of this class is under development.
*/
public final class Blackboard implements Closeable {
+ private SleuthkitCase caseDb;
+
+ /**
+ * Constructs a representation of the blackboard, a place where artifacts
+ * and their attributes are posted.
+ *
+ * @param casedb The case database.
+ */
+ Blackboard(SleuthkitCase casedb) {
+ this.caseDb = casedb;
+ }
+
/**
* Indexes the text associated with the an artifact.
*
@@ -43,7 +56,10 @@ public final class Blackboard implements Closeable {
*
* @throws BlackboardException If there is a problem indexing the artifact.
*/
- public void indexArtifact(BlackboardArtifact artifact) throws BlackboardException {
+ public synchronized void indexArtifact(BlackboardArtifact artifact) throws BlackboardException {
+ if (null == caseDb) {
+ throw new BlackboardException("Blackboard has been closed");
+ }
KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
if (null == searchService) {
throw new BlackboardException("Keyword search service not found");
@@ -67,12 +83,15 @@ public final class Blackboard implements Closeable {
* @throws BlackboardBlackboardException If there is a problem getting or
* adding the artifact type.
*/
- public BlackboardArtifact.Type getOrAddArtifactType(String typeName, String displayName) throws BlackboardException {
+ public synchronized BlackboardArtifact.Type getOrAddArtifactType(String typeName, String displayName) throws BlackboardException {
+ if (null == caseDb) {
+ throw new BlackboardException("Blackboard has been closed");
+ }
try {
- return Case.getCurrentCase().getSleuthkitCase().addBlackboardArtifactType(typeName, displayName);
+ return caseDb.addBlackboardArtifactType(typeName, displayName);
} catch (TskDataException typeExistsEx) {
try {
- return Case.getCurrentCase().getSleuthkitCase().getArtifactType(typeName);
+ return caseDb.getArtifactType(typeName);
} catch (TskCoreException ex) {
throw new BlackboardException("Failed to get or add artifact type", ex);
}
@@ -94,12 +113,15 @@ public final class Blackboard implements Closeable {
* @throws BlackboardBlackboardException If there is a problem getting or
* adding the attribute type.
*/
- public BlackboardAttribute.Type getOrAddAttributeType(String typeName, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName) throws BlackboardException {
+ public synchronized BlackboardAttribute.Type getOrAddAttributeType(String typeName, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName) throws BlackboardException {
+ if (null == caseDb) {
+ throw new BlackboardException("Blackboard has been closed");
+ }
try {
- return Case.getCurrentCase().getSleuthkitCase().addArtifactAttributeType(typeName, valueType, displayName);
+ return caseDb.addArtifactAttributeType(typeName, valueType, displayName);
} catch (TskDataException typeExistsEx) {
try {
- return Case.getCurrentCase().getSleuthkitCase().getAttributeType(typeName);
+ return caseDb.getAttributeType(typeName);
} catch (TskCoreException ex) {
throw new BlackboardException("Failed to get or add attribute type", ex);
}
@@ -109,13 +131,16 @@ public final class Blackboard implements Closeable {
}
/**
- * Cloese this blackboard and releases any resources associated with it.
- * @throws IOException
+ * Closes the blackboard.
+ *
+ * @throws IOException If there is a problem closing the blackboard.
*/
@Override
- public void close() throws IOException {
+ public synchronized void close() throws IOException {
+ caseDb = null;
}
+
/**
* A blackboard exception.
*/
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties
index 9353ca914b..1a3be9454f 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties
@@ -1,16 +1,3 @@
-FileManager.findFiles.exception.msg=Attempted to use FileManager after it was closed.
-FileManager.findFiles2.exception.msg=Attempted to use FileManager after it was closed.
-FileManager.findFiles3.exception.msg=Attempted to use FileManager after it was closed.
-FileManager.openFiles.exception.msg=Attempted to use FileManager after it was closed.
-FileManager.addDerivedFile.exception.msg=Attempted to use FileManager after it was closed.
-FileManager.addCarvedFile.exception.msg=Attempted to use FileManager after it was closed.
-FileManager.addLocalFilesDirs.exception.notReadable.msg=One of the local files/dirs to add is not readable\: {0}, aborting the process before any files added
-FileManager.addLocalFilesDirs.exception.cantAdd.msg=One of the local files/dirs could not be added\: {0}
-FileManager.addLocalFileSetRootDir.exception.errCreateDir.msg=Error creating local file set dir\: {0}
-FileManager.addLocalDirInt.exception.closed.msg=Attempted to use FileManager after it was closed.
-FileManager.addLocalDirInt.exception.doesntExist.msg=Attempted to add a local dir that does not exist\: {0}
-FileManager.addLocalDirInt.exception.notReadable.msg=Attempted to add a local dir that is not readable\: {0}
-FileManager.addLocalDirInt2.exception.closed.msg=Attempted to use FileManager after it was closed.
TagsManager.addContentTag.exception.beginByteOffsetOOR.msg=beginByteOffset \= {0} out of content size range (0 - {1})
TagsManager.addContentTag.exception.endByteOffsetOOR.msg=endByteOffset \= {0} out of content size range (0 - {1})
TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties
index 956a5e6169..ca8ed3431a 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties
@@ -1,16 +1,3 @@
-FileManager.findFiles.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
-FileManager.findFiles2.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
-FileManager.findFiles3.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
-FileManager.openFiles.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
-FileManager.addDerivedFile.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
-FileManager.addCarvedFile.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
-FileManager.addLocalFilesDirs.exception.notReadable.msg=\u8ffd\u52a0\u3059\u308b\u30ed\u30fc\u30ab\u30eb\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u4e2d\u306b\u8aad\u307f\u53d6\u308c\u306a\u3044\u3082\u306e\u304c\uff11\u500b\u3042\u308a\u307e\u3059\uff1a{0}\u3001\u30d5\u30a1\u30a4\u30eb\u304c\u8ffd\u52a0\u3055\u308c\u308b\u524d\u306b\u51e6\u7406\u3092\u4e2d\u6b62\u3057\u307e\u3059
-FileManager.addLocalFilesDirs.exception.cantAdd.msg=\u30ed\u30fc\u30ab\u30eb\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\uff11\u500b\u306f\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\uff1a{0}
-FileManager.addLocalFileSetRootDir.exception.errCreateDir.msg=\u30ed\u30fc\u30ab\u30eb\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u8d77\u3053\u308a\u307e\u3057\u305f\uff1a {0}
-FileManager.addLocalDirInt.exception.closed.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
-FileManager.addLocalDirInt.exception.doesntExist.msg=\u5b58\u5728\u3057\u306a\u3044\u30ed\u30fc\u30ab\u30eb\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u8ffd\u52a0\u3092\u8a66\u307f\u307e\u3057\u305f\: {0}
-FileManager.addLocalDirInt.exception.notReadable.msg=\u8aad\u307f\u53d6\u308a\u3067\u304d\u306a\u3044\u30ed\u30fc\u30ab\u30eb\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u8ffd\u52a0\u3092\u8a66\u307f\u307e\u3057\u305f\: {0}
-FileManager.addLocalDirInt2.exception.closed.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002
TagsManager.addContentTag.exception.beginByteOffsetOOR.msg=beginByteOffset \= {0} \u30b3\u30f3\u30c6\u30f3\u30c4\u30b5\u30a4\u30ba\u7bc4\u56f2(0 - {1})\u306e\u5916\u3067\u3059
TagsManager.addContentTag.exception.endByteOffsetOOR.msg=endByteOffset \= {0} \u30b3\u30f3\u30c6\u30f3\u30c4\u30b5\u30a4\u30ba\u7bc4\u56f2(0 - {1})\u306e\u5916\u3067\u3059
TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java
index 5b958cd5a7..2787924d93 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java
@@ -1,19 +1,19 @@
/*
*
* Autopsy Forensic Browser
- *
+ *
* Copyright 2011-2016 Basis Technology Corp.
- *
+ *
* Copyright 2012 42six Solutions.
* Contact: aebadirad 42six com
* Project Contact/Architect: 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.
@@ -25,10 +25,9 @@ package org.sleuthkit.autopsy.casemodule.services;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
-import java.util.logging.Level;
import org.openide.util.NbBundle;
-import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
@@ -36,67 +35,102 @@ import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.LayoutFile;
-import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskFileRange;
import org.sleuthkit.datamodel.VirtualDirectory;
-import org.sleuthkit.datamodel.CarvedFileContainer;
import org.sleuthkit.datamodel.LocalFilesDataSource;
import org.sleuthkit.datamodel.TskDataException;
+import org.apache.commons.lang3.StringUtils;
+import org.sleuthkit.datamodel.CarvingResult;
/**
- * Abstraction to facilitate access to localFiles and directories.
+ * A manager that provides methods for retrieving files from the current case
+ * and for adding local files, carved files, and derived files to the current
+ * case.
*/
public class FileManager implements Closeable {
- private SleuthkitCase tskCase;
- private static final Logger logger = Logger.getLogger(FileManager.class.getName());
- private volatile int curNumFileSets; //current number of filesets (root virt dir objects)
-
- public FileManager(SleuthkitCase tskCase) {
- this.tskCase = tskCase;
- init();
- }
+ private SleuthkitCase caseDb;
/**
- * initialize the file manager for the case
+ * Constructs a manager that provides methods for retrieving files from the
+ * current case and for adding local files, carved files, and derived files
+ * to the current case.
+ *
+ * @param caseDb The case database.
*/
- private synchronized void init() {
- //get the number of local file sets in db
- List virtRoots;
- curNumFileSets = 0;
- try {
- virtRoots = tskCase.getVirtualDirectoryRoots();
- for (VirtualDirectory vd : virtRoots) {
- if (vd.getName().startsWith(VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX)) {
- ++curNumFileSets;
- }
- }
- } catch (TskCoreException ex) {
- logger.log(Level.SEVERE, "Error initializing FileManager and getting number of local file sets"); //NON-NLS
- }
-
+ public FileManager(SleuthkitCase caseDb) {
+ this.caseDb = caseDb;
}
/**
- * Finds a set of localFiles that meets the name criteria in all data
- * sources in the current case.
+ * Finds all files with types that match one of a collection of MIME types.
*
- * @param fileName Pattern of the name of the file or directory to match
- * (case insensitive, used in LIKE SQL statement).
+ * @param mimeTypes The MIME types.
*
- * @return a list of AbstractFile for localFiles/directories whose name
- * matches the given fileName
+ * @return The files.
+ *
+ * @throws TskCoreException If there is a problem querying the case
+ * database.
+ */
+ public synchronized List findFilesByMimeType(Collection mimeTypes) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
+ }
+ return caseDb.findAllFilesWhere(createFileTypeInCondition(mimeTypes));
+ }
+
+ /**
+ * Finds all files in a given data source (image, local/logical files set,
+ * etc.) with types that match one of a collection of MIME types.
+ *
+ * @param dataSource The data source.
+ * @param mimeTypes The MIME types.
+ *
+ * @return The files.
+ *
+ * @throws TskCoreException If there is a problem querying the case
+ * database.
+ */
+ public synchronized List findFilesByMimeType(Content dataSource, Collection mimeTypes) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
+ }
+ return caseDb.findAllFilesWhere("data_source_obj_id = " + dataSource.getId() + " AND " + createFileTypeInCondition(mimeTypes));
+ }
+
+ /**
+ * Converts a list of MIME types into an SQL "mime_type IN" condition.
+ *
+ * @param mimeTypes The MIIME types.
+ *
+ * @return The condition string.
+ */
+ private static String createFileTypeInCondition(Collection mimeTypes) {
+ String types = StringUtils.join(mimeTypes, "', '");
+ return "mime_type IN ('" + types + "')";
+ }
+
+ /**
+ * Finds all files and directories with a given file name. The name search
+ * is for full or partial matches and is case insensitive (a case
+ * insensitive SQL LIKE clause is used to query the case database).
+ *
+ * @param fileName The full or partial file name.
+ *
+ * @return The matching files and directories.
+ *
+ * @throws TskCoreException if there is a problem querying the case
+ * database.
*/
public synchronized List findFiles(String fileName) throws TskCoreException {
- List result = new ArrayList<>();
-
- if (tskCase == null) {
- throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles.exception.msg"));
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
}
- List dataSources = tskCase.getRootObjects();
+ List result = new ArrayList<>();
+ List dataSources = caseDb.getRootObjects();
for (Content dataSource : dataSources) {
result.addAll(findFiles(dataSource, fileName));
}
@@ -104,290 +138,221 @@ public class FileManager implements Closeable {
}
/**
- * Finds a set of localFiles that meets the name criteria in all data
- * sources in the current case.
+ * Finds all files and directories with a given file name and parent file or
+ * directory name. The name searches are for full or partial matches and are
+ * case insensitive (a case insensitive SQL LIKE clause is used to query the
+ * case database).
*
- * @param fileName Pattern of the name of the file or directory to match
- * (case insensitive, used in LIKE SQL statement).
- * @param dirName Pattern of the name of the parent directory to use as the
- * root of the search (case insensitive, used in LIKE SQL
- * statement).
+ * @param fileName The full or partial file name.
+ * @param parentName The full or partial parent file or directory name.
*
- * @return a list of AbstractFile for localFiles/directories whose name
- * matches fileName and whose parent directory contains dirName.
+ * @return The matching files and directories.
+ *
+ * @throws TskCoreException if there is a problem querying the case
+ * database.
*/
- public synchronized List findFiles(String fileName, String dirName) throws TskCoreException {
- List result = new ArrayList<>();
-
- if (tskCase == null) {
- throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles2.exception.msg"));
+ public synchronized List findFiles(String fileName, String parentName) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
}
- List dataSources = tskCase.getRootObjects();
+ List result = new ArrayList<>();
+ List dataSources = caseDb.getRootObjects();
for (Content dataSource : dataSources) {
- result.addAll(findFiles(dataSource, fileName, dirName));
+ result.addAll(findFiles(dataSource, fileName, parentName));
}
return result;
}
/**
- * Finds a set of localFiles that meets the name criteria in all data
- * sources in the current case.
+ * Finds all files and directories with a given file name and parent file or
+ * directory. The name search is for full or partial matches and is case
+ * insensitive (a case insensitive SQL LIKE clause is used to query the case
+ * database).
*
- * @param fileName Pattern of the name of the file or directory to match
- * (case insensitive, used in LIKE SQL statement).
- * @param parentFile Object of root/parent directory to restrict search to.
+ * @param fileName The full or partial file name.
+ * @param parent The parent file or directory.
*
- * @return a list of AbstractFile for localFiles/directories whose name
- * matches fileName and that were inside a directory described by
- * parentFsContent.
+ * @return The matching files and directories.
+ *
+ * @throws TskCoreException if there is a problem querying the case
+ * database.
*/
- public synchronized List findFiles(String fileName, AbstractFile parentFile) throws TskCoreException {
- List result = new ArrayList<>();
-
- if (tskCase == null) {
- throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles3.exception.msg"));
+ public synchronized List findFiles(String fileName, AbstractFile parent) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
}
- List dataSources = tskCase.getRootObjects();
+ List result = new ArrayList<>();
+ List dataSources = caseDb.getRootObjects();
for (Content dataSource : dataSources) {
- result.addAll(findFiles(dataSource, fileName, parentFile));
+ result.addAll(findFiles(dataSource, fileName, parent));
}
return result;
}
/**
- * Finds a set of localFiles that meets the name criteria.
+ * Finds all files and directories with a given file name in a given data
+ * source (image, local/logical files set, etc.). The name search is for
+ * full or partial matches and is case insensitive (a case insensitive SQL
+ * LIKE clause is used to query the case database).
*
- * @param dataSource Root data source to limit search results to (Image,
- * VirtualDirectory, etc.).
- * @param fileName Pattern of the name of the file or directory to match
- * (case insensitive, used in LIKE SQL statement).
+ * @param dataSource The data source.
+ * @param fileName The full or partial file name.
*
- * @return a list of AbstractFile for localFiles/directories whose name
- * matches the given fileName
+ * @return The matching files and directories.
+ *
+ * @throws TskCoreException if there is a problem querying the case
+ * database.
*/
public synchronized List findFiles(Content dataSource, String fileName) throws TskCoreException {
- if (tskCase == null) {
- throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles.exception.msg"));
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
}
- return tskCase.findFiles(dataSource, fileName);
+ return caseDb.findFiles(dataSource, fileName);
}
/**
- * Finds a set of localFiles that meets the name criteria.
+ * Finds all files and directories with a given file name and parent file or
+ * directory name in a given data source (image, local/logical files set,
+ * etc.). The name searches are for full or partial matches and are case
+ * insensitive (a case insensitive SQL LIKE clause is used to query the case
+ * database).
*
- * @param dataSource Root data source to limit search results to (Image,
- * VirtualDirectory, etc.).
- * @param fileName Pattern of the name of the file or directory to match
- * (case insensitive, used in LIKE SQL statement).
- * @param dirName Pattern of the name of the parent directory to use as
- * the root of the search (case insensitive, used in LIKE
- * SQL statement).
+ * @param dataSource The data source.
+ * @param fileName The full or partial file name.
+ * @param parentName The full or partial parent file or directory name.
*
- * @return a list of AbstractFile for localFiles/directories whose name
- * matches fileName and whose parent directory contains dirName.
+ * @return The matching files and directories.
+ *
+ * @throws TskCoreException if there is a problem querying the case
+ * database.
*/
- public synchronized List findFiles(Content dataSource, String fileName, String dirName) throws TskCoreException {
- if (tskCase == null) {
- throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles2.exception.msg"));
+ public synchronized List findFiles(Content dataSource, String fileName, String parentName) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
}
- return tskCase.findFiles(dataSource, fileName, dirName);
+ return caseDb.findFiles(dataSource, fileName, parentName);
}
/**
- * Finds a set of localFiles that meets the name criteria.
+ * Finds all files and directories with a given file name and given parent
+ * file or directory in a given data source (image, local/logical files set,
+ * etc.). The name search is for full or partial matches and is case
+ * insensitive (a case insensitive SQL LIKE clause is used to query the case
+ * database).
*
- * @param dataSource Root data source to limit search results to (Image,
- * VirtualDirectory, etc.).
- * @param fileName Pattern of the name of the file or directory to match
- * (case insensitive, used in LIKE SQL statement).
- * @param parentFile Object of root/parent directory to restrict search to.
+ * @param dataSource The data source.
+ * @param fileName The full or partial file name.
+ * @param parent The parent file or directory.
*
- * @return a list of AbstractFile for localFiles/directories whose name
- * matches fileName and that were inside a directory described by
- * parentFsContent.
+ * @return The matching files and directories.
+ *
+ * @throws TskCoreException if there is a problem querying the case
+ * database.
*/
- public synchronized List findFiles(Content dataSource, String fileName, AbstractFile parentFile) throws TskCoreException {
- if (tskCase == null) {
- throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles3.exception.msg"));
+ public synchronized List findFiles(Content dataSource, String fileName, AbstractFile parent) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
}
- return findFiles(dataSource, fileName, parentFile.getName());
+ return findFiles(dataSource, fileName, parent.getName());
}
/**
- * @param dataSource data source Content (Image, parent-less
- * VirtualDirectory) where to find localFiles
- * @param filePath The full path to the file(s) of interest. This can
- * optionally include the image and volume names.
+ * Finds all files and directories with a given file name and path in a
+ * given data source (image, local/logical files set, etc.). The name search
+ * is for full or partial matches and is case insensitive (a case
+ * insensitive SQL LIKE clause is used to query the case database). Any path
+ * components at the volume level and above are removed for the search.
*
- * @return a list of AbstractFile that have the given file path.
+ * @param dataSource The data source.
+ * @param fileName The full or partial file name.
+ * @param filePath The file path (path components volume at the volume
+ * level or above will be removed).
+ *
+ * @return The matching files and directories.
+ *
+ * @throws TskCoreException if there is a problem querying the case
+ * database.
*/
public synchronized List openFiles(Content dataSource, String filePath) throws TskCoreException {
- if (tskCase == null) {
- throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.openFiles.exception.msg"));
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
}
- return tskCase.openFiles(dataSource, filePath);
+ return caseDb.openFiles(dataSource, filePath);
}
/**
- * Creates a derived file, adds it to the database and returns it.
+ * Adds a derived file to the case.
*
- * @param fileName file name the derived file
- * @param localPath local path of the derived file, including the file
- * name. The path is relative to the case folder.
- * @param size size of the derived file in bytes
- * @param ctime
- * @param crtime
- * @param atime
- * @param mtime
- * @param isFile whether a file or directory, true if a file
- * @param parentFile the parent file object this the new file was
- * derived from, either a fs file or parent derived
- * file/dikr\\r
- * @param rederiveDetails details needed to re-derive file (will be specific
- * to the derivation method), currently unused
- * @param toolName name of derivation method/tool, currently unused
- * @param toolVersion version of derivation method/tool, currently
- * unused
- * @param otherDetails details of derivation method/tool, currently
- * unused
+ * @param fileName The name of the file.
+ * @param localPath The local path of the file, relative to the case
+ * folder and including the file name.
+ * @param size The size of the file in bytes.
+ * @param ctime The change time of the file.
+ * @param crtime The create time of the file
+ * @param atime The accessed time of the file.
+ * @param mtime The modified time of the file.
+ * @param isFile True if a file, false if a directory.
+ * @param parentFile The parent file from which the file was derived.
+ * @param rederiveDetails The details needed to re-derive file (will be
+ * specific to the derivation method), currently
+ * unused.
+ * @param toolName The name of the derivation method or tool,
+ * currently unused.
+ * @param toolVersion The version of the derivation method or tool,
+ * currently unused.
+ * @param otherDetails Other details of the derivation method or tool,
+ * currently unused.
*
- * @return newly created derived file object added to the database
- *
- * @throws TskCoreException exception thrown if the object creation failed
- * due to a critical system error or of the file
- * manager has already been closed
+ * @return A DerivedFile object representing the derived file.
*
+ * @throws TskCoreException if there is a problem adding the file to the
+ * case database.
*/
- public synchronized DerivedFile addDerivedFile(String fileName, String localPath, long size,
+ public synchronized DerivedFile addDerivedFile(String fileName,
+ String localPath,
+ long size,
long ctime, long crtime, long atime, long mtime,
- boolean isFile, AbstractFile parentFile,
+ boolean isFile,
+ AbstractFile parentFile,
String rederiveDetails, String toolName, String toolVersion, String otherDetails) throws TskCoreException {
-
- if (tskCase == null) {
- throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.addDerivedFile.exception.msg"));
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
}
-
- return tskCase.addDerivedFile(fileName, localPath, size,
+ return caseDb.addDerivedFile(fileName, localPath, size,
ctime, crtime, atime, mtime,
isFile, parentFile, rederiveDetails, toolName, toolVersion, otherDetails);
}
/**
- * Adds a carved file to the VirtualDirectory '$CarvedFiles' in the volume
- * or image given by systemId.
+ * Adds a carving result to the case database.
*
- * @param carvedFileName the name of the carved file (containing appropriate
- * extension)
- * @param carvedFileSize size of the carved file to add
- * @param systemId the ID of the parent volume or file system
- * @param sectors a list of SectorGroups giving this sectors that
- * make up this carved file.
+ * @param carvingResult The carving result (a set of carved files and their
+ * parent) to be added.
*
- * @throws TskCoreException exception thrown when critical tsk error
- * occurred and carved file could not be added
+ * @return A list of LayoutFile representations of the carved files.
+ *
+ * @throws TskCoreException If there is a problem completing a case database
+ * operation.
*/
- public synchronized LayoutFile addCarvedFile(String carvedFileName, long carvedFileSize,
- long systemId, List sectors) throws TskCoreException {
-
- if (tskCase == null) {
- throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.addCarvedFile.exception.msg"));
+ public synchronized List addCarvedFiles(CarvingResult carvingResult) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
}
-
- return tskCase.addCarvedFile(carvedFileName, carvedFileSize, systemId, sectors);
+ return caseDb.addCarvedFiles(carvingResult);
}
-
+
/**
- * Adds a collection of carved localFiles to the VirtualDirectory
- * '$CarvedFiles' in the volume or image given by systemId. Creates
- * $CarvedFiles if it does not exist already.
- *
- * @param filesToAdd a list of CarvedFileContainer localFiles to add as
- * carved localFiles
- *
- * @return List This is a list of the localFiles added to the
- * database
- *
- * @throws org.sleuthkit.datamodel.TskCoreException
- */
- public List addCarvedFiles(List filesToAdd) throws TskCoreException {
- if (tskCase == null) {
- throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.addCarvedFile.exception.msg"));
- } else {
- return tskCase.addCarvedFiles(filesToAdd);
- }
- }
-
- /**
- *
- * Interface for receiving notifications on folders being added via a
- * callback
+ * Interface for receiving a notification for each file or directory added
+ * to the case database by a FileManager add files operation.
*/
public interface FileAddProgressUpdater {
/**
- * Called when new folders has been added
+ * Called after a file or directory is added to the case database.
*
- * @param newFile the file/folder added to the Case
+ * @param An AbstractFile represeting the added file or directory.
*/
- public void fileAdded(AbstractFile newFile);
- }
-
- /**
- * Add a set of local/logical localFiles and dirs.
- *
- * @param localAbsPaths list of absolute paths to local localFiles and
- * dirs
- * @param addProgressUpdater notifier to receive progress notifications on
- * folders added, or null if not used
- *
- * @return file set root VirtualDirectory contained containing all
- * AbstractFile objects added
- *
- * @throws TskCoreException exception thrown if the object creation failed
- * due to a critical system error or of the file
- * manager has already been closed. There is no
- * "revert" logic if one of the additions fails.
- * The addition stops with the first error
- * encountered.
- */
- public synchronized VirtualDirectory addLocalFilesDirs(List localAbsPaths, FileAddProgressUpdater addProgressUpdater) throws TskCoreException {
- List rootsToAdd;
- try {
- rootsToAdd = getFilesAndDirectories(localAbsPaths);
- } catch (TskDataException ex) {
- throw new TskCoreException(ex.getLocalizedMessage(), ex);
- }
-
- CaseDbTransaction trans = tskCase.beginTransaction();
- // make a virtual top-level directory for this set of localFiles/dirs
- final VirtualDirectory fileSetRootDir = addLocalFileSetRootDir(trans);
-
- try {
- // recursively add each item in the set
- for (java.io.File localRootToAdd : rootsToAdd) {
- AbstractFile localFileAdded = addLocalDirInt(trans, fileSetRootDir, localRootToAdd, addProgressUpdater);
-
- if (localFileAdded == null) {
- String msg = NbBundle
- .getMessage(this.getClass(), "FileManager.addLocalFilesDirs.exception.cantAdd.msg",
- localRootToAdd.getAbsolutePath());
- logger.log(Level.SEVERE, msg);
- throw new TskCoreException(msg);
- } else {
- //added.add(localFileAdded);
- //send new content event
- //for now reusing ingest events, in future this will be replaced by datamodel / observer sending out events
- // @@@ Is this the right place for this? A directory tree refresh will be triggered, so this may be creating a race condition
- // since the transaction is not yet committed.
- IngestServices.getInstance().fireModuleContentEvent(new ModuleContentEvent(localFileAdded));
- }
- }
-
- trans.commit();
- } catch (TskCoreException ex) {
- trans.rollback();
- }
- return fileSetRootDir;
+ void fileAdded(AbstractFile newFile);
}
/**
@@ -419,20 +384,27 @@ public class FileManager implements Closeable {
* directory that does not exist or cannot be read.
*/
public synchronized LocalFilesDataSource addLocalFilesDataSource(String deviceId, String rootVirtualDirectoryName, String timeZone, List localFilePaths, FileAddProgressUpdater progressUpdater) throws TskCoreException, TskDataException {
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
+ }
List localFiles = getFilesAndDirectories(localFilePaths);
CaseDbTransaction trans = null;
try {
String rootDirectoryName = rootVirtualDirectoryName;
- int newLocalFilesSetCount = curNumFileSets + 1;
- if (rootVirtualDirectoryName.isEmpty()) {
- rootDirectoryName = VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX + newLocalFilesSetCount;
+ if (rootDirectoryName.isEmpty()) {
+ rootDirectoryName = generateFilesDataSourceName(caseDb);
}
- trans = tskCase.beginTransaction();
- LocalFilesDataSource dataSource = tskCase.addLocalFilesDataSource(deviceId, rootDirectoryName, timeZone, trans);
+
+ /*
+ * Add the root virtual directory and its local/logical file
+ * children to the case database.
+ */
+ trans = caseDb.beginTransaction();
+ LocalFilesDataSource dataSource = caseDb.addLocalFilesDataSource(deviceId, rootDirectoryName, timeZone, trans);
VirtualDirectory rootDirectory = dataSource.getRootDirectory();
List filesAdded = new ArrayList<>();
for (java.io.File localFile : localFiles) {
- AbstractFile fileAdded = addLocalDirInt(trans, rootDirectory, localFile, progressUpdater);
+ AbstractFile fileAdded = addLocalFile(trans, rootDirectory, localFile, progressUpdater);
if (null != fileAdded) {
filesAdded.add(fileAdded);
} else {
@@ -440,13 +412,16 @@ public class FileManager implements Closeable {
}
}
trans.commit();
- if (rootVirtualDirectoryName.isEmpty()) {
- curNumFileSets = newLocalFilesSetCount;
- }
+
+ /*
+ * Publish content added events for the added files and directories.
+ */
for (AbstractFile fileAdded : filesAdded) {
IngestServices.getInstance().fireModuleContentEvent(new ModuleContentEvent(fileAdded));
}
+
return dataSource;
+
} catch (TskCoreException ex) {
if (null != trans) {
trans.rollback();
@@ -455,6 +430,34 @@ public class FileManager implements Closeable {
}
}
+ /**
+ * Generates a name for the root virtual directory for the data source.
+ *
+ * NOTE: Although this method is guarded by the file manager's monitor,
+ * there is currently a minimal chance of default name duplication for
+ * multi-user cases with multiple FileManagers running on different nodes.
+ *
+ * @return A default name for a local/logical files data source of the form:
+ * LogicalFileSet[N].
+ *
+ * @throws TskCoreException If there is a problem querying the case
+ * database.
+ */
+ private static synchronized String generateFilesDataSourceName(SleuthkitCase caseDb) throws TskCoreException {
+ int localFileDataSourcesCounter = 0;
+ try {
+ List localFileDataSources = caseDb.getVirtualDirectoryRoots();
+ for (VirtualDirectory vd : localFileDataSources) {
+ if (vd.getName().startsWith(VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX)) {
+ ++localFileDataSourcesCounter;
+ }
+ }
+ return VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX + (localFileDataSourcesCounter + 1);
+ } catch (TskCoreException ex) {
+ throw new TskCoreException("Error querying for existing local file data sources with defualt names", ex);
+ }
+ }
+
/**
* Converts a list of local/logical file and/or directory paths to a list of
* file objects.
@@ -472,7 +475,7 @@ public class FileManager implements Closeable {
for (String path : localFilePaths) {
java.io.File localFile = new java.io.File(path);
if (!localFile.exists() || !localFile.canRead()) {
- throw new TskDataException(NbBundle.getMessage(this.getClass(), "FileManager.addLocalFilesDirs.exception.notReadable.msg", localFile.getAbsolutePath()));
+ throw new TskDataException(String.format("File at %s does not exist or cannot be read", localFile.getAbsolutePath()));
}
localFiles.add(localFile);
}
@@ -480,130 +483,141 @@ public class FileManager implements Closeable {
}
/**
- * Adds a new virtual directory root object with FileSet X name and
- * consecutive sequence number characteristic to every add operation
- *
- * @return the virtual dir root container created
- *
- * @throws TskCoreException
- */
- private VirtualDirectory addLocalFileSetRootDir(CaseDbTransaction trans) throws TskCoreException {
-
- VirtualDirectory created = null;
-
- int newFileSetCount = curNumFileSets + 1;
- final String fileSetName = VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX + newFileSetCount;
-
- try {
- created = tskCase.addVirtualDirectory(0, fileSetName, trans);
- curNumFileSets = newFileSetCount;
- } catch (TskCoreException ex) {
- String msg = NbBundle
- .getMessage(this.getClass(), "FileManager.addLocalFileSetRootDir.exception.errCreateDir.msg",
- fileSetName);
- logger.log(Level.SEVERE, msg, ex);
- throw new TskCoreException(msg, ex);
- }
-
- return created;
- }
-
- /**
- * Helper (internal) method to recursively add contents of a folder. Node
- * passed in can be a file or directory. Children of directories are added.
+ * Adds a file or directory of logical/local files data source to the case
+ * database, recursively adding the contents of directories.
*
* @param trans A case database transaction.
- * @param parentVd Dir that is the parent of localFile
- * @param localFile File/Dir that we are adding
+ * @param parentDirectory The root virtual direcotry of the data source.
+ * @param localFile The local/logical file or directory.
* @param addProgressUpdater notifier to receive progress notifications on
* folders added, or null if not used
*
* @returns File object of file added or new virtualdirectory for the
* directory.
- * @throws TskCoreException
+ * @param progressUpdater Called after each file/directory is added to
+ * the case database.
+ *
+ * @return An AbstractFile representation of the local/logical file.
+ *
+ * @throws TskCoreException If there is a problem completing a database
+ * operation.
*/
- private AbstractFile addLocalDirInt(CaseDbTransaction trans, VirtualDirectory parentVd,
- java.io.File localFile, FileAddProgressUpdater addProgressUpdater) throws TskCoreException {
-
- if (tskCase == null) {
- throw new TskCoreException(
- NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt.exception.closed.msg"));
- }
-
- //final String localName = localDir.getName();
- if (!localFile.exists()) {
- throw new TskCoreException(
- NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt.exception.doesntExist.msg",
- localFile.getAbsolutePath()));
- }
- if (!localFile.canRead()) {
- throw new TskCoreException(
- NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt.exception.notReadable.msg",
- localFile.getAbsolutePath()));
- }
-
+ private AbstractFile addLocalFile(CaseDbTransaction trans, VirtualDirectory parentDirectory, java.io.File localFile, FileAddProgressUpdater progressUpdater) throws TskCoreException {
if (localFile.isDirectory()) {
- //create virtual folder (we don't have a notion of a 'local folder')
- final VirtualDirectory childVd = tskCase.addVirtualDirectory(parentVd.getId(), localFile.getName(), trans);
- if (childVd != null && addProgressUpdater != null) {
- addProgressUpdater.fileAdded(childVd);
- }
- //add children recursively
- final java.io.File[] childrenFiles = localFile.listFiles();
- if (childrenFiles != null) {
- for (java.io.File childFile : childrenFiles) {
- addLocalDirInt(trans, childVd, childFile, addProgressUpdater);
+ /*
+ * Add the directory as a virtual directory.
+ */
+ VirtualDirectory virtualDirectory = caseDb.addVirtualDirectory(parentDirectory.getId(), localFile.getName(), trans);
+ progressUpdater.fileAdded(virtualDirectory);
+
+ /*
+ * Add its children, if any.
+ */
+ final java.io.File[] childFiles = localFile.listFiles();
+ if (childFiles != null && childFiles.length > 0) {
+ for (java.io.File childFile : childFiles) {
+ addLocalFile(trans, virtualDirectory, childFile, progressUpdater);
}
}
- return childVd;
+
+ return virtualDirectory;
} else {
- //add leaf file, base case
- return this.addLocalFileInt(parentVd, localFile, trans);
+ return caseDb.addLocalFile(localFile.getName(), localFile.getAbsolutePath(), localFile.length(),
+ 0, 0, 0, 0,
+ localFile.isFile(), parentDirectory, trans);
}
}
/**
- * Adds a single local/logical file to the case. Adds it to the database.
- * Does not refresh the views of data. Assumes that the local file exists
- * and can be read. This checking is done by addLocalDirInt().
+ * Closes the file manager.
*
- * @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
- *
- * @throws TskCoreException exception thrown if the object creation failed
- * due to a critical system error or of the file
- * manager has already been closed
+ * @throws IOException If there is a problem closing the file manager.
*/
- private synchronized LocalFile addLocalFileInt(AbstractFile parentFile, java.io.File localFile, CaseDbTransaction trans) throws TskCoreException {
-
- if (tskCase == null) {
- throw new TskCoreException(
- NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt2.exception.closed.msg"));
- }
-
- long size = localFile.length();
- boolean isFile = localFile.isFile();
-
- long ctime = 0;
- long crtime = 0;
- long atime = 0;
- long mtime = 0;
-
- String fileName = localFile.getName();
-
- LocalFile lf = tskCase.addLocalFile(fileName, localFile.getAbsolutePath(), size,
- ctime, crtime, atime, mtime,
- isFile, parentFile, trans);
-
- return lf;
- }
-
@Override
public synchronized void close() throws IOException {
- tskCase = null;
+ caseDb = null;
}
+
+ /**
+ * Adds a set of local/logical files and/or directories to the case database
+ * as data source.
+ *
+ * @param localFilePaths A list of local/logical file and/or directory
+ * localFilePaths.
+ * @param progressUpdater Called after each file/directory is added to the
+ * case database.
+ *
+ * @return The root virtual directory for the local/logical files data
+ * source.
+ *
+ * @throws TskCoreException If any of the local file paths is for a file or
+ * directory that does not exist or cannot be read,
+ * or there is a problem completing a database
+ * operation.
+ * @deprecated Use addLocalFilesDataSource instead.
+ */
+ @Deprecated
+ public synchronized VirtualDirectory addLocalFilesDirs(List localFilePaths, FileAddProgressUpdater progressUpdater) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
+ }
+ try {
+ return addLocalFilesDataSource("", "", "", localFilePaths, progressUpdater).getRootDirectory();
+ } catch (TskDataException ex) {
+ throw new TskCoreException(ex.getLocalizedMessage(), ex);
+ }
+ }
+
+ /**
+ * Adds a carved file to the '$CarvedFiles' virtual directory of a data
+ * source, volume or file system.
+ *
+ * @param fileName The name of the file.
+ * @param fileSize The size of the file.
+ * @param parentObjId The object id of the parent data source, volume or
+ * file system.
+ * @param layout A list of the offsets and sizes that gives the layout
+ * of the file within its parent.
+ *
+ * @return A LayoutFile object representing the carved file.
+ *
+ * @throws TskCoreException if there is a problem adding the file to the
+ * case database.
+ * @deprecated Use List addCarvedFiles(CarvingResult
+ * carvingResult instead.
+ */
+ @Deprecated
+ public synchronized LayoutFile addCarvedFile(String fileName, long fileSize, long parentObjId, List layout) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
+ }
+ Content parent = caseDb.getContentById(parentObjId);
+ List carvedFiles = new ArrayList<>();
+ carvedFiles.add(new CarvingResult.CarvedFile(fileName, fileSize, layout));
+ List layoutFiles = caseDb.addCarvedFiles(new CarvingResult(parent, carvedFiles));
+ return layoutFiles.get(0);
+ }
+
+ /**
+ * Adds a collection of carved files to the '$CarvedFiles' virtual directory
+ * of a data source, volume or file system.
+ *
+ * @param A collection of CarvedFileContainer objects, one per carved file,
+ * all of which must have the same parent object id.
+ *
+ * @return A collection of LayoutFile object representing the carved files.
+ *
+ * @throws TskCoreException if there is a problem adding the files to the
+ * case database.
+ * @deprecated Use List addCarvedFiles(CarvingResult
+ * carvingResult instead.
+ */
+ @Deprecated
+ public synchronized List addCarvedFiles(List filesToAdd) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("File manager has been closed");
+ }
+ return caseDb.addCarvedFiles(filesToAdd);
+ }
+
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java
index 880bc8008e..a8d11d184c 100755
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java
@@ -1,19 +1,18 @@
/*
*
* Autopsy Forensic Browser
- *
- * Copyright 2012-2015 Basis Technology Corp.
- *
+ *
+ * Copyright 2011-2016 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
* Copyright 2012 42six Solutions.
* Contact: aebadirad 42six com
- * Project Contact/Architect: 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.
@@ -31,7 +30,8 @@ import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.datamodel.SleuthkitCase;
/**
- * A class to manage various services.
+ * A collection of case-level services (e.g., file manager, tags manager,
+ * keyword search, blackboard).
*/
public class Services implements Closeable {
@@ -41,36 +41,67 @@ public class Services implements Closeable {
private final KeywordSearchService keywordSearchService;
private final Blackboard blackboard;
- public Services(SleuthkitCase tskCase) {
- fileManager = new FileManager(tskCase);
+ /**
+ * Constructs a collection of case-level services (e.g., file manager, tags
+ * manager, keyword search, blackboard).
+ *
+ * @param caseDb The case database for the current case.
+ */
+ public Services(SleuthkitCase caseDb) {
+ fileManager = new FileManager(caseDb);
services.add(fileManager);
- tagsManager = new TagsManager(tskCase);
+ tagsManager = new TagsManager(caseDb);
services.add(tagsManager);
keywordSearchService = Lookup.getDefault().lookup(KeywordSearchService.class);
services.add(keywordSearchService);
-
- blackboard = new Blackboard();
+
+ blackboard = new Blackboard(caseDb);
services.add(blackboard);
}
+ /**
+ * Gets the file manager service for the current case.
+ *
+ * @return The file manager service for the current case.
+ */
public FileManager getFileManager() {
return fileManager;
}
+ /**
+ * Gets the tags manager service for the current case.
+ *
+ * @return The tags manager service for the current case.
+ */
public TagsManager getTagsManager() {
return tagsManager;
}
+ /**
+ * Gets the keyword search service for the current case.
+ *
+ * @return The keyword search service for the current case.
+ */
public KeywordSearchService getKeywordSearchService() {
return keywordSearchService;
}
-
+
+ /**
+ * Gets the blackboard service for the current case.
+ *
+ * @return The blackboard service for the current case.
+ */
public Blackboard getBlackboard() {
return blackboard;
}
+ /**
+ * Closes the services for the current case.
+ *
+ * @throws IOException if there is a problem closing the services.
+ */
@Override
public void close() throws IOException {
for (Closeable service : services) {
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java
index 53d6229688..e8d61bdeba 100755
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
- * Copyright 2011-16 Basis Technology Corp.
+ * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier sleuthkit org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -45,7 +45,7 @@ public class TagsManager implements Closeable {
private static final Logger logger = Logger.getLogger(TagsManager.class.getName());
private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS
private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS
- private final SleuthkitCase caseDb;
+ private SleuthkitCase caseDb;
private final HashMap uniqueTagNames = new HashMap<>();
private boolean tagNamesLoaded = false;
@@ -53,8 +53,8 @@ public class TagsManager implements Closeable {
* Constructs a per case Autopsy service that manages the creation,
* updating, and deletion of tags applied to content and blackboard
* artifacts by users.
- *
- * @param caseDb The case database for the current case.
+ *
+ * @param caseDb The case database.
*/
TagsManager(SleuthkitCase caseDb) {
this.caseDb = caseDb;
@@ -70,6 +70,9 @@ public class TagsManager implements Closeable {
* database.
*/
public synchronized List getAllTagNames() throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
return caseDb.getAllTagNames();
}
@@ -84,6 +87,9 @@ public class TagsManager implements Closeable {
* database.
*/
public synchronized List getTagNamesInUse() throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
return caseDb.getTagNamesInUse();
}
@@ -114,6 +120,9 @@ public class TagsManager implements Closeable {
* to the case database.
*/
public TagName addTagName(String displayName) throws TagNameAlreadyExistsException, TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
return addTagName(displayName, "", TagName.HTML_COLOR.NONE);
}
@@ -132,6 +141,9 @@ public class TagsManager implements Closeable {
* to the case database.
*/
public TagName addTagName(String displayName, String description) throws TagNameAlreadyExistsException, TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
return addTagName(displayName, description, TagName.HTML_COLOR.NONE);
}
@@ -151,6 +163,9 @@ public class TagsManager implements Closeable {
* to the case database.
*/
public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TagNameAlreadyExistsException, TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
if (uniqueTagNames.containsKey(displayName)) {
throw new TagNameAlreadyExistsException();
@@ -182,6 +197,9 @@ public class TagsManager implements Closeable {
* database.
*/
public ContentTag addContentTag(Content content, TagName tagName) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
return addContentTag(content, tagName, "", -1, -1);
}
@@ -198,6 +216,9 @@ public class TagsManager implements Closeable {
* database.
*/
public ContentTag addContentTag(Content content, TagName tagName, String comment) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
return addContentTag(content, tagName, comment, -1, -1);
}
@@ -218,10 +239,17 @@ public class TagsManager implements Closeable {
* the case database.
*/
public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws IllegalArgumentException, TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
ContentTag tag;
synchronized (this) {
lazyLoadExistingTagNames();
+ if (null == comment) {
+ throw new IllegalArgumentException("Passed null comment argument");
+ }
+
if (beginByteOffset >= 0 && endByteOffset >= 1) {
if (beginByteOffset > content.getSize() - 1) {
throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(),
@@ -261,6 +289,9 @@ public class TagsManager implements Closeable {
* case database.
*/
public void deleteContentTag(ContentTag tag) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
synchronized (this) {
lazyLoadExistingTagNames();
caseDb.deleteContentTag(tag);
@@ -282,6 +313,9 @@ public class TagsManager implements Closeable {
* case database.
*/
public synchronized List getAllContentTags() throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
return caseDb.getAllContentTags();
}
@@ -297,6 +331,9 @@ public class TagsManager implements Closeable {
* the case database.
*/
public synchronized long getContentTagsCountByTagName(TagName tagName) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
return caseDb.getContentTagsCountByTagName(tagName);
}
@@ -312,6 +349,9 @@ public class TagsManager implements Closeable {
* case database.
*/
public synchronized ContentTag getContentTagByTagID(long tagID) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
return caseDb.getContentTagByID(tagID);
}
@@ -328,6 +368,9 @@ public class TagsManager implements Closeable {
* case database.
*/
public synchronized List getContentTagsByTagName(TagName tagName) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
return caseDb.getContentTagsByTagName(tagName);
}
@@ -344,6 +387,9 @@ public class TagsManager implements Closeable {
* case database.
*/
public synchronized List getContentTagsByContent(Content content) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
return caseDb.getContentTagsByContent(content);
}
@@ -361,6 +407,9 @@ public class TagsManager implements Closeable {
* database.
*/
public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
return addBlackboardArtifactTag(artifact, tagName, "");
}
@@ -378,9 +427,15 @@ public class TagsManager implements Closeable {
* database.
*/
public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
BlackboardArtifactTag tag;
synchronized (this) {
lazyLoadExistingTagNames();
+ if (null == comment) {
+ throw new IllegalArgumentException("Passed null comment argument");
+ }
tag = caseDb.addBlackboardArtifactTag(artifact, tagName, comment);
}
@@ -401,6 +456,9 @@ public class TagsManager implements Closeable {
* case database.
*/
public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
synchronized (this) {
lazyLoadExistingTagNames();
caseDb.deleteBlackboardArtifactTag(tag);
@@ -422,6 +480,9 @@ public class TagsManager implements Closeable {
* case database.
*/
public synchronized List getAllBlackboardArtifactTags() throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
return caseDb.getAllBlackboardArtifactTags();
}
@@ -438,6 +499,9 @@ public class TagsManager implements Closeable {
* the case database.
*/
public synchronized long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
return caseDb.getBlackboardArtifactTagsCountByTagName(tagName);
}
@@ -453,6 +517,9 @@ public class TagsManager implements Closeable {
* case database.
*/
public synchronized BlackboardArtifactTag getBlackboardArtifactTagByTagID(long tagID) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
return caseDb.getBlackboardArtifactTagByID(tagID);
}
@@ -469,6 +536,9 @@ public class TagsManager implements Closeable {
* case database.
*/
public synchronized List getBlackboardArtifactTagsByTagName(TagName tagName) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
return caseDb.getBlackboardArtifactTagsByTagName(tagName);
}
@@ -485,16 +555,25 @@ public class TagsManager implements Closeable {
* case database.
*/
public synchronized List getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact) throws TskCoreException {
+ if (null == caseDb) {
+ throw new TskCoreException("Tags manager has been closed");
+ }
lazyLoadExistingTagNames();
return caseDb.getBlackboardArtifactTagsByArtifact(artifact);
}
/**
- * Saves the avaialble tag names to secondary storage.
+ * Closes the tags manager, saving the avaialble tag names to secondary
+ * storage.
+ *
+ * @throws IOException If there is a problem closing the tags manager.
+ * @deprecated Tags manager clients should not close the tags manager.
*/
@Override
+ @Deprecated
public synchronized void close() throws IOException {
saveTagNamesToTagsSettings();
+ caseDb = null;
}
/**
diff --git a/Core/src/org/sleuthkit/autopsy/core/layer.xml b/Core/src/org/sleuthkit/autopsy/core/layer.xml
index 8e71419b45..cd72a061f9 100644
--- a/Core/src/org/sleuthkit/autopsy/core/layer.xml
+++ b/Core/src/org/sleuthkit/autopsy/core/layer.xml
@@ -5,12 +5,12 @@
-
-
-
-
+
+
+
+
@@ -39,7 +39,7 @@
Actions
====================================================== -->
-
+
@@ -145,24 +145,25 @@
-
+
+
-
+
-
+
-
+
-
+
-
+
@@ -170,7 +171,7 @@
-
+
@@ -182,7 +183,7 @@
-
+
@@ -361,7 +362,8 @@
-
+
+
@@ -385,11 +387,11 @@
-
+
-
+
@@ -404,10 +406,10 @@
====================================================== -->
-
+
-
+
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.form
index 6c2a6cc2f6..0a6ea4b4a6 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.form
@@ -3,7 +3,7 @@
diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/KnownStatusSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/KnownStatusSearchPanel.java
index 291ced32e7..69ec869cfa 100644
--- a/Core/src/org/sleuthkit/autopsy/filesearch/KnownStatusSearchPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/filesearch/KnownStatusSearchPanel.java
@@ -17,13 +17,15 @@
* limitations under the License.
*/
-/*
+ /*
* KnownStatusSearchPanel.java
*
* Created on Oct 19, 2011, 11:45:44 AM
*/
package org.sleuthkit.autopsy.filesearch;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
import javax.swing.JCheckBox;
/**
@@ -32,6 +34,8 @@ import javax.swing.JCheckBox;
*/
class KnownStatusSearchPanel extends javax.swing.JPanel {
+ private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
+
/**
* Creates new form KnownStatusSearchPanel
*/
@@ -55,7 +59,7 @@ class KnownStatusSearchPanel extends javax.swing.JPanel {
JCheckBox getUnknownOptionCheckBox() {
return unknownOptionCheckBox;
}
-
+
private void setComponentsEnabled() {
boolean enabled = this.knownCheckBox.isSelected();
this.unknownOptionCheckBox.setEnabled(enabled);
@@ -63,6 +67,20 @@ class KnownStatusSearchPanel extends javax.swing.JPanel {
this.knownBadOptionCheckBox.setEnabled(enabled);
}
+ @Override
+ public void addPropertyChangeListener(PropertyChangeListener pcl) {
+ pcs.addPropertyChangeListener(pcl);
+ }
+
+ @Override
+ public void removePropertyChangeListener(PropertyChangeListener pcl) {
+ pcs.removePropertyChangeListener(pcl);
+ }
+
+ boolean isValidSearch() {
+ return this.unknownOptionCheckBox.isSelected() || this.knownBadOptionCheckBox.isSelected() || this.knownOptionCheckBox.isSelected();
+ }
+
/**
* 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
@@ -86,6 +104,11 @@ class KnownStatusSearchPanel extends javax.swing.JPanel {
unknownOptionCheckBox.setSelected(true);
unknownOptionCheckBox.setText(org.openide.util.NbBundle.getMessage(KnownStatusSearchPanel.class, "KnownStatusSearchPanel.unknownOptionCheckBox.text")); // NOI18N
+ unknownOptionCheckBox.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ unknownOptionCheckBoxActionPerformed(evt);
+ }
+ });
knownOptionCheckBox.setSelected(true);
knownOptionCheckBox.setText(org.openide.util.NbBundle.getMessage(KnownStatusSearchPanel.class, "KnownStatusSearchPanel.knownOptionCheckBox.text")); // NOI18N
@@ -97,6 +120,11 @@ class KnownStatusSearchPanel extends javax.swing.JPanel {
knownBadOptionCheckBox.setSelected(true);
knownBadOptionCheckBox.setText(org.openide.util.NbBundle.getMessage(KnownStatusSearchPanel.class, "KnownStatusSearchPanel.knownBadOptionCheckBox.text")); // NOI18N
+ knownBadOptionCheckBox.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ knownBadOptionCheckBoxActionPerformed(evt);
+ }
+ });
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
@@ -127,13 +155,22 @@ class KnownStatusSearchPanel extends javax.swing.JPanel {
}// //GEN-END:initComponents
private void knownOptionCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownOptionCheckBoxActionPerformed
- // TODO add your handling code here:
+ pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_knownOptionCheckBoxActionPerformed
private void knownCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownCheckBoxActionPerformed
setComponentsEnabled();
+ pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_knownCheckBoxActionPerformed
+ private void unknownOptionCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_unknownOptionCheckBoxActionPerformed
+ pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
+ }//GEN-LAST:event_unknownOptionCheckBoxActionPerformed
+
+ private void knownBadOptionCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownBadOptionCheckBoxActionPerformed
+ pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
+ }//GEN-LAST:event_knownBadOptionCheckBoxActionPerformed
+
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox knownBadOptionCheckBox;
private javax.swing.JCheckBox knownCheckBox;
diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java
index b119566299..4d3078fd46 100755
--- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java
+++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypeFilter.java
@@ -10,28 +10,28 @@ import java.awt.event.ActionListener;
/**
* Filter by mime type used in filter areas of file search by attribute.
*/
-class MimeTypeFilter extends AbstractFileSearchFilter {
+class MimeTypeFilter extends AbstractFileSearchFilter {
public MimeTypeFilter(MimeTypePanel component) {
super(component);
}
+
public MimeTypeFilter() {
this(new MimeTypePanel());
}
@Override
public boolean isEnabled() {
- return this.getComponent().isSelected() &&
- !this.getComponent().getMimeTypesSelected().isEmpty();
+ return this.getComponent().isSelected();
}
@Override
public String getPredicate() throws FilterValidationException {
String predicate = "";
- for(String mimeType : this.getComponent().getMimeTypesSelected()) {
+ for (String mimeType : this.getComponent().getMimeTypesSelected()) {
predicate += "mime_type = '" + mimeType + "' OR ";
}
- if(predicate.length() > 3) {
+ if (predicate.length() > 3) {
predicate = predicate.substring(0, predicate.length() - 3);
}
return predicate;
@@ -40,5 +40,9 @@ class MimeTypeFilter extends AbstractFileSearchFilter {
@Override
public void addActionListener(ActionListener l) {
}
-
+
+ @Override
+ public boolean isValid() {
+ return !this.getComponent().getMimeTypesSelected().isEmpty();
+ }
}
diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form
index a8c7fa65f9..7eb2d436df 100755
--- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form
+++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.form
@@ -31,7 +31,7 @@
-
+
diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java
index b4172354a4..e14e5e0dc4 100755
--- a/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java
+++ b/Core/src/org/sleuthkit/autopsy/filesearch/MimeTypePanel.java
@@ -5,12 +5,16 @@
*/
package org.sleuthkit.autopsy.filesearch;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
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.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
import org.apache.tika.mime.MediaType;
import org.apache.tika.mime.MimeTypes;
import org.sleuthkit.autopsy.coreutils.Logger;
@@ -25,6 +29,7 @@ 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;
+ private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
/**
* Creates new form MimeTypePanel
@@ -32,6 +37,12 @@ public class MimeTypePanel extends javax.swing.JPanel {
public MimeTypePanel() {
initComponents();
setComponentsEnabled();
+ this.mimeTypeList.addListSelectionListener(new ListSelectionListener() {
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
+ }
+ });
}
private String[] getMimeTypeArray() {
@@ -75,6 +86,16 @@ public class MimeTypePanel extends javax.swing.JPanel {
this.mimeTypeList.setEnabled(enabled);
this.jLabel1.setEnabled(enabled);
}
+
+ @Override
+ public void addPropertyChangeListener(PropertyChangeListener pcl) {
+ pcs.addPropertyChangeListener(pcl);
+ }
+
+ @Override
+ public void removePropertyChangeListener(PropertyChangeListener pcl) {
+ pcs.removePropertyChangeListener(pcl);
+ }
/**
* This method is called from within the constructor to initialize the form.
@@ -141,6 +162,8 @@ public class MimeTypePanel extends javax.swing.JPanel {
private void mimeTypeCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mimeTypeCheckBoxActionPerformed
setComponentsEnabled();
+ pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
+ this.mimeTypeList.setSelectedIndices(new int[0]);
}//GEN-LAST:event_mimeTypeCheckBoxActionPerformed
diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchFilter.java b/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchFilter.java
index 2433a71ba3..ee70ebd5e1 100644
--- a/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchFilter.java
+++ b/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchFilter.java
@@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionListener;
-
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException;
@@ -63,4 +62,9 @@ class NameSearchFilter extends AbstractFileSearchFilter {
public void addActionListener(ActionListener l) {
getComponent().addActionListener(l);
}
+
+ @Override
+ public boolean isValid() {
+ return !this.getComponent().getSearchTextField().getText().isEmpty();
+ }
}
diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchPanel.java
index 1ae2842947..4ffc2c86f7 100644
--- a/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/filesearch/NameSearchPanel.java
@@ -17,7 +17,7 @@
* limitations under the License.
*/
-/*
+ /*
* NameSearchPanel.java
*
* Created on Oct 19, 2011, 11:58:53 AM
@@ -26,9 +26,13 @@ package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
import javax.swing.JCheckBox;
import javax.swing.JMenuItem;
import javax.swing.JTextField;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
/**
*
@@ -36,6 +40,8 @@ import javax.swing.JTextField;
*/
class NameSearchPanel extends javax.swing.JPanel {
+ private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
+
/**
* Creates new form NameSearchPanel
*/
@@ -67,6 +73,22 @@ class NameSearchPanel extends javax.swing.JPanel {
copyMenuItem.addActionListener(actList);
pasteMenuItem.addActionListener(actList);
selectAllMenuItem.addActionListener(actList);
+ this.searchTextField.getDocument().addDocumentListener(new DocumentListener() {
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
+ }
+ });
}
@@ -77,12 +99,22 @@ class NameSearchPanel extends javax.swing.JPanel {
JTextField getSearchTextField() {
return searchTextField;
}
-
+
void setComponentsEnabled() {
boolean enabled = nameCheckBox.isSelected();
this.searchTextField.setEnabled(enabled);
this.noteNameLabel.setEnabled(enabled);
}
+
+ @Override
+ public void addPropertyChangeListener(PropertyChangeListener pcl) {
+ pcs.addPropertyChangeListener(pcl);
+ }
+
+ @Override
+ public void removePropertyChangeListener(PropertyChangeListener pcl) {
+ pcs.removePropertyChangeListener(pcl);
+ }
/**
* This method is called from within the constructor to initialize the form.
@@ -168,6 +200,7 @@ class NameSearchPanel extends javax.swing.JPanel {
private void nameCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nameCheckBoxActionPerformed
setComponentsEnabled();
+ pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_nameCheckBoxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/SizeSearchFilter.java b/Core/src/org/sleuthkit/autopsy/filesearch/SizeSearchFilter.java
index 03fc59b8d4..ca43dac7e0 100644
--- a/Core/src/org/sleuthkit/autopsy/filesearch/SizeSearchFilter.java
+++ b/Core/src/org/sleuthkit/autopsy/filesearch/SizeSearchFilter.java
@@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionListener;
import javax.swing.JComboBox;
-
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException;
@@ -73,4 +72,9 @@ class SizeSearchFilter extends AbstractFileSearchFilter {
public void addActionListener(ActionListener l) {
getComponent().addActionListener(l);
}
+
+ @Override
+ public boolean isValid() {
+ return true;
+ }
}
diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/SizeSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/SizeSearchPanel.java
index 4a0bc91d5e..4bde4eb5e7 100644
--- a/Core/src/org/sleuthkit/autopsy/filesearch/SizeSearchPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/filesearch/SizeSearchPanel.java
@@ -20,6 +20,8 @@ package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
import java.text.NumberFormat;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
@@ -32,6 +34,8 @@ import javax.swing.JMenuItem;
*/
class SizeSearchPanel extends javax.swing.JPanel {
+ private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
+
/**
* Creates new form SizeSearchPanel
*/
@@ -81,13 +85,23 @@ class SizeSearchPanel extends javax.swing.JPanel {
JComboBox getSizeUnitComboBox() {
return sizeUnitComboBox;
}
-
+
void setComponentsEnabled() {
boolean enabled = this.sizeCheckBox.isSelected();
this.sizeCompareComboBox.setEnabled(enabled);
this.sizeUnitComboBox.setEnabled(enabled);
this.sizeTextField.setEnabled(enabled);
}
+
+ @Override
+ public void addPropertyChangeListener(PropertyChangeListener pcl) {
+ pcs.addPropertyChangeListener(pcl);
+ }
+
+ @Override
+ public void removePropertyChangeListener(PropertyChangeListener pcl) {
+ pcs.removePropertyChangeListener(pcl);
+ }
/**
* This method is called from within the constructor to initialize the form.
@@ -168,6 +182,7 @@ class SizeSearchPanel extends javax.swing.JPanel {
private void sizeCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sizeCheckBoxActionPerformed
setComponentsEnabled();
+ pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_sizeCheckBoxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
diff --git a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java
index 12930abba9..1869be9169 100644
--- a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java
+++ b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java
@@ -32,9 +32,17 @@ import javax.swing.JOptionPane;
import org.netbeans.api.progress.ProgressHandle;
import org.openide.util.Cancellable;
import org.openide.util.NbBundle;
+import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
+import org.sleuthkit.datamodel.IngestJobInfo;
+import org.sleuthkit.datamodel.IngestJobInfo.IngestJobStatusType;
+import org.sleuthkit.datamodel.IngestModuleInfo;
+import org.sleuthkit.datamodel.IngestModuleInfo.IngestModuleType;
+import org.sleuthkit.datamodel.SleuthkitCase;
+import org.sleuthkit.datamodel.TskCoreException;
/**
* Encapsulates a data source and the ingest module pipelines used to process
@@ -151,6 +159,8 @@ final class DataSourceIngestJob {
private ProgressHandle fileIngestProgress;
private String currentFileIngestModule = "";
private String currentFileIngestTask = "";
+ private List ingestModules = new ArrayList<>();
+ private IngestJobInfo ingestJob;
/**
* A data source ingest job uses this field to report its creation time.
@@ -243,6 +253,20 @@ final class DataSourceIngestJob {
*/
Thread.currentThread().interrupt();
}
+ SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
+ try {
+ this.addIngestModules(firstStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
+ this.addIngestModules(fileIngestModuleTemplates, IngestModuleType.FILE_LEVEL, skCase);
+ this.addIngestModules(secondStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
+ } catch (TskCoreException ex) {
+ logger.log(Level.SEVERE, "Failed to add ingest modules to database.", ex);
+ }
+ }
+
+ private void addIngestModules(List templates, IngestModuleType type, SleuthkitCase skCase) throws TskCoreException {
+ for (IngestModuleTemplate module : templates) {
+ ingestModules.add(skCase.addIngestModule(module.getModuleName(), FactoryClassNameNormalizer.normalize(module.getModuleFactory().getClass().getCanonicalName()), type, module.getModuleFactory().getModuleVersionNumber()));
+ }
}
/**
@@ -365,6 +389,11 @@ final class DataSourceIngestJob {
logger.log(Level.INFO, "Starting second stage analysis for {0} (jobId={1}), no first stage configured", new Object[]{dataSource.getName(), this.id}); //NON-NLS
this.startSecondStage();
}
+ try {
+ this.ingestJob = Case.getCurrentCase().getSleuthkitCase().addIngestJob(dataSource, NetworkUtils.getLocalHostName(), ingestModules, new Date(this.createTime), new Date(0), IngestJobStatusType.STARTED, "");
+ } catch (TskCoreException ex) {
+ logger.log(Level.SEVERE, "Failed to add ingest job to database.", ex);
+ }
}
return errors;
}
@@ -641,8 +670,26 @@ final class DataSourceIngestJob {
}
}
}
-
+ if (this.cancelled) {
+ try {
+ ingestJob.setIngestJobStatus(IngestJobStatusType.CANCELLED);
+ } catch (TskCoreException ex) {
+ logger.log(Level.SEVERE, "Failed to set ingest status for ingest job in database.", ex);
+ }
+ } else {
+ try {
+ ingestJob.setIngestJobStatus(IngestJobStatusType.COMPLETED);
+ } catch (TskCoreException ex) {
+ logger.log(Level.SEVERE, "Failed to set ingest status for ingest job in database.", ex);
+ }
+ }
+ try {
+ this.ingestJob.setEndDateTime(new Date());
+ } catch (TskCoreException ex) {
+ logger.log(Level.SEVERE, "Failed to set end date for ingest job in database.", ex);
+ }
this.parentJob.dataSourceJobFinished(this);
+
}
/**
diff --git a/Core/src/org/sleuthkit/autopsy/ingest/FactoryClassNameNormalizer.java b/Core/src/org/sleuthkit/autopsy/ingest/FactoryClassNameNormalizer.java
new file mode 100755
index 0000000000..a03abea38a
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/ingest/FactoryClassNameNormalizer.java
@@ -0,0 +1,42 @@
+/*
+ * 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.ingest;
+
+import org.sleuthkit.autopsy.coreutils.Logger;
+
+/**
+ * Used to strip python ids on factory class names.
+ */
+class FactoryClassNameNormalizer {
+
+ private static final CharSequence pythonModuleSettingsPrefixCS = "org.python.proxies.".subSequence(0, "org.python.proxies.".length() - 1); //NON-NLS
+ private static final Logger logger = Logger.getLogger(FactoryClassNameNormalizer.class.getName());
+
+ static String normalize(String canonicalClassName) {
+ if (isPythonModuleSettingsFile(canonicalClassName)) {
+ // compiled python modules have variable instance number as a part of their file name.
+ // This block of code gets rid of that variable instance number and helps maitains constant module name over multiple runs.
+ String moduleClassName = canonicalClassName.replaceAll("[$][\\d]", ""); //NON-NLS NON-NLS
+ return moduleClassName;
+ }
+ return canonicalClassName;
+ }
+
+ /**
+ * Determines if the moduleSettingsFilePath is that of a serialized jython
+ * instance. Serialized Jython instances (settings saved on the disk)
+ * contain "org.python.proxies." in their fileName based on the current
+ * implementation.
+ *
+ * @param moduleSettingsFilePath path to the module settings file.
+ *
+ * @return True or false
+ */
+ private static boolean isPythonModuleSettingsFile(String moduleSettingsFilePath) {
+ return moduleSettingsFilePath.contains(pythonModuleSettingsPrefixCS);
+ }
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java
index 827bbc016d..bea9d2a10b 100644
--- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java
+++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java
@@ -33,10 +33,10 @@ import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.openide.util.io.NbObjectInputStream;
import org.openide.util.io.NbObjectOutputStream;
+import org.python.util.PythonObjectInputStream;
+import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
-import org.sleuthkit.autopsy.coreutils.Logger;
-import org.python.util.PythonObjectInputStream;
/**
* Encapsulates the ingest job settings for a particular execution context.
@@ -467,17 +467,9 @@ public class IngestJobSettings {
* @param settings The ingest job settings for the ingest module
*/
private void saveModuleSettings(IngestModuleFactory factory, IngestModuleIngestJobSettings settings) {
- try {
- String moduleSettingsFilePath = getModuleSettingsFilePath(factory);
- // compiled python modules have substring org.python.proxies. It can be used to identify them.
- if (isPythonModuleSettingsFile(moduleSettingsFilePath)) {
- // compiled python modules have variable instance number as a part of their file name.
- // This block of code gets rid of that variable instance number and helps maitains constant module name over multiple runs.
- moduleSettingsFilePath = moduleSettingsFilePath.replaceAll("[$][\\d]+.settings$", "\\$.settings"); //NON-NLS NON-NLS
- }
- try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(moduleSettingsFilePath))) {
- out.writeObject(settings);
- }
+ String moduleSettingsFilePath = Paths.get(this.moduleSettingsFolderPath, FactoryClassNameNormalizer.normalize(factory.getClass().getCanonicalName()) + MODULE_SETTINGS_FILE_EXT).toString();
+ try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(moduleSettingsFilePath))) {
+ out.writeObject(settings);
} catch (IOException ex) {
String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsSave.warning", factory.getModuleDisplayName(), this.executionContext); //NON-NLS
logger.log(Level.SEVERE, warning, ex);
diff --git a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java
index 69b7c57f4f..af43facec9 100644
--- a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java
+++ b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.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");
@@ -23,7 +23,9 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TskCoreException;
/**
- *
+ * An implementation of a keyword search service.
+ *
+ * TODO (AUT-2158: This interface should not extend Closeable.
*/
public interface KeywordSearchService extends Closeable {
@@ -49,4 +51,4 @@ public interface KeywordSearchService extends Closeable {
*/
public void tryConnect(String host, int port) throws KeywordSearchServiceException;
- }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java
index d7f0543c49..d76abda578 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java
@@ -26,7 +26,6 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.logging.Level;
-
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
@@ -72,6 +71,7 @@ class BrowserLocationAnalyzer {
}
}
+ @NbBundle.Messages({"BrowserLocationAnalyzer.indexError.message=Failed to index GPS trackpoint artifact for keyword search."})
private static void findGeoLocationsInDB(String DatabasePath, AbstractFile f) {
Connection connection = null;
ResultSet resultSet = null;
@@ -110,9 +110,9 @@ class BrowserLocationAnalyzer {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactTypeName(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ Bundle.BrowserLocationAnalyzer_indexError_message(), bba.getDisplayName());
}
}
} catch (Exception e) {
diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java
index 266bf09469..9f36f3cf83 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java
@@ -25,8 +25,8 @@ import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.logging.Level;
-
import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
@@ -78,6 +78,7 @@ class CacheLocationAnalyzer {
}
}
+ @Messages({"CacheLocationAnalyzer.indexError.message=Failed to index GPS trackpoint artifact for keyword search."})
private static void findGeoLocationsInFile(File file, AbstractFile f) {
byte[] bytes; // will temporarily hold bytes to be converted into the correct data types
@@ -140,14 +141,13 @@ class CacheLocationAnalyzer {
//Not storing these for now.
// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy));
// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID(),moduleName, confidence));
-
try {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ Bundle.CacheLocationAnalyzer_indexError_message(), bba.getDisplayName());
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java
index 7df25e15ff..198a503e4a 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java
@@ -28,7 +28,7 @@ import java.sql.Statement;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
-import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
@@ -58,7 +58,7 @@ class CallLogAnalyzer {
private static final Iterable tableNames = Arrays.asList("calls", "logs"); //NON-NLS
public static void findCallLogs(Content dataSource, FileManager fileManager) {
- blackboard = Case.getCurrentCase().getServices().getBlackboard();
+ blackboard = Case.getCurrentCase().getServices().getBlackboard();
try {
List absFiles = fileManager.findFiles(dataSource, "logs.db"); //NON-NLS
absFiles.addAll(fileManager.findFiles(dataSource, "contacts.db")); //NON-NLS
@@ -77,6 +77,7 @@ class CallLogAnalyzer {
}
}
+ @Messages({"CallLogAnalyzer.indexError.message=Failed to index call log artifact for keyword search."})
private static void findCallLogsInDB(String DatabasePath, AbstractFile f) {
if (DatabasePath == null || DatabasePath.isEmpty()) {
@@ -113,16 +114,16 @@ class CallLogAnalyzer {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ Bundle.CallLogAnalyzer_indexError_message(), bba.getDisplayName());
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error posting call log record to the Blackboard", ex); //NON-NLS
}
}
} catch (SQLException e) {
- logger.log(Level.WARNING, "Could not read table {0} in db {1}", new Object[]{tableName, DatabasePath}); //NON-NLS
+ logger.log(Level.WARNING, String.format("Could not read table %s in db %s", tableName, DatabasePath), e); //NON-NLS
}
}
} catch (SQLException e) {
diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java
index 25affa740f..9eb8ac0ae9 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java
@@ -27,7 +27,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.logging.Level;
-import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
@@ -79,6 +79,7 @@ class ContactAnalyzer {
* path The fileId will be the Abstract file associated
* with the artifacts
*/
+ @Messages({"ContactAnalyzer.indexError.message=Failed to index contact artifact for keyword search."})
private static void findContactsInDB(String databasePath, AbstractFile f) {
Connection connection = null;
ResultSet resultSet = null;
@@ -154,9 +155,9 @@ class ContactAnalyzer {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ Bundle.ContactAnalyzer_indexError_message(), bba.getDisplayName());
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java
index d7889257dc..fbb6c9befd 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java
@@ -26,8 +26,8 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.logging.Level;
-
import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
@@ -71,6 +71,7 @@ class GoogleMapLocationAnalyzer {
}
}
+ @Messages({"GoogleMapLocationAnalyzer.indexError.message=Failed to index GPS route artifact for keyword search."})
private static void findGeoLocationsInDB(String DatabasePath, AbstractFile f) {
Connection connection = null;
ResultSet resultSet = null;
@@ -136,9 +137,9 @@ class GoogleMapLocationAnalyzer {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ Bundle.GoogleMapLocationAnalyzer_indexError_message(), bba.getDisplayName());
}
}
} catch (Exception e) {
diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java
index 09dba30821..41d8676eed 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java
@@ -28,6 +28,7 @@ import java.util.List;
import java.util.logging.Level;
import org.apache.commons.codec.binary.Base64;
import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
@@ -68,6 +69,7 @@ class TangoMessageAnalyzer {
}
}
+ @Messages({"TangoMessageAnalyzer.indexError.message=Failed to index Tango message artifact for keyword search."})
private static void findTangoMessagesInDB(String DatabasePath, AbstractFile f) {
Connection connection = null;
ResultSet resultSet = null;
@@ -110,14 +112,14 @@ class TangoMessageAnalyzer {
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName,
NbBundle.getMessage(TangoMessageAnalyzer.class,
"TangoMessageAnalyzer.bbAttribute.tangoMessage")));
-
+
try {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ Bundle.TangoMessageAnalyzer_indexError_message(), bba.getDisplayName());
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
}
}
} catch (Exception e) {
diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java
index edf12e0b66..71139690da 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java
@@ -26,8 +26,8 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.logging.Level;
-
import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
@@ -68,6 +68,7 @@ class TextMessageAnalyzer {
}
}
+ @Messages({"TextMessageAnalyzer.indexError.message=Failed to index text message artifact for keyword search."})
private static void findTextsInDB(String DatabasePath, AbstractFile f) {
Connection connection = null;
ResultSet resultSet = null;
@@ -123,14 +124,14 @@ class TextMessageAnalyzer {
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName,
NbBundle.getMessage(TextMessageAnalyzer.class,
"TextMessageAnalyzer.bbAttribute.smsMessage")));
-
+
try {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ Bundle.TextMessageAnalyzer_indexError_message(), bba.getDisplayName());
}
}
} catch (Exception e) {
diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java
index 87bbd8dc4d..8db7132bf0 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java
@@ -26,8 +26,8 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.logging.Level;
-
import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
@@ -71,6 +71,7 @@ class WWFMessageAnalyzer {
}
}
+ @Messages({"WWFMessageAnalyzer.indexError.message=Failed to index WWF message artifact for keyword search."})
private static void findWWFMessagesInDB(String DatabasePath, AbstractFile f) {
Connection connection = null;
ResultSet resultSet = null;
@@ -110,14 +111,14 @@ class WWFMessageAnalyzer {
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName,
NbBundle.getMessage(WWFMessageAnalyzer.class,
"WWFMessageAnalyzer.bbAttribute.wordsWithFriendsMsg")));
-
+
try {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ Bundle.WWFMessageAnalyzer_indexError_message(), bba.getDisplayName());
}
}
} catch (Exception e) {
diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java
index 8e25feaa23..18a81126fa 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java
@@ -42,6 +42,7 @@ import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
import org.netbeans.api.progress.ProgressHandle;
import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
@@ -50,7 +51,6 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestMessage;
-import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
import org.sleuthkit.autopsy.ingest.IngestMonitor;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
@@ -267,6 +267,7 @@ class SevenZipExtractor {
*
* @return list of unpacked derived files
*/
+ @Messages({"SevenZipExtractor.indexError.message=Failed to index encryption detected artifact for keyword search."})
void unpack(AbstractFile archiveFile) {
blackboard = Case.getCurrentCase().getServices().getBlackboard();
String archiveFilePath;
@@ -586,9 +587,9 @@ class SevenZipExtractor {
// index the artifact for keyword search
blackboard.indexArtifact(artifact);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", artifact.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), artifact.getDisplayName());
+ Bundle.SevenZipExtractor_indexError_message(), artifact.getDisplayName());
}
services.fireModuleDataEvent(new ModuleDataEvent(EmbeddedFileExtractorModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED));
diff --git a/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java
index 2534d376f7..1fd1bd9116 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java
@@ -38,15 +38,16 @@ import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
+import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
-import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
@@ -133,6 +134,7 @@ public final class ExifParserFileIngestModule implements FileIngestModule {
return processFile(content);
}
+ @Messages({"ExifParserFileIngestModule.indexError.message=Failed to index EXIF Metadata artifact for keyword search."})
ProcessResult processFile(AbstractFile f) {
InputStream in = null;
BufferedInputStream bin = null;
@@ -206,9 +208,9 @@ public final class ExifParserFileIngestModule implements FileIngestModule {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ Bundle.ExifParserFileIngestModule_indexError_message(), bba.getDisplayName());
}
filesToFire = true;
}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java
index 6f9a9ea98c..07d2a9a5bd 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java
@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.Set;
import java.util.logging.Level;
import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger;
@@ -105,6 +106,7 @@ public class FileExtMismatchIngestModule implements FileIngestModule {
}
@Override
+ @Messages({"FileExtMismatchIngestModule.indexError.message=Failed to index file extension mismatch artifact for keyword search."})
public ProcessResult process(AbstractFile abstractFile) {
blackboard = Case.getCurrentCase().getServices().getBlackboard();
if (this.settings.skipKnownFiles() && (abstractFile.getKnown() == FileKnown.KNOWN)) {
@@ -139,9 +141,9 @@ public class FileExtMismatchIngestModule implements FileIngestModule {
// index the artifact for keyword search
blackboard.indexArtifact(bart);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bart.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bart.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bart.getDisplayName());
+ Bundle.FileExtMismatchIngestModule_indexError_message(), bart.getDisplayName());
}
services.fireModuleDataEvent(new ModuleDataEvent(FileExtMismatchDetectorModuleFactory.getModuleName(), ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED, Collections.singletonList(bart)));
diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/CustomFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/CustomFileTypesManager.java
index 784dea47b9..4e06ee7d74 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/CustomFileTypesManager.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/CustomFileTypesManager.java
@@ -104,6 +104,19 @@ final class CustomFileTypesManager {
return customTypes;
}
+ /**
+ * Gets the custom file types defined by Autopsy.
+ *
+ * @return A list of custom file types, possibly empty.
+ */
+ synchronized List getAutopsyDefinedFileTypes() {
+ /**
+ * It is safe to return references instead of copies in this snapshot
+ * because FileType objects are immutable.
+ */
+ return new ArrayList<>(autopsyDefinedFileTypes);
+ }
+
/**
* Gets the user-defined custom file types.
*
@@ -287,6 +300,15 @@ final class CustomFileTypesManager {
fileType = new FileType("application/x-iff", signatureList); //NON-NLS
autopsyDefinedFileTypes.add(fileType);
+ /*
+ * Add type for .tec files with leading End Of Image marker (JFIF JPEG)
+ */
+ byteArray = DatatypeConverter.parseHexBinary("FFD9FFD8"); //NON-NLS
+ signatureList.clear();
+ signatureList.add(new Signature(byteArray, 0L));
+ fileType = new FileType("image/jpeg", signatureList); //NON-NLS
+ autopsyDefinedFileTypes.add(fileType);
+
} catch (IllegalArgumentException ex) {
/*
* parseHexBinary() throws this if the argument passed in is not hex
diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java
index 44a7cda7da..487335d828 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java
@@ -56,8 +56,8 @@ public class FileTypeDetector {
*/
public FileTypeDetector() throws FileTypeDetectorInitException {
try {
- userDefinedFileTypes = CustomFileTypesManager.getInstance().getFileTypes();
- autopsyDefinedFileTypes = CustomFileTypesManager.getInstance().getFileTypes();
+ userDefinedFileTypes = CustomFileTypesManager.getInstance().getUserDefinedFileTypes();
+ autopsyDefinedFileTypes = CustomFileTypesManager.getInstance().getAutopsyDefinedFileTypes();
} catch (CustomFileTypesManager.CustomFileTypesException ex) {
throw new FileTypeDetectorInitException("Error loading custom file types", ex); //NON-NLS
}
@@ -168,7 +168,7 @@ public class FileTypeDetector {
/**
* 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.
+ * only if the add to case database flag is set.
*
* @param file The file to test.
* @param addToCaseDb Whether the MIME type should be added to the case
diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form
index 741c775f3c..0b33ec364f 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form
@@ -25,22 +25,24 @@
-
+
-
-
-
-
+
+
+
+
+
+
@@ -62,7 +64,7 @@
-
+
@@ -101,7 +103,10 @@
-
+
+
+
+
@@ -110,7 +115,7 @@
-
+
@@ -119,7 +124,10 @@
-
+
+
+
+
@@ -154,14 +162,14 @@
-
-
+
+
-
+
@@ -263,7 +271,7 @@
-
+
@@ -291,11 +299,11 @@
-
-
-
-
+
+
+
+
@@ -320,6 +328,7 @@
+
diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java
index da67c5697a..a4b4ff49d3 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java
@@ -36,8 +36,8 @@ import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
-import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature;
import org.sleuthkit.autopsy.modules.filetypeid.CustomFileTypesManager.CustomFileTypesException;
+import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature;
/**
* A panel to allow a user to make custom file type definitions. In addition to
@@ -329,6 +329,8 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
setMaximumSize(null);
setPreferredSize(new java.awt.Dimension(752, 507));
+ jPanel3.setPreferredSize(new java.awt.Dimension(781, 339));
+
ingestRunningWarningLabel.setFont(ingestRunningWarningLabel.getFont().deriveFont(ingestRunningWarningLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
ingestRunningWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/filetypeid/warning16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(ingestRunningWarningLabel, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text")); // NOI18N
@@ -336,11 +338,13 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
jLabel3.setFont(jLabel3.getFont().deriveFont(jLabel3.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.jLabel3.text")); // NOI18N
- jScrollPane2.setMinimumSize(new java.awt.Dimension(300, 100));
+ jScrollPane2.setMinimumSize(new java.awt.Dimension(300, 0));
+ jScrollPane2.setPreferredSize(new java.awt.Dimension(550, 275));
- jSplitPane1.setMinimumSize(new java.awt.Dimension(558, 285));
+ jSplitPane1.setMinimumSize(new java.awt.Dimension(0, 0));
- jPanel1.setMinimumSize(new java.awt.Dimension(362, 283));
+ jPanel1.setMinimumSize(new java.awt.Dimension(362, 0));
+ jPanel1.setPreferredSize(new java.awt.Dimension(362, 0));
jLabel2.setFont(jLabel2.getFont().deriveFont(jLabel2.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.jLabel2.text")); // NOI18N
@@ -399,20 +403,20 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
.addGap(12, 12, 12)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(typesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 397, Short.MAX_VALUE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(typesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 203, Short.MAX_VALUE)
+ .addGap(10, 10, 10)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newTypeButton)
.addComponent(editTypeButton)
.addComponent(deleteTypeButton))
- .addContainerGap())
+ .addGap(7, 7, 7))
);
jPanel1Layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {deleteTypeButton, newTypeButton});
jSplitPane1.setLeftComponent(jPanel1);
- jPanel2.setMinimumSize(new java.awt.Dimension(79, 283));
+ jPanel2.setMinimumSize(new java.awt.Dimension(79, 0));
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.jLabel1.text")); // NOI18N
@@ -421,6 +425,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
public int getSize() { return signatures.length; }
public Signature getElementAt(int i) { return signatures[i]; }
});
+ signatureList.setEnabled(false);
signatureList.setMaximumSize(new java.awt.Dimension(32767, 32767));
signatureList.setPreferredSize(null);
jScrollPane1.setViewportView(signatureList);
@@ -444,8 +449,8 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
.addContainerGap()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
- .addGap(40, 40, 40))
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 235, Short.MAX_VALUE)
+ .addContainerGap())
);
jSplitPane1.setRightComponent(jPanel2);
@@ -470,7 +475,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
.addContainerGap()
.addComponent(jLabel3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 281, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ingestRunningWarningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
@@ -481,14 +486,12 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
- .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, 752, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addGap(0, 0, 0))
+ .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, 345, Short.MAX_VALUE)
);
}// //GEN-END:initComponents
diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java
index 96f0c1b16e..1b60250a6b 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java
@@ -22,6 +22,7 @@ import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
+import java.nio.file.Paths;
import java.util.logging.Level;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
@@ -30,6 +31,7 @@ import org.apache.commons.io.FilenameUtils;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
+import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerException;
@@ -273,12 +275,17 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
private void saveAsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveAsButtonActionPerformed
try {
- String lastBaseDirectory = "";
+ String lastBaseDirectory = Paths.get(PlatformUtil.getUserConfigDirectory(), "HashDatabases").toString();
if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)) {
lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY);
}
StringBuilder path = new StringBuilder();
path.append(lastBaseDirectory);
+ File hashDbFolder = new File(path.toString());
+ // create the folder if it doesn't exist
+ if (!hashDbFolder.exists()){
+ hashDbFolder.mkdir();
+ }
if (!hashSetNameTextField.getText().isEmpty()) {
path.append(File.separator).append(hashSetNameTextField.getText());
} else {
diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java
index 18fd2c6202..337fa49f0b 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java
@@ -22,6 +22,7 @@ import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
+import java.nio.file.Paths;
import java.util.logging.Level;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
@@ -31,6 +32,7 @@ import org.apache.commons.io.FilenameUtils;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
+import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerException;
@@ -249,9 +251,16 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
}// //GEN-END:initComponents
private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed
+ String lastBaseDirectory = Paths.get(PlatformUtil.getUserConfigDirectory(), "HashDatabases").toString();
if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)) {
- fileChooser.setCurrentDirectory(new File(ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)));
+ lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY);
}
+ File hashDbFolder = new File(lastBaseDirectory);
+ // create the folder if it doesn't exist
+ if (!hashDbFolder.exists()) {
+ hashDbFolder.mkdir();
+ }
+ fileChooser.setCurrentDirectory(hashDbFolder);
if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
File databaseFile = fileChooser.getSelectedFile();
try {
diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java
index 0199727cb2..13f0d9914d 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java
@@ -26,27 +26,28 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
+import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestMessage;
+import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
+import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
+import org.sleuthkit.datamodel.HashHitInfo;
import org.sleuthkit.datamodel.HashUtility;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskException;
-import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
-import org.sleuthkit.autopsy.ingest.FileIngestModule;
-import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
-import org.sleuthkit.datamodel.HashHitInfo;
@NbBundle.Messages({
"HashDbIngestModule.noKnownBadHashDbSetMsg=No known bad hash database set.",
@@ -285,6 +286,7 @@ public class HashDbIngestModule implements FileIngestModule {
return ret;
}
+ @Messages({"HashDbIngestModule.indexError.message=Failed to index hashset hit artifact for keyword search."})
private void postHashSetHitToBlackboard(AbstractFile abstractFile, String md5Hash, String hashSetName, String comment, boolean showInboxMessage) {
try {
String MODULE_NAME = NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.moduleName");
@@ -303,9 +305,9 @@ public class HashDbIngestModule implements FileIngestModule {
// index the artifact for keyword search
blackboard.indexArtifact(badFile);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", badFile.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + badFile.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), badFile.getDisplayName());
+ Bundle.HashDbIngestModule_indexError_message(), badFile.getDisplayName());
}
if (showInboxMessage) {
diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java
index 22ca91c064..b3627c3ef3 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java
@@ -25,7 +25,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.logging.Level;
-import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger;
@@ -74,6 +74,7 @@ class CallLogAnalyzer {
}
}
+ @Messages({"CallLogAnalyzer.indexError.message=Failed to index call log artifact for keyword search."})
private void findCallLogsInDB(String DatabasePath, long fId) {
if (DatabasePath == null || DatabasePath.isEmpty()) {
return;
@@ -128,9 +129,9 @@ class CallLogAnalyzer {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ Bundle.CallLogAnalyzer_indexError_message(), bba.getDisplayName());
}
}
} catch (Exception e) {
diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java
index 7c63e28a8d..8741f4077b 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java
@@ -30,18 +30,18 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.logging.Level;
-import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
+import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
+import org.sleuthkit.datamodel.ReadContentInputStream;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
-import org.sleuthkit.autopsy.datamodel.ContentUtils;
-import org.sleuthkit.datamodel.ReadContentInputStream;
class ContactAnalyzer {
@@ -91,6 +91,7 @@ class ContactAnalyzer {
* path The fileId will be the Abstract file associated
* with the artifacts
*/
+ @Messages({"ContactAnalyzer.indexError.message=Failed to index contact artifact for keyword search."})
private void findContactsInDB(String DatabasePath, long fId) {
if (DatabasePath == null || DatabasePath.isEmpty()) {
return;
@@ -149,9 +150,9 @@ class ContactAnalyzer {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ Bundle.ContactAnalyzer_indexError_message(), bba.getDisplayName());
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java
index 44c08ae0cf..9ef547f4d9 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java
@@ -26,6 +26,7 @@ import java.sql.Statement;
import java.util.List;
import java.util.logging.Level;
import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger;
@@ -74,6 +75,7 @@ class TextMessageAnalyzer {
}
}
+ @Messages({"TextMessageAnalyzer.indexError.message=Failed to index text message artifact for keyword search."})
private void findTextsInDB(String DatabasePath, long fId) {
if (DatabasePath == null || DatabasePath.isEmpty()) {
return;
@@ -127,14 +129,14 @@ class TextMessageAnalyzer {
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT, moduleName, subject));
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, moduleName, body));
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, NbBundle.getMessage(this.getClass(), "TextMessageAnalyzer.bbAttribute.smsMessage")));
-
+
try {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ Bundle.TextMessageAnalyzer_indexError_message(), bba.getDisplayName());
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java
index 62b423015b..95f52b06e1 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java
@@ -24,7 +24,6 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
-import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
@@ -100,6 +99,7 @@ final class FilesIdentifierIngestModule implements FileIngestModule {
* @inheritDoc
*/
@Override
+ @Messages({"FilesIdentifierIngestModule.indexError.message=Failed to index interesting file hit artifact for keyword search."})
public ProcessResult process(AbstractFile file) {
blackboard = Case.getCurrentCase().getServices().getBlackboard();
@@ -131,9 +131,8 @@ final class FilesIdentifierIngestModule implements FileIngestModule {
// index the artifact for keyword search
blackboard.indexArtifact(artifact);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", artifact.getDisplayName()), ex); //NON-NLS
- MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), artifact.getDisplayName());
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex); //NON-NLS
+ MessageNotifyUtil.Notify.error(Bundle.FilesIdentifierIngestModule_indexError_message(), artifact.getDisplayName());
}
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, Collections.singletonList(artifact)));
diff --git a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java
index 03a64220fb..e51501fbbe 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.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");
@@ -30,9 +30,9 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
@@ -40,29 +40,25 @@ import org.openide.modules.InstalledFileLocator;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.ExecUtil;
+import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
+import org.sleuthkit.autopsy.coreutils.PlatformUtil;
+import org.sleuthkit.autopsy.coreutils.UNCPathUtilities;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
+import org.sleuthkit.autopsy.ingest.FileIngestModuleProcessTerminator;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestModule;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
-import org.sleuthkit.datamodel.AbstractFile;
-import org.sleuthkit.datamodel.Content;
-import org.sleuthkit.datamodel.Image;
-import org.sleuthkit.datamodel.LayoutFile;
-import org.sleuthkit.datamodel.TskCoreException;
-import org.sleuthkit.datamodel.TskData;
-import org.sleuthkit.datamodel.Volume;
-import org.sleuthkit.autopsy.coreutils.FileUtil;
-import org.sleuthkit.autopsy.coreutils.UNCPathUtilities;
-import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
-import org.sleuthkit.autopsy.coreutils.PlatformUtil;
-import org.sleuthkit.autopsy.ingest.ProcTerminationCode;
-import org.sleuthkit.autopsy.ingest.FileIngestModuleProcessTerminator;
import org.sleuthkit.autopsy.ingest.IngestMonitor;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
+import org.sleuthkit.autopsy.ingest.ProcTerminationCode;
+import org.sleuthkit.datamodel.AbstractFile;
+import org.sleuthkit.datamodel.LayoutFile;
+import org.sleuthkit.datamodel.TskData;
/**
* A file ingest module that runs the Unallocated Carver executable with
@@ -182,12 +178,6 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
Path tempFilePath = null;
try {
- long id = getRootId(file);
- // make sure we have a valid systemID
- if (id == -1) {
- return IngestModule.ProcessResult.ERROR;
- }
-
// Verify initialization succeeded.
if (null == this.executableFile) {
logger.log(Level.SEVERE, "PhotoRec carver called after failed start up"); // NON-NLS
@@ -205,6 +195,12 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
NbBundle.getMessage(this.getClass(), "PhotoRecIngestModule.NotEnoughDiskSpace"));
return IngestModule.ProcessResult.ERROR;
}
+ if (this.context.fileIngestIsCancelled() == true) {
+ // if it was cancelled by the user, result is OK
+ logger.log(Level.INFO, "PhotoRec cancelled by user"); // NON-NLS
+ MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "PhotoRecIngestModule.cancelledByUser"));
+ return IngestModule.ProcessResult.OK;
+ }
// Write the file to disk.
long writestart = System.currentTimeMillis();
@@ -212,6 +208,13 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
tempFilePath = Paths.get(paths.getTempDirPath().toString(), file.getName());
ContentUtils.writeToFile(file, tempFilePath.toFile());
+ if (this.context.fileIngestIsCancelled() == true) {
+ // if it was cancelled by the user, result is OK
+ logger.log(Level.INFO, "PhotoRec cancelled by user"); // NON-NLS
+ MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "PhotoRecIngestModule.cancelledByUser"));
+ return IngestModule.ProcessResult.OK;
+ }
+
// Create a subdirectory for this file.
Path outputDirPath = Paths.get(paths.getOutputDirPath().toString(), file.getName());
Files.createDirectory(outputDirPath);
@@ -262,6 +265,12 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
java.io.File newAuditFile = new java.io.File(Paths.get(outputDirPath.toString(), PHOTOREC_REPORT).toString()); //NON-NLS
oldAuditFile.renameTo(newAuditFile);
+ if (this.context.fileIngestIsCancelled() == true) {
+ // if it was cancelled by the user, result is OK
+ logger.log(Level.INFO, "PhotoRec cancelled by user"); // NON-NLS
+ MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "PhotoRecIngestModule.cancelledByUser"));
+ return IngestModule.ProcessResult.OK;
+ }
Path pathToRemove = Paths.get(outputDirPath.toAbsolutePath().toString());
try (DirectoryStream stream = Files.newDirectoryStream(pathToRemove)) {
for (Path entry : stream) {
@@ -276,10 +285,16 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
// Now that we've cleaned up the folders and data files, parse the xml output file to add carved items into the database
long calcstart = System.currentTimeMillis();
PhotoRecCarverOutputParser parser = new PhotoRecCarverOutputParser(outputDirPath);
- List carvedItems = parser.parse(newAuditFile, id, file);
+ if (this.context.fileIngestIsCancelled() == true) {
+ // if it was cancelled by the user, result is OK
+ logger.log(Level.INFO, "PhotoRec cancelled by user"); // NON-NLS
+ MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "PhotoRecIngestModule.cancelledByUser"));
+ return IngestModule.ProcessResult.OK;
+ }
+ List carvedItems = parser.parse(newAuditFile, file, context);
long calcdelta = (System.currentTimeMillis() - calcstart);
totals.totalParsetime.addAndGet(calcdelta);
- if (carvedItems != null) { // if there were any results from carving, add the unallocated carving event to the reports list.
+ if (carvedItems != null && !carvedItems.isEmpty()) { // if there were any results from carving, add the unallocated carving event to the reports list.
totals.totalItemsRecovered.addAndGet(carvedItems.size());
context.addFilesToJob(new ArrayList<>(carvedItems));
services.fireModuleContentEvent(new ModuleContentEvent(carvedItems.get(0))); // fire an event to update the tree
@@ -411,31 +426,6 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
return path;
}
- /**
- * Finds the root Volume or Image of the AbstractFile passed in.
- *
- * @param file The file we want to find the root parent for
- *
- * @return The ID of the root parent Volume or Image
- */
- private static long getRootId(AbstractFile file) {
- long id = -1;
- Content parent = null;
- try {
- parent = file.getParent();
- while (parent != null) {
- if (parent instanceof Volume || parent instanceof Image) {
- id = parent.getId();
- break;
- }
- parent = parent.getParent();
- }
- } catch (TskCoreException ex) {
- logger.log(Level.SEVERE, "PhotoRec carver exception while trying to get parent of AbstractFile.", ex); //NON-NLS
- }
- return id;
- }
-
/**
* Finds and returns the path to the executable, if able.
*
diff --git a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverOutputParser.java b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverOutputParser.java
index caff08b50c..ca42256063 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverOutputParser.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverOutputParser.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");
@@ -27,13 +27,16 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
+import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
+import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.datamodel.AbstractFile;
+import org.sleuthkit.datamodel.CarvingResult;
import org.sleuthkit.datamodel.LayoutFile;
-import org.sleuthkit.datamodel.CarvedFileContainer;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskFileRange;
import org.w3c.dom.Document;
@@ -70,24 +73,24 @@ class PhotoRecCarverOutputParser {
* @throws FileNotFoundException
* @throws IOException
*/
- List parse(File xmlInputFile, long id, AbstractFile af) throws FileNotFoundException, IOException {
+ List parse(File xmlInputFile, AbstractFile af, IngestJobContext context) throws FileNotFoundException, IOException {
try {
final Document doc = XMLUtil.loadDoc(PhotoRecCarverOutputParser.class, xmlInputFile.toString());
if (doc == null) {
- return null;
+ return new ArrayList<>();
}
Element root = doc.getDocumentElement();
if (root == null) {
logger.log(Level.SEVERE, "Error loading config file: invalid file format (bad root)."); //NON-NLS
- return null;
+ return new ArrayList<>();
}
NodeList fileObjects = root.getElementsByTagName("fileobject"); //NON-NLS
final int numberOfFiles = fileObjects.getLength();
if (numberOfFiles == 0) {
- return null;
+ return new ArrayList<>();
}
String fileName;
Long fileSize;
@@ -99,9 +102,14 @@ class PhotoRecCarverOutputParser {
FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
// create and initialize the list to put into the database
- List carvedFileContainer = new ArrayList<>();
-
+ List carvedFiles = new ArrayList<>();
for (int fileIndex = 0; fileIndex < numberOfFiles; ++fileIndex) {
+ if (context.fileIngestIsCancelled() == true) {
+ // if it was cancelled by the user, result is OK
+ logger.log(Level.INFO, "PhotoRec cancelled by user"); // NON-NLS
+ MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "PhotoRecIngestModule.cancelledByUser"));
+ break;
+ }
entry = (Element) fileObjects.item(fileIndex);
fileNames = entry.getElementsByTagName("filename"); //NON-NLS
fileSizes = entry.getElementsByTagName("filesize"); //NON-NLS
@@ -133,7 +141,7 @@ class PhotoRecCarverOutputParser {
if (fileByteEnd > af.getSize()) {
long overshoot = fileByteEnd - af.getSize();
if (fileSize > overshoot) {
- fileSize = fileSize - overshoot;
+ fileSize -= overshoot;
} else {
// This better never happen... Data for this file is corrupted. Skip it.
continue;
@@ -144,10 +152,10 @@ class PhotoRecCarverOutputParser {
}
if (!tskRanges.isEmpty()) {
- carvedFileContainer.add(new CarvedFileContainer(fileName, fileSize, id, tskRanges));
+ carvedFiles.add(new CarvingResult.CarvedFile(fileName, fileSize, tskRanges));
}
}
- return fileManager.addCarvedFiles(carvedFileContainer);
+ return fileManager.addCarvedFiles(new CarvingResult(af, carvedFiles));
} catch (NumberFormatException | TskCoreException ex) {
logger.log(Level.SEVERE, "Error parsing PhotoRec output and inserting it into the database: {0}", ex); //NON-NLS
}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/stix/Bundle.properties
index 10a5c0c593..cb44363a4a 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/stix/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/modules/stix/Bundle.properties
@@ -6,7 +6,7 @@ STIXReportModuleConfigPanel.jLabel2.text=Select a STIX file or directory of STIX
STIXReportModuleConfigPanel.jTextField1.text=
STIXReportModuleConfigPanel.jButton1.text=Choose file
STIXReportModuleConfigPanel.jCheckBox1.text=Include results for false indicators in output file
-STIXReportModule.notifyMsg.unableToOpenReportFile=Unable to open STIX report file {0}
+STIXReportModule.notifyMsg.unableToOpenReportFile=Unable to complete STIX report.
STIXReportModule.progress.completedWithErrors=Completed with errors
STIXReportModule.notifyMsg.unableToOpenFileDir=Unable to open STIX file/directory {0}
STIXReportModule.progress.couldNotOpenFileDir=Could not open file/directory {0}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/stix/Bundle_ja.properties
index 242f9b6b5c..5dfc25469b 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/stix/Bundle_ja.properties
+++ b/Core/src/org/sleuthkit/autopsy/modules/stix/Bundle_ja.properties
@@ -1,14 +1,13 @@
-OpenIDE-Module-Name=stix\u30E2\u30B8\u30E5\u30FC\u30EB
-STIXReportModule.getDesc.text=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u306B\u5BFE\u3057\u3066\u5E7E\u3064\u304B\u306ESTIX\uFF08Structured Threat Information eXpression\uFF1B\u8105\u5A01\u60C5\u5831\u69CB\u9020\u5316\u8A18\u8FF0\u5F62\u5F0F\uFF09\u30D5\u30A1\u30A4\u30EB\u3092\u5B9F\u884C\u3057\u3001\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210\u3057\u307E\u3059\u3002\u307E\u305F\u3001\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u5185\u306B\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u3092\u4F5C\u6210\u3002
+OpenIDE-Module-Name=stix\u30e2\u30b8\u30e5\u30fc\u30eb
+STIXReportModule.getDesc.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306b\u5bfe\u3057\u3066\u5e7e\u3064\u304b\u306eSTIX\uff08Structured Threat Information eXpression\uff1b\u8105\u5a01\u60c5\u5831\u69cb\u9020\u5316\u8a18\u8ff0\u5f62\u5f0f\uff09\u30d5\u30a1\u30a4\u30eb\u3092\u5b9f\u884c\u3057\u3001\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210\u3057\u307e\u3059\u3002\u307e\u305f\u3001\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u5185\u306b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u4f5c\u6210\u3002
STIXReportModule.getName.text=STIX
-STIXReportModule.notifyMsg.tooManyArtifactsgt1000="{0}"\u7528\u306B\u751F\u6210\u3055\u308C\u305FSTIX\u95A2\u9023\u306E\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u304C\u591A\u3059\u304E\u307E\u3059\u3002\u6700\u521D\u306E1000\u306E\u307F\u4FDD\u5B58\u3055\u308C\u307E\u3059\u3002
-STIXReportModule.notifyMsg.unableToOpenFileDir=STIX\u30D5\u30A1\u30A4\u30EB\uFF0F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u958B\u3051\u307E\u305B\u3093\u3067\u3057\u305F
-STIXReportModule.notifyMsg.unableToOpenReportFile=STIX\u30EC\u30DD\u30FC\u30C8\u30D5\u30A1\u30A4\u30EB{0}\u3092\u958B\u3051\u307E\u305B\u3093\u3067\u3057\u305F
-STIXReportModule.progress.completedWithErrors=\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u304C\u3001\u5B8C\u4E86\u3057\u307E\u3057\u305F
-STIXReportModule.progress.couldNotOpenFileDir=\u30D5\u30A1\u30A4\u30EB\uFF0F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u958B\u3051\u307E\u305B\u3093\u3067\u3057\u305F
-STIXReportModule.progress.readSTIX=STIX\u30D5\u30A1\u30A4\u30EB\u3092\u30D1\u30FC\u30B9\u4E2D
-STIXReportModuleConfigPanel.jButton1.text=\u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E
-STIXReportModuleConfigPanel.jCheckBox1.text=\u30A2\u30A6\u30C8\u30D7\u30C3\u30C8\u30D5\u30A1\u30A4\u30EB\u306E\u8AA4\u3063\u305F\u30A4\u30F3\u30B8\u30B1\u30FC\u30BF\u30FC\u306E\u7D50\u679C\u3082\u542B\u3080
-STIXReportModuleConfigPanel.jLabel2.text=STIX\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306FSTIX\u30D5\u30A1\u30A4\u30EB\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u9078\u629E
-STIXReportModule.notifyErr.noFildDirProvided=STIX\u30D5\u30A1\u30A4\u30EB\uFF0F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u63D0\u4F9B\u3055\u308C\u3066\u3044\u307E\u305B\u3093
-STIXReportModule.progress.noFildDirProvided=STIX\u30D5\u30A1\u30A4\u30EB\uFF0F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u63D0\u4F9B\u3055\u308C\u3066\u3044\u307E\u305B\u3093
\ No newline at end of file
+STIXReportModule.notifyMsg.tooManyArtifactsgt1000="{0}"\u7528\u306b\u751f\u6210\u3055\u308c\u305fSTIX\u95a2\u9023\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u304c\u591a\u3059\u304e\u307e\u3059\u3002\u6700\u521d\u306e1000\u306e\u307f\u4fdd\u5b58\u3055\u308c\u307e\u3059\u3002
+STIXReportModule.notifyMsg.unableToOpenFileDir=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u3092\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f
+STIXReportModule.progress.completedWithErrors=\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u304c\u3001\u5b8c\u4e86\u3057\u307e\u3057\u305f
+STIXReportModule.progress.couldNotOpenFileDir=\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u3092\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f
+STIXReportModule.progress.readSTIX=STIX\u30d5\u30a1\u30a4\u30eb\u3092\u30d1\u30fc\u30b9\u4e2d
+STIXReportModuleConfigPanel.jButton1.text=\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e
+STIXReportModuleConfigPanel.jCheckBox1.text=\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a1\u30a4\u30eb\u306e\u8aa4\u3063\u305f\u30a4\u30f3\u30b8\u30b1\u30fc\u30bf\u30fc\u306e\u7d50\u679c\u3082\u542b\u3080
+STIXReportModuleConfigPanel.jLabel2.text=STIX\u30d5\u30a1\u30a4\u30eb\u307e\u305f\u306fSTIX\u30d5\u30a1\u30a4\u30eb\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u9078\u629e
+STIXReportModule.notifyErr.noFildDirProvided=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u305b\u3093
+STIXReportModule.progress.noFildDirProvided=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u305b\u3093
\ No newline at end of file
diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java b/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java
index 2762f21e26..3cc97c3e10 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java
@@ -18,48 +18,47 @@
*/
package org.sleuthkit.autopsy.modules.stix;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.List;
-import java.util.logging.Level;
import java.io.BufferedWriter;
+import java.io.File;
import java.io.FileWriter;
+import java.io.IOException;
import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
import javax.swing.JPanel;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
-
import org.mitre.cybox.cybox_2.ObjectType;
import org.mitre.cybox.cybox_2.Observable;
import org.mitre.cybox.cybox_2.ObservableCompositionType;
+import org.mitre.cybox.cybox_2.OperatorTypeEnum;
+import org.mitre.cybox.objects.AccountObjectType;
+import org.mitre.cybox.objects.Address;
+import org.mitre.cybox.objects.DomainName;
+import org.mitre.cybox.objects.EmailMessage;
+import org.mitre.cybox.objects.FileObjectType;
+import org.mitre.cybox.objects.SystemObjectType;
+import org.mitre.cybox.objects.URIObjectType;
+import org.mitre.cybox.objects.URLHistory;
+import org.mitre.cybox.objects.WindowsNetworkShare;
+import org.mitre.cybox.objects.WindowsRegistryKey;
import org.mitre.stix.common_1.IndicatorBaseType;
import org.mitre.stix.indicator_2.Indicator;
import org.mitre.stix.stix_1.STIXPackage;
-
-import org.sleuthkit.autopsy.coreutils.Logger;
-import org.sleuthkit.autopsy.report.GeneralReportModule;
import org.openide.util.NbBundle;
-import org.sleuthkit.autopsy.report.ReportProgressPanel;
-import org.sleuthkit.datamodel.TskCoreException;
-
-import org.mitre.cybox.cybox_2.OperatorTypeEnum;
-import org.mitre.cybox.objects.Address;
-import org.mitre.cybox.objects.FileObjectType;
-import org.mitre.cybox.objects.URIObjectType;
-import org.mitre.cybox.objects.EmailMessage;
-import org.mitre.cybox.objects.WindowsNetworkShare;
-import org.mitre.cybox.objects.AccountObjectType;
-import org.mitre.cybox.objects.SystemObjectType;
-import org.mitre.cybox.objects.URLHistory;
-import org.mitre.cybox.objects.DomainName;
-import org.mitre.cybox.objects.WindowsRegistryKey;
+import org.openide.util.NbBundle.Messages;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
+import org.sleuthkit.autopsy.report.GeneralReportModule;
+import org.sleuthkit.autopsy.report.ReportProgressPanel;
import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus;
+import org.sleuthkit.datamodel.TskCoreException;
/**
*
@@ -79,8 +78,6 @@ public class STIXReportModule implements GeneralReportModule {
private final boolean skipShortCircuit = true;
- private BufferedWriter output = null;
-
// Hidden constructor for the report
private STIXReportModule() {
}
@@ -100,38 +97,23 @@ public class STIXReportModule implements GeneralReportModule {
* @param progressPanel panel to update the report's progress
*/
@Override
+ @Messages({"STIXReportModule.srcModuleName.text=STIX Report"})
public void generateReport(String baseReportDir, ReportProgressPanel progressPanel) {
// Start the progress bar and setup the report
progressPanel.setIndeterminate(false);
progressPanel.start();
progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.readSTIX"));
reportPath = baseReportDir + getRelativeFilePath();
-
+ File reportFile = new File(reportPath);
// Check if the user wants to display all output or just hits
reportAllResults = configPanel.getShowAllResults();
- // Set up the output file
- try {
- File file = new File(reportPath);
- output = new BufferedWriter(new FileWriter(file));
- } catch (IOException ex) {
- logger.log(Level.SEVERE, String.format("Unable to open STIX report file %s", reportPath), ex); //NON-NLS
- MessageNotifyUtil.Notify.show("STIXReportModule", //NON-NLS
- NbBundle.getMessage(this.getClass(),
- "STIXReportModule.notifyMsg.unableToOpenReportFile",
- reportPath),
- MessageNotifyUtil.MessageType.ERROR);
- progressPanel.complete(ReportStatus.ERROR);
- progressPanel.updateStatusLabel(
- NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.completedWithErrors"));
- return;
- }
-
// Keep track of whether any errors occur during processing
boolean hadErrors = false;
// Process the file/directory name entry
String stixFileName = configPanel.getStixFile();
+
if (stixFileName == null) {
logger.log(Level.SEVERE, "STIXReportModuleConfigPanel.stixFile not initialized "); //NON-NLS
MessageNotifyUtil.Message.error(
@@ -139,6 +121,7 @@ public class STIXReportModule implements GeneralReportModule {
progressPanel.complete(ReportStatus.ERROR);
progressPanel.updateStatusLabel(
NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.noFildDirProvided"));
+ new File(baseReportDir).delete();
return;
}
if (stixFileName.isEmpty()) {
@@ -148,6 +131,7 @@ public class STIXReportModule implements GeneralReportModule {
progressPanel.complete(ReportStatus.ERROR);
progressPanel.updateStatusLabel(
NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.noFildDirProvided"));
+ new File(baseReportDir).delete();
return;
}
File stixFile = new File(stixFileName);
@@ -160,58 +144,66 @@ public class STIXReportModule implements GeneralReportModule {
progressPanel.complete(ReportStatus.ERROR);
progressPanel.updateStatusLabel(
NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.couldNotOpenFileDir", stixFileName));
+ new File(baseReportDir).delete();
return;
}
- // Store the path
- ModuleSettings.setConfigSetting("STIX", "defaultPath", stixFileName); //NON-NLS
+ try (BufferedWriter output = new BufferedWriter(new FileWriter(reportFile))) {
+ // Store the path
+ ModuleSettings.setConfigSetting("STIX", "defaultPath", stixFileName); //NON-NLS
- // Create array of stix file(s)
- File[] stixFiles;
- if (stixFile.isFile()) {
- stixFiles = new File[1];
- stixFiles[0] = stixFile;
- } else {
- stixFiles = stixFile.listFiles();
- }
-
- // Set the length of the progress bar - we increment twice for each file
- progressPanel.setMaximumProgress(stixFiles.length * 2 + 1);
-
- // Process each STIX file
- for (File file : stixFiles) {
- try {
- processFile(file.getAbsolutePath(), progressPanel);
- } catch (TskCoreException ex) {
- logger.log(Level.SEVERE, String.format("Unable to process STIX file %s", file), ex); //NON-NLS
- MessageNotifyUtil.Notify.show("STIXReportModule", //NON-NLS
- ex.getLocalizedMessage(),
- MessageNotifyUtil.MessageType.ERROR);
- hadErrors = true;
+ // Create array of stix file(s)
+ File[] stixFiles;
+ if (stixFile.isFile()) {
+ stixFiles = new File[1];
+ stixFiles[0] = stixFile;
+ } else {
+ stixFiles = stixFile.listFiles();
}
- // Clear out the ID maps before loading the next file
- idToObjectMap = new HashMap();
- idToResult = new HashMap();
- }
+ // Set the length of the progress bar - we increment twice for each file
+ progressPanel.setMaximumProgress(stixFiles.length * 2 + 1);
- // Close the output file
- if (output != null) {
- try {
- output.close();
- } catch (IOException ex) {
- logger.log(Level.SEVERE, String.format("Error closing STIX report file %s", reportPath), ex); //NON-NLS
+ // Process each STIX file
+ for (File file : stixFiles) {
+ if (progressPanel.getStatus() == ReportStatus.CANCELED) {
+ return;
+ }
+ try {
+ processFile(file.getAbsolutePath(), progressPanel, output);
+ } catch (TskCoreException ex) {
+ logger.log(Level.SEVERE, String.format("Unable to process STIX file %s", file), ex); //NON-NLS
+ MessageNotifyUtil.Notify.show("STIXReportModule", //NON-NLS
+ ex.getLocalizedMessage(),
+ MessageNotifyUtil.MessageType.ERROR);
+ hadErrors = true;
+ }
+ // Clear out the ID maps before loading the next file
+ idToObjectMap = new HashMap();
+ idToResult = new HashMap();
}
- }
- // Set the progress bar to done. If any errors occurred along the way, modify
- // the "complete" message to indicate this.
- if (hadErrors) {
+ // Set the progress bar to done. If any errors occurred along the way, modify
+ // the "complete" message to indicate this.
+ Case.getCurrentCase().addReport(reportPath, Bundle.STIXReportModule_srcModuleName_text(), "");
+ if (hadErrors) {
+ progressPanel.complete(ReportStatus.ERROR);
+ progressPanel.updateStatusLabel(
+ NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.completedWithErrors"));
+ } else {
+ progressPanel.complete(ReportStatus.COMPLETE);
+ }
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, "Unable to complete STIX report.", ex); //NON-NLS
+ MessageNotifyUtil.Notify.show("STIXReportModule", //NON-NLS
+ NbBundle.getMessage(this.getClass(),
+ "STIXReportModule.notifyMsg.unableToOpenReportFile"),
+ MessageNotifyUtil.MessageType.ERROR);
progressPanel.complete(ReportStatus.ERROR);
progressPanel.updateStatusLabel(
NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.completedWithErrors"));
- } else {
- progressPanel.complete(ReportStatus.COMPLETE);
+ } catch (TskCoreException ex) {
+ logger.log(Level.SEVERE, "Unable to add report to database.", ex);
}
}
@@ -223,14 +215,14 @@ public class STIXReportModule implements GeneralReportModule {
*
* @throws TskCoreException
*/
- private void processFile(String stixFile, ReportProgressPanel progressPanel) throws
+ private void processFile(String stixFile, ReportProgressPanel progressPanel, BufferedWriter output) throws
TskCoreException {
// Load the STIX file
STIXPackage stix;
stix = loadSTIXFile(stixFile);
- printFileHeader(stixFile);
+ printFileHeader(stixFile, output);
// Save any observables listed up front
processObservables(stix);
@@ -240,7 +232,7 @@ public class STIXReportModule implements GeneralReportModule {
registryFileData = EvalRegistryObj.copyRegistryFiles();
// Process the indicators
- processIndicators(stix);
+ processIndicators(stix, output);
progressPanel.increment();
}
@@ -292,7 +284,7 @@ public class STIXReportModule implements GeneralReportModule {
*
* @param stix STIXPackage
*/
- private void processIndicators(STIXPackage stix) throws TskCoreException {
+ private void processIndicators(STIXPackage stix, BufferedWriter output) throws TskCoreException {
if (stix.getIndicators() != null) {
List s = stix.getIndicators().getIndicators();
for (IndicatorBaseType t : s) {
@@ -302,7 +294,7 @@ public class STIXReportModule implements GeneralReportModule {
if (ind.getObservable().getObject() != null) {
ObservableResult result = evaluateSingleObservable(ind.getObservable(), "");
if (result.isTrue() || reportAllResults) {
- writeResultsToFile(ind, result.getDescription(), result.isTrue());
+ writeResultsToFile(ind, result.getDescription(), result.isTrue(), output);
}
if (result.isTrue()) {
saveResultsAsArtifacts(ind, result);
@@ -311,7 +303,7 @@ public class STIXReportModule implements GeneralReportModule {
ObservableResult result = evaluateObservableComposition(ind.getObservable().getObservableComposition(), " ");
if (result.isTrue() || reportAllResults) {
- writeResultsToFile(ind, result.getDescription(), result.isTrue());
+ writeResultsToFile(ind, result.getDescription(), result.isTrue(), output);
}
if (result.isTrue()) {
saveResultsAsArtifacts(ind, result);
@@ -376,7 +368,7 @@ public class STIXReportModule implements GeneralReportModule {
* @param resultStr - Full results for this indicator
* @param found - true if the indicator was found in datasource(s)
*/
- private void writeResultsToFile(Indicator ind, String resultStr, boolean found) {
+ private void writeResultsToFile(Indicator ind, String resultStr, boolean found, BufferedWriter output) {
if (output != null) {
try {
if (found) {
@@ -412,7 +404,7 @@ public class STIXReportModule implements GeneralReportModule {
*
* @param a_fileName
*/
- private void printFileHeader(String a_fileName) {
+ private void printFileHeader(String a_fileName, BufferedWriter output) {
if (output != null) {
try {
char[] chars = new char[a_fileName.length() + 8];
diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/StixArtifactData.java b/Core/src/org/sleuthkit/autopsy/modules/stix/StixArtifactData.java
index 9a19e4cedf..8a8466d89f 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/stix/StixArtifactData.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/stix/StixArtifactData.java
@@ -19,7 +19,7 @@
package org.sleuthkit.autopsy.modules.stix;
import java.util.logging.Level;
-import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger;
@@ -58,6 +58,7 @@ class StixArtifactData {
objType = a_objType;
}
+ @Messages({"StixArtifactData.indexError.message=Failed to index STIX interesting file hit artifact for keyword search."})
public void createArtifact(String a_title) throws TskCoreException {
Blackboard blackboard = Case.getCurrentCase().getServices().getBlackboard();
@@ -72,14 +73,13 @@ class StixArtifactData {
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, "Stix", setName)); //NON-NLS
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE, "Stix", observableId)); //NON-NLS
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, "Stix", objType)); //NON-NLS
-
+
try {
// index the artifact for keyword search
blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
- MessageNotifyUtil.Notify.error(
- NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
+ logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
+ MessageNotifyUtil.Notify.error(Bundle.StixArtifactData_indexError_message(), bba.getDisplayName());
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties
index 0be3a1924f..6e920ad631 100644
--- a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties
@@ -179,7 +179,7 @@ ReportHTML.addThumbRows.dataType.msg=Tagged Results and Contents that contain im
ReportHTML.thumbLink.tags=Tags\:
ReportHTML.getName.text=Results - HTML
ReportHTML.getDesc.text=A report about results and tagged items in HTML format.
-ReportHTML.writeIndex.title=Autopsy Report for case {0}
+ReportHTML.writeIndex.title=for case {0}
ReportHTML.writeIndex.noFrames.msg=Your browser is not compatible with our frame setup.
ReportHTML.writeIndex.noFrames.seeNav=Please see the navigation page for artifact links,
ReportHTML.writeIndex.seeSum=and the summary page for a case summary.
@@ -225,7 +225,8 @@ ReportHTML.writeSum.noCaseNum=No case number
ReportBodyFile.generateReport.srcModuleName.text=TSK Body File
ReportExcel.endReport.srcModuleName.text=Excel Report
ReportHTML.writeIndex.srcModuleName.text=HTML Report
-ReportKML.genReport.srcModuleName.text=KML Report
+ReportKML.genReport.srcModuleName.text=Geospatial Data
+ReportKML.genReport.reportName=KML Report
ReportGenerator.artTableColHdr.extension.text=Extension
ReportGenerator.artTableColHdr.mimeType.text=MIME Type
ReportGenerator.artTableColHdr.processorArchitecture.text=Processor Architecture
diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties
index 6ff657b68a..a877c52899 100644
--- a/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties
+++ b/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties
@@ -188,7 +188,7 @@ 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
+ReportKML.genReport.reportName=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
diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java
index 1f49588837..834c221d9d 100644
--- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java
+++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java
@@ -26,25 +26,14 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
-import java.sql.ResultSet;
-import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
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;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeSet;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.JDialog;
@@ -53,47 +42,28 @@ 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;
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;
-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.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
- * FileReportModules to generate a report. If desired, displayProgressPanels()
- * can be called to show report generation progress using ReportProgressPanel
- * 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;
+ /**
+ * Progress reportGenerationPanel that can be used to check for cancellation.
+ */
+ private ReportProgressPanel progressPanel;
- private String reportPath;
- private ReportGenerationPanel panel = new ReportGenerationPanel();
+ private final String reportPath;
+ private final ReportGenerationPanel reportGenerationPanel = new ReportGenerationPanel();
static final String REPORTS_DIR = "Reports"; //NON-NLS
@@ -102,8 +72,6 @@ class ReportGenerator {
/**
* Displays the list of errors during report generation in user-friendly
* way. MessageNotifyUtil used to display bubble notification.
- *
- * @param listOfErrors List of strings explaining the errors.
*/
private void displayReportErrors() {
if (!errorList.isEmpty()) {
@@ -113,18 +81,20 @@ class ReportGenerator {
}
MessageNotifyUtil.Notify.error(
NbBundle.getMessage(this.getClass(), "ReportGenerator.notifyErr.errsDuringRptGen"), errorString);
- return;
}
}
- ReportGenerator(Map tableModuleStates, Map generalModuleStates, Map fileListModuleStates) {
+ /**
+ * Creates a report generator.
+ */
+ ReportGenerator() {
// 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();
+ this.errorList = new ArrayList<>();
// Create the root reports directory.
try {
@@ -132,69 +102,6 @@ class ReportGenerator {
} catch (IOException ex) {
errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedMakeRptFolder"));
logger.log(Level.SEVERE, "Failed to make report folder, may be unable to generate reports.", ex); //NON-NLS
- return;
- }
-
- // Initialize the progress panels
- generalProgress = new HashMap<>();
- tableProgress = new HashMap<>();
- fileProgress = new HashMap<>();
- setupProgressPanels(tableModuleStates, generalModuleStates, fileListModuleStates);
- this.columnHeaderMap = new HashMap<>();
- }
-
- /**
- * Create a ReportProgressPanel for each report generation module selected
- * by the user.
- *
- * @param tableModuleStates The enabled/disabled state of each
- * TableReportModule
- * @param generalModuleStates The enabled/disabled state of each
- * GeneralReportModule
- * @param fileListModuleStates The enabled/disabled state of each
- * FileReportModule
- */
- private void setupProgressPanels(Map tableModuleStates, Map generalModuleStates, Map fileListModuleStates) {
- if (null != tableModuleStates) {
- for (Entry entry : tableModuleStates.entrySet()) {
- if (entry.getValue()) {
- TableReportModule module = entry.getKey();
- String reportFilePath = module.getRelativeFilePath();
- if (!reportFilePath.isEmpty()) {
- tableProgress.put(module, panel.addReport(module.getName(), reportPath + reportFilePath));
- } else {
- tableProgress.put(module, panel.addReport(module.getName(), null));
- }
- }
- }
- }
-
- if (null != generalModuleStates) {
- for (Entry entry : generalModuleStates.entrySet()) {
- if (entry.getValue()) {
- GeneralReportModule module = entry.getKey();
- String reportFilePath = module.getRelativeFilePath();
- if (!reportFilePath.isEmpty()) {
- generalProgress.put(module, panel.addReport(module.getName(), reportPath + reportFilePath));
- } else {
- generalProgress.put(module, panel.addReport(module.getName(), null));
- }
- }
- }
- }
-
- if (null != fileListModuleStates) {
- for (Entry entry : fileListModuleStates.entrySet()) {
- if (entry.getValue()) {
- FileReportModule module = entry.getKey();
- String reportFilePath = module.getRelativeFilePath();
- if (!reportFilePath.isEmpty()) {
- fileProgress.put(module, panel.addReport(module.getName(), reportPath + reportFilePath));
- } else {
- fileProgress.put(module, panel.addReport(module.getName(), null));
- }
- }
- }
}
}
@@ -202,14 +109,14 @@ class ReportGenerator {
* Display the progress panels to the user, and add actions to close the
* parent dialog.
*/
- public void displayProgressPanels() {
+ private void displayProgressPanel() {
final JDialog dialog = new JDialog(new JFrame(), true);
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.setTitle(NbBundle.getMessage(this.getClass(), "ReportGenerator.displayProgress.title.text"));
- dialog.add(this.panel);
+ dialog.add(this.reportGenerationPanel);
dialog.pack();
- panel.addCloseAction(new ActionListener() {
+ reportGenerationPanel.addCloseAction(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
@@ -219,7 +126,7 @@ class ReportGenerator {
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
- panel.close();
+ reportGenerationPanel.close();
}
});
@@ -235,9 +142,15 @@ class ReportGenerator {
/**
* Run the GeneralReportModules using a SwingWorker.
*/
- public void generateGeneralReports() {
- GeneralReportsWorker worker = new GeneralReportsWorker();
- worker.execute();
+ void generateGeneralReport(GeneralReportModule generalReportModule) {
+ if (generalReportModule != null) {
+ setupProgressPanel(generalReportModule);
+ ReportWorker worker = new ReportWorker(() -> {
+ generalReportModule.generateReport(reportPath, progressPanel);
+ });
+ worker.execute();
+ displayProgressPanel();
+ }
}
/**
@@ -248,10 +161,18 @@ class ReportGenerator {
* @param tagSelections the enabled/disabled state of the tag names
* to be included in the report
*/
- public void generateTableReports(Map artifactTypeSelections, Map tagNameSelections) {
- if (!tableProgress.isEmpty() && null != artifactTypeSelections) {
- TableReportsWorker worker = new TableReportsWorker(artifactTypeSelections, tagNameSelections);
+ void generateTableReport(TableReportModule tableReport, Map artifactTypeSelections, Map tagNameSelections) {
+ if (tableReport != null && null != artifactTypeSelections) {
+ setupProgressPanel(tableReport);
+ ReportWorker worker = new ReportWorker(() -> {
+ tableReport.startReport(reportPath);
+ TableReportGenerator generator = new TableReportGenerator(artifactTypeSelections, tagNameSelections, progressPanel, tableReport);
+ generator.execute();
+ tableReport.endReport();
+ errorList = generator.getErrorList();
+ });
worker.execute();
+ displayProgressPanel();
}
}
@@ -261,146 +182,101 @@ class ReportGenerator {
* @param enabledInfo the Information that should be included about each
* file in the report.
*/
- public void generateFileListReports(Map enabledInfo) {
- if (!fileProgress.isEmpty() && null != enabledInfo) {
+ void generateFileListReport(FileReportModule fileReportModule, Map enabledInfo) {
+ if (fileReportModule != null && null != enabledInfo) {
List enabled = new ArrayList<>();
for (Entry e : enabledInfo.entrySet()) {
if (e.getValue()) {
enabled.add(e.getKey());
}
}
- FileReportsWorker worker = new FileReportsWorker(enabled);
- worker.execute();
- }
- }
-
- /**
- * SwingWorker to run GeneralReportModules.
- */
- private class GeneralReportsWorker extends SwingWorker {
-
- @Override
- protected Integer doInBackground() throws Exception {
- for (Entry entry : generalProgress.entrySet()) {
- GeneralReportModule module = entry.getKey();
- if (generalProgress.get(module).getStatus() != ReportStatus.CANCELED) {
- module.generateReport(reportPath, generalProgress.get(module));
- }
- }
- return 0;
- }
-
- @Override
- protected void done() {
- try {
- get();
- } catch (InterruptedException | ExecutionException ex) {
- MessageNotifyUtil.Notify.show(
- 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
- } // catch and ignore if we were cancelled
- catch (java.util.concurrent.CancellationException ex) {
- } finally {
- displayReportErrors();
- 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) {
- ReportProgressPanel progress = fileProgress.get(module);
- if (progress.getStatus() != ReportStatus.CANCELED) {
- progress.start();
- progress.updateStatusLabel(
+ setupProgressPanel(fileReportModule);
+ ReportWorker worker = new ReportWorker(() -> {
+ if (progressPanel.getStatus() != ReportStatus.CANCELED) {
+ progressPanel.start();
+ progressPanel.updateStatusLabel(
NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.queryingDb.text"));
}
- }
- List files = getFiles();
- int numFiles = files.size();
- for (FileReportModule module : fileModules) {
- module.startReport(reportPath);
- module.startTable(enabledInfo);
- fileProgress.get(module).setIndeterminate(false);
- fileProgress.get(module).setMaximumProgress(numFiles);
- }
-
- int i = 0;
- // Add files to report.
- for (AbstractFile file : files) {
- // Check to see if any reports have been cancelled.
- if (fileModules.isEmpty()) {
- break;
+ List files = getFiles();
+ int numFiles = files.size();
+ if (progressPanel.getStatus() != ReportStatus.CANCELED) {
+ fileReportModule.startReport(reportPath);
+ fileReportModule.startTable(enabled);
}
- // Remove cancelled reports, add files to report otherwise.
- Iterator iter = fileModules.iterator();
- while (iter.hasNext()) {
- FileReportModule module = iter.next();
- ReportProgressPanel progress = fileProgress.get(module);
- if (progress.getStatus() == ReportStatus.CANCELED) {
- iter.remove();
+ progressPanel.setIndeterminate(false);
+ progressPanel.setMaximumProgress(numFiles);
+
+ int i = 0;
+ // Add files to report.
+ for (AbstractFile file : files) {
+ // Check to see if any reports have been cancelled.
+ if (progressPanel.getStatus() == ReportStatus.CANCELED) {
+ return;
} else {
- module.addRow(file, enabledInfo);
- progress.increment();
+ fileReportModule.addRow(file, enabled);
+ progressPanel.increment();
}
if ((i % 100) == 0) {
- progress.updateStatusLabel(
+ progressPanel.updateStatusLabel(
NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processingFile.text",
file.getName()));
}
+ i++;
}
- i++;
- }
- for (FileReportModule module : fileModules) {
- module.endTable();
- module.endReport();
- fileProgress.get(module).complete(ReportStatus.COMPLETE);
- }
+ fileReportModule.endTable();
+ fileReportModule.endReport();
+ progressPanel.complete(ReportStatus.COMPLETE);
+ });
+ worker.execute();
+ displayProgressPanel();
+ }
+ }
- return 0;
+ /**
+ * Get all files in the image.
+ *
+ * @return
+ */
+ private List getFiles() {
+ List absFiles;
+ try {
+ SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
+ absFiles = skCase.findAllFilesWhere("meta_type != " + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()); //NON-NLS
+ return absFiles;
+ } catch (TskCoreException ex) {
+ MessageNotifyUtil.Notify.show(
+ 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. Unable to get all files in the image.", ex); //NON-NLS
+ return Collections.emptyList();
+ }
+ }
+
+ private void setupProgressPanel(ReportModule module) {
+ String reportFilePath = module.getRelativeFilePath();
+ if (!reportFilePath.isEmpty()) {
+ this.progressPanel = reportGenerationPanel.addReport(module.getName(), reportPath + reportFilePath);
+ } else {
+ this.progressPanel = reportGenerationPanel.addReport(module.getName(), null);
+ }
+ }
+
+ private class ReportWorker extends SwingWorker {
+
+ private final Runnable doInBackground;
+
+ private ReportWorker(Runnable doInBackground) {
+ this.doInBackground = doInBackground;
}
- /**
- * Get all files in the image.
- *
- * @return
- */
- private List getFiles() {
- List absFiles;
- try {
- SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
- absFiles = skCase.findAllFilesWhere("meta_type != " + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()); //NON-NLS
- return absFiles;
- } catch (TskCoreException ex) {
- MessageNotifyUtil.Notify.show(
- 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. Unable to get all files in the image.", ex); //NON-NLS
- return Collections.emptyList();
- }
+ @Override
+ protected Void doInBackground() throws Exception {
+ doInBackground.run();
+ return null;
}
@Override
@@ -420,1706 +296,6 @@ class ReportGenerator {
errorList.clear();
}
}
- }
- /**
- * SwingWorker to run TableReportModules to report on blackboard artifacts,
- * 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()) {
- tableModules.add(entry.getKey());
- }
-
- // Get the artifact types selected by the user.
- for (Entry entry : artifactTypeSelections.entrySet()) {
- if (entry.getValue()) {
- artifactTypes.add(entry.getKey());
- }
- }
-
- // Get the tag names selected by the user and make a tag names filter.
- if (null != tagNameSelections) {
- for (Entry entry : tagNameSelections.entrySet()) {
- if (entry.getValue() == true) {
- tagNamesFilter.add(entry.getKey());
- }
- }
- }
- }
-
- @Override
- protected Integer doInBackground() throws Exception {
- // Start the progress indicators for each active TableReportModule.
- for (TableReportModule module : tableModules) {
- ReportProgressPanel progress = tableProgress.get(module);
- if (progress.getStatus() != ReportStatus.CANCELED) {
- module.startReport(reportPath);
- progress.start();
- progress.setIndeterminate(false);
- progress.setMaximumProgress(this.artifactTypes.size() + 2); // +2 for content and blackboard artifact tags
- }
- }
-
- // report on the blackboard results
- makeBlackboardArtifactTables();
-
- // report on the tagged files and artifacts
- makeContentTagsTables();
- makeBlackboardArtifactTagsTables();
-
- // report on the tagged images
- makeThumbnailTable();
-
- // finish progress, wrap up
- for (TableReportModule module : tableModules) {
- tableProgress.get(module).complete(ReportStatus.COMPLETE);
- module.endReport();
- }
-
- return 0;
- }
-
- /**
- * Generate the tables for the selected blackboard artifacts
- */
- private void makeBlackboardArtifactTables() {
- // Make a comment string describing the tag names filter in effect.
- StringBuilder comment = new StringBuilder();
- if (!tagNamesFilter.isEmpty()) {
- comment.append(NbBundle.getMessage(this.getClass(), "ReportGenerator.artifactTable.taggedResults.text"));
- comment.append(makeCommaSeparatedList(tagNamesFilter));
- }
-
- // Add a table to the report for every enabled blackboard artifact type.
- for (BlackboardArtifact.Type type : artifactTypes) {
- // Check for cancellaton.
- removeCancelledTableReportModules();
- if (tableModules.isEmpty()) {
- return;
- }
-
- for (TableReportModule module : tableModules) {
- tableProgress.get(module).updateStatusLabel(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processing",
- type.getDisplayName()));
- }
-
- // Keyword hits and hashset hit artifacts get special handling.
- if (type.getTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
- writeKeywordHits(tableModules, comment.toString(), tagNamesFilter);
- continue;
- } else if (type.getTypeID() == ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
- writeHashsetHits(tableModules, comment.toString(), tagNamesFilter);
- continue;
- }
-
- List artifactList = getFilteredArtifacts(type, tagNamesFilter);
-
- if (artifactList.isEmpty()) {
- continue;
- }
-
- /*
- 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) {
- List attributes = data.getAttributes();
- for (BlackboardAttribute attribute : attributes) {
- attrTypeSet.add(attribute.getAttributeType());
- }
- }
- // Get the columns appropriate for the artifact type. This is
- // used to get the data that will be in the cells below based on
- // type, and display the column headers.
- List columns = getArtifactTableColumns(type.getTypeID(), attrTypeSet);
- if (columns.isEmpty()) {
- continue;
- }
- ReportGenerator.this.columnHeaderMap.put(type.getTypeID(), columns);
-
- // The artifact list is sorted now, as getting the row data is
- // dependent on having the columns, which is necessary for
- // sorting.
- Collections.sort(artifactList);
- List columnHeaderNames = new ArrayList<>();
- for (Column currColumn : columns) {
- columnHeaderNames.add(currColumn.getColumnHeader());
- }
-
- for (TableReportModule module : tableModules) {
- module.startDataType(type.getDisplayName(), comment.toString());
- module.startTable(columnHeaderNames);
- }
- for (ArtifactData artifactData : artifactList) {
- // Add the row data to all of the reports.
- for (TableReportModule module : tableModules) {
-
- // Get the row data for this artifact, and has the
- // module add it.
- List rowData = artifactData.getRow();
- if (rowData.isEmpty()) {
- continue;
- }
-
- module.addRow(rowData);
- }
- }
- // Finish up this data type
- for (TableReportModule module : tableModules) {
- tableProgress.get(module).increment();
- module.endTable();
- module.endDataType();
- }
- }
- }
-
- /**
- * Make table for tagged files
- */
- @SuppressWarnings("deprecation")
- private void makeContentTagsTables() {
- // Check for cancellaton.
- removeCancelledTableReportModules();
- if (tableModules.isEmpty()) {
- return;
- }
-
- // Get the content tags.
- List tags;
- try {
- tags = Case.getCurrentCase().getServices().getTagsManager().getAllContentTags();
- } catch (TskCoreException ex) {
- errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetContentTags"));
- logger.log(Level.SEVERE, "failed to get content tags", ex); //NON-NLS
- return;
- }
-
- // Tell the modules reporting on content tags is beginning.
- for (TableReportModule module : tableModules) {
- // @@@ This casting is a tricky little workaround to allow the HTML report module to slip in a content hyperlink.
- // @@@ Alos Using the obsolete ARTIFACT_TYPE.TSK_TAG_FILE is also an expedient hack.
- tableProgress.get(module).updateStatusLabel(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processing",
- ARTIFACT_TYPE.TSK_TAG_FILE.getDisplayName()));
- ArrayList columnHeaders = new ArrayList<>(Arrays.asList(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.tag"),
- NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.file"),
- NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.comment"),
- NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.timeModified"),
- NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.timeChanged"),
- NbBundle.getMessage(this.getClass(), "ReportGenerator.htmlOutput.header.timeAccessed"),
- 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(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.makeContTagTab.taggedFiles.msg"));
- comment.append(makeCommaSeparatedList(tagNamesFilter));
- }
- if (module instanceof ReportHTML) {
- ReportHTML htmlReportModule = (ReportHTML) module;
- htmlReportModule.startDataType(ARTIFACT_TYPE.TSK_TAG_FILE.getDisplayName(), comment.toString());
- htmlReportModule.startContentTagsTable(columnHeaders);
- } else {
- module.startDataType(ARTIFACT_TYPE.TSK_TAG_FILE.getDisplayName(), comment.toString());
- module.startTable(columnHeaders);
- }
- }
-
- // Give the modules the rows for the content tags.
- for (ContentTag tag : tags) {
- // skip tags that we are not reporting on
- 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()));
- 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) {
- ReportHTML htmlReportModule = (ReportHTML) module;
- htmlReportModule.addRowWithTaggedContentHyperlink(rowData, tag);
- } else {
- module.addRow(rowData);
- }
- }
-
- // see if it is for an image so that we later report on it
- checkIfTagHasImage(tag);
- }
-
- // The the modules content tags reporting is ended.
- for (TableReportModule module : tableModules) {
- tableProgress.get(module).increment();
- module.endTable();
- module.endDataType();
- }
- }
-
- @Override
- protected void done() {
- try {
- get();
- } catch (InterruptedException | ExecutionException ex) {
- MessageNotifyUtil.Notify.show(
- 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.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 {
- displayReportErrors();
- errorList.clear();
- }
- }
-
- /**
- * Generate the tables for the tagged artifacts
- */
- @SuppressWarnings("deprecation")
- private void makeBlackboardArtifactTagsTables() {
- // Check for cancellaton.
- removeCancelledTableReportModules();
- if (tableModules.isEmpty()) {
- return;
- }
-
- List tags;
- try {
- tags = Case.getCurrentCase().getServices().getTagsManager().getAllBlackboardArtifactTags();
- } catch (TskCoreException ex) {
- errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetBBArtifactTags"));
- logger.log(Level.SEVERE, "failed to get blackboard artifact tags", ex); //NON-NLS
- return;
- }
-
- // Tell the modules reporting on blackboard artifact tags data type is beginning.
- // @@@ Using the obsolete ARTIFACT_TYPE.TSK_TAG_ARTIFACT is an expedient hack.
- for (TableReportModule module : tableModules) {
- tableProgress.get(module).updateStatusLabel(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processing",
- ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getDisplayName()));
- StringBuilder comment = new StringBuilder();
- if (!tagNamesFilter.isEmpty()) {
- comment.append(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.makeBbArtTagTab.taggedRes.msg"));
- comment.append(makeCommaSeparatedList(tagNamesFilter));
- }
- module.startDataType(ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getDisplayName(), comment.toString());
- module.startTable(new ArrayList<>(Arrays.asList(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.tagTable.header.resultType"),
- NbBundle.getMessage(this.getClass(), "ReportGenerator.tagTable.header.tag"),
- NbBundle.getMessage(this.getClass(), "ReportGenerator.tagTable.header.comment"),
- NbBundle.getMessage(this.getClass(), "ReportGenerator.tagTable.header.srcFile"))));
- }
-
- // Give the modules the rows for the content tags.
- for (BlackboardArtifactTag tag : tags) {
- 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()));
- module.addRow(row);
- }
-
- // check if the tag is an image that we should later make a thumbnail for
- checkIfTagHasImage(tag);
- }
-
- // The the modules blackboard artifact tags reporting is ended.
- for (TableReportModule module : tableModules) {
- tableProgress.get(module).increment();
- module.endTable();
- module.endDataType();
- }
- }
-
- /**
- * Test if the user requested that this tag be reported on
- *
- * @param tagName
- *
- * @return true if it should be reported on
- */
- private boolean passesTagNamesFilter(String tagName) {
- return tagNamesFilter.isEmpty() || tagNamesFilter.contains(tagName);
- }
-
- void removeCancelledTableReportModules() {
- Iterator iter = tableModules.iterator();
- while (iter.hasNext()) {
- TableReportModule module = iter.next();
- if (tableProgress.get(module).getStatus() == ReportStatus.CANCELED) {
- iter.remove();
- }
- }
- }
-
- /**
- * Make a report for the files that were previously found to be images.
- */
- private void makeThumbnailTable() {
- 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(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.thumbnailTable.name"),
- NbBundle.getMessage(this.getClass(), "ReportGenerator.thumbnailTable.desc"));
- List emptyHeaders = new ArrayList<>();
- for (int i = 0; i < ReportHTML.THUMBNAIL_COLUMNS; i++) {
- emptyHeaders.add("");
- }
- htmlModule.startTable(emptyHeaders);
-
- htmlModule.addThumbnailRows(images);
-
- htmlModule.endTable();
- htmlModule.endDataType();
- }
- }
- }
-
- /**
- * Analyze artifact associated with tag and add to internal list if it
- * is associated with an image.
- *
- * @param artifactTag
- */
- private void checkIfTagHasImage(BlackboardArtifactTag artifactTag) {
- AbstractFile file;
- try {
- file = Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(artifactTag.getArtifact().getObjectID());
- } catch (TskCoreException ex) {
- errorList.add(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.errGetContentFromBBArtifact"));
- logger.log(Level.WARNING, "Error while getting content from a blackboard artifact to report on.", ex); //NON-NLS
- return;
- }
-
- if (file != null) {
- checkIfFileIsImage(file);
- }
- }
-
- /**
- * Analyze file that tag is associated with and determine if it is an
- * image and should have a thumbnail reported for it. Images are added
- * to internal list.
- *
- * @param contentTag
- */
- private void checkIfTagHasImage(ContentTag contentTag) {
- Content c = contentTag.getContent();
- if (c instanceof AbstractFile == false) {
- return;
- }
- checkIfFileIsImage((AbstractFile) c);
- }
-
- /**
- * If file is an image file, add it to the internal 'images' list.
- *
- * @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);
- }
- }
- }
-
- /// @@@ Should move the methods specific to TableReportsWorker into that scope.
- private Boolean failsTagFilter(HashSet tagNames, HashSet tagsNamesFilter) {
- if (null == tagsNamesFilter || tagsNamesFilter.isEmpty()) {
- return false;
- }
-
- HashSet filteredTagNames = new HashSet<>(tagNames);
- filteredTagNames.retainAll(tagsNamesFilter);
- return filteredTagNames.isEmpty();
- }
-
- /**
- * Get a List of the artifacts and data of the given type that pass the
- * given Tag Filter.
- *
- * @param type The artifact type to get
- * @param tagNamesFilter The tag names that should be included.
- *
- * @return a list of the filtered tags.
- */
- private List getFilteredArtifacts(BlackboardArtifact.Type type, HashSet tagNamesFilter) {
- List artifacts = new ArrayList<>();
- try {
- for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(type.getTypeID())) {
- List tags = Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact);
- HashSet uniqueTagNames = new HashSet<>();
- for (BlackboardArtifactTag tag : tags) {
- uniqueTagNames.add(tag.getName().getDisplayName());
- }
- if (failsTagFilter(uniqueTagNames, tagNamesFilter)) {
- continue;
- }
- try {
- artifacts.add(new ArtifactData(artifact, skCase.getBlackboardAttributes(artifact), uniqueTagNames));
- } catch (TskCoreException ex) {
- errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetBBAttribs"));
- logger.log(Level.SEVERE, "Failed to get Blackboard Attributes when generating report.", ex); //NON-NLS
- }
- }
- } catch (TskCoreException ex) {
- errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetBBArtifacts"));
- logger.log(Level.SEVERE, "Failed to get Blackboard Artifacts when generating report.", ex); //NON-NLS
- }
- return artifacts;
- }
-
- /**
- * Write the keyword hits to the provided TableReportModules.
- *
- * @param tableModules modules to report on
- */
- @SuppressWarnings("deprecation")
- private void writeKeywordHits(List tableModules, String comment, HashSet tagNamesFilter) {
-
- // Query for keyword lists-only so that we can tell modules what lists
- // will exist for their index.
- // @@@ There is a bug in here. We should use the tags in the below code
- // so that we only report the lists that we will later provide with real
- // hits. If no keyord hits are tagged, then we make the page for nothing.
- String orderByClause;
- if (currentCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) {
- orderByClause = "ORDER BY convert_to(att.value_text, 'SQL_ASCII') ASC NULLS FIRST"; //NON-NLS
- } else {
- orderByClause = "ORDER BY list ASC"; //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
- "AND att.artifact_id = art.artifact_id " + //NON-NLS
- "GROUP BY list " + orderByClause; //NON-NLS
-
- try (CaseDbQuery dbQuery = skCase.executeQuery(keywordListQuery)) {
- ResultSet listsRs = dbQuery.getResultSet();
- List lists = new ArrayList<>();
- while (listsRs.next()) {
- String list = listsRs.getString("list"); //NON-NLS
- if (list.isEmpty()) {
- list = NbBundle.getMessage(this.getClass(), "ReportGenerator.writeKwHits.userSrchs");
- }
- lists.add(list);
- }
-
- // Make keyword data type and give them set index
- for (TableReportModule module : tableModules) {
- module.startDataType(ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName(), comment);
- module.addSetIndex(lists);
- tableProgress.get(module).updateStatusLabel(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processing",
- ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName()));
- }
- } catch (TskCoreException | SQLException ex) {
- errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedQueryKWLists"));
- 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
- + "convert_to(f.parent_path, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
- + "convert_to(f.name, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
- + "convert_to(att2.value_text, 'SQL_ASCII') ASC NULLS FIRST"; //NON-NLS
- } else {
- 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
- "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
- "AND (att3.artifact_id = art.artifact_id) " + //NON-NLS
- "AND (f.obj_id = art.obj_id) " + //NON-NLS
- "AND (att1.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID() + ") " + //NON-NLS
- "AND (att2.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID() + ") " + //NON-NLS
- "AND (att3.attribute_type_id = " + ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + ") " + //NON-NLS
- "AND (art.artifact_type_id = " + ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") " + //NON-NLS
- orderByClause; //NON-NLS
-
- try (CaseDbQuery dbQuery = skCase.executeQuery(keywordsQuery)) {
- ResultSet resultSet = dbQuery.getResultSet();
-
- String currentKeyword = "";
- String currentList = "";
- while (resultSet.next()) {
- // Check to see if all the TableReportModules have been canceled
- if (tableModules.isEmpty()) {
- break;
- }
- Iterator iter = tableModules.iterator();
- while (iter.hasNext()) {
- TableReportModule module = iter.next();
- if (tableProgress.get(module).getStatus() == ReportStatus.CANCELED) {
- iter.remove();
- }
- }
-
- // Get any tags that associated with this artifact and apply the tag filter.
- HashSet uniqueTagNames = getUniqueTagNames(resultSet.getLong("artifact_id")); //NON-NLS
- if (failsTagFilter(uniqueTagNames, tagNamesFilter)) {
- 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) {
- uniquePath = skCase.getAbstractFileById(objId).getUniquePath();
- }
- } catch (TskCoreException ex) {
- errorList.add(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetAbstractFileByID"));
- logger.log(Level.WARNING, "Failed to get Abstract File by ID.", ex); //NON-NLS
- }
-
- // If the lists aren't the same, we've started a new list
- if ((!list.equals(currentList) && !list.isEmpty()) || (list.isEmpty() && !currentList.equals(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.writeKwHits.userSrchs")))) {
- if (!currentList.isEmpty()) {
- for (TableReportModule module : tableModules) {
- module.endTable();
- module.endSet();
- }
- }
- currentList = list.isEmpty() ? NbBundle
- .getMessage(this.getClass(), "ReportGenerator.writeKwHits.userSrchs") : list;
- currentKeyword = ""; // reset the current keyword because it's a new list
- for (TableReportModule module : tableModules) {
- module.startSet(currentList);
- tableProgress.get(module).updateStatusLabel(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processingList",
- ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName(), currentList));
- }
- }
- if (!keyword.equals(currentKeyword)) {
- if (!currentKeyword.equals("")) {
- for (TableReportModule module : tableModules) {
- module.endTable();
- }
- }
- currentKeyword = keyword;
- for (TableReportModule module : tableModules) {
- module.addSetElement(currentKeyword);
- List columnHeaderNames = new ArrayList<>();
- columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.preview"));
- columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile"));
- columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"));
- module.startTable(columnHeaderNames);
- }
- }
-
- String previewreplace = EscapeUtil.escapeHtml(preview);
- for (TableReportModule module : tableModules) {
- module.addRow(Arrays.asList(new String[]{previewreplace.replaceAll(" tableModules, String comment, HashSet tagNamesFilter) {
- String orderByClause;
- if (currentCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) {
- orderByClause = "ORDER BY convert_to(att.value_text, 'SQL_ASCII') ASC NULLS FIRST"; //NON-NLS
- } else {
- orderByClause = "ORDER BY att.value_text ASC"; //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
- "AND att.artifact_id = art.artifact_id " + //NON-NLS
- "GROUP BY list " + orderByClause; //NON-NLS
-
- try (CaseDbQuery dbQuery = skCase.executeQuery(hashsetsQuery)) {
- // Query for hashsets
- ResultSet listsRs = dbQuery.getResultSet();
- List lists = new ArrayList<>();
- while (listsRs.next()) {
- lists.add(listsRs.getString("list")); //NON-NLS
- }
-
- for (TableReportModule module : tableModules) {
- module.startDataType(ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName(), comment);
- module.addSetIndex(lists);
- tableProgress.get(module).updateStatusLabel(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processing",
- ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName()));
- }
- } catch (TskCoreException | SQLException ex) {
- errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedQueryHashsetLists"));
- logger.log(Level.SEVERE, "Failed to query hashset lists: ", ex); //NON-NLS
- return;
- }
-
- if (currentCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) {
- orderByClause = "ORDER BY convert_to(att.value_text, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
- + "convert_to(f.parent_path, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
- + "convert_to(f.name, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
- + "size ASC NULLS FIRST"; //NON-NLS
- } 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
- "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
- "AND (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
- orderByClause; //NON-NLS
-
- try (CaseDbQuery dbQuery = skCase.executeQuery(hashsetHitsQuery)) {
- // Query for hashset hits
- ResultSet resultSet = dbQuery.getResultSet();
- String currentSet = "";
- while (resultSet.next()) {
- // Check to see if all the TableReportModules have been canceled
- if (tableModules.isEmpty()) {
- break;
- }
- Iterator iter = tableModules.iterator();
- while (iter.hasNext()) {
- TableReportModule module = iter.next();
- if (tableProgress.get(module).getStatus() == ReportStatus.CANCELED) {
- iter.remove();
- }
- }
-
- // Get any tags that associated with this artifact and apply the tag filter.
- HashSet uniqueTagNames = getUniqueTagNames(resultSet.getLong("artifact_id")); //NON-NLS
- if (failsTagFilter(uniqueTagNames, tagNamesFilter)) {
- continue;
- }
- String tagsList = makeCommaSeparatedList(uniqueTagNames);
-
- Long objId = resultSet.getLong("obj_id"); //NON-NLS
- String set = resultSet.getString("setname"); //NON-NLS
- String size = resultSet.getString("size"); //NON-NLS
- String uniquePath = "";
-
- try {
- AbstractFile f = skCase.getAbstractFileById(objId);
- if (f != null) {
- uniquePath = skCase.getAbstractFileById(objId).getUniquePath();
- }
- } catch (TskCoreException ex) {
- errorList.add(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetAbstractFileFromID"));
- logger.log(Level.WARNING, "Failed to get Abstract File from ID.", ex); //NON-NLS
- return;
- }
-
- // If the sets aren't the same, we've started a new set
- if (!set.equals(currentSet)) {
- if (!currentSet.isEmpty()) {
- for (TableReportModule module : tableModules) {
- module.endTable();
- module.endSet();
- }
- }
- currentSet = set;
- for (TableReportModule module : tableModules) {
- module.startSet(currentSet);
- List columnHeaderNames = new ArrayList<>();
- columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.file"));
- columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.size"));
- columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"));
- module.startTable(columnHeaderNames);
- tableProgress.get(module).updateStatusLabel(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processingList",
- ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName(), currentSet));
- }
- }
-
- // Add a row for this hit to every module
- for (TableReportModule module : tableModules) {
- module.addRow(Arrays.asList(new String[]{uniquePath, size, tagsList}));
- }
- }
-
- // Finish the current data type
- for (TableReportModule module : tableModules) {
- tableProgress.get(module).increment();
- module.endDataType();
- }
- } catch (TskCoreException | SQLException ex) {
- errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedQueryHashsetHits"));
- logger.log(Level.SEVERE, "Failed to query hashsets hits: ", ex); //NON-NLS
- }
- }
-
- /**
- * For a given artifact type ID, return the list of the columns that we are
- * reporting on.
- *
- * @param artifactTypeId artifact type ID
- * @param attributeTypeSet The set of attributeTypeSet available for this
- * artifact type
- *
- * @return List row titles
- */
- private List getArtifactTableColumns(int artifactTypeId, Set attributeTypeSet) {
- ArrayList columns = new ArrayList<>();
-
- // Long switch statement to retain ordering of attribute types that are
- // attached to pre-defined artifact types.
- if (ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.title"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TITLE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateCreated"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
-
- } else if (ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.value"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_VALUE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
-
- } else if (ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateAccessed"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.referrer"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_REFERRER)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.title"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TITLE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.urlDomainDecoded"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL_DECODED)));
-
- } else if (ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dest"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.sourceUrl"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateAccessed"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
-
- } else if (ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.path"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- } else if (ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.progName"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.instDateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- } else if (ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() == artifactTypeId) {
- columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.preview")));
-
- } else if (ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == artifactTypeId) {
- columns.add(new SourceFileColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.file")));
-
- columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.size")));
-
- } else if (ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devMake"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devModel"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.deviceId"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_ID)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- } else if (ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.text"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.domain"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DOMAIN)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateAccessed"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.progName"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
-
- } else if (ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTaken"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devManufacturer"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devModel"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE)));
-
- } else if (ARTIFACT_TYPE.TSK_CONTACT.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumber"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumHome"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumOffice"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumMobile"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.email"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL)));
-
- } else if (ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.msgType"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.direction"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DIRECTION)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.readStatus"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_READ_STATUS)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.fromPhoneNum"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.fromEmail"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_FROM)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.toPhoneNum"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.toEmail"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_TO)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.subject"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SUBJECT)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.text"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT)));
-
- } else if (ARTIFACT_TYPE.TSK_CALLLOG.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.fromPhoneNum"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.toPhoneNum"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.direction"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DIRECTION)));
-
- } else if (ARTIFACT_TYPE.TSK_CALENDAR_ENTRY.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.calendarEntryType"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CALENDAR_ENTRY_TYPE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.description"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DESCRIPTION)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.startDateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.endDateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_END)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.location"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)));
-
- } else if (ARTIFACT_TYPE.TSK_SPEED_DIAL_ENTRY.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.shortCut"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SHORTCUT)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME_PERSON)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumber"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)));
-
- } else if (ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.deviceName"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.deviceAddress"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_ID)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- } else if (ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- } else if (ARTIFACT_TYPE.TSK_GPS_BOOKMARK.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.locationAddress"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- } else if (ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.locationAddress"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- } else if (ARTIFACT_TYPE.TSK_GPS_SEARCH.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.locationAddress"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- } else if (ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.category"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CATEGORY)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.userId"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.password"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PASSWORD)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.appName"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.appPath"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.description"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DESCRIPTION)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.replytoAddress"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_REPLYTO)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.mailServer"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SERVER_NAME)));
-
- } else if (ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
-
- } else if (ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID() == artifactTypeId) {
- columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.file")));
-
- columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.extension.text")));
-
- columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.mimeType.text")));
-
- columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.path")));
-
- } else if (ARTIFACT_TYPE.TSK_OS_INFO.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.processorArchitecture.text"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.osName.text"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.osInstallDate.text"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- } else if (ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailTo"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_TO)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailFrom"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_FROM)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSubject"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SUBJECT)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskDateTimeSent"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_SENT)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskDateTimeRcvd"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_RCVD)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskPath"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailCc"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_CC)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailBcc"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_BCC)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskMsgId"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MSG_ID)));
-
- } else if (ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSetName"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskInterestingFilesCategory"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CATEGORY)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskPath"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)));
-
- } else if (ARTIFACT_TYPE.TSK_GPS_ROUTE.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskGpsRouteCategory"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CATEGORY)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitudeEnd"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitudeEnd"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitudeStart"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitudeStart"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.location"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
-
- } else if (ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSetName"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.associatedArtifact"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
-
- } else if (ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.associatedArtifact"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.count"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_COUNT)));
-
- } else if (ARTIFACT_TYPE.TSK_OS_ACCOUNT.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.userName"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.userId"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)));
-
- } else if (ARTIFACT_TYPE.TSK_REMOTE_DRIVE.getTypeID() == artifactTypeId) {
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.localPath"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCAL_PATH)));
-
- columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.remotePath"),
- new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_REMOTE_PATH)));
- } else {
- // This is the case that it is a custom type. The reason an else is
- // necessary is to make sure that the source file column is added
- for (BlackboardAttribute.Type type : attributeTypeSet) {
- columns.add(new AttributeColumn(type.getDisplayName(), type));
- }
- columns.add(new SourceFileColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")));
- columns.add(new TaggedResultsColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags")));
-
- // Short circuits to guarantee that the attribute types aren't added
- // twice.
- return columns;
- }
- // If it is an attribute column, it removes the attribute type of that
- // column from the set, so types are not reported more than once.
- for (Column column : columns) {
- attributeTypeSet = column.removeTypeFromSet(attributeTypeSet);
- }
- // Now uses the remaining types in the set to construct columns
- for (BlackboardAttribute.Type type : attributeTypeSet) {
- columns.add(new AttributeColumn(type.getDisplayName(), type));
- }
- // Source file column is added here for ordering purposes.
- if (artifactTypeId == ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_CONTACT.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_CALENDAR_ENTRY.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_SPEED_DIAL_ENTRY.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_GPS_BOOKMARK.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_GPS_SEARCH.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID()
- || artifactTypeId == ARTIFACT_TYPE.TSK_OS_INFO.getTypeID()) {
- columns.add(new SourceFileColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")));
- }
- columns.add(new TaggedResultsColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags")));
-
- return columns;
- }
-
- /**
- * Converts a collection of strings into a single string of comma-separated
- * items
- *
- * @param items A collection of strings
- *
- * @return A string of comma-separated items
- */
- private String makeCommaSeparatedList(Collection items) {
- String list = "";
- for (Iterator iterator = items.iterator(); iterator.hasNext();) {
- list += iterator.next() + (iterator.hasNext() ? ", " : "");
- }
- return list;
- }
-
- /**
- * Given a tsk_file's obj_id, return the unique path of that file.
- *
- * @param objId tsk_file obj_id
- *
- * @return String unique path
- */
- private String getFileUniquePath(Content content) {
- try {
- if (content != null) {
- return content.getUniquePath();
- } else {
- return "";
- }
- } catch (TskCoreException ex) {
- errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetAbstractFileByID"));
- logger.log(Level.WARNING, "Failed to get Abstract File by ID.", ex); //NON-NLS
- }
- return "";
-
- }
-
- /**
- * Container class that holds data about an Artifact to eliminate duplicate
- * calls to the Sleuthkit database.
- */
- private class ArtifactData implements Comparable {
-
- 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
- * artifacts of the same type
- *
- * If all attributes are the same, they are assumed duplicates and are
- * compared by their artifact id. Should only be used with attributes of
- * the same type.
- */
- @Override
- public int compareTo(ArtifactData otherArtifactData) {
- List thisRow = getRow();
- List otherRow = otherArtifactData.getRow();
- for (int i = 0; i < thisRow.size(); i++) {
- int compare = thisRow.get(i).compareTo(otherRow.get(i));
- if (compare != 0) {
- return compare;
- }
- }
- return ((Long) this.getArtifactID()).compareTo((Long) otherArtifactData.getArtifactID());
- }
-
- /**
- * Get the values for each row in the table report.
- *
- * the value types of custom artifacts
- *
- * @return A list of string representing the data for this artifact.
- */
- public List getRow() {
- if (rowData == null) {
- try {
- rowData = getOrderedRowDataAsStrings();
- // If else is done so that row data is not set before
- // columns are added to the hash map.
- if (rowData.size() > 0) {
- // replace null values if attribute was not defined
- for (int i = 0; i < rowData.size(); i++) {
- if (rowData.get(i) == null) {
- rowData.set(i, "");
- }
- }
- } else {
- rowData = null;
- return new ArrayList<>();
- }
- } catch (TskCoreException ex) {
- errorList.add(
- NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.coreExceptionWhileGenRptRow"));
- logger.log(Level.WARNING, "Core exception while generating row data for artifact report.", ex); //NON-NLS
- rowData = Collections.emptyList();
- }
- }
- return rowData;
- }
-
- /**
- * Get a list of Strings with all the row values for the Artifact in the
- * correct order to be written to the report.
- *
- * @return List row values. Values could be null if attribute is
- * not defined in artifact
- *
- * @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) {
- AbstractFile file = (AbstractFile) content;
- orderedRowData.add(file.getName());
- orderedRowData.add(file.getNameExtension());
- String mimeType = file.getMIMEType();
- if (mimeType == null) {
- orderedRowData.add("");
- } else {
- orderedRowData.add(mimeType);
- }
- orderedRowData.add(file.getUniquePath());
- } else {
- // Make empty rows to make sure the formatting is correct
- orderedRowData.add(null);
- orderedRowData.add(null);
- orderedRowData.add(null);
- 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
- // maintained.
- for (BlackboardAttribute attr : attributes) {
- if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME))) {
- attributeDataArray[0] = attr.getDisplayString();
- } else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CATEGORY))) {
- attributeDataArray[1] = attr.getDisplayString();
- } else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))) {
- String pathToShow = attr.getDisplayString();
- if (pathToShow.isEmpty()) {
- pathToShow = getFileUniquePath(content);
- }
- 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;
- }
-
- }
-
- /**
- * Get any tags associated with an artifact
- *
- * @param artifactId
- *
- * @return hash set of tag display names
- *
- * @throws SQLException
- */
- @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
-
- try (CaseDbQuery dbQuery = skCase.executeQuery(query)) {
- ResultSet tagNameRows = dbQuery.getResultSet();
- while (tagNameRows.next()) {
- uniqueTagNames.add(tagNameRows.getString("display_name")); //NON-NLS
- }
- } 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;
-
- /**
- * Constructs an ArtifactCell
- *
- * @param columnHeader The header text of this column
- * @param attributeType The attribute type associated with this column
- */
- AttributeColumn(String columnHeader, BlackboardAttribute.Type attributeType) {
- 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)) {
- 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.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
- return types;
- }
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java
index eeca1efe56..54fa7b6b7e 100644
--- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java
+++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java
@@ -838,10 +838,17 @@ class ReportHTML implements TableReportModule {
try {
indexOut = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(indexFilePath), "UTF-8")); //NON-NLS
StringBuilder index = new StringBuilder();
- index.append("\n").append( //NON-NLS
+ final String reportTitle = reportBranding.getReportTitle();
+ String iconPath = reportBranding.getAgencyLogoPath();
+ if (iconPath == null){
+ // use default Autopsy icon if custom icon is not set
+ iconPath = "favicon.ico";
+ }
+ index.append("\n").append(reportTitle).append(" ").append(
NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.title", currentCase.getName())).append(
"\n"); //NON-NLS
- index.append("\n"); //NON-NLS
+ index.append("\n"); //NON-NLS
index.append("\n"); //NON-NLS
index.append("\n"); //NON-NLS
index.append("